Skip to main content

PYUSD on Solana: The Practical Integration Guide (with BlockEden.xyz RPC)

· 9 min read
Dora Noda
Software Engineer

PayPal USD (PYUSD) has landed on Solana, marking a significant milestone for digital payments. This guide provides a direct, production-minded walkthrough for engineers integrating PYUSD into wallets, dApps, and commerce platforms on Solana.

All examples use fresh, Token-2022-aware code and are designed to work seamlessly with BlockEden.xyz's low-latency Solana RPC endpoints.

TL;DR

  • What: PayPal USD (PYUSD) is now a native Token-2022 SPL token on Solana, offering fast, low-fee settlement for a globally recognized stablecoin.
  • Key Params: Mint 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo, decimals 6, and token program Token-2022.
  • Feature Set: Leverages Solana Token Extensions (Token-2022). It has a Transfer Hook initialized but currently inactive (null program), along with confidential transfer capabilities and other extensions.
  • Cross-chain: An official LayerZero integration enables PYUSD to move between Ethereum and Solana via a secure burn-and-mint mechanism, bypassing traditional bridges.
  • Action: Use this guide as a drop-in template to add PYUSD support to your application with BlockEden.xyz's reliable Solana RPC.

Why PYUSD on Solana Matters

The combination of PayPal's brand with Solana's performance creates a powerful new rail for digital dollars.

  1. Consumer Trust Meets Crypto UX: PYUSD is issued by the regulated trust company Paxos and is deeply integrated into PayPal and Venmo. This gives users a familiar asset. They can hold a single PYUSD balance and choose to withdraw to an external wallet on either Ethereum or Solana, abstracting away chain complexity.
  2. Payments-Ready Rails: Solana’s architecture provides sub-second transaction finality and fees that are fractions of a cent. PYUSD layers a stable, recognizable unit of account on top of this efficient settlement network, making it ideal for payments, commerce, and remittances.
  3. Institution-Grade Controls: By launching as a Token-2022 token, PYUSD can utilize built-in extensions for features like confidential transfers, rich metadata, and a permanent delegate. This enables advanced compliance and functionality without requiring bespoke, difficult-to-audit smart contracts.

The Absolute Essentials (Pin These)

Before you write a single line of code, get these parameters locked in. Always verify the mint address in a trusted explorer to avoid interacting with fraudulent tokens.

  • Mint (Mainnet): 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
  • Decimals: 6 (meaning 1 PYUSD = 1,000,000 base units)
  • Token Program: Token-2022 (Program ID: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb)
  • Token Extensions Used (at mint):
    • Metadata & Metadata Pointer
    • Permanent Delegate
    • Transfer Hook (initialized with a null program)
    • Confidential Transfer Configuration

You can verify all of this on the Solana Explorer. The explorer will clearly show the official mint address and its enabled extensions.

Set Up Your Project

Let's get our environment ready. You'll need the latest Solana web3 and SPL token libraries to ensure full Token-2022 compatibility.

1. Libraries

Install the necessary packages from npm.

npm i @solana/web3.js @solana/spl-token

2. RPC Connection

Point your application to your BlockEden.xyz Solana Mainnet RPC URL. For production, environment variables are a must.

// package.json
// npm i @solana/web3.js @solana/spl-token

import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import {
TOKEN_2022_PROGRAM_ID,
getMint,
getOrCreateAssociatedTokenAccount,
getAssociatedTokenAddress,
createTransferCheckedInstruction,
} from "@solana/spl-token";

// Use your BlockEden.xyz Solana RPC URL from your dashboard
const RPC_ENDPOINT =
process.env.SOLANA_RPC_URL ??
"[https://your-blockeden-solana-mainnet-endpoint.com](https://your-blockeden-solana-mainnet-endpoint.com)";
export const connection = new Connection(RPC_ENDPOINT, "confirmed");

// PYUSD (mainnet)
export const PYUSD_MINT = new PublicKey(
"2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
);

Reading PYUSD Mint Data

First, let's programmatically confirm the PYUSD mint's properties. This is a crucial first step to ensure your constants are correct and to fetch details like total supply.

// Confirm PYUSD mint info via Token-2022 APIs
const mintInfo = await getMint(
connection,
PYUSD_MINT,
"confirmed",
TOKEN_2022_PROGRAM_ID, // Specify the program ID
);

console.log({
supply: mintInfo.supply.toString(),
decimals: mintInfo.decimals, // Expect 6
isInitialized: mintInfo.isInitialized,
});

Notice we explicitly pass TOKEN_2022_PROGRAM_ID. This is the most common source of errors when working with Token Extensions.

Create or Fetch Associated Token Accounts (ATAs)

Associated Token Accounts for Token-2022 tokens must be derived using the Token-2022 program ID. If you use the legacy TOKEN_PROGRAM_ID, transactions will fail with an "incorrect program id" error.

// Payer and owner of the new ATA. Replace with your wallet logic.
const owner = Keypair.generate();

// Create or fetch the owner's PYUSD ATA (Token-2022 aware)
const ownerAta = await getOrCreateAssociatedTokenAccount(
connection,
owner, // Payer for creation
PYUSD_MINT, // Mint
owner.publicKey, // Owner of the ATA
false, // allowOwnerOffCurve
"confirmed",
undefined, // options
TOKEN_2022_PROGRAM_ID, // <-- IMPORTANT: Use Token-2022 Program ID
);

console.log("Owner PYUSD ATA:", ownerAta.address.toBase58());

Checking PYUSD Balances

To check a user's PYUSD balance, query their ATA, again remembering to specify the correct program ID.

Using @solana/spl-token

import { getAccount } from "@solana/spl-token";

const accountInfo = await getAccount(
connection,
ownerAta.address,
"confirmed",
TOKEN_2022_PROGRAM_ID,
);

const balance = Number(accountInfo.amount) / 10 ** mintInfo.decimals; // decimals = 6
console.log("PYUSD balance:", balance);

Using Direct JSON-RPC (curl)

You can also check all token accounts for an owner and filter by the Token-2022 program ID.

curl -X POST "$SOLANA_RPC_URL" -H 'content-type: application/json' -d '{
"jsonrpc":"2.0",
"id":1,
"method":"getTokenAccountsByOwner",
"params":[
"<OWNER_PUBLIC_KEY>",
{ "programId":"TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" },
{ "encoding":"jsonParsed" }
]
}'

Transferring PYUSD (User-to-User)

The rule of thumb for transferring any Token-2022 asset is to use createTransferCheckedInstruction. This instruction includes the token's decimals, preventing potential decimal-related vulnerabilities.

Here's a complete, reusable function for transferring PYUSD.

import { Transaction } from '@solana/web3.js';

async function transferPyusd({
fromWallet, // The sender's Keypair
toPubkey, // The recipient's PublicKey
uiAmount, // The amount in PYUSD, e.g., 1.25
}: {
fromWallet: Keypair;
toPubkey: PublicKey;
uiAmount: number;
}) {
const decimals = 6; // From mintInfo.decimals
const rawAmount = BigInt(Math.round(uiAmount * (10 ** decimals)));

// Get the sender's ATA address
const fromAta = await getAssociatedTokenAddress(
PYUSD_MINT,
fromWallet.publicKey,
false,
TOKEN_2022_PROGRAM_ID
);

// Ensure the recipient's ATA exists for Token-2022
const toAta = await getOrCreateAssociatedTokenAccount(
connection,
fromWallet, // Payer
PYUSD_MINT,
toPubkey,
false,
'confirmed',
undefined,
TOKEN_2022_PROGRAM_ID
);

const transferInstruction = createTransferCheckedInstruction(
fromAta, // Source ATA
PYUSD_MINT, // Mint
toAta.address, // Destination ATA
fromWallet.publicKey, // Owner of the source ATA
rawAmount, // Amount in base units
decimals, // Decimals
[], // Multisig signers
TOKEN_2022_PROGRAM_ID // <-- IMPORTANT
);

const transaction = new Transaction().add(transferInstruction);

// Set recent blockhash and fee payer
transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
transaction.feePayer = fromWallet.publicKey;

const signature = await connection.sendTransaction(transaction, [fromWallet]);
await connection.confirmTransaction(signature, 'confirmed');

console.log('Transaction successful with signature:', signature);
return signature;
}

A Note on the Transfer Hook: PYUSD's mint initializes the Transfer Hook extension but sets its program to null. This means standard transfers currently work without extra accounts or logic. If PayPal/Paxos ever activate the hook, they will update the mint to point to a new program. Your integration would then need to pass the extra accounts required by that program's interface.

Solana CLI Quick Test

For a quick manual test from your command line, you can use spl-token with the correct program ID.

# Ensure your CLI points to mainnet and your keypair is funded.
# Transfer 1.00 PYUSD to a recipient.
spl-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
transfer 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo 1.00 <RECIPIENT_PUBKEY> \
--fund-recipient --allow-unfunded-recipient

Cross-Chain PYUSD (Ethereum ↔ Solana)

PayPal has implemented an official cross-chain facility using LayerZero. Instead of relying on risky third-party bridges, this is a native burn-and-mint process: PYUSD is burned on the source chain (e.g., Ethereum) and an equivalent amount is minted on the destination chain (Solana). This eliminates bridge-specific risks and slippage.

You can find the full tutorial and parameters in the official PayPal Developer documentation.

Test with Faucets

For development and testing, do not use mainnet assets. Use the official faucets:

  • Paxos PYUSD Faucet: To get testnet PYUSD tokens.
  • Solana Faucet: To get devnet/testnet SOL for transaction fees.

Common Pitfalls (And Fixes)

  1. Wrong Program ID: Problem: Transactions fail with incorrect program id for instruction. Fix: Pass TOKEN_2022_PROGRAM_ID explicitly to all spl-token helper functions (getOrCreateAssociatedTokenAccount, getAccount, createTransferCheckedInstruction, etc.).
  2. Wrong Mint or Spoofed Assets: Problem: Your application interacts with a fake PYUSD token. Fix: Hardcode and verify the official mint address: 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo. Use an explorer that warns about non-canonical mints.
  3. Decimals Mismatch: Problem: Sending 1 PYUSD actually sends 0.000001 PYUSD. Fix: Always convert UI amounts to raw amounts by multiplying by 10^6. Fetch the mint's decimals programmatically to be safe.
  4. Hook Assumptions: Problem: You pre-build complex logic for a transfer hook that isn't active. Fix: Check the mint's extension data. As of today, PYUSD's hook is null. Build your system to adapt if the hook program is enabled in the future.

Production Checklist for PYUSD + BlockEden.xyz

When moving to production, ensure your infrastructure is robust.

  • RPC: Use a high-availability BlockEden.xyz endpoint. Use confirmed commitment for responsive UX and query with finalized for operations requiring ledger integrity.
  • Retry & Idempotency: Wrap transaction submissions with an exponential backoff retry mechanism. Store an idempotency key with each business operation to prevent duplicate transfers.
  • Observability: Log transaction signatures, slot numbers, and post-transaction balances. Use BlockEden.xyz's websocket subscriptions to get real-time settlement signals for your application's backend.
  • Compliance: Token-2022 provides primitives for compliance. If you need to implement features like the travel rule, the extension model allows you to do so cleanly, keeping your business logic separate from the token's core functionality.

Appendix A — Quick Reference

  • Mint (Mainnet): 2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo
  • Decimals: 6
  • Token Program ID: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
  • Background: PayPal announced Solana support on May 29, 2024.
  • Official Docs: Solana Token Extensions, PayPal Developer Portal

Appendix B — Direct JSON-RPC Calls (curl)

Get Mint Account Info & Confirm Owner

This call retrieves the mint account data and lets you verify its owner is the Token-2022 program.

# Replace with your BlockEden.xyz RPC URL
curl -s -X POST "$SOLANA_RPC_URL" -H 'content-type: application/json' -d '{
"jsonrpc":"2.0","id":1,"method":"getAccountInfo",
"params":["2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
{"encoding":"base64","commitment":"confirmed"}]
}'

# In the JSON response, the "owner" field should equal "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb".

List All PYUSD Token Accounts for a User

This is useful for wallets that need to discover all PYUSD holdings for a given user.

curl -s -X POST "$SOLANA_RPC_URL" -H 'content-type: application/json' -d '{
"jsonrpc":"2.0",
"id":1,
"method":"getTokenAccountsByOwner",
"params":[
"<OWNER_PUBLIC_KEY>",
{"mint":"2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo"},
{"encoding":"jsonParsed","commitment":"confirmed"}
]
}'

Ready to build? Grab your high-performance BlockEden.xyz RPC endpoint and start integrating the future of payments today.