@dexterai/x402 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -179,6 +179,54 @@ app.post('/protected', async (req, res) => {
179
179
 
180
180
  ---
181
181
 
182
+ ## 💸 Dynamic Pricing
183
+
184
+ For LLM/AI endpoints where cost scales with input size:
185
+
186
+ ```typescript
187
+ import { createX402Server, createDynamicPricing } from '@dexterai/x402/server';
188
+
189
+ const server = createX402Server({ payTo: '...', network: '...' });
190
+ const pricing = createDynamicPricing({
191
+ unitSize: 1000, // chars per unit
192
+ ratePerUnit: 0.01, // $0.01 per unit
193
+ minUsd: 0.01, // floor
194
+ maxUsd: 10.00, // ceiling
195
+ });
196
+
197
+ app.post('/api/llm', async (req, res) => {
198
+ const { prompt } = req.body;
199
+ const paymentSig = req.headers['payment-signature'];
200
+
201
+ if (!paymentSig) {
202
+ const quote = pricing.calculate(prompt);
203
+ const requirements = await server.buildRequirements({
204
+ amountAtomic: quote.amountAtomic,
205
+ resourceUrl: req.originalUrl,
206
+ });
207
+ res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));
208
+ res.setHeader('X-Quote-Hash', quote.quoteHash);
209
+ return res.status(402).json({ usdAmount: quote.usdAmount });
210
+ }
211
+
212
+ // Validate quote hasn't changed (prevents prompt manipulation)
213
+ const quoteHash = req.headers['x-quote-hash'];
214
+ if (!pricing.validateQuote(prompt, quoteHash)) {
215
+ return res.status(400).json({ error: 'Prompt changed, re-quote required' });
216
+ }
217
+
218
+ const result = await server.settlePayment(paymentSig);
219
+ if (!result.success) return res.status(402).json({ error: result.errorReason });
220
+
221
+ const response = await runLLM(prompt);
222
+ res.json(response);
223
+ });
224
+ ```
225
+
226
+ The client SDK automatically forwards `X-Quote-Hash` on retry.
227
+
228
+ ---
229
+
182
230
  ## 📋 API Reference
183
231
 
184
232
  ### `createX402Client(options)`
@@ -515,6 +515,10 @@ function createX402Client(config) {
515
515
  );
516
516
  }
517
517
  log("Payment requirements:", requirements);
518
+ const quoteHash = response.headers.get("X-Quote-Hash");
519
+ if (quoteHash) {
520
+ log("Quote hash received:", quoteHash);
521
+ }
518
522
  const match = findPaymentOption(requirements.accepts);
519
523
  if (!match) {
520
524
  const availableNetworks = requirements.accepts.map((a) => a.network).join(", ");
@@ -576,7 +580,9 @@ function createX402Client(config) {
576
580
  ...init,
577
581
  headers: {
578
582
  ...init?.headers || {},
579
- "PAYMENT-SIGNATURE": paymentSignatureHeader
583
+ "PAYMENT-SIGNATURE": paymentSignatureHeader,
584
+ // Forward quote hash for dynamic pricing validation
585
+ ...quoteHash ? { "X-Quote-Hash": quoteHash } : {}
580
586
  }
581
587
  });
582
588
  log("Retry response status:", retryResponse.status);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/solana.ts","../../src/adapters/evm.ts","../../src/client/index.ts","../../src/types.ts","../../src/adapters/index.ts","../../src/client/x402-client.ts"],"sourcesContent":["/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.mainnet-beta.solana.com',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields\n const { payTo, asset, amount, extra } = accept;\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n if (typeof extra?.decimals !== 'number') {\n throw new Error('Missing decimals in payment requirements');\n }\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to verify decimals\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ETHEREUM_MAINNET = 'eip155:1';\nexport const ARBITRUM_ONE = 'eip155:42161';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ETHEREUM_MAINNET]: 1,\n [ARBITRUM_ONE]: 42161,\n};\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://mainnet.base.org',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n};\n\n/**\n * USDC addresses by chain (for reference)\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, amount, extra } = accept;\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a random nonce (32 bytes hex)\n const nonce = '0x' + [...Array(32)]\n .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))\n .join('') as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n","/**\n * @dexterai/x402 Client\n *\n * Chain-agnostic client for x402 v2 payments.\n *\n * @example\n * ```typescript\n * import { createX402Client } from '@dexterai/x402/client';\n *\n * // Simple: auto-detects adapters, pass wallet\n * const client = createX402Client({\n * wallet: solanaWallet,\n * });\n *\n * // Multi-chain: explicit wallets\n * const client = createX402Client({\n * wallets: {\n * solana: solanaWallet,\n * evm: evmWallet,\n * },\n * });\n *\n * // Fetch with automatic payment handling\n * const response = await client.fetch('https://api.example.com/protected');\n * ```\n */\n\nexport { createX402Client } from './x402-client';\nexport type { X402ClientConfig, X402Client } from './x402-client';\n\n// Re-export types and adapters for convenience\nexport type { ChainAdapter, WalletSet } from '../adapters/types';\nexport { X402Error } from '../types';\nexport {\n createSolanaAdapter,\n createEvmAdapter,\n SOLANA_MAINNET,\n BASE_MAINNET,\n} from '../adapters';\n\n// Constants\nexport { DEXTER_FACILITATOR_URL, USDC_MINT } from '../types';\n","/**\n * x402 v2 SDK — Shared Types\n *\n * Chain-agnostic types for x402 v2 payments.\n * Works with Solana, Base, and any future x402-compatible networks.\n */\n\n// ============================================================================\n// Network Constants\n// ============================================================================\n\n/** CAIP-2 network identifier for Solana mainnet */\nexport const SOLANA_MAINNET_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n/** CAIP-2 network identifier for Base mainnet */\nexport const BASE_MAINNET_NETWORK = 'eip155:8453';\n\n/** Alias for Solana mainnet */\nexport const SOLANA_MAINNET = SOLANA_MAINNET_NETWORK;\n\n/** Alias for Base mainnet */\nexport const BASE_MAINNET = BASE_MAINNET_NETWORK;\n\n// ============================================================================\n// Asset Constants\n// ============================================================================\n\n/** USDC mint on Solana mainnet */\nexport const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n\n/** USDC address on Base mainnet */\nexport const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\n\n// ============================================================================\n// Facilitator Constants\n// ============================================================================\n\n/** Dexter's public x402 v2 facilitator URL */\nexport const DEXTER_FACILITATOR_URL = 'https://x402.dexter.cash';\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/**\n * Asset configuration for payments\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n /** Optional: Human-readable symbol */\n symbol?: string;\n}\n\n/**\n * Resource info included in payment requirements\n */\nexport interface ResourceInfo {\n /** Resource URL */\n url: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n}\n\n/**\n * Extra fields in payment requirements\n * Chain-specific fields may vary\n */\nexport interface AcceptsExtra {\n /** Facilitator address that pays tx fees (required) */\n feePayer: string;\n /** Token decimals (required) */\n decimals: number;\n /** EIP-712: Token name (EVM only) */\n name?: string;\n /** EIP-712: Token version (EVM only) */\n version?: string;\n /** Additional chain-specific fields */\n [key: string]: unknown;\n}\n\n/**\n * A single payment option in the accepts array\n */\nexport interface PaymentAccept {\n /** Payment scheme (always 'exact' for x402 v2) */\n scheme: 'exact';\n /** CAIP-2 network identifier */\n network: string;\n /** Payment amount in atomic units (as string to avoid precision loss) */\n amount: string;\n /** Token address */\n asset: string;\n /** Seller's address to receive payment */\n payTo: string;\n /** Maximum seconds until payment expires */\n maxTimeoutSeconds: number;\n /** Chain-specific extra data */\n extra: AcceptsExtra;\n}\n\n/**\n * Full PaymentRequired structure (sent in PAYMENT-REQUIRED header)\n */\nexport interface PaymentRequired {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** Available payment options */\n accepts: PaymentAccept[];\n /** Optional error message */\n error?: string;\n}\n\n/**\n * PaymentSignature structure (sent in PAYMENT-SIGNATURE header)\n */\nexport interface PaymentSignature {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** The payment option that was accepted */\n accepted: PaymentAccept;\n /** The signed payment */\n payload: {\n /** Signed transaction (base64 for Solana, JSON for EVM) */\n transaction: string;\n };\n}\n\n// ============================================================================\n// Facilitator Response Types\n// ============================================================================\n\n/**\n * Response from /verify endpoint\n */\nexport interface VerifyResponse {\n /** Whether the payment is valid */\n isValid: boolean;\n /** Reason for invalidity (if invalid) */\n invalidReason?: string;\n /** Payer address */\n payer?: string;\n}\n\n/**\n * Response from /settle endpoint\n */\nexport interface SettleResponse {\n /** Whether settlement succeeded */\n success: boolean;\n /** Transaction signature/hash */\n transaction?: string;\n /** Network the payment was made on */\n network: string;\n /** Error reason (if failed) */\n errorReason?: string;\n /** Error code (if failed) */\n errorCode?: string;\n /** Payer address */\n payer?: string;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * SDK error codes\n */\nexport type X402ErrorCode =\n // Client errors\n | 'missing_payment_required_header'\n | 'invalid_payment_required'\n | 'unsupported_network'\n | 'no_matching_payment_option'\n | 'no_solana_accept' // Legacy, kept for compatibility\n | 'missing_fee_payer'\n | 'missing_decimals'\n | 'amount_exceeds_max'\n | 'insufficient_balance'\n | 'wallet_missing_sign_transaction'\n | 'wallet_not_connected'\n | 'transaction_build_failed'\n | 'payment_rejected'\n // Server errors\n | 'invalid_payment_signature'\n | 'facilitator_verify_failed'\n | 'facilitator_settle_failed'\n | 'facilitator_request_failed'\n | 'no_matching_requirement';\n\n/**\n * Custom error class for x402 operations\n */\nexport class X402Error extends Error {\n /** Error code for programmatic handling */\n code: X402ErrorCode;\n /** Additional error details */\n details?: unknown;\n\n constructor(code: X402ErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, X402Error.prototype);\n }\n}\n","/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n ARBITRUM_ONE,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n const { createSolanaAdapter } = require('./solana');\n const { createEvmAdapter } = require('./evm');\n return [\n createSolanaAdapter({ verbose }),\n createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n","/**\n * x402 v2 Client\n *\n * Chain-agnostic client for x402 v2 payments.\n * Automatically detects 402 responses, finds a matching payment option,\n * builds the transaction with the appropriate chain adapter, and retries.\n *\n * @example\n * ```typescript\n * import { createX402Client } from '@dexterai/x402/client';\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const client = createX402Client({\n * adapters: [createSolanaAdapter(), createEvmAdapter()],\n * wallets: {\n * solana: solanaWallet,\n * evm: evmWallet,\n * },\n * });\n *\n * const response = await client.fetch(url);\n * ```\n */\n\nimport type { ChainAdapter, WalletSet } from '../adapters/types';\nimport type {\n PaymentRequired,\n PaymentAccept,\n} from '../types';\nimport { X402Error } from '../types';\nimport { createSolanaAdapter, createEvmAdapter, isSolanaWallet, isEvmWallet } from '../adapters';\n\n/**\n * Client configuration\n */\nexport interface X402ClientConfig {\n /**\n * Chain adapters to use for building transactions.\n * If not provided, uses Solana and EVM adapters by default.\n */\n adapters?: ChainAdapter[];\n\n /**\n * Wallets for each chain type.\n * Can also pass a single wallet for backwards compatibility.\n */\n wallets?: WalletSet;\n\n /**\n * Legacy: Single wallet (Solana).\n * Use `wallets` for multi-chain support.\n */\n wallet?: unknown;\n\n /**\n * Preferred network to use when multiple options are available.\n * CAIP-2 format (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'eip155:8453')\n */\n preferredNetwork?: string;\n\n /**\n * Custom RPC URLs by network\n */\n rpcUrls?: Record<string, string>;\n\n /**\n * Maximum payment amount allowed (in atomic units).\n * Rejects payments exceeding this amount.\n */\n maxAmountAtomic?: string;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Enable verbose logging\n */\n verbose?: boolean;\n}\n\n/**\n * x402 Client interface\n */\nexport interface X402Client {\n /**\n * Fetch with automatic x402 payment handling.\n * If the server returns 402, handles payment automatically and retries.\n */\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Result of finding a payment option\n */\ninterface MatchedPayment {\n accept: PaymentAccept;\n adapter: ChainAdapter;\n wallet: unknown;\n}\n\n/**\n * Create an x402 v2 client\n */\nexport function createX402Client(config: X402ClientConfig): X402Client {\n const {\n adapters = [createSolanaAdapter({ verbose: config.verbose }), createEvmAdapter({ verbose: config.verbose })],\n wallets: walletSet,\n wallet: legacyWallet,\n preferredNetwork,\n rpcUrls = {},\n maxAmountAtomic,\n fetch: customFetch = globalThis.fetch,\n verbose = false,\n } = config;\n\n const log = verbose\n ? console.log.bind(console, '[x402]')\n : () => {};\n\n // Build wallet set from legacy format if needed\n const wallets: WalletSet = walletSet || {};\n if (legacyWallet && !wallets.solana && isSolanaWallet(legacyWallet)) {\n wallets.solana = legacyWallet;\n }\n if (legacyWallet && !wallets.evm && isEvmWallet(legacyWallet)) {\n wallets.evm = legacyWallet;\n }\n\n /**\n * Find a payment option we can handle\n * Prioritizes:\n * 1. Preferred network (if specified)\n * 2. Networks where we have a connected wallet\n * 3. First available option\n */\n function findPaymentOption(accepts: PaymentAccept[]): MatchedPayment | null {\n // Filter to options we can handle\n const candidates: MatchedPayment[] = [];\n\n for (const accept of accepts) {\n const adapter = adapters.find(a => a.canHandle(accept.network));\n if (!adapter) continue;\n\n // Find the right wallet for this adapter\n let wallet: unknown;\n if (adapter.name === 'Solana') {\n wallet = wallets.solana;\n } else if (adapter.name === 'EVM') {\n wallet = wallets.evm;\n }\n\n if (wallet && adapter.isConnected(wallet)) {\n candidates.push({ accept, adapter, wallet });\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n // Prefer the specified network\n if (preferredNetwork) {\n const preferred = candidates.find(c => c.accept.network === preferredNetwork);\n if (preferred) return preferred;\n }\n\n // Return first available\n return candidates[0];\n }\n\n /**\n * Get RPC URL for a network\n */\n function getRpcUrl(network: string, adapter: ChainAdapter): string {\n return rpcUrls[network] || adapter.getDefaultRpcUrl(network);\n }\n\n /**\n * Main fetch function with x402 payment handling\n */\n async function x402Fetch(\n input: string | URL | Request,\n init?: RequestInit\n ): Promise<Response> {\n log('Making request:', input);\n\n // Make initial request\n const response = await customFetch(input, init);\n\n // If not 402, return as-is\n if (response.status !== 402) {\n return response;\n }\n\n log('Received 402 Payment Required');\n\n // Parse PAYMENT-REQUIRED header\n const paymentRequiredHeader = response.headers.get('PAYMENT-REQUIRED');\n if (!paymentRequiredHeader) {\n throw new X402Error(\n 'missing_payment_required_header',\n 'Server returned 402 but no PAYMENT-REQUIRED header'\n );\n }\n\n let requirements: PaymentRequired;\n try {\n const decoded = atob(paymentRequiredHeader);\n requirements = JSON.parse(decoded);\n } catch {\n throw new X402Error(\n 'invalid_payment_required',\n 'Failed to decode PAYMENT-REQUIRED header'\n );\n }\n\n log('Payment requirements:', requirements);\n\n // Find a payment option we can use\n const match = findPaymentOption(requirements.accepts);\n if (!match) {\n const availableNetworks = requirements.accepts.map(a => a.network).join(', ');\n throw new X402Error(\n 'no_matching_payment_option',\n `No connected wallet for any available network: ${availableNetworks}`\n );\n }\n\n const { accept, adapter, wallet } = match;\n log(`Using ${adapter.name} for ${accept.network}`);\n\n // Validate fee payer (Solana only - EVM users pay their own gas)\n if (adapter.name === 'Solana' && !accept.extra?.feePayer) {\n throw new X402Error(\n 'missing_fee_payer',\n 'Solana payment option missing feePayer in extra'\n );\n }\n\n // Validate decimals\n if (typeof accept.extra?.decimals !== 'number') {\n throw new X402Error(\n 'missing_decimals',\n 'Payment option missing decimals in extra'\n );\n }\n\n // Check amount limit\n if (maxAmountAtomic && BigInt(accept.amount) > BigInt(maxAmountAtomic)) {\n throw new X402Error(\n 'amount_exceeds_max',\n `Payment amount ${accept.amount} exceeds maximum ${maxAmountAtomic}`\n );\n }\n\n // Check balance before signing\n const rpcUrl = getRpcUrl(accept.network, adapter);\n log('Checking balance...');\n const balance = await adapter.getBalance(accept, wallet, rpcUrl);\n const requiredAmount = Number(accept.amount) / Math.pow(10, accept.extra.decimals);\n \n if (balance < requiredAmount) {\n const network = adapter.name === 'EVM' ? 'Base' : 'Solana';\n throw new X402Error(\n 'insufficient_balance',\n `Insufficient USDC balance on ${network}. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`\n );\n }\n log(`Balance OK: $${balance.toFixed(4)} >= $${requiredAmount.toFixed(4)}`);\n\n // Build and sign transaction\n log('Building transaction...');\n const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);\n log('Transaction signed');\n\n // Build PAYMENT-SIGNATURE payload\n // Solana uses payload.transaction (base64 serialized tx)\n // EVM uses payload directly (authorization + signature object)\n let payload: Record<string, unknown>;\n if (adapter.name === 'EVM') {\n // EVM: payload is the authorization + signature object\n payload = JSON.parse(signedTx.serialized);\n } else {\n // Solana: payload.transaction is the base64 tx\n payload = { transaction: signedTx.serialized };\n }\n\n const paymentSignature = {\n x402Version: 2,\n resource: requirements.resource,\n accepted: accept,\n payload,\n };\n\n const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));\n\n // Retry request with payment\n log('Retrying request with payment...');\n const retryResponse = await customFetch(input, {\n ...init,\n headers: {\n ...(init?.headers || {}),\n 'PAYMENT-SIGNATURE': paymentSignatureHeader,\n },\n });\n\n log('Retry response status:', retryResponse.status);\n\n if (retryResponse.status === 402) {\n // Try to get rejection reason from body\n let reason = 'unknown';\n try {\n const body = (await retryResponse.clone().json()) as Record<string, unknown>;\n reason = String(body.error || body.message || JSON.stringify(body));\n log('Rejection reason:', reason);\n } catch {\n // Ignore\n }\n throw new X402Error(\n 'payment_rejected',\n `Payment was rejected by the server: ${reason}`\n );\n }\n\n return retryResponse;\n }\n\n return {\n fetch: x402Fetch,\n };\n}\n\n// Re-export types for convenience\nexport type { ChainAdapter, WalletSet } from '../adapters/types';\nexport { X402Error } from '../types';\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
1
+ {"version":3,"sources":["../../src/adapters/solana.ts","../../src/adapters/evm.ts","../../src/client/index.ts","../../src/types.ts","../../src/adapters/index.ts","../../src/client/x402-client.ts"],"sourcesContent":["/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.mainnet-beta.solana.com',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields\n const { payTo, asset, amount, extra } = accept;\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n if (typeof extra?.decimals !== 'number') {\n throw new Error('Missing decimals in payment requirements');\n }\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to verify decimals\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ETHEREUM_MAINNET = 'eip155:1';\nexport const ARBITRUM_ONE = 'eip155:42161';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ETHEREUM_MAINNET]: 1,\n [ARBITRUM_ONE]: 42161,\n};\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://mainnet.base.org',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n};\n\n/**\n * USDC addresses by chain (for reference)\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, amount, extra } = accept;\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a random nonce (32 bytes hex)\n const nonce = '0x' + [...Array(32)]\n .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))\n .join('') as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n","/**\n * @dexterai/x402 Client\n *\n * Chain-agnostic client for x402 v2 payments.\n *\n * @example\n * ```typescript\n * import { createX402Client } from '@dexterai/x402/client';\n *\n * // Simple: auto-detects adapters, pass wallet\n * const client = createX402Client({\n * wallet: solanaWallet,\n * });\n *\n * // Multi-chain: explicit wallets\n * const client = createX402Client({\n * wallets: {\n * solana: solanaWallet,\n * evm: evmWallet,\n * },\n * });\n *\n * // Fetch with automatic payment handling\n * const response = await client.fetch('https://api.example.com/protected');\n * ```\n */\n\nexport { createX402Client } from './x402-client';\nexport type { X402ClientConfig, X402Client } from './x402-client';\n\n// Re-export types and adapters for convenience\nexport type { ChainAdapter, WalletSet } from '../adapters/types';\nexport { X402Error } from '../types';\nexport {\n createSolanaAdapter,\n createEvmAdapter,\n SOLANA_MAINNET,\n BASE_MAINNET,\n} from '../adapters';\n\n// Constants\nexport { DEXTER_FACILITATOR_URL, USDC_MINT } from '../types';\n","/**\n * x402 v2 SDK — Shared Types\n *\n * Chain-agnostic types for x402 v2 payments.\n * Works with Solana, Base, and any future x402-compatible networks.\n */\n\n// ============================================================================\n// Network Constants\n// ============================================================================\n\n/** CAIP-2 network identifier for Solana mainnet */\nexport const SOLANA_MAINNET_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n/** CAIP-2 network identifier for Base mainnet */\nexport const BASE_MAINNET_NETWORK = 'eip155:8453';\n\n/** Alias for Solana mainnet */\nexport const SOLANA_MAINNET = SOLANA_MAINNET_NETWORK;\n\n/** Alias for Base mainnet */\nexport const BASE_MAINNET = BASE_MAINNET_NETWORK;\n\n// ============================================================================\n// Asset Constants\n// ============================================================================\n\n/** USDC mint on Solana mainnet */\nexport const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n\n/** USDC address on Base mainnet */\nexport const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\n\n// ============================================================================\n// Facilitator Constants\n// ============================================================================\n\n/** Dexter's public x402 v2 facilitator URL */\nexport const DEXTER_FACILITATOR_URL = 'https://x402.dexter.cash';\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/**\n * Asset configuration for payments\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n /** Optional: Human-readable symbol */\n symbol?: string;\n}\n\n/**\n * Resource info included in payment requirements\n */\nexport interface ResourceInfo {\n /** Resource URL */\n url: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n}\n\n/**\n * Extra fields in payment requirements\n * Chain-specific fields may vary\n */\nexport interface AcceptsExtra {\n /** Facilitator address that pays tx fees (required) */\n feePayer: string;\n /** Token decimals (required) */\n decimals: number;\n /** EIP-712: Token name (EVM only) */\n name?: string;\n /** EIP-712: Token version (EVM only) */\n version?: string;\n /** Additional chain-specific fields */\n [key: string]: unknown;\n}\n\n/**\n * A single payment option in the accepts array\n */\nexport interface PaymentAccept {\n /** Payment scheme (always 'exact' for x402 v2) */\n scheme: 'exact';\n /** CAIP-2 network identifier */\n network: string;\n /** Payment amount in atomic units (as string to avoid precision loss) */\n amount: string;\n /** Token address */\n asset: string;\n /** Seller's address to receive payment */\n payTo: string;\n /** Maximum seconds until payment expires */\n maxTimeoutSeconds: number;\n /** Chain-specific extra data */\n extra: AcceptsExtra;\n}\n\n/**\n * Full PaymentRequired structure (sent in PAYMENT-REQUIRED header)\n */\nexport interface PaymentRequired {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** Available payment options */\n accepts: PaymentAccept[];\n /** Optional error message */\n error?: string;\n}\n\n/**\n * PaymentSignature structure (sent in PAYMENT-SIGNATURE header)\n */\nexport interface PaymentSignature {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** The payment option that was accepted */\n accepted: PaymentAccept;\n /** The signed payment */\n payload: {\n /** Signed transaction (base64 for Solana, JSON for EVM) */\n transaction: string;\n };\n}\n\n// ============================================================================\n// Facilitator Response Types\n// ============================================================================\n\n/**\n * Response from /verify endpoint\n */\nexport interface VerifyResponse {\n /** Whether the payment is valid */\n isValid: boolean;\n /** Reason for invalidity (if invalid) */\n invalidReason?: string;\n /** Payer address */\n payer?: string;\n}\n\n/**\n * Response from /settle endpoint\n */\nexport interface SettleResponse {\n /** Whether settlement succeeded */\n success: boolean;\n /** Transaction signature/hash */\n transaction?: string;\n /** Network the payment was made on */\n network: string;\n /** Error reason (if failed) */\n errorReason?: string;\n /** Error code (if failed) */\n errorCode?: string;\n /** Payer address */\n payer?: string;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * SDK error codes\n */\nexport type X402ErrorCode =\n // Client errors\n | 'missing_payment_required_header'\n | 'invalid_payment_required'\n | 'unsupported_network'\n | 'no_matching_payment_option'\n | 'no_solana_accept' // Legacy, kept for compatibility\n | 'missing_fee_payer'\n | 'missing_decimals'\n | 'amount_exceeds_max'\n | 'insufficient_balance'\n | 'wallet_missing_sign_transaction'\n | 'wallet_not_connected'\n | 'transaction_build_failed'\n | 'payment_rejected'\n // Server errors\n | 'invalid_payment_signature'\n | 'facilitator_verify_failed'\n | 'facilitator_settle_failed'\n | 'facilitator_request_failed'\n | 'no_matching_requirement';\n\n/**\n * Custom error class for x402 operations\n */\nexport class X402Error extends Error {\n /** Error code for programmatic handling */\n code: X402ErrorCode;\n /** Additional error details */\n details?: unknown;\n\n constructor(code: X402ErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, X402Error.prototype);\n }\n}\n","/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n ARBITRUM_ONE,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n const { createSolanaAdapter } = require('./solana');\n const { createEvmAdapter } = require('./evm');\n return [\n createSolanaAdapter({ verbose }),\n createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n","/**\n * x402 v2 Client\n *\n * Chain-agnostic client for x402 v2 payments.\n * Automatically detects 402 responses, finds a matching payment option,\n * builds the transaction with the appropriate chain adapter, and retries.\n *\n * @example\n * ```typescript\n * import { createX402Client } from '@dexterai/x402/client';\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const client = createX402Client({\n * adapters: [createSolanaAdapter(), createEvmAdapter()],\n * wallets: {\n * solana: solanaWallet,\n * evm: evmWallet,\n * },\n * });\n *\n * const response = await client.fetch(url);\n * ```\n */\n\nimport type { ChainAdapter, WalletSet } from '../adapters/types';\nimport type {\n PaymentRequired,\n PaymentAccept,\n} from '../types';\nimport { X402Error } from '../types';\nimport { createSolanaAdapter, createEvmAdapter, isSolanaWallet, isEvmWallet } from '../adapters';\n\n/**\n * Client configuration\n */\nexport interface X402ClientConfig {\n /**\n * Chain adapters to use for building transactions.\n * If not provided, uses Solana and EVM adapters by default.\n */\n adapters?: ChainAdapter[];\n\n /**\n * Wallets for each chain type.\n * Can also pass a single wallet for backwards compatibility.\n */\n wallets?: WalletSet;\n\n /**\n * Legacy: Single wallet (Solana).\n * Use `wallets` for multi-chain support.\n */\n wallet?: unknown;\n\n /**\n * Preferred network to use when multiple options are available.\n * CAIP-2 format (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'eip155:8453')\n */\n preferredNetwork?: string;\n\n /**\n * Custom RPC URLs by network\n */\n rpcUrls?: Record<string, string>;\n\n /**\n * Maximum payment amount allowed (in atomic units).\n * Rejects payments exceeding this amount.\n */\n maxAmountAtomic?: string;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Enable verbose logging\n */\n verbose?: boolean;\n}\n\n/**\n * x402 Client interface\n */\nexport interface X402Client {\n /**\n * Fetch with automatic x402 payment handling.\n * If the server returns 402, handles payment automatically and retries.\n */\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Result of finding a payment option\n */\ninterface MatchedPayment {\n accept: PaymentAccept;\n adapter: ChainAdapter;\n wallet: unknown;\n}\n\n/**\n * Create an x402 v2 client\n */\nexport function createX402Client(config: X402ClientConfig): X402Client {\n const {\n adapters = [createSolanaAdapter({ verbose: config.verbose }), createEvmAdapter({ verbose: config.verbose })],\n wallets: walletSet,\n wallet: legacyWallet,\n preferredNetwork,\n rpcUrls = {},\n maxAmountAtomic,\n fetch: customFetch = globalThis.fetch,\n verbose = false,\n } = config;\n\n const log = verbose\n ? console.log.bind(console, '[x402]')\n : () => {};\n\n // Build wallet set from legacy format if needed\n const wallets: WalletSet = walletSet || {};\n if (legacyWallet && !wallets.solana && isSolanaWallet(legacyWallet)) {\n wallets.solana = legacyWallet;\n }\n if (legacyWallet && !wallets.evm && isEvmWallet(legacyWallet)) {\n wallets.evm = legacyWallet;\n }\n\n /**\n * Find a payment option we can handle\n * Prioritizes:\n * 1. Preferred network (if specified)\n * 2. Networks where we have a connected wallet\n * 3. First available option\n */\n function findPaymentOption(accepts: PaymentAccept[]): MatchedPayment | null {\n // Filter to options we can handle\n const candidates: MatchedPayment[] = [];\n\n for (const accept of accepts) {\n const adapter = adapters.find(a => a.canHandle(accept.network));\n if (!adapter) continue;\n\n // Find the right wallet for this adapter\n let wallet: unknown;\n if (adapter.name === 'Solana') {\n wallet = wallets.solana;\n } else if (adapter.name === 'EVM') {\n wallet = wallets.evm;\n }\n\n if (wallet && adapter.isConnected(wallet)) {\n candidates.push({ accept, adapter, wallet });\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n // Prefer the specified network\n if (preferredNetwork) {\n const preferred = candidates.find(c => c.accept.network === preferredNetwork);\n if (preferred) return preferred;\n }\n\n // Return first available\n return candidates[0];\n }\n\n /**\n * Get RPC URL for a network\n */\n function getRpcUrl(network: string, adapter: ChainAdapter): string {\n return rpcUrls[network] || adapter.getDefaultRpcUrl(network);\n }\n\n /**\n * Main fetch function with x402 payment handling\n */\n async function x402Fetch(\n input: string | URL | Request,\n init?: RequestInit\n ): Promise<Response> {\n log('Making request:', input);\n\n // Make initial request\n const response = await customFetch(input, init);\n\n // If not 402, return as-is\n if (response.status !== 402) {\n return response;\n }\n\n log('Received 402 Payment Required');\n\n // Parse PAYMENT-REQUIRED header\n const paymentRequiredHeader = response.headers.get('PAYMENT-REQUIRED');\n if (!paymentRequiredHeader) {\n throw new X402Error(\n 'missing_payment_required_header',\n 'Server returned 402 but no PAYMENT-REQUIRED header'\n );\n }\n\n let requirements: PaymentRequired;\n try {\n const decoded = atob(paymentRequiredHeader);\n requirements = JSON.parse(decoded);\n } catch {\n throw new X402Error(\n 'invalid_payment_required',\n 'Failed to decode PAYMENT-REQUIRED header'\n );\n }\n\n log('Payment requirements:', requirements);\n\n // Capture X-Quote-Hash if present (for dynamic pricing validation)\n const quoteHash = response.headers.get('X-Quote-Hash');\n if (quoteHash) {\n log('Quote hash received:', quoteHash);\n }\n\n // Find a payment option we can use\n const match = findPaymentOption(requirements.accepts);\n if (!match) {\n const availableNetworks = requirements.accepts.map(a => a.network).join(', ');\n throw new X402Error(\n 'no_matching_payment_option',\n `No connected wallet for any available network: ${availableNetworks}`\n );\n }\n\n const { accept, adapter, wallet } = match;\n log(`Using ${adapter.name} for ${accept.network}`);\n\n // Validate fee payer (Solana only - EVM users pay their own gas)\n if (adapter.name === 'Solana' && !accept.extra?.feePayer) {\n throw new X402Error(\n 'missing_fee_payer',\n 'Solana payment option missing feePayer in extra'\n );\n }\n\n // Validate decimals\n if (typeof accept.extra?.decimals !== 'number') {\n throw new X402Error(\n 'missing_decimals',\n 'Payment option missing decimals in extra'\n );\n }\n\n // Check amount limit\n if (maxAmountAtomic && BigInt(accept.amount) > BigInt(maxAmountAtomic)) {\n throw new X402Error(\n 'amount_exceeds_max',\n `Payment amount ${accept.amount} exceeds maximum ${maxAmountAtomic}`\n );\n }\n\n // Check balance before signing\n const rpcUrl = getRpcUrl(accept.network, adapter);\n log('Checking balance...');\n const balance = await adapter.getBalance(accept, wallet, rpcUrl);\n const requiredAmount = Number(accept.amount) / Math.pow(10, accept.extra.decimals);\n \n if (balance < requiredAmount) {\n const network = adapter.name === 'EVM' ? 'Base' : 'Solana';\n throw new X402Error(\n 'insufficient_balance',\n `Insufficient USDC balance on ${network}. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`\n );\n }\n log(`Balance OK: $${balance.toFixed(4)} >= $${requiredAmount.toFixed(4)}`);\n\n // Build and sign transaction\n log('Building transaction...');\n const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);\n log('Transaction signed');\n\n // Build PAYMENT-SIGNATURE payload\n // Solana uses payload.transaction (base64 serialized tx)\n // EVM uses payload directly (authorization + signature object)\n let payload: Record<string, unknown>;\n if (adapter.name === 'EVM') {\n // EVM: payload is the authorization + signature object\n payload = JSON.parse(signedTx.serialized);\n } else {\n // Solana: payload.transaction is the base64 tx\n payload = { transaction: signedTx.serialized };\n }\n\n const paymentSignature = {\n x402Version: 2,\n resource: requirements.resource,\n accepted: accept,\n payload,\n };\n\n const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));\n\n // Retry request with payment\n log('Retrying request with payment...');\n const retryResponse = await customFetch(input, {\n ...init,\n headers: {\n ...(init?.headers || {}),\n 'PAYMENT-SIGNATURE': paymentSignatureHeader,\n // Forward quote hash for dynamic pricing validation\n ...(quoteHash ? { 'X-Quote-Hash': quoteHash } : {}),\n },\n });\n\n log('Retry response status:', retryResponse.status);\n\n if (retryResponse.status === 402) {\n // Try to get rejection reason from body\n let reason = 'unknown';\n try {\n const body = (await retryResponse.clone().json()) as Record<string, unknown>;\n reason = String(body.error || body.message || JSON.stringify(body));\n log('Rejection reason:', reason);\n } catch {\n // Ignore\n }\n throw new X402Error(\n 'payment_rejected',\n `Payment was rejected by the server: ${reason}`\n );\n }\n\n return retryResponse;\n }\n\n return {\n fetch: x402Fetch,\n };\n}\n\n// Re-export types for convenience\nexport type { ChainAdapter, WalletSet } from '../adapters/types';\nexport { X402Error } from '../types';\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
@@ -497,6 +497,10 @@ function createX402Client(config) {
497
497
  );
498
498
  }
499
499
  log("Payment requirements:", requirements);
500
+ const quoteHash = response.headers.get("X-Quote-Hash");
501
+ if (quoteHash) {
502
+ log("Quote hash received:", quoteHash);
503
+ }
500
504
  const match = findPaymentOption(requirements.accepts);
501
505
  if (!match) {
502
506
  const availableNetworks = requirements.accepts.map((a) => a.network).join(", ");
@@ -558,7 +562,9 @@ function createX402Client(config) {
558
562
  ...init,
559
563
  headers: {
560
564
  ...init?.headers || {},
561
- "PAYMENT-SIGNATURE": paymentSignatureHeader
565
+ "PAYMENT-SIGNATURE": paymentSignatureHeader,
566
+ // Forward quote hash for dynamic pricing validation
567
+ ...quoteHash ? { "X-Quote-Hash": quoteHash } : {}
562
568
  }
563
569
  });
564
570
  log("Retry response status:", retryResponse.status);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/solana.ts","../../src/adapters/evm.ts","../../src/types.ts","../../src/adapters/index.ts","../../src/client/x402-client.ts"],"sourcesContent":["/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.mainnet-beta.solana.com',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields\n const { payTo, asset, amount, extra } = accept;\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n if (typeof extra?.decimals !== 'number') {\n throw new Error('Missing decimals in payment requirements');\n }\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to verify decimals\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ETHEREUM_MAINNET = 'eip155:1';\nexport const ARBITRUM_ONE = 'eip155:42161';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ETHEREUM_MAINNET]: 1,\n [ARBITRUM_ONE]: 42161,\n};\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://mainnet.base.org',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n};\n\n/**\n * USDC addresses by chain (for reference)\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, amount, extra } = accept;\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a random nonce (32 bytes hex)\n const nonce = '0x' + [...Array(32)]\n .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))\n .join('') as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n","/**\n * x402 v2 SDK — Shared Types\n *\n * Chain-agnostic types for x402 v2 payments.\n * Works with Solana, Base, and any future x402-compatible networks.\n */\n\n// ============================================================================\n// Network Constants\n// ============================================================================\n\n/** CAIP-2 network identifier for Solana mainnet */\nexport const SOLANA_MAINNET_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n/** CAIP-2 network identifier for Base mainnet */\nexport const BASE_MAINNET_NETWORK = 'eip155:8453';\n\n/** Alias for Solana mainnet */\nexport const SOLANA_MAINNET = SOLANA_MAINNET_NETWORK;\n\n/** Alias for Base mainnet */\nexport const BASE_MAINNET = BASE_MAINNET_NETWORK;\n\n// ============================================================================\n// Asset Constants\n// ============================================================================\n\n/** USDC mint on Solana mainnet */\nexport const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n\n/** USDC address on Base mainnet */\nexport const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\n\n// ============================================================================\n// Facilitator Constants\n// ============================================================================\n\n/** Dexter's public x402 v2 facilitator URL */\nexport const DEXTER_FACILITATOR_URL = 'https://x402.dexter.cash';\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/**\n * Asset configuration for payments\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n /** Optional: Human-readable symbol */\n symbol?: string;\n}\n\n/**\n * Resource info included in payment requirements\n */\nexport interface ResourceInfo {\n /** Resource URL */\n url: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n}\n\n/**\n * Extra fields in payment requirements\n * Chain-specific fields may vary\n */\nexport interface AcceptsExtra {\n /** Facilitator address that pays tx fees (required) */\n feePayer: string;\n /** Token decimals (required) */\n decimals: number;\n /** EIP-712: Token name (EVM only) */\n name?: string;\n /** EIP-712: Token version (EVM only) */\n version?: string;\n /** Additional chain-specific fields */\n [key: string]: unknown;\n}\n\n/**\n * A single payment option in the accepts array\n */\nexport interface PaymentAccept {\n /** Payment scheme (always 'exact' for x402 v2) */\n scheme: 'exact';\n /** CAIP-2 network identifier */\n network: string;\n /** Payment amount in atomic units (as string to avoid precision loss) */\n amount: string;\n /** Token address */\n asset: string;\n /** Seller's address to receive payment */\n payTo: string;\n /** Maximum seconds until payment expires */\n maxTimeoutSeconds: number;\n /** Chain-specific extra data */\n extra: AcceptsExtra;\n}\n\n/**\n * Full PaymentRequired structure (sent in PAYMENT-REQUIRED header)\n */\nexport interface PaymentRequired {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** Available payment options */\n accepts: PaymentAccept[];\n /** Optional error message */\n error?: string;\n}\n\n/**\n * PaymentSignature structure (sent in PAYMENT-SIGNATURE header)\n */\nexport interface PaymentSignature {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** The payment option that was accepted */\n accepted: PaymentAccept;\n /** The signed payment */\n payload: {\n /** Signed transaction (base64 for Solana, JSON for EVM) */\n transaction: string;\n };\n}\n\n// ============================================================================\n// Facilitator Response Types\n// ============================================================================\n\n/**\n * Response from /verify endpoint\n */\nexport interface VerifyResponse {\n /** Whether the payment is valid */\n isValid: boolean;\n /** Reason for invalidity (if invalid) */\n invalidReason?: string;\n /** Payer address */\n payer?: string;\n}\n\n/**\n * Response from /settle endpoint\n */\nexport interface SettleResponse {\n /** Whether settlement succeeded */\n success: boolean;\n /** Transaction signature/hash */\n transaction?: string;\n /** Network the payment was made on */\n network: string;\n /** Error reason (if failed) */\n errorReason?: string;\n /** Error code (if failed) */\n errorCode?: string;\n /** Payer address */\n payer?: string;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * SDK error codes\n */\nexport type X402ErrorCode =\n // Client errors\n | 'missing_payment_required_header'\n | 'invalid_payment_required'\n | 'unsupported_network'\n | 'no_matching_payment_option'\n | 'no_solana_accept' // Legacy, kept for compatibility\n | 'missing_fee_payer'\n | 'missing_decimals'\n | 'amount_exceeds_max'\n | 'insufficient_balance'\n | 'wallet_missing_sign_transaction'\n | 'wallet_not_connected'\n | 'transaction_build_failed'\n | 'payment_rejected'\n // Server errors\n | 'invalid_payment_signature'\n | 'facilitator_verify_failed'\n | 'facilitator_settle_failed'\n | 'facilitator_request_failed'\n | 'no_matching_requirement';\n\n/**\n * Custom error class for x402 operations\n */\nexport class X402Error extends Error {\n /** Error code for programmatic handling */\n code: X402ErrorCode;\n /** Additional error details */\n details?: unknown;\n\n constructor(code: X402ErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, X402Error.prototype);\n }\n}\n","/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n ARBITRUM_ONE,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n const { createSolanaAdapter } = require('./solana');\n const { createEvmAdapter } = require('./evm');\n return [\n createSolanaAdapter({ verbose }),\n createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n","/**\n * x402 v2 Client\n *\n * Chain-agnostic client for x402 v2 payments.\n * Automatically detects 402 responses, finds a matching payment option,\n * builds the transaction with the appropriate chain adapter, and retries.\n *\n * @example\n * ```typescript\n * import { createX402Client } from '@dexterai/x402/client';\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const client = createX402Client({\n * adapters: [createSolanaAdapter(), createEvmAdapter()],\n * wallets: {\n * solana: solanaWallet,\n * evm: evmWallet,\n * },\n * });\n *\n * const response = await client.fetch(url);\n * ```\n */\n\nimport type { ChainAdapter, WalletSet } from '../adapters/types';\nimport type {\n PaymentRequired,\n PaymentAccept,\n} from '../types';\nimport { X402Error } from '../types';\nimport { createSolanaAdapter, createEvmAdapter, isSolanaWallet, isEvmWallet } from '../adapters';\n\n/**\n * Client configuration\n */\nexport interface X402ClientConfig {\n /**\n * Chain adapters to use for building transactions.\n * If not provided, uses Solana and EVM adapters by default.\n */\n adapters?: ChainAdapter[];\n\n /**\n * Wallets for each chain type.\n * Can also pass a single wallet for backwards compatibility.\n */\n wallets?: WalletSet;\n\n /**\n * Legacy: Single wallet (Solana).\n * Use `wallets` for multi-chain support.\n */\n wallet?: unknown;\n\n /**\n * Preferred network to use when multiple options are available.\n * CAIP-2 format (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'eip155:8453')\n */\n preferredNetwork?: string;\n\n /**\n * Custom RPC URLs by network\n */\n rpcUrls?: Record<string, string>;\n\n /**\n * Maximum payment amount allowed (in atomic units).\n * Rejects payments exceeding this amount.\n */\n maxAmountAtomic?: string;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Enable verbose logging\n */\n verbose?: boolean;\n}\n\n/**\n * x402 Client interface\n */\nexport interface X402Client {\n /**\n * Fetch with automatic x402 payment handling.\n * If the server returns 402, handles payment automatically and retries.\n */\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Result of finding a payment option\n */\ninterface MatchedPayment {\n accept: PaymentAccept;\n adapter: ChainAdapter;\n wallet: unknown;\n}\n\n/**\n * Create an x402 v2 client\n */\nexport function createX402Client(config: X402ClientConfig): X402Client {\n const {\n adapters = [createSolanaAdapter({ verbose: config.verbose }), createEvmAdapter({ verbose: config.verbose })],\n wallets: walletSet,\n wallet: legacyWallet,\n preferredNetwork,\n rpcUrls = {},\n maxAmountAtomic,\n fetch: customFetch = globalThis.fetch,\n verbose = false,\n } = config;\n\n const log = verbose\n ? console.log.bind(console, '[x402]')\n : () => {};\n\n // Build wallet set from legacy format if needed\n const wallets: WalletSet = walletSet || {};\n if (legacyWallet && !wallets.solana && isSolanaWallet(legacyWallet)) {\n wallets.solana = legacyWallet;\n }\n if (legacyWallet && !wallets.evm && isEvmWallet(legacyWallet)) {\n wallets.evm = legacyWallet;\n }\n\n /**\n * Find a payment option we can handle\n * Prioritizes:\n * 1. Preferred network (if specified)\n * 2. Networks where we have a connected wallet\n * 3. First available option\n */\n function findPaymentOption(accepts: PaymentAccept[]): MatchedPayment | null {\n // Filter to options we can handle\n const candidates: MatchedPayment[] = [];\n\n for (const accept of accepts) {\n const adapter = adapters.find(a => a.canHandle(accept.network));\n if (!adapter) continue;\n\n // Find the right wallet for this adapter\n let wallet: unknown;\n if (adapter.name === 'Solana') {\n wallet = wallets.solana;\n } else if (adapter.name === 'EVM') {\n wallet = wallets.evm;\n }\n\n if (wallet && adapter.isConnected(wallet)) {\n candidates.push({ accept, adapter, wallet });\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n // Prefer the specified network\n if (preferredNetwork) {\n const preferred = candidates.find(c => c.accept.network === preferredNetwork);\n if (preferred) return preferred;\n }\n\n // Return first available\n return candidates[0];\n }\n\n /**\n * Get RPC URL for a network\n */\n function getRpcUrl(network: string, adapter: ChainAdapter): string {\n return rpcUrls[network] || adapter.getDefaultRpcUrl(network);\n }\n\n /**\n * Main fetch function with x402 payment handling\n */\n async function x402Fetch(\n input: string | URL | Request,\n init?: RequestInit\n ): Promise<Response> {\n log('Making request:', input);\n\n // Make initial request\n const response = await customFetch(input, init);\n\n // If not 402, return as-is\n if (response.status !== 402) {\n return response;\n }\n\n log('Received 402 Payment Required');\n\n // Parse PAYMENT-REQUIRED header\n const paymentRequiredHeader = response.headers.get('PAYMENT-REQUIRED');\n if (!paymentRequiredHeader) {\n throw new X402Error(\n 'missing_payment_required_header',\n 'Server returned 402 but no PAYMENT-REQUIRED header'\n );\n }\n\n let requirements: PaymentRequired;\n try {\n const decoded = atob(paymentRequiredHeader);\n requirements = JSON.parse(decoded);\n } catch {\n throw new X402Error(\n 'invalid_payment_required',\n 'Failed to decode PAYMENT-REQUIRED header'\n );\n }\n\n log('Payment requirements:', requirements);\n\n // Find a payment option we can use\n const match = findPaymentOption(requirements.accepts);\n if (!match) {\n const availableNetworks = requirements.accepts.map(a => a.network).join(', ');\n throw new X402Error(\n 'no_matching_payment_option',\n `No connected wallet for any available network: ${availableNetworks}`\n );\n }\n\n const { accept, adapter, wallet } = match;\n log(`Using ${adapter.name} for ${accept.network}`);\n\n // Validate fee payer (Solana only - EVM users pay their own gas)\n if (adapter.name === 'Solana' && !accept.extra?.feePayer) {\n throw new X402Error(\n 'missing_fee_payer',\n 'Solana payment option missing feePayer in extra'\n );\n }\n\n // Validate decimals\n if (typeof accept.extra?.decimals !== 'number') {\n throw new X402Error(\n 'missing_decimals',\n 'Payment option missing decimals in extra'\n );\n }\n\n // Check amount limit\n if (maxAmountAtomic && BigInt(accept.amount) > BigInt(maxAmountAtomic)) {\n throw new X402Error(\n 'amount_exceeds_max',\n `Payment amount ${accept.amount} exceeds maximum ${maxAmountAtomic}`\n );\n }\n\n // Check balance before signing\n const rpcUrl = getRpcUrl(accept.network, adapter);\n log('Checking balance...');\n const balance = await adapter.getBalance(accept, wallet, rpcUrl);\n const requiredAmount = Number(accept.amount) / Math.pow(10, accept.extra.decimals);\n \n if (balance < requiredAmount) {\n const network = adapter.name === 'EVM' ? 'Base' : 'Solana';\n throw new X402Error(\n 'insufficient_balance',\n `Insufficient USDC balance on ${network}. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`\n );\n }\n log(`Balance OK: $${balance.toFixed(4)} >= $${requiredAmount.toFixed(4)}`);\n\n // Build and sign transaction\n log('Building transaction...');\n const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);\n log('Transaction signed');\n\n // Build PAYMENT-SIGNATURE payload\n // Solana uses payload.transaction (base64 serialized tx)\n // EVM uses payload directly (authorization + signature object)\n let payload: Record<string, unknown>;\n if (adapter.name === 'EVM') {\n // EVM: payload is the authorization + signature object\n payload = JSON.parse(signedTx.serialized);\n } else {\n // Solana: payload.transaction is the base64 tx\n payload = { transaction: signedTx.serialized };\n }\n\n const paymentSignature = {\n x402Version: 2,\n resource: requirements.resource,\n accepted: accept,\n payload,\n };\n\n const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));\n\n // Retry request with payment\n log('Retrying request with payment...');\n const retryResponse = await customFetch(input, {\n ...init,\n headers: {\n ...(init?.headers || {}),\n 'PAYMENT-SIGNATURE': paymentSignatureHeader,\n },\n });\n\n log('Retry response status:', retryResponse.status);\n\n if (retryResponse.status === 402) {\n // Try to get rejection reason from body\n let reason = 'unknown';\n try {\n const body = (await retryResponse.clone().json()) as Record<string, unknown>;\n reason = String(body.error || body.message || JSON.stringify(body));\n log('Rejection reason:', reason);\n } catch {\n // Ignore\n }\n throw new X402Error(\n 'payment_rejected',\n `Payment was rejected by the server: ${reason}`\n );\n }\n\n return retryResponse;\n }\n\n return {\n fetch: x402Fetch,\n };\n}\n\n// Re-export types for convenience\nexport type { ChainAdapter, WalletSet } from '../adapters/types';\nexport { X402Error } from '../types';\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}
1
+ {"version":3,"sources":["../../src/adapters/solana.ts","../../src/adapters/evm.ts","../../src/types.ts","../../src/adapters/index.ts","../../src/client/x402-client.ts"],"sourcesContent":["/**\n * Solana Chain Adapter\n *\n * Implements the ChainAdapter interface for Solana networks.\n * Handles transaction building, signing, and balance queries.\n */\n\nimport {\n PublicKey,\n Connection,\n TransactionMessage,\n VersionedTransaction,\n ComputeBudgetProgram,\n type TransactionInstruction,\n} from '@solana/web3.js';\nimport {\n getAssociatedTokenAddress,\n getAccount,\n createTransferCheckedInstruction,\n getMint,\n TOKEN_PROGRAM_ID,\n TOKEN_2022_PROGRAM_ID,\n} from '@solana/spl-token';\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for Solana\n */\nexport const SOLANA_MAINNET = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nexport const SOLANA_DEVNET = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\nexport const SOLANA_TESTNET = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z';\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [SOLANA_MAINNET]: 'https://api.mainnet-beta.solana.com',\n [SOLANA_DEVNET]: 'https://api.devnet.solana.com',\n [SOLANA_TESTNET]: 'https://api.testnet.solana.com',\n};\n\n/**\n * Dexter policy-safe compute budget settings\n */\nconst DEFAULT_COMPUTE_UNIT_LIMIT = 12_000;\nconst DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS = 1;\n\n/**\n * Solana wallet interface (compatible with @solana/wallet-adapter)\n */\nexport interface SolanaWallet {\n publicKey: { toBase58(): string } | null;\n signTransaction<T>(tx: T): Promise<T>;\n}\n\n/**\n * Check if an object is a valid Solana wallet\n */\nexport function isSolanaWallet(wallet: unknown): wallet is SolanaWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'publicKey' in w &&\n 'signTransaction' in w &&\n typeof w.signTransaction === 'function'\n );\n}\n\n/**\n * Solana Chain Adapter\n */\nexport class SolanaAdapter implements ChainAdapter {\n readonly name = 'Solana';\n readonly networks = [SOLANA_MAINNET, SOLANA_DEVNET, SOLANA_TESTNET];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:solana]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle both exact CAIP-2 and legacy formats\n if (this.networks.includes(network)) return true;\n // Legacy format support\n if (network === 'solana') return true;\n if (network === 'solana-devnet') return true;\n if (network === 'solana-testnet') return true;\n // Check if it starts with 'solana:'\n if (network.startsWith('solana:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n // Check custom config first\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n // Check defaults\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy networks\n if (network === 'solana') return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n if (network === 'solana-devnet') return DEFAULT_RPC_URLS[SOLANA_DEVNET];\n if (network === 'solana-testnet') return DEFAULT_RPC_URLS[SOLANA_TESTNET];\n // Default to mainnet\n return DEFAULT_RPC_URLS[SOLANA_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isSolanaWallet(wallet)) return null;\n return wallet.publicKey?.toBase58() ?? null;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isSolanaWallet(wallet)) return false;\n return wallet.publicKey !== null;\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isSolanaWallet(wallet) || !wallet.publicKey) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n const mintPubkey = new PublicKey(accept.asset);\n\n try {\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n const programId =\n mintInfo?.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n const ata = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n\n const account = await getAccount(connection, ata, undefined, programId);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(account.amount) / Math.pow(10, decimals);\n } catch {\n // Token account doesn't exist\n return 0;\n }\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isSolanaWallet(wallet)) {\n throw new Error('Invalid Solana wallet');\n }\n if (!wallet.publicKey) {\n throw new Error('Wallet not connected');\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n const connection = new Connection(url, 'confirmed');\n const userPubkey = new PublicKey(wallet.publicKey.toBase58());\n\n // Extract required fields\n const { payTo, asset, amount, extra } = accept;\n\n if (!extra?.feePayer) {\n throw new Error('Missing feePayer in payment requirements');\n }\n if (typeof extra?.decimals !== 'number') {\n throw new Error('Missing decimals in payment requirements');\n }\n\n const feePayerPubkey = new PublicKey(extra.feePayer);\n const mintPubkey = new PublicKey(asset);\n const destinationPubkey = new PublicKey(payTo);\n\n this.log('Building transaction:', {\n from: userPubkey.toBase58(),\n to: payTo,\n amount,\n asset,\n feePayer: extra.feePayer,\n });\n\n // Build instructions\n const instructions: TransactionInstruction[] = [];\n\n // 1. ComputeBudget: Set compute unit limit\n instructions.push(\n ComputeBudgetProgram.setComputeUnitLimit({\n units: DEFAULT_COMPUTE_UNIT_LIMIT,\n })\n );\n\n // 2. ComputeBudget: Set compute unit price\n instructions.push(\n ComputeBudgetProgram.setComputeUnitPrice({\n microLamports: DEFAULT_COMPUTE_UNIT_PRICE_MICROLAMPORTS,\n })\n );\n\n // 3. Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) {\n throw new Error(`Token mint ${asset} not found`);\n }\n\n const programId =\n mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58()\n ? TOKEN_2022_PROGRAM_ID\n : TOKEN_PROGRAM_ID;\n\n // Fetch mint to verify decimals\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n if (mint.decimals !== extra.decimals) {\n this.log(\n `Decimals mismatch: requirements say ${extra.decimals}, mint says ${mint.decimals}`\n );\n }\n\n // Derive Associated Token Accounts\n const sourceAta = await getAssociatedTokenAddress(\n mintPubkey,\n userPubkey,\n false,\n programId\n );\n const destinationAta = await getAssociatedTokenAddress(\n mintPubkey,\n destinationPubkey,\n false,\n programId\n );\n\n // Verify source ATA exists\n const sourceAtaInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceAtaInfo) {\n throw new Error(\n `No token account found for ${asset}. Please ensure you have USDC in your wallet.`\n );\n }\n\n // Verify destination ATA exists\n const destAtaInfo = await connection.getAccountInfo(destinationAta, 'confirmed');\n if (!destAtaInfo) {\n throw new Error(\n `Seller token account not found. The seller (${payTo}) must have a USDC account.`\n );\n }\n\n // 4. TransferChecked instruction\n const amountBigInt = BigInt(amount);\n instructions.push(\n createTransferCheckedInstruction(\n sourceAta,\n mintPubkey,\n destinationAta,\n userPubkey,\n amountBigInt,\n mint.decimals,\n [],\n programId\n )\n );\n\n // Get recent blockhash\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n\n // Compile to V0 message (feePayer is facilitator)\n const message = new TransactionMessage({\n payerKey: feePayerPubkey,\n recentBlockhash: blockhash,\n instructions,\n }).compileToV0Message();\n\n // Create and sign transaction\n const transaction = new VersionedTransaction(message);\n const signedTx = await wallet.signTransaction(transaction);\n\n this.log('Transaction signed successfully');\n\n return {\n serialized: Buffer.from(signedTx.serialize()).toString('base64'),\n };\n }\n}\n\n/**\n * Create a Solana adapter instance\n */\nexport function createSolanaAdapter(config?: AdapterConfig): SolanaAdapter {\n return new SolanaAdapter(config);\n}\n\n","/**\n * EVM Chain Adapter\n *\n * Implements the ChainAdapter interface for EVM networks (Base, Ethereum, Arbitrum, etc.)\n * Uses EIP-712 typed data signing for x402 v2 payments.\n */\n\nimport type { ChainAdapter, AdapterConfig, SignedTransaction } from './types';\nimport type { PaymentAccept } from '../types';\n\n/**\n * CAIP-2 network identifiers for EVM chains\n */\nexport const BASE_MAINNET = 'eip155:8453';\nexport const BASE_SEPOLIA = 'eip155:84532';\nexport const ETHEREUM_MAINNET = 'eip155:1';\nexport const ARBITRUM_ONE = 'eip155:42161';\n\n/**\n * Chain IDs by CAIP-2 network\n */\nconst CHAIN_IDS: Record<string, number> = {\n [BASE_MAINNET]: 8453,\n [BASE_SEPOLIA]: 84532,\n [ETHEREUM_MAINNET]: 1,\n [ARBITRUM_ONE]: 42161,\n};\n\n/**\n * Default RPC URLs\n */\nconst DEFAULT_RPC_URLS: Record<string, string> = {\n [BASE_MAINNET]: 'https://mainnet.base.org',\n [BASE_SEPOLIA]: 'https://sepolia.base.org',\n [ETHEREUM_MAINNET]: 'https://eth.llamarpc.com',\n [ARBITRUM_ONE]: 'https://arb1.arbitrum.io/rpc',\n};\n\n/**\n * USDC addresses by chain (for reference)\n */\nexport const USDC_ADDRESSES: Record<string, string> = {\n [BASE_MAINNET]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n [ETHEREUM_MAINNET]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n [ARBITRUM_ONE]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n};\n\n/**\n * EVM wallet interface (compatible with wagmi, ethers, viem)\n */\nexport interface EvmWallet {\n /** Wallet address */\n address: string;\n /** Chain ID currently connected to */\n chainId?: number;\n /**\n * Sign typed data (EIP-712)\n * This is the primary signing method for x402 EVM payments\n */\n signTypedData?(params: {\n domain: Record<string, unknown>;\n types: Record<string, unknown[]>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<string>;\n /**\n * Alternative: Send transaction directly\n * Used if signTypedData is not available\n */\n sendTransaction?(params: {\n to: string;\n data: string;\n value?: bigint;\n }): Promise<string>;\n}\n\n/**\n * Check if an object is a valid EVM wallet\n */\nexport function isEvmWallet(wallet: unknown): wallet is EvmWallet {\n if (!wallet || typeof wallet !== 'object') return false;\n const w = wallet as Record<string, unknown>;\n return (\n 'address' in w &&\n typeof w.address === 'string' &&\n w.address.startsWith('0x')\n );\n}\n\n// ERC20 balanceOf function selector: 0x70a08231\n\n/**\n * EVM Chain Adapter\n */\nexport class EvmAdapter implements ChainAdapter {\n readonly name = 'EVM';\n readonly networks = [BASE_MAINNET, BASE_SEPOLIA, ETHEREUM_MAINNET, ARBITRUM_ONE];\n\n private config: AdapterConfig;\n private log: (...args: unknown[]) => void;\n\n constructor(config: AdapterConfig = {}) {\n this.config = config;\n this.log = config.verbose\n ? console.log.bind(console, '[x402:evm]')\n : () => {};\n }\n\n canHandle(network: string): boolean {\n // Handle exact CAIP-2\n if (this.networks.includes(network)) return true;\n // Legacy format\n if (network === 'base') return true;\n if (network === 'ethereum') return true;\n if (network === 'arbitrum') return true;\n // Check if it starts with 'eip155:'\n if (network.startsWith('eip155:')) return true;\n return false;\n }\n\n getDefaultRpcUrl(network: string): string {\n if (this.config.rpcUrls?.[network]) {\n return this.config.rpcUrls[network];\n }\n if (DEFAULT_RPC_URLS[network]) {\n return DEFAULT_RPC_URLS[network];\n }\n // Normalize legacy\n if (network === 'base') return DEFAULT_RPC_URLS[BASE_MAINNET];\n if (network === 'ethereum') return DEFAULT_RPC_URLS[ETHEREUM_MAINNET];\n if (network === 'arbitrum') return DEFAULT_RPC_URLS[ARBITRUM_ONE];\n return DEFAULT_RPC_URLS[BASE_MAINNET];\n }\n\n getAddress(wallet: unknown): string | null {\n if (!isEvmWallet(wallet)) return null;\n return wallet.address;\n }\n\n isConnected(wallet: unknown): boolean {\n if (!isEvmWallet(wallet)) return false;\n return !!wallet.address;\n }\n\n private getChainId(network: string): number {\n if (CHAIN_IDS[network]) return CHAIN_IDS[network];\n // Try to extract from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainIdStr = network.split(':')[1];\n return parseInt(chainIdStr, 10);\n }\n // Defaults\n if (network === 'base') return 8453;\n if (network === 'ethereum') return 1;\n if (network === 'arbitrum') return 42161;\n return 8453; // Default to Base\n }\n\n async getBalance(\n accept: PaymentAccept,\n wallet: unknown,\n rpcUrl?: string\n ): Promise<number> {\n if (!isEvmWallet(wallet) || !wallet.address) {\n return 0;\n }\n\n const url = rpcUrl || this.getDefaultRpcUrl(accept.network);\n\n try {\n // Use eth_call to check ERC20 balance\n const data = this.encodeBalanceOf(wallet.address);\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'eth_call',\n params: [\n {\n to: accept.asset,\n data,\n },\n 'latest',\n ],\n }),\n });\n\n const result = (await response.json()) as { error?: unknown; result?: string };\n if (result.error || !result.result) {\n return 0;\n }\n\n const balance = BigInt(result.result);\n const decimals = accept.extra?.decimals ?? 6;\n return Number(balance) / Math.pow(10, decimals);\n } catch {\n return 0;\n }\n }\n\n private encodeBalanceOf(address: string): string {\n // Function selector for balanceOf(address)\n const selector = '0x70a08231';\n // Pad address to 32 bytes\n const paddedAddress = address.slice(2).toLowerCase().padStart(64, '0');\n return selector + paddedAddress;\n }\n\n async buildTransaction(\n accept: PaymentAccept,\n wallet: unknown,\n _rpcUrl?: string\n ): Promise<SignedTransaction> {\n if (!isEvmWallet(wallet)) {\n throw new Error('Invalid EVM wallet');\n }\n if (!wallet.address) {\n throw new Error('Wallet not connected');\n }\n\n const { payTo, asset, amount, extra } = accept;\n\n this.log('Building EVM transaction:', {\n from: wallet.address,\n to: payTo,\n amount,\n asset,\n network: accept.network,\n });\n\n // For x402 v2 EVM payments, we use EIP-712 typed data signing\n // The facilitator will execute the transfer on behalf of the user\n\n const chainId = this.getChainId(accept.network);\n\n // Build the EIP-712 typed data\n // This matches what Dexter's facilitator expects\n const domain = {\n name: extra?.name ?? 'USD Coin',\n version: extra?.version ?? '2',\n chainId: BigInt(chainId),\n verifyingContract: asset as `0x${string}`,\n };\n\n const types = {\n TransferWithAuthorization: [\n { name: 'from', type: 'address' },\n { name: 'to', type: 'address' },\n { name: 'value', type: 'uint256' },\n { name: 'validAfter', type: 'uint256' },\n { name: 'validBefore', type: 'uint256' },\n { name: 'nonce', type: 'bytes32' },\n ],\n };\n\n // Generate a random nonce (32 bytes hex)\n const nonce = '0x' + [...Array(32)]\n .map(() => Math.floor(Math.random() * 256).toString(16).padStart(2, '0'))\n .join('') as `0x${string}`;\n\n const now = Math.floor(Date.now() / 1000);\n \n // Authorization object - values as strings for JSON, BigInts for signing\n const authorization = {\n from: wallet.address,\n to: payTo,\n value: amount, // string\n validAfter: String(now - 600), // 10 minutes before (matching upstream)\n validBefore: String(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n // Message for signing uses BigInt values\n const message = {\n from: wallet.address,\n to: payTo,\n value: BigInt(amount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + (accept.maxTimeoutSeconds || 60)),\n nonce,\n };\n\n if (!wallet.signTypedData) {\n throw new Error('Wallet does not support signTypedData (EIP-712)');\n }\n\n const signature = await wallet.signTypedData({\n domain: domain as Record<string, unknown>,\n types: types as Record<string, unknown[]>,\n primaryType: 'TransferWithAuthorization',\n message: message as Record<string, unknown>,\n });\n\n this.log('EIP-712 signature obtained');\n\n // Payload structure matches upstream @x402/evm exactly\n const payload = {\n authorization,\n signature,\n };\n\n return {\n serialized: JSON.stringify(payload),\n signature,\n };\n }\n}\n\n/**\n * Create an EVM adapter instance\n */\nexport function createEvmAdapter(config?: AdapterConfig): EvmAdapter {\n return new EvmAdapter(config);\n}\n\n","/**\n * x402 v2 SDK — Shared Types\n *\n * Chain-agnostic types for x402 v2 payments.\n * Works with Solana, Base, and any future x402-compatible networks.\n */\n\n// ============================================================================\n// Network Constants\n// ============================================================================\n\n/** CAIP-2 network identifier for Solana mainnet */\nexport const SOLANA_MAINNET_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n/** CAIP-2 network identifier for Base mainnet */\nexport const BASE_MAINNET_NETWORK = 'eip155:8453';\n\n/** Alias for Solana mainnet */\nexport const SOLANA_MAINNET = SOLANA_MAINNET_NETWORK;\n\n/** Alias for Base mainnet */\nexport const BASE_MAINNET = BASE_MAINNET_NETWORK;\n\n// ============================================================================\n// Asset Constants\n// ============================================================================\n\n/** USDC mint on Solana mainnet */\nexport const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n\n/** USDC address on Base mainnet */\nexport const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\n\n// ============================================================================\n// Facilitator Constants\n// ============================================================================\n\n/** Dexter's public x402 v2 facilitator URL */\nexport const DEXTER_FACILITATOR_URL = 'https://x402.dexter.cash';\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/**\n * Asset configuration for payments\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n /** Optional: Human-readable symbol */\n symbol?: string;\n}\n\n/**\n * Resource info included in payment requirements\n */\nexport interface ResourceInfo {\n /** Resource URL */\n url: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n}\n\n/**\n * Extra fields in payment requirements\n * Chain-specific fields may vary\n */\nexport interface AcceptsExtra {\n /** Facilitator address that pays tx fees (required) */\n feePayer: string;\n /** Token decimals (required) */\n decimals: number;\n /** EIP-712: Token name (EVM only) */\n name?: string;\n /** EIP-712: Token version (EVM only) */\n version?: string;\n /** Additional chain-specific fields */\n [key: string]: unknown;\n}\n\n/**\n * A single payment option in the accepts array\n */\nexport interface PaymentAccept {\n /** Payment scheme (always 'exact' for x402 v2) */\n scheme: 'exact';\n /** CAIP-2 network identifier */\n network: string;\n /** Payment amount in atomic units (as string to avoid precision loss) */\n amount: string;\n /** Token address */\n asset: string;\n /** Seller's address to receive payment */\n payTo: string;\n /** Maximum seconds until payment expires */\n maxTimeoutSeconds: number;\n /** Chain-specific extra data */\n extra: AcceptsExtra;\n}\n\n/**\n * Full PaymentRequired structure (sent in PAYMENT-REQUIRED header)\n */\nexport interface PaymentRequired {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** Available payment options */\n accepts: PaymentAccept[];\n /** Optional error message */\n error?: string;\n}\n\n/**\n * PaymentSignature structure (sent in PAYMENT-SIGNATURE header)\n */\nexport interface PaymentSignature {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** The payment option that was accepted */\n accepted: PaymentAccept;\n /** The signed payment */\n payload: {\n /** Signed transaction (base64 for Solana, JSON for EVM) */\n transaction: string;\n };\n}\n\n// ============================================================================\n// Facilitator Response Types\n// ============================================================================\n\n/**\n * Response from /verify endpoint\n */\nexport interface VerifyResponse {\n /** Whether the payment is valid */\n isValid: boolean;\n /** Reason for invalidity (if invalid) */\n invalidReason?: string;\n /** Payer address */\n payer?: string;\n}\n\n/**\n * Response from /settle endpoint\n */\nexport interface SettleResponse {\n /** Whether settlement succeeded */\n success: boolean;\n /** Transaction signature/hash */\n transaction?: string;\n /** Network the payment was made on */\n network: string;\n /** Error reason (if failed) */\n errorReason?: string;\n /** Error code (if failed) */\n errorCode?: string;\n /** Payer address */\n payer?: string;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * SDK error codes\n */\nexport type X402ErrorCode =\n // Client errors\n | 'missing_payment_required_header'\n | 'invalid_payment_required'\n | 'unsupported_network'\n | 'no_matching_payment_option'\n | 'no_solana_accept' // Legacy, kept for compatibility\n | 'missing_fee_payer'\n | 'missing_decimals'\n | 'amount_exceeds_max'\n | 'insufficient_balance'\n | 'wallet_missing_sign_transaction'\n | 'wallet_not_connected'\n | 'transaction_build_failed'\n | 'payment_rejected'\n // Server errors\n | 'invalid_payment_signature'\n | 'facilitator_verify_failed'\n | 'facilitator_settle_failed'\n | 'facilitator_request_failed'\n | 'no_matching_requirement';\n\n/**\n * Custom error class for x402 operations\n */\nexport class X402Error extends Error {\n /** Error code for programmatic handling */\n code: X402ErrorCode;\n /** Additional error details */\n details?: unknown;\n\n constructor(code: X402ErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, X402Error.prototype);\n }\n}\n","/**\n * Chain Adapters\n *\n * x402 v2 is designed to be chain-agnostic. Each adapter handles\n * the specifics of transaction building and signing for its chain.\n *\n * @example\n * ```typescript\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const adapters = [\n * createSolanaAdapter(),\n * createEvmAdapter(),\n * ];\n *\n * // Find adapter for a network\n * const adapter = adapters.find(a => a.canHandle('eip155:8453'));\n * ```\n */\n\n// Types\nexport type {\n ChainAdapter,\n AdapterConfig,\n SignedTransaction,\n GenericWallet,\n WalletSet,\n BalanceInfo,\n} from './types';\n\n// Solana\nexport {\n SolanaAdapter,\n createSolanaAdapter,\n isSolanaWallet,\n SOLANA_MAINNET,\n SOLANA_DEVNET,\n SOLANA_TESTNET,\n} from './solana';\nexport type { SolanaWallet } from './solana';\n\n// EVM\nexport {\n EvmAdapter,\n createEvmAdapter,\n isEvmWallet,\n BASE_MAINNET,\n BASE_SEPOLIA,\n ETHEREUM_MAINNET,\n ARBITRUM_ONE,\n} from './evm';\nexport type { EvmWallet } from './evm';\n\n/**\n * Create all default adapters\n */\nexport function createDefaultAdapters(verbose = false) {\n const { createSolanaAdapter } = require('./solana');\n const { createEvmAdapter } = require('./evm');\n return [\n createSolanaAdapter({ verbose }),\n createEvmAdapter({ verbose }),\n ];\n}\n\n/**\n * Find adapter that can handle a network\n */\nexport function findAdapter(\n adapters: import('./types').ChainAdapter[],\n network: string\n): import('./types').ChainAdapter | undefined {\n return adapters.find(adapter => adapter.canHandle(network));\n}\n\n","/**\n * x402 v2 Client\n *\n * Chain-agnostic client for x402 v2 payments.\n * Automatically detects 402 responses, finds a matching payment option,\n * builds the transaction with the appropriate chain adapter, and retries.\n *\n * @example\n * ```typescript\n * import { createX402Client } from '@dexterai/x402/client';\n * import { createSolanaAdapter, createEvmAdapter } from '@dexterai/x402/adapters';\n *\n * const client = createX402Client({\n * adapters: [createSolanaAdapter(), createEvmAdapter()],\n * wallets: {\n * solana: solanaWallet,\n * evm: evmWallet,\n * },\n * });\n *\n * const response = await client.fetch(url);\n * ```\n */\n\nimport type { ChainAdapter, WalletSet } from '../adapters/types';\nimport type {\n PaymentRequired,\n PaymentAccept,\n} from '../types';\nimport { X402Error } from '../types';\nimport { createSolanaAdapter, createEvmAdapter, isSolanaWallet, isEvmWallet } from '../adapters';\n\n/**\n * Client configuration\n */\nexport interface X402ClientConfig {\n /**\n * Chain adapters to use for building transactions.\n * If not provided, uses Solana and EVM adapters by default.\n */\n adapters?: ChainAdapter[];\n\n /**\n * Wallets for each chain type.\n * Can also pass a single wallet for backwards compatibility.\n */\n wallets?: WalletSet;\n\n /**\n * Legacy: Single wallet (Solana).\n * Use `wallets` for multi-chain support.\n */\n wallet?: unknown;\n\n /**\n * Preferred network to use when multiple options are available.\n * CAIP-2 format (e.g., 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'eip155:8453')\n */\n preferredNetwork?: string;\n\n /**\n * Custom RPC URLs by network\n */\n rpcUrls?: Record<string, string>;\n\n /**\n * Maximum payment amount allowed (in atomic units).\n * Rejects payments exceeding this amount.\n */\n maxAmountAtomic?: string;\n\n /**\n * Custom fetch implementation\n */\n fetch?: typeof globalThis.fetch;\n\n /**\n * Enable verbose logging\n */\n verbose?: boolean;\n}\n\n/**\n * x402 Client interface\n */\nexport interface X402Client {\n /**\n * Fetch with automatic x402 payment handling.\n * If the server returns 402, handles payment automatically and retries.\n */\n fetch(input: string | URL | Request, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Result of finding a payment option\n */\ninterface MatchedPayment {\n accept: PaymentAccept;\n adapter: ChainAdapter;\n wallet: unknown;\n}\n\n/**\n * Create an x402 v2 client\n */\nexport function createX402Client(config: X402ClientConfig): X402Client {\n const {\n adapters = [createSolanaAdapter({ verbose: config.verbose }), createEvmAdapter({ verbose: config.verbose })],\n wallets: walletSet,\n wallet: legacyWallet,\n preferredNetwork,\n rpcUrls = {},\n maxAmountAtomic,\n fetch: customFetch = globalThis.fetch,\n verbose = false,\n } = config;\n\n const log = verbose\n ? console.log.bind(console, '[x402]')\n : () => {};\n\n // Build wallet set from legacy format if needed\n const wallets: WalletSet = walletSet || {};\n if (legacyWallet && !wallets.solana && isSolanaWallet(legacyWallet)) {\n wallets.solana = legacyWallet;\n }\n if (legacyWallet && !wallets.evm && isEvmWallet(legacyWallet)) {\n wallets.evm = legacyWallet;\n }\n\n /**\n * Find a payment option we can handle\n * Prioritizes:\n * 1. Preferred network (if specified)\n * 2. Networks where we have a connected wallet\n * 3. First available option\n */\n function findPaymentOption(accepts: PaymentAccept[]): MatchedPayment | null {\n // Filter to options we can handle\n const candidates: MatchedPayment[] = [];\n\n for (const accept of accepts) {\n const adapter = adapters.find(a => a.canHandle(accept.network));\n if (!adapter) continue;\n\n // Find the right wallet for this adapter\n let wallet: unknown;\n if (adapter.name === 'Solana') {\n wallet = wallets.solana;\n } else if (adapter.name === 'EVM') {\n wallet = wallets.evm;\n }\n\n if (wallet && adapter.isConnected(wallet)) {\n candidates.push({ accept, adapter, wallet });\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n // Prefer the specified network\n if (preferredNetwork) {\n const preferred = candidates.find(c => c.accept.network === preferredNetwork);\n if (preferred) return preferred;\n }\n\n // Return first available\n return candidates[0];\n }\n\n /**\n * Get RPC URL for a network\n */\n function getRpcUrl(network: string, adapter: ChainAdapter): string {\n return rpcUrls[network] || adapter.getDefaultRpcUrl(network);\n }\n\n /**\n * Main fetch function with x402 payment handling\n */\n async function x402Fetch(\n input: string | URL | Request,\n init?: RequestInit\n ): Promise<Response> {\n log('Making request:', input);\n\n // Make initial request\n const response = await customFetch(input, init);\n\n // If not 402, return as-is\n if (response.status !== 402) {\n return response;\n }\n\n log('Received 402 Payment Required');\n\n // Parse PAYMENT-REQUIRED header\n const paymentRequiredHeader = response.headers.get('PAYMENT-REQUIRED');\n if (!paymentRequiredHeader) {\n throw new X402Error(\n 'missing_payment_required_header',\n 'Server returned 402 but no PAYMENT-REQUIRED header'\n );\n }\n\n let requirements: PaymentRequired;\n try {\n const decoded = atob(paymentRequiredHeader);\n requirements = JSON.parse(decoded);\n } catch {\n throw new X402Error(\n 'invalid_payment_required',\n 'Failed to decode PAYMENT-REQUIRED header'\n );\n }\n\n log('Payment requirements:', requirements);\n\n // Capture X-Quote-Hash if present (for dynamic pricing validation)\n const quoteHash = response.headers.get('X-Quote-Hash');\n if (quoteHash) {\n log('Quote hash received:', quoteHash);\n }\n\n // Find a payment option we can use\n const match = findPaymentOption(requirements.accepts);\n if (!match) {\n const availableNetworks = requirements.accepts.map(a => a.network).join(', ');\n throw new X402Error(\n 'no_matching_payment_option',\n `No connected wallet for any available network: ${availableNetworks}`\n );\n }\n\n const { accept, adapter, wallet } = match;\n log(`Using ${adapter.name} for ${accept.network}`);\n\n // Validate fee payer (Solana only - EVM users pay their own gas)\n if (adapter.name === 'Solana' && !accept.extra?.feePayer) {\n throw new X402Error(\n 'missing_fee_payer',\n 'Solana payment option missing feePayer in extra'\n );\n }\n\n // Validate decimals\n if (typeof accept.extra?.decimals !== 'number') {\n throw new X402Error(\n 'missing_decimals',\n 'Payment option missing decimals in extra'\n );\n }\n\n // Check amount limit\n if (maxAmountAtomic && BigInt(accept.amount) > BigInt(maxAmountAtomic)) {\n throw new X402Error(\n 'amount_exceeds_max',\n `Payment amount ${accept.amount} exceeds maximum ${maxAmountAtomic}`\n );\n }\n\n // Check balance before signing\n const rpcUrl = getRpcUrl(accept.network, adapter);\n log('Checking balance...');\n const balance = await adapter.getBalance(accept, wallet, rpcUrl);\n const requiredAmount = Number(accept.amount) / Math.pow(10, accept.extra.decimals);\n \n if (balance < requiredAmount) {\n const network = adapter.name === 'EVM' ? 'Base' : 'Solana';\n throw new X402Error(\n 'insufficient_balance',\n `Insufficient USDC balance on ${network}. Have $${balance.toFixed(4)}, need $${requiredAmount.toFixed(4)}`\n );\n }\n log(`Balance OK: $${balance.toFixed(4)} >= $${requiredAmount.toFixed(4)}`);\n\n // Build and sign transaction\n log('Building transaction...');\n const signedTx = await adapter.buildTransaction(accept, wallet, rpcUrl);\n log('Transaction signed');\n\n // Build PAYMENT-SIGNATURE payload\n // Solana uses payload.transaction (base64 serialized tx)\n // EVM uses payload directly (authorization + signature object)\n let payload: Record<string, unknown>;\n if (adapter.name === 'EVM') {\n // EVM: payload is the authorization + signature object\n payload = JSON.parse(signedTx.serialized);\n } else {\n // Solana: payload.transaction is the base64 tx\n payload = { transaction: signedTx.serialized };\n }\n\n const paymentSignature = {\n x402Version: 2,\n resource: requirements.resource,\n accepted: accept,\n payload,\n };\n\n const paymentSignatureHeader = btoa(JSON.stringify(paymentSignature));\n\n // Retry request with payment\n log('Retrying request with payment...');\n const retryResponse = await customFetch(input, {\n ...init,\n headers: {\n ...(init?.headers || {}),\n 'PAYMENT-SIGNATURE': paymentSignatureHeader,\n // Forward quote hash for dynamic pricing validation\n ...(quoteHash ? { 'X-Quote-Hash': quoteHash } : {}),\n },\n });\n\n log('Retry response status:', retryResponse.status);\n\n if (retryResponse.status === 402) {\n // Try to get rejection reason from body\n let reason = 'unknown';\n try {\n const body = (await retryResponse.clone().json()) as Record<string, unknown>;\n reason = String(body.error || body.message || JSON.stringify(body));\n log('Rejection reason:', reason);\n } catch {\n // Ignore\n }\n throw new X402Error(\n 'payment_rejected',\n `Payment was rejected by the server: ${reason}`\n );\n }\n\n return retryResponse;\n }\n\n return {\n fetch: x402Fetch,\n };\n}\n\n// Re-export types for convenience\nexport type { ChainAdapter, WalletSet } from '../adapters/types';\nexport { X402Error } from '../types';\n"],"mappings":"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","names":["DEFAULT_RPC_URLS"]}