Solana Pay
Solana Pay is a URL standard for requesting payments. A transfer request encodes recipient, amount, SPL token and a unique reference public key, and a wallet scanning the QR builds the transaction itself. A merchant finds the payment on-chain by the reference key and validates it. Transaction requests let a server build an arbitrary transaction for the wallet to sign.
Reference: Solana Pay docs · Solana Pay spec
Real code, line by line
2 excerpts from different projects. Each caption links the exact lines at the fork's pinned commit. The notes below each excerpt explain the lines that matter.
typescript/packages/solana-pay/core/src/plugins/merchant.ts L83–108 @ e22d0af · MIT · original ): SolanaPayMerchantMethods & TClient { const existingPay = 'pay' in client ? (client as { pay: Record<string, unknown> }).pay : {}; const pay: SolanaPayMerchantMethods['pay'] = { ...existingPay, encodeURL(fields: TransactionRequestURLFields | TransferRequestURLFields): URL { return encodeURL(fields); }, createQR(url: URL | string, size?: number, background?: string, color?: string): any { return createQR(url, size, background, color); }, createQROptions(url: URL | string, size?: number, background?: string, color?: string) { return createQROptions(url, size, background, color); }, async findReference(reference: Reference, options?: FindReferenceOptions): Promise<ConfirmedSignatureInfo> { return await findReference(client.rpc, reference, options); }, async watchReference(reference: Reference, options?: WatchReferenceOptions): Promise<WatchReferenceResult> { return await watchReference(client.rpcSubscriptions, reference, options); }, async validateTransfer(signature: Signature, fields: TransferFields, options?: { commitment?: Finality }) { return await validateTransfer(client.rpc, signature, fields, options); }, buildTransaction( feePayer: Address, instructions: Instruction[], options?: BuildTransactionOptions,- Line 87
encodeURL(fields: TransactionRequestURLFields | TransferRequestURLFields): URL {: Encodes a Solana Pay request URL. - Line 96
async findReference(reference: Reference, options?: FindReferenceOptions): Promise<Confirm: Finds or validates the on-chain payment by its reference key.
pages/shop/checkout.tsx L50–75 @ b322aef · MIT · original link: new URL(apiUrl), label: "ChipCasher", message: "Thanks for your order! 🛍️", }; const solanaUrl = encodeURL(urlParams); const qr = createQR(solanaUrl, 512, 'transparent'); if (amount.isGreaterThan(0)) { qrRef.current.innerHTML = ''; // Clear previous QR code qr.append(qrRef.current); } } }, [amount, searchParams]); // Check every 0.5s if the transaction is completed useEffect(() => { if (typeof window === 'undefined') return; // Only run in the browser const interval = setInterval(async () => { try { // Check if there is any transaction for the reference const signatureInfo = await findReference(connection, reference, { finality: 'confirmed' }); // Validate that the transaction has the expected recipient, amount, and SPL token await validateTransfer( connection,- Line 54
const solanaUrl = encodeURL(urlParams);: Encodes a Solana Pay request URL. - Line 71
const signatureInfo = await findReference(connection, reference, { finality: 'confirmed' }: Finds or validates the on-chain payment by its reference key.
Go further
- pay: explore the full project
- ChipCasher: explore the full project
- Next lesson: Blinks and Solana Actions
Related lessons
- SPL Tokens: mints, accounts and transfers
- Building and sending transactions from a client
- Blinks and Solana Actions
Topics: Payments · Learning path · Glossary