@solana/pay
Version:
`@solana/pay` is a JavaScript library for facilitating commerce on Solana by using a token transfer URL scheme. The URL scheme ensures that no matter the wallet or service used, the payment request must be created and interpreted in one standard way.
1 lines • 75.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/client.ts","../src/plugins/merchant.ts","../src/createQR.ts","../src/utils/reference.ts","../src/encodeURL.ts","../src/findReference.ts","../src/validateTransfer.ts","../src/utils/amount.ts","../src/watchReference.ts","../src/createTransfer.ts","../src/fetchTransaction.ts","../src/parseURL.ts","../src/plugins/wallet.ts"],"sourcesContent":["export * from './constants.js';\nexport * from './client.js';\nexport * from './createQR.js';\nexport * from './createTransfer.js';\nexport * from './encodeURL.js';\nexport * from './fetchTransaction.js';\nexport * from './findReference.js';\nexport * from './parseURL.js';\nexport * from './types.js';\nexport * from './validateTransfer.js';\nexport * from './watchReference.js';\nexport * from './plugins/merchant.js';\nexport * from './plugins/wallet.js';\n","export { MEMO_PROGRAM_ADDRESS } from '@solana-program/memo';\nexport { TOKEN_2022_PROGRAM_ADDRESS } from '@solana-program/token-2022';\n\n/** @internal */\nexport const SOLANA_PROTOCOL = 'solana:';\n\n/** @internal */\nexport const HTTPS_PROTOCOL = 'https:';\n\n/** @internal */\nexport const SOL_DECIMALS = 9;\n","import { createClient, type DefaultRpcSubscriptionsChannelConfig, type TransactionSigner } from '@solana/kit';\nimport { planAndSendTransactions } from '@solana/kit-plugin-instruction-plan';\nimport { rpcTransactionPlanExecutor, rpcTransactionPlanner, solanaRpcConnection } from '@solana/kit-plugin-rpc';\nimport { payer } from '@solana/kit-plugin-signer';\n\nimport { solanaPayMerchant } from './plugins/merchant.js';\nimport { solanaPayWallet } from './plugins/wallet.js';\n\n/** Configuration for {@link createMerchantClient}. */\nexport interface MerchantClientConfig {\n /** Solana RPC URL (e.g. 'https://api.mainnet-beta.solana.com'). */\n rpcUrl: string;\n /** Optional RPC subscriptions config (e.g. custom WebSocket URL for localhost). */\n rpcSubscriptionsConfig?: DefaultRpcSubscriptionsChannelConfig<string>;\n}\n\n/** The type returned by {@link createMerchantClient}. */\nexport type MerchantClient = ReturnType<typeof createMerchantClient>;\n\n/**\n * Creates a merchant-side Solana Pay client with RPC and the merchant plugin.\n * No payer required — merchants only encode URLs, generate QR codes, and\n * read from the network to find/validate payments.\n *\n * @example\n * ```ts\n * const merchant = createMerchantClient({\n * rpcUrl: 'https://api.mainnet-beta.solana.com',\n * });\n *\n * const url = merchant.pay.encodeURL({ recipient, amount: 1.5 });\n * const found = await merchant.pay.findReference(reference);\n * await merchant.pay.validateTransfer(found.signature, { recipient, amount: 1.5 });\n * ```\n */\nexport function createMerchantClient(config: MerchantClientConfig) {\n return createClient()\n .use(solanaRpcConnection({ rpcUrl: config.rpcUrl, rpcSubscriptionsConfig: config.rpcSubscriptionsConfig }))\n .use(solanaPayMerchant());\n}\n\n/** Configuration for {@link createWalletClient}. */\nexport interface WalletClientConfig {\n /** Solana RPC URL (e.g. 'https://api.mainnet-beta.solana.com'). */\n rpcUrl: string;\n /** Wallet signer that will be used as the default sender / fee payer. */\n payer: TransactionSigner;\n /** Optional RPC subscriptions config (e.g. custom WebSocket URL for localhost). */\n rpcSubscriptionsConfig?: DefaultRpcSubscriptionsChannelConfig<string>;\n}\n\n/** The type returned by {@link createWalletClient}. */\nexport type WalletClient = ReturnType<typeof createWalletClient>;\n\n/**\n * Creates a wallet-side Solana Pay client with RPC, payer, transaction\n * planner/executor, and the wallet plugin. Handles URL parsing, transfer\n * instruction creation, and transaction sending.\n *\n * @example\n * ```ts\n * const wallet = createWalletClient({\n * rpcUrl: 'https://api.mainnet-beta.solana.com',\n * payer: myWalletSigner,\n * });\n *\n * const parsed = wallet.pay.parseURL(url);\n * const instructions = await wallet.pay.createTransfer({ recipient, amount: 1.5 });\n * await wallet.sendTransaction(instructions);\n * ```\n */\nexport function createWalletClient(config: WalletClientConfig) {\n return createClient()\n .use(solanaRpcConnection({ rpcUrl: config.rpcUrl, rpcSubscriptionsConfig: config.rpcSubscriptionsConfig }))\n .use(payer(config.payer))\n .use(rpcTransactionPlanner())\n .use(rpcTransactionPlanExecutor())\n .use(planAndSendTransactions())\n .use(solanaPayWallet());\n}\n\n/** Configuration for {@link createSolanaPayClient}. */\nexport interface SolanaPayClientConfig {\n /** Solana RPC URL (e.g. 'https://api.mainnet-beta.solana.com'). */\n rpcUrl: string;\n /** Wallet signer that will be used as the default sender / fee payer. */\n payer: TransactionSigner;\n /** Optional RPC subscriptions config (e.g. custom WebSocket URL for localhost). */\n rpcSubscriptionsConfig?: DefaultRpcSubscriptionsChannelConfig<string>;\n}\n\n/** The type returned by {@link createSolanaPayClient}. */\nexport type SolanaPayClient = ReturnType<typeof createSolanaPayClient>;\n\n/**\n * Creates a combined Solana Pay client with all merchant + wallet methods.\n *\n * @example\n * ```ts\n * const client = createSolanaPayClient({\n * rpcUrl: 'https://api.mainnet-beta.solana.com',\n * payer: myWalletSigner,\n * });\n *\n * const url = client.pay.encodeURL({ recipient, amount: 1.5 });\n * const parsed = client.pay.parseURL(url);\n * const instructions = await client.pay.createTransfer({ recipient, amount: 1.5 });\n * ```\n */\nexport function createSolanaPayClient(config: SolanaPayClientConfig) {\n return createClient()\n .use(solanaRpcConnection({ rpcUrl: config.rpcUrl, rpcSubscriptionsConfig: config.rpcSubscriptionsConfig }))\n .use(payer(config.payer))\n .use(rpcTransactionPlanner())\n .use(rpcTransactionPlanExecutor())\n .use(planAndSendTransactions())\n .use(solanaPayMerchant())\n .use(solanaPayWallet());\n}\n","import type { Address, GetSignaturesForAddressApi, GetTransactionApi, Instruction, Signature } from '@solana/kit';\nimport {\n appendTransactionMessageInstructions,\n compileTransaction,\n createTransactionMessage,\n getBase64EncodedWireTransaction,\n pipe,\n setTransactionMessageFeePayer,\n} from '@solana/kit';\nimport type { ClientWithRpc, ClientWithRpcSubscriptions } from '@solana/plugin-interfaces';\nimport type { LogsNotificationsApi } from '@solana/rpc-subscriptions-api';\n\nimport { createQR, createQROptions } from '../createQR.js';\nimport type { TransactionRequestURLFields, TransferRequestURLFields } from '../encodeURL.js';\nimport { encodeURL } from '../encodeURL.js';\nimport type { ConfirmedSignatureInfo, FindReferenceOptions } from '../findReference.js';\nimport { findReference } from '../findReference.js';\nimport type { Finality, Reference, TransferFields } from '../types.js';\nimport { validateTransfer } from '../validateTransfer.js';\nimport type { WatchReferenceOptions, WatchReferenceResult } from '../watchReference.js';\nimport { watchReference } from '../watchReference.js';\n\ntype MerchantRpcApi = GetSignaturesForAddressApi & GetTransactionApi;\n\ntype MerchantRpcSubscriptionsApi = LogsNotificationsApi;\n\ntype MerchantCompatibleClient = ClientWithRpc<MerchantRpcApi> & ClientWithRpcSubscriptions<MerchantRpcSubscriptionsApi>;\n\n/** Methods added to a client by the merchant plugin. */\nexport interface SolanaPayMerchantMethods {\n readonly pay: {\n encodeURL(fields: TransactionRequestURLFields | TransferRequestURLFields): URL;\n createQR(url: URL | string, size?: number, background?: string, color?: string): any;\n createQROptions(\n url: URL | string,\n size?: number,\n background?: string,\n color?: string,\n ): ReturnType<typeof createQROptions>;\n findReference(reference: Reference, options?: FindReferenceOptions): Promise<ConfirmedSignatureInfo>;\n watchReference(reference: Reference, options?: WatchReferenceOptions): Promise<WatchReferenceResult>;\n validateTransfer(\n signature: Signature,\n fields: TransferFields,\n options?: { commitment?: Finality },\n ): Promise<Awaited<ReturnType<typeof validateTransfer>>>;\n buildTransaction(feePayer: Address, instructions: Instruction[]): string;\n };\n}\n\n/**\n * Merchant plugin for Solana Pay.\n *\n * Adds a `pay` namespace with merchant-side methods: URL encoding,\n * QR code generation, reference lookup, and transfer validation.\n * No payer/signer required — merchant only reads from the network.\n */\nexport function solanaPayMerchant() {\n return function installMerchant<TClient extends MerchantCompatibleClient>(\n client: TClient,\n ): SolanaPayMerchantMethods & TClient {\n const existingPay = 'pay' in client ? (client as { pay: Record<string, unknown> }).pay : {};\n const pay: SolanaPayMerchantMethods['pay'] = {\n ...existingPay,\n encodeURL(fields: TransactionRequestURLFields | TransferRequestURLFields): URL {\n return encodeURL(fields);\n },\n createQR(url: URL | string, size?: number, background?: string, color?: string): any {\n return createQR(url, size, background, color);\n },\n createQROptions(url: URL | string, size?: number, background?: string, color?: string) {\n return createQROptions(url, size, background, color);\n },\n async findReference(reference: Reference, options?: FindReferenceOptions): Promise<ConfirmedSignatureInfo> {\n return await findReference(client.rpc, reference, options);\n },\n async watchReference(reference: Reference, options?: WatchReferenceOptions): Promise<WatchReferenceResult> {\n return await watchReference(client.rpcSubscriptions, reference, options);\n },\n async validateTransfer(signature: Signature, fields: TransferFields, options?: { commitment?: Finality }) {\n return await validateTransfer(client.rpc, signature, fields, options);\n },\n buildTransaction(feePayer: Address, instructions: Instruction[]): string {\n const tx = pipe(\n createTransactionMessage({ version: 0 }),\n m => setTransactionMessageFeePayer(feePayer, m),\n m => appendTransactionMessageInstructions(instructions, m),\n );\n return getBase64EncodedWireTransaction(compileTransaction(tx));\n },\n };\n\n return Object.freeze({ ...client, pay }) as SolanaPayMerchantMethods & TClient;\n };\n}\n","import type {\n CornerDotType,\n CornerSquareType,\n DotType,\n DrawType,\n ErrorCorrectionLevel,\n Mode,\n Options,\n TypeNumber,\n} from '@solana/qr-code-styling';\nimport QRCodeStylingModule from '@solana/qr-code-styling';\n\n// Resolve the QRCodeStyling constructor across ESM/CJS bundler variations.\n// Some bundlers (webpack/Next.js) resolve the default import directly as the class,\n// while others (tsup/esbuild) wrap it in a module namespace with a `.default` property.\nconst QRCodeStyling: typeof QRCodeStylingModule.default =\n typeof (QRCodeStylingModule as unknown as { default?: unknown }).default === 'function'\n ? QRCodeStylingModule.default\n : (QRCodeStylingModule as unknown as typeof QRCodeStylingModule.default);\n\n/**\n * Create a QR code from a Solana Pay URL.\n *\n * @param url - The URL to encode.\n * @param size - Width and height in pixels.\n * @param background - Background color, which should be light for device compatibility.\n * @param color - Foreground color, which should be dark for device compatibility.\n */\nexport function createQR(\n url: URL | string,\n size = 512,\n background = 'white',\n color = 'black',\n): InstanceType<typeof QRCodeStylingModule.default> {\n return new QRCodeStyling(createQROptions(url, size, background, color));\n}\n\n/** @ignore */\nexport function createQROptions(url: URL | string, size = 512, background = 'white', color = 'black'): Options {\n return {\n type: 'svg' as DrawType,\n width: size,\n height: size,\n data: String(url),\n margin: 16,\n qrOptions: {\n typeNumber: 0 as TypeNumber,\n mode: 'Byte' as Mode,\n errorCorrectionLevel: 'Q' as ErrorCorrectionLevel,\n },\n backgroundOptions: { color: background },\n dotsOptions: { type: 'extra-rounded' as DotType, color },\n cornersSquareOptions: {\n type: 'extra-rounded' as CornerSquareType,\n color,\n },\n cornersDotOptions: { type: 'square' as CornerDotType, color },\n imageOptions: { hideBackgroundDots: true, imageSize: 0.15, margin: 8 },\n image: `data:image/svg+xml;utf8,<svg fill=\"${encodeURIComponent(\n color,\n )}\" height=\"16\" viewBox=\"0 0 16 14\" width=\"16\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"m15.9176 11.038-2.6413 2.7713c-.0574.0602-.1269.1082-.2041.141s-.1604.0497-.2446.0497h-12.520966c-.059744 0-.118187-.0171-.168147-.0491-.0499596-.0321-.0892609-.0777-.1130745-.1313-.02381372-.0536-.03110249-.1129-.02097081-.1705.01013171-.0576.03724251-.111.07800141-.1538l2.6432769-2.7713c.05726-.06.12651-.1079.20346-.1407s.15996-.0498.2439-.05h12.52032c.0597 0 .1182.0171.1681.0492.05.032.0893.0776.1131.1313.0238.0536.0311.1128.021.1704-.0102.0576-.0373.1111-.078.1538zm-2.6413-5.58067c-.0574-.0602-.1269-.1082-.2041-.141s-.1604-.04971-.2446-.04966h-12.520966c-.059744 0-.118187.01708-.168147.04913-.0499596.03205-.0892609.07768-.1130745.13129-.02381372.0536-.03110249.11285-.02097081.17045.01013171.05761.03724251.11106.07800141.15379l2.6432769 2.77134c.05726.06004.12651.10794.20346.14073.07695.0328.15996.04979.2439.04993h12.52032c.0597 0 .1182-.01707.1681-.04913.05-.03205.0893-.07768.1131-.13129.0238-.0536.0311-.11285.021-.17045-.0102-.05761-.0373-.11106-.078-.15379zm-12.969666-1.99066h12.520966c.0842.00004.1674-.01687.2446-.04967s.1467-.0808.2041-.141l2.6413-2.771333c.0407-.042736.0678-.096189.078-.153792.0101-.057603.0028-.116847-.021-.170453s-.0631-.0992385-.1131-.1312911c-.0499-.0320526-.1084-.04912893-.1681-.0491309h-12.52032c-.08394.00013975-.16695.0171339-.2439.0499304s-.1462.0806976-.20346.1407366l-2.6425955 2.771333c-.0407196.04269-.0678184.09609-.07797306.15363-.01015467.05754-.00292373.11673.02080606.17031.0237297.05358.0629266.09922.1127835.13132.049857.03211.108207.04928.167893.04941z\"/></svg>`,\n };\n}\n","import type { Reference, References } from '../types.js';\n\n/**\n * Normalize a single reference or array of references into a consistent array form.\n * Returns undefined when the input is undefined.\n */\nexport function normalizeReferences(reference: References | undefined): Reference[] | undefined {\n if (!reference) return undefined;\n return Array.isArray(reference) ? reference : [reference];\n}\n","import { SOLANA_PROTOCOL } from './constants.js';\nimport type { Amount, Label, Memo, Message, Recipient, References, SPLToken } from './types.js';\nimport { normalizeReferences } from './utils/reference.js';\n\n/**\n * Fields of a Solana Pay transaction request URL.\n */\nexport interface TransactionRequestURLFields {\n /** `link` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#link). */\n link: URL;\n /** `label` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#label-1). */\n label?: Label;\n /** `message` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#message-1). */\n message?: Message;\n}\n\n/**\n * Fields of a Solana Pay transfer request URL.\n */\nexport interface TransferRequestURLFields {\n /** `recipient` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#recipient). */\n recipient: Recipient;\n /** `amount` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#amount). */\n amount?: Amount;\n /** `spl-token` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#spl-token). */\n splToken?: SPLToken;\n /** `reference` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#reference). */\n reference?: References;\n /** `label` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#label). */\n label?: Label;\n /** `message` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#message). */\n message?: Message;\n /** `memo` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#memo). */\n memo?: Memo;\n}\n\n/**\n * Encode a Solana Pay URL.\n *\n * @param fields Fields to encode in the URL.\n */\nexport function encodeURL(fields: TransactionRequestURLFields | TransferRequestURLFields): URL {\n return 'link' in fields ? encodeTransactionRequestURL(fields) : encodeTransferRequestURL(fields);\n}\n\nfunction encodeTransactionRequestURL({ link, label, message }: TransactionRequestURLFields): URL {\n // Remove trailing slashes\n const pathname = link.search\n ? encodeURIComponent(String(link).replace(/\\/\\?/, '?'))\n : String(link).replace(/\\/$/, '');\n const url = new URL(SOLANA_PROTOCOL + pathname);\n\n if (label) {\n url.searchParams.append('label', label);\n }\n\n if (message) {\n url.searchParams.append('message', message);\n }\n\n return url;\n}\n\nfunction encodeTransferRequestURL({\n recipient,\n amount,\n splToken,\n reference,\n label,\n message,\n memo,\n}: TransferRequestURLFields): URL {\n const pathname = recipient;\n const url = new URL(SOLANA_PROTOCOL + pathname);\n\n if (amount != null) {\n url.searchParams.append('amount', amount.toFixed(10).replace(/0+$/, '').replace(/\\.$/, ''));\n }\n\n if (splToken) {\n url.searchParams.append('spl-token', splToken);\n }\n\n const refs = normalizeReferences(reference);\n if (refs) {\n for (const ref of refs) {\n url.searchParams.append('reference', ref);\n }\n }\n\n if (label) {\n url.searchParams.append('label', label);\n }\n\n if (message) {\n url.searchParams.append('message', message);\n }\n\n if (memo) {\n url.searchParams.append('memo', memo);\n }\n\n return url;\n}\n","import type { Address, GetSignaturesForAddressApi, Rpc } from '@solana/kit';\nimport type { Commitment, Signature } from '@solana/kit';\n\nimport type { Reference } from './types.js';\n\n/**\n * Thrown when no transaction signature can be found referencing a given address.\n */\nexport class FindReferenceError extends Error {\n name = 'FindReferenceError';\n}\n\n/** Options for {@link findReference}. */\nexport interface FindReferenceOptions {\n /** Limit the number of signatures returned. */\n limit?: number;\n /** Start searching backwards from this signature. */\n before?: Signature;\n /** Search until this signature is reached. */\n until?: Signature;\n /** Commitment level to use for the query. */\n commitment?: Exclude<Commitment, 'processed'>;\n}\n\n/** A confirmed signature info entry returned by the RPC. */\nexport interface ConfirmedSignatureInfo {\n signature: Signature;\n slot: bigint | number;\n err: unknown | null;\n memo: string | null;\n blockTime: bigint | number | null;\n confirmationStatus: Commitment | null;\n}\n\n/**\n * Find the oldest transaction signature referencing a given address.\n *\n * @param rpc - An RPC client supporting `getSignaturesForAddress`.\n * @param reference - `reference` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#reference).\n * @param options - Options for `getSignaturesForAddress`.\n *\n * @throws {FindReferenceError}\n */\nexport async function findReference(\n rpc: Rpc<GetSignaturesForAddressApi>,\n reference: Reference,\n { commitment, ...options }: FindReferenceOptions = {},\n): Promise<ConfirmedSignatureInfo> {\n const signatures = await rpc\n .getSignaturesForAddress(reference as Address, { ...options, ...(commitment ? { commitment } : {}) })\n .send();\n\n const length = signatures.length;\n if (!length) throw new FindReferenceError('not found');\n\n // If one or more transaction signatures are found under the limit, return the oldest one.\n const oldest = signatures[length - 1];\n if (length < (options?.limit || 1000)) return oldest;\n\n try {\n // In the unlikely event that signatures up to the limit are found, recursively find the oldest one.\n return await findReference(rpc, reference, {\n commitment,\n ...options,\n before: oldest.signature,\n });\n } catch (error) {\n // If the signatures found were exactly at the limit, there won't be more to find, so return the oldest one.\n if (error instanceof FindReferenceError) return oldest;\n throw error;\n }\n}\n","import type {\n AccountMeta,\n Address,\n Base64EncodedDataResponse,\n GetTransactionApi,\n Instruction,\n InstructionWithAccounts,\n InstructionWithData,\n Lamports,\n ReadonlyUint8Array,\n Rpc,\n Signature,\n TokenBalance,\n} from '@solana/kit';\nimport {\n decompileTransactionMessage,\n getBase64Codec,\n getCompiledTransactionMessageCodec,\n getTransactionCodec,\n} from '@solana/kit';\nimport { parseAddMemoInstruction } from '@solana-program/memo';\nimport {\n identifySystemInstruction,\n parseTransferSolInstruction,\n SYSTEM_PROGRAM_ADDRESS,\n SystemInstruction,\n} from '@solana-program/system';\nimport {\n findAssociatedTokenPda,\n identifyTokenInstruction,\n parseTransferCheckedInstruction,\n parseTransferInstruction,\n TOKEN_PROGRAM_ADDRESS,\n TokenInstruction,\n} from '@solana-program/token';\n\nimport { MEMO_PROGRAM_ADDRESS, SOL_DECIMALS, TOKEN_2022_PROGRAM_ADDRESS } from './constants.js';\nimport type { Finality, Reference, TransferFields } from './types.js';\nimport { amountToBaseUnits } from './utils/amount.js';\nimport { normalizeReferences } from './utils/reference.js';\n\n/**\n * Thrown when a transaction doesn't contain a valid Solana Pay transfer.\n */\nexport class ValidateTransferError extends Error {\n name = 'ValidateTransferError';\n}\n\n/** A decompiled instruction with accounts and data present. */\ntype DecompiledInstruction = Instruction &\n InstructionWithAccounts<readonly AccountMeta[]> &\n InstructionWithData<ReadonlyUint8Array>;\n\n/** Balance change result from validation helpers. */\ninterface BalanceChange {\n pre: bigint;\n post: bigint;\n decimals: number;\n}\n\n/** Meta from a base64-encoded getTransaction response. */\ntype TransactionMeta = {\n err: unknown;\n preBalances: readonly Lamports[];\n postBalances: readonly Lamports[];\n preTokenBalances?: readonly TokenBalance[];\n postTokenBalances?: readonly TokenBalance[];\n};\n\nfunction validateAmount(amount: number): void {\n if (!Number.isFinite(amount) || amount < 0) {\n throw new ValidateTransferError('amount invalid');\n }\n}\n\nfunction parseBase64Transaction(b64TransactionResponse: Base64EncodedDataResponse) {\n const [base64Transaction] = b64TransactionResponse;\n const transactionBytes = getBase64Codec().encode(base64Transaction);\n const transaction = getTransactionCodec().decode(transactionBytes);\n const compiledMessage = getCompiledTransactionMessageCodec().decode(transaction.messageBytes);\n const decompiledMessage = decompileTransactionMessage(compiledMessage);\n const { staticAccounts } = compiledMessage;\n const instructions = [...decompiledMessage.instructions];\n return { instructions, staticAccounts };\n}\n\nfunction getMeta(meta: TransactionMeta | null) {\n if (!meta) throw new ValidateTransferError('missing meta');\n if (meta.err) throw new ValidateTransferError(JSON.stringify(meta.err));\n return meta;\n}\n\nfunction validateInstruction(instruction: Instruction | undefined): asserts instruction is DecompiledInstruction {\n if (!instruction) {\n throw new ValidateTransferError('missing instruction');\n }\n\n if (!instruction.accounts) {\n throw new ValidateTransferError('missing instruction accounts');\n }\n\n if (!instruction.data) {\n throw new ValidateTransferError('missing instruction data');\n }\n}\n\n/**\n * Check that a given transaction contains a valid Solana Pay transfer.\n *\n * @param rpc - An RPC client supporting `getTransaction`.\n * @param signature - The signature of the transaction to validate.\n * @param fields - Fields of a Solana Pay transfer request to validate.\n * @param options - Options for `getTransaction`.\n *\n * @throws {ValidateTransferError}\n */\nexport async function validateTransfer(\n rpc: Rpc<GetTransactionApi>,\n signature: Signature,\n { recipient, amount, splToken, reference, memo }: TransferFields,\n options?: { commitment?: Finality },\n) {\n validateAmount(amount);\n const refs = normalizeReferences(reference);\n\n const response = await rpc\n .getTransaction(signature, {\n commitment: options?.commitment ?? 'confirmed',\n maxSupportedTransactionVersion: 0,\n encoding: 'base64',\n })\n .send();\n\n if (!response) throw new ValidateTransferError('not found');\n\n const meta = getMeta(response.meta);\n const { instructions, staticAccounts } = parseBase64Transaction(response.transaction);\n\n // Transfer instruction must be the last instruction\n const instruction = instructions.pop();\n validateInstruction(instruction);\n\n const { pre, post, decimals } = splToken\n ? await validateSPLTokenTransfer(instruction, staticAccounts, meta, recipient, splToken, refs)\n : validateSystemTransfer(instruction, staticAccounts, meta, recipient, refs);\n\n const expected = amountToBaseUnits(amount, decimals);\n if (post - pre < expected) throw new ValidateTransferError('amount not transferred');\n\n if (memo !== undefined) {\n validateMemo(instructions.pop(), memo);\n }\n\n return response;\n}\n\nfunction validateMemo(instruction: Instruction | undefined, memo: string): void {\n if (!instruction) throw new ValidateTransferError('missing memo instruction');\n if (instruction.programAddress !== MEMO_PROGRAM_ADDRESS) {\n throw new ValidateTransferError('invalid memo program');\n }\n if (!instruction.data) throw new ValidateTransferError('invalid memo');\n\n const parsed = parseAddMemoInstruction(instruction as Instruction & InstructionWithData<ReadonlyUint8Array>);\n if (parsed.data.memo !== memo) throw new ValidateTransferError('invalid memo');\n}\n\nfunction validateProgram(instruction: DecompiledInstruction, validPrograms: readonly Address[]): void {\n if (!validPrograms.includes(instruction.programAddress)) {\n throw new ValidateTransferError('invalid transfer');\n }\n}\n\nfunction validateReferences(\n instruction: DecompiledInstruction,\n requiredAccounts: number,\n references?: Reference[],\n): void {\n if (!references) return;\n const extraAccounts = instruction.accounts.slice(requiredAccounts);\n if (extraAccounts.length !== references.length) throw new ValidateTransferError('invalid references');\n\n for (let i = 0; i < extraAccounts.length; i++) {\n if (extraAccounts[i].address !== references[i]) throw new ValidateTransferError(`invalid reference ${i}`);\n }\n}\n\nfunction validateSystemTransfer(\n instruction: DecompiledInstruction,\n staticAccounts: readonly Address[],\n meta: TransactionMeta,\n recipient: Address,\n references?: Reference[],\n): BalanceChange {\n validateProgram(instruction, [SYSTEM_PROGRAM_ADDRESS]);\n\n const instructionType = identifySystemInstruction(instruction);\n if (instructionType !== SystemInstruction.TransferSol) {\n throw new ValidateTransferError('invalid transfer');\n }\n\n const parsed = parseTransferSolInstruction(instruction);\n if (parsed.accounts.destination.address !== recipient) {\n throw new ValidateTransferError('invalid transfer');\n }\n\n validateReferences(instruction, Object.keys(parsed.accounts).length, references);\n\n const accountIndex = staticAccounts.indexOf(recipient);\n if (accountIndex === -1) throw new ValidateTransferError('recipient not found');\n\n const pre = meta.preBalances[accountIndex];\n const post = meta.postBalances[accountIndex];\n if (pre === undefined || post === undefined) throw new ValidateTransferError('missing balance data');\n return { pre, post, decimals: SOL_DECIMALS };\n}\n\nasync function validateSPLTokenTransfer(\n instruction: DecompiledInstruction,\n staticAccounts: readonly Address[],\n meta: TransactionMeta,\n recipient: Address,\n splToken: Address,\n references?: Reference[],\n): Promise<BalanceChange> {\n validateProgram(instruction, [TOKEN_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS]);\n\n const instructionType = identifyTokenInstruction(instruction);\n\n const [recipientATA] = await findAssociatedTokenPda({\n owner: recipient,\n tokenProgram: instruction.programAddress,\n mint: splToken,\n });\n\n let requiredAccounts: number;\n switch (instructionType) {\n case TokenInstruction.TransferChecked: {\n const parsed = parseTransferCheckedInstruction(instruction);\n if (parsed.accounts.destination.address !== recipientATA) {\n throw new ValidateTransferError('invalid transfer');\n }\n if (parsed.accounts.mint.address !== splToken) {\n throw new ValidateTransferError('invalid transfer');\n }\n requiredAccounts = Object.keys(parsed.accounts).length;\n break;\n }\n case TokenInstruction.Transfer: {\n const parsed = parseTransferInstruction(instruction);\n if (parsed.accounts.destination.address !== recipientATA) {\n throw new ValidateTransferError('invalid transfer');\n }\n requiredAccounts = Object.keys(parsed.accounts).length;\n break;\n }\n default:\n throw new ValidateTransferError('invalid transfer instruction');\n }\n\n validateReferences(instruction, requiredAccounts, references);\n\n const accountIndex = staticAccounts.indexOf(recipientATA);\n if (accountIndex === -1) throw new ValidateTransferError('recipient not found');\n\n const preBalance = meta.preTokenBalances?.find(x => x.accountIndex === accountIndex);\n const postBalance = meta.postTokenBalances?.find(x => x.accountIndex === accountIndex);\n if (!preBalance || !postBalance) throw new ValidateTransferError('missing balance data');\n\n return {\n pre: BigInt(preBalance.uiTokenAmount.amount),\n post: BigInt(postBalance.uiTokenAmount.amount),\n decimals: preBalance.uiTokenAmount.decimals,\n };\n}\n","/**\n * Convert a decimal amount to base units via string manipulation (avoids float precision issues).\n *\n * **Precision note:** JavaScript `number` has ~15 significant digits of precision.\n * For tokens with high decimals (e.g., 10), amounts above ~100,000 with full fractional\n * precision may exceed this limit. The function throws when this happens rather than\n * silently rounding. If you need arbitrary-precision amounts, convert to base units\n * (bigint) at the source rather than passing through a `number`.\n *\n * @internal\n */\nexport function amountToBaseUnits(amount: number, decimals: number): bigint {\n if (!Number.isFinite(amount) || amount < 0) {\n throw new Error(`Invalid amount: ${amount}`);\n }\n if (!Number.isInteger(decimals) || decimals < 0) {\n throw new Error(`Invalid decimals: ${decimals}`);\n }\n\n // Detect amounts where float64 has lost integer precision\n const str = amount.toFixed(decimals);\n const [whole, frac] = str.split('.');\n const significantDigits = whole.replace(/^0+/, '').length + (frac?.replace(/0+$/, '').length ?? 0);\n if (significantDigits > 15) {\n throw new Error(\n `Amount ${amount} with ${decimals} decimals exceeds safe floating-point precision (${significantDigits} significant digits > 15). ` +\n 'Use a smaller amount or fewer decimals to avoid silent precision loss.',\n );\n }\n\n return BigInt(whole + (frac ?? ''));\n}\n\n/** Count decimal places. @internal */\nexport function decimalPlaces(n: number): number {\n const s = n.toString();\n // Handle scientific notation (e.g., 1e-9, 1.5e-8)\n if (s.includes('e-')) {\n const [coeff, exp] = s.split('e-');\n const coeffDecimals = (coeff.split('.')[1] || '').length;\n return coeffDecimals + Number(exp);\n }\n const dot = s.indexOf('.');\n return dot === -1 ? 0 : s.length - dot - 1;\n}\n","import type { Address, Signature } from '@solana/kit';\nimport type { LogsNotificationsApi } from '@solana/rpc-subscriptions-api';\nimport type { RpcSubscriptions } from '@solana/rpc-subscriptions-spec';\n\nimport { FindReferenceError } from './findReference.js';\nimport type { Finality, Reference } from './types.js';\n\n/** Options for {@link watchReference}. */\nexport interface WatchReferenceOptions {\n /** Commitment level for the subscription. Defaults to `confirmed`. */\n commitment?: Finality;\n /** Abort signal to cancel the subscription. */\n abortSignal?: AbortSignal;\n}\n\n/** Result returned by {@link watchReference}. */\nexport interface WatchReferenceResult {\n /** The transaction signature. */\n signature: Signature;\n /** Error if the transaction failed, null if it succeeded. */\n err: unknown | null;\n}\n\n/**\n * Watch for a transaction referencing a given address using WebSocket subscriptions.\n *\n * Unlike {@link findReference}, which polls via HTTP, this function subscribes\n * to `logsNotifications` filtered by `{ mentions: [reference] }` and resolves\n * as soon as a matching transaction lands.\n *\n * @param rpcSubscriptions - An RPC subscriptions client supporting `logsNotifications`.\n * @param reference - `reference` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#reference).\n * @param options - Options for the subscription.\n *\n * @throws {FindReferenceError} If the subscription is aborted before a transaction is found.\n */\nexport async function watchReference(\n rpcSubscriptions: RpcSubscriptions<LogsNotificationsApi>,\n reference: Reference,\n options?: WatchReferenceOptions,\n): Promise<WatchReferenceResult> {\n const { commitment = 'confirmed', abortSignal: externalSignal } = options ?? {};\n\n if (externalSignal?.aborted) {\n throw new FindReferenceError('aborted');\n }\n\n const abortController = new AbortController();\n if (externalSignal) {\n externalSignal.addEventListener('abort', () => abortController.abort(externalSignal.reason), { once: true });\n }\n\n try {\n const subscription = await rpcSubscriptions\n .logsNotifications({ mentions: [reference as Address] }, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n\n for await (const notification of subscription) {\n return {\n signature: notification.value.signature,\n err: notification.value.err,\n };\n }\n } catch (error) {\n if (abortController.signal.aborted) {\n throw new FindReferenceError('aborted');\n }\n throw error;\n } finally {\n abortController.abort();\n }\n\n throw new FindReferenceError('not found');\n}\n","import {\n Account,\n AccountRole,\n type Address,\n type GetAccountInfoApi,\n type GetMultipleAccountsApi,\n type Instruction,\n type Rpc,\n type TransactionSigner,\n} from '@solana/kit';\nimport { getAddMemoInstruction } from '@solana-program/memo';\nimport { getTransferSolInstruction, SYSTEM_PROGRAM_ADDRESS } from '@solana-program/system';\nimport {\n AccountState,\n fetchMint,\n fetchToken,\n findAssociatedTokenPda,\n getTransferCheckedInstruction,\n Mint,\n TOKEN_PROGRAM_ADDRESS,\n} from '@solana-program/token';\n\nimport { SOL_DECIMALS, TOKEN_2022_PROGRAM_ADDRESS } from './constants.js';\nimport type { TransferFields } from './types.js';\nimport { amountToBaseUnits, decimalPlaces } from './utils/amount.js';\nimport { normalizeReferences } from './utils/reference.js';\n\n/**\n * Thrown when a Solana Pay transfer transaction can't be created from the fields provided.\n */\nexport class CreateTransferError extends Error {\n name = 'CreateTransferError';\n}\n\n/**\n * Create instructions for a Solana Pay transfer.\n *\n * Returns an array of {@link Instruction} that the caller composes into a transaction message\n * using `pipe(createTransactionMessage(...), ...)`.\n *\n * @param rpc - An RPC client supporting `getAccountInfo`.\n * @param sender - The signer that will send the transfer.\n * @param fields - Fields of a Solana Pay transfer request URL.\n *\n * @throws {CreateTransferError}\n */\nexport async function createTransfer(\n rpc: Rpc<GetAccountInfoApi & GetMultipleAccountsApi>,\n sender: TransactionSigner,\n { recipient, amount, splToken, reference, memo }: TransferFields,\n): Promise<Instruction[]> {\n const instructions: Instruction[] = [];\n\n // If a memo is provided, add it before the transfer instruction\n if (memo != null) {\n instructions.push(getAddMemoInstruction({ memo, signers: [sender] }));\n }\n\n // A native SOL or SPL token transfer instruction\n const transferInstruction = splToken\n ? await createSPLTokenInstruction(recipient, amount, splToken, sender, rpc)\n : await createSystemInstruction(recipient, amount, sender, rpc);\n\n // If reference accounts are provided, add them to the transfer instruction\n const refs = normalizeReferences(reference);\n if (refs) {\n const existingAccounts = transferInstruction.accounts ?? [];\n const refAccounts = refs.map(ref => ({\n address: ref,\n role: AccountRole.READONLY as const,\n }));\n const updatedInstruction = {\n ...transferInstruction,\n accounts: [...existingAccounts, ...refAccounts],\n };\n instructions.push(updatedInstruction);\n } else {\n instructions.push(transferInstruction);\n }\n\n return instructions;\n}\n\nasync function createSystemInstruction(\n recipient: Address,\n amount: number,\n sender: TransactionSigner,\n rpc: Rpc<GetMultipleAccountsApi>,\n): Promise<Instruction> {\n // Check that the sender and recipient accounts exist\n const {\n value: [senderInfo, recipientInfo],\n } = await rpc.getMultipleAccounts([sender.address, recipient], { encoding: 'base64' }).send();\n if (!senderInfo) throw new CreateTransferError('sender not found');\n\n // Check that the sender is a valid native account\n if (senderInfo.owner !== SYSTEM_PROGRAM_ADDRESS) throw new CreateTransferError('sender owner invalid');\n if (senderInfo.executable) throw new CreateTransferError('sender executable');\n\n // If the recipient exists, validate it's a valid native account.\n // A non-existent recipient is fine — the System Program will create it on transfer.\n if (recipientInfo) {\n if (recipientInfo.owner !== SYSTEM_PROGRAM_ADDRESS) throw new CreateTransferError('recipient owner invalid');\n if (recipientInfo.executable) throw new CreateTransferError('recipient executable');\n }\n\n // Check that the amount provided doesn't have greater precision than SOL\n if (decimalPlaces(amount) > SOL_DECIMALS) throw new CreateTransferError('amount decimals invalid');\n\n // Convert input decimal amount to integer lamports\n const lamports = amountToBaseUnits(amount, SOL_DECIMALS);\n\n // Check that the sender has enough lamports\n if (lamports > senderInfo.lamports) throw new CreateTransferError('insufficient funds');\n\n // Create an instruction to transfer native SOL\n return getTransferSolInstruction({\n source: sender,\n destination: recipient,\n amount: lamports,\n });\n}\n\nasync function createSPLTokenInstruction(\n recipient: Address,\n amount: number,\n splToken: Address,\n sender: TransactionSigner,\n rpc: Rpc<GetAccountInfoApi>,\n): Promise<Instruction> {\n // Fetch the mint and determine the token program from its owner\n let mint: Account<Mint>;\n try {\n mint = await fetchMint(rpc, splToken);\n } catch {\n throw new CreateTransferError('mint account not found');\n }\n if (!mint.data.isInitialized) throw new CreateTransferError('mint not initialized');\n const tokenProgram: Address =\n mint.programAddress === TOKEN_2022_PROGRAM_ADDRESS ? TOKEN_2022_PROGRAM_ADDRESS : TOKEN_PROGRAM_ADDRESS;\n\n // Check that the amount provided doesn't have greater precision than the mint\n if (decimalPlaces(amount) > mint.data.decimals) throw new CreateTransferError('amount decimals invalid');\n\n // Convert input decimal amount to integer tokens according to the mint decimals\n const tokens = amountToBaseUnits(amount, mint.data.decimals);\n\n // Derive sender and recipient ATAs in parallel\n const [[senderATA], [recipientATA]] = await Promise.all([\n findAssociatedTokenPda({ owner: sender.address, tokenProgram, mint: splToken }),\n findAssociatedTokenPda({ owner: recipient, tokenProgram, mint: splToken }),\n ]);\n\n // Fetch both token accounts in parallel\n const [senderAccount, recipientAccount] = await Promise.all([\n fetchToken(rpc, senderATA),\n fetchToken(rpc, recipientATA),\n ]);\n\n if (senderAccount.data.state === AccountState.Uninitialized)\n throw new CreateTransferError('sender not initialized');\n if (senderAccount.data.state === AccountState.Frozen) throw new CreateTransferError('sender frozen');\n if (recipientAccount.data.state === AccountState.Uninitialized)\n throw new CreateTransferError('recipient not initialized');\n if (recipientAccount.data.state === AccountState.Frozen) throw new CreateTransferError('recipient frozen');\n\n // Check that the sender has enough tokens\n if (tokens > senderAccount.data.amount) throw new CreateTransferError('insufficient funds');\n\n // Create an instruction to transfer SPL tokens, asserting the mint and decimals match\n return getTransferCheckedInstruction(\n {\n source: senderATA,\n mint: splToken,\n destination: recipientATA,\n authority: sender,\n amount: tokens,\n decimals: mint.data.decimals,\n },\n { programAddress: tokenProgram },\n );\n}\n","import { assertIsSignatureBytes, verifySignature } from '@solana/keys';\nimport type {\n Address,\n Commitment,\n CompiledTransactionMessage,\n CompiledTransactionMessageWithLifetime,\n GetLatestBlockhashApi,\n ReadonlyUint8Array,\n Rpc,\n Transaction,\n} from '@solana/kit';\nimport {\n address,\n compileTransaction,\n decompileTransactionMessage,\n getAddressEncoder,\n getBase64Encoder,\n getCompiledTransactionMessageDecoder,\n getTransactionDecoder,\n setTransactionMessageFeePayer,\n setTransactionMessageLifetimeUsingBlockhash,\n} from '@solana/kit';\n\n/**\n * Thrown when a transaction response can't be fetched.\n */\nexport class FetchTransactionError extends Error {\n name = 'FetchTransactionError';\n}\n\n/**\n * A compiled transaction with message bytes and signatures.\n */\nexport type FetchedTransaction = Transaction;\n\n/**\n * Fetch a transaction from a Solana Pay transaction request link.\n *\n * @param rpc - An RPC client supporting `getLatestBlockhash`.\n * @param account - Address of the account that may sign the transaction.\n * @param link - `link` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#link).\n * @param options - Options for `getLatestBlockhash`.\n *\n * @throws {FetchTransactionError}\n */\nexport async function fetchTransaction(\n rpc: Rpc<GetLatestBlockhashApi>,\n account: Address,\n link: URL | string,\n { commitment }: { commitment?: Commitment } = {},\n): Promise<FetchedTransaction> {\n let response: Response;\n try {\n response = await fetch(String(link), {\n method: 'POST',\n mode: 'cors',\n credentials: 'omit',\n headers: {\n 'Cache-Control': 'no-cache',\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ account }),\n });\n } catch (error) {\n throw new FetchTransactionError(`network error: ${error instanceof Error ? error.message : String(error)}`);\n }\n\n if (!response.ok) throw new FetchTransactionError(`request failed: ${response.status}`);\n\n let json: Record<string, unknown>;\n try {\n json = (await response.json()) as Record<string, unknown>;\n } catch {\n throw new FetchTransactionError('response is not valid JSON');\n }\n if (!json?.transaction) throw new FetchTransactionError('missing transaction');\n if (typeof json.transaction !== 'string') throw new FetchTransactionError('invalid transaction');\n\n // Decode the base64 transaction string to bytes, then decode the transaction\n let transactionBytes: ReadonlyUint8Array;\n try {\n transactionBytes = getBase64Encoder().encode(json.transaction);\n } catch {\n throw new FetchTransactionError('invalid base64 in transaction');\n }\n\n let transaction: Transaction;\n try {\n transaction = getTransactionDecoder().decode(transactionBytes);\n } catch {\n throw new FetchTransactionError('failed to decode transaction wire format');\n }\n\n let compiledMessage: CompiledTransactionMessage & CompiledTransactionMessageWithLifetime;\n try {\n compiledMessage = getCompiledTransactionMessageDecoder().decode(transaction.messageBytes);\n } catch {\n throw new FetchTransactionError('failed to decode compiled transaction message');\n }\n\n // Extract signatures map\n const signatures = transaction.signatures;\n const signerAddresses = Object.keys(signatures).map(addr => address(addr));\n\n const hasSignatures = signerAddresses.some(addr => {\n const sig = signatures[addr];\n return sig != null && !sig.every((b: number) => b === 0);\n });\n\n if (hasSignatures) {\n const feePayer = signerAddresses[0];\n if (!feePayer) throw new FetchTransactionError('missing fee payer');\n\n if (compiledMessage.staticAccounts.length === 0 || compiledMessage.staticAccounts[0] !== feePayer) {\n throw new FetchTransactionError('invalid fee payer');\n }\n\n if (!compiledMessage.lifetimeToken) {\n throw new FetchTransactionError('missing recent blockhash');\n }\n\n // A valid signature for everything except `account` must be provided.\n const addressEncoder = getAddressEncoder();\n for (const addr of signerAddresses) {\n const sig = signatures[addr];\n const isNonZero = sig != null && !sig.every((b: number) => b === 0);\n\n if (isNonZero) {\n const publicKeyBytes = addressEncoder.encode(addr);\n const cryptoKey = await crypto.subtle.importKey('raw', publicKeyBytes, { name: 'Ed25519' }, false, [\n 'verify',\n ]);\n assertIsSignatureBytes(sig);\n const isValid = await verifySignature(cryptoKey, sig, transaction.messageBytes);\n if (!isValid) throw new FetchTransactionError('invalid signature');\n } else if (addr === account) {\n // If the only signature needed is for `account`, refresh the blockhash\n if (signerAddresses.length === 1) {\n const { value } = await rpc.getLatestBlockhash({ commitment }).send();\n const msg = decompileTransactionMessage(compiledMessage);\n const updatedMsg = setTransactionMessageLifetimeUsingBlockhash(value, msg);\n return compileTransaction(updatedMsg);\n }\n } else {\n throw new FetchTransactionError('missing signature');\n }\n }\n\n return transaction;\n } else {\n // Ignore the fee payer and recent blockhash in the transaction and initialize them.\n const { value } = await rpc.getLatestBlockhash({ commitment }).send();\n const msg = decompileTransactionMessage(compiledMessage);\n const withFeePayer = setTransactionMessageFeePayer(account, msg);\n const withLifetime = setTransactionMessageLifetimeUsingBlockhash(value, withFeePayer);\n return compileTransaction(withLifetime);\n }\n}\n","import { address } from '@solana/kit';\n\nimport { HTTPS_PROTOCOL, SOLANA_PROTOCOL } from './constants.js';\nimport type { Amount, Label, Link, Memo, Message, Recipient, Reference, SPLToken } from './types.js';\n\n/**\n * A Solana Pay transaction request URL.\n */\nexport interface TransactionRequestURL {\n /** `link` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#link). */\n link: Link;\n /** `label` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#label-1). */\n label: Label | undefined;\n /** `message` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#message-1). */\n message: Message | undefined;\n}\n\n/**\n * A Solana Pay transfer request URL.\n */\nexport interface TransferRequestURL {\n /** `recipient` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#recipient). */\n recipient: Recipient;\n /** `amount` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#amount). */\n amount: Amount | undefined;\n /** `spl-token` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#spl-token). */\n splToken: SPLToken | undefined;\n /** `reference` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#reference). */\n reference: Reference[] | undefined;\n /** `label` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#label). */\n label: Label | undefined;\n /** `message` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#message). */\n message: Message | undefined;\n /** `memo` in the [Solana Pay spec](https://github.com/solana-foundation/pay/blob/main/typescript/packages/solana-pay/spec/SPEC.md#memo). */\n memo: Memo | undefined;\n}\n\n/**\n * Thrown when a URL can't be parsed as a Solana Pay URL.\n */\nexport class ParseURLError extends Error {\n name = 'ParseURLError';\n}\n\n/**\n * Parse a Solana Pay URL.\n *\n * @param url - URL to parse.\n *\n * @throws {ParseURLError}\n */\nexport function parseURL(url: URL | string): TransactionRequestURL | TransferRequestURL {\n if (typeof url === 'string') {\n if (url.length > 2048) throw new ParseURLError('length invalid');\n url = new URL(url);\n }\n\n if (url.protocol !== SOLANA_PROTOCOL) throw new ParseURLError('protocol invalid');\n if (!url.pathname) throw new ParseURLError('pathname missing');\n\n return /[:%]/.test(url.pathname) ? parseTransactionRequestURL(url) : parseTransferRequestURL(url);\n}\n\nfunction parseTransactionRequestURL({ pathname, searchParams }: URL): TransactionRequestURL {\n const link = new URL(decodeURIComponent(pathname));\n if (link.protocol !== HTTPS_PROTOCOL) throw new ParseURLError('link invalid');\n\n const label = searchParams.get('label') || undefined;\n const message = searchParams.get('message') || undefined;\n\n return {\n link,\n label,\n message,\n };\n}\n\nfunction parseTransferRequestURL({ pathname, searchParams }: URL): TransferRequestURL {\n let recipient: Recipient;\n try {\n recipient = address(pathname);\n } catch {\n throw new ParseURLError('recipient invalid');\n }\n\n let amount: number | undefined;\n const amountParam = searchParams.get('amount');\n if (amountParam != null) {\n if (!/^\\d+(\\.\\d+)?$/.test(amountParam)) throw new ParseURLError('amount invalid');\n\n amount = Number(amountParam);\n if (Number.isNaN(amount)) throw new ParseURLError('amount NaN');\n if (amount < 0) throw new ParseURLError('amount negative');\n }\n\n let splToken: SPLToken | undefined;\n const splTokenParam = searchParams.get('spl-token');\n if (splTokenParam != null) {\n try {\n splToken = address(splTokenParam);\n } catch {\n throw new ParseURLError('spl-token invalid');\n }\n }\n\n let reference: Reference[] | undefined;\n const referenceParams = searchParams.getAll('reference');\n if (referenceParams.length) {\n try {\n reference = referenceParams.map(ref => address(ref));\n } catch {\n throw new ParseURLError('reference invalid');\n }\n }\n\n const label = searchParams.get('label') || undefined;\n const message = searchParams.get('message') || undefined;\n const memo = searchParams.get('memo') || undefined;\n\n return {\n recipient,\n amount,\n splToken,\n reference,\n label,\n message,\n memo,\n };\n}\n","import type {\n Address,\n Commitment,\n GetAccountInfoApi,\n GetLatestBlockhashApi,\n GetMultipleAccountsApi,\n Instruction,\n TransactionSigner,\n} from '@solana/kit';\nimport type { ClientWithPayer, ClientWithRpc } from '@solana/plugin-interfaces';\n\nimport { createTransfer } from '../createTransfer.js';\nimport type { FetchedTransaction } from '../fetchTransaction.js';\nimport { fetchTransaction } from '../fetchTransaction.js';\nimport type { TransactionRequestURL, TransferRequestURL } from '../parseURL.js';\nimport { parseURL } from '../parseURL.js';\nimport type { TransferFields } from '../types.js';\n\ntype WalletRpcApi = GetAccountInfoApi & GetLatestBlockhashApi & GetMultipleAccountsApi;\n\ntype WalletCompatibleClient = ClientWithRpc<WalletRpcApi> & Partial<ClientWithPayer>;\n\n/** Methods added to a client by the wallet plugin. */\nexport interface SolanaPayWalletMethods {\n readonly pay: {\n parseURL(url: URL | string): TransactionRequestURL | TransferRequestURL;\n createTransfer(fields: TransferFields, sender?: TransactionSigner): Promise<Instruction[]>;\n fetchTransaction(\n account: Address,\n link: URL | string,\n options?: { commitment?: Commitment },\n ): Promise<FetchedTransaction>;\n };\n}\n\n/**\n * Wallet plugin for Solana Pay.\n *\n * Adds a `pay` namespace with wallet-side methods: URL parsing,\n * transfer instruction creation, and transaction request fetching.\n * Payer is required for `createTransfer` (via explicit sender or `client.payer`).\n */\nexport function solanaPayWallet() {\n return function installWallet<TClient extends WalletCompatibleClient>(\n client: TClient,\n ): SolanaPayWalletMethods & TClient {\n const existingPay = 'pay' in client ? (client as { pay: Record<string, unknown> }).pay : {};\n const pay: SolanaPayWalletMethods['pay'] = {\n ...existingPay,\n parseURL(url: URL | string): TransactionRequestURL | TransferRequestURL {\n return parseURL(url);\n },\n async createTransfer(fields: TransferFields, sender?: TransactionSigner): Promise<Instruction[]> {\n const signer = sender ?? client.payer;\n if (!signer) {\n throw new Error('solanaPayWallet.createTransfer requires a sender or client.payer');\n }\n return await createTransfer(client.rpc, signer, fields);\n },\n async fetchTransaction(\n account: Address,\n link: URL | string,\n options?: { commitment?: Commitment },\n ): Promise<FetchedTransaction> {\n return await fetchTransaction(client.rpc, account, link, options);\n },\n };\n\n return Object.freeze({ ...client, pay }) as SolanaPayWalletMethods & TClient;\n };\n}\n"],"mappings":"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","names":["import_kit","import_kit","QRCodeStylingModule","import_memo","import_kit","import_memo","import_system","import_token","import_kit","import_kit"]}