Sol.College

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.

solana-foundation/pay · 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,
  1. Line 87 encodeURL(fields: TransactionRequestURLFields | TransferRequestURLFields): URL {: Encodes a Solana Pay request URL.
  2. Line 96 async findReference(reference: Reference, options?: FindReferenceOptions): Promise<Confirm: Finds or validates the on-chain payment by its reference key.
asimbugra/ChipCasher · 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,
  1. Line 54 const solanaUrl = encodeURL(urlParams);: Encodes a Solana Pay request URL.
  2. Line 71 const signatureInfo = await findReference(connection, reference, { finality: 'confirmed' }: Finds or validates the on-chain payment by its reference key.

Go further

Related lessons

Topics: Payments · Learning path · Glossary