uvd-x402-sdk 2.76.0 → 2.77.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/chains/index.ts","../src/dx402.ts","../src/types/index.ts","../src/utils/base64.ts","../src/utils/x402.ts","../src/utils/token-metadata.ts","../src/utils/validation.ts","../src/client/X402Client.ts","../src/adapters/env-key.ts","../src/adapters/ows.ts","../src/facilitator.ts","../src/events.ts","../src/erc8128.ts","../src/erc7702.ts","../src/escrow-preauth.ts","../src/backend/facilitator-error.ts","../src/backend/index.ts"],"names":["nobleHexToBytes","paymentId","contentHash","ethers","DEFAULT_FACILITATOR_URL","ZERO_ADDRESS","requirements","reqOptions"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * uvd-x402-sdk - Chain Registry\n *\n * Complete configuration for all 25 supported blockchain networks.\n * EVM chains (15): Use ERC-3009 TransferWithAuthorization (includes Scroll, SKALE Base, Robinhood Chain mainnet + testnet)\n * SVM chains (2): Solana and Fogo - Use SPL tokens with partially-signed transactions\n * Stellar (1): Uses Soroban authorization entries\n * NEAR (1): Uses NEP-366 meta-transactions\n * Algorand (2): Uses ASA transfers with atomic transaction groups\n * Sui (2): Uses sponsored transactions (facilitator pays gas)\n * XRPL (2): Native XRP via pre-signed Payment transaction blobs (facilitator pays fee)\n */\n\nimport type { ChainConfig, NetworkType, TokenType, TokenConfig } from '../types';\n\n/**\n * Default facilitator URL for x402 payments\n */\nexport const DEFAULT_FACILITATOR_URL = 'https://facilitator.ultravioletadao.xyz';\n\n/**\n * All supported chains configuration\n *\n * To add a new chain:\n * 1. Add chain config below with all required fields\n * 2. Verify USDC contract supports ERC-3009 (transferWithAuthorization) for EVM chains\n * 3. Test on testnet first before enabling\n */\nexport const SUPPORTED_CHAINS: Record<string, ChainConfig> = {\n // ============================================================================\n // EVM CHAINS (15 networks)\n // ============================================================================\n\n base: {\n chainId: 8453,\n chainIdHex: '0x2105',\n name: 'base',\n displayName: 'Base',\n networkType: 'evm',\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n eurc: {\n address: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',\n decimals: 6,\n name: 'EURC',\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n avalanche: {\n chainId: 43114,\n chainIdHex: '0xa86a',\n name: 'avalanche',\n displayName: 'Avalanche C-Chain',\n networkType: 'evm',\n rpcUrl: 'https://avalanche-c-chain-rpc.publicnode.com',\n explorerUrl: 'https://snowtrace.io',\n nativeCurrency: {\n name: 'Avalanche',\n symbol: 'AVAX',\n decimals: 18,\n },\n usdc: {\n address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n eurc: {\n address: '0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD',\n decimals: 6,\n name: 'EURC',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n ethereum: {\n chainId: 1,\n chainIdHex: '0x1',\n name: 'ethereum',\n displayName: 'Ethereum',\n networkType: 'evm',\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n eurc: {\n address: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',\n decimals: 6,\n name: 'Euro Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n pyusd: {\n address: '0x6c3ea9036406852006290770BEdFcAbA0e23A0e8',\n decimals: 6,\n name: 'PayPal USD',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n polygon: {\n chainId: 137,\n chainIdHex: '0x89',\n name: 'polygon',\n displayName: 'Polygon',\n networkType: 'evm',\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n nativeCurrency: {\n name: 'Polygon',\n symbol: 'POL',\n decimals: 18,\n },\n usdc: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n arbitrum: {\n chainId: 42161,\n chainIdHex: '0xa4b1',\n name: 'arbitrum',\n displayName: 'Arbitrum One',\n networkType: 'evm',\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n usdt: {\n address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',\n decimals: 6,\n name: 'USD₮0',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n optimism: {\n chainId: 10,\n chainIdHex: '0xa',\n name: 'optimism',\n displayName: 'Optimism',\n networkType: 'evm',\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n usdt: {\n address: '0x01bff41798a0bcf287b996046ca68b395dbc1071',\n decimals: 6,\n name: 'USD₮0',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n celo: {\n chainId: 42220,\n chainIdHex: '0xa4ec',\n name: 'celo',\n displayName: 'Celo',\n networkType: 'evm',\n rpcUrl: 'https://forno.celo.org',\n explorerUrl: 'https://celoscan.io',\n nativeCurrency: {\n name: 'Celo',\n symbol: 'CELO',\n decimals: 18,\n },\n usdc: {\n address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n decimals: 6,\n name: 'USDC', // Celo uses \"USDC\" not \"USD Coin\" for EIP-712\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n decimals: 6,\n name: 'USDC', // Celo uses \"USDC\" not \"USD Coin\" for EIP-712\n version: '2',\n },\n usdt: {\n address: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e',\n decimals: 6,\n name: 'Tether USD', // Celo USDT uses \"Tether USD\" for EIP-712\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n hyperevm: {\n chainId: 999,\n chainIdHex: '0x3e7',\n name: 'hyperevm',\n displayName: 'HyperEVM',\n networkType: 'evm',\n rpcUrl: 'https://rpc.hyperliquid.xyz/evm',\n explorerUrl: 'https://hyperevmscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',\n decimals: 6,\n name: 'USDC', // HyperEVM uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',\n decimals: 6,\n name: 'USDC', // HyperEVM uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n unichain: {\n chainId: 130,\n chainIdHex: '0x82',\n name: 'unichain',\n displayName: 'Unichain',\n networkType: 'evm',\n rpcUrl: 'https://unichain-rpc.publicnode.com',\n explorerUrl: 'https://uniscan.xyz',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x078d782b760474a361dda0af3839290b0ef57ad6',\n decimals: 6,\n name: 'USDC', // Unichain uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x078d782b760474a361dda0af3839290b0ef57ad6',\n decimals: 6,\n name: 'USDC', // Unichain uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n monad: {\n chainId: 143,\n chainIdHex: '0x8f',\n name: 'monad',\n displayName: 'Monad',\n networkType: 'evm',\n rpcUrl: 'https://rpc.monad.xyz',\n explorerUrl: 'https://monad.socialscan.io',\n nativeCurrency: {\n name: 'Monad',\n symbol: 'MON',\n decimals: 18,\n },\n usdc: {\n address: '0x754704bc059f8c67012fed69bc8a327a5aafb603',\n decimals: 6,\n name: 'USDC', // Monad uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x754704bc059f8c67012fed69bc8a327a5aafb603',\n decimals: 6,\n name: 'USDC', // Monad uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n usdt: {\n address: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',\n decimals: 6,\n name: 'USD\\u20AE0', // USD₮0 (USDT0 omnichain via LayerZero)\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n bsc: {\n chainId: 56,\n chainIdHex: '0x38',\n name: 'bsc',\n displayName: 'BNB Smart Chain',\n networkType: 'evm',\n rpcUrl: 'https://binance.llamarpc.com',\n explorerUrl: 'https://bscscan.com',\n nativeCurrency: {\n name: 'Binance Coin',\n symbol: 'BNB',\n decimals: 18,\n },\n usdc: {\n // Binance-Peg USDC — 18 decimals, NOT the 6 every other chain uses.\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n name: 'USD Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n // Disabled on purpose: Binance-Peg USDC does not implement ERC-3009\n // `transferWithAuthorization`, so the exact scheme cannot settle it. The\n // entry exists so the 18-decimal figure is on record — assuming the usual\n // 6 here mis-prices a payment by 12 orders of magnitude.\n enabled: false,\n },\n },\n\n scroll: {\n chainId: 534352,\n chainIdHex: '0x82750',\n name: 'scroll',\n displayName: 'Scroll',\n networkType: 'evm',\n rpcUrl: 'https://rpc.scroll.io',\n explorerUrl: 'https://scrollscan.com',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'skale-base': {\n chainId: 1187947933,\n chainIdHex: '0x46cea59d',\n name: 'skale-base',\n displayName: 'SKALE Base',\n networkType: 'evm',\n rpcUrl: 'https://skale-base.skalenodes.com/v1/base',\n explorerUrl: 'https://skale-base-explorer.skalenodes.com',\n nativeCurrency: {\n name: 'CREDIT',\n symbol: 'CREDIT',\n decimals: 18,\n },\n usdc: {\n address: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'skale-base-sepolia': {\n chainId: 324705682,\n chainIdHex: '0x135a9d92',\n name: 'skale-base-sepolia',\n displayName: 'SKALE Base Sepolia',\n networkType: 'evm',\n rpcUrl: 'https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha',\n explorerUrl: 'https://base-sepolia-testnet-explorer.skalenodes.com',\n nativeCurrency: {\n name: 'CREDIT',\n symbol: 'CREDIT',\n decimals: 18,\n },\n usdc: {\n address: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // Robinhood Chain (Arbitrum Orbit L2). NOTE: there is NO USDC on this chain -\n // the settlement stablecoin is Paxos USDG (Global Dollar). The `usdc` field\n // below carries USDG for interface compatibility (same pattern as XRPL's native\n // asset), and `tokens.usdg` is the canonical entry.\n // CRITICAL: USDG's on-chain version() getter REVERTS, so the EIP-712 domain\n // { name: 'Global Dollar', version: '1' } can NEVER be resolved on-chain and\n // MUST come from this config (mirrored into PaymentRequirements.extra by callers).\n robinhood: {\n chainId: 4663,\n chainIdHex: '0x1237',\n name: 'robinhood',\n displayName: 'Robinhood Chain',\n networkType: 'evm',\n rpcUrl: 'https://rpc.mainnet.chain.robinhood.com',\n explorerUrl: 'https://robinhoodchain.blockscout.com',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168', // Paxos USDG (no USDC on this chain)\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n tokens: {\n usdg: {\n address: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168',\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'robinhood-testnet': {\n chainId: 46630,\n chainIdHex: '0xb626',\n name: 'robinhood-testnet',\n displayName: 'Robinhood Chain Testnet',\n networkType: 'evm',\n rpcUrl: 'https://rpc.testnet.chain.robinhood.com',\n explorerUrl: 'https://explorer.testnet.chain.robinhood.com',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x7E955252E15c84f5768B83c41a71F9eba181802F', // Paxos USDG testnet (no USDC on this chain)\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n tokens: {\n usdg: {\n address: '0x7E955252E15c84f5768B83c41a71F9eba181802F',\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // SVM CHAINS (2 networks) - Solana Virtual Machine\n // ============================================================================\n\n solana: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'solana',\n displayName: 'Solana',\n networkType: 'svm',\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://solscan.io',\n nativeCurrency: {\n name: 'Solana',\n symbol: 'SOL',\n decimals: 9,\n },\n usdc: {\n address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC SPL token mint\n decimals: 6,\n name: 'USD Coin',\n version: '1',\n },\n tokens: {\n usdc: {\n address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC SPL token mint\n decimals: 6,\n name: 'USD Coin',\n version: '1',\n },\n ausd: {\n address: 'AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9', // AUSD Token2022 mint\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n fogo: {\n chainId: 0, // Non-EVM (SVM)\n chainIdHex: '0x0',\n name: 'fogo',\n displayName: 'Fogo',\n networkType: 'svm',\n rpcUrl: 'https://rpc.fogo.nightly.app/',\n explorerUrl: 'https://explorer.fogo.nightly.app',\n nativeCurrency: {\n name: 'Fogo',\n symbol: 'FOGO',\n decimals: 9,\n },\n usdc: {\n address: 'uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG', // Fogo USDC mint\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // STELLAR (1 network)\n // ============================================================================\n\n stellar: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'stellar',\n displayName: 'Stellar',\n networkType: 'stellar',\n rpcUrl: 'https://horizon.stellar.org',\n explorerUrl: 'https://stellar.expert/explorer/public',\n nativeCurrency: {\n name: 'Lumens',\n symbol: 'XLM',\n decimals: 7, // Stellar uses 7 decimals (stroops)\n },\n usdc: {\n address: 'CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75', // Soroban Asset Contract\n decimals: 7, // Stellar USDC uses 7 decimals\n name: 'USDC',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // NEAR (1 network) - Uses NEP-366 meta-transactions\n // ============================================================================\n\n near: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'near',\n displayName: 'NEAR Protocol',\n networkType: 'near',\n rpcUrl: 'https://rpc.mainnet.near.org',\n explorerUrl: 'https://nearblocks.io',\n nativeCurrency: {\n name: 'NEAR',\n symbol: 'NEAR',\n decimals: 24, // NEAR uses 24 decimals (yoctoNEAR)\n },\n usdc: {\n address: '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1', // Native Circle USDC\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true, // NEP-366 meta-transactions supported\n },\n },\n\n // ============================================================================\n // ALGORAND (2 networks) - Uses ASA transfers with atomic transaction groups\n // ============================================================================\n\n algorand: {\n chainId: 0, // Non-EVM (Algorand uses genesis hash for network identification)\n chainIdHex: '0x0',\n name: 'algorand',\n displayName: 'Algorand',\n networkType: 'algorand',\n rpcUrl: 'https://mainnet-api.algonode.cloud',\n explorerUrl: 'https://allo.info',\n nativeCurrency: {\n name: 'Algo',\n symbol: 'ALGO',\n decimals: 6, // Algorand uses 6 decimals (microAlgos)\n },\n usdc: {\n address: '31566704', // USDC ASA ID on Algorand mainnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '31566704', // USDC ASA ID on Algorand mainnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'algorand-testnet': {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'algorand-testnet',\n displayName: 'Algorand Testnet',\n networkType: 'algorand',\n rpcUrl: 'https://testnet-api.algonode.cloud',\n explorerUrl: 'https://testnet.allo.info',\n nativeCurrency: {\n name: 'Algo',\n symbol: 'ALGO',\n decimals: 6,\n },\n usdc: {\n address: '10458941', // USDC ASA ID on Algorand testnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '10458941', // USDC ASA ID on Algorand testnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // SUI (2 networks) - Uses sponsored transactions (facilitator pays gas)\n // ============================================================================\n\n sui: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'sui',\n displayName: 'Sui',\n networkType: 'sui',\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n nativeCurrency: {\n name: 'Sui',\n symbol: 'SUI',\n decimals: 9,\n },\n usdc: {\n // USDC coin type on Sui mainnet\n address: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n ausd: {\n // AUSD (Agora USD) coin type on Sui mainnet\n address: '0x2053d08c1e2bd02791056171aab0fd12bd7cd7efad2ab8f6b9c8902f14df2ff2::ausd::AUSD',\n decimals: 6,\n name: 'AUSD',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'sui-testnet': {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'sui-testnet',\n displayName: 'Sui Testnet',\n networkType: 'sui',\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n nativeCurrency: {\n name: 'Sui',\n symbol: 'SUI',\n decimals: 9,\n },\n usdc: {\n // USDC coin type on Sui testnet\n address: '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // XRPL (2 networks) - XRP Ledger, native XRP via pre-signed Payment blobs\n // ============================================================================\n\n 'xrpl-mainnet': {\n chainId: 0, // Non-EVM (XRPL uses network id strings, no numeric chain ID)\n chainIdHex: '0x0',\n name: 'xrpl-mainnet',\n displayName: 'XRP Ledger',\n networkType: 'xrpl',\n rpcUrl: 'https://xrplcluster.com',\n explorerUrl: 'https://livenet.xrpl.org',\n nativeCurrency: {\n name: 'XRP',\n symbol: 'XRP',\n decimals: 6, // XRPL uses 6 decimals (drops); 1 XRP = 1,000,000 drops\n },\n // XRPL settles in native XRP - there is no USDC/token contract.\n // The `usdc` field describes the native asset for interface compatibility.\n usdc: {\n address: 'XRP', // Native asset - no token contract\n decimals: 6,\n name: 'XRP',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'xrpl-testnet': {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'xrpl-testnet',\n displayName: 'XRP Ledger Testnet',\n networkType: 'xrpl',\n rpcUrl: 'https://s.altnet.rippletest.net:51234',\n explorerUrl: 'https://testnet.xrpl.org',\n nativeCurrency: {\n name: 'XRP',\n symbol: 'XRP',\n decimals: 6,\n },\n // XRPL settles in native XRP - there is no USDC/token contract.\n usdc: {\n address: 'XRP', // Native asset - no token contract\n decimals: 6,\n name: 'XRP',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n};\n\n/**\n * Default chain for new users\n */\nexport const DEFAULT_CHAIN = 'base';\n\n/**\n * Get chain config by chain ID\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(SUPPORTED_CHAINS).find(chain => chain.chainId === chainId);\n}\n\n/**\n * Get chain config by name (case-insensitive)\n */\nexport function getChainByName(name: string): ChainConfig | undefined {\n return SUPPORTED_CHAINS[name.toLowerCase()];\n}\n\n/**\n * Check if a chain is supported\n */\nexport function isChainSupported(chainIdOrName: number | string): boolean {\n if (typeof chainIdOrName === 'number') {\n return Object.values(SUPPORTED_CHAINS).some(chain => chain.chainId === chainIdOrName);\n }\n return chainIdOrName.toLowerCase() in SUPPORTED_CHAINS;\n}\n\n/**\n * Get list of enabled chains\n */\nexport function getEnabledChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(chain => chain.x402.enabled);\n}\n\n/**\n * Get list of chains by network type\n */\nexport function getChainsByNetworkType(networkType: NetworkType): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === networkType && chain.x402.enabled\n );\n}\n\n/**\n * Get all EVM chain IDs (for wallet_switchEthereumChain)\n */\nexport function getEVMChainIds(): number[] {\n return getChainsByNetworkType('evm').map(chain => chain.chainId);\n}\n\n/**\n * Get list of SVM chains (Solana, Fogo)\n */\nexport function getSVMChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'svm' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is SVM-based (Solana Virtual Machine)\n */\nexport function isSVMChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'svm';\n}\n\n/**\n * Get list of Sui chains\n */\nexport function getSuiChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'sui' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is Sui-based\n */\nexport function isSuiChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'sui';\n}\n\n/**\n * Get network type from chain name\n */\nexport function getNetworkType(chainName: string): NetworkType | undefined {\n const chain = getChainByName(chainName);\n return chain?.networkType;\n}\n\n/**\n * Format transaction URL for block explorer\n */\nexport function getExplorerTxUrl(chainName: string, txHash: string): string | null {\n const chain = getChainByName(chainName);\n if (!chain) return null;\n\n switch (chain.networkType) {\n case 'evm':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'svm':\n case 'solana': // @deprecated\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'stellar':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'near':\n return `${chain.explorerUrl}/txns/${txHash}`;\n case 'algorand':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'sui':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'xrpl':\n return `${chain.explorerUrl}/transactions/${txHash}`;\n default:\n return null;\n }\n}\n\n/**\n * Format address URL for block explorer\n */\nexport function getExplorerAddressUrl(chainName: string, address: string): string | null {\n const chain = getChainByName(chainName);\n if (!chain) return null;\n\n switch (chain.networkType) {\n case 'evm':\n return `${chain.explorerUrl}/address/${address}`;\n case 'svm':\n case 'solana': // @deprecated\n return `${chain.explorerUrl}/account/${address}`;\n case 'stellar':\n return `${chain.explorerUrl}/account/${address}`;\n case 'near':\n return `${chain.explorerUrl}/address/${address}`;\n case 'algorand':\n return `${chain.explorerUrl}/account/${address}`;\n case 'sui':\n return `${chain.explorerUrl}/account/${address}`;\n case 'xrpl':\n return `${chain.explorerUrl}/accounts/${address}`;\n default:\n return null;\n }\n}\n\n/**\n * Get list of Algorand chains\n */\nexport function getAlgorandChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'algorand' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is Algorand-based\n */\nexport function isAlgorandChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'algorand';\n}\n\n/**\n * Get list of XRPL chains (XRP Ledger mainnet/testnet)\n */\nexport function getXRPLChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'xrpl' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is XRPL-based (XRP Ledger)\n */\nexport function isXRPLChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'xrpl';\n}\n\n// ============================================================================\n// MULTI-TOKEN SUPPORT FUNCTIONS\n// ============================================================================\n\n/**\n * Get token configuration for a specific chain and token type\n * Falls back to USDC config if token not found (for backward compatibility)\n *\n * @param chainName - Chain name (e.g., 'ethereum', 'base')\n * @param tokenType - Token type (e.g., 'usdc', 'eurc', 'pyusd')\n * @returns Token configuration or undefined if chain not found\n */\nexport function getTokenConfig(\n chainName: string,\n tokenType: TokenType = 'usdc'\n): TokenConfig | undefined {\n const chain = getChainByName(chainName);\n if (!chain) return undefined;\n\n // Try to get from tokens map first (new multi-token support)\n if (chain.tokens && chain.tokens[tokenType]) {\n return chain.tokens[tokenType];\n }\n\n // Fall back to usdc config for backward compatibility\n if (tokenType === 'usdc') {\n return chain.usdc;\n }\n\n return undefined;\n}\n\n/**\n * Find which token of a chain a contract address belongs to.\n *\n * The signed payload carries the token *address*, but a server that accepts\n * several stablecoins on the same chain needs the symbol, the decimals and the\n * EIP-712 domain to rebuild the payment requirements. This resolves the address\n * back to the registry entry so that metadata can travel with the payment.\n *\n * @param chainName - Chain name (e.g., 'optimism')\n * @param address - Token contract address (case-insensitive on EVM)\n * @returns The token type and its config, or undefined if the address is not in the registry\n */\nexport function getTokenByAddress(\n chainName: string,\n address: string\n): { tokenType: TokenType; config: TokenConfig } | undefined {\n const chain = getChainByName(chainName);\n if (!chain || !address) return undefined;\n\n const wanted = address.startsWith('0x') ? address.toLowerCase() : address;\n const matches = (candidate: string): boolean =>\n (candidate.startsWith('0x') ? candidate.toLowerCase() : candidate) === wanted;\n\n if (chain.tokens) {\n for (const [tokenType, config] of Object.entries(chain.tokens)) {\n if (config && matches(config.address)) {\n return { tokenType: tokenType as TokenType, config };\n }\n }\n }\n\n if (chain.usdc && matches(chain.usdc.address)) {\n return { tokenType: 'usdc', config: chain.usdc };\n }\n\n return undefined;\n}\n\n/**\n * Get list of supported tokens for a chain\n *\n * @param chainName - Chain name (e.g., 'ethereum', 'base')\n * @returns Array of supported token types, or empty array if chain not found\n */\nexport function getSupportedTokens(chainName: string): TokenType[] {\n const chain = getChainByName(chainName);\n if (!chain) return [];\n\n // If tokens map exists, return its keys\n if (chain.tokens) {\n return Object.keys(chain.tokens) as TokenType[];\n }\n\n // Default to just USDC for chains without explicit tokens map\n return ['usdc'];\n}\n\n/**\n * Check if a token is supported on a specific chain\n *\n * @param chainName - Chain name (e.g., 'ethereum', 'base')\n * @param tokenType - Token type (e.g., 'usdc', 'eurc', 'pyusd')\n * @returns true if token is supported on the chain\n */\nexport function isTokenSupported(chainName: string, tokenType: TokenType): boolean {\n const chain = getChainByName(chainName);\n if (!chain) return false;\n\n // Check tokens map\n if (chain.tokens && chain.tokens[tokenType]) {\n return true;\n }\n\n // USDC is always supported (backward compatibility)\n if (tokenType === 'usdc') {\n return true;\n }\n\n return false;\n}\n\n/**\n * Get all chains that support a specific token\n *\n * @param tokenType - Token type (e.g., 'usdc', 'eurc', 'pyusd')\n * @returns Array of chain configs that support the token\n */\nexport function getChainsByToken(tokenType: TokenType): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(chain => {\n if (!chain.x402.enabled) return false;\n if (chain.tokens && chain.tokens[tokenType]) return true;\n if (tokenType === 'usdc') return true; // USDC is universal\n return false;\n });\n}\n","/**\n * DX402 `durable-evidence`: recover a paid response after the fact.\n *\n * x402 settles payment on-chain permanently but delivers the purchased resource\n * **exactly once**, in the body of a `200 OK`, and keeps nothing. A buyer who did\n * not capture it at that instant cannot recover it, and neither party can later\n * prove *what* was delivered — only *that* payment happened.\n *\n * DX402 closes that gap. The seller seals a copy of the response to the payer's\n * own public key — recovered from the payment signature itself — and anchors it.\n * The buyer gets an `X-Durable-Evidence` header pointing at it.\n *\n * **Paying is publishing your encryption key.** No registration, no key\n * exchange, no extra round trip.\n *\n * ```ts\n * const evidence = evidenceFromHeaders(response.headers);\n * const body = await recoverEvidence(evidence, myPrivateKey);\n * ```\n *\n * Specification: `docs/plans/dx402/02-SPEC-v0.1.md` in x402-rs.\n */\n\nimport { gcm } from '@noble/ciphers/aes';\nimport { ed25519, x25519 } from '@noble/curves/ed25519';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { hkdf } from '@noble/hashes/hkdf';\nimport {\n hexToBytes as nobleHexToBytes,\n bytesToHex,\n} from '@noble/hashes/utils';\nimport { keccak_256 } from '@noble/hashes/sha3';\n\nimport { getChainById, getChainByName } from './chains';\nimport { sha256, sha512 } from '@noble/hashes/sha2';\n\nexport const EVIDENCE_HEADER = 'X-Durable-Evidence';\n\nconst MAGIC = new Uint8Array([0x44, 0x58, 0x34, 0x30, 0x32]); // \"DX402\"\n/** One recipient (the payer). Still emitted for that case, so deployed readers keep working. */\nconst FORMAT_V1 = 1;\n/** Several recipients. A v2 blob positively signals that somebody besides the payer can open it. */\nconst FORMAT_V2 = 2;\n\n/** Why a party holds a key to this evidence. */\nexport type RecipientRole = 'payer' | 'seller' | 'auditor';\nconst ROLE_NAMES: RecipientRole[] = ['payer', 'seller', 'auditor'];\nconst NONCE_LEN = 12;\nconst CEK_LEN = 32;\nconst HKDF_INFO = new TextEncoder().encode('DX402-v1-wrap');\n\nexport class DX402Error extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'DX402Error';\n }\n}\n\n/**\n * No evidence was anchored for this payment.\n *\n * A normal outcome, not a fault: the body may have exceeded the seller's size\n * cap, the store may have been unreachable, or the payer may be a\n * smart-contract wallet with no recoverable key.\n */\nexport class EvidenceSkipped extends DX402Error {\n constructor(public readonly reason: string) {\n super(`no durable evidence was anchored: ${reason}`);\n this.name = 'EvidenceSkipped';\n }\n}\n\n/**\n * The anchored bytes are not the bytes that were delivered.\n *\n * This is the interesting failure: the seller anchored something other than\n * what it served, which is precisely the fraud `contentHash` exists to expose.\n * Treat it as evidence of misbehaviour, not a transport glitch.\n */\nexport class ContentHashMismatch extends DX402Error {\n constructor(\n public readonly anchored: string,\n public readonly actual: string,\n ) {\n super(`content hash mismatch: anchored ${anchored}, decrypted ${actual}`);\n this.name = 'ContentHashMismatch';\n }\n}\n\nexport type EvidenceMode = 'direct' | 'escrowed';\n\nexport interface AnchoredEvidence {\n v: number;\n paymentId: string;\n pointer: string;\n backend: string;\n contentHash: string;\n cipher: string;\n keyAlg: 'ECIES-secp256k1' | 'ECIES-X25519';\n mode: EvidenceMode;\n retention: string;\n receipt?: string;\n}\n\n/**\n * Whether the facilitator is cryptographically unable to read this payload.\n *\n * `direct` and `escrowed` make materially different claims about who can open\n * the payload, so a caller that cares about confidentiality must check rather\n * than assume.\n */\nexport function isEndToEnd(evidence: AnchoredEvidence): boolean {\n return evidence.mode === 'direct';\n}\n\nfunction b64urlDecode(value: string): Uint8Array {\n const normalized = value.trim().replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);\n return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));\n}\n\n/**\n * Hex decode, strictly.\n *\n * The hand-rolled loop this replaces used `parseInt`, which returns NaN for\n * non-hex input — and a Uint8Array stores NaN as 0. So `'zz'.repeat(32)`\n * decoded to 32 zero bytes and `parseInt('4z', 16)` to 4: malformed input\n * became a plausible-looking key instead of an error. This gates real key\n * material (the payer private key in `recoverEvidence`, the 65-byte signature\n * in `payerKeyFromEvmSignature`, the payee address in `anchorDigest`), and the\n * symptom was a misleading 'wrong key, or the blob belongs to another payment'\n * one layer later. Same failure class as the base58 `rjust(32)` bug in the\n * Python SDK. Python (`bytes.fromhex`) and Rust (`hex::decode`) already reject;\n * TypeScript was the permissive outlier.\n */\nfunction hexToBytes(hex: string): Uint8Array {\n const clean = hex.startsWith('0x') ? hex.slice(2) : hex;\n try {\n return nobleHexToBytes(clean);\n } catch (e) {\n throw new DX402Error(`invalid hex: ${(e as Error).message}`);\n }\n}\n\n/** keccak256 of a body, `0x`-prefixed — matching the facilitator's `contentHash`. */\nexport function contentHash(body: Uint8Array): string {\n return '0x' + bytesToHex(keccak_256(body));\n}\n\n/**\n * Derive the canonical payment identifier: `keccak256(caip2Network || txHash)`.\n *\n * This value is the AEAD associated data binding a ciphertext to its payment.\n * Buyer and seller must derive it identically or decryption fails with no\n * obvious cause, which is why it lives in the SDK rather than in each caller.\n */\nexport function paymentId(caip2Network: string, txHash: string): string {\n const enc = new TextEncoder();\n const clean = txHash.startsWith('0x') ? txHash.slice(2) : txHash;\n const preimage = new Uint8Array([...enc.encode(caip2Network), ...enc.encode(clean)]);\n return '0x' + bytesToHex(keccak_256(preimage));\n}\n\n/** Parse an `X-Durable-Evidence` header value. */\nexport function parseEvidenceHeader(value: string): AnchoredEvidence {\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(new TextDecoder().decode(b64urlDecode(value)));\n } catch (err) {\n throw new DX402Error(`malformed ${EVIDENCE_HEADER} header: ${String(err)}`);\n }\n if ('skipped' in payload) {\n throw new EvidenceSkipped(String(payload.skipped));\n }\n if (!payload.paymentId || !payload.pointer || !payload.contentHash) {\n throw new DX402Error(`malformed ${EVIDENCE_HEADER} header: missing required fields`);\n }\n return payload as unknown as AnchoredEvidence;\n}\n\n/**\n * Pull the anchored evidence out of a response's headers.\n *\n * Accepts a `Headers` object or a plain record. Lookup is case-insensitive,\n * because HTTP does not care and different clients disagree about casing.\n */\nexport function evidenceFromHeaders(\n headers: Headers | Record<string, string>,\n): AnchoredEvidence {\n let raw: string | null | undefined;\n if (typeof (headers as Headers).get === 'function') {\n raw = (headers as Headers).get(EVIDENCE_HEADER);\n } else {\n const target = EVIDENCE_HEADER.toLowerCase();\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n if (key.toLowerCase() === target) {\n raw = value;\n break;\n }\n }\n }\n if (!raw) throw new DX402Error(`no ${EVIDENCE_HEADER} header on this response`);\n return parseEvidenceHeader(raw);\n}\n\n/**\n * Turn a DX402 pointer into a fetchable URL.\n *\n * `s3+https://...` is a scheme tag over an ordinary HTTPS URL; `ipfs://` and\n * `ar://` go through public gateways. Anything else passes through untouched, so\n * a caller with their own resolver is not blocked by this function.\n */\nexport function dereferencePointer(pointer: string): string {\n if (pointer.startsWith('s3+')) return pointer.slice(3);\n if (pointer.startsWith('ipfs://')) return `https://ipfs.io/ipfs/${pointer.slice(7)}`;\n if (pointer.startsWith('ar://')) return `https://arweave.net/${pointer.slice(5)}`;\n return pointer;\n}\n\ninterface Recipient {\n role: RecipientRole;\n alg: 'secp256k1' | 'x25519';\n ephemeral: Uint8Array;\n cekNonce: Uint8Array;\n wrappedCek: Uint8Array;\n}\n\ninterface SealedEnvelope {\n recipients: Recipient[];\n bodyNonce: Uint8Array;\n ciphertext: Uint8Array;\n}\n\n/**\n * Who can open this blob, without decrypting anything.\n *\n * Worth surfacing: a buyer has to be able to see that the seller — or a\n * designated auditor — also holds a key to what they bought. Finding that out\n * afterwards would destroy the privacy property.\n */\nexport function sealedRoles(raw: Uint8Array): RecipientRole[] {\n return parseSealed(raw).recipients.map((r) => r.role);\n}\n\n/**\n * Parse the sealed-blob layout.\n *\n * `MAGIC | version | alg | ephLen | eph | cekNonce | wrappedLen | wrapped |\n * bodyNonce | ciphertext`\n *\n * Every read is bounds-checked, so a truncated blob is a clear parse failure\n * rather than an out-of-range surprise later.\n */\nexport function parseSealed(raw: Uint8Array): SealedEnvelope {\n let pos = 0;\n const take = (n: number, what: string): Uint8Array => {\n if (raw.length < pos + n) throw new DX402Error(`truncated DX402 sealed blob at ${what}`);\n const chunk = raw.subarray(pos, pos + n);\n pos += n;\n return chunk;\n };\n\n const magic = take(MAGIC.length, 'magic');\n for (let i = 0; i < MAGIC.length; i++) {\n if (magic[i] !== MAGIC[i]) throw new DX402Error('not a DX402 sealed blob');\n }\n\n const version = take(1, 'version')[0];\n let count: number;\n if (version === FORMAT_V1) count = 1;\n else if (version === FORMAT_V2) count = take(1, 'recipient count')[0];\n else throw new DX402Error(`unsupported sealed-blob version ${version}`);\n\n // An envelope nobody can open is not evidence.\n if (count === 0) throw new DX402Error('DX402 sealed blob has no recipients');\n\n const recipients: Recipient[] = [];\n for (let i = 0; i < count; i++) {\n let role: RecipientRole = 'payer';\n if (version === FORMAT_V2) {\n const b = take(1, 'role')[0];\n if (b >= ROLE_NAMES.length) throw new DX402Error(`unknown role ${b}`);\n role = ROLE_NAMES[b];\n }\n\n const algByte = take(1, 'algorithm')[0];\n if (algByte !== 1 && algByte !== 2) {\n throw new DX402Error(`unknown key algorithm ${algByte}`);\n }\n const ephLen = take(1, 'ephemeral key length')[0];\n const ephemeral = take(ephLen, 'ephemeral key');\n const cekNonce = take(NONCE_LEN, 'cek nonce');\n const lenBytes = take(2, 'wrapped key length');\n const wrappedCek = take((lenBytes[0] << 8) | lenBytes[1], 'wrapped cek');\n\n recipients.push({\n role,\n alg: algByte === 1 ? 'secp256k1' : 'x25519',\n ephemeral,\n cekNonce,\n wrappedCek,\n });\n }\n\n const bodyNonce = take(NONCE_LEN, 'body nonce');\n return { recipients, bodyNonce, ciphertext: raw.subarray(pos) };\n}\n\nfunction sharedSecret(sealed: Recipient, privateKey: Uint8Array): Uint8Array {\n if (sealed.alg === 'secp256k1') {\n // Compressed output is 33 bytes: a 0x02/0x03 tag plus the x-coordinate.\n // Only the x-coordinate is the ECDH result, matching what the Rust side\n // feeds into HKDF. Including the tag byte would derive a different key and\n // fail with no useful diagnostic.\n const full = secp256k1.getSharedSecret(privateKey, sealed.ephemeral, true);\n return full.subarray(1);\n }\n\n // ed25519 seed -> X25519 scalar: SHA-512 the seed, take the low half.\n // @noble/curves clamps internally.\n const scalar = sha512(privateKey).subarray(0, 32);\n const shared = x25519.getSharedSecret(scalar, sealed.ephemeral);\n\n // RFC 7748 section 6.1: an all-zero result means a small-order public key was\n // supplied, which would make the wrapping key reproducible by whoever\n // supplied it.\n if (shared.every((b) => b === 0)) {\n throw new DX402Error('degenerate ECDH result (small-order public key)');\n }\n return shared;\n}\n\n/**\n * Decrypt a sealed envelope with whichever recipient slot belongs to `privateKey`.\n *\n * Tries every slot: a holder does not necessarily know which one is theirs, and\n * in a multi-recipient envelope the payer is not always first. A slot that does\n * not open is skipped, not reported — \"that one was not for me\" is not an error.\n */\nexport function unseal(\n sealed: SealedEnvelope,\n privateKey: Uint8Array,\n aad: Uint8Array,\n): Uint8Array {\n for (const recipient of sealed.recipients) {\n let shared: Uint8Array;\n try {\n shared = sharedSecret(recipient, privateKey);\n } catch (err) {\n if (err instanceof DX402Error) throw err;\n continue;\n }\n\n const wrapKey = hkdf(sha256, shared, aad, HKDF_INFO, 32);\n let cek: Uint8Array;\n try {\n cek = gcm(wrapKey, recipient.cekNonce, aad).decrypt(recipient.wrappedCek);\n } catch {\n continue; // not our slot\n }\n if (cek.length !== CEK_LEN) {\n throw new DX402Error(`unwrapped CEK is ${cek.length} bytes, expected ${CEK_LEN}`);\n }\n return gcm(cek, sealed.bodyNonce, aad).decrypt(sealed.ciphertext);\n }\n\n throw new DX402Error(\n 'no recipient slot opened -- wrong key, or the blob belongs to another payment',\n );\n}\n\n/**\n * Fetch, decrypt and verify the body behind `evidence`.\n *\n * `privateKey` is the raw key of the wallet that paid: 32 bytes for both an EVM\n * secp256k1 key and an ed25519 seed. Hex accepted with or without `0x`.\n *\n * In `direct` mode this needs no permission from anyone — the ciphertext was\n * sealed to the public key of the wallet that paid, so retrieval is arithmetic\n * rather than an access-control decision that could be refused or misconfigured.\n *\n * The `contentHash` check is **not optional**: it is what catches a seller that\n * anchored something other than what it served.\n */\nexport async function recoverEvidence(\n evidence: AnchoredEvidence,\n privateKey: Uint8Array | string,\n options: { fetch?: typeof fetch } = {},\n): Promise<Uint8Array> {\n const key = typeof privateKey === 'string' ? hexToBytes(privateKey) : privateKey;\n if (key.length !== 32) {\n throw new DX402Error(`private key must be 32 bytes, got ${key.length}`);\n }\n\n const doFetch = options.fetch ?? fetch;\n const url = dereferencePointer(evidence.pointer);\n const res = await doFetch(url);\n if (!res.ok) {\n throw new DX402Error(`could not fetch sealed evidence: HTTP ${res.status}`);\n }\n const blob = new Uint8Array(await res.arrayBuffer());\n\n const sealed = parseSealed(blob);\n const aad = new TextEncoder().encode(evidence.paymentId);\n\n let plaintext: Uint8Array;\n try {\n plaintext = unseal(sealed, key, aad);\n } catch (err) {\n if (err instanceof DX402Error) throw err;\n throw new DX402Error(\n 'decryption failed -- wrong key, or the blob belongs to another payment',\n );\n }\n\n const actual = contentHash(plaintext);\n if (actual.toLowerCase() !== evidence.contentHash.toLowerCase()) {\n throw new ContentHashMismatch(evidence.contentHash, actual);\n }\n\n return plaintext;\n}\n\n// ============================================================================\n// Seller side -- sealing\n// ============================================================================\n//\n// The half above recovers evidence. This half PRODUCES it, and it belongs to\n// whoever holds the plaintext: the resource server, right after settlement.\n//\n// The facilitator is deliberately not involved. It only ever sees /verify and\n// /settle, never a response body, so sealing cannot happen there.\n\nimport { edwardsToMontgomeryPub } from '@noble/curves/ed25519';\nimport { randomBytes } from '@noble/hashes/utils';\n\n/**\n * Map an ed25519 public key to its X25519 form.\n *\n * On ed25519 chains (Solana, NEAR, Stellar, Algorand) the address **is** the\n * public key, so this is all that stands between an address and an encryption\n * target — no signature, no lookup.\n */\nexport function ed25519ToX25519(pubkey: Uint8Array): Uint8Array {\n if (pubkey.length !== 32) {\n throw new DX402Error(`ed25519 public key must be 32 bytes, got ${pubkey.length}`);\n }\n return edwardsToMontgomeryPub(pubkey);\n}\n\n/**\n * Recover an EVM payer's secp256k1 public key from their payment signature.\n *\n * `digest` is the EIP-712 digest the payer actually signed. Getting it wrong\n * does not throw: it recovers a *different, perfectly valid* key, and the body\n * would be sealed to a stranger while every log line said success. The token's\n * EIP-712 domain name varies per chain and even flips between a chain's mainnet\n * and testnet, so derive it from the same table the facilitator uses.\n *\n * Returns the SEC1-compressed key (33 bytes).\n */\nexport function payerKeyFromEvmSignature(\n signature: Uint8Array | string,\n digest: Uint8Array,\n): Uint8Array {\n const sig = typeof signature === 'string' ? hexToBytes(signature) : signature;\n if (sig.length !== 65) {\n throw new DX402Error(`signature must be 65 bytes, got ${sig.length}`);\n }\n\n let v = sig[65 - 1];\n if (v === 27 || v === 28) v -= 27;\n else if (v >= 35) v = (v - 35) % 2;\n if (v !== 0 && v !== 1) throw new DX402Error(`invalid recovery id ${sig[64]}`);\n\n const parsed = secp256k1.Signature.fromCompact(sig.subarray(0, 64)).addRecoveryBit(v);\n return parsed.recoverPublicKey(digest).toRawBytes(true);\n}\n\n/**\n * Seal `body` so that only the holder of the payer's private key can read it.\n *\n * `payerKey` is a 33-byte SEC1-compressed secp256k1 key (EVM, XRPL) or a 32-byte\n * X25519 key from {@link ed25519ToX25519}.\n *\n * `paymentIdValue` is bound in as AEAD associated data, which is what stops a\n * ciphertext from being replayed as the evidence for a different payment.\n * Derive it with {@link paymentId} on both sides — deriving it differently makes\n * decryption fail with no obvious cause.\n *\n * Returns the bytes to upload. Nothing here touches the network.\n */\nexport function sealEvidence(\n body: Uint8Array,\n payerKey: Uint8Array,\n paymentIdValue: string,\n): Uint8Array {\n const aad = new TextEncoder().encode(paymentIdValue);\n const cek = randomBytes(32);\n const bodyNonce = randomBytes(NONCE_LEN);\n const cekNonce = randomBytes(NONCE_LEN);\n\n const ciphertext = gcm(cek, bodyNonce, aad).encrypt(body);\n\n let algByte: number;\n let ephemeral: Uint8Array;\n let shared: Uint8Array;\n\n if (payerKey.length === 33) {\n algByte = 1;\n const ephPriv = secp256k1.utils.randomPrivateKey();\n ephemeral = secp256k1.getPublicKey(ephPriv, true);\n // Only the x-coordinate is the ECDH result; the leading tag byte is not\n // part of it. Including it would derive a different key and fail with no\n // useful diagnostic.\n shared = secp256k1.getSharedSecret(ephPriv, payerKey, true).subarray(1);\n } else if (payerKey.length === 32) {\n algByte = 2;\n const ephPriv = randomBytes(32);\n ephemeral = x25519.getPublicKey(ephPriv);\n shared = x25519.getSharedSecret(ephPriv, payerKey);\n\n // RFC 7748 section 6.1: a small-order payer key would drive the shared\n // secret to a constant that whoever supplied it could reproduce.\n if (shared.every((b) => b === 0)) {\n throw new DX402Error('degenerate ECDH result (small-order public key)');\n }\n } else {\n throw new DX402Error(\n `payer key must be 33 bytes (secp256k1) or 32 (X25519), got ${payerKey.length}`,\n );\n }\n\n const wrapKey = hkdf(sha256, shared, aad, HKDF_INFO, 32);\n const wrappedCek = gcm(wrapKey, cekNonce, aad).encrypt(cek);\n\n const out = new Uint8Array(\n MAGIC.length + 3 + ephemeral.length + NONCE_LEN + 2 + wrappedCek.length +\n NONCE_LEN + ciphertext.length,\n );\n let pos = 0;\n out.set(MAGIC, pos); pos += MAGIC.length;\n out[pos++] = FORMAT_V1;\n out[pos++] = algByte;\n out[pos++] = ephemeral.length;\n out.set(ephemeral, pos); pos += ephemeral.length;\n out.set(cekNonce, pos); pos += NONCE_LEN;\n out[pos++] = (wrappedCek.length >> 8) & 0xff;\n out[pos++] = wrappedCek.length & 0xff;\n out.set(wrappedCek, pos); pos += wrappedCek.length;\n out.set(bodyNonce, pos); pos += NONCE_LEN;\n out.set(ciphertext, pos);\n return out;\n}\n\n// ============================================================================\n// Anchor authorization -- proving the anchor is yours\n// ============================================================================\n//\n// An anchor carrying a valid payee signature is `verified` and final. One\n// without is provisional: it still blocks a duplicate, but a verified anchor\n// for the same payment supersedes it.\n//\n// That asymmetry exists because the paymentId claim is permanent. Without it,\n// whoever anchored first owned the evidence of a payment forever and the real\n// seller was locked out.\n\nconst ANCHOR_DOMAIN_NAME = 'DX402 Anchor';\nconst ANCHOR_DOMAIN_VERSION = '1';\nconst ANCHOR_TYPE =\n 'Dx402AnchorAuthorization(bytes32 paymentId,bytes32 contentHash,string pointer,address payee)';\nconst EIP712_DOMAIN_TYPE = 'EIP712Domain(string name,string version,uint256 chainId)';\n\n/** The zero address, for the ed25519 form of the digest. */\nexport const ZERO_ADDRESS = '0x' + '00'.repeat(20);\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(total);\n let pos = 0;\n for (const p of parts) {\n out.set(p, pos);\n pos += p.length;\n }\n return out;\n}\n\nfunction uint256(n: number | bigint): Uint8Array {\n const out = new Uint8Array(32);\n let v = BigInt(n);\n for (let i = 31; i >= 0 && v > 0n; i--) {\n out[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return out;\n}\n\n/**\n * The 32-byte digest a seller signs to prove an anchor is theirs.\n *\n * One canonical message across every curve. `payee` is the EVM address for a\n * secp256k1 payee and the **zero address** for an ed25519 one — an ed25519\n * address does not fit the `address` field, and the binding is already\n * established by which key verifies the signature.\n *\n * `pointer` is whatever you send in the anchor, or the **empty string** when you\n * send `sealed` and the facilitator issues the pointer itself: you cannot sign a\n * value you have not seen.\n *\n * Getting this wrong throws nothing — it produces a signature that simply never\n * verifies, and the anchor stays provisional with no clue why. The tests pin it\n * against digests emitted by the facilitator's own Rust implementation.\n */\nexport function anchorDigest(\n paymentId: string,\n contentHash: string,\n pointer: string,\n payee: string,\n chainId: number,\n): Uint8Array {\n const b32 = (value: string, field: string): Uint8Array => {\n const raw = hexToBytes(value);\n if (raw.length !== 32) throw new DX402Error(`${field} must be 32 bytes, got ${raw.length}`);\n return raw;\n };\n\n const addr = hexToBytes(payee);\n if (addr.length !== 20) {\n throw new DX402Error(`payee must be a 20-byte address, got ${addr.length}`);\n }\n\n const enc = new TextEncoder();\n const domainSeparator = keccak_256(\n concatBytes(\n keccak_256(enc.encode(EIP712_DOMAIN_TYPE)),\n keccak_256(enc.encode(ANCHOR_DOMAIN_NAME)),\n keccak_256(enc.encode(ANCHOR_DOMAIN_VERSION)),\n uint256(chainId),\n ),\n );\n\n const structHash = keccak_256(\n concatBytes(\n keccak_256(enc.encode(ANCHOR_TYPE)),\n b32(paymentId, 'paymentId'),\n b32(contentHash, 'contentHash'),\n keccak_256(enc.encode(pointer)),\n new Uint8Array(12),\n addr,\n ),\n );\n\n return keccak_256(concatBytes(new Uint8Array([0x19, 0x01]), domainSeparator, structHash));\n}\n\n/**\n * Sign an anchor authorization with a Solana / Stellar ed25519 key.\n *\n * A Solana payee cannot produce an EIP-712 signature at all — its address is an\n * ed25519 key — so requiring one would leave that chain unable to prove\n * authorship even once the on-chain gate is enforced. This closes it today, with\n * no RPC.\n */\nexport function signAnchorEd25519(\n privateKey: Uint8Array,\n paymentId: string,\n contentHash: string,\n pointer = '',\n): string {\n if (privateKey.length !== 32) {\n throw new DX402Error(`ed25519 seed must be 32 bytes, got ${privateKey.length}`);\n }\n const digest = anchorDigest(paymentId, contentHash, pointer, ZERO_ADDRESS, 0);\n return '0x' + bytesToHex(ed25519.sign(digest, privateKey));\n}\n\n/**\n * Sign an anchor authorization with an EVM secp256k1 key.\n *\n * `payee` must be the address of `privateKey` — the facilitator recovers the\n * signer and compares, so declaring somebody else's address simply leaves the\n * anchor provisional.\n */\nexport function signAnchorEvm(\n privateKey: Uint8Array,\n paymentId: string,\n contentHash: string,\n pointer: string,\n payee: string,\n chainId: number,\n): string {\n const digest = anchorDigest(paymentId, contentHash, pointer, payee, chainId);\n const sig = secp256k1.sign(digest, privateKey);\n return '0x' + bytesToHex(sig.toCompactRawBytes()) + (sig.recovery === 1 ? '01' : '00');\n}\n\n/**\n * Derive the encryption target from a Solana (or Fogo) address.\n *\n * On ed25519 chains the address **is** the public key, so this needs no\n * signature and no lookup. Rejects anything that does not decode to exactly 32\n * bytes: a short decode silently padded up to 32 produces a small-order point,\n * which fails a layer later with a message that points nowhere near the cause.\n */\nexport function payerKeyFromSolanaAddress(address: string): Uint8Array {\n if (!address || !address.trim()) throw new DX402Error('empty Solana address');\n\n const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n let num = 0n;\n for (const ch of address) {\n const idx = alphabet.indexOf(ch);\n if (idx < 0) throw new DX402Error(`invalid base58 character '${ch}' in address`);\n num = num * 58n + BigInt(idx);\n }\n\n let hex = num.toString(16);\n if (hex.length % 2) hex = '0' + hex;\n const body = hexToBytes(hex);\n const leading = address.length - address.replace(/^1+/, '').length;\n\n const decoded = new Uint8Array(leading + body.length);\n decoded.set(body, leading);\n if (decoded.length !== 32) {\n throw new DX402Error(`Solana address decodes to ${decoded.length} bytes, expected 32`);\n }\n return ed25519ToX25519(decoded);\n}\n\n/**\n * Seal `body` so every listed recipient can read it, and nobody else.\n *\n * The body is encrypted **once**; only the content key is wrapped per recipient,\n * so adding the seller costs about sixty bytes rather than a second copy of the\n * payload. That is what makes it practical for a seller to keep a readable copy\n * of what it delivered — and answer a false \"that is not what you sent\" —\n * instead of paying to anchor evidence it cannot open.\n *\n * A single payer recipient is emitted as format **v1, byte-for-byte**, so\n * nothing already anchored becomes unreadable and readers still on v1 keep\n * working.\n */\nexport function sealEvidenceTo(\n body: Uint8Array,\n recipients: Array<{ role: RecipientRole; key: Uint8Array }>,\n paymentIdValue: string,\n): Uint8Array {\n if (recipients.length === 0) {\n throw new DX402Error('an envelope with no recipients could never be opened');\n }\n\n const aad = new TextEncoder().encode(paymentIdValue);\n const cek = randomBytes(CEK_LEN);\n const bodyNonce = randomBytes(NONCE_LEN);\n const ciphertext = gcm(cek, bodyNonce, aad).encrypt(body);\n\n const wrapped = recipients.map(({ role, key }) => {\n let algByte: number;\n let ephemeral: Uint8Array;\n let shared: Uint8Array;\n\n if (key.length === 33) {\n algByte = 1;\n const priv = secp256k1.utils.randomPrivateKey();\n ephemeral = secp256k1.getPublicKey(priv, true);\n shared = secp256k1.getSharedSecret(priv, key, true).subarray(1);\n } else if (key.length === 32) {\n algByte = 2;\n const priv = randomBytes(32);\n ephemeral = x25519.getPublicKey(priv);\n shared = x25519.getSharedSecret(priv, key);\n if (shared.every((b) => b === 0)) {\n throw new DX402Error('degenerate ECDH result (small-order public key)');\n }\n } else {\n throw new DX402Error(\n `public key must be 33 bytes (secp256k1) or 32 (X25519), got ${key.length}`,\n );\n }\n\n const wrapKey = hkdf(sha256, shared, aad, HKDF_INFO, 32);\n const cekNonce = randomBytes(NONCE_LEN);\n return {\n role,\n algByte,\n ephemeral,\n cekNonce,\n wrappedCek: gcm(wrapKey, cekNonce, aad).encrypt(cek),\n };\n });\n\n const singlePayer = wrapped.length === 1 && wrapped[0].role === 'payer';\n const parts: Uint8Array[] = [MAGIC, new Uint8Array([singlePayer ? FORMAT_V1 : FORMAT_V2])];\n if (!singlePayer) parts.push(new Uint8Array([wrapped.length]));\n\n for (const r of wrapped) {\n if (!singlePayer) parts.push(new Uint8Array([ROLE_NAMES.indexOf(r.role)]));\n parts.push(new Uint8Array([r.algByte, r.ephemeral.length]));\n parts.push(r.ephemeral, r.cekNonce);\n parts.push(new Uint8Array([(r.wrappedCek.length >> 8) & 0xff, r.wrappedCek.length & 0xff]));\n parts.push(r.wrappedCek);\n }\n\n parts.push(bodyNonce, ciphertext);\n return concatBytes(...parts);\n}\n\n// ============================================================================\n// The whole seller side, in one call\n// ============================================================================\n\nexport interface AnchorOptions {\n paymentId: string;\n network: string;\n txHash: string;\n payer: string;\n payee: string;\n /** The buyer's encryption key, from `payerKeyFromSolanaAddress` or similar. */\n payerKey: Uint8Array;\n /**\n * Your **public** key, to keep a readable copy so you can answer a false\n * \"that is not what you sent\".\n *\n * It does not have to be your payment key, and should not be — a custodial\n * payment wallet works fine here, because this key only ever decrypts.\n */\n sellerEncryptionKey?: Uint8Array;\n /**\n * The settlement proof, in the facilitator's `ProofOfPayment` shape\n * (`transactionHash`, `blockNumber`, `network`, `payer`, `payee`, `amount`,\n * `token`, `timestamp`, `paymentHash`).\n *\n * **The only thing that reaches `verified: true`.** Without it the\n * facilitator has checked no chain, so it records the anchor as provisional\n * and answers `notVerifiedReason: \"dx402_proof_missing\"`: the signature is\n * accepted (`signed: true`) but authorship is not certified, and a claim that\n * proves more may supersede it.\n */\n proofOfPayment?: Record<string, unknown>;\n /**\n * Which backend to anchor to (`\"s3\"`, `\"ipfs-private\"`, `\"ipfs-public\"`).\n * Omit to take the facilitator's default.\n *\n * Ask {@link availableBackends} what a given facilitator offers rather than\n * assuming — it depends on the deployment, and you may be pointed at one that\n * is not ours. **`ipfs-public` is irreversible**: the bytes become permanently\n * resolvable by anyone, and nobody, the facilitator included, can take them\n * down.\n */\n storage?: string;\n /**\n * `(digest) => \"0x...\"`. A callable rather than a private key is what lets a\n * custodian sign: it receives the digest and returns the signature without the\n * seed ever leaving it.\n *\n * Without one the anchor is **provisional** — it holds the slot, but a signed\n * anchor for the same payment supersedes it.\n */\n sign?: (digest: Uint8Array) => string | Promise<string>;\n /**\n * `(sealedBytes) => pointer`. Bring your own storage.\n *\n * Without this the sealed envelope travels **inside** the anchor request and\n * the facilitator hosts it, which is the easy path and stays the default. With\n * it, the SDK still seals exactly as before -- the buyer has to be able to\n * decrypt, so the sealing is not optional -- then hands you the ciphertext,\n * you write it wherever you keep durable bytes, and you return the pointer\n * that addresses it. The request then carries only that pointer, so the\n * ciphertext never travels through the anchor call and\n * {@link ANCHOR_MAX_REQUEST_BYTES} does not apply to your body.\n *\n * A callable rather than a precomputed pointer, for the same reason\n * {@link AnchorOptions.sign} is one: the SDK must seal first, and only then\n * can anything be uploaded. Handing in a pointer computed in advance would\n * mean addressing bytes that do not exist yet.\n *\n * The returned pointer is what the buyer will dereference, so it must be\n * readable by them -- see {@link dereferencePointer} for the schemes the SDK\n * resolves out of the box. It is also bound into the seller signature.\n *\n * **It is never allowed to break the sale.** If it throws or returns\n * something unusable, the anchor degrades to a skip and the payment is\n * untouched.\n */\n upload?: (sealed: Uint8Array) => string | Promise<string>;\n /**\n * Which storage family the pointer belongs to: `s3`, `ipfs` or `arweave`.\n *\n * Defaults to `s3`, and in {@link AnchorOptions.upload} mode it is inferred\n * from the pointer's scheme when you do not say. Distinct from `storage`,\n * which names one of the FACILITATOR's own offers and is meaningless when you\n * supply the bytes yourself.\n */\n backend?: 's3' | 'ipfs' | 'arweave';\n retention?: string;\n facilitator?: string;\n fetch?: typeof fetch;\n}\n\n/**\n * Seal a response body, anchor it, and return the `X-Durable-Evidence` value.\n *\n * **It never throws.** Every failure resolves to a skip notice, because evidence\n * is an addition to the payment path and must never be a gate in front of it —\n * an unreachable facilitator has to cost the receipt, never the sale.\n *\n * # Two ways to store the ciphertext\n *\n * **Hosted (default).** The sealed envelope travels inside the anchor request\n * and the facilitator stores it and issues the pointer. Nothing to set up. The\n * request carries the ciphertext, so it is bounded by\n * {@link ANCHOR_MAX_REQUEST_BYTES}.\n *\n * **Your own storage.** Pass {@link AnchorOptions.upload}. The SDK seals\n * identically, hands you the ciphertext, and sends the pointer you return in\n * place of the blob — so the ciphertext never travels through the anchor call\n * and that request bound does not apply to your body. The facilitator has\n * accepted a caller-supplied pointer since v0.1; this is the SDK catching up.\n *\n * ```ts\n * await anchorEvidence(body, {\n * ...common,\n * // called with the SEALED bytes, never the plaintext\n * upload: async (sealed) => {\n * await myBucket.put(key, sealed);\n * return `s3+https://cdn.example.com/${key}`;\n * },\n * });\n * ```\n *\n * Either way the seller keeps custody of nothing it did not already have: the\n * facilitator cannot read a `direct`-mode envelope in the hosted case either.\n * What changes is durability and cost, which become yours.\n */\n\n/** `0x` + 40 hex. An ed25519 payee (Solana, Stellar) never matches. */\nfunction isEvmAddress(value: string): boolean {\n return /^0x[0-9a-fA-F]{40}$/.test((value ?? '').trim());\n}\n\n/** The chain id behind a network name or CAIP-2 id, or undefined if unknown. */\nfunction chainIdFor(network: string): number | undefined {\n // `eip155:8453` carries the chain id literally. Read it rather than going\n // through the chain table, which has no entry for EVM TESTNETS -- so without\n // this a seller on one cannot produce a verifiable anchor signature at all.\n const raw = network ?? '';\n if (raw.toLowerCase().startsWith('eip155:')) {\n const tail = raw.slice('eip155:'.length);\n if (/^\\d+$/.test(tail)) return Number(tail);\n }\n const name = raw.includes(':') ? (raw.split(':')[1] ?? '') : raw;\n const byId = Number(name);\n if (Number.isFinite(byId) && byId > 0) return getChainById(byId)?.chainId;\n return getChainByName(name)?.chainId;\n}\n\n/**\n * The digest the facilitator will ACTUALLY verify, chosen by the payee's curve.\n *\n * The gate dispatches on the payee and checks **one** form -- never both. A\n * secp256k1 payee is verified against the digest built with its REAL address and\n * chain id; an ed25519 payee, whose address does not fit the `address` field, is\n * verified against the zero address and chain id 0.\n *\n * Signing the wrong form throws nothing. It yields a signature that never\n * verifies, the anchor silently stays **provisional**, and a provisional anchor\n * can be superseded by anyone -- the very hijack a signed anchor exists to stop.\n * Reproduced against production by KarmaKadabra, 2026-08-19: with everything else\n * identical, the ed25519 form was refused (`409 dx402_already_anchored`) and the\n * EVM form superseded the provisional.\n *\n * `pointer` defaults to the empty string, which is right when you send `sealed`:\n * the facilitator issues the pointer and you cannot sign what you have not seen.\n * When you supply your OWN pointer it must be passed here **verbatim** -- the\n * facilitator verifies against `req.pointer` when one is present and against\n * `\"\"` when it is absent (x402-rs `dx402/service.rs`, `signed_pointer`), so\n * signing the empty string alongside a pointer produces a signature that never\n * verifies and an anchor that silently stays provisional.\n */\nexport function sellerDigestFor(\n paymentId: string,\n contentHash: string,\n payee: string,\n network: string,\n pointer = '',\n): Uint8Array | undefined {\n if (isEvmAddress(payee)) {\n const chainId = chainIdFor(network);\n // An EVM payee whose chain id we cannot resolve. Falling through to the\n // ed25519 form is how this shipped in 0.53.0: it throws nothing and yields\n // a signature that never verifies, so the anchor stays provisional forever\n // with no error anywhere. Refuse instead -- unsigned is honest and\n // recoverable, signed-but-worthless only looks done.\n if (!chainId) return undefined;\n return anchorDigest(paymentId, contentHash, pointer, payee, chainId);\n }\n return anchorDigest(paymentId, contentHash, pointer, ZERO_ADDRESS, 0);\n}\n\n\n/**\n * Largest `POST /dx402/anchor` request the facilitator accepts, mirroring its\n * `MAX_REQUEST_BODY_BYTES` (default 64 KiB, an anti-OOM bound on every route).\n * After base64 inflation and ~600 bytes of metadata this leaves ~47 KB of\n * plaintext.\n */\nexport const ANCHOR_MAX_REQUEST_BYTES = 64 * 1024;\n\n/** base64 without spreading the array into arguments -- a large blob would\n * otherwise overflow the call stack and surface as a generic failure. */\nfunction toBase64(bytes: Uint8Array): string {\n let out = '';\n const CHUNK = 0x8000;\n for (let i = 0; i < bytes.length; i += CHUNK) {\n out += String.fromCharCode(...bytes.subarray(i, i + CHUNK));\n }\n return btoa(out);\n}\n\n/**\n * Which storage family a pointer names, for the anchor's `backend` field.\n *\n * The facilitator records this; it does not fetch through it. `s3` is the\n * fallback because `s3+https://` is the SDK's own scheme for \"an ordinary HTTPS\n * URL\", which is what most sellers' own sinks are.\n */\nfunction backendForPointer(pointer: string): 's3' | 'ipfs' | 'arweave' {\n if (pointer.startsWith('ipfs://')) return 'ipfs';\n if (pointer.startsWith('ar://')) return 'arweave';\n return 's3';\n}\n\nexport async function anchorEvidence(\n body: Uint8Array,\n opts: AnchorOptions,\n): Promise<Record<string, unknown>> {\n try {\n const recipients: Array<{ role: RecipientRole; key: Uint8Array }> = [\n { role: 'payer', key: opts.payerKey },\n ];\n if (opts.sellerEncryptionKey) {\n recipients.push({ role: 'seller', key: opts.sellerEncryptionKey });\n }\n const blob = sealEvidenceTo(body, recipients, opts.paymentId);\n const hash = contentHash(body);\n\n // Bring-your-own-storage. The sealing above is identical either way -- the\n // buyer must be able to decrypt -- so all that changes is who holds the\n // ciphertext and, therefore, whether it has to travel in this request.\n //\n // The upload is fenced off completely: a seller's bucket going down is not\n // a reason for a paid response to fail, so anything thrown here becomes a\n // skip, exactly like an unreachable facilitator.\n let pointer: string | undefined;\n if (opts.upload) {\n try {\n pointer = await opts.upload(blob);\n } catch {\n return { v: 1, skipped: 'anchor_failed', stage: 'upload' };\n }\n if (typeof pointer !== 'string' || pointer.trim() === '') {\n // An empty pointer addresses nothing, and the facilitator would record\n // an anchor that dereferences to a 404 forever. Worse than no anchor.\n return { v: 1, skipped: 'anchor_failed', stage: 'upload' };\n }\n pointer = pointer.trim();\n }\n\n const payload: Record<string, unknown> = {\n paymentId: opts.paymentId,\n network: opts.network,\n txHash: opts.txHash,\n payer: opts.payer,\n payee: opts.payee,\n // Exactly one of these. The facilitator dispatches on their presence:\n // `sealed` -> it hosts and derives the pointer; `pointer` alone -> it uses\n // yours; neither -> error (x402-rs `dx402/service.rs`).\n ...(pointer !== undefined ? { pointer } : { sealed: toBase64(blob) }),\n backend: opts.backend ?? (pointer !== undefined ? backendForPointer(pointer) : 's3'),\n contentHash: hash,\n keyAlg: opts.payerKey.length === 32 ? 'ECIES-X25519' : 'ECIES-secp256k1',\n mode: 'direct',\n retention: opts.retention ?? '90d',\n };\n\n let unsigned: string | undefined;\n if (opts.proofOfPayment) {\n payload.proofOfPayment = opts.proofOfPayment;\n }\n\n if (opts.storage) {\n payload.storage = opts.storage;\n }\n\n if (opts.sign) {\n // The signature covers the pointer the facilitator will verify against:\n // ours when we supply one, the empty string when the facilitator issues\n // it. Signing the wrong one throws nothing and leaves the anchor\n // provisional -- which is the state anyone can supersede.\n const digest = sellerDigestFor(opts.paymentId, hash, opts.payee, opts.network, pointer ?? '');\n if (digest === undefined) {\n unsigned = 'unknown_chain_id';\n } else {\n payload.sellerSignature = await opts.sign(digest);\n }\n }\n\n // Measure the SEALED, serialised request -- not the plaintext. The\n // envelope adds a nonce, the wrapped CEK and its JSON, and the ciphertext\n // travels base64 (4/3). Checking the plaintext lets through bodies the\n // facilitator then rejects, arriving as a generic failure long after the\n // sealing work was done. Measured by KarmaKadabra, 2026-08-19: 47 KB of\n // plaintext fits, 48 KB does not.\n //\n // In `upload` mode the ciphertext is not in the request at all, so this\n // bound says nothing about the body and is not applied. The request is a\n // pointer and some metadata; only a pathological pointer could approach it.\n const wire = JSON.stringify(payload);\n if (pointer === undefined && new TextEncoder().encode(wire).length > ANCHOR_MAX_REQUEST_BYTES) {\n return { v: 1, skipped: 'too_large' };\n }\n\n const base = (opts.facilitator ?? 'https://facilitator.ultravioletadao.xyz').replace(\n /\\/+$/,\n '',\n );\n const doFetch = opts.fetch ?? fetch;\n const res = await doFetch(`${base}/dx402/anchor`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: wire,\n });\n // Carry the facilitator's own diagnosis out rather than flattening every\n // failure to `anchor_failed`. A rejected signature answers 422\n // `dx402_signature_not_verified`; erasing it here would reproduce, one\n // layer down, the exact problem that code exists to solve.\n if (!res.ok) {\n let error: unknown;\n try {\n error = ((await res.json()) as { error?: unknown }).error;\n } catch {\n /* a non-JSON error body is still a failure */\n }\n return { v: 1, skipped: 'anchor_failed', status: res.status, error };\n }\n const out = (await res.json()) as Record<string, unknown>;\n if (unsigned) out.unsigned = unsigned;\n return out;\n } catch {\n return { v: 1, skipped: 'anchor_failed' };\n }\n}\n\n/** One storage option a facilitator offers, from `GET /dx402/stats`. */\nexport interface BackendOffer {\n id: string;\n retention: string;\n /**\n * Whether the bytes can actually be removed when retention expires.\n *\n * `false` means the `retentionUntil` in the signed receipt **cannot be\n * honoured**: on public IPFS, unpinning removes the facilitator's copy, not\n * the network's.\n */\n revocable: boolean;\n /** Whether anyone resolves the bytes without going through the facilitator. */\n public: boolean;\n enabled: boolean;\n disabledReason?: string;\n}\n\n/**\n * Ask a facilitator which storage backends it actually offers.\n *\n * Ask instead of assuming. What exists depends on the deployment — one without\n * a Pinata credential offers only `s3` — and an integrator may be pointed at a\n * facilitator that is not ours. A hardcoded list in your code is a promise\n * somebody else has to keep.\n *\n * Resolves to `[]` rather than rejecting when the facilitator is unreachable or\n * does not run DX402 — same discipline as {@link anchorEvidence}.\n */\nexport async function availableBackends(\n facilitator = 'https://facilitator.ultravioletadao.xyz',\n opts: { fetch?: typeof fetch } = {},\n): Promise<BackendOffer[]> {\n try {\n const doFetch = opts.fetch ?? fetch;\n const res = await doFetch(`${facilitator.replace(/\\/+$/, '')}/dx402/stats`);\n if (!res.ok) return [];\n const body = (await res.json()) as { backends?: BackendOffer[] };\n return body.backends ?? [];\n } catch {\n return [];\n }\n}\n\n/** Encode an anchor result for the `X-Durable-Evidence` response header. */\nexport function evidenceHeader(evidence: unknown): string {\n // Encode to UTF-8 first. `btoa` takes a *binary* string: any code point above\n // U+00FF throws InvalidCharacterError, and one between U+0080 and U+00FF is\n // silently emitted as a single latin-1 byte, so the far side decodes mojibake.\n // Either is reachable from ordinary evidence -- a `notVerifiedReason` or a\n // pointer with a non-ASCII character is enough.\n const bytes = new TextEncoder().encode(JSON.stringify(evidence));\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n","/**\n * uvd-x402-sdk - Type Definitions\n *\n * Core TypeScript interfaces for the x402 payment SDK.\n * These types define the contract between the SDK and consuming applications.\n */\n\n// ============================================================================\n// CHAIN CONFIGURATION TYPES\n// ============================================================================\n\n/**\n * Network type categorization\n * - 'evm': Ethereum Virtual Machine compatible chains (use EIP-712)\n * - 'svm': Solana Virtual Machine chains (Solana, Fogo) (use SPL tokens)\n * - 'stellar': Stellar network (use Soroban)\n * - 'near': NEAR Protocol (use NEP-366)\n * - 'algorand': Algorand network (use ASA transfers with atomic transactions)\n * - 'sui': Sui blockchain (use sponsored transactions)\n * - 'xrpl': XRP Ledger (use pre-signed Payment transaction blobs)\n *\n * @deprecated 'solana' type is deprecated, use 'svm' instead\n */\nexport type NetworkType = 'evm' | 'svm' | 'solana' | 'stellar' | 'near' | 'algorand' | 'sui' | 'xrpl';\n\n/**\n * Supported x402 payment schemes\n * - 'exact': Standard one-shot payment (default)\n * - 'escrow': Escrow-based payment with verify/settle/refund\n * - 'commerce': Commerce alias for escrow (marketplace integrations)\n */\nexport type X402Scheme = 'exact' | 'escrow' | 'commerce';\n\n/**\n * Supported stablecoin token types\n * - usdc: USD Coin (Circle) - 6 decimals\n * - eurc: Euro Coin (Circle) - 6 decimals\n * - ausd: Agora USD (Agora Finance) - 6 decimals\n * - pyusd: PayPal USD (PayPal/Paxos) - 6 decimals\n * - usdt: Tether USD (USDT0 omnichain via LayerZero) - 6 decimals\n * - usdg: Global Dollar (Paxos) - 6 decimals; settlement stablecoin on Robinhood Chain\n */\nexport type TokenType = 'usdc' | 'eurc' | 'ausd' | 'pyusd' | 'usdt' | 'usdg';\n\n/**\n * Token configuration for EIP-712 signing and transfers\n */\nexport interface TokenConfig {\n /** Contract/mint address */\n address: string;\n /** Token decimals (6 for all supported stablecoins) */\n decimals: number;\n /** Token name for EIP-712 domain (e.g., \"USD Coin\" or \"USDC\") */\n name: string;\n /** Token version for EIP-712 domain */\n version: string;\n}\n\n/**\n * USDC token configuration for a specific chain\n * @deprecated Use TokenConfig instead. This is kept for backward compatibility.\n */\nexport interface USDCConfig {\n /** Contract/mint address */\n address: string;\n /** Token decimals (6 for most chains, 7 for Stellar) */\n decimals: number;\n /** Token name for EIP-712 domain (e.g., \"USD Coin\" or \"USDC\") */\n name: string;\n /** Token version for EIP-712 domain */\n version: string;\n}\n\n/**\n * Native currency configuration\n */\nexport interface NativeCurrency {\n name: string;\n symbol: string;\n decimals: number;\n}\n\n/**\n * Complete chain configuration\n */\nexport interface ChainConfig {\n /** Numeric chain ID (0 for non-EVM chains) */\n chainId: number;\n /** Hex-encoded chain ID for wallet_switchEthereumChain */\n chainIdHex: string;\n /** Internal chain identifier (e.g., 'base', 'solana') */\n name: string;\n /** Human-readable display name */\n displayName: string;\n /** Network type for routing */\n networkType: NetworkType;\n /** Primary RPC endpoint URL */\n rpcUrl: string;\n /** Block explorer base URL */\n explorerUrl: string;\n /** Native currency info */\n nativeCurrency: NativeCurrency;\n /** USDC token configuration */\n usdc: USDCConfig;\n /**\n * Multi-token configurations (EVM chains only)\n * Maps token type to its configuration for this chain.\n * Not all tokens are available on all chains.\n */\n tokens?: Partial<Record<TokenType, TokenConfig>>;\n /** x402 facilitator configuration */\n x402: {\n facilitatorUrl: string;\n enabled: boolean;\n };\n}\n\n// ============================================================================\n// WALLET TYPES\n// ============================================================================\n\n/**\n * Current wallet connection state\n */\nexport interface WalletState {\n /** Whether a wallet is currently connected */\n connected: boolean;\n /** Connected wallet address (null if not connected) */\n address: string | null;\n /** Current chain ID (null for non-EVM or disconnected) */\n chainId: number | null;\n /** Current network name */\n network: string | null;\n /** Network type of connected wallet */\n networkType: NetworkType | null;\n /** USDC balance on current chain (null if unknown) */\n balance: string | null;\n}\n\n/**\n * Wallet adapter interface for different wallet types\n */\nexport interface WalletAdapter {\n /** Unique identifier for this wallet type */\n readonly id: string;\n /** Display name */\n readonly name: string;\n /** Network type this adapter supports */\n readonly networkType: NetworkType;\n\n /** Check if this wallet is available/installed */\n isAvailable(): boolean;\n\n /** Connect to the wallet */\n connect(chainName?: string): Promise<string>;\n\n /** Disconnect from the wallet */\n disconnect(): Promise<void>;\n\n /** Switch to a different chain (EVM only) */\n switchChain?(chainName: string): Promise<void>;\n\n /**\n * Sign a payment payload\n * For EVM chains, supports multi-token via paymentInfo.tokenType\n */\n signPayment(paymentInfo: PaymentInfo, chainConfig: ChainConfig): Promise<string>;\n\n /**\n * Check token balance (defaults to USDC for backward compatibility)\n * EVM providers may accept optional tokenType parameter\n */\n getBalance(chainConfig: ChainConfig, tokenType?: TokenType): Promise<string>;\n\n /** Get current address */\n getAddress(): string | null;\n\n /** Get current chain ID (EVM only) */\n getChainId?(): number | null;\n}\n\n/**\n * EIP-712 domain for typed data signing\n */\nexport interface EIP712Domain {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: string;\n}\n\n/**\n * EIP-712 type definitions\n */\nexport interface EIP712Types {\n [typeName: string]: Array<{ name: string; type: string }>;\n}\n\n// ============================================================================\n// PAYMENT TYPES\n// ============================================================================\n\n/**\n * Payment information returned by backend on 402 response\n */\nexport interface PaymentInfo {\n /** Default recipient address */\n recipient: string;\n /** Network-specific recipient addresses */\n recipients?: {\n evm?: string;\n solana?: string;\n near?: string;\n stellar?: string;\n algorand?: string;\n sui?: string;\n xrpl?: string;\n };\n /** Facilitator address (for Solana fee payer) */\n facilitator?: string;\n /** Amount in USD (e.g., \"10.00\") */\n amount: string;\n /** Token symbol (usually \"USDC\") */\n token?: string;\n /**\n * Token type for multi-token support\n * Defaults to 'usdc' if not specified for backward compatibility\n */\n tokenType?: TokenType;\n /** Network hint from backend */\n network?: string;\n /** Supported chain IDs */\n supportedChains?: number[];\n}\n\n/**\n * Simple payment request from application\n */\nexport interface PaymentRequest {\n /** Amount in USDC (e.g., \"10.00\") */\n amount: string;\n /** Override recipient address (optional) */\n recipient?: string;\n /** Application-specific metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * x402 payment header names\n *\n * - 'X-PAYMENT': v1 header name (default, most compatible)\n * - 'PAYMENT-SIGNATURE': v2 header name (newer standard)\n *\n * Both headers use the same base64-encoded JSON payload format.\n * The facilitator accepts both headers.\n */\nexport type X402HeaderName = 'X-PAYMENT' | 'PAYMENT-SIGNATURE';\n\n/**\n * Payment headers object containing both v1 and v2 header formats\n */\nexport interface PaymentHeaders {\n /** v1 header: X-PAYMENT */\n 'X-PAYMENT': string;\n /** v2 header: PAYMENT-SIGNATURE (same value, different header name) */\n 'PAYMENT-SIGNATURE': string;\n}\n\n/**\n * Result of a payment operation\n */\nexport interface PaymentResult {\n /** Whether payment was successful */\n success: boolean;\n /** Base64-encoded X-PAYMENT header value */\n paymentHeader: string;\n /**\n * Payment headers object for easy use with fetch/axios\n *\n * @example\n * ```ts\n * // Use v1 header\n * fetch(url, { headers: { 'X-PAYMENT': result.headers['X-PAYMENT'] } });\n *\n * // Use v2 header\n * fetch(url, { headers: { 'PAYMENT-SIGNATURE': result.headers['PAYMENT-SIGNATURE'] } });\n * ```\n */\n headers: PaymentHeaders;\n /** Transaction hash (if available) */\n transactionHash?: string;\n /** Network where payment was made */\n network: string;\n /** Payer address */\n payer?: string;\n /** Error message (if success is false) */\n error?: string;\n}\n\n// ============================================================================\n// PAYLOAD TYPES (Internal)\n// ============================================================================\n\n/**\n * EVM payment payload (ERC-3009 TransferWithAuthorization)\n */\nexport interface EVMPaymentPayload {\n from: string;\n to: string;\n value: string;\n validAfter: number;\n validBefore: number;\n nonce: string;\n v: number;\n r: string;\n s: string;\n chainId: number;\n token: string;\n}\n\n/**\n * Token info for non-USDC stablecoins (e.g., Token2022 like AUSD)\n * Required in payload for facilitator to verify Token2022 transfers correctly.\n */\nexport interface TokenInfo {\n /** Token mint address */\n address: string;\n /** Token symbol (e.g., 'AUSD') */\n symbol: string;\n /** Token decimals (e.g., 6) */\n decimals: number;\n}\n\n/**\n * Solana payment payload (partially-signed transaction)\n */\nexport interface SolanaPaymentPayload {\n /** Base64-encoded serialized transaction */\n transaction: string;\n /**\n * Token info for non-USDC tokens (e.g., Token2022 like AUSD)\n * CRITICAL: Must be included for Token2022 tokens for facilitator verification\n */\n token?: TokenInfo;\n}\n\n/**\n * Stellar payment payload (Soroban authorization)\n */\nexport interface StellarPaymentPayload {\n /** Sender G... public key */\n from: string;\n /** Recipient G... public key */\n to: string;\n /** Amount in stroops (7 decimals) */\n amount: string;\n /** USDC SAC contract address */\n tokenContract: string;\n /** Base64 XDR-encoded SorobanAuthorizationEntry */\n authorizationEntryXdr: string;\n /** Random 64-bit nonce */\n nonce: number;\n /** Ledger when authorization expires */\n signatureExpirationLedger: number;\n}\n\n/**\n * NEAR payment payload (NEP-366 meta-transaction)\n */\nexport interface NEARPaymentPayload {\n /** Base64 Borsh-encoded SignedDelegateAction */\n signedDelegateAction: string;\n network: 'near';\n}\n\n/**\n * Algorand payment payload (atomic transaction group)\n *\n * Follows the GoPlausible x402-avm spec for atomic groups:\n * - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees\n * - Transaction 1: ASA transfer (SIGNED) - client -> merchant\n *\n * The facilitator signs transaction 0 and submits the complete atomic group.\n */\nexport interface AlgorandPaymentPayload {\n /** Index of the payment transaction in the group (always 1) */\n paymentIndex: number;\n /**\n * Array of base64-encoded msgpack transactions forming the atomic group:\n * - [0]: Unsigned fee transaction (facilitator signs)\n * - [1]: Signed ASA transfer (client signed)\n */\n paymentGroup: string[];\n}\n\n/**\n * Sui payment payload (sponsored transaction)\n *\n * Uses Sui sponsored transactions where:\n * - User creates a programmable transaction for USDC transfer\n * - User signs the transaction\n * - Facilitator sponsors (pays gas in SUI) and submits\n *\n * User pays: ZERO SUI\n */\nexport interface SuiPaymentPayload {\n /** Base64-encoded BCS serialized TransactionData */\n transactionBytes: string;\n /** Base64-encoded user signature */\n senderSignature: string;\n /** Sender address (0x + 64 hex chars) */\n from: string;\n /** Recipient address (0x + 64 hex chars) */\n to: string;\n /** Amount in base units (string to handle large numbers) */\n amount: string;\n /** Coin object ID used for the transfer (REQUIRED by facilitator) */\n coinObjectId: string;\n}\n\n/**\n * XRPL payment payload (pre-signed Payment transaction blob)\n *\n * Uses the t54 \"pre-signed Payment blob\" scheme on the XRP Ledger:\n * - The client builds and FULLY signs a Payment transaction off-chain,\n * paying its own XRP network fee.\n * - The single `signedTxBlob` field (hex-encoded fully-signed XRPL tx blob)\n * is sent to the facilitator, which decodes it to re-derive payer/amount/\n * destination and submits it.\n *\n * All payment-level fields (destination, amount, InvoiceID, SourceTag, etc.)\n * come from PaymentRequirements/extra, NOT from this payload.\n *\n * XRP is the native asset (6 decimals / drops). There is no token contract.\n *\n * The JSON field name is EXACTLY `signedTxBlob` (camelCase).\n */\nexport interface XRPLPaymentPayload {\n /** Hex-encoded fully-signed XRPL Payment transaction blob (tx_blob) */\n signedTxBlob: string;\n}\n\n/**\n * Union type for all payment payloads\n */\nexport type PaymentPayload =\n | EVMPaymentPayload\n | SolanaPaymentPayload\n | StellarPaymentPayload\n | NEARPaymentPayload\n | AlgorandPaymentPayload\n | SuiPaymentPayload\n | XRPLPaymentPayload;\n\n// ============================================================================\n// X402 HEADER TYPES (v1 and v2)\n// ============================================================================\n\n/**\n * x402 protocol version\n */\nexport type X402Version = 1 | 2;\n\n/**\n * CAIP-2 chain identifiers for x402 v2\n * @see https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md\n */\nexport const CAIP2_IDENTIFIERS: Record<string, string> = {\n // EVM chains\n base: 'eip155:8453',\n ethereum: 'eip155:1',\n polygon: 'eip155:137',\n arbitrum: 'eip155:42161',\n optimism: 'eip155:10',\n avalanche: 'eip155:43114',\n celo: 'eip155:42220',\n hyperevm: 'eip155:999',\n unichain: 'eip155:130',\n monad: 'eip155:143',\n bsc: 'eip155:56',\n scroll: 'eip155:534352',\n 'skale-base': 'eip155:1187947933',\n 'skale-base-sepolia': 'eip155:324705682',\n robinhood: 'eip155:4663',\n 'robinhood-testnet': 'eip155:46630',\n // SVM chains\n solana: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n fogo: 'svm:fogo',\n // Stellar\n stellar: 'stellar:pubnet',\n // NEAR\n near: 'near:mainnet',\n // Algorand\n algorand: 'algorand:mainnet',\n 'algorand-testnet': 'algorand:testnet',\n // Sui\n sui: 'sui:mainnet',\n 'sui-testnet': 'sui:testnet',\n // XRPL (XRP Ledger has no CAIP-2 form - the v1 string IS the network id)\n 'xrpl-mainnet': 'xrpl-mainnet',\n 'xrpl-testnet': 'xrpl-testnet',\n};\n\n/**\n * Reverse mapping from CAIP-2 to chain name\n */\nexport const CAIP2_TO_CHAIN: Record<string, string> = Object.fromEntries(\n Object.entries(CAIP2_IDENTIFIERS).map(([k, v]) => [v, k])\n);\n\n/**\n * x402 v1 header structure (network as string)\n */\nexport interface X402HeaderV1 {\n x402Version: 1;\n scheme: X402Scheme;\n network: string;\n payload: X402PayloadData;\n}\n\n/**\n * x402 v2 payment option\n */\nexport interface X402PaymentOption {\n network: string; // CAIP-2 format\n asset: string;\n amount: string;\n facilitator?: string;\n}\n\n/**\n * x402 v2 header structure (CAIP-2 network, accepts array)\n */\nexport interface X402HeaderV2 {\n x402Version: 2;\n scheme: X402Scheme;\n network: string; // CAIP-2 format\n payload: X402PayloadData;\n accepts?: X402PaymentOption[];\n}\n\n/**\n * Union type for both v1 and v2 headers\n */\nexport type X402Header = X402HeaderV1 | X402HeaderV2;\n\n/**\n * EVM-specific payload in x402 header\n */\nexport interface X402EVMPayload {\n signature: string;\n authorization: {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n };\n /**\n * Which token was actually paid.\n *\n * Only present when the payment is created with `includeTokenMetadata`. The\n * signature alone does not say which stablecoin it authorizes — a server that\n * accepts several tokens on the same chain cannot rebuild the payment\n * requirements without this. Omitted by default so existing v1 wire formats\n * stay byte-identical.\n */\n token?: PaymentTokenMetadata;\n}\n\n/**\n * Token identification carried inside an x402 payload.\n *\n * Mirrors what a resource server needs to build `paymentRequirements`: the\n * `asset` it must charge and the `extra` EIP-712 domain the facilitator needs\n * to recover the signature.\n */\nexport interface PaymentTokenMetadata {\n /** Token contract address (the `asset` of the payment requirements) */\n address: string;\n /** Uppercase token symbol, e.g. `USDC`, `EURC`, `USDT` */\n symbol: string;\n /** Token decimals — the amount in the authorization is in these units */\n decimals: number;\n /** EIP-712 domain of the token contract (the `extra` of the requirements) */\n eip712: {\n name: string;\n version: string;\n };\n}\n\n/**\n * Solana-specific payload in x402 header\n */\nexport interface X402SolanaPayload {\n transaction: string;\n}\n\n/**\n * Settlement account payload for Crossmint and other custodial wallets\n * that can only sendTransaction (not signTransaction).\n *\n * In this mode, the client already submitted the transaction on-chain.\n * The facilitator verifies the on-chain tx, then sweeps USDC from the\n * settlement account to the payTo address.\n *\n * Used by: Crossmint smart wallets via @faremeter/wallet-crossmint\n */\nexport interface X402SettlementAccountPayload {\n /** On-chain transaction signature (already submitted) */\n transactionSignature: string;\n /** Base58 secret key for sweeping settlement account (optional) */\n settleSecretKey?: string;\n /** Address to receive rent from closed settlement ATA (optional) */\n settlementRentDestination?: string;\n}\n\n/**\n * Stellar-specific payload in x402 header\n */\nexport interface X402StellarPayload {\n from: string;\n to: string;\n amount: string;\n tokenContract: string;\n authorizationEntryXdr: string;\n nonce: number;\n signatureExpirationLedger: number;\n}\n\n/**\n * NEAR-specific payload in x402 header\n */\nexport interface X402NEARPayload {\n signedDelegateAction: string;\n}\n\n/**\n * Algorand-specific payload in x402 header (atomic group format)\n */\nexport interface X402AlgorandPayload {\n /** Index of the payment transaction in the group (always 1) */\n paymentIndex: number;\n /** Array of base64-encoded msgpack transactions */\n paymentGroup: string[];\n}\n\n/**\n * Sui-specific payload in x402 header (sponsored transaction)\n */\nexport interface X402SuiPayload {\n /** BCS-encoded transaction bytes (base64) */\n transactionBytes: string;\n /** User's signature on the transaction (base64) */\n senderSignature: string;\n /** Sender's Sui address (0x...) */\n from: string;\n /** Recipient's Sui address (0x...) */\n to: string;\n /** Amount in smallest unit (string to avoid precision issues) */\n amount: string;\n /** Coin object ID used for the transfer (REQUIRED by facilitator) */\n coinObjectId: string;\n}\n\n/**\n * XRPL-specific payload in x402 header (t54 pre-signed Payment blob)\n *\n * The JSON field name is EXACTLY `signedTxBlob` (camelCase). The facilitator\n * decodes the blob to re-derive payer/amount/destination; no other fields are\n * carried in the payload.\n */\nexport interface X402XRPLPayload {\n /** Hex-encoded fully-signed XRPL Payment transaction blob (tx_blob) */\n signedTxBlob: string;\n}\n\n/**\n * Union of all x402 payload types\n */\nexport type X402PayloadData =\n | X402EVMPayload\n | X402SolanaPayload\n | X402SettlementAccountPayload\n | X402StellarPayload\n | X402NEARPayload\n | X402AlgorandPayload\n | X402SuiPayload\n | X402XRPLPayload;\n\n// ============================================================================\n// CLIENT CONFIGURATION\n// ============================================================================\n\n/**\n * Multi-payment configuration for supporting multiple networks\n */\nexport interface MultiPaymentConfig {\n /** Networks to support (e.g., ['base', 'solana', 'stellar', 'near']) */\n networks: string[];\n /** Default network if user hasn't selected one */\n defaultNetwork?: string;\n /** Whether to auto-detect user's preferred network based on wallet */\n autoDetect?: boolean;\n}\n\n/**\n * SDK client configuration options\n */\nexport interface X402ClientConfig {\n /** Facilitator URL (default: https://facilitator.ultravioletadao.xyz) */\n facilitatorUrl?: string;\n /** Default chain to connect to */\n defaultChain?: string;\n /** Auto-connect on initialization */\n autoConnect?: boolean;\n /** Enable debug logging */\n debug?: boolean;\n /** Custom chain configurations (override defaults) */\n customChains?: Record<string, Partial<ChainConfig>>;\n /** Wallet preference order */\n walletPreference?: string[];\n /** Custom RPC URLs (override defaults) */\n rpcOverrides?: Record<string, string>;\n /**\n * x402 protocol version to use\n * - 1: Classic format with network as string (e.g., \"base\")\n * - 2: CAIP-2 format with accepts array (e.g., \"eip155:8453\")\n * - 'auto': Auto-detect from 402 response (default)\n */\n x402Version?: X402Version | 'auto';\n /** Multi-payment configuration for supporting multiple networks */\n multiPayment?: MultiPaymentConfig;\n /**\n * Include a `token` block in the payload naming the asset, its decimals and\n * its EIP-712 domain.\n *\n * Needed when the resource accepts more than one stablecoin on the same\n * chain: the signature alone does not say which one was paid, so the server\n * cannot rebuild `paymentRequirements`. Off by default — the emitted header\n * stays byte-identical to previous versions.\n */\n includeTokenMetadata?: boolean;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: Required<Pick<X402ClientConfig, 'facilitatorUrl' | 'defaultChain' | 'autoConnect' | 'debug' | 'x402Version'>> = {\n facilitatorUrl: 'https://facilitator.ultravioletadao.xyz',\n defaultChain: 'base',\n autoConnect: false,\n debug: false,\n x402Version: 'auto',\n};\n\n// ============================================================================\n// BALANCE TYPES\n// ============================================================================\n\n/**\n * Balance information for a single network\n */\nexport interface NetworkBalance {\n /** Chain name */\n chainName: string;\n /** Human-readable display name */\n displayName: string;\n /** Formatted balance (e.g., \"15.50\") or null if loading/error */\n balance: string | null;\n /** Whether balance is currently being fetched */\n isLoading: boolean;\n /** Error message if fetch failed */\n error: string | null;\n}\n\n// ============================================================================\n// EVENT TYPES\n// ============================================================================\n\n/**\n * Events emitted by the SDK client\n */\nexport type X402Event =\n | 'connect'\n | 'disconnect'\n | 'chainChanged'\n | 'accountChanged'\n | 'balanceChanged'\n | 'paymentStarted'\n | 'paymentSigned'\n | 'paymentCompleted'\n | 'paymentFailed';\n\n/**\n * Event data types\n */\nexport interface X402EventData {\n connect: WalletState;\n disconnect: void;\n chainChanged: { chainId: number; chainName: string };\n accountChanged: { address: string };\n balanceChanged: { balance: string };\n paymentStarted: { amount: string; network: string };\n paymentSigned: { paymentHeader: string };\n paymentCompleted: PaymentResult;\n paymentFailed: { error: string; code: X402ErrorCode };\n}\n\n/**\n * Event handler type\n */\nexport type X402EventHandler<E extends X402Event> = (data: X402EventData[E]) => void;\n\n// ============================================================================\n// ERROR TYPES\n// ============================================================================\n\n/**\n * Error codes for categorizing errors\n */\nexport type X402ErrorCode =\n | 'WALLET_NOT_FOUND'\n | 'WALLET_NOT_CONNECTED'\n | 'WALLET_NOT_SUPPORTED'\n | 'WALLET_CONNECTION_FAILED'\n | 'WALLET_CONNECTION_REJECTED'\n | 'WALLET_CONNECTION_TIMEOUT'\n | 'CHAIN_NOT_SUPPORTED'\n | 'CHAIN_SWITCH_REJECTED'\n | 'INSUFFICIENT_BALANCE'\n | 'SIGNATURE_REJECTED'\n | 'PAYMENT_FAILED'\n | 'PAYMENT_TIMEOUT'\n | 'NETWORK_ERROR'\n | 'INVALID_CONFIG'\n | 'INVALID_AMOUNT'\n | 'INVALID_RECIPIENT'\n | 'UNKNOWN_ERROR';\n\n/**\n * SDK-specific error class\n */\nexport class X402Error extends Error {\n public readonly code: X402ErrorCode;\n public readonly details?: unknown;\n\n constructor(message: string, code: X402ErrorCode, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, X402Error);\n }\n }\n}\n","/**\n * uvd-x402-sdk - UTF-8 safe base64\n *\n * `btoa()` only accepts code points 0-255. Any character above that throws\n * `InvalidCharacterError`, and the X-PAYMENT payload is not guaranteed to be\n * ASCII: the EIP-712 domain name of USDT on Optimism and Arbitrum is literally\n * `USD₮0` (U+20AE). A header carrying that name crashes a plain `btoa()`.\n *\n * So the JSON is UTF-8 encoded to bytes first, and only then base64'd. Decoding\n * reverses it. For ASCII-only input the output is byte-identical to\n * `btoa(json)`, which is why swapping this in cannot change any existing header.\n *\n * `TextEncoder`/`TextDecoder` are available in every browser the SDK targets and\n * in Node 11+; `btoa`/`atob` are used for the byte<->base64 step because they\n * exist in both environments without pulling in `Buffer`.\n */\n\n/**\n * Encode a string as base64, handling non-ASCII characters correctly.\n *\n * @param value - Any UTF-8 string\n * @returns Base64-encoded value\n */\nexport function encodeBase64Utf8(value: string): string {\n const bytes = new TextEncoder().encode(value);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Decode a base64 string produced by {@link encodeBase64Utf8}.\n *\n * @param encoded - Base64-encoded value\n * @returns The original UTF-8 string\n */\nexport function decodeBase64Utf8(encoded: string): string {\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n\n/**\n * JSON-serialize a value and encode it as UTF-8 safe base64.\n *\n * This is the encoder for every X-PAYMENT header the SDK emits.\n *\n * @param value - Value to serialize\n * @returns Base64-encoded JSON\n */\nexport function encodeBase64Json(value: unknown): string {\n return encodeBase64Utf8(JSON.stringify(value));\n}\n","/**\n * uvd-x402-sdk - x402 Protocol Utilities\n *\n * Utilities for working with x402 v1 and v2 protocols.\n * Handles version detection, payload encoding, and CAIP-2 conversions.\n */\n\nimport type {\n X402Header,\n X402HeaderV1,\n X402HeaderV2,\n X402PayloadData,\n X402PaymentOption,\n X402Version,\n ChainConfig,\n} from '../types';\nimport { CAIP2_IDENTIFIERS, CAIP2_TO_CHAIN } from '../types';\nimport { getChainByName } from '../chains';\nimport { decodeBase64Utf8, encodeBase64Json } from './base64';\n\n/**\n * Detect x402 version from a response header or body\n *\n * @param data - The 402 response data (parsed JSON or header value)\n * @returns The detected version (1 or 2)\n */\nexport function detectX402Version(data: unknown): X402Version {\n if (typeof data === 'string') {\n // A `PAYMENT-REQUIRED` header value is base64 JSON, and the doc above\n // invites one. Returning 1 without decoding misread every v2 challenge as\n // v1 — silently, as a plausible value rather than an error, and the two\n // wire forms are structurally incompatible.\n //\n // This is not hypothetical: measured 2026-08-20, 36 of 36 live Bazaar\n // resources answering 402 carry the challenge in the header, and several\n // put a free content preview in the body, so the header is the only place\n // the version signal exists.\n const trimmed = data.trim();\n if (!trimmed) return 1;\n for (const decode of [\n () => JSON.parse(decodeBase64Utf8(trimmed)),\n () => JSON.parse(trimmed),\n ]) {\n try {\n const parsed = decode();\n if (typeof parsed === 'object' && parsed !== null) {\n return detectX402Version(parsed);\n }\n } catch {\n // not this encoding; try the next\n }\n }\n return 1; // undecodable: fall back to v1, as before\n }\n\n if (typeof data !== 'object' || data === null) {\n return 1; // Default to v1\n }\n\n const obj = data as Record<string, unknown>;\n\n // Check explicit version field\n if (obj.x402Version === 2) {\n return 2;\n }\n\n // Check for v2 indicators\n if (obj.accepts && Array.isArray(obj.accepts)) {\n return 2;\n }\n\n // `paymentRequirements` is the v1 spelling, so its presence points at v1 --\n // but only when there is no v2 signal, which the checks above already ruled\n // out. Recognised so the value is not treated as an unknown shape.\n if (Array.isArray(obj.paymentRequirements)) {\n return 1;\n }\n\n // Check if network is in CAIP-2 format\n if (typeof obj.network === 'string') {\n if (obj.network.includes(':')) {\n return 2;\n }\n }\n\n return 1;\n}\n\n/**\n * Convert chain name to CAIP-2 identifier\n *\n * @param chainName - Chain name (e.g., 'base', 'solana')\n * @returns CAIP-2 identifier (e.g., 'eip155:8453', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')\n */\nexport function chainToCAIP2(chainName: string): string {\n const caip2 = CAIP2_IDENTIFIERS[chainName.toLowerCase()];\n if (caip2) {\n return caip2;\n }\n\n // Try to construct from chain config\n const chain = getChainByName(chainName);\n if (chain) {\n if (chain.networkType === 'evm') {\n return `eip155:${chain.chainId}`;\n }\n // For non-EVM, return the name as-is with network prefix\n return `${chain.networkType}:${chainName}`;\n }\n\n return chainName; // Return as-is if unknown\n}\n\n/**\n * Convert CAIP-2 identifier to chain name\n *\n * @param caip2 - CAIP-2 identifier\n * @returns Chain name or null if unknown\n */\nexport function caip2ToChain(caip2: string): string | null {\n // Check direct mapping\n if (CAIP2_TO_CHAIN[caip2]) {\n return CAIP2_TO_CHAIN[caip2];\n }\n\n // Try to extract from EIP-155 format\n const match = caip2.match(/^eip155:(\\d+)$/);\n if (match) {\n const chainId = parseInt(match[1], 10);\n // Find chain by ID\n for (const [name, _config] of Object.entries(CAIP2_IDENTIFIERS)) {\n const chain = getChainByName(name);\n if (chain?.chainId === chainId) {\n return name;\n }\n }\n }\n\n // Try to extract from network:name format\n const parts = caip2.split(':');\n if (parts.length === 2) {\n const networkName = parts[1];\n if (getChainByName(networkName)) {\n return networkName;\n }\n }\n\n return null;\n}\n\n/**\n * Parse network identifier from either v1 or v2 format\n *\n * @param network - Network identifier (v1 string or v2 CAIP-2)\n * @returns Normalized chain name\n */\nexport function parseNetworkIdentifier(network: string): string {\n // If it contains a colon, it's likely CAIP-2\n if (network.includes(':')) {\n return caip2ToChain(network) || network;\n }\n return network.toLowerCase();\n}\n\n/**\n * Encode x402 payload as base64 header value\n *\n * @param header - The x402 header object\n * @returns Base64-encoded string\n */\nexport function encodeX402Header(header: X402Header): string {\n return encodeBase64Json(header);\n}\n\n/**\n * Decode x402 header from base64 string\n *\n * @param encoded - Base64-encoded header value\n * @returns Parsed x402 header\n */\nexport function decodeX402Header(encoded: string): X402Header {\n const json = decodeBase64Utf8(encoded);\n return JSON.parse(json) as X402Header;\n}\n\n/**\n * Create x402 v1 header\n *\n * @param network - Chain name (e.g., 'base')\n * @param payload - Network-specific payload\n * @returns x402 v1 header object\n */\nexport function createX402V1Header(\n network: string,\n payload: X402PayloadData\n): X402HeaderV1 {\n return {\n x402Version: 1,\n scheme: 'exact',\n network,\n payload,\n };\n}\n\n/**\n * Create x402 v2 header\n *\n * @param network - CAIP-2 network identifier\n * @param payload - Network-specific payload\n * @param accepts - Optional array of payment options\n * @returns x402 v2 header object\n */\nexport function createX402V2Header(\n network: string,\n payload: X402PayloadData,\n accepts?: X402PaymentOption[]\n): X402HeaderV2 {\n const header: X402HeaderV2 = {\n x402Version: 2,\n scheme: 'exact',\n network: network.includes(':') ? network : chainToCAIP2(network),\n payload,\n };\n\n if (accepts && accepts.length > 0) {\n header.accepts = accepts;\n }\n\n return header;\n}\n\n/**\n * Create x402 header with automatic version selection\n *\n * @param chainConfig - Chain configuration\n * @param payload - Network-specific payload\n * @param version - Version to use (1, 2, or 'auto')\n * @returns x402 header object\n */\nexport function createX402Header(\n chainConfig: ChainConfig,\n payload: X402PayloadData,\n version: X402Version | 'auto' = 'auto'\n): X402Header {\n // Default to v1 for maximum compatibility\n const effectiveVersion = version === 'auto' ? 1 : version;\n\n if (effectiveVersion === 2) {\n return createX402V2Header(chainConfig.name, payload);\n }\n\n return createX402V1Header(chainConfig.name, payload);\n}\n\n/**\n * Generate payment options array for multi-network support\n *\n * @param chainConfigs - Array of chain configurations\n * @param amount - Amount in USDC (e.g., \"10.00\")\n * @param facilitator - Optional facilitator URL override\n * @returns Array of x402 v2 payment options\n */\nexport function generatePaymentOptions(\n chainConfigs: ChainConfig[],\n amount: string,\n facilitator?: string\n): X402PaymentOption[] {\n // Convert amount to atomic units for each chain\n return chainConfigs\n .filter(chain => chain.x402.enabled)\n .map(chain => {\n const atomicAmount = Math.floor(\n parseFloat(amount) * Math.pow(10, chain.usdc.decimals)\n ).toString();\n\n return {\n network: chainToCAIP2(chain.name),\n asset: chain.usdc.address,\n amount: atomicAmount,\n facilitator: facilitator || chain.x402.facilitatorUrl,\n };\n });\n}\n\n/**\n * Check if a network string is in CAIP-2 format\n *\n * @param network - Network identifier\n * @returns True if CAIP-2 format\n */\nexport function isCAIP2Format(network: string): boolean {\n return network.includes(':');\n}\n\n/**\n * Convert between x402 v1 and v2 header formats\n *\n * @param header - Source header\n * @param targetVersion - Target version\n * @returns Converted header\n */\nexport function convertX402Header(\n header: X402Header,\n targetVersion: X402Version\n): X402Header {\n if (header.x402Version === targetVersion) {\n return header;\n }\n\n if (targetVersion === 2) {\n // v1 -> v2\n return {\n x402Version: 2,\n scheme: 'exact',\n network: chainToCAIP2(header.network),\n payload: header.payload,\n };\n } else {\n // v2 -> v1\n const chainName = isCAIP2Format(header.network)\n ? caip2ToChain(header.network) || header.network\n : header.network;\n\n return {\n x402Version: 1,\n scheme: 'exact',\n network: chainName,\n payload: header.payload,\n };\n }\n}\n\n/**\n * Read a 402 payment challenge from wherever the seller put it.\n *\n * x402 allows BOTH transports and sellers pick freely:\n *\n * - base64 JSON in the `PAYMENT-REQUIRED` (or `X-PAYMENT-REQUIRED`) header\n * - JSON in the response body\n *\n * Measured against production on 2026-08-20: of 40 live Bazaar resources,\n * **36 of 36 that answered 402 carried the challenge in the header, and none in\n * the body**. Worse, sellers like Tenjin use the 402 body for a free preview of\n * the paid content — so the body is valid JSON that simply has no `accepts`, and\n * a body-only reader parses it happily and finds nothing.\n *\n * Reads the header first because that is where live sellers put it, and falls\n * back to the body so the sellers who use it keep working.\n *\n * Returns `null` when neither transport carries a challenge — a real \"no terms\n * here\", distinct from a challenge we failed to decode.\n */\nexport function paymentChallengeFrom(\n headers: { get(name: string): string | null } | Record<string, string>,\n body?: unknown,\n): Record<string, unknown> | null {\n const read = (name: string): string | null => {\n if (typeof (headers as { get?: unknown }).get === 'function') {\n return (headers as { get(n: string): string | null }).get(name);\n }\n const rec = headers as Record<string, string>;\n return rec[name] ?? rec[name.toLowerCase()] ?? rec[name.toUpperCase()] ?? null;\n };\n\n const raw = read('payment-required') ?? read('x-payment-required');\n if (raw) {\n const trimmed = raw.trim();\n for (const decode of [\n () => JSON.parse(decodeBase64Utf8(trimmed)),\n () => JSON.parse(trimmed),\n ]) {\n try {\n const parsed = decode();\n if (isChallenge(parsed)) return parsed as Record<string, unknown>;\n } catch {\n // not this encoding; try the next\n }\n }\n }\n\n const parsedBody = typeof body === 'string' ? tryJson(body) : body;\n return isChallenge(parsedBody) ? (parsedBody as Record<string, unknown>) : null;\n}\n\n/**\n * Whether a value actually looks like an x402 challenge.\n *\n * Deliberately stricter than \"is an object\": a 402 body carrying a free preview\n * is valid JSON with no payment terms in it, and treating that as a challenge is\n * how a body-only reader concludes it looked and found nothing wrong.\n */\nfunction isChallenge(v: unknown): boolean {\n if (typeof v !== 'object' || v === null) return false;\n const o = v as Record<string, unknown>;\n // `paymentRequirements` is the v1 spelling of `accepts`. Missing it made a\n // seller using it look like \"no terms here\" — the exact false negative this\n // function exists to prevent. Found in the Python SDK by KarmaKadabra's\n // buyer, which matched both keys in production, 2026-08-20.\n return (\n Array.isArray(o.accepts) ||\n Array.isArray(o.paymentRequirements) ||\n typeof o.payTo === 'string'\n );\n}\n\nfunction tryJson(s: string): unknown {\n try {\n return JSON.parse(s);\n } catch {\n return null;\n }\n}\n","/**\n * uvd-x402-sdk - Token metadata for payment payloads\n *\n * An EIP-3009 authorization is signed against a token contract, but the encoded\n * payload only carries the signature and the transfer fields. The token itself\n * is implicit — the server is expected to already know which asset it asked\n * for.\n *\n * That holds when a resource accepts exactly one token per chain. It breaks as\n * soon as it accepts several: a EURC payment and a USDC payment on Base produce\n * indistinguishable payloads, and the server cannot build the\n * `paymentRequirements` (`asset` + `extra`) the facilitator needs to settle.\n *\n * So the payment can opt into carrying the token with it.\n */\n\nimport { getTokenByAddress } from '../chains';\nimport type { PaymentTokenMetadata } from '../types';\n\n/**\n * Build the token metadata block for a payload, resolving the address against\n * the chain registry.\n *\n * @param chainName - Chain the payment was signed for\n * @param address - Token contract address from the signed payload\n * @returns Metadata block, or undefined if the address is not in the registry\n */\nexport function buildTokenMetadata(\n chainName: string,\n address: string\n): PaymentTokenMetadata | undefined {\n const match = getTokenByAddress(chainName, address);\n if (!match) return undefined;\n\n return {\n address: match.config.address,\n symbol: match.tokenType.toUpperCase(),\n decimals: match.config.decimals,\n eip712: {\n name: match.config.name,\n version: match.config.version,\n },\n };\n}\n","/**\n * uvd-x402-sdk - Validation and Payment Header Utilities\n *\n * Functions for validating payment parameters and creating\n * payment headers for HTTP requests.\n */\n\nimport type { X402HeaderName, PaymentHeaders } from '../types';\nimport { X402Error } from '../types';\n\n/**\n * Regular expression for validating Ethereum addresses\n */\nconst ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;\n\n/**\n * Regular expression for validating Solana addresses (base58, 32-44 chars)\n */\nconst SOLANA_ADDRESS_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\n/**\n * Regular expression for validating Stellar addresses (G... format)\n */\nconst STELLAR_ADDRESS_REGEX = /^G[A-Z2-7]{55}$/;\n\n/**\n * Regular expression for validating NEAR addresses\n */\nconst NEAR_ADDRESS_REGEX = /^[a-z0-9._-]+$/;\n\n/**\n * Regular expression for validating XRPL classic addresses (r... base58, Ripple alphabet)\n */\nconst XRPL_ADDRESS_REGEX = /^r[1-9A-HJ-NP-Za-km-z]{24,34}$/;\n\n/**\n * Validate that a recipient address is present and valid\n *\n * This function ensures that:\n * 1. The recipient is not null, undefined, or empty\n * 2. The recipient is not just whitespace\n * 3. For EVM, it's a valid checksummed or lowercase 0x address\n *\n * @param recipient - The recipient address to validate\n * @param networkType - Optional network type for format validation\n * @throws X402Error with code 'INVALID_RECIPIENT' if validation fails\n */\nexport function validateRecipient(\n recipient: string | undefined | null,\n networkType?: 'evm' | 'svm' | 'solana' | 'stellar' | 'near' | 'xrpl'\n): asserts recipient is string {\n // Check for null, undefined, or empty\n if (!recipient) {\n throw new X402Error(\n 'Recipient address is required. The payTo/recipient field cannot be empty. ' +\n 'Please provide a valid recipient address where payments should be sent.',\n 'INVALID_RECIPIENT'\n );\n }\n\n // Check for whitespace-only\n const trimmed = recipient.trim();\n if (trimmed === '') {\n throw new X402Error(\n 'Recipient address cannot be empty or whitespace. ' +\n 'Please provide a valid recipient address.',\n 'INVALID_RECIPIENT'\n );\n }\n\n // Network-specific validation\n if (networkType) {\n switch (networkType) {\n case 'evm':\n if (!ETH_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid EVM recipient address: \"${trimmed}\". ` +\n 'Expected a 40-character hexadecimal address starting with 0x.',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'svm':\n case 'solana':\n if (!SOLANA_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid Solana recipient address: \"${trimmed}\". ` +\n 'Expected a base58-encoded public key (32-44 characters).',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'stellar':\n if (!STELLAR_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid Stellar recipient address: \"${trimmed}\". ` +\n 'Expected a G-prefixed public key (56 characters).',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'near':\n if (!NEAR_ADDRESS_REGEX.test(trimmed) || trimmed.length > 64) {\n throw new X402Error(\n `Invalid NEAR recipient address: \"${trimmed}\". ` +\n 'Expected a valid NEAR account ID.',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'xrpl':\n if (!XRPL_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid XRPL recipient address: \"${trimmed}\". ` +\n 'Expected a classic r-address (base58, Ripple alphabet).',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n }\n }\n}\n\n/**\n * Validate payment amount\n *\n * Ensures the amount is a valid positive number string\n *\n * @param amount - The amount string to validate\n * @throws X402Error with code 'INVALID_AMOUNT' if validation fails\n */\nexport function validateAmount(amount: string | undefined | null): asserts amount is string {\n if (!amount) {\n throw new X402Error(\n 'Payment amount is required.',\n 'INVALID_AMOUNT'\n );\n }\n\n const trimmed = amount.trim();\n if (trimmed === '') {\n throw new X402Error(\n 'Payment amount cannot be empty.',\n 'INVALID_AMOUNT'\n );\n }\n\n // Parse as number\n const num = parseFloat(trimmed);\n if (isNaN(num)) {\n throw new X402Error(\n `Invalid payment amount: \"${trimmed}\". Expected a valid number.`,\n 'INVALID_AMOUNT'\n );\n }\n\n if (num <= 0) {\n throw new X402Error(\n `Payment amount must be positive. Got: ${trimmed}`,\n 'INVALID_AMOUNT'\n );\n }\n}\n\n// ============================================================================\n// PAYMENT HEADER UTILITIES\n// ============================================================================\n\n/**\n * Create payment headers object from a base64-encoded payload\n *\n * Returns an object with both X-PAYMENT and PAYMENT-SIGNATURE headers,\n * making it easy to use either header format.\n *\n * @param paymentHeader - Base64-encoded payment payload\n * @returns PaymentHeaders object with both header formats\n *\n * @example\n * ```ts\n * const headers = createPaymentHeaders(paymentHeader);\n *\n * // Use v1 header (most compatible)\n * fetch(url, { headers: { 'X-PAYMENT': headers['X-PAYMENT'] } });\n *\n * // Use v2 header\n * fetch(url, { headers: { 'PAYMENT-SIGNATURE': headers['PAYMENT-SIGNATURE'] } });\n * ```\n */\nexport function createPaymentHeaders(paymentHeader: string): PaymentHeaders {\n return {\n 'X-PAYMENT': paymentHeader,\n 'PAYMENT-SIGNATURE': paymentHeader,\n };\n}\n\n/**\n * Get a single payment header by name\n *\n * @param paymentHeader - Base64-encoded payment payload\n * @param headerName - Header name to use ('X-PAYMENT' or 'PAYMENT-SIGNATURE')\n * @returns Object with a single header entry\n *\n * @example\n * ```ts\n * // Use with fetch spread operator\n * fetch(url, {\n * headers: {\n * 'Content-Type': 'application/json',\n * ...getPaymentHeader(result.paymentHeader, 'X-PAYMENT'),\n * },\n * });\n * ```\n */\nexport function getPaymentHeader(\n paymentHeader: string,\n headerName: X402HeaderName = 'X-PAYMENT'\n): Record<X402HeaderName, string> {\n return { [headerName]: paymentHeader } as Record<X402HeaderName, string>;\n}\n\n/**\n * Default x402 payment header name\n *\n * Use 'X-PAYMENT' for maximum compatibility with all facilitators.\n * Use 'PAYMENT-SIGNATURE' for x402 v2 compliance.\n */\nexport const DEFAULT_PAYMENT_HEADER: X402HeaderName = 'X-PAYMENT';\n\n/**\n * All supported x402 payment header names\n */\nexport const PAYMENT_HEADER_NAMES: readonly X402HeaderName[] = [\n 'X-PAYMENT',\n 'PAYMENT-SIGNATURE',\n] as const;\n","/**\n * uvd-x402-sdk - Main Client\n *\n * The X402Client is the primary entry point for the SDK.\n * It manages wallet connections, chain switching, and payment creation.\n */\n\nimport { ethers } from 'ethers';\nimport type {\n ChainConfig,\n NetworkType,\n PaymentInfo,\n PaymentResult,\n WalletState,\n X402ClientConfig,\n X402Event,\n X402EventData,\n X402EventHandler,\n EVMPaymentPayload,\n TokenType,\n X402EVMPayload,\n} from '../types';\nimport { X402Error, DEFAULT_CONFIG } from '../types';\nimport {\n SUPPORTED_CHAINS,\n getChainByName,\n getChainById,\n getEnabledChains,\n getTokenConfig,\n} from '../chains';\nimport {\n validateRecipient,\n chainToCAIP2,\n encodeBase64Json,\n buildTokenMetadata,\n} from '../utils';\n\n/**\n * X402Client - Main SDK client for x402 payments\n *\n * @example\n * ```ts\n * import { X402Client } from 'uvd-x402-sdk';\n *\n * const client = new X402Client({ defaultChain: 'base' });\n *\n * // Connect wallet\n * await client.connect('base');\n *\n * // Create payment\n * const result = await client.createPayment({\n * recipient: '0x...',\n * amount: '10.00',\n * });\n *\n * // Use result.paymentHeader in your API request\n * ```\n */\nexport class X402Client {\n // Configuration\n private readonly config: Required<Pick<X402ClientConfig, 'facilitatorUrl' | 'defaultChain' | 'autoConnect' | 'debug'>> & X402ClientConfig;\n\n // Wallet state\n private provider: ethers.BrowserProvider | ethers.JsonRpcProvider | null = null;\n private signer: ethers.Signer | null = null;\n private connectedAddress: string | null = null;\n private currentChainId: number | null = null;\n private currentNetwork: NetworkType | null = null;\n private currentChainName: string | null = null;\n\n // Event emitter\n private eventHandlers: Map<X402Event, Set<X402EventHandler<X402Event>>> = new Map();\n\n constructor(config: X402ClientConfig = {}) {\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n };\n\n // Apply custom RPC overrides\n if (config.rpcOverrides) {\n for (const [chainName, rpcUrl] of Object.entries(config.rpcOverrides)) {\n if (SUPPORTED_CHAINS[chainName]) {\n SUPPORTED_CHAINS[chainName].rpcUrl = rpcUrl;\n }\n }\n }\n\n // Apply custom chain configurations\n if (config.customChains) {\n for (const [chainName, chainConfig] of Object.entries(config.customChains)) {\n if (SUPPORTED_CHAINS[chainName]) {\n Object.assign(SUPPORTED_CHAINS[chainName], chainConfig);\n }\n }\n }\n\n this.log('X402Client initialized', { config: this.config });\n }\n\n // ============================================================================\n // PUBLIC API - Wallet Connection\n // ============================================================================\n\n /**\n * Connect to a wallet on the specified chain\n */\n async connect(chainName?: string): Promise<string> {\n const targetChain = chainName || this.config.defaultChain;\n const chain = getChainByName(targetChain);\n\n if (!chain) {\n throw new X402Error(`Unsupported chain: ${targetChain}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (!chain.x402.enabled) {\n throw new X402Error(`Chain ${targetChain} is not enabled for x402 payments`, 'CHAIN_NOT_SUPPORTED');\n }\n\n this.log(`Connecting wallet on ${chain.displayName}...`);\n\n // Route to appropriate connection method based on network type\n switch (chain.networkType) {\n case 'evm':\n return this.connectEVMWallet(chain);\n case 'solana':\n throw new X402Error(\n 'Solana support requires importing from \"uvd-x402-sdk/solana\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n case 'stellar':\n throw new X402Error(\n 'Stellar support requires importing from \"uvd-x402-sdk/stellar\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n case 'near':\n throw new X402Error(\n 'NEAR support requires importing from \"uvd-x402-sdk/near\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n case 'xrpl':\n throw new X402Error(\n 'XRPL support requires importing from \"uvd-x402-sdk/xrpl\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n default:\n throw new X402Error(`Unknown network type for chain ${targetChain}`, 'CHAIN_NOT_SUPPORTED');\n }\n }\n\n /**\n * Connect using a private key (Node.js / server-side, no browser wallet needed)\n */\n async connectWithPrivateKey(privateKey: string, chainName?: string): Promise<string> {\n const targetChain = chainName || this.config.defaultChain;\n const chain = getChainByName(targetChain);\n\n if (!chain) {\n throw new X402Error(`Unsupported chain: ${targetChain}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (!chain.x402.enabled) {\n throw new X402Error(`Chain ${targetChain} is not enabled for x402 payments`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error('connectWithPrivateKey is only supported for EVM chains', 'CHAIN_NOT_SUPPORTED');\n }\n\n this.log(`Connecting with private key on ${chain.displayName}...`);\n\n const rpcProvider = new ethers.JsonRpcProvider(chain.rpcUrl);\n const wallet = new ethers.Wallet(privateKey, rpcProvider);\n\n this.provider = rpcProvider;\n this.signer = wallet;\n this.connectedAddress = wallet.address;\n this.currentChainId = chain.chainId;\n this.currentNetwork = 'evm';\n this.currentChainName = chain.name;\n\n const state = this.getState();\n this.emit('connect', state);\n this.log('Private key wallet connected', { address: this.connectedAddress, chain: chain.name });\n\n return this.connectedAddress;\n }\n\n /**\n * Disconnect the current wallet\n */\n async disconnect(): Promise<void> {\n this.provider = null;\n this.signer = null;\n this.connectedAddress = null;\n this.currentChainId = null;\n this.currentNetwork = null;\n this.currentChainName = null;\n\n this.emit('disconnect', undefined);\n this.log('Wallet disconnected');\n }\n\n /**\n * Switch to a different chain (EVM only)\n */\n async switchChain(chainName: string): Promise<void> {\n const chain = getChainByName(chainName);\n\n if (!chain) {\n throw new X402Error(`Unsupported chain: ${chainName}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error(\n 'switchChain is only supported for EVM networks. Reconnect with connect() for other networks.',\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n\n if (!this.provider) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n // Private key connections cannot use wallet_switchEthereumChain — re-create provider\n if (this.provider instanceof ethers.JsonRpcProvider && this.signer instanceof ethers.Wallet) {\n const rpcProvider = new ethers.JsonRpcProvider(chain.rpcUrl);\n const wallet = new ethers.Wallet(this.signer.privateKey, rpcProvider);\n this.provider = rpcProvider;\n this.signer = wallet;\n this.currentChainId = chain.chainId;\n this.currentChainName = chain.name;\n this.emit('chainChanged', { chainId: chain.chainId, chainName: chain.name });\n this.log('Switched chain (private key mode)', { chain: chain.name });\n return;\n }\n\n await this.switchEVMChain(chain);\n }\n\n // ============================================================================\n // PUBLIC API - Payment Creation\n // ============================================================================\n\n /**\n * Create a payment authorization\n *\n * @param paymentInfo - Payment information from 402 response\n * @returns Payment result with encoded X-PAYMENT header\n */\n async createPayment(paymentInfo: PaymentInfo): Promise<PaymentResult> {\n if (!this.connectedAddress) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n if (!this.currentChainName) {\n throw new X402Error('Chain not set', 'CHAIN_NOT_SUPPORTED');\n }\n\n const chain = getChainByName(this.currentChainName);\n if (!chain) {\n throw new X402Error(`Chain ${this.currentChainName} not found`, 'CHAIN_NOT_SUPPORTED');\n }\n\n this.emit('paymentStarted', { amount: paymentInfo.amount, network: chain.name });\n this.log('Creating payment...', { paymentInfo, chain: chain.name });\n\n try {\n // Route to appropriate payment method\n switch (chain.networkType) {\n case 'evm':\n return await this.createEVMPayment(paymentInfo, chain);\n default:\n throw new X402Error(\n `Payment creation for ${chain.networkType} requires the appropriate provider`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n } catch (error) {\n const x402Error = error instanceof X402Error\n ? error\n : new X402Error(\n error instanceof Error ? error.message : 'Unknown error',\n 'PAYMENT_FAILED',\n error\n );\n\n this.emit('paymentFailed', { error: x402Error.message, code: x402Error.code });\n throw x402Error;\n }\n }\n\n /**\n * Check USDC balance on current chain\n */\n async getBalance(): Promise<string> {\n if (!this.connectedAddress || !this.currentChainName) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n const chain = getChainByName(this.currentChainName);\n if (!chain) {\n throw new X402Error(`Chain ${this.currentChainName} not found`, 'CHAIN_NOT_SUPPORTED');\n }\n\n switch (chain.networkType) {\n case 'evm':\n return this.getEVMBalance(chain);\n default:\n throw new X402Error(\n `Balance check for ${chain.networkType} requires the appropriate provider`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n }\n\n // ============================================================================\n // PUBLIC API - Getters\n // ============================================================================\n\n /**\n * Get current wallet state\n */\n getState(): WalletState {\n return {\n connected: this.connectedAddress !== null,\n address: this.connectedAddress,\n chainId: this.currentChainId,\n network: this.currentChainName,\n networkType: this.currentNetwork,\n balance: null, // Call getBalance() separately\n };\n }\n\n /**\n * Get connected wallet address\n */\n getAddress(): string | null {\n return this.connectedAddress;\n }\n\n /**\n * Get current chain ID\n */\n getChainId(): number | null {\n return this.currentChainId;\n }\n\n /**\n * Get current chain name\n */\n getChainName(): string | null {\n return this.currentChainName;\n }\n\n /**\n * Get current chain display name\n */\n getChainDisplayName(): string | null {\n if (!this.currentChainName) return null;\n const chain = getChainByName(this.currentChainName);\n return chain?.displayName ?? null;\n }\n\n /**\n * Check if wallet is connected\n */\n isConnected(): boolean {\n return this.connectedAddress !== null;\n }\n\n /**\n * Get list of enabled chains\n */\n getEnabledChains(): ChainConfig[] {\n return getEnabledChains();\n }\n\n /**\n * Get chain config by name\n */\n getChain(name: string): ChainConfig | undefined {\n return getChainByName(name);\n }\n\n // ============================================================================\n // PUBLIC API - Events\n // ============================================================================\n\n /**\n * Subscribe to an event\n */\n on<E extends X402Event>(event: E, handler: X402EventHandler<E>): () => void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler as X402EventHandler<X402Event>);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off<E extends X402Event>(event: E, handler: X402EventHandler<E>): void {\n this.eventHandlers.get(event)?.delete(handler as X402EventHandler<X402Event>);\n }\n\n // ============================================================================\n // PRIVATE - EVM Wallet Connection\n // ============================================================================\n\n private async connectEVMWallet(chain: ChainConfig): Promise<string> {\n // Check for injected provider\n if (typeof window === 'undefined' || !window.ethereum) {\n throw new X402Error(\n 'No Ethereum wallet found. Please install MetaMask or another EVM wallet.',\n 'WALLET_NOT_FOUND'\n );\n }\n\n try {\n this.provider = new ethers.BrowserProvider(window.ethereum);\n\n // Request account access\n await this.provider.send('eth_requestAccounts', []);\n\n // Switch to target chain\n await this.switchEVMChain(chain);\n\n // Get signer and address\n this.signer = await this.provider.getSigner();\n this.connectedAddress = await this.signer.getAddress();\n this.currentChainId = chain.chainId;\n this.currentNetwork = 'evm';\n this.currentChainName = chain.name;\n\n // Setup event listeners\n this.setupEVMEventListeners();\n\n const state = this.getState();\n this.emit('connect', state);\n this.log('EVM wallet connected', { address: this.connectedAddress, chain: chain.name });\n\n return this.connectedAddress;\n } catch (error: unknown) {\n if (error instanceof Error) {\n if (error.message.includes('User rejected') || (error as { code?: number }).code === 4001) {\n throw new X402Error('Connection rejected by user', 'WALLET_CONNECTION_REJECTED');\n }\n }\n throw new X402Error(\n `Failed to connect wallet: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'UNKNOWN_ERROR',\n error\n );\n }\n }\n\n private async switchEVMChain(chain: ChainConfig): Promise<void> {\n if (!this.provider) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n try {\n await this.provider.send('wallet_switchEthereumChain', [{ chainId: chain.chainIdHex }]);\n } catch (switchError: unknown) {\n // Chain not added - try to add it\n if ((switchError as { code?: number }).code === 4902) {\n try {\n await this.provider.send('wallet_addEthereumChain', [\n {\n chainId: chain.chainIdHex,\n chainName: chain.displayName,\n nativeCurrency: chain.nativeCurrency,\n rpcUrls: [chain.rpcUrl],\n blockExplorerUrls: [chain.explorerUrl],\n },\n ]);\n } catch (addError) {\n throw new X402Error(\n `Failed to add ${chain.displayName} network`,\n 'CHAIN_SWITCH_REJECTED',\n addError\n );\n }\n } else if ((switchError as { code?: number }).code === 4001) {\n throw new X402Error('Network switch rejected by user', 'CHAIN_SWITCH_REJECTED');\n } else {\n throw new X402Error(\n `Failed to switch to ${chain.displayName}`,\n 'CHAIN_SWITCH_REJECTED',\n switchError\n );\n }\n }\n\n this.currentChainId = chain.chainId;\n this.currentChainName = chain.name;\n this.emit('chainChanged', { chainId: chain.chainId, chainName: chain.name });\n }\n\n private setupEVMEventListeners(): void {\n if (typeof window === 'undefined' || !window.ethereum) return;\n\n window.ethereum.on?.('accountsChanged', ((...args: unknown[]) => {\n const accounts = args[0] as string[];\n if (accounts.length === 0) {\n this.disconnect();\n } else if (accounts[0] !== this.connectedAddress) {\n this.connectedAddress = accounts[0];\n this.emit('accountChanged', { address: accounts[0] });\n }\n }) as (...args: unknown[]) => void);\n\n window.ethereum.on?.('chainChanged', ((...args: unknown[]) => {\n const chainIdHex = args[0] as string;\n const chainId = parseInt(chainIdHex, 16);\n const chain = getChainById(chainId);\n if (chain) {\n this.currentChainId = chainId;\n this.currentChainName = chain.name;\n this.emit('chainChanged', { chainId, chainName: chain.name });\n }\n }) as (...args: unknown[]) => void);\n }\n\n // ============================================================================\n // PRIVATE - EVM Payment Creation\n // ============================================================================\n\n private async createEVMPayment(paymentInfo: PaymentInfo, chain: ChainConfig): Promise<PaymentResult> {\n if (!this.signer) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n // Get recipient address for EVM\n const recipient = this.getRecipientForNetwork(paymentInfo, 'evm');\n\n // Validate recipient address - prevents empty/invalid addresses\n validateRecipient(recipient, 'evm');\n\n // Which stablecoin to charge. Defaults to USDC so existing callers are\n // unaffected; anything else is resolved from the chain's token registry.\n const tokenType: TokenType = paymentInfo.tokenType || 'usdc';\n const token = getTokenConfig(chain.name, tokenType);\n if (!token) {\n throw new X402Error(\n `Token ${tokenType} not supported on ${chain.name}`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n\n // Generate random nonce\n const nonceBytes = new Uint8Array(32);\n if (typeof window !== 'undefined' && window.crypto) {\n window.crypto.getRandomValues(nonceBytes);\n } else {\n for (let i = 0; i < 32; i++) {\n nonceBytes[i] = Math.floor(Math.random() * 256);\n }\n }\n const nonce = ethers.hexlify(nonceBytes);\n\n // Set validity window (5 minutes for congested networks, 1 minute otherwise)\n const validAfter = 0;\n const validityWindowSeconds = chain.name === 'base' ? 300 : 60;\n const validBefore = Math.floor(Date.now() / 1000) + validityWindowSeconds;\n\n // EIP-712 domain of the token being charged\n const domain = {\n name: token.name,\n version: token.version,\n chainId: chain.chainId,\n verifyingContract: token.address,\n };\n\n // EIP-712 types for TransferWithAuthorization (ERC-3009)\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 // Parse amount in the token's own decimals\n const value = ethers.parseUnits(paymentInfo.amount, token.decimals);\n const from = await this.signer.getAddress();\n const to = ethers.getAddress(recipient);\n\n // Message to sign\n const message = {\n from,\n to,\n value,\n validAfter,\n validBefore,\n nonce,\n };\n\n this.log('Signing EIP-712 message...', { domain, message });\n\n // Sign the EIP-712 message\n let signature: string;\n try {\n signature = await this.signer.signTypedData(domain, types, message);\n } catch (error: unknown) {\n if (error instanceof Error && (error.message.includes('User rejected') || (error as { code?: number }).code === 4001)) {\n throw new X402Error('Signature rejected by user', 'SIGNATURE_REJECTED');\n }\n throw new X402Error(\n `Failed to sign payment: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error\n );\n }\n\n const sig = ethers.Signature.from(signature);\n\n // Construct payload\n const payload: EVMPaymentPayload = {\n from,\n to,\n value: value.toString(),\n validAfter,\n validBefore,\n nonce,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n chainId: chain.chainId,\n token: token.address,\n };\n\n // Encode as X-PAYMENT header\n const paymentHeader = this.encodeEVMPaymentHeader(payload, chain);\n\n this.emit('paymentSigned', { paymentHeader });\n\n const result: PaymentResult = {\n success: true,\n paymentHeader,\n headers: {\n 'X-PAYMENT': paymentHeader,\n 'PAYMENT-SIGNATURE': paymentHeader,\n },\n network: chain.name,\n payer: from,\n };\n\n this.emit('paymentCompleted', result);\n this.log('Payment created successfully', { network: chain.name, from });\n\n return result;\n }\n\n private encodeEVMPaymentHeader(payload: EVMPaymentPayload, chain: ChainConfig): string {\n // Reconstruct full signature from v, r, s\n const fullSignature = payload.r + payload.s.slice(2) + payload.v.toString(16).padStart(2, '0');\n\n // Determine version to use (default to v1 for backward compatibility)\n const version = this.config.x402Version === 2 ? 2 : 1;\n\n // Build the payload data\n const payloadData: X402EVMPayload = {\n signature: fullSignature,\n authorization: {\n from: payload.from,\n to: payload.to,\n value: payload.value,\n validAfter: payload.validAfter.toString(),\n validBefore: payload.validBefore.toString(),\n nonce: payload.nonce,\n },\n };\n\n if (this.config.includeTokenMetadata) {\n const token = buildTokenMetadata(chain.name, payload.token);\n if (!token) {\n throw new X402Error(\n `Token ${payload.token} is not in the registry for ${chain.name}; cannot build token metadata`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n payloadData.token = token;\n }\n\n // Format in x402 standard format (v1 or v2)\n const x402Payload = version === 2\n ? {\n x402Version: 2 as const,\n scheme: 'exact' as const,\n network: chainToCAIP2(chain.name), // CAIP-2 format for v2\n payload: payloadData,\n }\n : {\n x402Version: 1 as const,\n scheme: 'exact' as const,\n network: chain.name, // Plain chain name for v1\n payload: payloadData,\n };\n\n // Base64 encode (UTF-8 safe: token domain names like `USD₮0` are not ASCII)\n return encodeBase64Json(x402Payload);\n }\n\n // ============================================================================\n // PRIVATE - EVM Balance Check\n // ============================================================================\n\n private async getEVMBalance(chain: ChainConfig): Promise<string> {\n // Use public RPC for balance check (more reliable than wallet provider)\n const publicProvider = new ethers.JsonRpcProvider(chain.rpcUrl);\n\n const usdcAbi = ['function balanceOf(address owner) view returns (uint256)'];\n const usdcContract = new ethers.Contract(chain.usdc.address, usdcAbi, publicProvider);\n\n try {\n const balance = await usdcContract.balanceOf(this.connectedAddress);\n const formatted = ethers.formatUnits(balance, chain.usdc.decimals);\n return parseFloat(formatted).toFixed(2);\n } catch {\n return '0.00';\n }\n }\n\n // ============================================================================\n // PRIVATE - Utilities\n // ============================================================================\n\n private getRecipientForNetwork(paymentInfo: PaymentInfo, network: NetworkType): string {\n // Map SVM to solana for recipient lookup\n const lookupNetwork = network === 'svm' ? 'solana' : network;\n const recipients = paymentInfo.recipients as Record<string, string> | undefined;\n if (recipients?.[lookupNetwork]) {\n return recipients[lookupNetwork];\n }\n return paymentInfo.recipient;\n }\n\n private emit<E extends X402Event>(event: E, data: X402EventData[E]): void {\n this.eventHandlers.get(event)?.forEach(handler => {\n try {\n handler(data);\n } catch (error) {\n console.error(`Error in ${event} handler:`, error);\n }\n });\n }\n\n private log(message: string, data?: unknown): void {\n if (this.config.debug) {\n console.log(`[X402Client] ${message}`, data ?? '');\n }\n }\n}\n\n// Type augmentation for window.ethereum\ndeclare global {\n interface Window {\n ethereum?: {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n on?: (event: string, handler: (...args: unknown[]) => void) => void;\n removeListener?: (event: string, handler: (...args: unknown[]) => void) => void;\n };\n }\n}\n","/**\n * uvd-x402-sdk - EnvKeyAdapter\n *\n * SigningWalletAdapter implementation using a raw private key.\n * Reads the key from a constructor parameter or the WALLET_PRIVATE_KEY\n * environment variable.\n *\n * Intended for server-side / CLI / agent use cases where the\n * signing key is available in the environment. NEVER use this\n * in browser contexts -- use OWSWalletAdapter instead.\n *\n * @example Using environment variable\n * ```ts\n * // Reads process.env.WALLET_PRIVATE_KEY\n * const wallet = new EnvKeyAdapter();\n * console.log(wallet.getAddress()); // 0x...\n * ```\n *\n * @example Using explicit key\n * ```ts\n * const wallet = new EnvKeyAdapter(process.env.MY_AGENT_KEY!);\n * const auth = await wallet.signEIP3009({\n * to: '0xRecipient',\n * amountUsdc: 0.10,\n * network: 'base',\n * });\n * ```\n */\n\nimport { ethers } from 'ethers';\nimport { getChainByName } from '../chains';\nimport { X402Error } from '../types';\nimport type {\n SigningWalletAdapter,\n EIP3009Params,\n EIP3009Authorization,\n} from '../wallet';\n\n/**\n * EnvKeyAdapter -- SigningWalletAdapter backed by a raw private key.\n */\nexport class EnvKeyAdapter implements SigningWalletAdapter {\n private readonly wallet: ethers.Wallet;\n\n /**\n * Create an EnvKeyAdapter.\n *\n * @param privateKey - Hex-encoded private key (with or without 0x prefix).\n * If omitted, reads from `process.env.WALLET_PRIVATE_KEY`.\n * @throws {X402Error} if no private key is available\n */\n constructor(privateKey?: string) {\n const key = privateKey || (typeof process !== 'undefined' ? process.env.WALLET_PRIVATE_KEY : undefined);\n\n if (!key) {\n throw new X402Error(\n 'No private key provided. Pass it to the constructor or set WALLET_PRIVATE_KEY env var.',\n 'WALLET_NOT_CONNECTED',\n );\n }\n\n this.wallet = new ethers.Wallet(key);\n }\n\n /**\n * Get the checksummed EVM wallet address.\n */\n getAddress(): string {\n return this.wallet.address;\n }\n\n /**\n * Sign a message using EIP-191 personal_sign.\n *\n * @param message - The message string to sign\n * @returns Hex-encoded signature\n */\n async signMessage(message: string): Promise<string> {\n return this.wallet.signMessage(message);\n }\n\n /**\n * Sign EIP-712 typed structured data.\n *\n * @param typedData - JSON string with `domain`, `types`, `primaryType`, and `message` fields\n * @returns Object with signature and v/r/s components\n */\n async signTypedData(typedData: string): Promise<{\n signature: string;\n v: number;\n r: string;\n s: string;\n }> {\n const parsed = JSON.parse(typedData) as {\n domain: ethers.TypedDataDomain;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n };\n\n // ethers v6 signTypedData does not take primaryType -- it infers it\n // from the types object (the type not listed as a field of another type).\n // We pass domain, types (without EIP712Domain), and the message value.\n const { domain, types, message } = parsed;\n\n // Remove EIP712Domain from types if present (ethers handles it via domain)\n const cleanTypes = { ...types };\n delete cleanTypes['EIP712Domain'];\n\n const signature = await this.wallet.signTypedData(domain, cleanTypes, message);\n const sig = ethers.Signature.from(signature);\n\n return {\n signature,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n };\n }\n\n /**\n * Sign a serialized EVM transaction.\n *\n * Uses the raw private key via ethers.Wallet.signTransaction().\n * Used by AdvancedEscrowClient for on-chain operations (release,\n * refund, charge) when constructed with a SigningWalletAdapter.\n *\n * @param unsignedTx - Hex-encoded unsigned transaction (ethers serialized)\n * @returns Hex-encoded signed raw transaction, ready for broadcast\n */\n async signTransaction(unsignedTx: string): Promise<string> {\n const tx = ethers.Transaction.from(unsignedTx);\n return this.wallet.signTransaction(tx);\n }\n\n /**\n * Sign an EIP-3009 ReceiveWithAuthorization for USDC.\n *\n * @param params - EIP-3009 parameters\n * @returns Signed authorization ready for facilitator relay\n */\n async signEIP3009(params: EIP3009Params): Promise<EIP3009Authorization> {\n const chain = getChainByName(params.network);\n if (!chain) {\n throw new X402Error(`Unsupported network: ${params.network}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error(\n `EIP-3009 is only supported on EVM chains. ${params.network} is ${chain.networkType}.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n }\n\n const chainId = params.chainId ?? chain.chainId;\n const usdcAddress = params.usdcContract ?? chain.usdc.address;\n const from = this.wallet.address;\n const to = ethers.getAddress(params.to);\n const value = ethers.parseUnits(params.amountUsdc.toString(), chain.usdc.decimals);\n const validAfter = params.validAfter ?? 0;\n const validBefore = params.validBefore ?? Math.floor(Date.now() / 1000) + 300;\n\n // Generate random 32-byte nonce\n const nonce = ethers.hexlify(ethers.randomBytes(32));\n\n // EIP-712 domain (matches USDC contract's domain separator)\n const domain: ethers.TypedDataDomain = {\n name: chain.usdc.name,\n version: chain.usdc.version,\n chainId,\n verifyingContract: usdcAddress,\n };\n\n // EIP-712 types for TransferWithAuthorization (ERC-3009)\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 // Message to sign\n const message = {\n from,\n to,\n value,\n validAfter,\n validBefore,\n nonce,\n };\n\n // Sign the EIP-712 typed data\n let signature: string;\n try {\n signature = await this.wallet.signTypedData(domain, types, message);\n } catch (error: unknown) {\n throw new X402Error(\n `Failed to sign EIP-3009 authorization: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n\n const sig = ethers.Signature.from(signature);\n\n return {\n from,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n signature,\n };\n }\n}\n","/**\n * uvd-x402-sdk - OWSWalletAdapter\n *\n * SigningWalletAdapter implementation using the Open Wallet Standard (OWS).\n * Delegates all signing to an OWS wallet instance, which manages key\n * security (encrypted vault, hardware isolation, etc.).\n *\n * Requires `@open-wallet-standard/core` as an optional peer dependency.\n * If the package is not installed, the adapter throws a helpful error\n * at construction time.\n *\n * @example\n * ```ts\n * import { OWSWalletAdapter } from 'uvd-x402-sdk';\n *\n * // The OWS wallet object must implement signMessage and signTypedData\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const auth = await wallet.signEIP3009({\n * to: '0xRecipient',\n * amountUsdc: 0.50,\n * network: 'base',\n * });\n * ```\n */\n\nimport { ethers } from 'ethers';\nimport { getChainByName } from '../chains';\nimport { X402Error } from '../types';\nimport type {\n SigningWalletAdapter,\n EIP3009Params,\n EIP3009Authorization,\n} from '../wallet';\n\n// ============================================================================\n// OWS WALLET INTERFACE (minimal subset we need)\n// ============================================================================\n\n/**\n * Minimal OWS wallet interface for signing operations.\n *\n * This mirrors the subset of the Open Wallet Standard that we use,\n * avoiding a hard compile-time dependency on @open-wallet-standard/core.\n * Any object that satisfies this shape can be passed to OWSWalletAdapter.\n */\nexport interface OWSWallet {\n /** Get wallet accounts (at least one EVM account expected) */\n accounts: ReadonlyArray<{\n /** EVM address (0x...) */\n address: string;\n /** Chain identifiers this account supports */\n chains?: ReadonlyArray<string>;\n }>;\n\n /** Sign a personal message (EIP-191) */\n signMessage(params: {\n account: { address: string };\n message: string | Uint8Array;\n }): Promise<{ signature: string }>;\n\n /** Sign EIP-712 typed data */\n signTypedData(params: {\n account: { address: string };\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<{ signature: string }>;\n\n /** Sign a serialized EVM transaction (hex-encoded) */\n signTransaction(params: {\n account: { address: string };\n transaction: string;\n chainId: string;\n }): Promise<{ signedTransaction: string }>;\n}\n\n// ============================================================================\n// OWS WALLET ADAPTER\n// ============================================================================\n\n/**\n * OWSWalletAdapter -- SigningWalletAdapter backed by an Open Wallet Standard wallet.\n */\nexport class OWSWalletAdapter implements SigningWalletAdapter {\n private readonly owsWallet: OWSWallet;\n private readonly address: string;\n\n /**\n * Create an OWSWalletAdapter.\n *\n * @param owsWallet - An object implementing the OWSWallet interface\n * (typically from @open-wallet-standard/core or a compatible provider)\n * @param accountIndex - Which account to use if the wallet has multiple (default: 0)\n * @throws {X402Error} if the wallet has no accounts\n */\n constructor(owsWallet: OWSWallet, accountIndex = 0) {\n if (!owsWallet || !owsWallet.accounts || owsWallet.accounts.length === 0) {\n throw new X402Error(\n 'OWS wallet has no accounts. Create or import a wallet first.',\n 'WALLET_NOT_CONNECTED',\n );\n }\n\n const account = owsWallet.accounts[accountIndex];\n if (!account) {\n throw new X402Error(\n `OWS wallet account index ${accountIndex} does not exist. Wallet has ${owsWallet.accounts.length} account(s).`,\n 'WALLET_NOT_CONNECTED',\n );\n }\n\n this.owsWallet = owsWallet;\n this.address = ethers.getAddress(account.address);\n }\n\n /**\n * Get the checksummed EVM wallet address.\n */\n getAddress(): string {\n return this.address;\n }\n\n /**\n * Sign a message using EIP-191 personal_sign.\n *\n * @param message - The message string to sign\n * @returns Hex-encoded signature\n */\n async signMessage(message: string): Promise<string> {\n try {\n const result = await this.owsWallet.signMessage({\n account: { address: this.address },\n message,\n });\n return result.signature;\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signMessage failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n }\n\n /**\n * Sign EIP-712 typed structured data.\n *\n * @param typedData - JSON string with `domain`, `types`, `primaryType`, and `message` fields\n * @returns Object with signature and v/r/s components\n */\n async signTypedData(typedData: string): Promise<{\n signature: string;\n v: number;\n r: string;\n s: string;\n }> {\n const parsed = JSON.parse(typedData) as {\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n };\n\n try {\n const result = await this.owsWallet.signTypedData({\n account: { address: this.address },\n domain: parsed.domain,\n types: parsed.types,\n primaryType: parsed.primaryType,\n message: parsed.message,\n });\n\n const sig = ethers.Signature.from(result.signature);\n\n return {\n signature: result.signature,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n };\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signTypedData failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n }\n\n /**\n * Sign a serialized EVM transaction.\n *\n * Delegates to the OWS wallet's signTransaction method.\n * Used by AdvancedEscrowClient for on-chain operations (release,\n * refund, charge) where the wallet signs instead of a raw private key.\n *\n * @param unsignedTx - Hex-encoded unsigned transaction\n * @returns Hex-encoded signed raw transaction\n */\n async signTransaction(unsignedTx: string): Promise<string> {\n try {\n const result = await this.owsWallet.signTransaction({\n account: { address: this.address },\n transaction: unsignedTx,\n chainId: '1', // chainId is embedded in the serialized TX; this is a hint\n });\n return result.signedTransaction;\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signTransaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n }\n\n /**\n * Sign an EIP-3009 ReceiveWithAuthorization for USDC.\n *\n * @param params - EIP-3009 parameters\n * @returns Signed authorization ready for facilitator relay\n */\n async signEIP3009(params: EIP3009Params): Promise<EIP3009Authorization> {\n const chain = getChainByName(params.network);\n if (!chain) {\n throw new X402Error(`Unsupported network: ${params.network}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error(\n `EIP-3009 is only supported on EVM chains. ${params.network} is ${chain.networkType}.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n }\n\n const chainId = params.chainId ?? chain.chainId;\n const usdcAddress = params.usdcContract ?? chain.usdc.address;\n const from = this.address;\n const to = ethers.getAddress(params.to);\n const value = ethers.parseUnits(params.amountUsdc.toString(), chain.usdc.decimals);\n const validAfter = params.validAfter ?? 0;\n const validBefore = params.validBefore ?? Math.floor(Date.now() / 1000) + 300;\n\n // Generate random 32-byte nonce\n const nonce = ethers.hexlify(ethers.randomBytes(32));\n\n // EIP-712 domain\n const domain: Record<string, unknown> = {\n name: chain.usdc.name,\n version: chain.usdc.version,\n chainId,\n verifyingContract: usdcAddress,\n };\n\n // EIP-712 types for TransferWithAuthorization (ERC-3009)\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 // Message to sign\n const message: Record<string, unknown> = {\n from,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n };\n\n let signatureResult: { signature: string };\n try {\n signatureResult = await this.owsWallet.signTypedData({\n account: { address: this.address },\n domain,\n types,\n primaryType: 'TransferWithAuthorization',\n message,\n });\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signEIP3009 failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n\n const sig = ethers.Signature.from(signatureResult.signature);\n\n return {\n from,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n signature: signatureResult.signature,\n };\n }\n}\n","/**\n * Facilitator Configuration\n *\n * This module contains the known facilitator addresses for each chain.\n * The SDK uses these automatically so users don't need to configure them.\n *\n * The facilitator (https://facilitator.ultravioletadao.xyz) has wallets\n * on each supported blockchain for:\n * - EVM: Signing EIP-3009 transferWithAuthorization transactions\n * - Solana: Paying transaction fees (fee payer)\n * - Algorand: Signing fee transactions in atomic groups\n * - Stellar: Signing authorization entries\n * - NEAR: Acting as relayer for meta-transactions\n * - Sui: Sponsoring transactions (paying gas via sponsored txs)\n * - XRPL: Submitting pre-signed Payment blobs (paying the network fee)\n */\n\n/**\n * Default facilitator URL\n */\nexport const DEFAULT_FACILITATOR_URL = 'https://facilitator.ultravioletadao.xyz';\n\n/**\n * Facilitator wallet addresses by chain type\n *\n * These are the public addresses of the facilitator's wallets.\n * The facilitator uses these to pay fees and sign transactions.\n */\nexport const FACILITATOR_ADDRESSES = {\n // ============================================\n // EVM Chains\n // ============================================\n /**\n * EVM facilitator address (mainnet)\n * Used for: Submitting EIP-3009 transferWithAuthorization transactions\n * Note: Same address across all EVM mainnet chains\n */\n evm: '0x103040545AC5031A11E8C03dd11324C7333a13C7',\n\n /**\n * EVM facilitator address (testnet)\n * Used for: All EVM testnet chains\n */\n 'evm-testnet': '0x34033041a5944B8F10f8E4D8496Bfb84f1A293A8',\n\n // ============================================\n // Solana\n // ============================================\n /**\n * Solana facilitator address (mainnet)\n * Used for: Paying transaction fees on Solana\n */\n solana: 'F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq',\n\n /**\n * Solana facilitator address (devnet)\n */\n 'solana-devnet': '6xNPewUdKRbEZDReQdpyfNUdgNg8QRc8Mt263T5GZSRv',\n\n // ============================================\n // Fogo (uses same addresses as Solana)\n // ============================================\n /**\n * Fogo facilitator address (mainnet)\n */\n fogo: 'F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq',\n\n /**\n * Fogo facilitator address (testnet)\n */\n 'fogo-testnet': '6xNPewUdKRbEZDReQdpyfNUdgNg8QRc8Mt263T5GZSRv',\n\n // ============================================\n // NEAR\n // ============================================\n /**\n * NEAR facilitator address (mainnet)\n * Used for: Relaying meta-transactions\n */\n near: 'uvd-facilitator.near',\n\n /**\n * NEAR facilitator address (testnet)\n */\n 'near-testnet': 'uvd-facilitator.testnet',\n\n // ============================================\n // Stellar\n // ============================================\n /**\n * Stellar facilitator address (mainnet)\n * Used for: Signing soroban authorization entries\n */\n stellar: 'GCHPGXJT2WFFRFCA5TV4G4E3PMMXLNIDUH27PKDYA4QJ2XGYZWGFZNHB',\n\n /**\n * Stellar facilitator address (testnet)\n */\n 'stellar-testnet': 'GBBFZMLUJEZVI32EN4XA2KPP445XIBTMTRBLYWFIL556RDTHS2OWFQ2Z',\n\n // ============================================\n // Algorand\n // ============================================\n /**\n * Algorand facilitator address (mainnet)\n * Used for: Signing Transaction 0 (fee tx) in atomic groups\n */\n algorand: 'KIMS5H6QLCUDL65L5UBTOXDPWLMTS7N3AAC3I6B2NCONEI5QIVK7LH2C2I',\n\n /**\n * Algorand facilitator address (testnet)\n */\n 'algorand-testnet': '5DPPDQNYUPCTXRZWRYSF3WPYU6RKAUR25F3YG4EKXQRHV5AUAI62H5GXL4',\n\n // ============================================\n // Sui\n // ============================================\n /**\n * Sui facilitator address (mainnet)\n * Used for: Sponsoring transactions (paying gas)\n */\n sui: '0xe7bbf2b13f7d72714760aa16e024fa1b35a978793f9893d0568a4fbf356a764a',\n\n /**\n * Sui facilitator address (testnet)\n */\n 'sui-testnet': '0xabbd16a2fab2a502c9cfe835195a6fc7d70bfc27cffb40b8b286b52a97006e67',\n\n // ============================================\n // XRPL (XRP Ledger)\n // ============================================\n /**\n * XRPL facilitator address (mainnet)\n * Used for: Submitting pre-signed Payment blobs and paying the network fee\n */\n 'xrpl-mainnet': 'rfADKkVXBNqK3z72tVSS3LVzAR3psYkonp',\n\n /**\n * XRPL facilitator address (testnet)\n */\n 'xrpl-testnet': 'rGhTioKAFHe75KgVnQtacRiKFuPv28Wbwk',\n} as const;\n\n/**\n * Get the facilitator address for a specific chain\n *\n * @param chainName - The chain name (e.g., 'algorand', 'solana', 'base')\n * @param networkType - The network type (e.g., 'evm', 'svm', 'algorand')\n * @returns The facilitator address for that chain, or undefined if not supported\n */\nexport function getFacilitatorAddress(\n chainName: string,\n networkType?: string\n): string | undefined {\n // Check for exact chain match first\n const exactMatch = FACILITATOR_ADDRESSES[chainName as keyof typeof FACILITATOR_ADDRESSES];\n if (exactMatch) {\n return exactMatch;\n }\n\n // Fall back to network type\n if (networkType === 'evm') {\n return FACILITATOR_ADDRESSES.evm;\n }\n if (networkType === 'svm' || networkType === 'solana') {\n return FACILITATOR_ADDRESSES.solana;\n }\n if (networkType === 'algorand') {\n return FACILITATOR_ADDRESSES.algorand;\n }\n if (networkType === 'stellar') {\n return FACILITATOR_ADDRESSES.stellar;\n }\n if (networkType === 'near') {\n return FACILITATOR_ADDRESSES.near;\n }\n if (networkType === 'sui') {\n return FACILITATOR_ADDRESSES.sui;\n }\n if (networkType === 'xrpl') {\n return FACILITATOR_ADDRESSES['xrpl-mainnet'];\n }\n\n return undefined;\n}\n\n/**\n * Type for facilitator addresses\n */\nexport type FacilitatorAddresses = typeof FACILITATOR_ADDRESSES;\n","/**\n * Live traffic stream client (`GET /events`, Server-Sent Events).\n *\n * The facilitator emits one event per operation it handles, so you can render or\n * react to live traffic without polling and without scraping logs.\n *\n * @example\n * ```ts\n * import { streamTrafficEvents } from '@ultravioletadao/x402-sdk';\n *\n * for await (const event of streamTrafficEvents()) {\n * console.log(event.kind, event.network, event.ok, event.tx);\n * }\n * ```\n *\n * @example Only settlements on the chains you care about. The facilitator has NO\n * server-side filter by network, so this is applied client-side.\n * ```ts\n * const stream = streamTrafficEvents({\n * networks: ['base', 'polygon'],\n * kinds: ['settle'],\n * });\n * for await (const event of stream) console.log(event.tx);\n * ```\n *\n * Three properties of this stream decide how you should use it:\n *\n * **It is lossy by design.** The facilitator will never slow down or fail a\n * payment to keep an observer in sync, so an event you were not connected for is\n * simply gone. Treat it as a live hint and use the chain as the source of truth.\n * Absence of events is NOT evidence that nothing happened.\n *\n * **Failed operations are not published.** Only operations that resolved emit an\n * event, so `ok: false` means \"resolved and came back negative\", never \"blew up\".\n * A stream that looks healthy is not proof that the rail is.\n *\n * **Admission is bounded.** The endpoint is public and unauthenticated, so it\n * sheds with HTTP 503 + `Retry-After` once too many subscribers are connected,\n * and returns 404 when the operator disabled it.\n */\n\nimport { DEFAULT_FACILITATOR_URL } from './facilitator';\n\n/** Operations the facilitator publishes. */\nexport type TrafficEventKind = 'verify' | 'settle';\n\n/** Operations the facilitator publishes, as a value. */\nexport const EVENT_KINDS: readonly TrafficEventKind[] = ['verify', 'settle'] as const;\n\n/**\n * The stream sends a `:keepalive` comment on this cadence, so any read timeout\n * you add must comfortably exceed it or you will kill healthy connections on an\n * idle rail.\n */\nexport const KEEPALIVE_INTERVAL_MS = 15_000;\n\n/**\n * One facilitator operation, as seen by an observer.\n *\n * Optional fields are *omitted* by the facilitator rather than sent as null, and\n * they are all absent when the operator runs the stream in `minimal` detail\n * mode. Never assume `payer` or `amount` is present.\n */\nexport interface TrafficEvent {\n /** Unix epoch **milliseconds**, UTC. Note: milliseconds, not seconds. */\n ts: number;\n kind: TrafficEventKind | string;\n /**\n * The facilitator's canonical network slug, the same one `/supported` uses.\n *\n * Beware: this is the *canonical* name, which is not always the alias you are\n * allowed to send. `skale` is accepted on the way in, but this field always\n * says `skale-base`. Match on the canonical form or you will silently drop\n * every event for that chain.\n */\n network: string;\n /** Resolved successfully? False means resolved-negative, not errored. */\n ok: boolean;\n payer?: string;\n /** Present on `settle`, absent on `verify` — nothing settled yet. */\n tx?: string;\n amount?: string;\n asset?: string;\n /**\n * The protected endpoint being bought.\n *\n * Answers \"what was paid for\", which the amount alone never does — two\n * 1-USDC settles are indistinguishable without it.\n */\n resource?: string;\n /** The seller receiving the payment. */\n payTo?: string;\n /** Human-readable description the seller advertised. */\n description?: string;\n /** Payment scheme: `exact`, `escrow`, `commerce`, `upto`. */\n scheme?: string;\n /**\n * Why the operation failed, as a BOUNDED CATEGORY — never the error text.\n *\n * Present only on operations that errored, and only where the operator set\n * `X402_EVENTS_PUBLISH_FAILURES=true`. A closed set (`contract_revert`,\n * `invalid_signature`, `insufficient_funds`, `invalid_timing`,\n * `blocked_address`, …, `other`) precisely so it can never carry an address\n * or an RPC URL.\n *\n * Note the distinction it makes visible: `ok: false` with no `error` means the\n * operation RESOLVED and came back negative; `error` set means it blew up.\n * Before this existed the second case produced no event at all.\n */\n error?: string;\n}\n\n/** Raised when the stream cannot be opened. Carries the HTTP status. */\nexport class TrafficStreamError extends Error {\n readonly status: number;\n /** Seconds to wait before retrying, when the server said so (503). */\n readonly retryAfter?: number;\n\n constructor(message: string, status: number, retryAfter?: number) {\n super(message);\n this.name = 'TrafficStreamError';\n this.status = status;\n this.retryAfter = retryAfter;\n }\n}\n\nexport interface StreamTrafficEventsOptions {\n /** Facilitator to subscribe to. Defaults to the Ultravioleta DAO facilitator. */\n facilitatorUrl?: string;\n /**\n * Only yield events for these networks. Applied client-side — the facilitator\n * has no per-network filter, so every event still crosses the wire. Match the\n * canonical slug (`skale-base`, not `skale`).\n */\n networks?: string[];\n /** Only yield these operations. */\n kinds?: TrafficEventKind[];\n /** Abort the stream. Without one, iteration ends only when the server closes. */\n signal?: AbortSignal;\n /** Extra headers, for a deployment that gates the stream behind authorization. */\n headers?: Record<string, string>;\n}\n\n/** One decoded SSE frame: the event name and its raw data payload. */\nexport interface SSEFrame {\n event: string;\n data: string;\n}\n\n/**\n * Incremental Server-Sent Events parser.\n *\n * Kept separate from the network layer so the framing can be tested without a\n * socket — which matters, because the case that breaks in production is an idle\n * rail sending nothing but keepalive comments for minutes.\n */\nexport class SSEParser {\n private buffer = '';\n private eventName = '';\n private dataLines: string[] = [];\n\n /** Feed a chunk of the response body; get back whatever frames completed. */\n push(chunk: string): SSEFrame[] {\n this.buffer += chunk;\n const frames: SSEFrame[] = [];\n\n let newlineIndex: number;\n while ((newlineIndex = this.buffer.indexOf('\\n')) !== -1) {\n const line = this.buffer.slice(0, newlineIndex).replace(/\\r$/, '');\n this.buffer = this.buffer.slice(newlineIndex + 1);\n\n if (line === '') {\n // Blank line dispatches. A dispatch with no data is a no-op per spec.\n if (this.dataLines.length > 0) {\n frames.push({\n event: this.eventName || 'message',\n data: this.dataLines.join('\\n'),\n });\n }\n this.eventName = '';\n this.dataLines = [];\n continue;\n }\n\n if (line.startsWith(':')) {\n // Comment. This is what a keepalive looks like — deliberately silent.\n continue;\n }\n\n const colon = line.indexOf(':');\n const field = colon === -1 ? line : line.slice(0, colon);\n let value = colon === -1 ? '' : line.slice(colon + 1);\n // A single leading space after the colon is framing, not value.\n if (value.startsWith(' ')) value = value.slice(1);\n\n if (field === 'event') this.eventName = value;\n else if (field === 'data') this.dataLines.push(value);\n // id / retry: accepted and ignored, so a future facilitator that starts\n // sending them does not break this parser.\n }\n\n return frames;\n }\n}\n\n/**\n * Decode one SSE frame into a {@link TrafficEvent}.\n *\n * Returns null for anything malformed: a single bad message must never tear down\n * a long-lived stream — the connection is worth more than the message.\n */\nexport function parseTrafficEvent(frame: SSEFrame): TrafficEvent | null {\n let payload: unknown;\n try {\n payload = JSON.parse(frame.data);\n } catch {\n return null;\n }\n if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {\n return null;\n }\n\n const raw = payload as Record<string, unknown>;\n // The SSE event name is authoritative for `kind`; the body carries it too and\n // they agree, but the framing is the contract.\n const kind = (raw.kind as string) || frame.event;\n\n if (typeof raw.ts !== 'number' || typeof raw.network !== 'string' || typeof raw.ok !== 'boolean') {\n return null;\n }\n\n const event: TrafficEvent = {\n ts: raw.ts,\n kind,\n network: raw.network,\n ok: raw.ok,\n };\n if (typeof raw.payer === 'string') event.payer = raw.payer;\n if (typeof raw.tx === 'string') event.tx = raw.tx;\n if (typeof raw.amount === 'string') event.amount = raw.amount;\n if (typeof raw.asset === 'string') event.asset = raw.asset;\n if (typeof raw.resource === 'string') event.resource = raw.resource;\n if (typeof raw.payTo === 'string') event.payTo = raw.payTo;\n if (typeof raw.description === 'string') event.description = raw.description;\n if (typeof raw.scheme === 'string') event.scheme = raw.scheme;\n if (typeof raw.error === 'string') event.error = raw.error;\n return event;\n}\n\n/** Does this event pass the caller's client-side filters? */\nexport function matchesFilters(\n event: TrafficEvent,\n options: Pick<StreamTrafficEventsOptions, 'networks' | 'kinds'>\n): boolean {\n if (options.kinds && options.kinds.length > 0) {\n if (!options.kinds.some((k) => k.toLowerCase() === event.kind.toLowerCase())) return false;\n }\n if (options.networks && options.networks.length > 0) {\n if (!options.networks.some((n) => n.toLowerCase() === event.network.toLowerCase())) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Subscribe to the facilitator's live traffic stream.\n *\n * Works in Node 18+ and in browsers: it uses `fetch` and the response body\n * stream rather than `EventSource`, so it also works where custom headers are\n * needed (`EventSource` cannot send them).\n *\n * Iteration ends when the server closes the connection or the `signal` aborts.\n * It does NOT reconnect on its own — reconnect policy belongs to the caller, who\n * is the only one who knows whether a gap matters.\n *\n * @throws {TrafficStreamError} 404 when the operator disabled the stream, 503\n * with `retryAfter` when it is at subscriber capacity.\n */\nexport async function* streamTrafficEvents(\n options: StreamTrafficEventsOptions = {}\n): AsyncGenerator<TrafficEvent, void, undefined> {\n const baseUrl = (options.facilitatorUrl || DEFAULT_FACILITATOR_URL).replace(/\\/$/, '');\n const response = await fetch(`${baseUrl}/events`, {\n method: 'GET',\n headers: { Accept: 'text/event-stream', ...(options.headers || {}) },\n signal: options.signal,\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n if (response.status === 404) {\n throw new TrafficStreamError(\n `GET /events is disabled on this facilitator (operator set X402_EVENTS_ENABLED=false): ${body}`,\n 404\n );\n }\n if (response.status === 503) {\n const header = response.headers.get('retry-after');\n const retryAfter = header ? Number(header) : undefined;\n throw new TrafficStreamError(\n `GET /events is at subscriber capacity; retry after ${header ?? 'unknown'}s. ` +\n `This is admission control, not an outage.`,\n 503,\n Number.isFinite(retryAfter) ? retryAfter : undefined\n );\n }\n throw new TrafficStreamError(`GET /events failed: ${response.status} - ${body}`, response.status);\n }\n\n if (!response.body) {\n throw new TrafficStreamError('GET /events returned no body to stream', response.status);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const parser = new SSEParser();\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n for (const frame of parser.push(decoder.decode(value, { stream: true }))) {\n const event = parseTrafficEvent(frame);\n if (event && matchesFilters(event, options)) yield event;\n }\n }\n } finally {\n // Releasing the lock lets the caller's `break` actually close the socket\n // instead of leaking a half-read response.\n reader.releaseLock();\n }\n}\n","/**\n * uvd-x402-sdk - ERC-8128 HTTP Message Signature Signer\n *\n * Signs HTTP requests per ERC-8128 (Signed HTTP Requests with Ethereum,\n * RFC 9421 profile) so agents can authenticate against APIs that reject\n * API keys and only accept wallet signing (e.g. Execution Market, where\n * `EM_API_KEYS_ENABLED=false` in production).\n *\n * Flow:\n * 1. Fetch a fresh single-use nonce from the server (`fetchNonce`)\n * 2. Build the RFC 9421 signature base from request components\n * 3. Sign with EIP-191 personal_sign\n * 4. Produce `Signature` + `Signature-Input` (+ `Content-Digest`) headers\n *\n * Wire format: pinned by the F3-1 golden vectors (`src/erc8128.vectors.json`)\n * — `alg=\"eip191\"` always emitted, keyid ALWAYS lowercase, params in the\n * order `created;expires;nonce;keyid;alg`. Byte-equality against the vectors\n * is enforced in `src/erc8128.test.ts`.\n *\n * Three signing entry points:\n * - {@link signRequest} — raw private key (ethers Wallet), for scripts /\n * bots that hold the key in env.\n * - {@link signRequestWithWallet} — any {@link SigningWalletAdapter}\n * (EnvKeyAdapter, OWSWalletAdapter, custom); only `getAddress()` and\n * `signMessage()` are used, the key never leaves the adapter.\n * - {@link signRequestWithSigner} — callback-based, for browser wallets or\n * out-of-process signers that expose a bare EIP-191 personal_sign.\n *\n * @example Sign a single request\n * ```typescript\n * import { signRequest, fetchNonce } from 'uvd-x402-sdk';\n *\n * const nonce = await fetchNonce('https://api.execution.market');\n * const headers = await signRequest({\n * privateKey: process.env.WALLET_PRIVATE_KEY!,\n * method: 'POST',\n * url: 'https://api.execution.market/api/v1/tasks',\n * body: '{\"title\": \"test\"}',\n * nonce,\n * chainId: 8453,\n * });\n * // headers = { Signature: '...', 'Signature-Input': '...', 'Content-Digest': '...' }\n * ```\n *\n * @example Auto-signing fetch wrapper\n * ```typescript\n * import { createSignedFetch, EnvKeyAdapter } from 'uvd-x402-sdk';\n *\n * const signedFetch = createSignedFetch({\n * wallet: new EnvKeyAdapter(), // or privateKey: '...'\n * apiBase: 'https://api.execution.market',\n * });\n *\n * const resp = await signedFetch('/api/v1/tasks', {\n * method: 'POST',\n * body: JSON.stringify({ title: 'test' }),\n * });\n * ```\n *\n * Reference:\n * - ERC-8128: https://eip.tools/eip/8128\n * - RFC 9421: https://www.rfc-editor.org/rfc/rfc9421\n * - ERC-191: https://eips.ethereum.org/EIPS/eip-191\n */\n\nimport { ethers } from 'ethers';\nimport { X402Error } from './types';\nimport type { SigningWalletAdapter } from './wallet';\n\n/** Default label for ERC-8128 signatures */\nconst DEFAULT_LABEL = 'eth';\n\n/** Signature algorithm parameter — pinned by F3-1 (always emitted) */\nconst ALG = 'eip191';\n\n/** Default validity window (seconds) — server policy typically caps at 300 */\nconst DEFAULT_VALIDITY_SEC = 300;\n\n/** Default EVM chain ID for the keyid (Base mainnet, the production auth chain) */\nconst DEFAULT_CHAIN_ID = 8453;\n\n/**\n * Request components shared by every ERC-8128 signing entry point.\n */\nexport interface ERC8128RequestOptions {\n /** HTTP method (GET, POST, etc.) */\n method: string;\n /** Full URL of the request (authority + path + query are covered) */\n url: string;\n /**\n * Request body (for POST/PUT/PATCH). Omit for bodyless requests.\n * Must be byte-identical to what is sent on the wire — the\n * `Content-Digest` covers it.\n */\n body?: string;\n /** Single-use nonce from the server. Required by most servers. */\n nonce?: string;\n /** EVM chain ID for the keyid (default: 8453 = Base) */\n chainId?: number;\n /** Signature label (default: \"eth\") */\n label?: string;\n /** Signature validity window in seconds (default: 300) */\n validitySec?: number;\n}\n\nexport interface SignRequestOptions extends ERC8128RequestOptions {\n /** Hex-encoded private key (with or without 0x prefix) */\n privateKey: string;\n}\n\nexport interface SignRequestWithSignerOptions extends ERC8128RequestOptions {\n /** Signer address (any case — lowercased for the keyid per F3-1) */\n address: string;\n /**\n * EIP-191 personal_sign callback over the RFC 9421 signature base.\n * Must return the 65-byte signature (r||s||v) as 0x-prefixed hex.\n * The private key never leaves the signer (OWS vault, browser wallet).\n */\n signMessage: (signatureBase: string) => Promise<string> | string;\n}\n\nexport interface SignatureHeaders {\n Signature: string;\n 'Signature-Input': string;\n 'Content-Digest'?: string;\n}\n\n/**\n * Configuration for {@link createSignedFetch}. Provide exactly one signer:\n * a raw `privateKey` or a `wallet` adapter.\n */\nexport interface CreateSignedFetchConfig {\n /** Origin of the API (e.g. \"https://api.execution.market\") */\n apiBase: string;\n /** EVM chain ID for the keyid (default: 8453 = Base) */\n chainId?: number;\n /** Hex-encoded private key (with or without 0x prefix) */\n privateKey?: string;\n /** SigningWalletAdapter — the key never leaves the adapter */\n wallet?: SigningWalletAdapter;\n}\n\n/**\n * Sign an HTTP request per ERC-8128 with a raw private key.\n *\n * Thin wrapper over {@link signRequestWithSigner} using an ethers Wallet.\n *\n * @returns Headers to merge into the request (Signature, Signature-Input, Content-Digest).\n */\nexport async function signRequest(options: SignRequestOptions): Promise<SignatureHeaders> {\n const key = options.privateKey.startsWith('0x')\n ? options.privateKey\n : `0x${options.privateKey}`;\n const wallet = new ethers.Wallet(key);\n return signRequestWithSigner({\n address: wallet.address,\n signMessage: (signatureBase) => wallet.signMessage(signatureBase),\n method: options.method,\n url: options.url,\n body: options.body,\n nonce: options.nonce,\n chainId: options.chainId,\n label: options.label,\n validitySec: options.validitySec,\n });\n}\n\n/**\n * Sign an HTTP request per ERC-8128 with a {@link SigningWalletAdapter}.\n *\n * Only `getAddress()` and `signMessage()` (EIP-191 personal_sign) are used —\n * the private key never leaves the adapter. Works with EnvKeyAdapter,\n * OWSWalletAdapter, or any custom adapter.\n *\n * @returns Headers to merge into the request (Signature, Signature-Input, Content-Digest).\n */\nexport async function signRequestWithWallet(\n wallet: SigningWalletAdapter,\n options: ERC8128RequestOptions\n): Promise<SignatureHeaders> {\n return signRequestWithSigner({\n ...options,\n address: wallet.getAddress(),\n signMessage: (signatureBase) => wallet.signMessage(signatureBase),\n });\n}\n\n/**\n * Sign an HTTP request per ERC-8128 with a signing callback.\n *\n * For signers that never expose the raw key (OWS vault, browser wallets):\n * the callback receives the RFC 9421 signature base and returns the EIP-191\n * personal_sign signature as 0x-hex.\n *\n * @returns Headers to merge into the request (Signature, Signature-Input, Content-Digest).\n */\nexport async function signRequestWithSigner(\n options: SignRequestWithSignerOptions\n): Promise<SignatureHeaders> {\n const {\n address: rawAddress,\n signMessage,\n method,\n url,\n body,\n nonce,\n chainId = DEFAULT_CHAIN_ID,\n label = DEFAULT_LABEL,\n validitySec = DEFAULT_VALIDITY_SEC,\n } = options;\n\n // CRITICAL: lowercase — checksummed keyid caused the v9.x silent-auth INC.\n const address = rawAddress.toLowerCase();\n\n const parsed = new URL(url);\n const authority = parsed.host;\n const path = parsed.pathname || '/';\n const query = parsed.search || undefined; // includes '?' prefix\n\n const now = Math.floor(Date.now() / 1000);\n const created = now;\n const expires = now + validitySec;\n\n const keyid = `erc8128:${chainId}:${address}`;\n\n // Determine covered components\n const covered: string[] = ['@method', '@authority', '@path'];\n if (query) {\n covered.push('@query');\n }\n\n const headers: SignatureHeaders = {\n Signature: '',\n 'Signature-Input': '',\n };\n\n if (body !== undefined) {\n const digest = computeContentDigest(body);\n headers['Content-Digest'] = digest;\n covered.push('content-digest');\n }\n\n // Build signature base\n const sigBase = buildSignatureBase({\n method,\n authority,\n path,\n query,\n contentDigest: headers['Content-Digest'],\n covered,\n created,\n expires,\n nonce,\n keyid,\n });\n\n // EIP-191 personal_sign via the callback — the key stays in the signer\n const sigHex = await signMessage(sigBase);\n\n // Encode signature as base64 (RFC 8941 byte sequence)\n const sigBytes = ethers.getBytes(sigHex.startsWith('0x') ? sigHex : `0x${sigHex}`);\n const sigB64 = ethers.encodeBase64(sigBytes);\n\n // Build headers\n const sigParams = buildSignatureParams({ covered, created, expires, nonce, keyid });\n\n headers.Signature = `${label}=:${sigB64}:`;\n headers['Signature-Input'] = `${label}=${sigParams}`;\n\n return headers;\n}\n\n/**\n * Fetch a fresh single-use nonce from the server.\n *\n * @param apiBase - Origin of the API (e.g. \"https://api.execution.market\")\n * — the `/api/v1/auth/erc8128/nonce` path is appended here.\n * @param timeoutMs - Request timeout in milliseconds (default: 10000).\n * @returns The nonce value (single-use, short TTL — fetch one per request).\n */\nexport async function fetchNonce(apiBase: string, timeoutMs = 10000): Promise<string> {\n const url = `${apiBase.replace(/\\/$/, '')}/api/v1/auth/erc8128/nonce`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const resp = await fetch(url, { signal: controller.signal });\n if (!resp.ok) {\n throw new Error(`Failed to fetch nonce: ${resp.status} ${resp.statusText}`);\n }\n const data = (await resp.json()) as { nonce: string };\n return data.nonce;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Create a fetch wrapper that auto-signs requests with ERC-8128\n * (nonce fetch + signature headers on every call).\n *\n * @example\n * ```typescript\n * const signedFetch = createSignedFetch({\n * wallet: new EnvKeyAdapter(), // or privateKey: '...'\n * apiBase: 'https://api.execution.market',\n * chainId: 8453,\n * });\n *\n * const resp = await signedFetch('/api/v1/tasks', {\n * method: 'POST',\n * body: JSON.stringify({ title: 'test' }),\n * });\n * ```\n */\nexport function createSignedFetch(config: CreateSignedFetchConfig) {\n const { apiBase, chainId, privateKey, wallet } = config;\n\n if (!privateKey && !wallet) {\n throw new X402Error(\n 'createSignedFetch requires a signer: pass privateKey or wallet.',\n 'WALLET_NOT_CONNECTED'\n );\n }\n\n return async (path: string, init?: RequestInit): Promise<Response> => {\n const url = `${apiBase.replace(/\\/$/, '')}${path}`;\n const method = (init?.method || 'GET').toUpperCase();\n const body = init?.body ? String(init.body) : undefined;\n\n // Fresh single-use nonce per request\n const nonce = await fetchNonce(apiBase);\n\n // Sign request\n const requestOptions: ERC8128RequestOptions = { method, url, body, nonce, chainId };\n const sigHeaders = wallet\n ? await signRequestWithWallet(wallet, requestOptions)\n : await signRequest({ ...requestOptions, privateKey: privateKey! });\n\n // Merge headers\n const headers = new Headers(init?.headers);\n headers.set('Signature', sigHeaders.Signature);\n headers.set('Signature-Input', sigHeaders['Signature-Input']);\n if (sigHeaders['Content-Digest']) {\n headers.set('Content-Digest', sigHeaders['Content-Digest']);\n }\n if (body) {\n headers.set('Content-Type', headers.get('Content-Type') || 'application/json');\n }\n\n return fetch(url, { ...init, headers, method });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Signature-base construction (exported: browser / out-of-process signers\n// build the exact same base and sign it elsewhere)\n// ---------------------------------------------------------------------------\n\nfunction computeContentDigest(body: string): string {\n const hash = ethers.sha256(ethers.toUtf8Bytes(body));\n // hash is 0x-prefixed hex, convert to raw bytes then base64\n const b64 = ethers.encodeBase64(ethers.getBytes(hash));\n return `sha-256=:${b64}:`;\n}\n\nexport interface SignatureBaseParams {\n method: string;\n authority: string;\n path: string;\n query?: string;\n contentDigest?: string;\n covered: string[];\n created: number;\n expires: number;\n nonce?: string;\n keyid: string;\n}\n\n/**\n * Build the RFC 9421 signature base — the exact string that gets EIP-191\n * personal_signed. Exported so external signers (OWS, browser) can reproduce\n * it byte-for-byte; pinned by the F3-1 golden vectors.\n */\nexport function buildSignatureBase(params: SignatureBaseParams): string {\n const lines: string[] = [];\n\n for (const component of params.covered) {\n switch (component) {\n case '@method':\n lines.push(`\"@method\": ${params.method.toUpperCase()}`);\n break;\n case '@authority':\n lines.push(`\"@authority\": ${params.authority}`);\n break;\n case '@path':\n lines.push(`\"@path\": ${params.path}`);\n break;\n case '@query':\n lines.push(`\"@query\": ${params.query || '?'}`);\n break;\n case 'content-digest':\n lines.push(`\"content-digest\": ${params.contentDigest || ''}`);\n break;\n }\n }\n\n const sigParams = buildSignatureParams({\n covered: params.covered,\n created: params.created,\n expires: params.expires,\n nonce: params.nonce,\n keyid: params.keyid,\n });\n lines.push(`\"@signature-params\": ${sigParams}`);\n\n return lines.join('\\n');\n}\n\nexport interface SignatureParamsInput {\n covered: string[];\n created: number;\n expires: number;\n nonce?: string;\n keyid: string;\n}\n\n/**\n * Build the `@signature-params` value per RFC 9421, in the pinned order\n * `created;expires;nonce;keyid;alg` (F3-1).\n */\nexport function buildSignatureParams(params: SignatureParamsInput): string {\n const compStr = params.covered.map((c) => `\"${c}\"`).join(' ');\n const parts: string[] = [`(${compStr})`];\n parts.push(`created=${params.created}`);\n parts.push(`expires=${params.expires}`);\n if (params.nonce) {\n parts.push(`nonce=\"${params.nonce}\"`);\n }\n parts.push(`keyid=\"${params.keyid}\"`);\n parts.push(`alg=\"${ALG}\"`);\n return parts.join(';');\n}\n","/**\n * EIP-7702: make a DELEGATED EOA's EIP-3009 signature settle again.\n *\n * **THE PROBLEM.** A gasless-wallet provider's first sponsored operation on a\n * chain may delegate the user's EOA (EIP-7702) to a smart-account\n * implementation — Alchemy's `SemiModularAccount7702` (`0x69007702…`) is the one\n * seen in the wild. From then on the address HAS code, so Circle's USDC (and any\n * `SignatureChecker` consumer) verifies signatures via **ERC-1271 only**. A raw\n * ECDSA authorization, however perfect, is rejected: `0x151d90fe`. The account is\n * not broken and the signature is not wrong — they simply no longer speak the\n * same dialect.\n *\n * Consequence for anything x402: a delegated payer's `transferWithAuthorization`\n * / `receiveWithAuthorization` becomes **unsettleable on-chain**, so direct x402\n * payments AND marketplace escrow locks both fail. Measured in production\n * 2026-07-31: 14 of 14 delegated agents failed their escrow lock; the one\n * non-delegated agent locked fine. The failure is silent in the worst way — the\n * sellers looked broken and they were correct.\n *\n * **THE FIX** (verified on-chain; the wallet provider needs to change nothing).\n * That account's `isValidSignature` DOES accept the EOA's own ECDSA — it just\n * wants it in the account's envelope. Two steps, both provable against the\n * verified source (`SemiModularAccountBase._exec1271Validation` +\n * `SparseCalldataSegmentLib`):\n *\n * 1. The account does not check `hash` directly; it checks a REPLAY-SAFE hash =\n * EIP-712 over the account's OWN domain\n * `EIP712Domain(uint256 chainId, address verifyingContract=account)` with\n * struct `ReplaySafeHash(bytes32 hash)`. Sign THAT, not the transfer digest.\n * 2. Wrap the 65-byte signature with the account's fallback-validation locator:\n * `0x00 00000000` (validation type 0, entity id 0 = FALLBACK_VALIDATION_ID)\n * `FF` (RESERVED_VALIDATION_DATA_INDEX, the final segment) `00`\n * (SignatureType.EOA).\n *\n * Because step 1 is still an ordinary typed-data signature, a REMOTE signer (a\n * delegated agentic wallet) can produce it: the private key is never needed\n * locally.\n *\n * **THE WRAP IS DELEGATE-SPECIFIC, NOT \"delegated == wrap\".** This is the part\n * that bit us on 2026-08-25, and it is why this module exists in TypeScript at\n * all: the moment a worker rates an agent through the facilitator's EIP-7702\n * feedback rail, their EOA becomes delegated to Execution Market's\n * `FeedbackDelegate` — which validates PLAIN ECDSA\n * (`ECDSA.recover(hash, sig) == address(this)`). Wrapping that signature makes it\n * invalid, so *the act of rating would break the rater's next payment*. Same\n * silent-at-lock-time failure the wrap was built to fix, now caused by\n * over-applying it.\n *\n * **DETECTION IS INJECTABLE, ON PURPOSE.** Knowing whether an address is\n * delegated needs one `eth_getCode` — a chain read, and this SDK does not own an\n * RPC policy. So detection is a callable you pass in ({@link DelegationResolver}).\n * {@link rpcDelegationResolver} ships a default over `fetch`; a caller with its\n * own endpoints, proxy or rotation passes its own.\n *\n * **THE THIRD STATE IS LOAD-BEARING.** A resolver returns `true` / `false` /\n * **`null` = could not tell**. `null` must never collapse to \"not delegated\":\n * that is exactly how the original bug survived eight days — the resolver failed,\n * returned nothing, and the caller's `if (delegated)` read it as falsy and signed\n * raw. **An unreadable answer is not a negative answer.**\n *\n * Port of `uvd_x402_sdk.erc7702` (Python). Keep the two in step: they are the\n * same protocol seen from two languages, and a divergence here is a signature\n * that cannot settle.\n */\n\n/** EIP-7702 delegation designator. */\nexport const DELEGATE_PREFIX = 'ef0100';\n\n/**\n * Delegate targets whose ERC-1271 needs the account-envelope wrap.\n *\n * Only a known Alchemy SMA implementation needs it. Every other delegate signs\n * PLAIN (the standard 1271 \"smart-EOA\" pattern accepts the EOA's own ECDSA), and\n * if some exotic future delegate needs a third dialect it fails VISIBLY at lock\n * time — never silently.\n *\n * Notably NOT here: Execution Market's `FeedbackDelegate` (all nine deploys). An\n * account that has rated through the facilitator's rail is delegated to it and\n * must sign plain.\n */\nexport const SMA_WRAP_TARGETS: readonly string[] = [\n '0x69007702764179f14f51cdce752f4f775d74e139', // Alchemy SemiModularAccount7702\n];\n\n/**\n * `true` only when this delegate target needs the account-envelope wrap.\n *\n * A plain EOA (`target` null/undefined) and any other delegate — FeedbackDelegate,\n * a standard 1271 smart-EOA — do NOT: they take the ordinary ECDSA signature.\n */\nexport function needsAccountWrap(target: string | null | undefined): boolean {\n return !!target && SMA_WRAP_TARGETS.includes(target.toLowerCase());\n}\n\n/**\n * Account fallback-validation locator + final-segment marker + EOA signature type.\n *\n * - `0x00 00000000` — validation type 0, entity id 0 (FALLBACK_VALIDATION_LOOKUP_KEY)\n * - `0xFF` — RESERVED_VALIDATION_DATA_INDEX (getFinalSegment)\n * - `0x00` — SignatureType.EOA\n */\nconst WRAP_PREFIX = '00000000' + '00' + 'ff' + '00';\n\n/**\n * The delegate target this EOA's EIP-7702 code points at, or `null`.\n *\n * `null` for a plain EOA, for non-7702 code, and for anything unparseable — the\n * caller confirms the implementation before applying the wrap.\n */\nexport function delegateTarget(code: string | null | undefined): string | null {\n if (!code) return null;\n const h = (code.startsWith('0x') ? code.slice(2) : code).toLowerCase();\n if (!h.startsWith(DELEGATE_PREFIX) || h.length < 46) return null;\n return `0x${h.slice(6, 46)}`;\n}\n\n/** Wrap a 65-byte ECDSA signature in the account's fallback-EOA envelope. */\nexport function wrapSignature(innerSignature: string): string {\n const s = innerSignature.startsWith('0x') ? innerSignature.slice(2) : innerSignature;\n return `0x${WRAP_PREFIX}${s}`;\n}\n\n/**\n * The typed data whose signature the delegated account accepts.\n *\n * The domain is the ACCOUNT's own — `chainId` + `verifyingContract=account`, the\n * two fields its typehash declares — and the struct is\n * `ReplaySafeHash(bytes32 hash)` over the inner EIP-3009 digest. Signing THIS,\n * not the digest, is what validates.\n */\nexport function replaySafeTypedData(\n innerDigest: string,\n chainId: number,\n account: string\n): { domain: Record<string, unknown>; types: Record<string, unknown>; message: Record<string, unknown> } {\n return {\n domain: { chainId, verifyingContract: account },\n types: { ReplaySafeHash: [{ name: 'hash', type: 'bytes32' }] },\n message: { hash: innerDigest },\n };\n}\n\n/**\n * `(address, network) -> target | true | false | null`.\n *\n * Four answers, richer than a boolean on purpose: a resolver MAY return the\n * delegate **target address** (a string) instead of just `true` — that is what\n * lets the caller pick the right signing dialect (SMA wrap vs plain). `true` =\n * delegated, target unknown; `false` = not delegated; `null` = UNKNOWN\n * (unreadable chain), never \"no\".\n */\nexport type DelegationResolver = (\n address: string,\n network: string\n) => Promise<string | boolean | null> | (string | boolean | null);\n\n/**\n * A default resolver over plain JSON-RPC `eth_getCode`, using `fetch`.\n *\n * Rotates through `urls` and returns `null` when **every** endpoint failed: an\n * unreadable chain is not a \"not delegated\" verdict.\n *\n * A caller with its own RPC policy (a signed proxy, paid endpoints, per-chain\n * routing) should pass its own resolver instead; that is the whole point of the\n * injection.\n */\nexport function rpcDelegationResolver(\n urls: string | string[],\n timeoutMs = 6000\n): DelegationResolver {\n const endpoints = typeof urls === 'string' ? [urls] : [...urls];\n\n return async (address: string): Promise<string | boolean | null> => {\n const addr = (address || '').trim();\n if (!addr || endpoints.length === 0) return null;\n\n for (const url of endpoints) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = 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_getCode',\n params: [addr.toLowerCase(), 'latest'],\n }),\n signal: controller.signal,\n });\n clearTimeout(timer);\n if (!res.ok) continue;\n const code = (await res.json())?.result;\n if (typeof code === 'string' && code.startsWith('0x')) {\n // Return the TARGET when delegated, so the caller can pick the signing\n // dialect; `false` for a plain EOA (readable, no delegation).\n return delegateTarget(code) ?? false;\n }\n } catch {\n clearTimeout(timer);\n // Rotate to the next endpoint. Exhausting them all is UNKNOWN, below.\n }\n }\n return null;\n };\n}\n\n/** `{ delegated, target }` for one address on one network. */\nexport interface DelegationVerdict {\n /** `null` = UNKNOWN. Never treat it as `false`. */\n delegated: boolean | null;\n /** The delegate implementation, when the resolver could name it. */\n target: string | null;\n}\n\n/**\n * Resolve one address's delegation on one network.\n *\n * - `{delegated: null, target: null}` — unknown (no resolver, or an unreadable\n * chain). NEVER \"no\".\n * - `{delegated: false, target: null}` — a plain EOA.\n * - `{delegated: true, target: '0x…'}` — delegated, and we know to WHAT (pick the\n * dialect from it).\n * - `{delegated: true, target: null}` — delegated, target unknown (a legacy\n * boolean-only resolver).\n */\nexport async function resolveDelegation(\n address: string,\n network: string,\n resolver?: DelegationResolver\n): Promise<DelegationVerdict> {\n if (!resolver) return { delegated: null, target: null };\n\n let v: string | boolean | null;\n try {\n v = await resolver(address, network);\n } catch {\n // A broken resolver is UNKNOWN, not a negative.\n return { delegated: null, target: null };\n }\n\n if (typeof v === 'string') {\n const t = v.trim();\n // Only a real 20-byte address counts as a target. A non-address string is\n // garbage, and garbage is UNKNOWN — never a verdict we sign on.\n if (/^0x[0-9a-fA-F]{40}$/.test(t)) return { delegated: true, target: t };\n return { delegated: null, target: null };\n }\n if (typeof v === 'boolean') return { delegated: v, target: null };\n return { delegated: null, target: null };\n}\n\n/**\n * `true` / `false` / `null` (**unknown**) for one address on one network.\n *\n * Without a resolver the answer is `null`, never `false`: \"nobody asked\" and \"the\n * address is a plain EOA\" are different facts and only one of them is safe to\n * sign on.\n */\nexport async function isDelegated(\n address: string,\n network: string,\n resolver?: DelegationResolver\n): Promise<boolean | null> {\n return (await resolveDelegation(address, network, resolver)).delegated;\n}\n","/**\n * uvd-x402-sdk - Escrow Pre-Auth Builder (sign-on-assignment)\n *\n * Builds and signs the EIP-3009 `ReceiveWithAuthorization` that locks a\n * bounty in the x402r AuthCaptureEscrow, and packs it into the raw-JSON\n * `X-Payment-Auth` wrapper the Ultravioleta Facilitator's `/settle` expects.\n * Used by marketplaces built on the escrow rail (e.g. Execution Market's\n * universal escrow, ADR-002).\n *\n * >>> PROTOCOL CONSTRAINT <<<\n * The EIP-3009 nonce is `AuthCaptureEscrow.getHash(paymentInfo)` which\n * INCLUDES the receiver — the escrow signature can only be created AT\n * ASSIGNMENT, when the worker/payee is known. Never design flows that sign\n * an escrow auth before the receiver is chosen (\"stored pre-auth with late\n * receiver fill\" is on-chain unsound).\n *\n * Fail-loud policy: an incomplete network config, an unknown tier, a bounty\n * outside the on-chain deposit limit, or a `maxFeeBps` that cannot cover the\n * operator's static fee all throw instead of falling back — a silent\n * fallback would sign an EIP-3009 authorization with the WRONG EIP-712\n * domain (chainId + verifyingContract): a mismatched, wallet-draining auth.\n *\n * Wire format is pinned by golden vectors (`src/escrow-preauth.vectors.json`):\n * payer-zeroed raw-keccak nonce (`keccak(chainId, escrow,\n * keccak(PAYMENT_INFO_TYPEHASH, paymentInfo tuple with payer=0))`),\n * `ReceiveWithAuthorization` typed data, raw JSON (NOT base64) wrapper.\n * Byte-parity with the production references is enforced in\n * `src/escrow-preauth.test.ts`.\n *\n * @example Sign the escrow lock at assignment time\n * ```typescript\n * import { buildEscrowPreAuth, EnvKeyAdapter } from 'uvd-x402-sdk';\n *\n * // Server-published escrow config (e.g. GET /api/v1/h2a/payment-config\n * // on Execution Market — escrow_networks[network]).\n * const paymentAuth = await buildEscrowPreAuth(new EnvKeyAdapter(), {\n * networkConfig: config.escrow.networks.base,\n * payerWallet: '0xPublisher...',\n * workerWallet: '0xWorker...', // committed by the nonce\n * bountyAtomic: '100000', // $0.10 in 6-decimal USDC\n * reviewDeadlineSec: taskDeadlineEpoch,\n * });\n * // Send as the X-Payment-Auth header (raw JSON, NOT base64).\n * ```\n *\n * Reference implementations (kept in byte-parity via the shared vectors):\n * - Python: `em_plugin_sdk.escrow_signing.build_escrow_pre_auth`\n * (production reference, derived from `uvd_x402_sdk.advanced_escrow`)\n * - Browser (viem): Execution Market `dashboard/src/services/h2aSigning.ts`\n */\n\nimport { ethers } from 'ethers';\nimport { X402Error } from './types';\nimport {\n needsAccountWrap,\n replaySafeTypedData,\n resolveDelegation,\n wrapSignature,\n type DelegationResolver,\n} from './erc7702.js';\n\nconst ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\nconst USDC_DECIMALS = 6;\n\n/** AuthCaptureEscrow deposit condition: $100 max per deposit. */\nexport const ESCROW_DEPOSIT_LIMIT_USD = 100;\n\n/**\n * StaticFeeCalculator: canonical 13% flat fee. The signed maxFeeBps MUST\n * cover it or the on-chain release reverts.\n */\nexport const OPERATOR_FEE_BPS = 1300;\n\n/** Fee-bound defaults for optional config keys only — never for the domain. */\nconst DEFAULT_MIN_FEE_BPS = 0;\nconst DEFAULT_MAX_FEE_BPS = 1800;\n\n/**\n * EIP-712 type for the escrow flow. The token collector pulls the funds, so\n * the scheme is ReceiveWithAuthorization (not TransferWithAuthorization).\n */\nconst RECEIVE_WITH_AUTHORIZATION_TYPES = {\n ReceiveWithAuthorization: [\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/**\n * ABI type of the paymentInfo tuple — mirrors AdvancedEscrowClient /\n * em_plugin_sdk.escrow_signing (unnamed components, positional encoding).\n */\nconst PAYMENT_INFO_TUPLE =\n 'tuple(address,address,address,address,uint120,uint48,uint48,uint48,uint16,uint16,address,uint256)';\n\n/** Per-tier expiry windows in seconds, relative to now() at signing. */\nexport interface EscrowTierWindows {\n pre: number;\n auth: number;\n refund: number;\n}\n\n/** Canonical fallback — mirrors uvd_x402_sdk TIER_TIMINGS. */\nexport const ESCROW_TIER_WINDOWS: Record<string, EscrowTierWindows> = {\n micro: { pre: 3600, auth: 7200, refund: 86400 },\n standard: { pre: 7200, auth: 86400, refund: 604800 },\n};\n\n/**\n * Human review windows. Agents approve in seconds, so the short SDK tier\n * windows (micro auth = 2h) work for them. A HUMAN publisher reviews on\n * their own schedule — if authorizationExpiry passes before approval, the\n * on-chain release REVERTS (AfterAuthorizationExpiry). So release/refund\n * windows are extended to comfortably outlast the deadline + review buffer.\n */\nexport const REVIEW_WINDOW_SEC = 7 * 24 * 3600; // >=7 days to approve after the deadline\nexport const REFUND_WINDOW_SEC = 7 * 24 * 3600; // +7 days to refund after that\n\n/**\n * One network's escrow parameters, as published by the marketplace server\n * (e.g. Execution Market's `GET /api/v1/h2a/payment-config` →\n * `escrow_networks[network]`). Snake_case on purpose: pass the server's\n * JSON straight through so the SDK builds the paymentInfo EXACTLY like the\n * production reference.\n */\nexport interface EscrowNetworkConfig {\n chain_id: number;\n operator: string;\n escrow: string;\n token_collector: string;\n usdc: string;\n usdc_domain_name: string;\n usdc_domain_version: string;\n /** 32-byte hex PAYMENT_INFO_TYPEHASH (with or without 0x prefix). */\n payment_info_typehash: string;\n /** Server-published tier windows; falls back to ESCROW_TIER_WINDOWS. */\n tiers?: Record<string, EscrowTierWindows>;\n min_fee_bps?: number;\n max_fee_bps?: number;\n}\n\n/** paymentInfo exactly as serialized in the X-Payment-Auth wrapper. */\nexport interface EscrowPaymentInfo {\n operator: string;\n receiver: string;\n token: string;\n /** Atomic units, as string (uint120 on-chain). */\n maxAmount: string;\n preApprovalExpiry: number;\n authorizationExpiry: number;\n refundExpiry: number;\n minFeeBps: number;\n maxFeeBps: number;\n feeReceiver: string;\n /** 32-byte hex. */\n salt: string;\n}\n\nconst REQUIRED_NETWORK_KEYS: Array<keyof EscrowNetworkConfig> = [\n 'chain_id',\n 'operator',\n 'escrow',\n 'token_collector',\n 'usdc',\n 'usdc_domain_name',\n 'usdc_domain_version',\n 'payment_info_typehash',\n];\n\nfunction hex32(value: string): string {\n return value.startsWith('0x') ? value : `0x${value}`;\n}\n\n/** 32 random bytes as 0x-hex (WebCrypto when available, ethers otherwise). */\nfunction randomSalt(): string {\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n if (webCrypto?.getRandomValues) {\n const bytes = new Uint8Array(32);\n webCrypto.getRandomValues(bytes);\n return ethers.hexlify(bytes);\n }\n return ethers.hexlify(ethers.randomBytes(32));\n}\n\n/**\n * Compute the escrow EIP-3009 nonce = `AuthCaptureEscrow.getHash(paymentInfo)`.\n *\n * `keccak(chainId, escrow, keccak(PAYMENT_INFO_TYPEHASH, paymentInfo tuple\n * with payer=0))` — the payer slot is zeroed for the payer-agnostic hash;\n * the RECEIVER is part of the hash, which is why the signature commits to\n * the chosen worker. Port of `AdvancedEscrowClient._compute_nonce` /\n * `em_plugin_sdk.escrow_signing.compute_escrow_nonce`.\n *\n * @param chainId - EVM chain id.\n * @param escrowAddress - AuthCaptureEscrow contract on that chain.\n * @param paymentInfoTypehash - 32-byte hex typehash from the server config.\n * @param pi - paymentInfo exactly as serialized on the wire.\n * @returns 32-byte hex nonce (0x-prefixed, lowercase).\n */\nexport function computeEscrowNonce(\n chainId: number,\n escrowAddress: string,\n paymentInfoTypehash: string,\n pi: EscrowPaymentInfo\n): string {\n const coder = ethers.AbiCoder.defaultAbiCoder();\n\n const piTuple = [\n ethers.getAddress(pi.operator),\n ZERO_ADDRESS, // payer = 0 for the payer-agnostic hash\n ethers.getAddress(pi.receiver),\n ethers.getAddress(pi.token),\n BigInt(pi.maxAmount), // uint120\n pi.preApprovalExpiry, // uint48\n pi.authorizationExpiry, // uint48\n pi.refundExpiry, // uint48\n pi.minFeeBps, // uint16\n pi.maxFeeBps, // uint16\n ethers.getAddress(pi.feeReceiver),\n BigInt(hex32(pi.salt)), // uint256\n ];\n\n const piHash = ethers.keccak256(\n coder.encode(['bytes32', PAYMENT_INFO_TUPLE], [hex32(paymentInfoTypehash), piTuple])\n );\n return ethers.keccak256(\n coder.encode(\n ['uint256', 'address', 'bytes32'],\n [chainId, ethers.getAddress(escrowAddress), piHash]\n )\n );\n}\n\n/**\n * Minimal signer for {@link buildEscrowPreAuth}: EIP-712 typed-data signing\n * over the full typed-data JSON string (`domain`, `types`, `primaryType`,\n * `message`) — the same contract as `SigningWalletAdapter.signTypedData`,\n * so every adapter (EnvKeyAdapter, OWSWalletAdapter, custom) satisfies it\n * structurally. Browser wallets can wrap their own signTypedData in this\n * shape; the key never leaves the signer.\n */\nexport interface EscrowPreAuthSigner {\n signTypedData(typedData: string): Promise<{ signature: string }>;\n}\n\nexport interface EscrowPreAuthParams {\n /** Network escrow config as published by the marketplace server. */\n networkConfig: EscrowNetworkConfig;\n /**\n * Publisher wallet (payer). Not checked against the signer's address —\n * payer binding is enforced on-chain and by the backend, not here.\n */\n payerWallet: string;\n /** Chosen worker's wallet (escrow receiver — committed by the nonce). */\n workerWallet: string;\n /** Bounty in atomic units (6-decimal USDC). */\n bountyAtomic: string | bigint;\n /** Expiry tier; windows come from config when present. Default 'micro'. */\n tier?: string;\n /**\n * Task deadline (epoch seconds). The release/refund windows are extended\n * to outlast it + a review buffer so a human publisher can still approve\n * after the worker delivers. When omitted, falls back to now()-based\n * windows.\n */\n reviewDeadlineSec?: number;\n /**\n * On-chain deposit limit in USD (AuthCaptureEscrow deposit condition).\n * Default {@link ESCROW_DEPOSIT_LIMIT_USD}; override only when the server\n * publishes a different limit.\n */\n depositLimitUsd?: number;\n /**\n * How to find out whether `payerWallet` is EIP-7702-delegated, and to what.\n *\n * Optional, and its absence is honest rather than convenient: with no resolver\n * the verdict is UNKNOWN and this function signs the ordinary way, exactly as\n * it did before. Pass one — {@link rpcDelegationResolver} or your own — as soon\n * as your payers can be delegated accounts, because a delegated payer signing\n * the wrong dialect produces an authorization that **cannot settle on-chain**\n * and only fails at lock time.\n *\n * When a resolver IS supplied and it reaches no verdict, this throws instead of\n * guessing: an unreadable chain is not a \"not delegated\" answer.\n */\n delegationResolver?: DelegationResolver;\n}\n\n/**\n * Build + sign the escrow lock authorization AT ASSIGNMENT time and return\n * the raw JSON string for the `X-Payment-Auth` header (NOT base64 — the\n * backend relays it verbatim to the Facilitator `/settle`). Mirror of\n * `AdvancedEscrowClient.authorize()`'s /settle payload and of\n * `em_plugin_sdk.escrow_signing.build_escrow_pre_auth`.\n *\n * @throws {X402Error} `INVALID_CONFIG` on an incomplete network config,\n * unknown tier, or a `maxFeeBps` that cannot cover the operator's static\n * fee; `INVALID_AMOUNT` on a bounty outside (0, deposit limit].\n */\nexport async function buildEscrowPreAuth(\n wallet: EscrowPreAuthSigner,\n params: EscrowPreAuthParams\n): Promise<string> {\n const cfg = params.networkConfig;\n\n const missing = REQUIRED_NETWORK_KEYS.filter((key) => !cfg[key]);\n if (missing.length > 0) {\n throw new X402Error(\n `Incomplete escrow network config (missing ${missing.join(', ')}) — ` +\n 'refusing to sign an EIP-3009 authorization with a mismatched domain.',\n 'INVALID_CONFIG'\n );\n }\n\n const maxAmount = BigInt(params.bountyAtomic);\n if (maxAmount <= 0n) {\n throw new X402Error(\n `Bounty must be positive, got ${maxAmount} atomic units`,\n 'INVALID_AMOUNT'\n );\n }\n const depositLimitUsd = params.depositLimitUsd ?? ESCROW_DEPOSIT_LIMIT_USD;\n const depositLimitAtomic = BigInt(Math.round(depositLimitUsd * 10 ** USDC_DECIMALS));\n if (maxAmount > depositLimitAtomic) {\n throw new X402Error(\n `Bounty ${maxAmount} atomic units exceeds the on-chain escrow deposit ` +\n `limit ($${depositLimitUsd}).`,\n 'INVALID_AMOUNT'\n );\n }\n\n const minFeeBps = cfg.min_fee_bps ?? DEFAULT_MIN_FEE_BPS;\n const maxFeeBps = cfg.max_fee_bps ?? DEFAULT_MAX_FEE_BPS;\n if (maxFeeBps < OPERATOR_FEE_BPS) {\n throw new X402Error(\n `maxFeeBps=${maxFeeBps} cannot cover the operator's ${OPERATOR_FEE_BPS} ` +\n 'bps static fee — the on-chain release would revert.',\n 'INVALID_CONFIG'\n );\n }\n\n const tierKey = params.tier ?? 'micro';\n const windows = cfg.tiers?.[tierKey] ?? ESCROW_TIER_WINDOWS[tierKey];\n if (!windows) {\n const known = [...new Set([...Object.keys(cfg.tiers ?? {}), ...Object.keys(ESCROW_TIER_WINDOWS)])].sort();\n throw new X402Error(\n `Unknown escrow tier '${tierKey}' — known tiers: ${known.join(', ')}`,\n 'INVALID_CONFIG'\n );\n }\n\n const now = Math.floor(Date.now() / 1000);\n\n // The release window must outlast the human review. Base it on the task\n // deadline (the worker delivers near it) plus a generous buffer, and never\n // shorter than the SDK tier window. preApprovalExpiry stays short — the\n // lock executes immediately at assignment.\n const reviewBase = Math.max(now, params.reviewDeadlineSec ?? now);\n const authExpiry = Math.max(now + windows.auth, reviewBase + REVIEW_WINDOW_SEC);\n const refundExpiry = Math.max(now + windows.refund, authExpiry + REFUND_WINDOW_SEC);\n\n const paymentInfo: EscrowPaymentInfo = {\n operator: ethers.getAddress(cfg.operator),\n receiver: ethers.getAddress(params.workerWallet),\n token: ethers.getAddress(cfg.usdc),\n maxAmount: maxAmount.toString(),\n preApprovalExpiry: now + windows.pre,\n authorizationExpiry: authExpiry,\n refundExpiry: refundExpiry,\n minFeeBps: minFeeBps,\n maxFeeBps: maxFeeBps,\n feeReceiver: ethers.getAddress(cfg.operator),\n salt: randomSalt(),\n };\n\n const nonce = computeEscrowNonce(\n cfg.chain_id,\n cfg.escrow,\n cfg.payment_info_typehash,\n paymentInfo\n );\n\n const payer = ethers.getAddress(params.payerWallet);\n const tokenCollector = ethers.getAddress(cfg.token_collector);\n\n // String-valued message fields: the typed data travels as JSON to the\n // adapter (SigningWalletAdapter.signTypedData contract), and ethers\n // accepts decimal strings for uint256 / 0x-hex for bytes32.\n const typedData = {\n domain: {\n name: cfg.usdc_domain_name,\n version: cfg.usdc_domain_version,\n chainId: cfg.chain_id,\n verifyingContract: ethers.getAddress(cfg.usdc),\n },\n types: RECEIVE_WITH_AUTHORIZATION_TYPES,\n primaryType: 'ReceiveWithAuthorization',\n message: {\n from: payer,\n to: tokenCollector,\n value: maxAmount.toString(),\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce: nonce,\n },\n };\n\n // ── EIP-7702: a DELEGATED payer cannot settle a raw ECDSA authorization ──\n //\n // Once the payer's EOA carries code, USDC validates via ERC-1271 only and raw\n // ECDSA reverts (0x151d90fe) — the lock fails on-chain. Measured in production\n // 2026-07-31: 14 of 14 delegated payers failed; the one plain EOA locked fine.\n //\n // THREE STATES, and the third is the one that matters: an UNKNOWN delegation is\n // NOT \"not delegated\". Collapsing it to false is exactly how the original bug\n // survived eight days — signing raw for an account that can never settle it,\n // silently.\n //\n // AND THE DIALECT DEPENDS ON THE TARGET. \"Delegated\" is not one signature\n // scheme: the account-envelope wrap is Alchemy-SMA-specific. A delegate that\n // validates plain ECDSA through ERC-1271 — Execution Market's FeedbackDelegate,\n // which every account that has rated through the facilitator's rail is pointed\n // at — needs the ORDINARY signature. Wrapping it is as unsettleable as signing\n // raw for an SMA.\n const { delegated, target } = await resolveDelegation(\n payer,\n `eip155:${cfg.chain_id}`,\n params.delegationResolver\n );\n if (delegated === null && params.delegationResolver) {\n throw new X402Error(\n `Could not determine whether ${payer} is EIP-7702-delegated on chain ` +\n `${cfg.chain_id} (the resolver gave no verdict) — refusing to sign an ` +\n 'escrow authorization blindly: the wrong dialect is unsettleable ' +\n 'on-chain and the failure only shows up at lock time. Retry when the ' +\n 'chain is readable.',\n 'INVALID_CONFIG'\n );\n }\n\n let signature: string;\n if (delegated && (needsAccountWrap(target) || target === null)) {\n // SMA-wrap: the known Alchemy account, OR a legacy boolean-only resolver that\n // could not name the target — for which we keep the conservative behaviour\n // rather than silently changing what such callers got. A resolver that\n // returns the target lands any non-SMA delegate in the plain branch below.\n const innerDigest = ethers.TypedDataEncoder.hash(\n typedData.domain,\n typedData.types,\n typedData.message\n );\n const replaySafe = replaySafeTypedData(innerDigest, cfg.chain_id, payer);\n const wrapped = await wallet.signTypedData(\n JSON.stringify({ ...replaySafe, primaryType: 'ReplaySafeHash' })\n );\n if (!wrapped?.signature) {\n throw new X402Error(\n 'The wallet returned no signature for the replay-safe wrap — refusing ' +\n 'to build an unsettleable authorization.',\n 'INVALID_CONFIG'\n );\n }\n signature = wrapSignature(wrapped.signature);\n } else {\n // Plain EOA, unknown-with-no-resolver, or a delegate that takes ordinary\n // ECDSA (FeedbackDelegate and the standard 1271 smart-EOA pattern).\n signature = (await wallet.signTypedData(JSON.stringify(typedData))).signature;\n }\n\n // Raw JSON (NOT base64): the backend relays this verbatim to the\n // Facilitator /settle after validating payer/amount/receiver.\n return JSON.stringify({\n x402Version: 2,\n scheme: 'escrow',\n payload: {\n authorization: {\n from: payer,\n to: tokenCollector,\n value: maxAmount.toString(),\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce: nonce,\n },\n signature: signature,\n paymentInfo: paymentInfo,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${cfg.chain_id}`,\n },\n });\n}\n","/**\n * Reading a facilitator refusal as DATA instead of prose.\n *\n * # Why this file exists\n *\n * `402` and `503` say opposite things and the SDK used to collapse both into\n * `success: false` plus an English sentence.\n *\n * - **402** means the payment was REJECTED. The credential is spent; sign a new\n * authorization.\n * - **503** means NO VERDICT WAS REACHED. Nothing was rejected and nothing was\n * executed; retry the SAME credential.\n *\n * Turning a 503 into a 402 makes the buyer sign and send a second payment for a\n * money movement that was never refused — they pay twice. That is the most\n * expensive mistake this SDK can make, so every facilitator edge now reports the\n * status, the facilitator's own `reason`, and whether the request may be\n * replayed.\n *\n * # The writer lease\n *\n * The facilitator serialises every EVM write through the one process that holds\n * the EVM writer lease, because they all spend gas from the same EOA and the\n * nonce for it is allocated in memory. A task that does not hold the lease\n * forwards the request to the one that does; when it cannot, it answers\n * `503` + `Retry-After: 5` + `{\"error\": \"...\", \"reason\": \"<why>\"}`.\n *\n * The five reasons do NOT share retry semantics, which is the whole point of\n * surfacing them:\n *\n * | reason | did the write run? | replay? |\n * |----------------------------|--------------------|---------|\n * | `holder_unknown` | no | yes |\n * | `forwarding_disabled` | no | yes |\n * | `forwarded_but_not_writer` | no | yes |\n * | `body_unreadable` | no | yes |\n * | `forward_failed` | **maybe** | **no** |\n *\n * `forward_failed` is emitted after the forward was attempted: the holder may\n * have executed the write and the response been lost on the way back. It is a\n * timeout wearing a status code. Replaying a `/register` on it is exactly the\n * sequence that once minted five duplicate agents — reconcile with\n * `GET /identity/{network}/owner/{recipient}` or `getRegisterStatus` instead.\n *\n * Source of the shape: x402-rs `src/handlers.rs` `writer_lease_unavailable()`\n * and `require_writer_lease()`.\n */\n\n/**\n * A `reason` the facilitator attaches to a writer-lease 503.\n *\n * Typed as a union for discrimination but never used to VALIDATE: the fields\n * that carry it are plain `string`, so a reason added on the server does not\n * break compilation here.\n */\nexport type WriterLeaseReason =\n | 'holder_unknown'\n | 'forwarding_disabled'\n | 'forwarded_but_not_writer'\n | 'body_unreadable'\n | 'forward_failed';\n\n/** Every writer-lease reason the facilitator emits today. */\nexport const WRITER_LEASE_REASONS: readonly WriterLeaseReason[] = [\n 'holder_unknown',\n 'forwarding_disabled',\n 'forwarded_but_not_writer',\n 'body_unreadable',\n 'forward_failed',\n];\n\n/**\n * The reasons returned BEFORE the write is handed to anyone.\n *\n * The facilitator refuses these in its router, so the request provably did not\n * execute and re-sending the identical body is safe — including a mint.\n */\nexport const REPLAYABLE_LEASE_REASONS: readonly WriterLeaseReason[] = [\n 'holder_unknown',\n 'forwarding_disabled',\n 'forwarded_but_not_writer',\n 'body_unreadable',\n];\n\n/**\n * The reason that is ambiguous: the write may already have happened.\n *\n * Still `retryable` — the credential was not rejected — but never replayed\n * automatically. Resolve it by reading state, not by re-POSTing.\n */\nexport const AMBIGUOUS_LEASE_REASONS: readonly WriterLeaseReason[] = ['forward_failed'];\n\n/**\n * Ceiling, in seconds, on how long an automatic retry will wait.\n *\n * `Retry-After` is a hint from a server that may be misconfigured. Honouring a\n * literal `Retry-After: 3600` would hang the caller's request for an hour\n * inside a function documented as returning promptly, so the header is honoured\n * only up to this bound.\n */\nexport const MAX_RETRY_AFTER_SECONDS = 15;\n\n/** Wait used when a 503 carries no usable `Retry-After`. */\nexport const DEFAULT_RETRY_AFTER_SECONDS = 5;\n\n/** How many EXTRA attempts a retryable facilitator refusal gets by default. */\nexport const DEFAULT_FACILITATOR_RETRIES = 2;\n\n/**\n * A non-2xx answer from the facilitator, kept structured.\n *\n * `error` is byte-identical to the string this SDK has always produced, so\n * callers matching on it keep working; everything else is new and optional.\n */\nexport interface FacilitatorErrorInfo {\n /** Legacy flattened message: `Facilitator error: <status> - <body>`. */\n error: string;\n /** HTTP status the facilitator answered with. */\n status: number;\n /** The facilitator's own `reason`, when the body carried one. */\n reason?: string;\n /**\n * Seconds to wait before retrying, already clamped to\n * {@link MAX_RETRY_AFTER_SECONDS}. Absent when the answer is not retryable.\n */\n retryAfterSeconds?: number;\n /**\n * The request reached no verdict; the credential is untouched and the SAME\n * request may be sent again. Never surface this as a payment rejection.\n */\n retryable: boolean;\n /**\n * The facilitator NAMED a reason that proves it executed nothing, so an\n * automatic replay cannot double-write.\n *\n * False for `forward_failed`, whose write may already have landed, and false\n * for an unattributed 5xx from a proxy — \"something in front answered\" is not\n * evidence that nothing ran.\n */\n safeToReplay: boolean;\n /** Raw response body, for logs. */\n body: string;\n}\n\n/** Fields every facilitator response type gained so a 503 stops looking terminal. */\nexport interface FacilitatorFailureFields {\n /** HTTP status, when the failure was transport-level rather than a verdict. */\n status?: number;\n /** The facilitator's `reason` for the refusal (see {@link WriterLeaseReason}). */\n reason?: string;\n /** True when the same request may be sent again without re-signing anything. */\n retryable?: boolean;\n /** Seconds to wait before retrying, clamped to {@link MAX_RETRY_AFTER_SECONDS}. */\n retryAfterSeconds?: number;\n /** True when the facilitator provably executed nothing. */\n safeToReplay?: boolean;\n}\n\n/** A 503/429 that carries a reason known to be pre-execution. */\nexport function isReplayableLeaseReason(reason?: string): boolean {\n return REPLAYABLE_LEASE_REASONS.includes(reason as WriterLeaseReason);\n}\n\n/** A 503 whose write may already have run. Reconcile, do not re-POST. */\nexport function isAmbiguousLeaseReason(reason?: string): boolean {\n return AMBIGUOUS_LEASE_REASONS.includes(reason as WriterLeaseReason);\n}\n\n/**\n * Read `Retry-After` and clamp it.\n *\n * Tolerates a `Response`-shaped object with no `headers` at all: test doubles\n * and non-standard fetch polyfills routinely omit it, and throwing there would\n * turn a readable refusal into an unreadable crash.\n */\nexport function parseRetryAfterSeconds(response: {\n headers?: { get?: (name: string) => string | null };\n}): number | undefined {\n let raw: string | null | undefined;\n try {\n raw = response?.headers?.get?.('retry-after');\n } catch {\n return undefined;\n }\n if (raw === null || raw === undefined || raw === '') return undefined;\n const seconds = Number(raw);\n if (!Number.isFinite(seconds) || seconds < 0) return undefined;\n return Math.min(seconds, MAX_RETRY_AFTER_SECONDS);\n}\n\n/** Pull `reason` out of a JSON error body, if there is one and it is a string. */\nfunction reasonFrom(body: string): string | undefined {\n try {\n const parsed = JSON.parse(body) as { reason?: unknown };\n if (parsed && typeof parsed === 'object' && typeof parsed.reason === 'string') {\n return parsed.reason;\n }\n } catch {\n /* an HTML 503 from a load balancer is still a 503 */\n }\n return undefined;\n}\n\n/**\n * Turn a non-2xx facilitator response into {@link FacilitatorErrorInfo}.\n *\n * Reads the body exactly once. The `error` string keeps the historical format\n * verbatim; reformatting it would break callers that match on it.\n */\nexport async function readFacilitatorError(response: {\n status: number;\n text: () => Promise<string>;\n headers?: { get?: (name: string) => string | null };\n}): Promise<FacilitatorErrorInfo> {\n let body = '';\n try {\n body = await response.text();\n } catch {\n body = '';\n }\n const status = response.status;\n const reason = reasonFrom(body);\n // 429 is admission control and 502/503/504 are \"no verdict\". None of them is\n // a rejection of the payment, so none of them may be reported as one.\n const retryable = status === 429 || status === 502 || status === 503 || status === 504;\n const retryAfterSeconds = retryable\n ? (parseRetryAfterSeconds(response) ?? DEFAULT_RETRY_AFTER_SECONDS)\n : undefined;\n // Replay only what the facilitator SAID it did not execute.\n //\n // A 429 is admission control: the request was counted, never handled. A 503\n // that names one of the pre-execution writer-lease reasons is refused in the\n // router before any signing. Everything else — an unattributed 503 from a\n // load balancer, a 502, a 504, `forward_failed` — is merely retryable: the\n // caller may resend after reconciling, but this SDK will not do it for them,\n // because \"a proxy answered\" is not evidence that nothing ran.\n const safeToReplay = status === 429 || (status === 503 && isReplayableLeaseReason(reason));\n\n return {\n error: `Facilitator error: ${status} - ${body}`,\n status,\n reason,\n retryAfterSeconds,\n retryable,\n safeToReplay,\n body,\n };\n}\n\n/** The subset of {@link FacilitatorErrorInfo} that is copied onto a response. */\nexport function failureFields(info: FacilitatorErrorInfo): Required<\n Pick<FacilitatorFailureFields, 'status' | 'retryable' | 'safeToReplay'>\n> &\n FacilitatorFailureFields {\n return {\n status: info.status,\n retryable: info.retryable,\n safeToReplay: info.safeToReplay,\n ...(info.reason !== undefined ? { reason: info.reason } : {}),\n ...(info.retryAfterSeconds !== undefined\n ? { retryAfterSeconds: info.retryAfterSeconds }\n : {}),\n };\n}\n\n/**\n * Copy the failure fields off one response onto another.\n *\n * Used where a wrapper returns its own shape: without this the wrapper flattens\n * a `503` back into a bare failure and reintroduces, one level up, exactly the\n * ambiguity the fields exist to remove.\n */\nexport function carryFailureFields(\n source: FacilitatorFailureFields,\n): FacilitatorFailureFields {\n return {\n ...(source.status !== undefined ? { status: source.status } : {}),\n ...(source.reason !== undefined ? { reason: source.reason } : {}),\n ...(source.retryable !== undefined ? { retryable: source.retryable } : {}),\n ...(source.retryAfterSeconds !== undefined\n ? { retryAfterSeconds: source.retryAfterSeconds }\n : {}),\n ...(source.safeToReplay !== undefined ? { safeToReplay: source.safeToReplay } : {}),\n };\n}\n\n/** Options for {@link facilitatorFetch}. */\nexport interface FacilitatorFetchOptions {\n /** Abort the request after this many milliseconds. */\n timeoutMs: number;\n /** Extra attempts after the first. Default {@link DEFAULT_FACILITATOR_RETRIES}. */\n retries?: number;\n /**\n * Whether this particular refusal may be replayed.\n *\n * Default: only when the facilitator proved it executed nothing\n * (`info.safeToReplay`). Pass a stricter predicate on paths where even a\n * proven-safe replay is unwanted.\n */\n canReplay?: (info: FacilitatorErrorInfo) => boolean;\n /** Injected for tests. */\n fetchImpl?: typeof fetch;\n /** Injected for tests, so a retry does not really sleep. */\n sleepImpl?: (ms: number) => Promise<void>;\n}\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * POST/GET the facilitator, replaying a refusal that provably executed nothing.\n *\n * Returns the response plus, when it was not ok, the structured refusal — the\n * body has already been consumed to build it, so callers must not read it\n * again.\n *\n * Network errors and timeouts still THROW, exactly as before: callers already\n * have `catch` blocks that turn them into `{ success: false }`, and an\n * `AbortError` on the escrow paths triggers an on-chain reconciliation that\n * must keep firing.\n */\nexport async function facilitatorFetch(\n url: string,\n init: RequestInit,\n options: FacilitatorFetchOptions,\n): Promise<{ response: Response; error?: FacilitatorErrorInfo }> {\n const retries = options.retries ?? DEFAULT_FACILITATOR_RETRIES;\n const canReplay = options.canReplay ?? ((info: FacilitatorErrorInfo) => info.safeToReplay);\n const doFetch = options.fetchImpl ?? fetch;\n const sleep = options.sleepImpl ?? defaultSleep;\n\n let attempt = 0;\n for (;;) {\n // A fresh controller per attempt: an aborted signal stays aborted, so\n // reusing one would make every retry fail instantly.\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), options.timeoutMs);\n let response: Response;\n try {\n response = await doFetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (response.ok) return { response };\n\n const error = await readFacilitatorError(response);\n if (attempt >= retries || !error.retryable || !canReplay(error)) {\n return { response, error };\n }\n\n attempt += 1;\n await sleep((error.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS) * 1000);\n }\n}\n","/**\n * uvd-x402-sdk - Backend Utilities\n *\n * Server-side utilities for building x402 payment APIs.\n * These utilities help backend developers:\n * - Build verify/settle requests for the facilitator\n * - Parse X-PAYMENT headers from incoming requests\n * - Configure CORS for x402 payment flows\n * - Create atomic payment handlers\n * - Discover and register resources via Bazaar Discovery API\n * - Manage escrow payments with refund and dispute resolution\n *\n * @example Basic payment flow\n * ```ts\n * import {\n * parsePaymentHeader,\n * FacilitatorClient,\n * X402_CORS_HEADERS,\n * } from 'uvd-x402-sdk/backend';\n *\n * // Parse payment from request header\n * const payment = parsePaymentHeader(req.headers['x-payment']);\n *\n * // Verify with facilitator\n * const client = new FacilitatorClient();\n * const verifyResult = await client.verify(payment, paymentRequirements);\n *\n * // If valid, provide service then settle\n * const settleResult = await client.settle(payment, paymentRequirements);\n * ```\n *\n * @example Escrow payment with refund support\n * ```ts\n * import { EscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const escrow = new EscrowClient();\n *\n * // Hold payment in escrow\n * const escrowPayment = await escrow.createEscrow({\n * paymentHeader: req.headers['x-payment'],\n * requirements: paymentRequirements,\n * escrowDuration: 86400, // 24 hours\n * });\n *\n * // After service delivered, release to recipient\n * await escrow.release(escrowPayment.id);\n *\n * // Or if service failed, request refund\n * await escrow.requestRefund({\n * escrowId: escrowPayment.id,\n * reason: 'Service not delivered',\n * });\n * ```\n *\n * @example Resource discovery\n * ```ts\n * import { BazaarClient } from 'uvd-x402-sdk/backend';\n *\n * const bazaar = new BazaarClient();\n * const resources = await bazaar.discover({\n * category: 'ai',\n * network: 'base',\n * maxPrice: '0.10',\n * });\n * ```\n */\n\nimport type {\n X402Header,\n X402PayloadData,\n X402Version,\n} from '../types';\nimport { decodeX402Header, chainToCAIP2, parseNetworkIdentifier } from '../utils';\nimport { REVIEW_WINDOW_SEC, REFUND_WINDOW_SEC } from '../escrow-preauth';\nimport { getChainByName } from '../chains';\nimport {\n DEFAULT_RETRY_AFTER_SECONDS,\n carryFailureFields,\n isReplayableLeaseReason,\n facilitatorFetch,\n failureFields,\n readFacilitatorError,\n} from './facilitator-error';\nimport type { FacilitatorErrorInfo, FacilitatorFailureFields } from './facilitator-error';\n\n// A facilitator refusal is DATA, not prose. `402` and `503` say opposite things\n// and this file used to answer both with `success: false` plus a sentence --\n// see ./facilitator-error.ts for why that costs the buyer a second payment.\nexport {\n AMBIGUOUS_LEASE_REASONS,\n DEFAULT_FACILITATOR_RETRIES,\n DEFAULT_RETRY_AFTER_SECONDS,\n MAX_RETRY_AFTER_SECONDS,\n REPLAYABLE_LEASE_REASONS,\n WRITER_LEASE_REASONS,\n carryFailureFields,\n facilitatorFetch,\n isAmbiguousLeaseReason,\n isReplayableLeaseReason,\n parseRetryAfterSeconds,\n readFacilitatorError,\n} from './facilitator-error';\nexport type {\n FacilitatorErrorInfo,\n FacilitatorFailureFields,\n FacilitatorFetchOptions,\n WriterLeaseReason,\n} from './facilitator-error';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Payment requirements sent to the facilitator\n */\nexport interface PaymentRequirements {\n /** Payment scheme */\n scheme: 'exact' | 'escrow' | 'commerce';\n /** Network name (v1) or CAIP-2 identifier (v2) */\n network: string;\n /** Maximum amount required in atomic units (e.g., \"1000000\" for 1 USDC) */\n maxAmountRequired: string;\n /** Resource URL being paid for */\n resource: string;\n /** Description of what's being paid for */\n description: string;\n /** MIME type of the resource */\n mimeType: string;\n /** Recipient address for payment */\n payTo: string;\n /** Maximum timeout in seconds */\n maxTimeoutSeconds: number;\n /** Token contract address */\n asset: string;\n /** Optional output schema for the resource */\n outputSchema?: unknown;\n /** Optional extra data */\n extra?: unknown;\n}\n\n/**\n * Verify request body for the facilitator /verify endpoint\n */\nexport interface VerifyRequest {\n x402Version: X402Version;\n paymentPayload: X402Header;\n paymentRequirements: PaymentRequirements;\n}\n\n/**\n * Settle request body for the facilitator /settle endpoint\n */\nexport interface SettleRequest {\n x402Version: X402Version;\n paymentPayload: X402Header;\n paymentRequirements: PaymentRequirements;\n}\n\n/**\n * Verify response from the facilitator\n */\nexport interface VerifyResponse extends FacilitatorFailureFields {\n isValid: boolean;\n /**\n * Why the payment is not valid.\n *\n * Read `retryable` before showing this to anyone. When `retryable` is true the\n * facilitator reached NO VERDICT -- it did not reject the payment, so this\n * string is a transport diagnosis, not a rejection, and re-signing on it makes\n * the buyer pay twice.\n */\n invalidReason?: string;\n payer?: string;\n network?: string;\n}\n\n/**\n * Settle response from the facilitator\n */\nexport interface SettleResponse extends FacilitatorFailureFields {\n success: boolean;\n transactionHash?: string;\n network?: string;\n /**\n * Transport-level failure (unreachable facilitator, non-2xx, timeout).\n *\n * `success: false` with `retryable: true` is NOT a rejected payment. The\n * authorization is untouched and the same one must be resent; treating it as\n * a refusal and asking for a new signature charges the buyer twice.\n */\n error?: string;\n /**\n * The facilitator's own reason when it settled nothing — e.g. a transfer that\n * mined and reverted. Distinct from `error` above, which is this client\n * failing to ask; this one is the facilitator answering \"no\".\n */\n errorReason?: string;\n /** The address the facilitator confirmed as the payer. */\n payer?: string;\n /**\n * Settlement proof, present when the ERC-8004 extension asked for it.\n *\n * Typed here rather than only on {@link SettleResponseWithProof} because\n * `settle()` returns it whenever the facilitator sends it, and it is what\n * DX402's `anchorEvidence` needs to reach `verified: true`.\n */\n proofOfPayment?: ProofOfPayment;\n}\n\n/**\n * Options for building payment requirements\n */\nexport interface PaymentRequirementsOptions {\n /** Amount in human-readable format (e.g., \"1.00\") */\n amount: string;\n /** Recipient address */\n recipient: string;\n /** Resource URL being protected */\n resource: string;\n /** Chain name (e.g., \"base\") */\n chainName?: string;\n /** Description of the resource */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n /** Timeout in seconds (default: 300) */\n timeoutSeconds?: number;\n /** x402 version to use */\n x402Version?: X402Version;\n}\n\n/**\n * x402 payment option advertised in a 402 response.\n *\n * The SDK keeps the response shape richer than the minimal protocol fields so\n * servers can preserve settlement-critical metadata such as payTo and extra.\n */\nexport interface PaymentAcceptance {\n network: string;\n asset: string;\n amount: string;\n /**\n * Payment scheme. REQUIRED by the facilitator's v2 `PaymentRequirementsV2`.\n *\n * Optional here only so existing callers keep compiling — when it is absent,\n * `buildRequirementFromAcceptance` defaults it to `'exact'`. Do not treat its\n * optionality as \"the facilitator does not need it\": an accepts[] entry that\n * reaches a v2 client without a scheme is unpayable.\n */\n scheme?: string;\n payTo?: string;\n facilitator?: string;\n resource?: string;\n description?: string;\n mimeType?: string;\n maxTimeoutSeconds?: number;\n outputSchema?: unknown;\n extra?: unknown;\n}\n\n/**\n * Verified payment context attached by server middleware.\n */\nexport interface VerifiedPaymentState {\n payment: X402Header;\n requirements: PaymentRequirements;\n verifyResult: VerifyResponse;\n settle: () => Promise<SettleResponse>;\n}\n\n/**\n * Shared server middleware options.\n */\nexport interface PaymentMiddlewareOptions extends FacilitatorClientOptions {\n /** Alias for baseUrl to keep middleware options ergonomic */\n facilitatorUrl?: string;\n /**\n * Settlement behavior after verification.\n * - manual: verify only; caller settles explicitly\n * - before-handler: settle immediately before calling next()\n */\n settlementStrategy?: 'manual' | 'before-handler';\n}\n\n/**\n * Custom resolver for selecting the correct payment requirement when multiple\n * accepts are advertised.\n */\nexport type PaymentRequirementResolver = (\n payment: X402Header,\n requirements: PaymentRequirements[]\n) => PaymentRequirements | null | Promise<PaymentRequirements | null>;\n\n// ============================================================================\n// HEADER PARSING\n// ============================================================================\n\n/**\n * Parse X-PAYMENT or PAYMENT-SIGNATURE header value\n *\n * @param headerValue - Base64-encoded header value (or undefined/null)\n * @returns Parsed x402 header object, or null if invalid\n *\n * @example\n * ```ts\n * // Express.js\n * const payment = parsePaymentHeader(req.headers['x-payment']);\n * if (!payment) {\n * return res.status(400).json({ error: 'Invalid payment header' });\n * }\n * ```\n */\nexport function parsePaymentHeader(\n headerValue: string | undefined | null\n): X402Header | null {\n if (!headerValue) {\n return null;\n }\n\n try {\n return decodeX402Header(headerValue);\n } catch {\n return null;\n }\n}\n\n/**\n * Extract payment header from request headers object\n *\n * Checks both X-PAYMENT and PAYMENT-SIGNATURE headers.\n *\n * @param headers - Request headers object (case-insensitive)\n * @returns Parsed x402 header object, or null if not found/invalid\n *\n * @example\n * ```ts\n * const payment = extractPaymentFromHeaders(req.headers);\n * ```\n */\nexport function extractPaymentFromHeaders(\n headers: Record<string, string | string[] | undefined>\n): X402Header | null {\n // Normalize header keys to lowercase\n const normalizedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (typeof value === 'string') {\n normalizedHeaders[key.toLowerCase()] = value;\n } else if (Array.isArray(value) && value.length > 0) {\n normalizedHeaders[key.toLowerCase()] = value[0];\n }\n }\n\n // Try X-PAYMENT first, then PAYMENT-SIGNATURE\n const headerValue =\n normalizedHeaders['x-payment'] ||\n normalizedHeaders['payment-signature'];\n\n return parsePaymentHeader(headerValue);\n}\n\n// ============================================================================\n// REQUEST BUILDERS\n// ============================================================================\n\n/**\n * Build payment requirements for the facilitator\n *\n * @param options - Payment requirements options\n * @returns PaymentRequirements object ready for verify/settle\n *\n * @example\n * ```ts\n * const requirements = buildPaymentRequirements({\n * amount: '1.00',\n * recipient: '0x1234...',\n * resource: 'https://api.example.com/premium-data',\n * chainName: 'base',\n * });\n * ```\n */\nexport function buildPaymentRequirements(\n options: PaymentRequirementsOptions\n): PaymentRequirements {\n const {\n amount,\n recipient,\n resource,\n chainName = 'base',\n description = 'Payment for resource access',\n mimeType = 'application/json',\n timeoutSeconds = 300,\n x402Version = 1,\n } = options;\n\n const chain = getChainByName(chainName);\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n\n // Convert amount to atomic units\n const atomicAmount = Math.floor(\n parseFloat(amount) * Math.pow(10, chain.usdc.decimals)\n ).toString();\n\n // Use CAIP-2 for v2, chain name for v1\n const network = x402Version === 2 ? chainToCAIP2(chainName) : chainName;\n\n return {\n scheme: 'exact',\n network,\n maxAmountRequired: atomicAmount,\n resource,\n description,\n mimeType,\n payTo: recipient,\n maxTimeoutSeconds: timeoutSeconds,\n asset: chain.usdc.address,\n };\n}\n\n/**\n * Build a verify request for the facilitator /verify endpoint\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns VerifyRequest body ready for fetch/axios\n *\n * @example\n * ```ts\n * const payment = parsePaymentHeader(req.headers['x-payment']);\n * const verifyBody = buildVerifyRequest(payment, requirements);\n *\n * const response = await fetch('https://facilitator.uvd.xyz/verify', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify(verifyBody),\n * });\n * ```\n */\nexport function buildVerifyRequest(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n): VerifyRequest {\n return {\n x402Version: paymentHeader.x402Version,\n paymentPayload: paymentHeader,\n paymentRequirements: requirements,\n };\n}\n\n/**\n * Build a settle request for the facilitator /settle endpoint\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns SettleRequest body ready for fetch/axios\n */\n/**\n * Describes the protected resource, as x402 v2 expects it.\n *\n * Note this is an OBJECT in v2. Sending a bare URL string here is the single\n * most common v2 mistake and it fails as an unhelpful \"no variant matched\"\n * deserialization error at the facilitator, naming no field.\n */\nexport interface ResourceInfoV2 {\n url: string;\n description: string;\n mimeType: string;\n}\n\n/**\n * Payment requirements in x402 v2 form.\n *\n * Differences from v1 that actually bite:\n * - `network` is CAIP-2 (`eip155:8453`), NOT a plain name (`base`). Mixing a v1\n * name into a v2 request fails deserialization, and vice versa.\n * - `maxAmountRequired` is renamed to `amount`.\n * - `resource` / `description` / `mimeType` moved out to {@link ResourceInfoV2}.\n */\nexport interface PaymentRequirementsV2 {\n scheme: string;\n /** CAIP-2 chain id, e.g. `eip155:8453`. */\n network: string;\n asset: string;\n amount: string;\n payTo: string;\n maxTimeoutSeconds: number;\n extra?: unknown;\n}\n\n/** The v2 payment payload — note it carries no top-level scheme/network. */\nexport interface PaymentPayloadV2 {\n x402Version: 2;\n resource: ResourceInfoV2;\n accepted: PaymentRequirementsV2;\n payload: X402PayloadData;\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Verify request body in x402 v2 form.\n *\n * There is deliberately NO `paymentRequirements` key: that is the v1 envelope.\n * v2 carries `resource` and `accepted` at the top level instead.\n */\nexport interface VerifyRequestV2 {\n x402Version: 2;\n paymentPayload: PaymentPayloadV2;\n resource: ResourceInfoV2;\n accepted: PaymentRequirementsV2;\n}\n\n/** Settle request body in x402 v2 form. Same shape as {@link VerifyRequestV2}. */\nexport type SettleRequestV2 = VerifyRequestV2;\n\nfunction buildV2Envelope(\n payload: X402PayloadData,\n resource: ResourceInfoV2,\n accepted: PaymentRequirementsV2\n): VerifyRequestV2 {\n return {\n x402Version: 2,\n // The facilitator reads the payload from here; `resource` and `accepted` are\n // repeated at the top level because the v2 envelope declares both.\n paymentPayload: { x402Version: 2, resource, accepted, payload },\n resource,\n accepted,\n };\n}\n\n/**\n * Build a verify request for the facilitator `/verify` endpoint, in **v2** form.\n *\n * Use this whenever your 402 advertises CAIP-2 networks. {@link buildVerifyRequest}\n * emits the v1 envelope `{x402Version, paymentPayload, paymentRequirements}` and\n * cannot express v2 — putting a v2 payload inside it matches no variant at the\n * facilitator and fails with an error that names no field.\n *\n * @example\n * ```ts\n * const body = buildVerifyRequestV2(\n * payment.payload,\n * { url: 'https://api.example.com/thing', description: 'Thing', mimeType: 'application/json' },\n * { scheme: 'exact', network: 'eip155:8453', asset: '0x8335...', amount: '100000',\n * payTo: '0xabc...', maxTimeoutSeconds: 300 }\n * );\n * ```\n */\nexport function buildVerifyRequestV2(\n payload: X402PayloadData,\n resource: ResourceInfoV2,\n accepted: PaymentRequirementsV2\n): VerifyRequestV2 {\n return buildV2Envelope(payload, resource, accepted);\n}\n\n/**\n * Build a settle request for the facilitator `/settle` endpoint, in **v2** form.\n *\n * See {@link buildVerifyRequestV2} — the envelope is identical.\n */\nexport function buildSettleRequestV2(\n payload: X402PayloadData,\n resource: ResourceInfoV2,\n accepted: PaymentRequirementsV2\n): SettleRequestV2 {\n return buildV2Envelope(payload, resource, accepted);\n}\n\nexport function buildSettleRequest(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n): SettleRequest {\n return {\n x402Version: paymentHeader.x402Version,\n paymentPayload: paymentHeader,\n paymentRequirements: requirements,\n };\n}\n\n// ============================================================================\n// CORS CONFIGURATION\n// ============================================================================\n\n/**\n * Recommended CORS headers for x402 payment APIs\n *\n * These headers allow browsers to send payment headers in cross-origin requests.\n */\nexport const X402_CORS_HEADERS = {\n 'Access-Control-Allow-Headers':\n 'Content-Type, X-PAYMENT, PAYMENT-SIGNATURE, Authorization',\n 'Access-Control-Expose-Headers':\n 'X-PAYMENT-RESPONSE, PAYMENT-RESPONSE, PAYMENT-REQUIRED',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n} as const;\n\n/**\n * All x402 custom header names that should be allowed in CORS\n */\nexport const X402_HEADER_NAMES = [\n 'X-PAYMENT',\n 'PAYMENT-SIGNATURE',\n 'X-PAYMENT-RESPONSE',\n 'PAYMENT-RESPONSE',\n 'PAYMENT-REQUIRED',\n] as const;\n\n/**\n * Get CORS headers with custom origin\n *\n * @param origin - Allowed origin (use '*' for any, or specific domain)\n * @returns Complete CORS headers object\n *\n * @example\n * ```ts\n * // Express.js middleware\n * app.use((req, res, next) => {\n * const corsHeaders = getCorsHeaders('https://myapp.com');\n * Object.entries(corsHeaders).forEach(([key, value]) => {\n * res.setHeader(key, value);\n * });\n * if (req.method === 'OPTIONS') {\n * return res.status(204).end();\n * }\n * next();\n * });\n * ```\n */\nexport function getCorsHeaders(origin: string = '*'): Record<string, string> {\n return {\n 'Access-Control-Allow-Origin': origin,\n ...X402_CORS_HEADERS,\n };\n}\n\n// ============================================================================\n// FACILITATOR CLIENT\n// ============================================================================\n\n/**\n * Options for the FacilitatorClient\n */\nexport interface FacilitatorClientOptions {\n /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */\n baseUrl?: string;\n /**\n * Request timeout in milliseconds (default: auto per network).\n * When not set, the client uses per-network defaults from ESCROW_TIMEOUT_MS\n * (960s for Ethereum L1, 90s for L2s, 30s for others).\n * Set explicitly to override per-network auto-detection.\n */\n timeout?: number;\n /**\n * Extra attempts after the first when the facilitator answers a refusal it\n * proved it did not execute (`safeToReplay`). Default 2; `0` disables.\n *\n * Only ever spent on `429` and on a `503` naming a pre-execution writer-lease\n * reason. An ambiguous `forward_failed` -- whose write may already have landed\n * -- is never replayed here, at any setting.\n */\n retries?: number;\n}\n\n/**\n * Client for interacting with the x402 facilitator API\n *\n * @example\n * ```ts\n * const client = new FacilitatorClient();\n *\n * // Verify a payment\n * const verifyResult = await client.verify(paymentHeader, requirements);\n * if (!verifyResult.isValid) {\n * return res.status(402).json({ error: verifyResult.invalidReason });\n * }\n *\n * // Provide the service, then settle\n * const settleResult = await client.settle(paymentHeader, requirements);\n * if (!settleResult.success) {\n * // Handle settlement failure (maybe refund or retry)\n * }\n * ```\n */\nexport class FacilitatorClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly explicitTimeout: boolean;\n private readonly retries: number | undefined;\n\n constructor(options: FacilitatorClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';\n this.explicitTimeout = options.timeout !== undefined;\n this.timeout = options.timeout || 30000;\n this.retries = options.retries;\n }\n\n /**\n * Get timeout for a specific network, using per-chain defaults when no explicit timeout was set.\n */\n private getTimeout(network?: string): number {\n if (this.explicitTimeout) return this.timeout;\n if (!network) return this.timeout;\n // Extract chainId from CAIP-2 format (eip155:1) or legacy names\n const match = network.match(/^eip155:(\\d+)$/);\n if (match) {\n const chainId = parseInt(match[1], 10);\n return ESCROW_TIMEOUT_MS[chainId] || this.timeout;\n }\n // Legacy network name mapping for Ethereum\n if (network === 'ethereum' || network === 'ethereum-mainnet') return ESCROW_TIMEOUT_MS[1];\n return this.timeout;\n }\n\n /**\n * Verify a payment with the facilitator\n *\n * Call this before providing the paid resource to validate the payment.\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns Verification result\n */\n async verify(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n ): Promise<VerifyResponse> {\n const body = buildVerifyRequest(paymentHeader, requirements);\n\n try {\n const { response, error } = await facilitatorFetch(\n `${this.baseUrl}/verify`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n\n if (error) {\n // `isValid: false` is unavoidable -- nothing was validated -- but it is\n // no longer the whole story. A caller that answers 402 on this without\n // reading `retryable` tells the buyer their payment was REFUSED and\n // asks them to sign another one, for a payment the facilitator never\n // looked at. That is the double-charge this field exists to prevent.\n return {\n isValid: false,\n invalidReason: error.error,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // A thrown error is a transport failure (timeout, DNS, connection reset).\n // No verdict was reached either, so it is retryable for exactly the same\n // reason a 503 is -- and it used to be reported as an invalid payment.\n return {\n isValid: false,\n invalidReason: error instanceof Error ? error.message : 'Unknown error',\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Settle a payment with the facilitator\n *\n * Call this after providing the paid resource to execute the on-chain transfer.\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns Settlement result with transaction hash\n */\n async settle(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n ): Promise<SettleResponse> {\n const body = buildSettleRequest(paymentHeader, requirements);\n const settleTimeout = this.getTimeout(requirements.network);\n\n try {\n // A `/settle` refusal that the facilitator proved it did not execute is\n // replayed here with the SAME authorization. That is safe twice over: the\n // facilitator refused in its router before signing anything, and the\n // authorization carries a single-use nonce the chain rejects on a real\n // duplicate. What is NOT replayed is `forward_failed` -- the hop to the\n // lease holder died after handing the write over, so the transfer may\n // already be mining.\n const { response, error } = await facilitatorFetch(\n `${this.baseUrl}/settle`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n },\n { timeoutMs: settleTimeout, retries: this.retries },\n );\n\n if (error) {\n return {\n success: false,\n error: error.error,\n ...failureFields(error),\n };\n }\n\n const result = await response.json();\n // Read all three spellings. The facilitator's canonical name for this\n // field is `transaction`, and this client used to read only the two\n // camel/snake variants — so it silently returned `undefined` for the\n // most important field a settle produces. A consumer failed closed on\n // that and revoked access to a payment that had already settled\n // on-chain: the money moved, the receipt was unreadable.\n //\n // The server now emits all three, but this fallback stays: it makes the\n // client work against facilitators that have not deployed that yet, and\n // against any that only ever emitted the canonical name.\n const transactionHash =\n result.transaction ?? result.transactionHash ?? result.transaction_hash;\n if (result.success && !transactionHash) {\n // Never let a missing hash pass as a normal success. A caller that\n // gates access on the receipt needs to know the receipt is absent,\n // not infer it from an undefined field.\n console.warn(\n '[x402] settle reported success but carried no transaction hash under ' +\n 'transaction/transactionHash/transaction_hash — treat delivery as unconfirmed'\n );\n }\n return {\n // Read the facilitator's verdict instead of asserting one.\n //\n // This was the literal `true`, so a settle was reported successful\n // whenever the HTTP call was — and \"the request arrived\" is not \"the\n // money moved\". A payment that MINES AND THEN REVERTS is answered with\n // 200 and `success: false` (x402-rs src/chain/evm.rs:1343, serialised\n // through StatusCode::OK), which is precisely the case a caller most\n // needs to hear about. Every consumer doing `result.success === true`\n // was reading a constant, so a reverted payment was booked as settled\n // and no reconciliation path could ever fire.\n //\n // Absent `success` is treated as NOT successful: a facilitator that\n // does not say it worked has not said it worked.\n success: result.success === true,\n transactionHash,\n network: result.network,\n // Why it failed, when it did. Without this the caller gets `success:\n // false` and no way to tell a reverted transfer from a rejected\n // authorization except by parsing prose.\n errorReason: result.errorReason ?? result.error_reason,\n // The settlement proof, when the facilitator attached one (it does for\n // the ERC-8004 extension). Dropping it here made `verified: true`\n // unreachable for DX402 anchoring through this client: `anchorEvidence`\n // documents proofOfPayment as the only thing that gets there, the\n // facilitator returns it, and this method threw it away — so a seller\n // using the SDK end to end could only ever produce provisional anchors.\n proofOfPayment: result.proofOfPayment ?? result.proof_of_payment,\n payer: result.payer,\n };\n } catch (error) {\n // Timeout or connection failure. The write may have landed -- this is the\n // same ambiguity as `forward_failed`, so it is retryable but never\n // replayed automatically. Reconcile on-chain, or by transaction hash,\n // before sending anything again.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Verify and settle atomically\n *\n * Convenience method that verifies first, then settles if valid.\n * Use this for simple payment flows where you don't need custom logic between verify and settle.\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns Combined result with verify and settle status\n */\n async verifyAndSettle(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n ): Promise<\n {\n verified: boolean;\n settled: boolean;\n transactionHash?: string;\n error?: string;\n } & FacilitatorFailureFields\n > {\n // Verify first\n const verifyResult = await this.verify(paymentHeader, requirements);\n if (!verifyResult.isValid) {\n // Carry the refusal's shape up. Flattening it to `verified: false` here\n // would undo the whole point one level below: the caller could not tell a\n // rejected authorization from a facilitator that never answered.\n return {\n verified: false,\n settled: false,\n error: verifyResult.invalidReason,\n ...carryFailureFields(verifyResult),\n };\n }\n\n // Settle\n const settleResult = await this.settle(paymentHeader, requirements);\n return {\n verified: true,\n settled: settleResult.success,\n transactionHash: settleResult.transactionHash,\n error: settleResult.error,\n ...carryFailureFields(settleResult),\n };\n }\n\n /**\n * Check if the facilitator is healthy\n *\n * @returns True if the facilitator is responding\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/health`, {\n method: 'GET',\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n\n /**\n * Get the facilitator version info\n *\n * @returns Version info (e.g., { version: \"1.37.0\" })\n */\n async getVersion(): Promise<{ version: string; [key: string]: unknown }> {\n const response = await fetch(`${this.baseUrl}/version`, {\n method: 'GET',\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /version failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Get the facilitator's supported networks and payment schemes\n *\n * @returns Supported networks/schemes with 'kinds' array\n *\n * @example\n * ```ts\n * const supported = await client.getSupported();\n * for (const kind of supported.kinds) {\n * console.log(`${kind.network} - ${kind.scheme}`);\n * }\n * ```\n */\n async getSupported(): Promise<{\n kinds: Array<{ network: string; scheme: string; [key: string]: unknown }>;\n [key: string]: unknown;\n }> {\n const response = await fetch(`${this.baseUrl}/supported`, {\n method: 'GET',\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /supported failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Aggregated totals per network and asset (`GET /api/stats`).\n *\n * **An index, not a ledger.** Records are written best-effort AFTER\n * settlement, so an outage loses rows while payments proceed — verify\n * anything that matters against the transaction hash. Counting starts when\n * the operator enabled the store, so earlier operations are UNKNOWN, not\n * zero. And unless `X402_EVENTS_PUBLISH_FAILURES=true`, operations that ERROR\n * are not recorded at all: a 100% success rate means \"no failures were\n * recorded\".\n *\n * `volumeAtomic` is a STRING (u256-shaped; a JS number loses precision above\n * 2^53) and each row carries its own `decimals`. **Use that, never a\n * constant** — USDC is 6 decimals nearly everywhere and 18 on BSC, so scaling\n * by 6 there overstates volume by 10^12. `decimals` is null when the asset is\n * unrecognised; render the atomic value rather than guessing a scale.\n */\n async getStats(): Promise<{\n totals: { settlesOk: number; settlesFailed: number; verifies: number; networks: number };\n byNetworkAndAsset: Array<{\n network: string;\n asset: string;\n settlesOk: number;\n settlesFailed: number;\n verifies: number;\n volumeAtomic: string;\n decimals: number | null;\n lastTs: number;\n }>;\n [key: string]: unknown;\n }> {\n const response = await fetch(`${this.baseUrl}/api/stats`, { method: 'GET' });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /api/stats failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Recent recorded operations, newest first (`GET /transactions`).\n *\n * There is **no pagination and no cursor**: this returns the newest N,\n * walking back at most 30 days. With 10,000 rows you get the newest 200, not\n * page one of fifty. `limit` is clamped to 200 by the facilitator.\n *\n * `network` matches the canonical slug `/supported` uses, which is not always\n * the alias you may send — `skale` is accepted inbound but records say\n * `skale-base`.\n */\n async getTransactions(options: { limit?: number; network?: string } = {}): Promise<{\n transactions: Array<Record<string, unknown>>;\n count: number;\n [key: string]: unknown;\n }> {\n const params = new URLSearchParams();\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.network) params.set('network', options.network);\n const query = params.toString();\n const response = await fetch(\n `${this.baseUrl}/transactions${query ? `?${query}` : ''}`,\n { method: 'GET' }\n );\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /transactions failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Get the facilitator's blocked/sanctioned addresses\n *\n * @returns Blacklist info (totalBlocked, loadedAtStartup, addresses)\n *\n * @example\n * ```ts\n * const bl = await client.getBlacklist();\n * console.log(`Blocked: ${bl.totalBlocked} addresses`);\n * ```\n */\n async getBlacklist(): Promise<{\n totalBlocked: number;\n loadedAtStartup: boolean;\n [key: string]: unknown;\n }> {\n const response = await fetch(`${this.baseUrl}/blacklist`, {\n method: 'GET',\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /blacklist failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Negotiate payment requirements with the facilitator via POST /accepts.\n *\n * Sends merchant payment requirements to the facilitator, which matches\n * them against its supported capabilities and returns enriched requirements\n * with facilitator data (feePayer, tokens, escrow configuration).\n *\n * This is used by Faremeter middleware and clients that need to discover\n * what the facilitator can settle before constructing payment authorizations.\n *\n * @param paymentRequirements - List of payment requirement objects\n * @param x402Version - x402 protocol version (default: 2)\n * @returns List of enriched payment requirements with facilitator extras\n *\n * @example\n * ```ts\n * const enriched = await client.accepts([\n * {\n * scheme: 'exact',\n * network: 'base-mainnet',\n * maxAmountRequired: '1000000',\n * resource: 'https://api.example.com/data',\n * payTo: '0xMerchant...',\n * },\n * ]);\n * // enriched[0].extra.feePayer is now set\n * ```\n */\n async accepts(\n paymentRequirements: PaymentRequirements[],\n x402Version: number = 2\n ): Promise<PaymentRequirements[]> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/accepts`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n x402Version,\n accepts: paymentRequirements,\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Facilitator /accepts error: ${response.status} - ${errorText}`);\n }\n\n const data = await response.json();\n return data.accepts || [];\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n}\n\n// ============================================================================\n// ATOMIC PAYMENT HELPERS\n// ============================================================================\n\n/**\n * Create a 402 Payment Required response\n *\n * @param requirements - Payment requirements\n * @param options - Additional response options\n * @returns Object with status code, headers, and body for the 402 response\n *\n * @example\n * ```ts\n * // Express.js\n * app.get('/premium-data', (req, res) => {\n * const payment = extractPaymentFromHeaders(req.headers);\n *\n * if (!payment) {\n * const { status, headers, body } = create402Response({\n * amount: '1.00',\n * recipient: '0x...',\n * resource: 'https://api.example.com/premium-data',\n * });\n * return res.status(status).set(headers).json(body);\n * }\n *\n * // Verify and serve...\n * });\n * ```\n */\nexport function create402Response(\n requirements: PaymentRequirementsOptions,\n options: {\n accepts?: PaymentAcceptance[];\n } = {}\n): {\n status: 402;\n headers: Record<string, string>;\n body: Record<string, unknown>;\n} {\n const primaryRequirement = buildPaymentRequirements(requirements);\n const version = requirements.x402Version\n || ((options.accepts && options.accepts.length > 0)\n || primaryRequirement.network.includes(':')\n || (options.accepts || []).some((accept) => accept.network.includes(':'))\n ? 2\n : 1);\n const advertisedRequirements = [\n normalizeRequirementForVersion(primaryRequirement, version),\n ...(options.accepts || []).map((accept) =>\n buildRequirementFromAcceptance(accept, primaryRequirement.resource, version, primaryRequirement)\n ),\n ];\n const body = create402ResponseBody(advertisedRequirements[0], advertisedRequirements, version);\n\n return {\n status: 402,\n headers: {\n 'Content-Type': 'application/json',\n ...X402_CORS_HEADERS,\n },\n body,\n };\n}\n\nconst DEFAULT_PAYMENT_DESCRIPTION = 'Payment required';\nconst DEFAULT_PAYMENT_MIME_TYPE = 'application/json';\nconst DEFAULT_PAYMENT_TIMEOUT_SECONDS = 300;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction resolveAdvertisedVersion(\n accepts: PaymentAcceptance[],\n requestedVersion?: X402Version | 'auto'\n): X402Version {\n if (requestedVersion && requestedVersion !== 'auto') {\n return requestedVersion;\n }\n\n if (accepts.length > 1 || accepts.some((accept) => accept.network.includes(':'))) {\n return 2;\n }\n\n return 1;\n}\n\nfunction normalizeRequirementForVersion(\n requirements: PaymentRequirements,\n version: X402Version\n): PaymentRequirements {\n return {\n ...requirements,\n network: version === 2\n ? (requirements.network.includes(':') ? requirements.network : chainToCAIP2(requirements.network))\n : (requirements.network.includes(':') ? parseNetworkIdentifier(requirements.network) : requirements.network),\n };\n}\n\nfunction buildRequirementFromAcceptance(\n accept: PaymentAcceptance,\n resource: string,\n version: X402Version,\n defaults?: PaymentRequirements\n): PaymentRequirements {\n const payTo = accept.payTo ?? defaults?.payTo;\n if (!payTo) {\n throw new Error('Payment accepts entries must include payTo');\n }\n\n return normalizeRequirementForVersion({\n // Honour a caller-supplied scheme; 'exact' is the default, not an override.\n // Hardcoding it silently discarded 'escrow' / 'commerce' accepts.\n scheme: (accept.scheme as PaymentRequirements['scheme']) ?? 'exact',\n network: accept.network,\n maxAmountRequired: accept.amount,\n resource: accept.resource ?? defaults?.resource ?? resource,\n description: accept.description ?? defaults?.description ?? DEFAULT_PAYMENT_DESCRIPTION,\n mimeType: accept.mimeType ?? defaults?.mimeType ?? DEFAULT_PAYMENT_MIME_TYPE,\n payTo,\n asset: accept.asset,\n maxTimeoutSeconds: accept.maxTimeoutSeconds ?? defaults?.maxTimeoutSeconds ?? DEFAULT_PAYMENT_TIMEOUT_SECONDS,\n ...(accept.outputSchema !== undefined\n ? { outputSchema: accept.outputSchema }\n : defaults?.outputSchema !== undefined\n ? { outputSchema: defaults.outputSchema }\n : {}),\n ...(accept.extra !== undefined\n ? { extra: accept.extra }\n : defaults?.extra !== undefined\n ? { extra: defaults.extra }\n : {}),\n }, version);\n}\n\nfunction toPaymentAcceptance(\n requirements: PaymentRequirements,\n facilitator?: string\n): PaymentAcceptance {\n return {\n network: requirements.network,\n asset: requirements.asset,\n amount: requirements.maxAmountRequired,\n // scheme is REQUIRED by the facilitator's v2 PaymentRequirementsV2. Dropping it\n // here produced an accepts[] entry that no v2 client could pay: the spec makes\n // the client echo the accept verbatim, so the omission travelled downstream and\n // died in deserialization with an error naming no field.\n scheme: requirements.scheme,\n payTo: requirements.payTo,\n resource: requirements.resource,\n description: requirements.description,\n mimeType: requirements.mimeType,\n maxTimeoutSeconds: requirements.maxTimeoutSeconds,\n ...(facilitator ? { facilitator } : {}),\n ...(requirements.outputSchema !== undefined ? { outputSchema: requirements.outputSchema } : {}),\n ...(requirements.extra !== undefined ? { extra: requirements.extra } : {}),\n };\n}\n\nfunction create402ResponseBody(\n primaryRequirement: PaymentRequirements,\n advertisedRequirements: PaymentRequirements[],\n version: X402Version,\n facilitator?: string\n): Record<string, unknown> {\n const normalizedPrimary = normalizeRequirementForVersion(primaryRequirement, version);\n const normalizedAdvertised = advertisedRequirements.map((requirements) =>\n normalizeRequirementForVersion(requirements, version)\n );\n\n const body: Record<string, unknown> = {\n x402Version: version,\n ...normalizedPrimary,\n };\n\n if (version === 2 && normalizedAdvertised.length > 1) {\n body.accepts = normalizedAdvertised.map((requirements) =>\n toPaymentAcceptance(requirements, facilitator)\n );\n }\n\n return body;\n}\n\nfunction getComparableNetwork(network: string): string {\n return parseNetworkIdentifier(network).toLowerCase();\n}\n\nfunction getPaymentRecipient(payment: X402Header): string | undefined {\n const payload = payment.payload as unknown;\n if (!isObject(payload)) {\n return undefined;\n }\n const authorization = payload.authorization;\n\n if (isObject(authorization) && typeof authorization.to === 'string') {\n return authorization.to.toLowerCase();\n }\n\n if (typeof payload.to === 'string') {\n return payload.to.toLowerCase();\n }\n\n return undefined;\n}\n\nfunction getPaymentAmount(payment: X402Header): string | undefined {\n const payload = payment.payload as unknown;\n if (!isObject(payload)) {\n return undefined;\n }\n const authorization = payload.authorization;\n\n if (isObject(authorization) && typeof authorization.value === 'string') {\n return authorization.value;\n }\n\n if (typeof payload.amount === 'string') {\n return payload.amount;\n }\n\n return undefined;\n}\n\nfunction getPaymentAsset(payment: X402Header): string | undefined {\n const payload = payment.payload as unknown;\n if (!isObject(payload)) {\n return undefined;\n }\n\n if (typeof payload.tokenContract === 'string') {\n return payload.tokenContract.toLowerCase();\n }\n\n return undefined;\n}\n\nasync function resolvePaymentRequirement(\n payment: X402Header,\n requirements: PaymentRequirements[],\n resolver?: PaymentRequirementResolver\n): Promise<{ requirement: PaymentRequirements | null; reason?: string }> {\n const normalizedRequirements = requirements.map((requirements) =>\n normalizeRequirementForVersion(requirements, payment.x402Version)\n );\n\n if (resolver) {\n const resolved = await resolver(payment, normalizedRequirements);\n return {\n requirement: resolved\n ? normalizeRequirementForVersion(resolved, payment.x402Version)\n : null,\n ...(resolved ? {} : { reason: 'Custom requirement resolver did not return a matching requirement.' }),\n };\n }\n\n const networkMatches = normalizedRequirements.filter((requirements) =>\n getComparableNetwork(requirements.network) === getComparableNetwork(payment.network)\n );\n\n if (networkMatches.length === 0) {\n return {\n requirement: null,\n reason: `No advertised payment requirement matched network ${payment.network}.`,\n };\n }\n\n let matches = networkMatches;\n\n const paymentRecipient = getPaymentRecipient(payment);\n if (paymentRecipient) {\n const recipientMatches = matches.filter((requirements) =>\n requirements.payTo.toLowerCase() === paymentRecipient\n );\n if (recipientMatches.length === 0) {\n return {\n requirement: null,\n reason: 'Payment recipient does not match any advertised requirement.',\n };\n }\n matches = recipientMatches;\n }\n\n const paymentAmount = getPaymentAmount(payment);\n if (paymentAmount) {\n const amountMatches = matches.filter((requirements) =>\n requirements.maxAmountRequired === paymentAmount\n );\n if (amountMatches.length === 0) {\n return {\n requirement: null,\n reason: 'Payment amount does not match any advertised requirement.',\n };\n }\n matches = amountMatches;\n }\n\n const paymentAsset = getPaymentAsset(payment);\n if (paymentAsset) {\n const assetMatches = matches.filter((requirements) =>\n requirements.asset.toLowerCase() === paymentAsset\n );\n if (assetMatches.length === 0) {\n return {\n requirement: null,\n reason: 'Payment asset does not match any advertised requirement.',\n };\n }\n matches = assetMatches;\n }\n\n if (matches.length !== 1) {\n return {\n requirement: null,\n reason: 'Payment matched multiple advertised requirements. Advertise unique network/payTo/amount combinations or provide resolveRequirement().',\n };\n }\n\n return { requirement: matches[0] };\n}\n\nfunction createVerifiedPaymentState(\n client: FacilitatorClient,\n payment: X402Header,\n requirements: PaymentRequirements,\n verifyResult: VerifyResponse\n): VerifiedPaymentState {\n let settlePromise: Promise<SettleResponse> | null = null;\n return {\n payment,\n requirements,\n verifyResult,\n settle: () => {\n if (!settlePromise) {\n settlePromise = client.settle(payment, requirements);\n }\n return settlePromise;\n },\n };\n}\n\n/**\n * Answer a no-verdict facilitator refusal as 503 + `Retry-After`.\n *\n * The body repeats the facilitator's own `reason` and a `retryable` flag so a\n * client that only reads JSON still learns the payment was not rejected. The\n * header is a whole-second integer, as RFC 9110 requires.\n */\nfunction respondUnavailable(\n res: {\n status: (code: number) => {\n json: (body: unknown) => void;\n set: (headers: Record<string, string>) => { json: (body: unknown) => void };\n };\n },\n message: string,\n failure: FacilitatorFailureFields & { error?: string; invalidReason?: string },\n): void {\n const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));\n const body = {\n error: message,\n reason: failure.reason ?? failure.invalidReason ?? failure.error,\n retryable: true,\n retryAfterSeconds: seconds,\n // False for `forward_failed` and for a bare timeout: the write may already\n // have landed, so the caller must reconcile before resending.\n safeToReplay: failure.safeToReplay === true,\n };\n const staged = res.status(503);\n if (typeof staged.set === 'function') {\n staged.set({ 'Retry-After': String(seconds) }).json(body);\n return;\n }\n staged.json(body);\n}\n\n/**\n * Create an Express-compatible middleware for x402 payments\n *\n * @param getRequirements - Function to get payment requirements for a request\n * @param options - Middleware options\n * @returns Express middleware function\n *\n * @example\n * ```ts\n * const paymentMiddleware = createPaymentMiddleware(\n * (req) => ({\n * amount: '1.00',\n * recipient: process.env.PAYMENT_RECIPIENT,\n * resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`,\n * }),\n * { facilitatorUrl: 'https://facilitator.uvd.xyz' }\n * );\n *\n * app.get('/premium/*', paymentMiddleware, async (req, res) => {\n * const settleResult = await req.x402?.settle();\n * if (!settleResult?.success) {\n * return res.status(500).json({ error: settleResult?.error });\n * }\n *\n * res.json({ premium: 'data' });\n * });\n * ```\n */\nexport function createPaymentMiddleware(\n getRequirements: (req: { headers: Record<string, string | string[] | undefined> }) => PaymentRequirementsOptions,\n options: PaymentMiddlewareOptions = {}\n): (\n req: { headers: Record<string, string | string[] | undefined>; x402?: VerifiedPaymentState },\n res: { status: (code: number) => { json: (body: unknown) => void; set: (headers: Record<string, string>) => { json: (body: unknown) => void } } },\n next: () => void\n) => Promise<void> {\n const client = new FacilitatorClient({\n baseUrl: options.facilitatorUrl || options.baseUrl,\n timeout: options.timeout,\n retries: options.retries,\n });\n const settlementStrategy = options.settlementStrategy || 'before-handler';\n\n return async (req, res, next) => {\n // Extract payment header\n const payment = extractPaymentFromHeaders(req.headers);\n\n // If no payment, return 402\n if (!payment) {\n const reqOptions = getRequirements(req);\n const { status, headers, body } = create402Response(reqOptions);\n res.status(status).set(headers).json(body);\n return;\n }\n\n // Build requirements and verify\n const reqOptions = getRequirements(req);\n const requirements = buildPaymentRequirements(reqOptions);\n const verifyResult = await client.verify(payment, requirements);\n\n if (!verifyResult.isValid) {\n // 402 says \"your payment was REJECTED, sign a new authorization\". Sending\n // it for a facilitator that never reached a verdict is what makes the\n // buyer pay twice: their first authorization was never refused and is\n // still perfectly good. A no-verdict answer must keep the credential\n // alive, so it goes out as 503 + Retry-After instead.\n if (verifyResult.retryable) {\n respondUnavailable(res, 'Payment verification unavailable', verifyResult);\n return;\n }\n res.status(402).json({\n error: 'Payment verification failed',\n reason: verifyResult.invalidReason,\n });\n return;\n }\n\n req.x402 = createVerifiedPaymentState(client, payment, requirements, verifyResult);\n\n if (settlementStrategy === 'before-handler') {\n const settleResult = await req.x402.settle();\n if (!settleResult.success) {\n // Same distinction on the settle side. A 500 tells a client its request\n // is broken and to stop; a settle that reached no verdict is the one\n // case where retrying the identical request is correct.\n if (settleResult.retryable) {\n respondUnavailable(res, 'Payment settlement unavailable', settleResult);\n return;\n }\n res.status(500).json({\n error: 'Payment settlement failed',\n reason: settleResult.error || 'Unknown settlement error',\n });\n return;\n }\n }\n\n next();\n };\n}\n\n// ============================================================================\n// HONO MIDDLEWARE\n// ============================================================================\n\n/**\n * Options for creating a Hono x402 payment middleware\n */\nexport interface HonoMiddlewareOptions extends PaymentMiddlewareOptions {\n /** Payment requirements to advertise */\n accepts: PaymentAcceptance[];\n /** Response version to advertise (defaults to auto) */\n x402Version?: X402Version | 'auto';\n /** Custom requirement resolver for ambiguous multi-accept flows */\n resolveRequirement?: PaymentRequirementResolver;\n}\n\n/**\n * Create a Hono-compatible middleware for x402 payments.\n *\n * Handles the x402 payment flow:\n * 1. Returns 402 with payment requirements if no X-PAYMENT header\n * 2. Verifies the payment with the facilitator\n * 3. Optionally settles before the handler when settlementStrategy is set\n * 4. Passes control to the next handler on success\n *\n * @param options - Middleware options with facilitator URL and payment accepts\n * @returns Hono middleware function\n *\n * @example\n * ```ts\n * import { createHonoMiddleware } from 'uvd-x402-sdk';\n *\n * const paywall = createHonoMiddleware({\n * accepts: [{\n * network: 'skale-base',\n * asset: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n * amount: '1000000',\n * payTo: '0xYourWallet',\n * extra: { name: 'Bridged USDC (SKALE Bridge)', version: '2' },\n * }],\n * });\n *\n * app.get('/api/premium', paywall, (c) => {\n * return c.json({ message: 'Premium content!' });\n * });\n * ```\n */\n/** {@link respondUnavailable} for a Hono context. */\nfunction honoUnavailable(\n c: {\n json: (body: unknown, status?: number) => unknown;\n header?: (name: string, value: string) => void;\n },\n message: string,\n failure: FacilitatorFailureFields & { error?: string; invalidReason?: string },\n): unknown {\n const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));\n c.header?.('Retry-After', String(seconds));\n return c.json(\n {\n error: message,\n reason: failure.reason ?? failure.invalidReason ?? failure.error,\n retryable: true,\n retryAfterSeconds: seconds,\n safeToReplay: failure.safeToReplay === true,\n },\n 503,\n );\n}\n\nexport function createHonoMiddleware(options: HonoMiddlewareOptions) {\n const client = new FacilitatorClient({\n baseUrl: options.facilitatorUrl || options.baseUrl,\n timeout: options.timeout,\n retries: options.retries,\n });\n const settlementStrategy = options.settlementStrategy || 'before-handler';\n\n if (!options.accepts[0]) {\n throw new Error('At least one accept entry is required');\n }\n\n return async (\n c: {\n req: { header: (name: string) => string | undefined; url: string };\n json: (body: unknown, status?: number) => unknown;\n set?: (key: string, value: unknown) => void;\n /** Hono's response-header setter. Optional so older context doubles still fit. */\n header?: (name: string, value: string) => void;\n },\n next: () => Promise<void>\n ) => {\n const paymentHeader = c.req.header('X-PAYMENT') || c.req.header('x-payment');\n const advertisedVersion = resolveAdvertisedVersion(options.accepts, options.x402Version);\n const advertisedRequirements = options.accepts.map((accept) =>\n buildRequirementFromAcceptance(accept, c.req.url, advertisedVersion)\n );\n\n if (!paymentHeader) {\n return c.json(\n create402ResponseBody(\n advertisedRequirements[0],\n advertisedRequirements,\n advertisedVersion,\n options.facilitatorUrl\n ),\n 402\n );\n }\n\n const parsed = parsePaymentHeader(paymentHeader);\n if (!parsed) {\n return c.json({ error: 'Invalid X-PAYMENT header' }, 400);\n }\n\n const { requirement, reason } = await resolvePaymentRequirement(\n parsed,\n advertisedRequirements,\n options.resolveRequirement\n );\n\n if (!requirement) {\n return c.json({\n error: 'Payment verification failed',\n reason,\n }, 402);\n }\n\n const verifyResult = await client.verify(parsed, requirement);\n if (!verifyResult.isValid) {\n // See respondUnavailable: 402 here would tell the buyer to sign again for\n // an authorization the facilitator never rejected.\n if (verifyResult.retryable) {\n return honoUnavailable(c, 'Payment verification unavailable', verifyResult);\n }\n return c.json({\n error: 'Payment verification failed',\n reason: verifyResult.invalidReason,\n }, 402);\n }\n\n const verifiedPayment = createVerifiedPaymentState(client, parsed, requirement, verifyResult);\n c.set?.('x402', verifiedPayment);\n\n if (settlementStrategy === 'before-handler') {\n const settleResult = await verifiedPayment.settle();\n if (!settleResult.success) {\n if (settleResult.retryable) {\n return honoUnavailable(c, 'Payment settlement unavailable', settleResult);\n }\n return c.json({\n error: 'Payment settlement failed',\n reason: settleResult.error || 'Unknown error',\n }, 500);\n }\n }\n\n await next();\n };\n}\n\n// ============================================================================\n// BAZAAR DISCOVERY API\n// ============================================================================\n//\n// The Bazaar is the discovery registry served by the facilitator itself, under\n// `/discovery/*`. There is no separate Bazaar host.\n\n/**\n * Maximum length of the free-text `q` filter.\n *\n * Mirrors the facilitator's `MAX_SEARCH_LEN`; a longer needle is rejected\n * server-side with a 400.\n */\nexport const MAX_SEARCH_LEN = 128;\n\n/**\n * Liveness of a registered resource, as measured by the facilitator's prober.\n *\n * Resources that stop answering are quarantined rather than deleted, so filter\n * on this before paying anyone.\n */\nexport type DiscoveryHealthStatus =\n | 'alive'\n | 'degraded'\n | 'auth_gated'\n | 'quarantined'\n | 'unknown'\n | 'unprobeable';\n\n/** Values accepted by the `health` filter, including the `any` escape hatch. */\nexport const HEALTH_FILTERS = [\n 'alive',\n 'degraded',\n 'auth_gated',\n 'quarantined',\n 'unknown',\n 'unprobeable',\n 'any',\n] as const;\n\n/** Curated tier, in descending order of trust. */\nexport type DiscoveryTier = 'first_party' | 'vip' | 'verified' | 'listed';\n\n/** Values accepted by the `tier` filter. */\nexport const TIER_FILTERS = [\n 'first_party',\n 'vip',\n 'verified',\n 'listed',\n] as const;\n\n/** How a resource got into the registry. */\nexport type DiscoverySource =\n | 'self_registered'\n | 'settlement'\n | 'crawled'\n | 'aggregated';\n\n/** Health of a single resource, as reported by the registry's prober. */\nexport interface DiscoveryHealth {\n /** Last observed liveness */\n status?: DiscoveryHealthStatus;\n /** Unix epoch seconds of the last probe */\n lastChecked?: number;\n /** HTTP status the probe got back (402 is the healthy answer for x402) */\n httpStatus?: number;\n /** Round-trip time of the last probe, in milliseconds */\n latencyMs?: number;\n}\n\n/** Curation metadata attached to a resource. */\nexport interface DiscoveryCuration {\n /** Curated tier */\n tier?: DiscoveryTier;\n /** Human-readable name of the curated set */\n label?: string;\n}\n\n/** One payment method a resource declares. */\nexport interface DiscoveryAccepts {\n /** Payment scheme (\"exact\", \"escrow\", \"commerce\") */\n scheme: string;\n /** CAIP-2 network id, e.g. \"eip155:8453\" */\n network: string;\n /** Token contract address */\n asset?: string;\n /** Price in atomic units of `asset` */\n amount?: string;\n /** Recipient address */\n payTo?: string;\n /** Settlement deadline in seconds */\n maxTimeoutSeconds?: number;\n /** Scheme-specific extras (EIP-712 domain, etc.) */\n extra?: Record<string, unknown>;\n /** Anything the registry adds later */\n [key: string]: unknown;\n}\n\n/**\n * A discoverable paid resource, exactly as `GET /discovery/resources` serves it.\n *\n * Timestamps are Unix epoch **seconds**, not ISO strings and not milliseconds.\n */\nexport interface DiscoveryResource {\n /** Resource URL. This is the registry's primary key -- there is no `id` */\n url: string;\n /** Resource type (\"http\", \"mcp\", \"a2a\") */\n type: string;\n /** x402 protocol version the resource speaks */\n x402Version: number;\n /** Human-readable description */\n description?: string;\n /** Payment methods the resource accepts */\n accepts: DiscoveryAccepts[];\n /** Free-form metadata (category, provider, tags) */\n metadata?: Record<string, unknown>;\n /** How this resource entered the registry */\n source?: DiscoverySource;\n /** Facilitator this resource was aggregated from */\n sourceFacilitator?: string;\n /** Unix epoch seconds when the registry first saw this resource */\n firstSeen?: number;\n /** Unix epoch seconds when the registry last saw this resource */\n lastSeen?: number;\n /** Unix epoch seconds of the last change to this record */\n lastUpdated?: number;\n /** Liveness, when the resource has been probed */\n health?: DiscoveryHealth;\n /** Curation tier, when the resource has been curated */\n curation?: DiscoveryCuration;\n /** Anything the registry adds later */\n [key: string]: unknown;\n}\n\n/** Pagination envelope of `GET /discovery/resources`. */\nexport interface DiscoveryPagination {\n /** Page size that was applied */\n limit: number;\n /** Offset that was applied */\n offset: number;\n /** Total number of resources matching the filters, across all pages */\n total: number;\n}\n\n/** Paginated response from `GET /discovery/resources`. */\nexport interface DiscoveryResponse {\n /** x402 protocol version of the response envelope */\n x402Version: number;\n /** Resources on this page */\n items: DiscoveryResource[];\n /** Pagination state */\n pagination: DiscoveryPagination;\n}\n\n/**\n * Filters for `listResources()`.\n *\n * Every one of these is applied server-side over the whole catalog, so\n * `pagination.total` reflects the filtered set. Filtering a page after the\n * fact is not the same thing and will under-report.\n */\nexport interface DiscoveryListOptions {\n /** Page size (default: 10, max: 100) */\n limit?: number;\n /** Number of resources to skip */\n offset?: number;\n /** Filter by category */\n category?: string;\n /** Filter by network, CAIP-2 or v1 name */\n network?: string;\n /** Filter by provider name */\n provider?: string;\n /** Filter by tag */\n tag?: string;\n /** Filter by how the resource was discovered */\n source?: DiscoverySource;\n /** Filter by originating facilitator */\n sourceFacilitator?: string;\n /** Filter by liveness, or 'any' to opt out of the default visibility rules */\n health?: DiscoveryHealthStatus | 'any';\n /** Filter by curated tier */\n tier?: DiscoveryTier;\n /** Free-text search over url / description / provider / category / tags */\n q?: string;\n}\n\n/** Options for `registerResource()`. */\nexport interface DiscoveryRegisterOptions {\n /** URL of the paid resource. Doubles as its identity in the registry */\n url: string;\n /** Resource type (default: \"http\") */\n type?: string;\n /** Human-readable description */\n description?: string;\n /** Payment methods the resource accepts */\n accepts?: DiscoveryAccepts[];\n /** Free-form metadata (category, provider, tags) */\n metadata?: Record<string, unknown>;\n}\n\n/** Aggregate catalog metrics from `GET /discovery/stats`. */\nexport interface DiscoveryStats {\n /** Every record the registry holds, including quarantined ones */\n total: number;\n /** Records served by default listings */\n visible: number;\n /** Counts by discovery source */\n bySource: Record<string, number>;\n /** Counts by originating facilitator */\n bySourceFacilitator: Record<string, number>;\n /** Counts by CAIP-2 network */\n byNetwork: Record<string, number>;\n /** Counts by curated tier */\n byTier: Record<string, number>;\n /** Counts by liveness */\n byHealth: Record<string, number>;\n /** Unix epoch seconds this snapshot was computed (60s cache) */\n generatedAt?: number;\n}\n\n/** Options for the {@link BazaarClient}. */\nexport interface BazaarClientOptions {\n /** Facilitator base URL (default: https://facilitator.ultravioletadao.xyz) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\n/** Render an epoch-seconds field as a `Date`. */\nexport function epochToDate(seconds?: number): Date | undefined {\n return seconds === undefined ? undefined : new Date(seconds * 1000);\n}\n\n/** True when the last probe reached this resource. */\nexport function isAlive(resource: DiscoveryResource): boolean {\n return resource.health?.status === 'alive';\n}\n\n/**\n * Client for the x402 Bazaar Discovery API.\n *\n * The Bazaar is the facilitator's own registry of x402-enabled resources.\n * Providers register their endpoints and consumers discover them, with a\n * liveness probe and a curation tier attached to every record.\n *\n * @example\n * ```ts\n * const bazaar = new BazaarClient();\n *\n * // Only endpoints a probe actually reached, best-curated first\n * const page = await bazaar.listResources({ limit: 20, health: 'alive', tier: 'vip' });\n * for (const r of page.items) {\n * console.log(r.url, r.health?.status, r.health?.latencyMs, r.curation?.label);\n * }\n *\n * // Free-text search runs server-side over the whole catalog\n * const hits = await bazaar.listResources({ q: 'logs' });\n * console.log(hits.pagination.total);\n *\n * // Register your own\n * await bazaar.registerResource({\n * url: 'https://api.example.com/v1/generate',\n * description: 'Generate images with AI',\n * accepts: [{\n * scheme: 'exact',\n * network: 'eip155:8453',\n * asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * amount: '10000',\n * payTo: '0xYourWallet...',\n * maxTimeoutSeconds: 60,\n * }],\n * metadata: { category: 'ai', tags: ['image'] },\n * });\n * ```\n */\nexport class BazaarClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: BazaarClientOptions = {}) {\n this.baseUrl = (\n options.baseUrl || 'https://facilitator.ultravioletadao.xyz'\n ).replace(/\\/+$/, '');\n this.timeout = options.timeout || 30000;\n }\n\n /**\n * Issue a request against the facilitator with the configured timeout.\n */\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: { Accept: 'application/json', ...(init?.headers || {}) },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Bazaar API error: ${response.status} - ${errorText}`\n );\n }\n\n return (await response.json()) as T;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * List resources from the discovery registry.\n *\n * @param options - Server-side filters and pagination\n * @returns One page of resources plus the total across all pages\n *\n * @example\n * ```ts\n * const page = await bazaar.listResources({ network: 'eip155:8453', health: 'alive' });\n * ```\n */\n async listResources(\n options: DiscoveryListOptions = {}\n ): Promise<DiscoveryResponse> {\n if (options.q !== undefined && options.q.length > MAX_SEARCH_LEN) {\n throw new Error(`q must be at most ${MAX_SEARCH_LEN} characters`);\n }\n\n const params = new URLSearchParams();\n params.set('limit', String(options.limit ?? 10));\n params.set('offset', String(options.offset ?? 0));\n if (options.category) params.set('category', options.category);\n if (options.network) params.set('network', options.network);\n if (options.provider) params.set('provider', options.provider);\n if (options.tag) params.set('tag', options.tag);\n if (options.source) params.set('source', options.source);\n if (options.sourceFacilitator)\n params.set('sourceFacilitator', options.sourceFacilitator);\n if (options.health) params.set('health', options.health);\n if (options.tier) params.set('tier', options.tier);\n if (options.q) params.set('q', options.q);\n\n return this.request<DiscoveryResponse>(\n `/discovery/resources?${params.toString()}`\n );\n }\n\n /**\n * Walk the whole filtered catalog, one page at a time.\n *\n * Pages are fetched in sequence rather than in parallel: the read routes are\n * rate limited, and a burst of parallel pages is how a legitimate catalog\n * walk turns into a wall of 429s.\n *\n * @param options - Same filters as {@link listResources}; `limit` is the page size\n *\n * @example\n * ```ts\n * for await (const r of bazaar.iterateResources({ health: 'alive' })) {\n * console.log(r.url);\n * }\n * ```\n */\n async *iterateResources(\n options: DiscoveryListOptions = {}\n ): AsyncGenerator<DiscoveryResource, void, undefined> {\n const pageSize = options.limit ?? 100;\n let offset = options.offset ?? 0;\n\n for (;;) {\n const page = await this.listResources({\n ...options,\n limit: pageSize,\n offset,\n });\n if (page.items.length === 0) return;\n\n for (const item of page.items) yield item;\n\n offset += page.items.length;\n if (offset >= page.pagination.total) return;\n }\n }\n\n /**\n * Look up a single resource by its URL.\n *\n * The registry keys on URL and has no by-id lookup, so this searches and\n * then matches exactly.\n *\n * @param resourceUrl - Exact URL of the resource\n * @returns The resource, or null when it is not registered\n */\n async getResourceByUrl(\n resourceUrl: string\n ): Promise<DiscoveryResource | null> {\n const page = await this.listResources({\n q: resourceUrl.slice(0, MAX_SEARCH_LEN),\n limit: 100,\n health: 'any',\n });\n return page.items.find((item) => item.url === resourceUrl) ?? null;\n }\n\n /**\n * Register a paid resource in the discovery registry.\n *\n * Registration is open and rate limited; re-registering a known URL updates\n * the existing record rather than creating a duplicate.\n *\n * @param options - Resource details\n * @returns The registry's acknowledgement\n */\n async registerResource(\n options: DiscoveryRegisterOptions\n ): Promise<Record<string, unknown>> {\n const payload: Record<string, unknown> = {\n url: options.url,\n type: options.type || 'http',\n description: options.description || '',\n };\n if (options.accepts) payload.accepts = options.accepts;\n if (options.metadata) payload.metadata = options.metadata;\n\n return this.request<Record<string, unknown>>('/discovery/register', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n }\n\n /**\n * Aggregate catalog metrics (60s cached server-side).\n *\n * @returns Counts by source, facilitator, network, tier and liveness\n */\n async getStats(): Promise<DiscoveryStats> {\n return this.request<DiscoveryStats>('/discovery/stats');\n }\n\n /**\n * Check that the facilitator serving the registry is up.\n *\n * @returns True when the facilitator answers its health check\n */\n async healthCheck(): Promise<boolean> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n try {\n const response = await fetch(`${this.baseUrl}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n return response.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * @deprecated Renamed to {@link listResources}, which returns the registry's\n * real `{ items, pagination }` envelope. The old `discover()` returned a\n * `{ resources, page, totalPages }` shape that no endpoint ever served.\n */\n async discover(options: DiscoveryListOptions = {}): Promise<DiscoveryResponse> {\n return this.listResources(options);\n }\n}\n\n/**\n * @deprecated Use {@link DiscoveryResource}. The old shape (`id`, `name`,\n * `pricePerRequest`, `isActive`, ISO `createdAt`) described an API that was\n * never deployed.\n */\nexport type BazaarResource = DiscoveryResource;\n\n/** @deprecated Use {@link DiscoveryResponse}. */\nexport type BazaarDiscoverResponse = DiscoveryResponse;\n\n/** @deprecated Use {@link DiscoveryListOptions}. */\nexport type BazaarDiscoverOptions = DiscoveryListOptions;\n\n/** @deprecated Use {@link DiscoveryRegisterOptions}. */\nexport type BazaarRegisterOptions = DiscoveryRegisterOptions;\n\n// ============================================================================\n// ESCROW & REFUND EXTENSION\n// ============================================================================\n\n/**\n * Escrow payment status\n */\nexport type EscrowStatus =\n | 'pending' // Payment initiated, awaiting confirmation\n | 'held' // Funds held in escrow\n | 'released' // Funds released to recipient\n | 'refunded' // Funds returned to payer\n | 'disputed' // Dispute in progress\n | 'expired'; // Escrow expired without resolution\n\n/**\n * Refund request status\n */\nexport type RefundStatus =\n | 'pending' // Refund requested, awaiting processing\n | 'approved' // Refund approved\n | 'rejected' // Refund rejected\n | 'processed' // Refund completed on-chain\n | 'disputed'; // Under dispute review\n\n/**\n * Dispute resolution outcome\n */\nexport type DisputeOutcome =\n | 'pending' // Dispute under review\n | 'payer_wins' // Payer gets refund\n | 'recipient_wins' // Recipient keeps funds\n | 'split'; // Funds split between parties\n\n/**\n * Escrow payment record\n */\nexport interface EscrowPayment {\n /** Unique escrow ID */\n id: string;\n /** Original payment header (base64 encoded) */\n paymentHeader: string;\n /** Current status */\n status: EscrowStatus;\n /** Network where payment was made */\n network: string;\n /** Payer address */\n payer: string;\n /** Recipient address */\n recipient: string;\n /** Amount in atomic units */\n amount: string;\n /** Token/asset contract */\n asset: string;\n /** Resource URL being paid for */\n resource: string;\n /** Escrow expiration timestamp (ISO) */\n expiresAt: string;\n /** Release conditions (optional) */\n releaseConditions?: {\n /** Minimum time before release (seconds) */\n minHoldTime?: number;\n /** Required confirmations */\n confirmations?: number;\n /** Custom condition metadata */\n custom?: unknown;\n };\n /** Transaction hash if released/refunded */\n transactionHash?: string;\n /** Creation timestamp (ISO) */\n createdAt: string;\n /** Last update timestamp (ISO) */\n updatedAt: string;\n}\n\n/**\n * Refund request record\n */\nexport interface RefundRequest {\n /** Unique refund request ID */\n id: string;\n /** Related escrow ID */\n escrowId: string;\n /** Current status */\n status: RefundStatus;\n /** Reason for refund request */\n reason: string;\n /** Additional evidence/details */\n evidence?: string;\n /** Amount requested (may be partial) */\n amountRequested: string;\n /** Amount approved (if any) */\n amountApproved?: string;\n /** Requester (payer) address */\n requester: string;\n /** Transaction hash if processed */\n transactionHash?: string;\n /** Response from recipient/facilitator */\n response?: {\n status: 'approved' | 'rejected';\n reason?: string;\n respondedAt: string;\n };\n /** Creation timestamp (ISO) */\n createdAt: string;\n /** Last update timestamp (ISO) */\n updatedAt: string;\n}\n\n/**\n * Dispute record\n */\nexport interface Dispute {\n /** Unique dispute ID */\n id: string;\n /** Related escrow ID */\n escrowId: string;\n /** Related refund request ID (if any) */\n refundRequestId?: string;\n /** Dispute outcome */\n outcome: DisputeOutcome;\n /** Initiator (payer or recipient) */\n initiator: 'payer' | 'recipient';\n /** Reason for dispute */\n reason: string;\n /** Evidence from payer */\n payerEvidence?: string;\n /** Evidence from recipient */\n recipientEvidence?: string;\n /** Arbitration notes */\n arbitrationNotes?: string;\n /** Amount resolved to payer */\n payerAmount?: string;\n /** Amount resolved to recipient */\n recipientAmount?: string;\n /** Transaction hash(es) for resolution */\n transactionHashes?: string[];\n /** Creation timestamp (ISO) */\n createdAt: string;\n /** Resolution timestamp (ISO) */\n resolvedAt?: string;\n}\n\n/**\n * Options for creating an escrow payment\n */\nexport interface CreateEscrowOptions {\n /** Payment header (from client SDK) */\n paymentHeader: string;\n /** Payment requirements */\n requirements: PaymentRequirements;\n /** Escrow duration in seconds (default: 86400 = 24h) */\n escrowDuration?: number;\n /** Release conditions */\n releaseConditions?: {\n minHoldTime?: number;\n confirmations?: number;\n custom?: unknown;\n };\n}\n\n/**\n * Options for requesting a refund\n */\nexport interface RequestRefundOptions {\n /** Escrow ID to refund */\n escrowId: string;\n /** Reason for refund */\n reason: string;\n /** Amount to refund (full amount if not specified) */\n amount?: string;\n /** Supporting evidence */\n evidence?: string;\n}\n\n/**\n * Options for the EscrowClient\n */\nexport interface EscrowClientOptions {\n /** Base URL of the Escrow API (default: https://escrow.ultravioletadao.xyz) */\n baseUrl?: string;\n /** API key for authenticated operations */\n apiKey?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\n/**\n * Client for x402 Escrow & Refund operations\n *\n * The Escrow system holds payments until service is verified,\n * enabling refunds and dispute resolution.\n *\n * @example\n * ```ts\n * // Create escrow payment (backend)\n * const escrow = new EscrowClient();\n * const escrowPayment = await escrow.createEscrow({\n * paymentHeader: req.headers['x-payment'],\n * requirements: paymentRequirements,\n * escrowDuration: 86400, // 24 hours\n * });\n *\n * // After service is provided, release the escrow\n * await escrow.release(escrowPayment.id);\n *\n * // If service not provided, payer can request refund\n * await escrow.requestRefund({\n * escrowId: escrowPayment.id,\n * reason: 'Service not delivered within expected timeframe',\n * });\n * ```\n */\nexport class EscrowClient {\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly timeout: number;\n\n constructor(options: EscrowClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://escrow.ultravioletadao.xyz';\n this.apiKey = options.apiKey;\n this.timeout = options.timeout || 30000;\n }\n\n private getHeaders(authenticated: boolean = false): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n };\n if (authenticated && this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Create an escrow payment\n *\n * Holds the payment in escrow until released or refunded.\n *\n * @param options - Escrow creation options\n * @returns Created escrow payment\n */\n async createEscrow(options: CreateEscrowOptions): Promise<EscrowPayment> {\n const url = `${this.baseUrl}/escrow`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({\n paymentHeader: options.paymentHeader,\n paymentRequirements: options.requirements,\n escrowDuration: options.escrowDuration || 86400,\n releaseConditions: options.releaseConditions,\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get escrow payment by ID\n *\n * @param escrowId - Escrow payment ID\n * @returns Escrow payment details\n */\n async getEscrow(escrowId: string): Promise<EscrowPayment> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(escrowId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Release escrow funds to recipient\n *\n * Call this after service has been successfully provided.\n *\n * @param escrowId - Escrow payment ID\n * @returns Updated escrow payment with transaction hash\n */\n async release(escrowId: string): Promise<EscrowPayment> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(escrowId)}/release`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Request a refund for an escrow payment\n *\n * Initiates a refund request that must be approved.\n *\n * @param options - Refund request options\n * @returns Created refund request\n */\n async requestRefund(options: RequestRefundOptions): Promise<RefundRequest> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(options.escrowId)}/refund`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({\n reason: options.reason,\n amount: options.amount,\n evidence: options.evidence,\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Approve a refund request (for recipients)\n *\n * @param refundId - Refund request ID\n * @param amount - Amount to approve (may be less than requested)\n * @returns Updated refund request\n */\n async approveRefund(refundId: string, amount?: string): Promise<RefundRequest> {\n const url = `${this.baseUrl}/refund/${encodeURIComponent(refundId)}/approve`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ amount }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Reject a refund request (for recipients)\n *\n * @param refundId - Refund request ID\n * @param reason - Reason for rejection\n * @returns Updated refund request\n */\n async rejectRefund(refundId: string, reason: string): Promise<RefundRequest> {\n const url = `${this.baseUrl}/refund/${encodeURIComponent(refundId)}/reject`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ reason }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get refund request by ID\n *\n * @param refundId - Refund request ID\n * @returns Refund request details\n */\n async getRefund(refundId: string): Promise<RefundRequest> {\n const url = `${this.baseUrl}/refund/${encodeURIComponent(refundId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Open a dispute for an escrow payment\n *\n * Initiates arbitration when payer and recipient disagree.\n *\n * @param escrowId - Escrow payment ID\n * @param reason - Reason for dispute\n * @param evidence - Supporting evidence\n * @returns Created dispute\n */\n async openDispute(\n escrowId: string,\n reason: string,\n evidence?: string\n ): Promise<Dispute> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(escrowId)}/dispute`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ reason, evidence }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Submit evidence to a dispute\n *\n * @param disputeId - Dispute ID\n * @param evidence - Evidence to submit\n * @returns Updated dispute\n */\n async submitEvidence(disputeId: string, evidence: string): Promise<Dispute> {\n const url = `${this.baseUrl}/dispute/${encodeURIComponent(disputeId)}/evidence`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ evidence }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get dispute by ID\n *\n * @param disputeId - Dispute ID\n * @returns Dispute details\n */\n async getDispute(disputeId: string): Promise<Dispute> {\n const url = `${this.baseUrl}/dispute/${encodeURIComponent(disputeId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * List escrow payments (with filters)\n *\n * @param options - Filter and pagination options\n * @returns Paginated list of escrow payments\n */\n async listEscrows(options: {\n status?: EscrowStatus;\n payer?: string;\n recipient?: string;\n page?: number;\n limit?: number;\n } = {}): Promise<{\n escrows: EscrowPayment[];\n total: number;\n page: number;\n limit: number;\n hasMore: boolean;\n }> {\n const params = new URLSearchParams();\n if (options.status) params.set('status', options.status);\n if (options.payer) params.set('payer', options.payer);\n if (options.recipient) params.set('recipient', options.recipient);\n if (options.page) params.set('page', options.page.toString());\n if (options.limit) params.set('limit', options.limit.toString());\n\n const url = `${this.baseUrl}/escrow${params.toString() ? `?${params}` : ''}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(true),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Query on-chain escrow state from the facilitator\n *\n * Calls POST /escrow/state to read current escrow state without settlement.\n *\n * @param options - Escrow state query parameters\n * @returns On-chain escrow state (status, balance, timestamps)\n *\n * @example\n * ```ts\n * const state = await escrow.getEscrowState({\n * network: 'base-mainnet',\n * payer: '0xPayer...',\n * recipient: '0xRecipient...',\n * nonce: '0x1234...',\n * });\n * console.log(`Status: ${state.status}`);\n * ```\n */\n async getEscrowState(options: {\n network: string;\n payer: string;\n recipient: string;\n nonce: string;\n }): Promise<Record<string, unknown>> {\n const url = `${this.baseUrl}/escrow/state`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(options),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Check Escrow API health\n *\n * @returns True if healthy\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/health`, {\n method: 'GET',\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n\n// ============================================================================\n// ESCROW HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Check if an escrow can be released\n *\n * @param escrow - Escrow payment to check\n * @returns True if the escrow can be released\n */\nexport function canReleaseEscrow(escrow: EscrowPayment): boolean {\n if (escrow.status !== 'held') {\n return false;\n }\n\n // Check expiration\n if (new Date(escrow.expiresAt) < new Date()) {\n return false;\n }\n\n // Check minimum hold time if specified\n if (escrow.releaseConditions?.minHoldTime) {\n const createdAt = new Date(escrow.createdAt);\n const minReleaseTime = new Date(\n createdAt.getTime() + escrow.releaseConditions.minHoldTime * 1000\n );\n if (new Date() < minReleaseTime) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Check if an escrow can be refunded\n *\n * @param escrow - Escrow payment to check\n * @returns True if the escrow can be refunded\n */\nexport function canRefundEscrow(escrow: EscrowPayment): boolean {\n // Can only refund held or pending escrows\n return escrow.status === 'held' || escrow.status === 'pending';\n}\n\n/**\n * Check if an escrow is expired\n *\n * @param escrow - Escrow payment to check\n * @returns True if the escrow is expired\n */\nexport function isEscrowExpired(escrow: EscrowPayment): boolean {\n return new Date(escrow.expiresAt) < new Date();\n}\n\n/**\n * Calculate time remaining until escrow expires\n *\n * @param escrow - Escrow payment to check\n * @returns Milliseconds until expiration (negative if expired)\n */\nexport function escrowTimeRemaining(escrow: EscrowPayment): number {\n return new Date(escrow.expiresAt).getTime() - Date.now();\n}\n\n// ============================================================================\n// ERC-8004 TRUSTLESS AGENTS\n// ============================================================================\n\n/**\n * ERC-8004 extension identifier\n */\nexport const ERC8004_EXTENSION_ID = '8004-reputation';\n\n/**\n * Agent ID type: EVM uses sequential uint256 (number), Solana uses base58 pubkey (string)\n */\nexport type AgentId = number | string;\n\n/**\n * ERC-8004 contract addresses per network\n */\n// Mainnet addresses (CREATE2 deterministic - same on all mainnets)\nconst MAINNET_IDENTITY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';\nconst MAINNET_REPUTATION = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63';\n// Deployed after the identity/reputation pair, which is why it was missing here.\n// Verified live on all ten EVM mainnets; SKALE Base has no code at this address\n// and is the one mainnet that legitimately has no validation registry.\nconst MAINNET_VALIDATION = '0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58';\n\n// Testnet addresses (same on all testnets)\nconst TESTNET_IDENTITY = '0x8004A818BFB912233c491871b3d84c89A494BD9e';\nconst TESTNET_REPUTATION = '0x8004B663056A597Dffe9eCcC1965A193B7388713';\nconst TESTNET_VALIDATION = '0x8004Cb1BF31DAf7788923b405b754f57acEB4272';\n\n// Solana program IDs (QuantuLabs 8004-solana)\nconst SOLANA_AGENT_REGISTRY = '8oo4dC4JvBLwy5tGgiH3WwK4B9PWxL9Z4XjA2jzkQMbQ';\nconst SOLANA_ATOM_ENGINE = 'AToMw53aiPQ8j7iHVb4fGt6nzUNxUhcPc3tbPBZuzVVb';\n\n/**\n * ERC-8004 contract addresses per network (21 networks: 19 EVM + 2 Solana)\n */\nexport const ERC8004_CONTRACTS: Record<string, {\n identityRegistry?: string;\n reputationRegistry?: string;\n validationRegistry?: string;\n agentRegistryProgram?: string;\n atomEngineProgram?: string;\n}> = {\n // Mainnets (11)\n ethereum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n base: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n polygon: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n arbitrum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n optimism: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n celo: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n bsc: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n monad: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n avalanche: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n scroll: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n // SKALE Base is the one mainnet without a validation registry (no code at\n // the canonical address), so leaving it out is correct, not an omission.\n 'skale-base': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n // Deprecated alias for 'base' -- kept so existing lookups keep resolving.\n 'base-mainnet': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n // Testnets (8)\n 'ethereum-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'base-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'polygon-amoy': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'arbitrum-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'optimism-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'celo-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'avalanche-fuji': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'skale-base-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n // Solana (2) - uses QuantuLabs 8004-solana Anchor program + ATOM Engine\n solana: {\n agentRegistryProgram: SOLANA_AGENT_REGISTRY,\n atomEngineProgram: SOLANA_ATOM_ENGINE,\n },\n 'solana-devnet': {\n agentRegistryProgram: SOLANA_AGENT_REGISTRY,\n atomEngineProgram: SOLANA_ATOM_ENGINE,\n },\n};\n\n/**\n * Return the network name the facilitator actually accepts.\n *\n * `base-mainnet` reads like the canonical spelling and is not: the facilitator\n * answers `400 {\"error\": \"Invalid network: base-mainnet\"}`. Every name is passed\n * through here before it reaches a URL or a request body, so callers holding the\n * old spelling keep working instead of being rejected at the edge.\n */\nexport function wireNetwork(network: string): string {\n return network === 'base-mainnet' ? 'base' : network;\n}\n\n/**\n * Network type for ERC-8004 operations (21 networks: 19 EVM + 2 Solana)\n *\n * These are the names the FACILITATOR accepts, verified against\n * GET /feedback -> supportedNetworks. 'base-mainnet' is kept only as a\n * deprecated alias: the facilitator rejects it outright (400 \"Invalid network\"),\n * so anything passed through this module is normalised to 'base' before it\n * reaches the wire. Use 'base'.\n */\nexport type Erc8004Network =\n // EVM Mainnets\n | 'ethereum' | 'base' | 'polygon' | 'arbitrum' | 'optimism' | 'celo' | 'bsc' | 'monad' | 'avalanche' | 'scroll' | 'skale-base'\n // Deprecated alias, rewritten to 'base' before it reaches the wire\n | 'base-mainnet'\n // EVM Testnets\n | 'ethereum-sepolia' | 'base-sepolia' | 'polygon-amoy' | 'arbitrum-sepolia' | 'optimism-sepolia' | 'celo-sepolia' | 'avalanche-fuji' | 'skale-base-sepolia'\n // Solana (uses QuantuLabs 8004-solana Anchor program + ATOM Engine)\n | 'solana' | 'solana-devnet';\n\n/**\n * Networks where the facilitator serves the RELAYED feedback rail, i.e. where\n * Execution Market has deployed a `FeedbackDelegate` and the facilitator\n * verified it on-chain (code present, and its `REPUTATION_REGISTRY()` reads\n * back that network's registry).\n *\n * Anywhere else `POST /feedback/evm/prepare` answers 400 — and it should. An\n * invented delegate address would send a type-4 transaction to an account with\n * no code behind it, and in the EVM a `.call()` to an address with no code\n * RETURNS SUCCESS. The failure would look exactly like a rating that rated\n * nobody.\n *\n * `avalanche` is absent and is not waiting to join: the C-Chain rejects the\n * transaction type itself (`-32000 transaction type not supported`), so there\n * is nothing to deploy against. Anchor the rating on a chain that supports\n * EIP-7702; the payment stays where it was made.\n */\nexport const RELAYED_FEEDBACK_NETWORKS: readonly Erc8004Network[] = [\n 'base',\n 'ethereum',\n 'polygon',\n 'arbitrum',\n 'optimism',\n 'celo',\n 'bsc',\n 'monad',\n 'base-sepolia',\n] as const;\n\n/**\n * Whether `network` serves the rater-authored feedback rail.\n *\n * Lets a caller route without paying a round trip for a 400. The facilitator\n * re-checks the delegate on-chain on every request regardless — this list is a\n * routing hint, never the authority.\n */\nexport function supportsRelayedFeedback(network: string): boolean {\n return (RELAYED_FEEDBACK_NETWORKS as readonly string[]).includes(wireNetwork(network));\n}\n\n/**\n * An EIP-7702 authorization, as a wallet produces it.\n *\n * Needed only the first time a rater rates: it points their EOA at the\n * `FeedbackDelegate`. Once delegated, `prepare` answers `delegated: true` and\n * the submission carries no authorization at all.\n */\nexport interface RelayAuthorizationParams {\n /**\n * Chain the authorization is for.\n *\n * `0` is EIP-7702's wildcard and is valid on EVERY chain — a far broader\n * grant than pinning this one. Send the chain id `prepare` returned.\n */\n chainId: number;\n /**\n * The delegate the account is pointed at. Must be the address `prepare`\n * offered; the facilitator refuses anything else before it pays for a\n * transaction.\n */\n address: string;\n /** The rater account's nonce at the moment the authorization executes */\n nonce: number;\n yParity: number;\n r: string;\n s: string;\n}\n\n/**\n * Request body for `POST /feedback/evm/prepare`.\n *\n * `rater` is the address that will appear on-chain as the author, which is the\n * whole point of this rail.\n */\nexport interface PrepareRelayFeedbackRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n feedback: FeedbackParams & { rater: string };\n}\n\n/**\n * Response from `POST /feedback/evm/prepare`.\n *\n * Everything the rater has to sign so the CHAIN records them as the author\n * while the facilitator pays the gas.\n */\nexport interface PrepareRelayFeedbackResponse {\n success: boolean;\n /** The `FeedbackDelegate` the rater's EOA must be delegated to */\n delegate?: string;\n /** Registry calldata the rater is authorising, hex-encoded */\n data?: string;\n /**\n * The value the rater's signature must recover against.\n *\n * **The EIP-191 envelope is already applied here.** A holder of a raw key\n * signs this directly as a prehash (viem's `sign({ hash })`, ethers'\n * `signingKey.sign`). A WALLET must not be handed this value: `personal_sign`\n * applies the envelope itself, so it gets wrapped twice and recovers an\n * address that is not the rater. Wallets sign {@link signingPayload}.\n */\n digest?: string;\n /**\n * The same hash with the envelope still OFF — what a wallet signs.\n *\n * `keccak256('\\x19Ethereum Signed Message:\\n32' || signingPayload)` is\n * exactly {@link digest}, so a client can check the two against each other\n * rather than rebuilding the preimage from `data`.\n *\n * Requires facilitator v1.95.0+. Older facilitators omit it; a client that\n * needs it should fail loudly rather than fall back to signing `digest`\n * through a wallet, which produces a well-formed signature that authorises\n * nobody.\n */\n signingPayload?: string;\n /**\n * The full `eth_signTypedData_v4` payload. **v4 delegates only.**\n *\n * Present exactly when the delegate deployed on that chain is v4, which the\n * facilitator reads from the chain per request rather than assuming from a\n * release. **When it is present, sign IT** — the wallet renders the agent, the\n * score, the tags and the deadline as named fields, so the rater sees what\n * they authorise instead of a hex blob.\n *\n * v4 carries no {@link signingPayload} and needs none: `signTypedData` has no\n * envelope to apply twice, which is the entire class of bug that kept the v3\n * rail at zero signatures for days.\n *\n * Requires facilitator v1.96.0+.\n */\n typedData?: Record<string, unknown>;\n /**\n * Unix seconds after which the authorisation is void. Short on purpose:\n * relaying is permissionless, so a signed authorisation is live in the wild\n * until it expires.\n */\n deadline?: number;\n /** Single-use value binding this authorisation. Echo it back on submit */\n nonce?: string;\n /**\n * Whether the account is already delegated. When `false` the submission MUST\n * carry an `authorization`.\n */\n delegated: boolean;\n /** The account nonce to put in the EIP-7702 authorization, when needed */\n accountNonce?: number;\n chainId: number;\n error?: string;\n network: Erc8004Network;\n}\n\n/**\n * Request body for `POST /feedback/evm/submit`.\n *\n * The feedback parameters are not redundant with `prepare`: the facilitator\n * rebuilds the registry calldata from them and requires the rater's signature\n * to cover exactly that. It does not relay calldata it was handed.\n */\nexport interface SubmitRelayFeedbackRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n feedback: FeedbackParams & { rater: string };\n /** The deadline `prepare` returned */\n deadline: number;\n /** The single-use nonce `prepare` returned */\n nonce: string;\n /**\n * The rater's signature. It must recover to `rater` over `digest` — so\n * either a raw-key prehash signature over `digest`, or a wallet\n * `personal_sign` over `signingPayload`. Not `personal_sign` over `digest`.\n */\n signature: string;\n /** Required only when `prepare` answered `delegated: false` */\n authorization?: RelayAuthorizationParams;\n}\n\n/**\n * Request body for `POST /feedback/response/evm/prepare`.\n *\n * `responder` is the address the chain will record as the author.\n */\nexport interface PrepareRelayResponseRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n responder: string;\n agentId: number | string;\n /** WHOSE feedback is being answered — inside the signed struct. */\n clientAddress: string;\n /** Which feedback (1-indexed) — also inside the struct. */\n feedbackIndex: number;\n responseUri: string;\n responseHash?: string;\n}\n\n/** Request body for `POST /feedback/response/evm/submit`. */\nexport interface SubmitRelayResponseRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n responder: string;\n agentId: number | string;\n clientAddress: string;\n feedbackIndex: number;\n responseUri: string;\n responseHash?: string;\n deadline: number;\n nonce: string;\n /** The responder's signature over the typed data. */\n signature: string;\n authorization?: RelayAuthorizationParams;\n}\n\n/**\n * Proof of payment returned when settling with ERC-8004 extension\n */\nexport interface ProofOfPayment {\n /** Transaction hash of the settled payment */\n transactionHash: string;\n /** Block number where the transaction was included */\n blockNumber: number;\n /** Network where the payment was settled */\n network: string;\n /** The payer (consumer/client) address */\n payer: string;\n /** The payee (agent/resource owner) address */\n payee: string;\n /** Amount paid in token base units */\n amount: string;\n /** Token contract address */\n token: string;\n /** Unix timestamp of the block */\n timestamp: number;\n /** Keccak256 hash of the payment data for verification */\n paymentHash: string;\n}\n\n/**\n * Extended settle response with ERC-8004 proof of payment\n */\nexport interface SettleResponseWithProof extends SettleResponse {\n /** Proof of payment for ERC-8004 reputation submission */\n proofOfPayment?: ProofOfPayment;\n}\n\n/**\n * Agent identity from the Identity Registry\n */\nexport interface AgentIdentity {\n /** The agent's ID (EVM: sequential uint256, Solana: base58 pubkey string) */\n agentId: AgentId;\n /** Owner address of the agent NFT */\n owner: string;\n /** URI pointing to agent registration file */\n agentUri: string;\n /** Payment wallet address (if set) */\n agentWallet?: string;\n /** Network where the agent is registered */\n network: Erc8004Network;\n}\n\n/**\n * Agent registration file structure (resolved from agentURI)\n */\nexport interface AgentRegistrationFile {\n /** Type identifier */\n type: string;\n /** Agent name */\n name: string;\n /** Agent description */\n description: string;\n /** Image URL */\n image?: string;\n /** List of services the agent provides */\n services: AgentService[];\n /** Whether x402 payments are supported */\n x402Support: boolean;\n /** Whether the agent is active */\n active: boolean;\n /** List of registrations across chains */\n registrations: AgentRegistration[];\n /** Supported trust models */\n supportedTrust: string[];\n}\n\n/**\n * Agent service entry\n */\nexport interface AgentService {\n name: string;\n endpoint: string;\n version?: string;\n}\n\n/**\n * Agent registration reference\n */\nexport interface AgentRegistration {\n agentId: AgentId;\n agentRegistry: string; // Format: {namespace}:{chainId}:{address}\n}\n\n/**\n * Reputation summary for an agent\n */\nexport interface ReputationSummary {\n /** Agent ID (EVM: number, Solana: string) */\n agentId: AgentId;\n /** Number of feedback entries */\n count: number;\n /** Aggregated value */\n summaryValue: number;\n /** Decimal places for summaryValue */\n summaryValueDecimals: number;\n /** Network */\n network: Erc8004Network;\n}\n\n/**\n * Individual feedback entry\n */\nexport interface FeedbackEntry {\n /** Client who submitted the feedback */\n client: string;\n /** Feedback index (1-indexed) */\n feedbackIndex: number;\n /** Feedback value */\n value: number;\n /** Value decimals */\n valueDecimals: number;\n /** Primary tag */\n tag1: string;\n /** Secondary tag */\n tag2: string;\n /** Whether this feedback was revoked */\n isRevoked: boolean;\n}\n\n/**\n * Parameters for submitting reputation feedback\n */\nexport interface FeedbackParams {\n /** The agent's ID (EVM: tokenId number, Solana: base58 pubkey string) */\n agentId: AgentId;\n /** Feedback value (e.g., 87 for 87/100) */\n value: number;\n /** Decimal places for value interpretation (0-18) */\n valueDecimals?: number;\n /** Primary categorization tag (e.g., \"starred\", \"uptime\") */\n tag1?: string;\n /** Secondary categorization tag */\n tag2?: string;\n /** Service endpoint that was used */\n endpoint?: string;\n /** URI to off-chain feedback file (IPFS, HTTPS) */\n feedbackUri?: string;\n /** Keccak256 hash of feedback content (for integrity) */\n feedbackHash?: string;\n /**\n * Quality score 0-100.\n *\n * Solana only, and effectively required there: the ATOM Engine ignores an\n * unscored feedback. It is written to the agent but contributes nothing to\n * reputation, and the program reports `had_impact=false`. This is not\n * retroactive — reputation stays at zero however much unscored feedback\n * accumulates.\n */\n score?: number;\n /** Proof of payment (required for authorized feedback) */\n proof?: ProofOfPayment;\n}\n\n/**\n * Feedback request body for POST /feedback\n */\nexport interface FeedbackRequest {\n /** x402 protocol version */\n x402Version: 1 | 2;\n /** Network where feedback will be submitted */\n network: Erc8004Network;\n /** Feedback parameters */\n feedback: FeedbackParams;\n}\n\n/**\n * Feedback response from POST /feedback\n */\nexport interface FeedbackResponse extends FacilitatorFailureFields {\n /** Whether the feedback was successfully submitted */\n success: boolean;\n /** Transaction hash of the feedback submission */\n transaction?: string;\n /** Feedback index assigned (1-indexed) */\n feedbackIndex?: number;\n /** Error message (if failed) */\n error?: string;\n /** Network where feedback was submitted */\n network: Erc8004Network;\n}\n\n/**\n * Reputation query response\n */\n/**\n * Error from an ERC-8004 lookup, carrying the HTTP status as a field.\n *\n * `notFound` and `retryable` are mutually exclusive and must stay that way in\n * calling code: the facilitator answers 404 for \"this address owns no agent\"\n * and 503 for \"I could not find out\", usually an RPC failure behind it.\n * Treating a 503 as absence is how a transient failure becomes a permanent\n * wrong answer — on a registration path it mints a second agent for an owner\n * who already has one, burning gas and leaving an orphan.\n */\nexport class Erc8004LookupError extends Error {\n /** HTTP status returned by the facilitator */\n readonly status: number;\n /** Raw response body, for debugging */\n readonly body: string;\n /**\n * `Retry-After`, already clamped, when the facilitator sent one.\n *\n * Optional so every existing three-argument construction keeps compiling; it\n * falls back to the default wait rather than to zero, because a caller that\n * retries instantly on a 503 is the load that caused it.\n */\n private readonly retryAfterHint: number | undefined;\n\n constructor(message: string, status: number, body: string, retryAfterSeconds?: number) {\n super(message);\n this.name = 'Erc8004LookupError';\n this.status = status;\n this.body = body;\n this.retryAfterHint = retryAfterSeconds;\n }\n\n /** The address genuinely owns no agent on this network. */\n get notFound(): boolean {\n return this.status === 404;\n }\n\n /**\n * The lookup reached no verdict. Retry; never read as \"owns nothing\".\n *\n * `502` and `504` join `503` and `429` here: a gateway that answered on the\n * facilitator's behalf is exactly as silent about the agent's existence, and\n * reading either as absence has the same consequence -- a duplicate mint.\n */\n get retryable(): boolean {\n return (\n this.status === 429 ||\n this.status === 502 ||\n this.status === 503 ||\n this.status === 504\n );\n }\n\n /**\n * The facilitator's own `reason`, when the body carried one.\n *\n * On a WRITE route this is the writer-lease reason and it decides whether the\n * request may be re-sent; see {@link isReplayableLeaseReason}.\n */\n get reason(): string | undefined {\n try {\n const parsed = JSON.parse(this.body) as { reason?: unknown };\n if (parsed && typeof parsed === 'object' && typeof parsed.reason === 'string') {\n return parsed.reason;\n }\n } catch {\n /* a non-JSON body is still a status */\n }\n return undefined;\n }\n\n /**\n * The facilitator NAMED a reason proving it executed nothing.\n *\n * False for `forward_failed` and for every unattributed 5xx: \"something\n * answered\" is not evidence that nothing ran. On `/register`, replaying when\n * this is false is the sequence that minted five duplicate agents.\n */\n get safeToReplay(): boolean {\n return this.status === 429 || (this.status === 503 && isReplayableLeaseReason(this.reason));\n }\n\n /** Seconds to wait before retrying, clamped. Absent when not retryable. */\n get retryAfterSeconds(): number | undefined {\n if (!this.retryable) return undefined;\n return this.retryAfterHint ?? DEFAULT_RETRY_AFTER_SECONDS;\n }\n}\n\n/**\n * ATOM Engine reputation analytics (Solana only).\n *\n * Present only when the agent's `atom_stats` account has been initialized. The\n * facilitator does that during `registerAgent`; agents registered elsewhere may\n * never have it, in which case their feedback is never scored.\n *\n * The engine measures quality through EMA scores, so there are no\n * positive/negative tallies.\n */\nexport interface AtomStats {\n /** Trust tier 0-4 */\n trustTier: number;\n /** Human-readable trust tier */\n trustTierName: string;\n /** Cached quality score */\n qualityScore: number;\n /** Cached loyalty score */\n loyaltyScore: number;\n /** Statistical confidence */\n confidence: number;\n /** Risk assessment (lower is better) */\n riskScore: number;\n /** Client diversity from HyperLogLog */\n diversityRatio: number;\n /** Lowest score ever recorded */\n minScore: number;\n /** Highest score ever recorded */\n maxScore: number;\n /** Most recent score recorded */\n lastScore: number;\n /** Total feedback counted by the engine */\n feedbackCount: number;\n /** Slot of the most recent feedback */\n lastFeedbackSlot: number;\n}\n\nexport interface ReputationResponse {\n agentId: AgentId;\n summary: ReputationSummary;\n feedback?: FeedbackEntry[];\n /** ATOM Engine analytics; absent when the agent has no initialized stats */\n atomStats?: AtomStats | null;\n network: Erc8004Network;\n}\n\n/**\n * Key-value metadata entry for agent registration\n */\nexport interface MetadataEntryParam {\n /** Metadata key */\n key: string;\n /** Metadata value (hex-encoded bytes or UTF-8 string) */\n value: string;\n}\n\n/**\n * Request body for POST /register\n */\nexport interface RegisterAgentRequest {\n /** x402 protocol version */\n x402Version: 1 | 2;\n /** Network where agent will be registered */\n network: Erc8004Network;\n /** URI pointing to agent registration file (IPFS, HTTPS) */\n agentUri: string;\n /** Optional metadata key-value pairs */\n metadata?: MetadataEntryParam[];\n /** Optional recipient address - NFT is transferred to this address after minting */\n recipient?: string;\n}\n\n/**\n * Response from POST /register\n */\nexport interface RegisterAgentResponse extends FacilitatorFailureFields {\n /** Whether registration succeeded */\n success: boolean;\n /** The newly assigned agent ID (EVM: tokenId number, Solana: base58 pubkey string) */\n agentId?: AgentId;\n /** Registration transaction hash */\n transaction?: string;\n /** Transfer transaction hash (if recipient was specified) */\n transferTransaction?: string;\n /** Owner address of the agent NFT */\n owner?: string;\n /** Error message if failed */\n error?: string;\n /** Network where agent was registered */\n network: string;\n}\n\n/**\n * Response from GET /identity/{network}/owner/{address}\n */\nexport interface IdentityByOwnerResponse {\n /** First (lowest) token ID owned by this address */\n agentId: AgentId;\n /** The queried address (checksummed) */\n owner: string;\n /** Agent's registration URI (may be empty) */\n agentUri: string;\n /** Network name */\n network: string;\n /** Total number of agent NFTs owned (as string) */\n balance: string;\n}\n\n/**\n * Response from GET /identity/{network}/{agent_id}/metadata/{key}\n */\n/**\n * Lifecycle of an async registration. `mint_confirmed` and `done` carry an\n * `agentId`; `failed` carries an `error`.\n */\nexport type RegisterJobStatus = 'pending' | 'mint_confirmed' | 'done' | 'failed';\n\n/**\n * Status of an asynchronous registration.\n *\n * Returned by `POST /register` with `Prefer: respond-async` (HTTP 202) and by\n * `GET /register/status/{jobId}`.\n *\n * Terminal jobs are retained for one hour and then age out, after which the\n * status endpoint 404s. Read the agent id before then, or it is only\n * recoverable from the chain.\n */\nexport interface RegisterJobResponse {\n jobId: string;\n status: RegisterJobStatus;\n network?: string;\n agentId?: AgentId;\n transaction?: string;\n transferTransaction?: string;\n owner?: string;\n error?: string;\n}\n\n/** Whether polling can stop: the job either finished or failed. */\nexport function isRegisterJobTerminal(job: RegisterJobResponse): boolean {\n return job.status === 'done' || job.status === 'failed';\n}\n\n/**\n * Thrown when a registration is still running after the wait elapsed.\n *\n * This is emphatically **not** a failure. The mint may still land. `jobId` is a\n * field rather than only part of the message, because the correct recovery is to\n * keep polling `getRegisterStatus(jobId)` — and a caller who cannot reach the id\n * without parsing a string will re-register instead, minting a duplicate agent.\n * That is the exact sequence that once produced five duplicate mints.\n *\n * Never map this to \"registration failed\".\n */\nexport class RegistrationPendingError extends Error {\n readonly jobId: string;\n readonly lastStatus: RegisterJobStatus;\n readonly timeoutMs: number;\n readonly retryable = true;\n\n constructor(jobId: string, lastStatus: RegisterJobStatus, timeoutMs: number) {\n super(\n `Registration job ${jobId} still '${lastStatus}' after ${Math.round(\n timeoutMs / 1000,\n )}s. It may still complete: poll getRegisterStatus('${jobId}') rather than registering again.`,\n );\n this.name = 'RegistrationPendingError';\n this.jobId = jobId;\n this.lastStatus = lastStatus;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Present a finished async job in the shape the synchronous call returns.\n *\n * Keeping the return type identical is the whole point of `asyncTransport`:\n * switching transports must not force callers to rewrite anything downstream.\n */\nfunction jobToRegisterResponse(\n job: RegisterJobResponse,\n network: Erc8004Network,\n): RegisterAgentResponse {\n return {\n success: job.status !== 'failed',\n agentId: job.agentId,\n transaction: job.transaction,\n transferTransaction: job.transferTransaction,\n owner: job.owner,\n error: job.error,\n network: (job.network as Erc8004Network) ?? network,\n };\n}\n\nexport interface IdentityMetadataResponse {\n /** Agent ID (EVM: number, Solana: string) */\n agentId: AgentId;\n /** Metadata key */\n key: string;\n /**\n * Raw hex-encoded value. The facilitator sends this as `value`; this field\n * used to be declared as `valueHex`, which no response ever carried, so it\n * was always undefined at runtime.\n */\n value: string;\n /** UTF-8 decoded value (if decodable) */\n valueUtf8?: string;\n /** Whether the entry can still be changed */\n immutable?: boolean;\n /** Network */\n network: string;\n}\n\n/**\n * Response from GET /identity/{network}/total-supply\n *\n * On Solana the counts come from the Metaplex Core collection, not the registry,\n * which keeps no counter of its own.\n */\nexport interface IdentityTotalSupplyResponse {\n /** Registered agents, net of burns */\n totalSupply: number;\n /** All-time mint count (Solana) */\n numMinted?: number;\n /** Metaplex Core collection backing the count (Solana) */\n collection?: string;\n /** Network */\n network: string;\n}\n\n/**\n * Options for the ERC8004Client\n */\nexport interface Erc8004ClientOptions {\n /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /**\n * Extra attempts after the first, spent only on a refusal the facilitator\n * proved it did not execute. Default 2; `0` disables. An ambiguous\n * `forward_failed` is never replayed at any setting.\n */\n retries?: number;\n}\n\n/**\n * Client for ERC-8004 Trustless Agents API\n *\n * Provides methods for:\n * - Registering new agents (gasless, facilitator pays gas)\n * - Registering agents on behalf of users (gasless delegation)\n * - Querying agent identity, metadata, and total supply\n * - Querying agent reputation\n * - Submitting reputation feedback\n * - Revoking feedback\n *\n * @example\n * ```ts\n * const client = new Erc8004Client();\n *\n * // Get agent identity\n * const identity = await client.getIdentity('ethereum', 42);\n * console.log(identity.agentUri);\n *\n * // Get agent reputation\n * const reputation = await client.getReputation('ethereum', 42);\n * console.log(`Score: ${reputation.summary.summaryValue}`);\n *\n * // Submit feedback after payment\n * const result = await client.submitFeedback({\n * x402Version: 1,\n * network: 'ethereum',\n * feedback: {\n * agentId: 42,\n * value: 95,\n * valueDecimals: 0,\n * tag1: 'quality',\n * proof: settleResponse.proofOfPayment,\n * },\n * });\n * ```\n */\nexport class Erc8004Client {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly retries: number | undefined;\n\n constructor(options: Erc8004ClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';\n this.timeout = options.timeout || 30000;\n this.retries = options.retries;\n }\n\n /**\n * POST a write route, keeping a refusal readable.\n *\n * Every ERC-8004 write goes through the facilitator's EVM writer lease, so\n * every one of them can answer `503` + `reason`. Flattened to a string, those\n * are indistinguishable from \"the registry rejected your feedback\" — and on\n * `/register` the wrong reading re-POSTs a mint that may already have landed,\n * which is precisely how five duplicate agents were once created.\n *\n * A refusal the facilitator proved it did not execute is replayed\n * automatically (`safeToReplay`); `forward_failed` never is.\n */\n private async writeJson(\n url: string,\n body: unknown,\n extraHeaders: Record<string, string> = {},\n ): Promise<{ response: Response; error?: FacilitatorErrorInfo }> {\n return facilitatorFetch(\n url,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n }\n\n /**\n * Get agent identity from the Identity Registry\n *\n * @param network - Network where agent is registered\n * @param agentId - Agent's tokenId\n * @returns Agent identity information\n */\n async getIdentity(network: Erc8004Network, agentId: AgentId): Promise<AgentIdentity> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/${agentId}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get agent identity by owner address\n *\n * Resolves the first ERC-8004 agent ID owned by a wallet address on a given network.\n *\n * @param network - Network to query\n * @param address - Owner wallet address\n * @returns Agent identity information including balance\n *\n * @example\n * ```ts\n * const identity = await client.getIdentityByOwner('base-mainnet', '0x52E0...');\n * console.log(`Agent #${identity.agentId}, balance: ${identity.balance}`);\n * ```\n */\n async getIdentityByOwner(network: Erc8004Network, address: string): Promise<IdentityByOwnerResponse> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/owner/${address}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n }).finally(() => clearTimeout(timeoutId));\n\n if (!response.ok) {\n // 404 and 503 are different answers: \"owns nothing\" versus \"could not\n // find out\". Reading the status out of a message string is how they get\n // collapsed, and collapsing them mints a duplicate agent for an owner\n // who already has one. Carry the status, the reason and the wait as\n // fields.\n const info = await readFacilitatorError(response);\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${info.status} - ${info.body}`,\n info.status,\n info.body,\n info.retryAfterSeconds,\n );\n }\n\n return await response.json();\n }\n\n /**\n * Resolve agent registration file from agentURI\n *\n * @param agentUri - URI pointing to agent registration file\n * @returns Resolved agent registration file\n */\n async resolveAgentUri(agentUri: string): Promise<AgentRegistrationFile> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Handle IPFS URIs\n let url = agentUri;\n if (agentUri.startsWith('ipfs://')) {\n const cid = agentUri.replace('ipfs://', '');\n url = `https://ipfs.io/ipfs/${cid}`;\n }\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`Failed to resolve agentURI: ${response.status}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get agent reputation from the Reputation Registry\n *\n * @param network - Network where agent is registered\n * @param agentId - Agent's tokenId\n * @param options - Query options (tag filters, include individual feedback, client addresses)\n * @param options.clientAddresses - Comma-separated client addresses to filter by.\n * If omitted, the facilitator auto-discovers all clients via getClients().\n * @returns Reputation summary and optionally individual feedback entries\n */\n async getReputation(\n network: Erc8004Network,\n agentId: AgentId,\n options: {\n tag1?: string;\n tag2?: string;\n includeFeedback?: boolean;\n clientAddresses?: string;\n } = {}\n ): Promise<ReputationResponse> {\n const params = new URLSearchParams();\n if (options.tag1) params.set('tag1', options.tag1);\n if (options.tag2) params.set('tag2', options.tag2);\n if (options.includeFeedback) params.set('includeFeedback', 'true');\n if (options.clientAddresses) params.set('clientAddresses', options.clientAddresses);\n\n const url = `${this.baseUrl}/reputation/${wireNetwork(network)}/${agentId}${params.toString() ? `?${params}` : ''}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Submit reputation feedback for an agent\n *\n * Requires proof of payment for authorized feedback submission.\n *\n * @deprecated On this route the facilitator is the AUTHOR: the registry\n * records `msg.sender`, and that is the facilitator's wallet — which can also\n * revoke what it wrote. On the networks in {@link RELAYED_FEEDBACK_NETWORKS}\n * use {@link Erc8004Client.prepareRelayedFeedback} +\n * {@link Erc8004Client.submitRelayedFeedback} instead, which record the RATER\n * as author. This route still works and is not going away without notice: it\n * is the only one available where no `FeedbackDelegate` is deployed.\n *\n * @param request - Feedback request with agent ID, value, and proof\n * @returns Feedback response with transaction hash\n *\n * @example\n * ```ts\n * // After settling a payment with ERC-8004 extension\n * const settleResult = await facilitator.settle(payment, {\n * ...requirements,\n * extra: { '8004-reputation': { includeProof: true } },\n * });\n *\n * // Submit feedback with proof of payment\n * const feedback = await erc8004.submitFeedback({\n * x402Version: 1,\n * network: 'ethereum',\n * feedback: {\n * agentId: 42,\n * value: 95, // 95/100\n * valueDecimals: 0,\n * tag1: 'quality',\n * tag2: 'response-time',\n * proof: settleResult.proofOfPayment,\n * },\n * });\n * ```\n */\n async submitFeedback(request: FeedbackRequest): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback`;\n\n try {\n const { response, error } = await this.writeJson(url, {\n ...request,\n network: wireNetwork(request.network),\n });\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network: request.network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // Timeout or connection failure: the write may already be on-chain.\n // Retryable, never replayable -- reconcile before resending.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Ask the facilitator what the rater must sign to author a rating.\n *\n * Step 1 of the rater-authored rail. Writes nothing on-chain and costs\n * nothing: it reads the delegate, the rater's delegation state and their\n * account nonce, then hands back a digest, a deadline and a single-use nonce.\n *\n * Why this exists: the ERC-8004 Reputation Registry records `msg.sender` as\n * the author, and the deployed implementation has no delegation path — no\n * `giveFeedbackWithSignature`, no ERC-2771 forwarder. So a rating the\n * facilitator relays the ordinary way is a rating attributed to the\n * FACILITATOR. EIP-7702 fixes it without touching the registry: the rater\n * delegates their own EOA to the `FeedbackDelegate` and the transaction is\n * sent TO THE RATER'S ADDRESS, so the registry sees the rater while the\n * facilitator pays.\n *\n * What to do with the answer:\n * 1. Produce the rater's signature. **Which value you sign depends on how you\n * sign it**, and getting it wrong yields a well-formed signature that\n * authorises nobody:\n * - raw key: sign `digest` as a **prehash**. It already carries the\n * EIP-191 envelope.\n * - wallet: `personal_sign` over `signingPayload`. `personal_sign` adds the\n * envelope itself, so signing `digest` with it wraps the value TWICE and\n * recovers a stranger — the only symptom is `relay_bad_signature`.\n * - **unless `typedData` came back** — that chain runs a v4 delegate. Then\n * sign THAT with `eth_signTypedData_v4` and ignore the other two: it is\n * the only form the rater can read, and it has no envelope ambiguity.\n * 2. If `delegated` is `false`, also produce an EIP-7702 authorization over\n * `(chainId, delegate, accountNonce)`.\n * 3. Hand both to {@link submitRelayedFeedback} with the SAME feedback\n * parameters, `deadline` and `nonce`.\n *\n * @param request - Network, rater address and feedback parameters\n * @returns Everything needed to sign, including whether an EIP-7702\n * authorization is still required\n *\n * @example\n * ```ts\n * const prep = await erc8004.prepareRelayedFeedback({\n * x402Version: 1,\n * network: 'base',\n * feedback: { agentId: 18896, value: 95, tag1: 'quality', rater: raterAddress },\n * });\n * // prep.delegated === false -> an EIP-7702 authorization is required\n * ```\n */\n async prepareRelayedFeedback(\n request: PrepareRelayFeedbackRequest,\n ): Promise<PrepareRelayFeedbackResponse> {\n const url = `${this.baseUrl}/feedback/evm/prepare`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify({ ...request, network: wireNetwork(request.network) }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n success: false,\n delegated: false,\n chainId: 0,\n error: `Facilitator error: ${response.status} - ${errorText}`,\n network: request.network,\n };\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n delegated: false,\n chainId: 0,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n };\n }\n }\n\n /**\n * Relay a rater-authored rating; the facilitator pays the gas.\n *\n * Step 2 of the rater-authored rail. The on-chain record that comes out of it\n * has the RATER as `msg.sender`, so `getClients(agentId)` shows the rater\n * rather than the facilitator.\n *\n * Pass back the same feedback parameters, `deadline` and `nonce` that\n * {@link prepareRelayedFeedback} returned. They are not redundant: the\n * facilitator rebuilds the registry calldata from them and requires the\n * rater's signature to cover exactly that.\n *\n * `authorization` is required only when `prepare` answered\n * `delegated: false`. One that names a different delegate than the one\n * `prepare` offered is refused before any gas is spent.\n *\n * @param request - Feedback parameters plus the rater's signature\n * @returns Feedback response with the transaction hash\n */\n async submitRelayedFeedback(\n request: SubmitRelayFeedbackRequest,\n ): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback/evm/submit`;\n\n try {\n const { response, error } = await this.writeJson(url, {\n ...request,\n network: wireNetwork(request.network),\n });\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network: request.network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // Timeout or connection failure: the write may already be on-chain.\n // Retryable, never replayable -- reconcile before resending.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Revoke previously submitted feedback\n *\n * Only the original submitter can revoke their feedback.\n *\n * @param network - Network where feedback was submitted\n * @param agentId - Agent ID\n * @param feedbackIndex - Index of feedback to revoke\n * @returns Revocation result\n */\n async revokeFeedback(\n network: Erc8004Network,\n agentId: AgentId,\n feedbackIndex: number,\n options?: { sealHash?: string; originalFeedback?: Omit<FeedbackParams, 'agentId' | 'proof'> }\n ): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback/revoke`;\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n network: wireNetwork(network),\n agentId,\n feedbackIndex,\n };\n // Solana revocations need the SEAL hash of the feedback being revoked. Pass\n // originalFeedback and the facilitator derives it; computing it yourself\n // means reimplementing the program's keccak256 layout exactly.\n if (options?.sealHash) {\n payload.sealHash = options.sealHash;\n } else if (options?.originalFeedback) {\n payload.originalFeedback = options.originalFeedback;\n }\n\n try {\n const { response, error } = await this.writeJson(url, payload);\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Get ERC-8004 contract addresses for a network\n *\n * @param network - Network to get contracts for\n * @returns Contract addresses or undefined if not deployed\n */\n getContracts(network: Erc8004Network): typeof ERC8004_CONTRACTS[Erc8004Network] | undefined {\n return ERC8004_CONTRACTS[network];\n }\n\n /**\n * Check if ERC-8004 is available on a network\n *\n * @param network - Network to check\n * @returns True if ERC-8004 contracts are deployed\n */\n isAvailable(network: string): network is Erc8004Network {\n return network in ERC8004_CONTRACTS;\n }\n\n /**\n * Get feedback endpoint metadata\n *\n * @returns Endpoint information for /feedback\n */\n async getFeedbackMetadata(): Promise<{\n endpoint: string;\n supportedNetworks: Erc8004Network[];\n version: string;\n }> {\n const url = `${this.baseUrl}/feedback`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`Failed to get feedback metadata: ${response.status}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Ask what the RESPONDER must sign to author a response on-chain.\n *\n * The mirror of {@link prepareRelayedFeedback}, for the other write the\n * registry accepts from anybody. `appendResponse` is not agent-only — the\n * registry takes it from any address — so on the plain {@link appendResponse}\n * route the `responder` recorded on-chain is the FACILITATOR. That does not\n * destroy anyone's reputation the way a revoke would; it ties the\n * facilitator's on-chain identity to a third party's content, which is its own\n * kind of wrong.\n *\n * **v4 delegates only.** The v3 delegate accepts exactly two selectors and\n * `appendResponse` is not one of them, so a v3 network answers 400\n * `relay_response_needs_v4` rather than silently falling back to the route\n * this replaces.\n *\n * `clientAddress` and `feedbackIndex` are inside the signed struct: without\n * them one signature would answer any client's rating, or any rating at that\n * index.\n */\n async prepareRelayedResponse(\n request: PrepareRelayResponseRequest\n ): Promise<PrepareRelayFeedbackResponse> {\n return this.postRelay('/feedback/response/evm/prepare', request, {\n success: false,\n delegated: false,\n chainId: 0,\n network: request.network,\n });\n }\n\n /**\n * Relay a responder-authored response; the facilitator pays the gas.\n *\n * Pass back the same parameters, `deadline` and `nonce` that\n * {@link prepareRelayedResponse} returned: the facilitator rebuilds the struct\n * from them and refuses to relay anything the signature does not cover.\n */\n async submitRelayedResponse(\n request: SubmitRelayResponseRequest\n ): Promise<FeedbackResponse> {\n return this.postRelay('/feedback/response/evm/submit', request, {\n success: false,\n network: request.network,\n });\n }\n\n /** Shared POST for the relay routes: a refusal is data, never a throw. */\n private async postRelay<T>(path: string, request: { network: Erc8004Network }, onError: T): Promise<T> {\n try {\n const { response, error } = await this.writeJson(`${this.baseUrl}${path}`, {\n ...request,\n network: wireNetwork(request.network),\n });\n if (error) {\n return { ...onError, error: error.error, ...failureFields(error) };\n }\n return await response.json();\n } catch (error) {\n return {\n ...onError,\n error: error instanceof Error ? error.message : 'Unknown error',\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Append a response to existing feedback\n *\n * @deprecated On this route the facilitator is the AUTHOR: the registry\n * records `msg.sender` as the `responder`, and that is the facilitator's\n * wallet. Where the delegate is **v4**, use {@link prepareRelayedResponse} +\n * {@link submitRelayedResponse} instead. This route still works and is the\n * only one available where the delegate is still v3.\n *\n * **This is NOT agent-only**, despite what this comment claimed until\n * 2026-08-25. Verified on-chain on 2026-08-18: the registry accepts\n * `appendResponse` from ANY address. There is no identity-owner check, here or\n * in the contract.\n *\n * @param network - Network where feedback was submitted\n * @param agentId - Agent ID\n * @param feedbackIndex - Index of feedback to respond to\n * @param response - Response content\n * @param responseUri - Optional URI to off-chain response file\n * @returns Response result\n *\n * @example\n * ```ts\n * // Agent responds to feedback\n * const result = await erc8004.appendResponse(\n * 'ethereum',\n * 42,\n * 1,\n * 'Thank you for your feedback! We have addressed the issue.',\n * );\n * ```\n */\n async appendResponse(\n network: Erc8004Network,\n agentId: AgentId,\n feedbackIndex: number,\n response: string,\n options?: { responseUri?: string; sealHash?: string }\n ): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback/response`;\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n network: wireNetwork(network),\n agentId,\n feedbackIndex,\n response,\n };\n if (options?.responseUri) {\n payload.responseUri = options.responseUri;\n }\n if (options?.sealHash) {\n payload.sealHash = options.sealHash;\n }\n\n try {\n const { response: fetchResponse, error } = await this.writeJson(url, payload);\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network,\n ...failureFields(error),\n };\n }\n\n return await fetchResponse.json();\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Register an agent on the Identity Registry (idempotent)\n *\n * If the recipient already owns an agent on the target network, returns the\n * existing one instead of minting a duplicate. The facilitator pays gas fees.\n * Optionally transfer the NFT to a recipient address (gasless delegation).\n *\n * @param request - Registration request\n * @returns Registration response with agent ID and transaction hash\n *\n * @example\n * ```ts\n * // Register agent owned by facilitator\n * const result = await client.registerAgent({\n * x402Version: 1,\n * network: 'ethereum',\n * agentUri: 'ipfs://QmYourAgentFile',\n * });\n * console.log(`Agent #${result.agentId} registered`);\n *\n * // Register agent and transfer to user\n * const result = await client.registerAgent({\n * x402Version: 1,\n * network: 'ethereum',\n * agentUri: 'ipfs://QmYourAgentFile',\n * recipient: '0xUserAddress...',\n * });\n * console.log(`Agent #${result.agentId} transferred to user`);\n * ```\n */\n async registerAgent(\n request: RegisterAgentRequest,\n options?: { asyncTransport?: boolean; pollIntervalMs?: number; timeoutMs?: number },\n ): Promise<RegisterAgentResponse> {\n // asyncTransport changes how the wait is carried out, not what comes back.\n // The synchronous call holds one HTTP request open for the whole mint, which\n // on a congested chain outlives proxy timeouts; each poll here is short, so\n // nothing in the path can time out ambiguously.\n if (options?.asyncTransport) {\n const job = await this.registerAgentAsync(request);\n const terminal = await this.waitForRegistration(job.jobId, {\n pollIntervalMs: options.pollIntervalMs,\n timeoutMs: options.timeoutMs,\n });\n return jobToRegisterResponse(terminal, request.network);\n }\n\n const url = `${this.baseUrl}/register`;\n\n try {\n const { response, error } = await this.writeJson(url, {\n ...request,\n network: wireNetwork(request.network),\n });\n\n if (error) {\n // The facilitator answers 4xx with a structured RegisterAgentResponse,\n // and on 409 - a registration for this agent is ALREADY IN FLIGHT -\n // that body carries the agent id and tx of the run already underway,\n // plus an explicit \"poll GET /register/status/{jobId}\" hint.\n //\n // Flattening it into a bare string threw away the only thing that lets\n // a caller resolve instead of re-POSTing, and re-POSTing a mint is\n // exactly how duplicate agents get created. Keep the body.\n try {\n const parsed = JSON.parse(error.body) as RegisterAgentResponse;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return {\n ...parsed,\n // Never let a non-2xx body claim success, whatever it says.\n success: false,\n error: parsed.error ?? `Facilitator error: ${error.status}`,\n network: parsed.network ?? request.network,\n ...failureFields(error),\n };\n }\n } catch {\n // Not JSON - fall through to the flattened error.\n }\n return {\n success: false,\n error: error.error,\n network: request.network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // A MINT that timed out is the single most dangerous ambiguity in this\n // SDK: the transaction may be mining right now. `safeToReplay: false`\n // says so out loud. Resolve with\n // `GET /identity/{network}/owner/{recipient}` -- honouring its 404-vs-503\n // distinction -- or with `getRegisterStatus`, never by re-POSTing.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Start a registration without waiting for the chain to confirm it.\n *\n * Registration waits on a mint receipt, which on a congested chain outlives\n * client and proxy timeouts. A timed-out synchronous call is genuinely\n * ambiguous — the mint may well have landed — and retrying it is how five\n * duplicate agents once got minted. This returns immediately with a job id\n * instead; poll {@link getRegisterStatus} or use {@link waitForRegistration}.\n *\n * On Solana, `recipient` is a base58 address: the facilitator mints,\n * initializes the ATOM stats and transfers, paying every fee.\n */\n async registerAgentAsync(request: RegisterAgentRequest): Promise<RegisterJobResponse> {\n const url = `${this.baseUrl}/register`;\n\n // A 503 here is the SAFE half of the register story: the job was never\n // created, so a replay creates one job, not two. `writeJson` replays only\n // what the facilitator proved it did not execute, and never\n // `forward_failed`.\n const { response, error } = await this.writeJson(\n url,\n { ...request, network: wireNetwork(request.network) },\n { Prefer: 'respond-async' },\n );\n\n if (error) {\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${error.status} - ${error.body}`,\n error.status,\n error.body,\n error.retryAfterSeconds,\n );\n }\n\n return await response.json();\n }\n\n /**\n * Read the current state of an asynchronous registration.\n *\n * Throws {@link Erc8004LookupError} with `notFound` when the job is unknown or\n * has aged out — terminal jobs are kept for one hour.\n */\n async getRegisterStatus(jobId: string): Promise<RegisterJobResponse> {\n const url = `${this.baseUrl}/register/status/${encodeURIComponent(jobId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n }).finally(() => clearTimeout(timeoutId));\n\n if (!response.ok) {\n const info = await readFacilitatorError(response);\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${info.status} - ${info.body}`,\n info.status,\n info.body,\n info.retryAfterSeconds,\n );\n }\n\n return await response.json();\n }\n\n /**\n * Poll an asynchronous registration until it finishes.\n *\n * Rejects on timeout rather than resolving with the last non-terminal status,\n * so \"still pending\" is never mistaken for \"did not happen\": the mint may\n * still land afterwards, and treating a timeout as failure is what leads to\n * registering the same agent twice. Keep the job id and poll again rather\n * than re-registering.\n */\n async waitForRegistration(\n jobId: string,\n options?: { pollIntervalMs?: number; timeoutMs?: number },\n ): Promise<RegisterJobResponse> {\n const pollIntervalMs = options?.pollIntervalMs ?? 2000;\n const timeoutMs = options?.timeoutMs ?? 300_000;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n const job = await this.getRegisterStatus(jobId);\n if (isRegisterJobTerminal(job)) {\n return job;\n }\n if (Date.now() >= deadline) {\n throw new RegistrationPendingError(jobId, job.status, timeoutMs);\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n }\n\n /**\n * Get registration endpoint metadata\n *\n * @returns Endpoint information for POST /register\n */\n async getRegisterInfo(): Promise<Record<string, unknown>> {\n const url = `${this.baseUrl}/register`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get a specific metadata entry for an agent\n *\n * @param network - Network where agent is registered\n * @param agentId - Agent's tokenId\n * @param key - Metadata key to retrieve\n * @returns Metadata value (hex-encoded and UTF-8 decoded if possible)\n */\n async getIdentityMetadata(\n network: Erc8004Network,\n agentId: AgentId,\n key: string,\n ): Promise<IdentityMetadataResponse> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/${agentId}/metadata/${encodeURIComponent(key)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get total number of registered agents on a network\n *\n * @param network - Network to query\n * @returns Total supply count\n */\n async getIdentityTotalSupply(network: Erc8004Network): Promise<IdentityTotalSupplyResponse> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/total-supply`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n}\n\n/**\n * Build payment requirements with ERC-8004 extension\n *\n * Adds the 8004-reputation extension to include proof of payment\n * in settlement responses for reputation submission.\n *\n * @param options - Base payment requirements options\n * @returns Payment requirements with ERC-8004 extension\n *\n * @example\n * ```ts\n * const requirements = buildErc8004PaymentRequirements({\n * amount: '1.00',\n * recipient: '0x...',\n * resource: 'https://api.example.com/service',\n * chainName: 'ethereum',\n * });\n *\n * // Settlement will include proofOfPayment\n * const result = await facilitator.settle(payment, requirements);\n * console.log(result.proofOfPayment);\n * ```\n */\nexport function buildErc8004PaymentRequirements(\n options: PaymentRequirementsOptions\n): PaymentRequirements & { extra: { '8004-reputation': { includeProof: boolean } } } {\n const base = buildPaymentRequirements(options);\n return {\n ...base,\n extra: {\n [ERC8004_EXTENSION_ID]: {\n includeProof: true,\n },\n },\n };\n}\n\n// ============================================================================\n// ADVANCED ESCROW (PaymentOperator - On-Chain Escrow)\n// ============================================================================\n//\n// The 5 Advanced Escrow flows via the PaymentOperator contract:\n// 1. AUTHORIZE - Lock funds in escrow (via facilitator)\n// 2. RELEASE - Capture escrowed funds to receiver (on-chain)\n// 3. REFUND IN ESCROW - Return escrowed funds to payer (on-chain)\n// 4. CHARGE - Direct instant payment without escrow (on-chain)\n// 5. REFUND POST ESCROW - Dispute refund after release (on-chain)\n//\n// Contract mapping:\n// operator.authorize() -> escrow.authorize() (lock funds)\n// operator.release() -> escrow.capture() (pay receiver)\n// operator.refundInEscrow() -> escrow.partialVoid() (refund payer)\n// operator.charge() -> escrow.charge() (direct payment)\n// operator.refundPostEscrow() -> escrow.refund() (dispute refund)\n// ============================================================================\n\n/**\n * PAYMENT_INFO_TYPEHASH used for nonce computation.\n * Must match the on-chain AuthCaptureEscrow contract.\n */\nexport const PAYMENT_INFO_TYPEHASH =\n '0xae68ac7ce30c86ece8196b61a7c486d8f0061f575037fbd34e7fe4e2820c6591';\n\nexport const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n/**\n * Contract deposit limit (enforced by PaymentOperator condition).\n * As of 2026-02-03, commerce-payments contracts enforce $100 max per deposit.\n */\nexport const DEPOSIT_LIMIT_USDC = '100000000'; // $100 in atomic units (6 decimals)\n\n/**\n * Default facilitator request timeout per chain in milliseconds.\n * Ethereum L1 (~12s blocks) needs much longer than L2s (~2s blocks).\n * Timeout chain: Client > SDK > Facilitator. The facilitator uses 900s for Ethereum L1.\n */\nexport const ESCROW_TIMEOUT_MS: Record<number, number> = {\n 1: 960_000, // Ethereum L1: 960s (facilitator uses 900s TxWatcher)\n 11155111: 960_000, // Ethereum Sepolia: same as L1\n 137: 90_000, // Polygon: 90s\n 8453: 90_000, // Base: 90s\n 84532: 90_000, // Base Sepolia: 90s\n 42161: 90_000, // Arbitrum: 90s\n 10: 90_000, // Optimism: 90s\n 43114: 90_000, // Avalanche: 90s\n 42220: 90_000, // Celo: 90s\n 143: 90_000, // Monad: 90s\n};\n\n/** Default timeout when chain is not in ESCROW_TIMEOUT_MS */\nconst DEFAULT_ESCROW_TIMEOUT_MS = 30_000;\n\n/**\n * USDC EIP-712 domain name per chain.\n * Most chains use \"USD Coin\", but some (Celo, Monad, HyperEVM) use \"USDC\".\n * This must match the on-chain token's name() for EIP-712 signing to work.\n */\nexport const USDC_DOMAIN_NAME: Record<number, string> = {\n 8453: 'USD Coin', // Base Mainnet\n 84532: 'USD Coin', // Base Sepolia\n 1: 'USD Coin', // Ethereum Mainnet\n 11155111: 'USD Coin', // Ethereum Sepolia\n 137: 'USD Coin', // Polygon\n 42161: 'USD Coin', // Arbitrum\n 43114: 'USD Coin', // Avalanche\n 42220: 'USDC', // Celo\n 143: 'USDC', // Monad\n};\n\n/**\n * Multi-chain escrow contract addresses for the Advanced Escrow system.\n * Keyed by EVM chain ID. Source: x402r-sdk A1igator/multichain-config deployment.\n */\nexport const ESCROW_CONTRACTS: Record<number, AdvancedEscrowContracts> = {\n // Base Sepolia (testnet, chain 84532)\n 84532: {\n operator: '0x97d53e63A9CB97556c00BeFd325AF810c9b267B2',\n escrow: '0x29025c0E9D4239d438e169570818dB9FE0A80873',\n tokenCollector: '0x5cA789000070DF15b4663DB64a50AeF5D49c5Ee0',\n protocolFeeConfig: '0x8F96C493bAC365E41f0315cf45830069EBbDCaCe',\n refundRequest: '0x1C2Ab244aC8bDdDB74d43389FF34B118aF2E90F4',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n },\n // Base Mainnet (chain 8453)\n 8453: {\n operator: '0x3D0837fF8Ea36F417261577b9BA568400A840260',\n escrow: '0xb9488351E48b23D798f24e8174514F28B741Eb4f',\n tokenCollector: '0x48ADf6E37F9b31dC2AAD0462C5862B5422C736B8',\n protocolFeeConfig: '0x59314674BAbb1a24Eb2704468a9cCdD50668a1C6',\n refundRequest: '0x35fb2EFEfAc3Ee9f6E52A9AAE5C9655bC08dEc00',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n },\n // Ethereum Sepolia (testnet, chain 11155111)\n 11155111: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n },\n // Ethereum Mainnet (chain 1) - Updated from Ali's redeploy (commit e6cf29d)\n 1: {\n operator: '0x69B67962ffb7c5C7078ff348a87DF604dfA8001b',\n escrow: '0x9D4146EF898c8E60B3e865AE254ef438E7cEd2A0',\n tokenCollector: '0x206D4DbB6E7b876e4B5EFAAD2a04e7d7813FB6ba',\n protocolFeeConfig: '0x5b3e33791C1764cF7e2573Bf8116F1D361FD97Cd',\n refundRequest: '0xFa8C4Cb156053b867Ae7489220A29b5939E3Df70',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n },\n // Polygon (chain 137)\n 137: {\n operator: '0xb33D6502EdBbC47201cd1E53C49d703EC0a660b8',\n escrow: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n tokenCollector: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n protocolFeeConfig: '0xE78648e7af7B1BaDE717FF6E410B922F92adE80f',\n refundRequest: '0xed02d3E5167BCc9582D851885A89b050AB816a56',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n },\n // Arbitrum (chain 42161)\n 42161: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n },\n // Celo (chain 42220)\n 42220: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n },\n // Monad (chain 143)\n 143: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0x754704Bc059F8C67012fEd69BC8a327a5aafb603',\n },\n // Avalanche (chain 43114)\n 43114: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n },\n // Optimism (chain 10)\n 10: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n },\n // SKALE Base (chain 1187947933) - CREATE3 deployment, operator via factory\n 1187947933: {\n operator: '0x28c23AE8f55aDe5Ea10a5353FC40418D0c1B3d33',\n escrow: '0xBC151792f80C0EB1973d56b0235e6bee2A60e245',\n tokenCollector: '0x9A12A116a44636F55c9e135189A1321Abcfe2f30',\n protocolFeeConfig: '0xf62788834C99B2E85a6891C0b46D1EB996f8f596',\n refundRequest: '0x69e9BF2b40Ed472b55E47e9D4205d93Ed673093F',\n usdc: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n },\n};\n\n/**\n * Base Mainnet contract addresses for the Advanced Escrow system.\n * @deprecated Use ESCROW_CONTRACTS[8453] or getEscrowContractsByChainId(8453) instead.\n */\nexport const BASE_MAINNET_CONTRACTS: AdvancedEscrowContracts = ESCROW_CONTRACTS[8453];\n\n/**\n * Get escrow contract addresses for a given chain ID.\n *\n * @param chainId - EVM chain ID (e.g., 8453 for Base, 1 for Ethereum)\n * @returns Contract addresses or undefined if chain is not supported\n */\nexport function getEscrowContractsByChainId(chainId: number): AdvancedEscrowContracts | undefined {\n return ESCROW_CONTRACTS[chainId];\n}\n\n/**\n * Get all chain IDs that have escrow contracts deployed.\n *\n * @returns Array of chain IDs with escrow support\n */\nexport function getEscrowSupportedChainIds(): number[] {\n return Object.keys(ESCROW_CONTRACTS).map(Number);\n}\n\n/**\n * Check if escrow contracts are deployed on a given chain.\n *\n * @param chainId - EVM chain ID\n * @returns True if escrow is supported on this chain\n */\nexport function isEscrowSupportedOnChain(chainId: number): boolean {\n return chainId in ESCROW_CONTRACTS;\n}\n\n/**\n * Task tiers determine timing parameters for escrow operations.\n */\nexport type AdvancedEscrowTaskTier = 'micro' | 'standard' | 'premium' | 'enterprise';\n\n/**\n * Timing configuration per task tier (in seconds).\n */\nexport const TIER_TIMINGS: Record<AdvancedEscrowTaskTier, { pre: number; auth: number; refund: number }> = {\n micro: { pre: 3600, auth: 7200, refund: 86400 },\n standard: { pre: 7200, auth: 86400, refund: 604800 },\n premium: { pre: 14400, auth: 172800, refund: 1209600 },\n enterprise: { pre: 86400, auth: 604800, refund: 2592000 },\n};\n\n/**\n * PaymentInfo struct matching the on-chain PaymentOperator contract.\n */\nexport interface AdvancedPaymentInfo {\n operator: string;\n receiver: string;\n token: string;\n maxAmount: string;\n preApprovalExpiry: number;\n authorizationExpiry: number;\n refundExpiry: number;\n minFeeBps: number;\n maxFeeBps: number;\n feeReceiver: string;\n salt: string;\n}\n\n/**\n * Result of an AUTHORIZE operation.\n */\nexport interface AdvancedAuthorizationResult {\n success: boolean;\n transactionHash?: string;\n paymentInfo?: AdvancedPaymentInfo;\n salt?: string;\n error?: string;\n}\n\n/**\n * Result of an on-chain transaction (release, refund, charge).\n */\nexport interface AdvancedTransactionResult extends FacilitatorFailureFields {\n success: boolean;\n transactionHash?: string;\n gasUsed?: number;\n /**\n * Why it failed.\n *\n * On the gasless (`*ViaFacilitator`) paths, check `retryable` first: a\n * facilitator that could not hand the write to its lease holder rejected\n * nothing on-chain, and the escrow is exactly as it was. Reporting that as a\n * failed refund is how funds get written off while they are still sitting in\n * escrow, recoverable.\n */\n error?: string;\n}\n\n/**\n * Response from the facilitator's /escrow/state endpoint.\n * Represents the on-chain state of an escrow for a given paymentInfo + payer.\n */\nexport interface EscrowStateResponse {\n /** Whether the payment has already been collected (released) */\n hasCollectedPayment: boolean;\n /** Amount that can still be captured/released (in atomic units) */\n capturableAmount: string;\n /** Amount that can still be refunded to the payer (in atomic units) */\n refundableAmount: string;\n /** Keccak256 hash of the paymentInfo struct */\n paymentInfoHash: string;\n /** Network in CAIP-2 format (e.g., \"eip155:8453\") */\n network: string;\n}\n\n/**\n * Contract addresses configuration for AdvancedEscrowClient.\n *\n * Maps to the on-chain x402r escrow contracts:\n * - operator: PaymentOperatorFactory\n * - escrow: AuthCaptureEscrow\n * - tokenCollector: TokenCollector\n * - protocolFeeConfig: ProtocolFeeConfig\n * - refundRequest: RefundRequest\n * - usdc: USDC token contract\n */\nexport interface AdvancedEscrowContracts {\n /** PaymentOperatorFactory contract address */\n operator: string;\n /** AuthCaptureEscrow contract address */\n escrow: string;\n /** TokenCollector contract address */\n tokenCollector: string;\n /** ProtocolFeeConfig contract address */\n protocolFeeConfig: string;\n /** RefundRequest contract address */\n refundRequest: string;\n /** USDC token contract address */\n usdc: string;\n}\n\n/**\n * Configuration options for AdvancedEscrowClient.\n */\nexport interface AdvancedEscrowClientOptions {\n /** Facilitator URL for AUTHORIZE operations */\n facilitatorUrl?: string;\n /** JSON-RPC URL for on-chain operations (required when using SigningWalletAdapter) */\n rpcUrl?: string;\n /**\n * Chain ID (default: 8453 for Base Mainnet).\n * Supported chains: 8453 (Base), 84532 (Base Sepolia), 1 (Ethereum),\n * 11155111 (Ethereum Sepolia), 137 (Polygon), 42161 (Arbitrum),\n * 10 (Optimism), 42220 (Celo), 143 (Monad), 43114 (Avalanche).\n */\n chainId?: number;\n /** Contract addresses (auto-resolved from chainId if not provided) */\n contracts?: AdvancedEscrowContracts;\n /** Gas limit for transactions (default: 300000) */\n gasLimit?: number;\n /**\n * Request timeout in milliseconds for facilitator HTTP calls (authorize, gasless release/refund).\n * Default is per-network: 960s for Ethereum L1, 90s for L2s.\n * Ethereum L1 confirmations can take several minutes under congestion.\n */\n timeout?: number;\n /**\n * SigningWalletAdapter for OWS wallet signing (v2.36.0+).\n *\n * When provided, the client uses the adapter for all signing operations\n * instead of requiring a raw ethers.Signer. The first constructor argument\n * is ignored when `wallet` is set.\n *\n * Requires `rpcUrl` to be set for on-chain transaction building.\n *\n * @example\n * ```typescript\n * import { OWSWalletAdapter, AdvancedEscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const client = new AdvancedEscrowClient(null, {\n * wallet,\n * rpcUrl: 'https://mainnet.base.org',\n * chainId: 8453,\n * });\n * ```\n */\n wallet?: import('../wallet').SigningWalletAdapter;\n /**\n * Extra attempts on the gasless facilitator paths when the facilitator proved\n * it executed nothing. Default 2; `0` disables.\n */\n retries?: number;\n}\n\n/**\n * Minimal PaymentOperator ABI for the 4 on-chain functions.\n * (AUTHORIZE goes through the facilitator, not directly on-chain)\n */\nexport const OPERATOR_ABI = [\n 'function release(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount)',\n 'function refundInEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint120 amount)',\n 'function charge(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n 'function refundPostEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n];\n\n/**\n * CREATE3-deployed operators (SKALE, future chains) use updated ABI with extra `bytes data` param\n * on release() and refundInEscrow(). Pass empty bytes (0x) for the data parameter.\n */\nexport const OPERATOR_ABI_CREATE3 = [\n 'function release(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, bytes data)',\n 'function refundInEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint120 amount, bytes data)',\n 'function charge(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n 'function refundPostEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n];\n\n/** Chain IDs using CREATE3-deployed operators with updated ABI */\nconst CREATE3_CHAIN_IDS = new Set([1187947933]);\n\n/**\n * AdvancedEscrowClient provides the 5 Advanced Escrow flows via the\n * PaymentOperator contract on 9 supported EVM networks.\n *\n * Supported chains: Base (8453), Base Sepolia (84532), Ethereum (1),\n * Ethereum Sepolia (11155111), Polygon (137), Arbitrum (42161),\n * Optimism (10), Celo (42220), Monad (143), Avalanche (43114).\n *\n * Contract addresses are auto-resolved from the chain ID.\n * Pass custom contracts to override.\n *\n * Two signer modes (v2.36.0+):\n * - **Legacy**: Pass an ethers.Signer as the first argument.\n * - **OWS Wallet**: Pass a SigningWalletAdapter via `options.wallet`.\n * The adapter signs transactions offline (no raw private key needed).\n * Requires `rpcUrl` for transaction building and broadcast.\n *\n * @example Legacy mode (ethers.Signer)\n * ```typescript\n * import { ethers } from 'ethers';\n * import { AdvancedEscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');\n * const signer = new ethers.Wallet(process.env.KEY!, provider);\n * const client = new AdvancedEscrowClient(signer, { chainId: 8453 });\n * ```\n *\n * @example OWS Wallet mode (SigningWalletAdapter)\n * ```typescript\n * import { OWSWalletAdapter } from 'uvd-x402-sdk';\n * import { AdvancedEscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const client = new AdvancedEscrowClient(null, {\n * wallet,\n * rpcUrl: 'https://mainnet.base.org',\n * chainId: 8453,\n * });\n * await client.init();\n *\n * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');\n * const auth = await client.authorize(pi);\n * const release = await client.release(pi);\n * ```\n */\nexport class AdvancedEscrowClient {\n private facilitatorUrl: string;\n private chainId: number;\n private gasLimit: number;\n private readonly timeout: number;\n private readonly retries: number | undefined;\n private contracts: AdvancedEscrowContracts;\n private signer: any; // ethers.Signer (legacy mode)\n private walletAdapter: import('../wallet').SigningWalletAdapter | null; // OWS mode (v2.36.0+)\n private rpcUrl: string | undefined;\n private payerAddress: string = '';\n\n /**\n * Create an AdvancedEscrowClient.\n *\n * Two modes of operation:\n *\n * 1. **Legacy (ethers.Signer)**: Pass an ethers Signer as the first argument.\n * ```ts\n * const client = new AdvancedEscrowClient(signer, { rpcUrl, chainId });\n * ```\n *\n * 2. **OWS Wallet (SigningWalletAdapter)**: Pass `wallet` in options. The\n * first argument is ignored (pass `null`). Requires `rpcUrl` for on-chain\n * transaction building and broadcast.\n * ```ts\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const client = new AdvancedEscrowClient(null, { wallet, rpcUrl, chainId });\n * ```\n *\n * @param signer - ethers.Signer instance (ignored when options.wallet is set)\n * @param options - Configuration options\n */\n constructor(signer: any, options: AdvancedEscrowClientOptions = {}) {\n this.walletAdapter = options.wallet || null;\n this.signer = this.walletAdapter ? null : signer;\n this.rpcUrl = options.rpcUrl;\n this.facilitatorUrl = (options.facilitatorUrl || 'https://facilitator.ultravioletadao.xyz').replace(/\\/$/, '');\n this.chainId = options.chainId || 8453;\n this.gasLimit = options.gasLimit || 300000;\n this.timeout = options.timeout || ESCROW_TIMEOUT_MS[this.chainId] || DEFAULT_ESCROW_TIMEOUT_MS;\n this.retries = options.retries;\n\n if (this.walletAdapter && !this.rpcUrl) {\n throw new Error(\n 'AdvancedEscrowClient: rpcUrl is required when using a SigningWalletAdapter. ' +\n 'The adapter signs transactions offline; an RPC provider is needed to build ' +\n 'and broadcast them.'\n );\n }\n\n if (options.contracts) {\n this.contracts = options.contracts;\n } else {\n const resolved = ESCROW_CONTRACTS[this.chainId];\n if (!resolved) {\n throw new Error(\n `No escrow contracts found for chain ID ${this.chainId}. ` +\n `Supported chains: ${getEscrowSupportedChainIds().join(', ')}. ` +\n `Pass custom contracts via options.contracts to use an unsupported chain.`\n );\n }\n this.contracts = resolved;\n }\n }\n\n /**\n * Initialize the client (resolves payer address).\n * Call this before using any methods.\n */\n async init(): Promise<void> {\n if (this.walletAdapter) {\n this.payerAddress = this.walletAdapter.getAddress();\n } else {\n this.payerAddress = await this.signer.getAddress();\n }\n }\n\n /**\n * Build a PaymentInfo struct with appropriate timing for the task tier.\n *\n * @param receiver - Worker's wallet address\n * @param amount - Amount in token atomic units (e.g., '5000000' for $5 USDC)\n * @param tier - Task tier determines timing parameters\n * @param salt - Random salt (auto-generated if not provided)\n */\n buildPaymentInfo(\n receiver: string,\n amount: string,\n tier: AdvancedEscrowTaskTier = 'standard',\n salt?: string,\n opts?: { deadline?: number; reviewWindowSec?: number },\n ): AdvancedPaymentInfo {\n const now = Math.floor(Date.now() / 1000);\n const t = TIER_TIMINGS[tier];\n // The release window must outlast the REVIEW, not just the tier. `micro`\n // alone gives two hours; a buyer approving later gets\n // `AfterAuthorizationExpiry` on-chain — the release reverts and the worker\n // is not paid. Measured in production 2026-08-19: a release attempted 26.2\n // HOURS past expiry, 8 escrows stuck on one network in 24h.\n //\n // This comment used to add \"and only the payer's `reclaim()` can move the\n // funds\". That is FALSE and it is why those escrows were treated as lost:\n // `AuthCaptureEscrow.partialVoid` is `onlySender(operator)` — the operator\n // is the facilitator — pays the PAYER, and does not look at\n // `authorizationExpiry`. `refundViaFacilitator` reaches it with no gas and\n // no payer. Widening the window still matters: it is what pays the WORKER,\n // and a refund does not.\n //\n // buildEscrowPreAuth — the other escrow path in this same SDK — already\n // floors both windows this way and says why. This path never got the memo,\n // and it is the one the marketplace documents as recommended.\n const reviewWindow = opts?.reviewWindowSec ?? REVIEW_WINDOW_SEC;\n const reviewBase = Math.max(now, opts?.deadline ?? now);\n const authorizationExpiry = Math.max(now + t.auth, reviewBase + reviewWindow);\n const refundExpiry = Math.max(now + t.refund, authorizationExpiry + REFUND_WINDOW_SEC);\n // Use crypto-safe randomness (Node.js crypto or Web Crypto API)\n let generatedSalt = salt;\n if (!generatedSalt) {\n const bytes = new Uint8Array(32);\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.getRandomValues) {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n // Node.js fallback\n const nodeCrypto = require('crypto');\n const buf = nodeCrypto.randomBytes(32);\n bytes.set(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));\n }\n generatedSalt = '0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n return {\n operator: this.contracts.operator,\n receiver,\n token: this.contracts.usdc,\n maxAmount: amount,\n preApprovalExpiry: now + t.pre,\n authorizationExpiry,\n refundExpiry,\n minFeeBps: 0,\n maxFeeBps: 800,\n feeReceiver: this.contracts.operator,\n salt: generatedSalt,\n };\n }\n\n /**\n * Compute the correct nonce (with PAYMENT_INFO_TYPEHASH).\n * Matches the on-chain AuthCaptureEscrow nonce derivation.\n */\n private async computeNonce(paymentInfo: AdvancedPaymentInfo): Promise<string> {\n // Dynamic import of ethers to avoid hard dependency at module level\n const { ethers } = await import('ethers');\n\n const piTuple = ethers.AbiCoder.defaultAbiCoder().encode(\n ['bytes32', 'tuple(address,address,address,address,uint120,uint48,uint48,uint48,uint16,uint16,address,uint256)'],\n [\n PAYMENT_INFO_TYPEHASH,\n [\n paymentInfo.operator,\n ZERO_ADDRESS, // payer = 0 for payer-agnostic hash\n paymentInfo.receiver,\n paymentInfo.token,\n paymentInfo.maxAmount,\n paymentInfo.preApprovalExpiry,\n paymentInfo.authorizationExpiry,\n paymentInfo.refundExpiry,\n paymentInfo.minFeeBps,\n paymentInfo.maxFeeBps,\n paymentInfo.feeReceiver,\n paymentInfo.salt,\n ],\n ],\n );\n const piHash = ethers.keccak256(piTuple);\n\n const finalEncoded = ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'address', 'bytes32'],\n [this.chainId, this.contracts.escrow, piHash],\n );\n return ethers.keccak256(finalEncoded);\n }\n\n /**\n * Sign ReceiveWithAuthorization for ERC-3009.\n *\n * Uses SigningWalletAdapter.signTypedData() when in OWS mode,\n * or ethers Signer.signTypedData() in legacy mode.\n */\n private async signErc3009(auth: Record<string, string>): Promise<string> {\n const domain = {\n name: USDC_DOMAIN_NAME[this.chainId] || 'USD Coin',\n version: '2',\n chainId: this.chainId,\n verifyingContract: this.contracts.usdc,\n };\n\n const types = {\n ReceiveWithAuthorization: [\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 const message = {\n from: auth.from,\n to: auth.to,\n value: auth.value,\n validAfter: auth.validAfter,\n validBefore: auth.validBefore,\n nonce: auth.nonce,\n };\n\n // OWS wallet adapter mode: serialize to JSON and use adapter.signTypedData()\n if (this.walletAdapter) {\n const typedData = JSON.stringify({\n domain,\n types,\n primaryType: 'ReceiveWithAuthorization',\n message,\n });\n const result = await this.walletAdapter.signTypedData(typedData);\n return result.signature;\n }\n\n // Legacy ethers.Signer mode\n return this.signer.signTypedData(domain, types, message);\n }\n\n /**\n * Build the on-chain PaymentInfo tuple for contract calls.\n */\n private buildTuple(pi: AdvancedPaymentInfo): any[] {\n return [\n pi.operator,\n this.payerAddress,\n pi.receiver,\n pi.token,\n pi.maxAmount,\n pi.preApprovalExpiry,\n pi.authorizationExpiry,\n pi.refundExpiry,\n pi.minFeeBps,\n pi.maxFeeBps,\n pi.feeReceiver,\n pi.salt,\n ];\n }\n\n /**\n * AUTHORIZE: Lock funds in escrow via the facilitator.\n *\n * Sends an ERC-3009 ReceiveWithAuthorization to the facilitator,\n * which calls PaymentOperator.authorize() on-chain.\n */\n async authorize(paymentInfo: AdvancedPaymentInfo): Promise<AdvancedAuthorizationResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const nonce = await this.computeNonce(paymentInfo);\n\n const auth = {\n from: this.payerAddress,\n to: this.contracts.tokenCollector,\n value: paymentInfo.maxAmount,\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce,\n };\n const signature = await this.signErc3009(auth);\n\n const payload = {\n x402Version: 2,\n scheme: 'escrow',\n payload: {\n authorization: auth,\n signature,\n paymentInfo: paymentInfo,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${this.chainId}`,\n maxAmountRequired: paymentInfo.maxAmount,\n asset: this.contracts.usdc,\n payTo: paymentInfo.receiver,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n },\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.facilitatorUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n const result = await response.json();\n\n if (result.success) {\n return {\n success: true,\n transactionHash: result.transaction,\n paymentInfo,\n salt: paymentInfo.salt,\n };\n }\n return { success: false, error: result.errorReason };\n } catch (fetchErr: any) {\n clearTimeout(timeoutId);\n\n // On timeout, check on-chain state as fallback\n if (fetchErr.name === 'AbortError') {\n try {\n const state = await this.queryEscrowState(paymentInfo);\n if (state.capturableAmount && BigInt(state.capturableAmount) > 0n) {\n return {\n success: true,\n paymentInfo,\n salt: paymentInfo.salt,\n };\n }\n } catch { /* fallback query failed, report original timeout */ }\n return { success: false, error: `Authorize timed out after ${this.timeout}ms. On-chain state could not confirm escrow lock.` };\n }\n throw fetchErr;\n }\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * RELEASE: Capture escrowed funds to receiver (worker gets paid).\n *\n * Calls PaymentOperator.release() -> escrow.capture()\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to release (defaults to maxAmount)\n */\n async release(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const isCreate3 = CREATE3_CHAIN_IDS.has(this.chainId);\n const abi = isCreate3 ? OPERATOR_ABI_CREATE3 : OPERATOR_ABI;\n const amt = amount || paymentInfo.maxAmount;\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode: build unsigned TX, sign via adapter, broadcast\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, abi, (iface) => {\n return isCreate3\n ? iface.encodeFunctionData('release', [tuple, amt, '0x'])\n : iface.encodeFunctionData('release', [tuple, amt]);\n });\n }\n\n // Legacy ethers.Signer mode: contract sends directly\n const contract = new ethers.Contract(this.contracts.operator, abi, this.signer);\n const tx = isCreate3\n ? await contract.release(tuple, amt, '0x', { gasLimit: this.gasLimit })\n : await contract.release(tuple, amt, { gasLimit: this.gasLimit });\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * REFUND IN ESCROW: Return escrowed funds to payer (cancel task).\n *\n * Calls PaymentOperator.refundInEscrow() -> escrow.partialVoid()\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to refund (defaults to maxAmount)\n */\n async refundInEscrow(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const isCreate3 = CREATE3_CHAIN_IDS.has(this.chainId);\n const abi = isCreate3 ? OPERATOR_ABI_CREATE3 : OPERATOR_ABI;\n const amt = amount || paymentInfo.maxAmount;\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode: build unsigned TX, sign via adapter, broadcast\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, abi, (iface) => {\n return isCreate3\n ? iface.encodeFunctionData('refundInEscrow', [tuple, amt, '0x'])\n : iface.encodeFunctionData('refundInEscrow', [tuple, amt]);\n });\n }\n\n // Legacy ethers.Signer mode\n const contract = new ethers.Contract(this.contracts.operator, abi, this.signer);\n const tx = isCreate3\n ? await contract.refundInEscrow(tuple, amt, '0x', { gasLimit: this.gasLimit })\n : await contract.refundInEscrow(tuple, amt, { gasLimit: this.gasLimit });\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n // ==========================================================================\n // GASLESS FACILITATOR METHODS\n // ==========================================================================\n\n /**\n * GASLESS RELEASE: Release escrowed funds via the facilitator.\n *\n * Instead of calling the PaymentOperator contract directly (which requires\n * gas), this sends a release request to the facilitator, which submits\n * the transaction on your behalf.\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to release in atomic units (defaults to maxAmount)\n * @returns Transaction result from the facilitator\n *\n * @example\n * ```typescript\n * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');\n * await client.authorize(pi);\n * // Worker completes task...\n * const result = await client.releaseViaFacilitator(pi);\n * console.log(result.transactionHash);\n * ```\n */\n async releaseViaFacilitator(\n paymentInfo: AdvancedPaymentInfo,\n amount?: string,\n ): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const payload = {\n x402Version: 2,\n scheme: 'escrow',\n action: 'release',\n payload: {\n paymentInfo: {\n operator: paymentInfo.operator,\n receiver: paymentInfo.receiver,\n token: paymentInfo.token,\n maxAmount: paymentInfo.maxAmount,\n preApprovalExpiry: paymentInfo.preApprovalExpiry,\n authorizationExpiry: paymentInfo.authorizationExpiry,\n refundExpiry: paymentInfo.refundExpiry,\n minFeeBps: paymentInfo.minFeeBps,\n maxFeeBps: paymentInfo.maxFeeBps,\n feeReceiver: paymentInfo.feeReceiver,\n salt: paymentInfo.salt,\n },\n payer: this.payerAddress,\n amount: amount || paymentInfo.maxAmount,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${this.chainId}`,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n },\n };\n\n try {\n // A 503 from the writer lease is NOT a refused release. The facilitator\n // never reached the chain, so the escrow still holds every token and\n // the same request is the right thing to send again. Reading it as a\n // refusal is how a recoverable escrow gets written off.\n const { response, error } = await facilitatorFetch(\n `${this.facilitatorUrl}/settle`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n if (error) {\n return { success: false, error: error.error, ...failureFields(error) };\n }\n const result = await response.json();\n\n if (result.success) {\n return {\n success: true,\n transactionHash: result.transaction || result.transactionHash || result.transaction_hash,\n };\n }\n // Parity with the Python SDK (2026-08-22): a last-resort message that\n // says only \"Release failed\" is the same dead end as an empty string —\n // name the status and what the body DID carry so the caller has a\n // thread to pull. Divergence between the two SDKs is exactly what let\n // the escrow-window bug live in one of them for weeks.\n return {\n success: false,\n error:\n result.errorReason ||\n result.error ||\n `Release refused with no reason (HTTP ${response.status}, body keys: ${Object.keys(result ?? {}).sort().join(', ') || 'none'})`,\n };\n } catch (fetchErr: any) {\n // On timeout, check on-chain state as fallback\n if (fetchErr.name === 'AbortError') {\n try {\n const state = await this.queryEscrowState(paymentInfo);\n if (state.capturableAmount === '0' && state.hasCollectedPayment) {\n return { success: true };\n }\n } catch { /* fallback query failed */ }\n return { success: false, error: `Gasless release timed out after ${this.timeout}ms. Check escrow state on-chain.` };\n }\n throw fetchErr;\n }\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * GASLESS REFUND: return escrowed funds to the payer via the facilitator.\n *\n * Sends `action: \"refundInEscrow\"` to `POST /settle`; the facilitator's\n * PaymentOperator calls `AuthCaptureEscrow.partialVoid`.\n *\n * # This is how an EXPIRED escrow is recovered\n *\n * A widely repeated claim — including in this SDK's own comments until now —\n * says that once `authorizationExpiry` passes, only the payer's `reclaim()`\n * can move the funds. **That is false, and believing it has left real money\n * stranded.**\n *\n * Read the contract (`AuthCaptureEscrow.sol`):\n *\n * - `partialVoid` is `onlySender(paymentInfo.operator)` — the operator is the\n * FACILITATOR, not the payer — it sends the tokens **to the payer**, and it\n * **does not check `authorizationExpiry` at all**. It works before expiry\n * and after it, and the payer never has to appear.\n * - `reclaim` is `onlySender(paymentInfo.payer)` and only after expiry. It is\n * a payer's self-service escape hatch, which is why this facilitator does\n * not expose it — **not** the only way out.\n *\n * So a release that reverted with `AfterAuthorizationExpiry` is recoverable\n * from here, with no gas and no cooperation from the payer. Get the amount\n * from {@link queryEscrowState}'s `capturableAmount`.\n *\n * # A refusal that is not a refusal\n *\n * Check `retryable` before writing an escrow off. A `503` means the\n * facilitator never reached the chain — the escrow is untouched and the same\n * request should be sent again.\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to refund in atomic units (defaults to maxAmount).\n * For a stuck escrow pass `capturableAmount` from {@link queryEscrowState}.\n * @returns Transaction result from the facilitator\n *\n * @example Recovering an escrow whose release window already closed\n * ```typescript\n * const state = await client.queryEscrowState(pi);\n * if (state.capturableAmount !== '0') {\n * // No payer needed, no gas, and expiry is irrelevant to partialVoid.\n * const result = await client.refundViaFacilitator(pi, state.capturableAmount);\n * if (!result.success && result.retryable) {\n * // No verdict was reached. The funds are still there; send it again.\n * }\n * }\n * ```\n */\n async refundViaFacilitator(\n paymentInfo: AdvancedPaymentInfo,\n amount?: string,\n ): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const payload = {\n x402Version: 2,\n scheme: 'escrow',\n action: 'refundInEscrow',\n payload: {\n paymentInfo: {\n operator: paymentInfo.operator,\n receiver: paymentInfo.receiver,\n token: paymentInfo.token,\n maxAmount: paymentInfo.maxAmount,\n preApprovalExpiry: paymentInfo.preApprovalExpiry,\n authorizationExpiry: paymentInfo.authorizationExpiry,\n refundExpiry: paymentInfo.refundExpiry,\n minFeeBps: paymentInfo.minFeeBps,\n maxFeeBps: paymentInfo.maxFeeBps,\n feeReceiver: paymentInfo.feeReceiver,\n salt: paymentInfo.salt,\n },\n payer: this.payerAddress,\n amount: amount || paymentInfo.maxAmount,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${this.chainId}`,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n },\n };\n\n try {\n // The non-2xx branch used to be missing entirely: `response.json()` on\n // a 503 body yields `{error, reason}`, `result.success` is undefined,\n // and the refund was reported as failed. That is a recoverable escrow\n // declared lost on a facilitator hiccup.\n const { response, error } = await facilitatorFetch(\n `${this.facilitatorUrl}/settle`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n if (error) {\n return { success: false, error: error.error, ...failureFields(error) };\n }\n const result = await response.json();\n\n if (result.success) {\n return {\n success: true,\n transactionHash: result.transaction || result.transactionHash || result.transaction_hash,\n };\n }\n return {\n success: false,\n error:\n result.errorReason ||\n result.error ||\n `Refund refused with no reason (HTTP ${response.status}, body keys: ${Object.keys(result ?? {}).sort().join(', ') || 'none'})`,\n };\n } catch (fetchErr: any) {\n // On timeout, check on-chain state as fallback\n if (fetchErr.name === 'AbortError') {\n try {\n const state = await this.queryEscrowState(paymentInfo);\n if (state.refundableAmount === '0') {\n return { success: true };\n }\n } catch { /* fallback query failed */ }\n return { success: false, error: `Gasless refund timed out after ${this.timeout}ms. Check escrow state on-chain.` };\n }\n throw fetchErr;\n }\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * QUERY ESCROW STATE: Read on-chain escrow state via the facilitator.\n *\n * This is a read-only operation that queries the facilitator for the\n * current escrow state without requiring gas or a signer.\n *\n * @param paymentInfo - PaymentInfo to query state for\n * @returns Escrow state including capturable/refundable amounts\n *\n * @example\n * ```typescript\n * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');\n * await client.authorize(pi);\n *\n * const state = await client.queryEscrowState(pi);\n * console.log(`Capturable: ${state.capturableAmount}`);\n * console.log(`Refundable: ${state.refundableAmount}`);\n * console.log(`Already collected: ${state.hasCollectedPayment}`);\n * ```\n */\n async queryEscrowState(paymentInfo: AdvancedPaymentInfo): Promise<EscrowStateResponse> {\n if (!this.payerAddress) await this.init();\n\n const payload = {\n paymentInfo: {\n operator: paymentInfo.operator,\n receiver: paymentInfo.receiver,\n token: paymentInfo.token,\n maxAmount: paymentInfo.maxAmount,\n preApprovalExpiry: paymentInfo.preApprovalExpiry,\n authorizationExpiry: paymentInfo.authorizationExpiry,\n refundExpiry: paymentInfo.refundExpiry,\n minFeeBps: paymentInfo.minFeeBps,\n maxFeeBps: paymentInfo.maxFeeBps,\n feeReceiver: paymentInfo.feeReceiver,\n salt: paymentInfo.salt,\n },\n payer: this.payerAddress,\n network: `eip155:${this.chainId}`,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n };\n\n const response = await fetch(`${this.facilitatorUrl}/escrow/state`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow state query failed: ${response.status} - ${errorText}`);\n }\n\n return await response.json() as EscrowStateResponse;\n }\n\n /**\n * CHARGE: Direct instant payment (no escrow hold).\n *\n * Calls PaymentOperator.charge() -> escrow.charge()\n * Funds go directly from payer to receiver.\n *\n * @param paymentInfo - PaymentInfo with receiver and amount\n * @param amount - Amount to charge (defaults to maxAmount)\n */\n async charge(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const nonce = await this.computeNonce(paymentInfo);\n const amt = amount || paymentInfo.maxAmount;\n\n const auth = {\n from: this.payerAddress,\n to: this.contracts.tokenCollector,\n value: String(amt),\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce,\n };\n const signature = await this.signErc3009(auth);\n // Pass raw signature bytes as collectorData (ethers handles hex -> bytes)\n const collectorData = ethers.getBytes(signature);\n\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, OPERATOR_ABI, (iface) => {\n return iface.encodeFunctionData('charge', [\n tuple, amt, this.contracts.tokenCollector, collectorData,\n ]);\n });\n }\n\n // Legacy ethers.Signer mode\n const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);\n const tx = await contract.charge(\n tuple,\n amt,\n this.contracts.tokenCollector,\n collectorData,\n { gasLimit: this.gasLimit },\n );\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * REFUND POST ESCROW: Dispute refund after funds were released.\n *\n * Calls PaymentOperator.refundPostEscrow() -> escrow.refund()\n *\n * WARNING: NOT FUNCTIONAL IN PRODUCTION (as of 2026-02-03).\n * The protocol team has not implemented the required tokenCollector\n * contract. This call will fail on-chain.\n *\n * For dispute resolution, use refundInEscrow() instead: keep funds\n * in escrow and refund before releasing. This guarantees funds are\n * available and under arbiter control.\n *\n * Kept for future use when tokenCollector is implemented.\n *\n * @param paymentInfo - PaymentInfo from the original authorization\n * @param amount - Amount to refund (defaults to maxAmount)\n * @param tokenCollector - Address of token collector for refund sourcing\n * @param collectorData - Data for the token collector\n */\n async refundPostEscrow(\n paymentInfo: AdvancedPaymentInfo,\n amount?: string,\n tokenCollector?: string,\n collectorData?: string,\n ): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const amt = amount || paymentInfo.maxAmount;\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, OPERATOR_ABI, (iface) => {\n return iface.encodeFunctionData('refundPostEscrow', [\n tuple, amt, tokenCollector || ZERO_ADDRESS, collectorData || '0x',\n ]);\n });\n }\n\n // Legacy ethers.Signer mode\n const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);\n const tx = await contract.refundPostEscrow(\n tuple,\n amt,\n tokenCollector || ZERO_ADDRESS,\n collectorData || '0x',\n { gasLimit: this.gasLimit },\n );\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n // ==========================================================================\n // INTERNAL: Adapter-based transaction signing and broadcast\n // ==========================================================================\n\n /**\n * Build an unsigned transaction, sign via SigningWalletAdapter, and broadcast.\n *\n * Used by release(), refundInEscrow(), charge(), refundPostEscrow() when\n * operating in OWS wallet adapter mode. The adapter signs the serialized\n * transaction offline; the RPC provider broadcasts the signed raw TX.\n *\n * @param ethersModule - ethers namespace (from `const { ethers } = await import('ethers')`)\n * @param abi - Contract ABI (OPERATOR_ABI or OPERATOR_ABI_CREATE3)\n * @param encodeCalldata - Function that encodes the calldata using the interface\n * @returns Transaction result\n */\n private async sendViaAdapter(\n ethersModule: any,\n abi: string[],\n encodeCalldata: (iface: any) => string,\n ): Promise<AdvancedTransactionResult> {\n const provider = new ethersModule.JsonRpcProvider(this.rpcUrl);\n const iface = new ethersModule.Interface(abi);\n const data = encodeCalldata(iface);\n\n // Build unsigned transaction\n const nonce = await provider.getTransactionCount(this.payerAddress);\n const feeData = await provider.getFeeData();\n\n const unsignedTx = ethersModule.Transaction.from({\n to: this.contracts.operator,\n data,\n gasLimit: this.gasLimit,\n nonce,\n chainId: this.chainId,\n maxFeePerGas: feeData.maxFeePerGas,\n maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,\n type: 2, // EIP-1559\n });\n\n // Sign via adapter\n const signedTxHex = await this.walletAdapter!.signTransaction(unsignedTx.unsignedSerialized);\n\n // Broadcast\n const txResponse = await provider.broadcastTransaction(signedTxHex);\n const receipt = await txResponse.wait();\n\n return {\n success: receipt !== null && receipt.status === 1,\n transactionHash: txResponse.hash,\n gasUsed: receipt ? Number(receipt.gasUsed) : undefined,\n error: receipt && receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/chains/index.ts","../src/dx402.ts","../src/types/index.ts","../src/utils/base64.ts","../src/utils/x402.ts","../src/utils/token-metadata.ts","../src/utils/validation.ts","../src/client/X402Client.ts","../src/adapters/env-key.ts","../src/adapters/ows.ts","../src/facilitator.ts","../src/events.ts","../src/erc8128.ts","../src/erc7702.ts","../src/escrow-preauth.ts","../src/backend/facilitator-error.ts","../src/backend/index.ts"],"names":["nobleHexToBytes","paymentId","contentHash","ethers","DEFAULT_FACILITATOR_URL","ZERO_ADDRESS","requirements","reqOptions"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * uvd-x402-sdk - Chain Registry\n *\n * Complete configuration for all 25 supported blockchain networks.\n * EVM chains (15): Use ERC-3009 TransferWithAuthorization (includes Scroll, SKALE Base, Robinhood Chain mainnet + testnet)\n * SVM chains (2): Solana and Fogo - Use SPL tokens with partially-signed transactions\n * Stellar (1): Uses Soroban authorization entries\n * NEAR (1): Uses NEP-366 meta-transactions\n * Algorand (2): Uses ASA transfers with atomic transaction groups\n * Sui (2): Uses sponsored transactions (facilitator pays gas)\n * XRPL (2): Native XRP via pre-signed Payment transaction blobs (facilitator pays fee)\n */\n\nimport type { ChainConfig, NetworkType, TokenType, TokenConfig } from '../types';\n\n/**\n * Default facilitator URL for x402 payments\n */\nexport const DEFAULT_FACILITATOR_URL = 'https://facilitator.ultravioletadao.xyz';\n\n/**\n * All supported chains configuration\n *\n * To add a new chain:\n * 1. Add chain config below with all required fields\n * 2. Verify USDC contract supports ERC-3009 (transferWithAuthorization) for EVM chains\n * 3. Test on testnet first before enabling\n */\nexport const SUPPORTED_CHAINS: Record<string, ChainConfig> = {\n // ============================================================================\n // EVM CHAINS (15 networks)\n // ============================================================================\n\n base: {\n chainId: 8453,\n chainIdHex: '0x2105',\n name: 'base',\n displayName: 'Base',\n networkType: 'evm',\n rpcUrl: 'https://mainnet.base.org',\n explorerUrl: 'https://basescan.org',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n eurc: {\n address: '0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42',\n decimals: 6,\n name: 'EURC',\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n avalanche: {\n chainId: 43114,\n chainIdHex: '0xa86a',\n name: 'avalanche',\n displayName: 'Avalanche C-Chain',\n networkType: 'evm',\n rpcUrl: 'https://avalanche-c-chain-rpc.publicnode.com',\n explorerUrl: 'https://snowtrace.io',\n nativeCurrency: {\n name: 'Avalanche',\n symbol: 'AVAX',\n decimals: 18,\n },\n usdc: {\n address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n eurc: {\n address: '0xC891EB4cbdEFf6e073e859e987815Ed1505c2ACD',\n decimals: 6,\n name: 'EURC',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n ethereum: {\n chainId: 1,\n chainIdHex: '0x1',\n name: 'ethereum',\n displayName: 'Ethereum',\n networkType: 'evm',\n rpcUrl: 'https://eth.llamarpc.com',\n explorerUrl: 'https://etherscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n eurc: {\n address: '0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c',\n decimals: 6,\n name: 'Euro Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n pyusd: {\n address: '0x6c3ea9036406852006290770BEdFcAbA0e23A0e8',\n decimals: 6,\n name: 'PayPal USD',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n polygon: {\n chainId: 137,\n chainIdHex: '0x89',\n name: 'polygon',\n displayName: 'Polygon',\n networkType: 'evm',\n rpcUrl: 'https://polygon-rpc.com',\n explorerUrl: 'https://polygonscan.com',\n nativeCurrency: {\n name: 'Polygon',\n symbol: 'POL',\n decimals: 18,\n },\n usdc: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n arbitrum: {\n chainId: 42161,\n chainIdHex: '0xa4b1',\n name: 'arbitrum',\n displayName: 'Arbitrum One',\n networkType: 'evm',\n rpcUrl: 'https://arb1.arbitrum.io/rpc',\n explorerUrl: 'https://arbiscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n usdt: {\n address: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9',\n decimals: 6,\n name: 'USD₮0',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n optimism: {\n chainId: 10,\n chainIdHex: '0xa',\n name: 'optimism',\n displayName: 'Optimism',\n networkType: 'evm',\n rpcUrl: 'https://mainnet.optimism.io',\n explorerUrl: 'https://optimistic.etherscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n usdt: {\n address: '0x01bff41798a0bcf287b996046ca68b395dbc1071',\n decimals: 6,\n name: 'USD₮0',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n celo: {\n chainId: 42220,\n chainIdHex: '0xa4ec',\n name: 'celo',\n displayName: 'Celo',\n networkType: 'evm',\n rpcUrl: 'https://forno.celo.org',\n explorerUrl: 'https://celoscan.io',\n nativeCurrency: {\n name: 'Celo',\n symbol: 'CELO',\n decimals: 18,\n },\n usdc: {\n address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n decimals: 6,\n name: 'USDC', // Celo uses \"USDC\" not \"USD Coin\" for EIP-712\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n decimals: 6,\n name: 'USDC', // Celo uses \"USDC\" not \"USD Coin\" for EIP-712\n version: '2',\n },\n usdt: {\n address: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e',\n decimals: 6,\n name: 'Tether USD', // Celo USDT uses \"Tether USD\" for EIP-712\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n hyperevm: {\n chainId: 999,\n chainIdHex: '0x3e7',\n name: 'hyperevm',\n displayName: 'HyperEVM',\n networkType: 'evm',\n rpcUrl: 'https://rpc.hyperliquid.xyz/evm',\n explorerUrl: 'https://hyperevmscan.io',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',\n decimals: 6,\n name: 'USDC', // HyperEVM uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',\n decimals: 6,\n name: 'USDC', // HyperEVM uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n unichain: {\n chainId: 130,\n chainIdHex: '0x82',\n name: 'unichain',\n displayName: 'Unichain',\n networkType: 'evm',\n rpcUrl: 'https://unichain-rpc.publicnode.com',\n explorerUrl: 'https://uniscan.xyz',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x078d782b760474a361dda0af3839290b0ef57ad6',\n decimals: 6,\n name: 'USDC', // Unichain uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x078d782b760474a361dda0af3839290b0ef57ad6',\n decimals: 6,\n name: 'USDC', // Unichain uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n monad: {\n chainId: 143,\n chainIdHex: '0x8f',\n name: 'monad',\n displayName: 'Monad',\n networkType: 'evm',\n rpcUrl: 'https://rpc.monad.xyz',\n explorerUrl: 'https://monad.socialscan.io',\n nativeCurrency: {\n name: 'Monad',\n symbol: 'MON',\n decimals: 18,\n },\n usdc: {\n address: '0x754704bc059f8c67012fed69bc8a327a5aafb603',\n decimals: 6,\n name: 'USDC', // Monad uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x754704bc059f8c67012fed69bc8a327a5aafb603',\n decimals: 6,\n name: 'USDC', // Monad uses \"USDC\" not \"USD Coin\"\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n usdt: {\n address: '0xe7cd86e13AC4309349F30B3435a9d337750fC82D',\n decimals: 6,\n name: 'USD\\u20AE0', // USD₮0 (USDT0 omnichain via LayerZero)\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n bsc: {\n chainId: 56,\n chainIdHex: '0x38',\n name: 'bsc',\n displayName: 'BNB Smart Chain',\n networkType: 'evm',\n rpcUrl: 'https://binance.llamarpc.com',\n explorerUrl: 'https://bscscan.com',\n nativeCurrency: {\n name: 'Binance Coin',\n symbol: 'BNB',\n decimals: 18,\n },\n usdc: {\n // Binance-Peg USDC — 18 decimals, NOT the 6 every other chain uses.\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d',\n decimals: 18,\n name: 'USD Coin',\n version: '2',\n },\n ausd: {\n address: '0x00000000eFE302BEAA2b3e6e1b18d08D69a9012a',\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n // Disabled on purpose: Binance-Peg USDC does not implement ERC-3009\n // `transferWithAuthorization`, so the exact scheme cannot settle it. The\n // entry exists so the 18-decimal figure is on record — assuming the usual\n // 6 here mis-prices a payment by 12 orders of magnitude.\n enabled: false,\n },\n },\n\n scroll: {\n chainId: 534352,\n chainIdHex: '0x82750',\n name: 'scroll',\n displayName: 'Scroll',\n networkType: 'evm',\n rpcUrl: 'https://rpc.scroll.io',\n explorerUrl: 'https://scrollscan.com',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4',\n decimals: 6,\n name: 'USD Coin',\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'skale-base': {\n chainId: 1187947933,\n chainIdHex: '0x46cea59d',\n name: 'skale-base',\n displayName: 'SKALE Base',\n networkType: 'evm',\n rpcUrl: 'https://skale-base.skalenodes.com/v1/base',\n explorerUrl: 'https://skale-base-explorer.skalenodes.com',\n nativeCurrency: {\n name: 'CREDIT',\n symbol: 'CREDIT',\n decimals: 18,\n },\n usdc: {\n address: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'skale-base-sepolia': {\n chainId: 324705682,\n chainIdHex: '0x135a9d92',\n name: 'skale-base-sepolia',\n displayName: 'SKALE Base Sepolia',\n networkType: 'evm',\n rpcUrl: 'https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha',\n explorerUrl: 'https://base-sepolia-testnet-explorer.skalenodes.com',\n nativeCurrency: {\n name: 'CREDIT',\n symbol: 'CREDIT',\n decimals: 18,\n },\n usdc: {\n address: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n tokens: {\n usdc: {\n address: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n decimals: 6,\n name: 'Bridged USDC (SKALE Bridge)', // Must match on-chain EIP-712 domain exactly\n version: '2',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // Robinhood Chain (Arbitrum Orbit L2). NOTE: there is NO USDC on this chain -\n // the settlement stablecoin is Paxos USDG (Global Dollar). The `usdc` field\n // below carries USDG for interface compatibility (same pattern as XRPL's native\n // asset), and `tokens.usdg` is the canonical entry.\n // CRITICAL: USDG's on-chain version() getter REVERTS, so the EIP-712 domain\n // { name: 'Global Dollar', version: '1' } can NEVER be resolved on-chain and\n // MUST come from this config (mirrored into PaymentRequirements.extra by callers).\n robinhood: {\n chainId: 4663,\n chainIdHex: '0x1237',\n name: 'robinhood',\n displayName: 'Robinhood Chain',\n networkType: 'evm',\n rpcUrl: 'https://rpc.mainnet.chain.robinhood.com',\n explorerUrl: 'https://robinhoodchain.blockscout.com',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168', // Paxos USDG (no USDC on this chain)\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n tokens: {\n usdg: {\n address: '0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168',\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'robinhood-testnet': {\n chainId: 46630,\n chainIdHex: '0xb626',\n name: 'robinhood-testnet',\n displayName: 'Robinhood Chain Testnet',\n networkType: 'evm',\n rpcUrl: 'https://rpc.testnet.chain.robinhood.com',\n explorerUrl: 'https://explorer.testnet.chain.robinhood.com',\n nativeCurrency: {\n name: 'Ethereum',\n symbol: 'ETH',\n decimals: 18,\n },\n usdc: {\n address: '0x7E955252E15c84f5768B83c41a71F9eba181802F', // Paxos USDG testnet (no USDC on this chain)\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n tokens: {\n usdg: {\n address: '0x7E955252E15c84f5768B83c41a71F9eba181802F',\n decimals: 6,\n name: 'Global Dollar', // on-chain version() reverts; domain must be supplied off-chain\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // SVM CHAINS (2 networks) - Solana Virtual Machine\n // ============================================================================\n\n solana: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'solana',\n displayName: 'Solana',\n networkType: 'svm',\n rpcUrl: 'https://api.mainnet-beta.solana.com',\n explorerUrl: 'https://solscan.io',\n nativeCurrency: {\n name: 'Solana',\n symbol: 'SOL',\n decimals: 9,\n },\n usdc: {\n address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC SPL token mint\n decimals: 6,\n name: 'USD Coin',\n version: '1',\n },\n tokens: {\n usdc: {\n address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // USDC SPL token mint\n decimals: 6,\n name: 'USD Coin',\n version: '1',\n },\n ausd: {\n address: 'AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9', // AUSD Token2022 mint\n decimals: 6,\n name: 'Agora Dollar',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n fogo: {\n chainId: 0, // Non-EVM (SVM)\n chainIdHex: '0x0',\n name: 'fogo',\n displayName: 'Fogo',\n networkType: 'svm',\n rpcUrl: 'https://rpc.fogo.nightly.app/',\n explorerUrl: 'https://explorer.fogo.nightly.app',\n nativeCurrency: {\n name: 'Fogo',\n symbol: 'FOGO',\n decimals: 9,\n },\n usdc: {\n address: 'uSd2czE61Evaf76RNbq4KPpXnkiL3irdzgLFUMe3NoG', // Fogo USDC mint\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // STELLAR (1 network)\n // ============================================================================\n\n stellar: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'stellar',\n displayName: 'Stellar',\n networkType: 'stellar',\n rpcUrl: 'https://horizon.stellar.org',\n explorerUrl: 'https://stellar.expert/explorer/public',\n nativeCurrency: {\n name: 'Lumens',\n symbol: 'XLM',\n decimals: 7, // Stellar uses 7 decimals (stroops)\n },\n usdc: {\n address: 'CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75', // Soroban Asset Contract\n decimals: 7, // Stellar USDC uses 7 decimals\n name: 'USDC',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // NEAR (1 network) - Uses NEP-366 meta-transactions\n // ============================================================================\n\n near: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'near',\n displayName: 'NEAR Protocol',\n networkType: 'near',\n rpcUrl: 'https://rpc.mainnet.near.org',\n explorerUrl: 'https://nearblocks.io',\n nativeCurrency: {\n name: 'NEAR',\n symbol: 'NEAR',\n decimals: 24, // NEAR uses 24 decimals (yoctoNEAR)\n },\n usdc: {\n address: '17208628f84f5d6ad33f0da3bbbeb27ffcb398eac501a31bd6ad2011e36133a1', // Native Circle USDC\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true, // NEP-366 meta-transactions supported\n },\n },\n\n // ============================================================================\n // ALGORAND (2 networks) - Uses ASA transfers with atomic transaction groups\n // ============================================================================\n\n algorand: {\n chainId: 0, // Non-EVM (Algorand uses genesis hash for network identification)\n chainIdHex: '0x0',\n name: 'algorand',\n displayName: 'Algorand',\n networkType: 'algorand',\n rpcUrl: 'https://mainnet-api.algonode.cloud',\n explorerUrl: 'https://allo.info',\n nativeCurrency: {\n name: 'Algo',\n symbol: 'ALGO',\n decimals: 6, // Algorand uses 6 decimals (microAlgos)\n },\n usdc: {\n address: '31566704', // USDC ASA ID on Algorand mainnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '31566704', // USDC ASA ID on Algorand mainnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'algorand-testnet': {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'algorand-testnet',\n displayName: 'Algorand Testnet',\n networkType: 'algorand',\n rpcUrl: 'https://testnet-api.algonode.cloud',\n explorerUrl: 'https://testnet.allo.info',\n nativeCurrency: {\n name: 'Algo',\n symbol: 'ALGO',\n decimals: 6,\n },\n usdc: {\n address: '10458941', // USDC ASA ID on Algorand testnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '10458941', // USDC ASA ID on Algorand testnet\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // SUI (2 networks) - Uses sponsored transactions (facilitator pays gas)\n // ============================================================================\n\n sui: {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'sui',\n displayName: 'Sui',\n networkType: 'sui',\n rpcUrl: 'https://fullnode.mainnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/mainnet',\n nativeCurrency: {\n name: 'Sui',\n symbol: 'SUI',\n decimals: 9,\n },\n usdc: {\n // USDC coin type on Sui mainnet\n address: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n ausd: {\n // AUSD (Agora USD) coin type on Sui mainnet\n address: '0x2053d08c1e2bd02791056171aab0fd12bd7cd7efad2ab8f6b9c8902f14df2ff2::ausd::AUSD',\n decimals: 6,\n name: 'AUSD',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'sui-testnet': {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'sui-testnet',\n displayName: 'Sui Testnet',\n networkType: 'sui',\n rpcUrl: 'https://fullnode.testnet.sui.io:443',\n explorerUrl: 'https://suiscan.xyz/testnet',\n nativeCurrency: {\n name: 'Sui',\n symbol: 'SUI',\n decimals: 9,\n },\n usdc: {\n // USDC coin type on Sui testnet\n address: '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n tokens: {\n usdc: {\n address: '0xa1ec7fc00a6f40db9693ad1415d0c193ad3906494428cf252621037bd7117e29::usdc::USDC',\n decimals: 6,\n name: 'USDC',\n version: '1',\n },\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n // ============================================================================\n // XRPL (2 networks) - XRP Ledger, native XRP via pre-signed Payment blobs\n // ============================================================================\n\n 'xrpl-mainnet': {\n chainId: 0, // Non-EVM (XRPL uses network id strings, no numeric chain ID)\n chainIdHex: '0x0',\n name: 'xrpl-mainnet',\n displayName: 'XRP Ledger',\n networkType: 'xrpl',\n rpcUrl: 'https://xrplcluster.com',\n explorerUrl: 'https://livenet.xrpl.org',\n nativeCurrency: {\n name: 'XRP',\n symbol: 'XRP',\n decimals: 6, // XRPL uses 6 decimals (drops); 1 XRP = 1,000,000 drops\n },\n // XRPL settles in native XRP - there is no USDC/token contract.\n // The `usdc` field describes the native asset for interface compatibility.\n usdc: {\n address: 'XRP', // Native asset - no token contract\n decimals: 6,\n name: 'XRP',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n\n 'xrpl-testnet': {\n chainId: 0, // Non-EVM\n chainIdHex: '0x0',\n name: 'xrpl-testnet',\n displayName: 'XRP Ledger Testnet',\n networkType: 'xrpl',\n rpcUrl: 'https://s.altnet.rippletest.net:51234',\n explorerUrl: 'https://testnet.xrpl.org',\n nativeCurrency: {\n name: 'XRP',\n symbol: 'XRP',\n decimals: 6,\n },\n // XRPL settles in native XRP - there is no USDC/token contract.\n usdc: {\n address: 'XRP', // Native asset - no token contract\n decimals: 6,\n name: 'XRP',\n version: '1',\n },\n x402: {\n facilitatorUrl: DEFAULT_FACILITATOR_URL,\n enabled: true,\n },\n },\n};\n\n/**\n * Default chain for new users\n */\nexport const DEFAULT_CHAIN = 'base';\n\n/**\n * Get chain config by chain ID\n */\nexport function getChainById(chainId: number): ChainConfig | undefined {\n return Object.values(SUPPORTED_CHAINS).find(chain => chain.chainId === chainId);\n}\n\n/**\n * Get chain config by name (case-insensitive)\n */\nexport function getChainByName(name: string): ChainConfig | undefined {\n return SUPPORTED_CHAINS[name.toLowerCase()];\n}\n\n/**\n * Check if a chain is supported\n */\nexport function isChainSupported(chainIdOrName: number | string): boolean {\n if (typeof chainIdOrName === 'number') {\n return Object.values(SUPPORTED_CHAINS).some(chain => chain.chainId === chainIdOrName);\n }\n return chainIdOrName.toLowerCase() in SUPPORTED_CHAINS;\n}\n\n/**\n * Get list of enabled chains\n */\nexport function getEnabledChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(chain => chain.x402.enabled);\n}\n\n/**\n * Get list of chains by network type\n */\nexport function getChainsByNetworkType(networkType: NetworkType): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === networkType && chain.x402.enabled\n );\n}\n\n/**\n * Get all EVM chain IDs (for wallet_switchEthereumChain)\n */\nexport function getEVMChainIds(): number[] {\n return getChainsByNetworkType('evm').map(chain => chain.chainId);\n}\n\n/**\n * Get list of SVM chains (Solana, Fogo)\n */\nexport function getSVMChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'svm' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is SVM-based (Solana Virtual Machine)\n */\nexport function isSVMChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'svm';\n}\n\n/**\n * Get list of Sui chains\n */\nexport function getSuiChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'sui' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is Sui-based\n */\nexport function isSuiChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'sui';\n}\n\n/**\n * Get network type from chain name\n */\nexport function getNetworkType(chainName: string): NetworkType | undefined {\n const chain = getChainByName(chainName);\n return chain?.networkType;\n}\n\n/**\n * Format transaction URL for block explorer\n */\nexport function getExplorerTxUrl(chainName: string, txHash: string): string | null {\n const chain = getChainByName(chainName);\n if (!chain) return null;\n\n switch (chain.networkType) {\n case 'evm':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'svm':\n case 'solana': // @deprecated\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'stellar':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'near':\n return `${chain.explorerUrl}/txns/${txHash}`;\n case 'algorand':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'sui':\n return `${chain.explorerUrl}/tx/${txHash}`;\n case 'xrpl':\n return `${chain.explorerUrl}/transactions/${txHash}`;\n default:\n return null;\n }\n}\n\n/**\n * Format address URL for block explorer\n */\nexport function getExplorerAddressUrl(chainName: string, address: string): string | null {\n const chain = getChainByName(chainName);\n if (!chain) return null;\n\n switch (chain.networkType) {\n case 'evm':\n return `${chain.explorerUrl}/address/${address}`;\n case 'svm':\n case 'solana': // @deprecated\n return `${chain.explorerUrl}/account/${address}`;\n case 'stellar':\n return `${chain.explorerUrl}/account/${address}`;\n case 'near':\n return `${chain.explorerUrl}/address/${address}`;\n case 'algorand':\n return `${chain.explorerUrl}/account/${address}`;\n case 'sui':\n return `${chain.explorerUrl}/account/${address}`;\n case 'xrpl':\n return `${chain.explorerUrl}/accounts/${address}`;\n default:\n return null;\n }\n}\n\n/**\n * Get list of Algorand chains\n */\nexport function getAlgorandChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'algorand' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is Algorand-based\n */\nexport function isAlgorandChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'algorand';\n}\n\n/**\n * Get list of XRPL chains (XRP Ledger mainnet/testnet)\n */\nexport function getXRPLChains(): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(\n chain => chain.networkType === 'xrpl' && chain.x402.enabled\n );\n}\n\n/**\n * Check if a chain is XRPL-based (XRP Ledger)\n */\nexport function isXRPLChain(chainName: string): boolean {\n const chain = getChainByName(chainName);\n return chain?.networkType === 'xrpl';\n}\n\n// ============================================================================\n// MULTI-TOKEN SUPPORT FUNCTIONS\n// ============================================================================\n\n/**\n * Get token configuration for a specific chain and token type\n * Falls back to USDC config if token not found (for backward compatibility)\n *\n * @param chainName - Chain name (e.g., 'ethereum', 'base')\n * @param tokenType - Token type (e.g., 'usdc', 'eurc', 'pyusd')\n * @returns Token configuration or undefined if chain not found\n */\nexport function getTokenConfig(\n chainName: string,\n tokenType: TokenType = 'usdc'\n): TokenConfig | undefined {\n const chain = getChainByName(chainName);\n if (!chain) return undefined;\n\n // Try to get from tokens map first (new multi-token support)\n if (chain.tokens && chain.tokens[tokenType]) {\n return chain.tokens[tokenType];\n }\n\n // Fall back to usdc config for backward compatibility\n if (tokenType === 'usdc') {\n return chain.usdc;\n }\n\n return undefined;\n}\n\n/**\n * Find which token of a chain a contract address belongs to.\n *\n * The signed payload carries the token *address*, but a server that accepts\n * several stablecoins on the same chain needs the symbol, the decimals and the\n * EIP-712 domain to rebuild the payment requirements. This resolves the address\n * back to the registry entry so that metadata can travel with the payment.\n *\n * @param chainName - Chain name (e.g., 'optimism')\n * @param address - Token contract address (case-insensitive on EVM)\n * @returns The token type and its config, or undefined if the address is not in the registry\n */\nexport function getTokenByAddress(\n chainName: string,\n address: string\n): { tokenType: TokenType; config: TokenConfig } | undefined {\n const chain = getChainByName(chainName);\n if (!chain || !address) return undefined;\n\n const wanted = address.startsWith('0x') ? address.toLowerCase() : address;\n const matches = (candidate: string): boolean =>\n (candidate.startsWith('0x') ? candidate.toLowerCase() : candidate) === wanted;\n\n if (chain.tokens) {\n for (const [tokenType, config] of Object.entries(chain.tokens)) {\n if (config && matches(config.address)) {\n return { tokenType: tokenType as TokenType, config };\n }\n }\n }\n\n if (chain.usdc && matches(chain.usdc.address)) {\n return { tokenType: 'usdc', config: chain.usdc };\n }\n\n return undefined;\n}\n\n/**\n * Get list of supported tokens for a chain\n *\n * @param chainName - Chain name (e.g., 'ethereum', 'base')\n * @returns Array of supported token types, or empty array if chain not found\n */\nexport function getSupportedTokens(chainName: string): TokenType[] {\n const chain = getChainByName(chainName);\n if (!chain) return [];\n\n // If tokens map exists, return its keys\n if (chain.tokens) {\n return Object.keys(chain.tokens) as TokenType[];\n }\n\n // Default to just USDC for chains without explicit tokens map\n return ['usdc'];\n}\n\n/**\n * Check if a token is supported on a specific chain\n *\n * @param chainName - Chain name (e.g., 'ethereum', 'base')\n * @param tokenType - Token type (e.g., 'usdc', 'eurc', 'pyusd')\n * @returns true if token is supported on the chain\n */\nexport function isTokenSupported(chainName: string, tokenType: TokenType): boolean {\n const chain = getChainByName(chainName);\n if (!chain) return false;\n\n // Check tokens map\n if (chain.tokens && chain.tokens[tokenType]) {\n return true;\n }\n\n // USDC is always supported (backward compatibility)\n if (tokenType === 'usdc') {\n return true;\n }\n\n return false;\n}\n\n/**\n * Get all chains that support a specific token\n *\n * @param tokenType - Token type (e.g., 'usdc', 'eurc', 'pyusd')\n * @returns Array of chain configs that support the token\n */\nexport function getChainsByToken(tokenType: TokenType): ChainConfig[] {\n return Object.values(SUPPORTED_CHAINS).filter(chain => {\n if (!chain.x402.enabled) return false;\n if (chain.tokens && chain.tokens[tokenType]) return true;\n if (tokenType === 'usdc') return true; // USDC is universal\n return false;\n });\n}\n","/**\n * DX402 `durable-evidence`: recover a paid response after the fact.\n *\n * x402 settles payment on-chain permanently but delivers the purchased resource\n * **exactly once**, in the body of a `200 OK`, and keeps nothing. A buyer who did\n * not capture it at that instant cannot recover it, and neither party can later\n * prove *what* was delivered — only *that* payment happened.\n *\n * DX402 closes that gap. The seller seals a copy of the response to the payer's\n * own public key — recovered from the payment signature itself — and anchors it.\n * The buyer gets an `X-Durable-Evidence` header pointing at it.\n *\n * **Paying is publishing your encryption key.** No registration, no key\n * exchange, no extra round trip.\n *\n * ```ts\n * const evidence = evidenceFromHeaders(response.headers);\n * const body = await recoverEvidence(evidence, myPrivateKey);\n * ```\n *\n * Specification: `docs/plans/dx402/02-SPEC-v0.1.md` in x402-rs.\n */\n\nimport { gcm } from '@noble/ciphers/aes';\nimport { ed25519, x25519 } from '@noble/curves/ed25519';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { hkdf } from '@noble/hashes/hkdf';\nimport {\n hexToBytes as nobleHexToBytes,\n bytesToHex,\n} from '@noble/hashes/utils';\nimport { keccak_256 } from '@noble/hashes/sha3';\n\nimport { getChainById, getChainByName } from './chains';\nimport { sha256, sha512 } from '@noble/hashes/sha2';\n\nexport const EVIDENCE_HEADER = 'X-Durable-Evidence';\n\nconst MAGIC = new Uint8Array([0x44, 0x58, 0x34, 0x30, 0x32]); // \"DX402\"\n/** One recipient (the payer). Still emitted for that case, so deployed readers keep working. */\nconst FORMAT_V1 = 1;\n/** Several recipients. A v2 blob positively signals that somebody besides the payer can open it. */\nconst FORMAT_V2 = 2;\n\n/** Why a party holds a key to this evidence. */\nexport type RecipientRole = 'payer' | 'seller' | 'auditor';\nconst ROLE_NAMES: RecipientRole[] = ['payer', 'seller', 'auditor'];\nconst NONCE_LEN = 12;\nconst CEK_LEN = 32;\nconst HKDF_INFO = new TextEncoder().encode('DX402-v1-wrap');\n\nexport class DX402Error extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'DX402Error';\n }\n}\n\n/**\n * No evidence was anchored for this payment.\n *\n * A normal outcome, not a fault: the body may have exceeded the seller's size\n * cap, the store may have been unreachable, or the payer may be a\n * smart-contract wallet with no recoverable key.\n */\nexport class EvidenceSkipped extends DX402Error {\n constructor(public readonly reason: string) {\n super(`no durable evidence was anchored: ${reason}`);\n this.name = 'EvidenceSkipped';\n }\n}\n\n/**\n * The anchored bytes are not the bytes that were delivered.\n *\n * This is the interesting failure: the seller anchored something other than\n * what it served, which is precisely the fraud `contentHash` exists to expose.\n * Treat it as evidence of misbehaviour, not a transport glitch.\n */\nexport class ContentHashMismatch extends DX402Error {\n constructor(\n public readonly anchored: string,\n public readonly actual: string,\n ) {\n super(`content hash mismatch: anchored ${anchored}, decrypted ${actual}`);\n this.name = 'ContentHashMismatch';\n }\n}\n\nexport type EvidenceMode = 'direct' | 'escrowed';\n\nexport interface AnchoredEvidence {\n v: number;\n paymentId: string;\n pointer: string;\n backend: string;\n contentHash: string;\n cipher: string;\n keyAlg: 'ECIES-secp256k1' | 'ECIES-X25519';\n mode: EvidenceMode;\n retention: string;\n receipt?: string;\n}\n\n/**\n * Whether the facilitator is cryptographically unable to read this payload.\n *\n * `direct` and `escrowed` make materially different claims about who can open\n * the payload, so a caller that cares about confidentiality must check rather\n * than assume.\n */\nexport function isEndToEnd(evidence: AnchoredEvidence): boolean {\n return evidence.mode === 'direct';\n}\n\nfunction b64urlDecode(value: string): Uint8Array {\n const normalized = value.trim().replace(/-/g, '+').replace(/_/g, '/');\n const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);\n return Uint8Array.from(atob(padded), (c) => c.charCodeAt(0));\n}\n\n/**\n * Hex decode, strictly.\n *\n * The hand-rolled loop this replaces used `parseInt`, which returns NaN for\n * non-hex input — and a Uint8Array stores NaN as 0. So `'zz'.repeat(32)`\n * decoded to 32 zero bytes and `parseInt('4z', 16)` to 4: malformed input\n * became a plausible-looking key instead of an error. This gates real key\n * material (the payer private key in `recoverEvidence`, the 65-byte signature\n * in `payerKeyFromEvmSignature`, the payee address in `anchorDigest`), and the\n * symptom was a misleading 'wrong key, or the blob belongs to another payment'\n * one layer later. Same failure class as the base58 `rjust(32)` bug in the\n * Python SDK. Python (`bytes.fromhex`) and Rust (`hex::decode`) already reject;\n * TypeScript was the permissive outlier.\n */\nfunction hexToBytes(hex: string): Uint8Array {\n const clean = hex.startsWith('0x') ? hex.slice(2) : hex;\n try {\n return nobleHexToBytes(clean);\n } catch (e) {\n throw new DX402Error(`invalid hex: ${(e as Error).message}`);\n }\n}\n\n/** keccak256 of a body, `0x`-prefixed — matching the facilitator's `contentHash`. */\nexport function contentHash(body: Uint8Array): string {\n return '0x' + bytesToHex(keccak_256(body));\n}\n\n/**\n * Derive the canonical payment identifier: `keccak256(caip2Network || txHash)`.\n *\n * This value is the AEAD associated data binding a ciphertext to its payment.\n * Buyer and seller must derive it identically or decryption fails with no\n * obvious cause, which is why it lives in the SDK rather than in each caller.\n */\nexport function paymentId(caip2Network: string, txHash: string): string {\n const enc = new TextEncoder();\n const clean = txHash.startsWith('0x') ? txHash.slice(2) : txHash;\n const preimage = new Uint8Array([...enc.encode(caip2Network), ...enc.encode(clean)]);\n return '0x' + bytesToHex(keccak_256(preimage));\n}\n\n/** Parse an `X-Durable-Evidence` header value. */\nexport function parseEvidenceHeader(value: string): AnchoredEvidence {\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(new TextDecoder().decode(b64urlDecode(value)));\n } catch (err) {\n throw new DX402Error(`malformed ${EVIDENCE_HEADER} header: ${String(err)}`);\n }\n if ('skipped' in payload) {\n throw new EvidenceSkipped(String(payload.skipped));\n }\n if (!payload.paymentId || !payload.pointer || !payload.contentHash) {\n throw new DX402Error(`malformed ${EVIDENCE_HEADER} header: missing required fields`);\n }\n return payload as unknown as AnchoredEvidence;\n}\n\n/**\n * Pull the anchored evidence out of a response's headers.\n *\n * Accepts a `Headers` object or a plain record. Lookup is case-insensitive,\n * because HTTP does not care and different clients disagree about casing.\n */\nexport function evidenceFromHeaders(\n headers: Headers | Record<string, string>,\n): AnchoredEvidence {\n let raw: string | null | undefined;\n if (typeof (headers as Headers).get === 'function') {\n raw = (headers as Headers).get(EVIDENCE_HEADER);\n } else {\n const target = EVIDENCE_HEADER.toLowerCase();\n for (const [key, value] of Object.entries(headers as Record<string, string>)) {\n if (key.toLowerCase() === target) {\n raw = value;\n break;\n }\n }\n }\n if (!raw) throw new DX402Error(`no ${EVIDENCE_HEADER} header on this response`);\n return parseEvidenceHeader(raw);\n}\n\n/**\n * Turn a DX402 pointer into a fetchable URL.\n *\n * `s3+https://...` is a scheme tag over an ordinary HTTPS URL; `ipfs://` and\n * `ar://` go through public gateways. Anything else passes through untouched, so\n * a caller with their own resolver is not blocked by this function.\n */\nexport function dereferencePointer(pointer: string): string {\n if (pointer.startsWith('s3+')) return pointer.slice(3);\n if (pointer.startsWith('ipfs://')) return `https://ipfs.io/ipfs/${pointer.slice(7)}`;\n if (pointer.startsWith('ar://')) return `https://arweave.net/${pointer.slice(5)}`;\n return pointer;\n}\n\ninterface Recipient {\n role: RecipientRole;\n alg: 'secp256k1' | 'x25519';\n ephemeral: Uint8Array;\n cekNonce: Uint8Array;\n wrappedCek: Uint8Array;\n}\n\ninterface SealedEnvelope {\n recipients: Recipient[];\n bodyNonce: Uint8Array;\n ciphertext: Uint8Array;\n}\n\n/**\n * Who can open this blob, without decrypting anything.\n *\n * Worth surfacing: a buyer has to be able to see that the seller — or a\n * designated auditor — also holds a key to what they bought. Finding that out\n * afterwards would destroy the privacy property.\n */\nexport function sealedRoles(raw: Uint8Array): RecipientRole[] {\n return parseSealed(raw).recipients.map((r) => r.role);\n}\n\n/**\n * Parse the sealed-blob layout.\n *\n * `MAGIC | version | alg | ephLen | eph | cekNonce | wrappedLen | wrapped |\n * bodyNonce | ciphertext`\n *\n * Every read is bounds-checked, so a truncated blob is a clear parse failure\n * rather than an out-of-range surprise later.\n */\nexport function parseSealed(raw: Uint8Array): SealedEnvelope {\n let pos = 0;\n const take = (n: number, what: string): Uint8Array => {\n if (raw.length < pos + n) throw new DX402Error(`truncated DX402 sealed blob at ${what}`);\n const chunk = raw.subarray(pos, pos + n);\n pos += n;\n return chunk;\n };\n\n const magic = take(MAGIC.length, 'magic');\n for (let i = 0; i < MAGIC.length; i++) {\n if (magic[i] !== MAGIC[i]) throw new DX402Error('not a DX402 sealed blob');\n }\n\n const version = take(1, 'version')[0];\n let count: number;\n if (version === FORMAT_V1) count = 1;\n else if (version === FORMAT_V2) count = take(1, 'recipient count')[0];\n else throw new DX402Error(`unsupported sealed-blob version ${version}`);\n\n // An envelope nobody can open is not evidence.\n if (count === 0) throw new DX402Error('DX402 sealed blob has no recipients');\n\n const recipients: Recipient[] = [];\n for (let i = 0; i < count; i++) {\n let role: RecipientRole = 'payer';\n if (version === FORMAT_V2) {\n const b = take(1, 'role')[0];\n if (b >= ROLE_NAMES.length) throw new DX402Error(`unknown role ${b}`);\n role = ROLE_NAMES[b];\n }\n\n const algByte = take(1, 'algorithm')[0];\n if (algByte !== 1 && algByte !== 2) {\n throw new DX402Error(`unknown key algorithm ${algByte}`);\n }\n const ephLen = take(1, 'ephemeral key length')[0];\n const ephemeral = take(ephLen, 'ephemeral key');\n const cekNonce = take(NONCE_LEN, 'cek nonce');\n const lenBytes = take(2, 'wrapped key length');\n const wrappedCek = take((lenBytes[0] << 8) | lenBytes[1], 'wrapped cek');\n\n recipients.push({\n role,\n alg: algByte === 1 ? 'secp256k1' : 'x25519',\n ephemeral,\n cekNonce,\n wrappedCek,\n });\n }\n\n const bodyNonce = take(NONCE_LEN, 'body nonce');\n return { recipients, bodyNonce, ciphertext: raw.subarray(pos) };\n}\n\nfunction sharedSecret(sealed: Recipient, privateKey: Uint8Array): Uint8Array {\n if (sealed.alg === 'secp256k1') {\n // Compressed output is 33 bytes: a 0x02/0x03 tag plus the x-coordinate.\n // Only the x-coordinate is the ECDH result, matching what the Rust side\n // feeds into HKDF. Including the tag byte would derive a different key and\n // fail with no useful diagnostic.\n const full = secp256k1.getSharedSecret(privateKey, sealed.ephemeral, true);\n return full.subarray(1);\n }\n\n // ed25519 seed -> X25519 scalar: SHA-512 the seed, take the low half.\n // @noble/curves clamps internally.\n const scalar = sha512(privateKey).subarray(0, 32);\n const shared = x25519.getSharedSecret(scalar, sealed.ephemeral);\n\n // RFC 7748 section 6.1: an all-zero result means a small-order public key was\n // supplied, which would make the wrapping key reproducible by whoever\n // supplied it.\n if (shared.every((b) => b === 0)) {\n throw new DX402Error('degenerate ECDH result (small-order public key)');\n }\n return shared;\n}\n\n/**\n * Decrypt a sealed envelope with whichever recipient slot belongs to `privateKey`.\n *\n * Tries every slot: a holder does not necessarily know which one is theirs, and\n * in a multi-recipient envelope the payer is not always first. A slot that does\n * not open is skipped, not reported — \"that one was not for me\" is not an error.\n */\nexport function unseal(\n sealed: SealedEnvelope,\n privateKey: Uint8Array,\n aad: Uint8Array,\n): Uint8Array {\n for (const recipient of sealed.recipients) {\n let shared: Uint8Array;\n try {\n shared = sharedSecret(recipient, privateKey);\n } catch (err) {\n if (err instanceof DX402Error) throw err;\n continue;\n }\n\n const wrapKey = hkdf(sha256, shared, aad, HKDF_INFO, 32);\n let cek: Uint8Array;\n try {\n cek = gcm(wrapKey, recipient.cekNonce, aad).decrypt(recipient.wrappedCek);\n } catch {\n continue; // not our slot\n }\n if (cek.length !== CEK_LEN) {\n throw new DX402Error(`unwrapped CEK is ${cek.length} bytes, expected ${CEK_LEN}`);\n }\n return gcm(cek, sealed.bodyNonce, aad).decrypt(sealed.ciphertext);\n }\n\n throw new DX402Error(\n 'no recipient slot opened -- wrong key, or the blob belongs to another payment',\n );\n}\n\n/**\n * Fetch, decrypt and verify the body behind `evidence`.\n *\n * `privateKey` is the raw key of the wallet that paid: 32 bytes for both an EVM\n * secp256k1 key and an ed25519 seed. Hex accepted with or without `0x`.\n *\n * In `direct` mode this needs no permission from anyone — the ciphertext was\n * sealed to the public key of the wallet that paid, so retrieval is arithmetic\n * rather than an access-control decision that could be refused or misconfigured.\n *\n * The `contentHash` check is **not optional**: it is what catches a seller that\n * anchored something other than what it served.\n */\nexport async function recoverEvidence(\n evidence: AnchoredEvidence,\n privateKey: Uint8Array | string,\n options: { fetch?: typeof fetch } = {},\n): Promise<Uint8Array> {\n const key = typeof privateKey === 'string' ? hexToBytes(privateKey) : privateKey;\n if (key.length !== 32) {\n throw new DX402Error(`private key must be 32 bytes, got ${key.length}`);\n }\n\n const doFetch = options.fetch ?? fetch;\n const url = dereferencePointer(evidence.pointer);\n const res = await doFetch(url);\n if (!res.ok) {\n throw new DX402Error(`could not fetch sealed evidence: HTTP ${res.status}`);\n }\n const blob = new Uint8Array(await res.arrayBuffer());\n\n const sealed = parseSealed(blob);\n const aad = new TextEncoder().encode(evidence.paymentId);\n\n let plaintext: Uint8Array;\n try {\n plaintext = unseal(sealed, key, aad);\n } catch (err) {\n if (err instanceof DX402Error) throw err;\n throw new DX402Error(\n 'decryption failed -- wrong key, or the blob belongs to another payment',\n );\n }\n\n const actual = contentHash(plaintext);\n if (actual.toLowerCase() !== evidence.contentHash.toLowerCase()) {\n throw new ContentHashMismatch(evidence.contentHash, actual);\n }\n\n return plaintext;\n}\n\n// ============================================================================\n// Seller side -- sealing\n// ============================================================================\n//\n// The half above recovers evidence. This half PRODUCES it, and it belongs to\n// whoever holds the plaintext: the resource server, right after settlement.\n//\n// The facilitator is deliberately not involved. It only ever sees /verify and\n// /settle, never a response body, so sealing cannot happen there.\n\nimport { edwardsToMontgomeryPub } from '@noble/curves/ed25519';\nimport { randomBytes } from '@noble/hashes/utils';\n\n/**\n * Map an ed25519 public key to its X25519 form.\n *\n * On ed25519 chains (Solana, NEAR, Stellar, Algorand) the address **is** the\n * public key, so this is all that stands between an address and an encryption\n * target — no signature, no lookup.\n */\nexport function ed25519ToX25519(pubkey: Uint8Array): Uint8Array {\n if (pubkey.length !== 32) {\n throw new DX402Error(`ed25519 public key must be 32 bytes, got ${pubkey.length}`);\n }\n return edwardsToMontgomeryPub(pubkey);\n}\n\n/**\n * Recover an EVM payer's secp256k1 public key from their payment signature.\n *\n * `digest` is the EIP-712 digest the payer actually signed. Getting it wrong\n * does not throw: it recovers a *different, perfectly valid* key, and the body\n * would be sealed to a stranger while every log line said success. The token's\n * EIP-712 domain name varies per chain and even flips between a chain's mainnet\n * and testnet, so derive it from the same table the facilitator uses.\n *\n * Returns the SEC1-compressed key (33 bytes).\n */\nexport function payerKeyFromEvmSignature(\n signature: Uint8Array | string,\n digest: Uint8Array,\n): Uint8Array {\n const sig = typeof signature === 'string' ? hexToBytes(signature) : signature;\n if (sig.length !== 65) {\n throw new DX402Error(`signature must be 65 bytes, got ${sig.length}`);\n }\n\n let v = sig[65 - 1];\n if (v === 27 || v === 28) v -= 27;\n else if (v >= 35) v = (v - 35) % 2;\n if (v !== 0 && v !== 1) throw new DX402Error(`invalid recovery id ${sig[64]}`);\n\n const parsed = secp256k1.Signature.fromCompact(sig.subarray(0, 64)).addRecoveryBit(v);\n return parsed.recoverPublicKey(digest).toRawBytes(true);\n}\n\n/**\n * Seal `body` so that only the holder of the payer's private key can read it.\n *\n * `payerKey` is a 33-byte SEC1-compressed secp256k1 key (EVM, XRPL) or a 32-byte\n * X25519 key from {@link ed25519ToX25519}.\n *\n * `paymentIdValue` is bound in as AEAD associated data, which is what stops a\n * ciphertext from being replayed as the evidence for a different payment.\n * Derive it with {@link paymentId} on both sides — deriving it differently makes\n * decryption fail with no obvious cause.\n *\n * Returns the bytes to upload. Nothing here touches the network.\n */\nexport function sealEvidence(\n body: Uint8Array,\n payerKey: Uint8Array,\n paymentIdValue: string,\n): Uint8Array {\n const aad = new TextEncoder().encode(paymentIdValue);\n const cek = randomBytes(32);\n const bodyNonce = randomBytes(NONCE_LEN);\n const cekNonce = randomBytes(NONCE_LEN);\n\n const ciphertext = gcm(cek, bodyNonce, aad).encrypt(body);\n\n let algByte: number;\n let ephemeral: Uint8Array;\n let shared: Uint8Array;\n\n if (payerKey.length === 33) {\n algByte = 1;\n const ephPriv = secp256k1.utils.randomPrivateKey();\n ephemeral = secp256k1.getPublicKey(ephPriv, true);\n // Only the x-coordinate is the ECDH result; the leading tag byte is not\n // part of it. Including it would derive a different key and fail with no\n // useful diagnostic.\n shared = secp256k1.getSharedSecret(ephPriv, payerKey, true).subarray(1);\n } else if (payerKey.length === 32) {\n algByte = 2;\n const ephPriv = randomBytes(32);\n ephemeral = x25519.getPublicKey(ephPriv);\n shared = x25519.getSharedSecret(ephPriv, payerKey);\n\n // RFC 7748 section 6.1: a small-order payer key would drive the shared\n // secret to a constant that whoever supplied it could reproduce.\n if (shared.every((b) => b === 0)) {\n throw new DX402Error('degenerate ECDH result (small-order public key)');\n }\n } else {\n throw new DX402Error(\n `payer key must be 33 bytes (secp256k1) or 32 (X25519), got ${payerKey.length}`,\n );\n }\n\n const wrapKey = hkdf(sha256, shared, aad, HKDF_INFO, 32);\n const wrappedCek = gcm(wrapKey, cekNonce, aad).encrypt(cek);\n\n const out = new Uint8Array(\n MAGIC.length + 3 + ephemeral.length + NONCE_LEN + 2 + wrappedCek.length +\n NONCE_LEN + ciphertext.length,\n );\n let pos = 0;\n out.set(MAGIC, pos); pos += MAGIC.length;\n out[pos++] = FORMAT_V1;\n out[pos++] = algByte;\n out[pos++] = ephemeral.length;\n out.set(ephemeral, pos); pos += ephemeral.length;\n out.set(cekNonce, pos); pos += NONCE_LEN;\n out[pos++] = (wrappedCek.length >> 8) & 0xff;\n out[pos++] = wrappedCek.length & 0xff;\n out.set(wrappedCek, pos); pos += wrappedCek.length;\n out.set(bodyNonce, pos); pos += NONCE_LEN;\n out.set(ciphertext, pos);\n return out;\n}\n\n// ============================================================================\n// Anchor authorization -- proving the anchor is yours\n// ============================================================================\n//\n// An anchor carrying a valid payee signature is `verified` and final. One\n// without is provisional: it still blocks a duplicate, but a verified anchor\n// for the same payment supersedes it.\n//\n// That asymmetry exists because the paymentId claim is permanent. Without it,\n// whoever anchored first owned the evidence of a payment forever and the real\n// seller was locked out.\n\nconst ANCHOR_DOMAIN_NAME = 'DX402 Anchor';\nconst ANCHOR_DOMAIN_VERSION = '1';\nconst ANCHOR_TYPE =\n 'Dx402AnchorAuthorization(bytes32 paymentId,bytes32 contentHash,string pointer,address payee)';\nconst EIP712_DOMAIN_TYPE = 'EIP712Domain(string name,string version,uint256 chainId)';\n\n/** The zero address, for the ed25519 form of the digest. */\nexport const ZERO_ADDRESS = '0x' + '00'.repeat(20);\n\nfunction concatBytes(...parts: Uint8Array[]): Uint8Array {\n const total = parts.reduce((n, p) => n + p.length, 0);\n const out = new Uint8Array(total);\n let pos = 0;\n for (const p of parts) {\n out.set(p, pos);\n pos += p.length;\n }\n return out;\n}\n\nfunction uint256(n: number | bigint): Uint8Array {\n const out = new Uint8Array(32);\n let v = BigInt(n);\n for (let i = 31; i >= 0 && v > 0n; i--) {\n out[i] = Number(v & 0xffn);\n v >>= 8n;\n }\n return out;\n}\n\n/**\n * The 32-byte digest a seller signs to prove an anchor is theirs.\n *\n * One canonical message across every curve. `payee` is the EVM address for a\n * secp256k1 payee and the **zero address** for an ed25519 one — an ed25519\n * address does not fit the `address` field, and the binding is already\n * established by which key verifies the signature.\n *\n * `pointer` is whatever you send in the anchor, or the **empty string** when you\n * send `sealed` and the facilitator issues the pointer itself: you cannot sign a\n * value you have not seen.\n *\n * Getting this wrong throws nothing — it produces a signature that simply never\n * verifies, and the anchor stays provisional with no clue why. The tests pin it\n * against digests emitted by the facilitator's own Rust implementation.\n */\nexport function anchorDigest(\n paymentId: string,\n contentHash: string,\n pointer: string,\n payee: string,\n chainId: number,\n): Uint8Array {\n const b32 = (value: string, field: string): Uint8Array => {\n const raw = hexToBytes(value);\n if (raw.length !== 32) throw new DX402Error(`${field} must be 32 bytes, got ${raw.length}`);\n return raw;\n };\n\n const addr = hexToBytes(payee);\n if (addr.length !== 20) {\n throw new DX402Error(`payee must be a 20-byte address, got ${addr.length}`);\n }\n\n const enc = new TextEncoder();\n const domainSeparator = keccak_256(\n concatBytes(\n keccak_256(enc.encode(EIP712_DOMAIN_TYPE)),\n keccak_256(enc.encode(ANCHOR_DOMAIN_NAME)),\n keccak_256(enc.encode(ANCHOR_DOMAIN_VERSION)),\n uint256(chainId),\n ),\n );\n\n const structHash = keccak_256(\n concatBytes(\n keccak_256(enc.encode(ANCHOR_TYPE)),\n b32(paymentId, 'paymentId'),\n b32(contentHash, 'contentHash'),\n keccak_256(enc.encode(pointer)),\n new Uint8Array(12),\n addr,\n ),\n );\n\n return keccak_256(concatBytes(new Uint8Array([0x19, 0x01]), domainSeparator, structHash));\n}\n\n/**\n * Sign an anchor authorization with a Solana / Stellar ed25519 key.\n *\n * A Solana payee cannot produce an EIP-712 signature at all — its address is an\n * ed25519 key — so requiring one would leave that chain unable to prove\n * authorship even once the on-chain gate is enforced. This closes it today, with\n * no RPC.\n */\nexport function signAnchorEd25519(\n privateKey: Uint8Array,\n paymentId: string,\n contentHash: string,\n pointer = '',\n): string {\n if (privateKey.length !== 32) {\n throw new DX402Error(`ed25519 seed must be 32 bytes, got ${privateKey.length}`);\n }\n const digest = anchorDigest(paymentId, contentHash, pointer, ZERO_ADDRESS, 0);\n return '0x' + bytesToHex(ed25519.sign(digest, privateKey));\n}\n\n/**\n * Sign an anchor authorization with an EVM secp256k1 key.\n *\n * `payee` must be the address of `privateKey` — the facilitator recovers the\n * signer and compares, so declaring somebody else's address simply leaves the\n * anchor provisional.\n */\nexport function signAnchorEvm(\n privateKey: Uint8Array,\n paymentId: string,\n contentHash: string,\n pointer: string,\n payee: string,\n chainId: number,\n): string {\n const digest = anchorDigest(paymentId, contentHash, pointer, payee, chainId);\n const sig = secp256k1.sign(digest, privateKey);\n return '0x' + bytesToHex(sig.toCompactRawBytes()) + (sig.recovery === 1 ? '01' : '00');\n}\n\n/**\n * Derive the encryption target from a Solana (or Fogo) address.\n *\n * On ed25519 chains the address **is** the public key, so this needs no\n * signature and no lookup. Rejects anything that does not decode to exactly 32\n * bytes: a short decode silently padded up to 32 produces a small-order point,\n * which fails a layer later with a message that points nowhere near the cause.\n */\nexport function payerKeyFromSolanaAddress(address: string): Uint8Array {\n if (!address || !address.trim()) throw new DX402Error('empty Solana address');\n\n const alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';\n let num = 0n;\n for (const ch of address) {\n const idx = alphabet.indexOf(ch);\n if (idx < 0) throw new DX402Error(`invalid base58 character '${ch}' in address`);\n num = num * 58n + BigInt(idx);\n }\n\n let hex = num.toString(16);\n if (hex.length % 2) hex = '0' + hex;\n const body = hexToBytes(hex);\n const leading = address.length - address.replace(/^1+/, '').length;\n\n const decoded = new Uint8Array(leading + body.length);\n decoded.set(body, leading);\n if (decoded.length !== 32) {\n throw new DX402Error(`Solana address decodes to ${decoded.length} bytes, expected 32`);\n }\n return ed25519ToX25519(decoded);\n}\n\n/**\n * Seal `body` so every listed recipient can read it, and nobody else.\n *\n * The body is encrypted **once**; only the content key is wrapped per recipient,\n * so adding the seller costs about sixty bytes rather than a second copy of the\n * payload. That is what makes it practical for a seller to keep a readable copy\n * of what it delivered — and answer a false \"that is not what you sent\" —\n * instead of paying to anchor evidence it cannot open.\n *\n * A single payer recipient is emitted as format **v1, byte-for-byte**, so\n * nothing already anchored becomes unreadable and readers still on v1 keep\n * working.\n */\nexport function sealEvidenceTo(\n body: Uint8Array,\n recipients: Array<{ role: RecipientRole; key: Uint8Array }>,\n paymentIdValue: string,\n): Uint8Array {\n if (recipients.length === 0) {\n throw new DX402Error('an envelope with no recipients could never be opened');\n }\n\n const aad = new TextEncoder().encode(paymentIdValue);\n const cek = randomBytes(CEK_LEN);\n const bodyNonce = randomBytes(NONCE_LEN);\n const ciphertext = gcm(cek, bodyNonce, aad).encrypt(body);\n\n const wrapped = recipients.map(({ role, key }) => {\n let algByte: number;\n let ephemeral: Uint8Array;\n let shared: Uint8Array;\n\n if (key.length === 33) {\n algByte = 1;\n const priv = secp256k1.utils.randomPrivateKey();\n ephemeral = secp256k1.getPublicKey(priv, true);\n shared = secp256k1.getSharedSecret(priv, key, true).subarray(1);\n } else if (key.length === 32) {\n algByte = 2;\n const priv = randomBytes(32);\n ephemeral = x25519.getPublicKey(priv);\n shared = x25519.getSharedSecret(priv, key);\n if (shared.every((b) => b === 0)) {\n throw new DX402Error('degenerate ECDH result (small-order public key)');\n }\n } else {\n throw new DX402Error(\n `public key must be 33 bytes (secp256k1) or 32 (X25519), got ${key.length}`,\n );\n }\n\n const wrapKey = hkdf(sha256, shared, aad, HKDF_INFO, 32);\n const cekNonce = randomBytes(NONCE_LEN);\n return {\n role,\n algByte,\n ephemeral,\n cekNonce,\n wrappedCek: gcm(wrapKey, cekNonce, aad).encrypt(cek),\n };\n });\n\n const singlePayer = wrapped.length === 1 && wrapped[0].role === 'payer';\n const parts: Uint8Array[] = [MAGIC, new Uint8Array([singlePayer ? FORMAT_V1 : FORMAT_V2])];\n if (!singlePayer) parts.push(new Uint8Array([wrapped.length]));\n\n for (const r of wrapped) {\n if (!singlePayer) parts.push(new Uint8Array([ROLE_NAMES.indexOf(r.role)]));\n parts.push(new Uint8Array([r.algByte, r.ephemeral.length]));\n parts.push(r.ephemeral, r.cekNonce);\n parts.push(new Uint8Array([(r.wrappedCek.length >> 8) & 0xff, r.wrappedCek.length & 0xff]));\n parts.push(r.wrappedCek);\n }\n\n parts.push(bodyNonce, ciphertext);\n return concatBytes(...parts);\n}\n\n// ============================================================================\n// The whole seller side, in one call\n// ============================================================================\n\nexport interface AnchorOptions {\n paymentId: string;\n network: string;\n txHash: string;\n payer: string;\n payee: string;\n /** The buyer's encryption key, from `payerKeyFromSolanaAddress` or similar. */\n payerKey: Uint8Array;\n /**\n * Your **public** key, to keep a readable copy so you can answer a false\n * \"that is not what you sent\".\n *\n * It does not have to be your payment key, and should not be — a custodial\n * payment wallet works fine here, because this key only ever decrypts.\n */\n sellerEncryptionKey?: Uint8Array;\n /**\n * The settlement proof, in the facilitator's `ProofOfPayment` shape\n * (`transactionHash`, `blockNumber`, `network`, `payer`, `payee`, `amount`,\n * `token`, `timestamp`, `paymentHash`).\n *\n * **The only thing that reaches `verified: true`.** Without it the\n * facilitator has checked no chain, so it records the anchor as provisional\n * and answers `notVerifiedReason: \"dx402_proof_missing\"`: the signature is\n * accepted (`signed: true`) but authorship is not certified, and a claim that\n * proves more may supersede it.\n */\n proofOfPayment?: Record<string, unknown>;\n /**\n * Which backend to anchor to (`\"s3\"`, `\"ipfs-private\"`, `\"ipfs-public\"`).\n * Omit to take the facilitator's default.\n *\n * Ask {@link availableBackends} what a given facilitator offers rather than\n * assuming — it depends on the deployment, and you may be pointed at one that\n * is not ours. **`ipfs-public` is irreversible**: the bytes become permanently\n * resolvable by anyone, and nobody, the facilitator included, can take them\n * down.\n */\n storage?: string;\n /**\n * `(digest) => \"0x...\"`. A callable rather than a private key is what lets a\n * custodian sign: it receives the digest and returns the signature without the\n * seed ever leaving it.\n *\n * Without one the anchor is **provisional** — it holds the slot, but a signed\n * anchor for the same payment supersedes it.\n */\n sign?: (digest: Uint8Array) => string | Promise<string>;\n /**\n * `(sealedBytes) => pointer`. Bring your own storage.\n *\n * Without this the sealed envelope travels **inside** the anchor request and\n * the facilitator hosts it, which is the easy path and stays the default. With\n * it, the SDK still seals exactly as before -- the buyer has to be able to\n * decrypt, so the sealing is not optional -- then hands you the ciphertext,\n * you write it wherever you keep durable bytes, and you return the pointer\n * that addresses it. The request then carries only that pointer, so the\n * ciphertext never travels through the anchor call and\n * {@link ANCHOR_MAX_REQUEST_BYTES} does not apply to your body.\n *\n * A callable rather than a precomputed pointer, for the same reason\n * {@link AnchorOptions.sign} is one: the SDK must seal first, and only then\n * can anything be uploaded. Handing in a pointer computed in advance would\n * mean addressing bytes that do not exist yet.\n *\n * The returned pointer is what the buyer will dereference, so it must be\n * readable by them -- see {@link dereferencePointer} for the schemes the SDK\n * resolves out of the box. It is also bound into the seller signature.\n *\n * **It is never allowed to break the sale.** If it throws or returns\n * something unusable, the anchor degrades to a skip and the payment is\n * untouched.\n */\n upload?: (sealed: Uint8Array) => string | Promise<string>;\n /**\n * Which storage family the pointer belongs to: `s3`, `ipfs` or `arweave`.\n *\n * Defaults to `s3`, and in {@link AnchorOptions.upload} mode it is inferred\n * from the pointer's scheme when you do not say. Distinct from `storage`,\n * which names one of the FACILITATOR's own offers and is meaningless when you\n * supply the bytes yourself.\n */\n backend?: 's3' | 'ipfs' | 'arweave';\n retention?: string;\n facilitator?: string;\n fetch?: typeof fetch;\n}\n\n/**\n * Seal a response body, anchor it, and return the `X-Durable-Evidence` value.\n *\n * **It never throws.** Every failure resolves to a skip notice, because evidence\n * is an addition to the payment path and must never be a gate in front of it —\n * an unreachable facilitator has to cost the receipt, never the sale.\n *\n * # Two ways to store the ciphertext\n *\n * **Hosted (default).** The sealed envelope travels inside the anchor request\n * and the facilitator stores it and issues the pointer. Nothing to set up. The\n * request carries the ciphertext, so it is bounded by\n * {@link ANCHOR_MAX_REQUEST_BYTES}.\n *\n * **Your own storage.** Pass {@link AnchorOptions.upload}. The SDK seals\n * identically, hands you the ciphertext, and sends the pointer you return in\n * place of the blob — so the ciphertext never travels through the anchor call\n * and that request bound does not apply to your body. The facilitator has\n * accepted a caller-supplied pointer since v0.1; this is the SDK catching up.\n *\n * ```ts\n * await anchorEvidence(body, {\n * ...common,\n * // called with the SEALED bytes, never the plaintext\n * upload: async (sealed) => {\n * await myBucket.put(key, sealed);\n * return `s3+https://cdn.example.com/${key}`;\n * },\n * });\n * ```\n *\n * Either way the seller keeps custody of nothing it did not already have: the\n * facilitator cannot read a `direct`-mode envelope in the hosted case either.\n * What changes is durability and cost, which become yours.\n */\n\n/** `0x` + 40 hex. An ed25519 payee (Solana, Stellar) never matches. */\nfunction isEvmAddress(value: string): boolean {\n return /^0x[0-9a-fA-F]{40}$/.test((value ?? '').trim());\n}\n\n/** The chain id behind a network name or CAIP-2 id, or undefined if unknown. */\nfunction chainIdFor(network: string): number | undefined {\n // `eip155:8453` carries the chain id literally. Read it rather than going\n // through the chain table, which has no entry for EVM TESTNETS -- so without\n // this a seller on one cannot produce a verifiable anchor signature at all.\n const raw = network ?? '';\n if (raw.toLowerCase().startsWith('eip155:')) {\n const tail = raw.slice('eip155:'.length);\n if (/^\\d+$/.test(tail)) return Number(tail);\n }\n const name = raw.includes(':') ? (raw.split(':')[1] ?? '') : raw;\n const byId = Number(name);\n if (Number.isFinite(byId) && byId > 0) return getChainById(byId)?.chainId;\n return getChainByName(name)?.chainId;\n}\n\n/**\n * The digest the facilitator will ACTUALLY verify, chosen by the payee's curve.\n *\n * The gate dispatches on the payee and checks **one** form -- never both. A\n * secp256k1 payee is verified against the digest built with its REAL address and\n * chain id; an ed25519 payee, whose address does not fit the `address` field, is\n * verified against the zero address and chain id 0.\n *\n * Signing the wrong form throws nothing. It yields a signature that never\n * verifies, the anchor silently stays **provisional**, and a provisional anchor\n * can be superseded by anyone -- the very hijack a signed anchor exists to stop.\n * Reproduced against production by KarmaKadabra, 2026-08-19: with everything else\n * identical, the ed25519 form was refused (`409 dx402_already_anchored`) and the\n * EVM form superseded the provisional.\n *\n * `pointer` defaults to the empty string, which is right when you send `sealed`:\n * the facilitator issues the pointer and you cannot sign what you have not seen.\n * When you supply your OWN pointer it must be passed here **verbatim** -- the\n * facilitator verifies against `req.pointer` when one is present and against\n * `\"\"` when it is absent (x402-rs `dx402/service.rs`, `signed_pointer`), so\n * signing the empty string alongside a pointer produces a signature that never\n * verifies and an anchor that silently stays provisional.\n */\nexport function sellerDigestFor(\n paymentId: string,\n contentHash: string,\n payee: string,\n network: string,\n pointer = '',\n): Uint8Array | undefined {\n if (isEvmAddress(payee)) {\n const chainId = chainIdFor(network);\n // An EVM payee whose chain id we cannot resolve. Falling through to the\n // ed25519 form is how this shipped in 0.53.0: it throws nothing and yields\n // a signature that never verifies, so the anchor stays provisional forever\n // with no error anywhere. Refuse instead -- unsigned is honest and\n // recoverable, signed-but-worthless only looks done.\n if (!chainId) return undefined;\n return anchorDigest(paymentId, contentHash, pointer, payee, chainId);\n }\n return anchorDigest(paymentId, contentHash, pointer, ZERO_ADDRESS, 0);\n}\n\n\n/**\n * Largest `POST /dx402/anchor` request the facilitator accepts, mirroring its\n * `MAX_REQUEST_BODY_BYTES` (default 64 KiB, an anti-OOM bound on every route).\n */\nexport const ANCHOR_MAX_REQUEST_BYTES = 64 * 1024;\n\n\n/** base64 without spreading the array into arguments -- a large blob would\n * otherwise overflow the call stack and surface as a generic failure. */\nfunction toBase64(bytes: Uint8Array): string {\n let out = '';\n const CHUNK = 0x8000;\n for (let i = 0; i < bytes.length; i += CHUNK) {\n out += String.fromCharCode(...bytes.subarray(i, i + CHUNK));\n }\n return btoa(out);\n}\n\n/**\n * Which storage family a pointer names, for the anchor's `backend` field.\n *\n * The facilitator records this; it does not fetch through it. `s3` is the\n * fallback because `s3+https://` is the SDK's own scheme for \"an ordinary HTTPS\n * URL\", which is what most sellers' own sinks are.\n */\nfunction backendForPointer(pointer: string): 's3' | 'ipfs' | 'arweave' {\n if (pointer.startsWith('ipfs://')) return 'ipfs';\n if (pointer.startsWith('ar://')) return 'arweave';\n return 's3';\n}\n\nexport async function anchorEvidence(\n body: Uint8Array,\n opts: AnchorOptions,\n): Promise<Record<string, unknown>> {\n try {\n const recipients: Array<{ role: RecipientRole; key: Uint8Array }> = [\n { role: 'payer', key: opts.payerKey },\n ];\n if (opts.sellerEncryptionKey) {\n recipients.push({ role: 'seller', key: opts.sellerEncryptionKey });\n }\n const blob = sealEvidenceTo(body, recipients, opts.paymentId);\n const hash = contentHash(body);\n\n // Bring-your-own-storage. The sealing above is identical either way -- the\n // buyer must be able to decrypt -- so all that changes is who holds the\n // ciphertext and, therefore, whether it has to travel in this request.\n //\n // The upload is fenced off completely: a seller's bucket going down is not\n // a reason for a paid response to fail, so anything thrown here becomes a\n // skip, exactly like an unreachable facilitator.\n let pointer: string | undefined;\n if (opts.upload) {\n try {\n pointer = await opts.upload(blob);\n } catch {\n return { v: 1, skipped: 'anchor_failed', stage: 'upload' };\n }\n if (typeof pointer !== 'string' || pointer.trim() === '') {\n // An empty pointer addresses nothing, and the facilitator would record\n // an anchor that dereferences to a 404 forever. Worse than no anchor.\n return { v: 1, skipped: 'anchor_failed', stage: 'upload' };\n }\n pointer = pointer.trim();\n }\n\n const payload: Record<string, unknown> = {\n paymentId: opts.paymentId,\n network: opts.network,\n txHash: opts.txHash,\n payer: opts.payer,\n payee: opts.payee,\n // Exactly one of these. The facilitator dispatches on their presence:\n // `sealed` -> it hosts and derives the pointer; `pointer` alone -> it uses\n // yours; neither -> error (x402-rs `dx402/service.rs`).\n ...(pointer !== undefined ? { pointer } : { sealed: toBase64(blob) }),\n // Declared, not measured. Since x402-rs 2.3.0 the facilitator records\n // the store that ACTUALLY took the bytes and returns that, so a response\n // may name a different backend than the request did -- `ipfs` where you\n // said `s3`, because a deployment whose primary is Pinata wrote there.\n // That is the facilitator correcting the record, not a mismatch to\n // assert on.\n backend: opts.backend ?? (pointer !== undefined ? backendForPointer(pointer) : 's3'),\n contentHash: hash,\n keyAlg: opts.payerKey.length === 32 ? 'ECIES-X25519' : 'ECIES-secp256k1',\n mode: 'direct',\n retention: opts.retention ?? '90d',\n };\n\n let unsigned: string | undefined;\n if (opts.proofOfPayment) {\n payload.proofOfPayment = opts.proofOfPayment;\n }\n\n if (opts.storage) {\n payload.storage = opts.storage;\n }\n\n if (opts.sign) {\n // The signature covers the pointer the facilitator will verify against:\n // ours when we supply one, the empty string when the facilitator issues\n // it. Signing the wrong one throws nothing and leaves the anchor\n // provisional -- which is the state anyone can supersede.\n const digest = sellerDigestFor(opts.paymentId, hash, opts.payee, opts.network, pointer ?? '');\n if (digest === undefined) {\n unsigned = 'unknown_chain_id';\n } else {\n payload.sellerSignature = await opts.sign(digest);\n }\n }\n\n // Measure the SEALED, serialised request -- not the plaintext. The\n // envelope adds a nonce, the wrapped CEK and its JSON, and the ciphertext\n // travels base64 (4/3). Checking the plaintext lets through bodies the\n // facilitator then rejects, arriving as a generic failure long after the\n // sealing work was done. Measured by KarmaKadabra, 2026-08-19: 47 KB of\n // plaintext fits, 48 KB does not.\n //\n // In `upload` mode the ciphertext is not in the request at all, so this\n // bound says nothing about the body and is not applied. The request is a\n // pointer and some metadata; only a pathological pointer could approach it.\n const wire = JSON.stringify(payload);\n if (pointer === undefined && new TextEncoder().encode(wire).length > ANCHOR_MAX_REQUEST_BYTES) {\n return { v: 1, skipped: 'too_large' };\n }\n\n const base = (opts.facilitator ?? 'https://facilitator.ultravioletadao.xyz').replace(\n /\\/+$/,\n '',\n );\n const doFetch = opts.fetch ?? fetch;\n const res = await doFetch(`${base}/dx402/anchor`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: wire,\n });\n // Carry the facilitator's own diagnosis out rather than flattening every\n // failure to `anchor_failed`. A rejected signature answers 422\n // `dx402_signature_not_verified`; erasing it here would reproduce, one\n // layer down, the exact problem that code exists to solve.\n if (!res.ok) {\n let error: unknown;\n try {\n error = ((await res.json()) as { error?: unknown }).error;\n } catch {\n /* a non-JSON error body is still a failure */\n }\n return { v: 1, skipped: 'anchor_failed', status: res.status, error };\n }\n const out = (await res.json()) as Record<string, unknown>;\n if (unsigned) out.unsigned = unsigned;\n return out;\n } catch {\n return { v: 1, skipped: 'anchor_failed' };\n }\n}\n\n/** One storage option a facilitator offers, from `GET /dx402/stats`. */\nexport interface BackendOffer {\n id: string;\n retention: string;\n /**\n * Whether the bytes can actually be removed when retention expires.\n *\n * `false` means the `retentionUntil` in the signed receipt **cannot be\n * honoured**: on public IPFS, unpinning removes the facilitator's copy, not\n * the network's.\n */\n revocable: boolean;\n /** Whether anyone resolves the bytes without going through the facilitator. */\n public: boolean;\n enabled: boolean;\n disabledReason?: string;\n}\n\n/**\n * Ask a facilitator which storage backends it actually offers.\n *\n * Ask instead of assuming. What exists depends on the deployment — one without\n * a Pinata credential offers only `s3` — and an integrator may be pointed at a\n * facilitator that is not ours. A hardcoded list in your code is a promise\n * somebody else has to keep.\n *\n * Resolves to `[]` rather than rejecting when the facilitator is unreachable or\n * does not run DX402 — same discipline as {@link anchorEvidence}.\n */\nexport async function availableBackends(\n facilitator = 'https://facilitator.ultravioletadao.xyz',\n opts: { fetch?: typeof fetch } = {},\n): Promise<BackendOffer[]> {\n try {\n const doFetch = opts.fetch ?? fetch;\n const res = await doFetch(`${facilitator.replace(/\\/+$/, '')}/dx402/stats`);\n if (!res.ok) return [];\n const body = (await res.json()) as { backends?: BackendOffer[] };\n return body.backends ?? [];\n } catch {\n return [];\n }\n}\n\n/** Encode an anchor result for the `X-Durable-Evidence` response header. */\nexport function evidenceHeader(evidence: unknown): string {\n // Encode to UTF-8 first. `btoa` takes a *binary* string: any code point above\n // U+00FF throws InvalidCharacterError, and one between U+0080 and U+00FF is\n // silently emitted as a single latin-1 byte, so the far side decodes mojibake.\n // Either is reachable from ordinary evidence -- a `notVerifiedReason` or a\n // pointer with a non-ASCII character is enough.\n const bytes = new TextEncoder().encode(JSON.stringify(evidence));\n return toBase64(bytes).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n","/**\n * uvd-x402-sdk - Type Definitions\n *\n * Core TypeScript interfaces for the x402 payment SDK.\n * These types define the contract between the SDK and consuming applications.\n */\n\n// ============================================================================\n// CHAIN CONFIGURATION TYPES\n// ============================================================================\n\n/**\n * Network type categorization\n * - 'evm': Ethereum Virtual Machine compatible chains (use EIP-712)\n * - 'svm': Solana Virtual Machine chains (Solana, Fogo) (use SPL tokens)\n * - 'stellar': Stellar network (use Soroban)\n * - 'near': NEAR Protocol (use NEP-366)\n * - 'algorand': Algorand network (use ASA transfers with atomic transactions)\n * - 'sui': Sui blockchain (use sponsored transactions)\n * - 'xrpl': XRP Ledger (use pre-signed Payment transaction blobs)\n *\n * @deprecated 'solana' type is deprecated, use 'svm' instead\n */\nexport type NetworkType = 'evm' | 'svm' | 'solana' | 'stellar' | 'near' | 'algorand' | 'sui' | 'xrpl';\n\n/**\n * Supported x402 payment schemes\n * - 'exact': Standard one-shot payment (default)\n * - 'escrow': Escrow-based payment with verify/settle/refund\n * - 'commerce': Commerce alias for escrow (marketplace integrations)\n */\nexport type X402Scheme = 'exact' | 'escrow' | 'commerce';\n\n/**\n * Supported stablecoin token types\n * - usdc: USD Coin (Circle) - 6 decimals\n * - eurc: Euro Coin (Circle) - 6 decimals\n * - ausd: Agora USD (Agora Finance) - 6 decimals\n * - pyusd: PayPal USD (PayPal/Paxos) - 6 decimals\n * - usdt: Tether USD (USDT0 omnichain via LayerZero) - 6 decimals\n * - usdg: Global Dollar (Paxos) - 6 decimals; settlement stablecoin on Robinhood Chain\n */\nexport type TokenType = 'usdc' | 'eurc' | 'ausd' | 'pyusd' | 'usdt' | 'usdg';\n\n/**\n * Token configuration for EIP-712 signing and transfers\n */\nexport interface TokenConfig {\n /** Contract/mint address */\n address: string;\n /** Token decimals (6 for all supported stablecoins) */\n decimals: number;\n /** Token name for EIP-712 domain (e.g., \"USD Coin\" or \"USDC\") */\n name: string;\n /** Token version for EIP-712 domain */\n version: string;\n}\n\n/**\n * USDC token configuration for a specific chain\n * @deprecated Use TokenConfig instead. This is kept for backward compatibility.\n */\nexport interface USDCConfig {\n /** Contract/mint address */\n address: string;\n /** Token decimals (6 for most chains, 7 for Stellar) */\n decimals: number;\n /** Token name for EIP-712 domain (e.g., \"USD Coin\" or \"USDC\") */\n name: string;\n /** Token version for EIP-712 domain */\n version: string;\n}\n\n/**\n * Native currency configuration\n */\nexport interface NativeCurrency {\n name: string;\n symbol: string;\n decimals: number;\n}\n\n/**\n * Complete chain configuration\n */\nexport interface ChainConfig {\n /** Numeric chain ID (0 for non-EVM chains) */\n chainId: number;\n /** Hex-encoded chain ID for wallet_switchEthereumChain */\n chainIdHex: string;\n /** Internal chain identifier (e.g., 'base', 'solana') */\n name: string;\n /** Human-readable display name */\n displayName: string;\n /** Network type for routing */\n networkType: NetworkType;\n /** Primary RPC endpoint URL */\n rpcUrl: string;\n /** Block explorer base URL */\n explorerUrl: string;\n /** Native currency info */\n nativeCurrency: NativeCurrency;\n /** USDC token configuration */\n usdc: USDCConfig;\n /**\n * Multi-token configurations (EVM chains only)\n * Maps token type to its configuration for this chain.\n * Not all tokens are available on all chains.\n */\n tokens?: Partial<Record<TokenType, TokenConfig>>;\n /** x402 facilitator configuration */\n x402: {\n facilitatorUrl: string;\n enabled: boolean;\n };\n}\n\n// ============================================================================\n// WALLET TYPES\n// ============================================================================\n\n/**\n * Current wallet connection state\n */\nexport interface WalletState {\n /** Whether a wallet is currently connected */\n connected: boolean;\n /** Connected wallet address (null if not connected) */\n address: string | null;\n /** Current chain ID (null for non-EVM or disconnected) */\n chainId: number | null;\n /** Current network name */\n network: string | null;\n /** Network type of connected wallet */\n networkType: NetworkType | null;\n /** USDC balance on current chain (null if unknown) */\n balance: string | null;\n}\n\n/**\n * Wallet adapter interface for different wallet types\n */\nexport interface WalletAdapter {\n /** Unique identifier for this wallet type */\n readonly id: string;\n /** Display name */\n readonly name: string;\n /** Network type this adapter supports */\n readonly networkType: NetworkType;\n\n /** Check if this wallet is available/installed */\n isAvailable(): boolean;\n\n /** Connect to the wallet */\n connect(chainName?: string): Promise<string>;\n\n /** Disconnect from the wallet */\n disconnect(): Promise<void>;\n\n /** Switch to a different chain (EVM only) */\n switchChain?(chainName: string): Promise<void>;\n\n /**\n * Sign a payment payload\n * For EVM chains, supports multi-token via paymentInfo.tokenType\n */\n signPayment(paymentInfo: PaymentInfo, chainConfig: ChainConfig): Promise<string>;\n\n /**\n * Check token balance (defaults to USDC for backward compatibility)\n * EVM providers may accept optional tokenType parameter\n */\n getBalance(chainConfig: ChainConfig, tokenType?: TokenType): Promise<string>;\n\n /** Get current address */\n getAddress(): string | null;\n\n /** Get current chain ID (EVM only) */\n getChainId?(): number | null;\n}\n\n/**\n * EIP-712 domain for typed data signing\n */\nexport interface EIP712Domain {\n name: string;\n version: string;\n chainId: number;\n verifyingContract: string;\n}\n\n/**\n * EIP-712 type definitions\n */\nexport interface EIP712Types {\n [typeName: string]: Array<{ name: string; type: string }>;\n}\n\n// ============================================================================\n// PAYMENT TYPES\n// ============================================================================\n\n/**\n * Payment information returned by backend on 402 response\n */\nexport interface PaymentInfo {\n /** Default recipient address */\n recipient: string;\n /** Network-specific recipient addresses */\n recipients?: {\n evm?: string;\n solana?: string;\n near?: string;\n stellar?: string;\n algorand?: string;\n sui?: string;\n xrpl?: string;\n };\n /** Facilitator address (for Solana fee payer) */\n facilitator?: string;\n /** Amount in USD (e.g., \"10.00\") */\n amount: string;\n /** Token symbol (usually \"USDC\") */\n token?: string;\n /**\n * Token type for multi-token support\n * Defaults to 'usdc' if not specified for backward compatibility\n */\n tokenType?: TokenType;\n /** Network hint from backend */\n network?: string;\n /** Supported chain IDs */\n supportedChains?: number[];\n}\n\n/**\n * Simple payment request from application\n */\nexport interface PaymentRequest {\n /** Amount in USDC (e.g., \"10.00\") */\n amount: string;\n /** Override recipient address (optional) */\n recipient?: string;\n /** Application-specific metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * x402 payment header names\n *\n * - 'X-PAYMENT': v1 header name (default, most compatible)\n * - 'PAYMENT-SIGNATURE': v2 header name (newer standard)\n *\n * Both headers use the same base64-encoded JSON payload format.\n * The facilitator accepts both headers.\n */\nexport type X402HeaderName = 'X-PAYMENT' | 'PAYMENT-SIGNATURE';\n\n/**\n * Payment headers object containing both v1 and v2 header formats\n */\nexport interface PaymentHeaders {\n /** v1 header: X-PAYMENT */\n 'X-PAYMENT': string;\n /** v2 header: PAYMENT-SIGNATURE (same value, different header name) */\n 'PAYMENT-SIGNATURE': string;\n}\n\n/**\n * Result of a payment operation\n */\nexport interface PaymentResult {\n /** Whether payment was successful */\n success: boolean;\n /** Base64-encoded X-PAYMENT header value */\n paymentHeader: string;\n /**\n * Payment headers object for easy use with fetch/axios\n *\n * @example\n * ```ts\n * // Use v1 header\n * fetch(url, { headers: { 'X-PAYMENT': result.headers['X-PAYMENT'] } });\n *\n * // Use v2 header\n * fetch(url, { headers: { 'PAYMENT-SIGNATURE': result.headers['PAYMENT-SIGNATURE'] } });\n * ```\n */\n headers: PaymentHeaders;\n /** Transaction hash (if available) */\n transactionHash?: string;\n /** Network where payment was made */\n network: string;\n /** Payer address */\n payer?: string;\n /** Error message (if success is false) */\n error?: string;\n}\n\n// ============================================================================\n// PAYLOAD TYPES (Internal)\n// ============================================================================\n\n/**\n * EVM payment payload (ERC-3009 TransferWithAuthorization)\n */\nexport interface EVMPaymentPayload {\n from: string;\n to: string;\n value: string;\n validAfter: number;\n validBefore: number;\n nonce: string;\n v: number;\n r: string;\n s: string;\n chainId: number;\n token: string;\n}\n\n/**\n * Token info for non-USDC stablecoins (e.g., Token2022 like AUSD)\n * Required in payload for facilitator to verify Token2022 transfers correctly.\n */\nexport interface TokenInfo {\n /** Token mint address */\n address: string;\n /** Token symbol (e.g., 'AUSD') */\n symbol: string;\n /** Token decimals (e.g., 6) */\n decimals: number;\n}\n\n/**\n * Solana payment payload (partially-signed transaction)\n */\nexport interface SolanaPaymentPayload {\n /** Base64-encoded serialized transaction */\n transaction: string;\n /**\n * Token info for non-USDC tokens (e.g., Token2022 like AUSD)\n * CRITICAL: Must be included for Token2022 tokens for facilitator verification\n */\n token?: TokenInfo;\n}\n\n/**\n * Stellar payment payload (Soroban authorization)\n */\nexport interface StellarPaymentPayload {\n /** Sender G... public key */\n from: string;\n /** Recipient G... public key */\n to: string;\n /** Amount in stroops (7 decimals) */\n amount: string;\n /** USDC SAC contract address */\n tokenContract: string;\n /** Base64 XDR-encoded SorobanAuthorizationEntry */\n authorizationEntryXdr: string;\n /** Random 64-bit nonce */\n nonce: number;\n /** Ledger when authorization expires */\n signatureExpirationLedger: number;\n}\n\n/**\n * NEAR payment payload (NEP-366 meta-transaction)\n */\nexport interface NEARPaymentPayload {\n /** Base64 Borsh-encoded SignedDelegateAction */\n signedDelegateAction: string;\n network: 'near';\n}\n\n/**\n * Algorand payment payload (atomic transaction group)\n *\n * Follows the GoPlausible x402-avm spec for atomic groups:\n * - Transaction 0: Fee payment (UNSIGNED) - facilitator -> facilitator, covers all fees\n * - Transaction 1: ASA transfer (SIGNED) - client -> merchant\n *\n * The facilitator signs transaction 0 and submits the complete atomic group.\n */\nexport interface AlgorandPaymentPayload {\n /** Index of the payment transaction in the group (always 1) */\n paymentIndex: number;\n /**\n * Array of base64-encoded msgpack transactions forming the atomic group:\n * - [0]: Unsigned fee transaction (facilitator signs)\n * - [1]: Signed ASA transfer (client signed)\n */\n paymentGroup: string[];\n}\n\n/**\n * Sui payment payload (sponsored transaction)\n *\n * Uses Sui sponsored transactions where:\n * - User creates a programmable transaction for USDC transfer\n * - User signs the transaction\n * - Facilitator sponsors (pays gas in SUI) and submits\n *\n * User pays: ZERO SUI\n */\nexport interface SuiPaymentPayload {\n /** Base64-encoded BCS serialized TransactionData */\n transactionBytes: string;\n /** Base64-encoded user signature */\n senderSignature: string;\n /** Sender address (0x + 64 hex chars) */\n from: string;\n /** Recipient address (0x + 64 hex chars) */\n to: string;\n /** Amount in base units (string to handle large numbers) */\n amount: string;\n /** Coin object ID used for the transfer (REQUIRED by facilitator) */\n coinObjectId: string;\n}\n\n/**\n * XRPL payment payload (pre-signed Payment transaction blob)\n *\n * Uses the t54 \"pre-signed Payment blob\" scheme on the XRP Ledger:\n * - The client builds and FULLY signs a Payment transaction off-chain,\n * paying its own XRP network fee.\n * - The single `signedTxBlob` field (hex-encoded fully-signed XRPL tx blob)\n * is sent to the facilitator, which decodes it to re-derive payer/amount/\n * destination and submits it.\n *\n * All payment-level fields (destination, amount, InvoiceID, SourceTag, etc.)\n * come from PaymentRequirements/extra, NOT from this payload.\n *\n * XRP is the native asset (6 decimals / drops). There is no token contract.\n *\n * The JSON field name is EXACTLY `signedTxBlob` (camelCase).\n */\nexport interface XRPLPaymentPayload {\n /** Hex-encoded fully-signed XRPL Payment transaction blob (tx_blob) */\n signedTxBlob: string;\n}\n\n/**\n * Union type for all payment payloads\n */\nexport type PaymentPayload =\n | EVMPaymentPayload\n | SolanaPaymentPayload\n | StellarPaymentPayload\n | NEARPaymentPayload\n | AlgorandPaymentPayload\n | SuiPaymentPayload\n | XRPLPaymentPayload;\n\n// ============================================================================\n// X402 HEADER TYPES (v1 and v2)\n// ============================================================================\n\n/**\n * x402 protocol version\n */\nexport type X402Version = 1 | 2;\n\n/**\n * CAIP-2 chain identifiers for x402 v2\n * @see https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2.md\n */\nexport const CAIP2_IDENTIFIERS: Record<string, string> = {\n // EVM chains\n base: 'eip155:8453',\n ethereum: 'eip155:1',\n polygon: 'eip155:137',\n arbitrum: 'eip155:42161',\n optimism: 'eip155:10',\n avalanche: 'eip155:43114',\n celo: 'eip155:42220',\n hyperevm: 'eip155:999',\n unichain: 'eip155:130',\n monad: 'eip155:143',\n bsc: 'eip155:56',\n scroll: 'eip155:534352',\n 'skale-base': 'eip155:1187947933',\n 'skale-base-sepolia': 'eip155:324705682',\n robinhood: 'eip155:4663',\n 'robinhood-testnet': 'eip155:46630',\n // SVM chains\n solana: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n fogo: 'svm:fogo',\n // Stellar\n stellar: 'stellar:pubnet',\n // NEAR\n near: 'near:mainnet',\n // Algorand\n algorand: 'algorand:mainnet',\n 'algorand-testnet': 'algorand:testnet',\n // Sui\n sui: 'sui:mainnet',\n 'sui-testnet': 'sui:testnet',\n // XRPL (XRP Ledger has no CAIP-2 form - the v1 string IS the network id)\n 'xrpl-mainnet': 'xrpl-mainnet',\n 'xrpl-testnet': 'xrpl-testnet',\n};\n\n/**\n * Reverse mapping from CAIP-2 to chain name\n */\nexport const CAIP2_TO_CHAIN: Record<string, string> = Object.fromEntries(\n Object.entries(CAIP2_IDENTIFIERS).map(([k, v]) => [v, k])\n);\n\n/**\n * x402 v1 header structure (network as string)\n */\nexport interface X402HeaderV1 {\n x402Version: 1;\n scheme: X402Scheme;\n network: string;\n payload: X402PayloadData;\n}\n\n/**\n * x402 v2 payment option\n */\nexport interface X402PaymentOption {\n network: string; // CAIP-2 format\n asset: string;\n amount: string;\n facilitator?: string;\n}\n\n/**\n * x402 v2 header structure (CAIP-2 network, accepts array)\n */\nexport interface X402HeaderV2 {\n x402Version: 2;\n scheme: X402Scheme;\n network: string; // CAIP-2 format\n payload: X402PayloadData;\n accepts?: X402PaymentOption[];\n}\n\n/**\n * Union type for both v1 and v2 headers\n */\nexport type X402Header = X402HeaderV1 | X402HeaderV2;\n\n/**\n * EVM-specific payload in x402 header\n */\nexport interface X402EVMPayload {\n signature: string;\n authorization: {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n };\n /**\n * Which token was actually paid.\n *\n * Only present when the payment is created with `includeTokenMetadata`. The\n * signature alone does not say which stablecoin it authorizes — a server that\n * accepts several tokens on the same chain cannot rebuild the payment\n * requirements without this. Omitted by default so existing v1 wire formats\n * stay byte-identical.\n */\n token?: PaymentTokenMetadata;\n}\n\n/**\n * Token identification carried inside an x402 payload.\n *\n * Mirrors what a resource server needs to build `paymentRequirements`: the\n * `asset` it must charge and the `extra` EIP-712 domain the facilitator needs\n * to recover the signature.\n */\nexport interface PaymentTokenMetadata {\n /** Token contract address (the `asset` of the payment requirements) */\n address: string;\n /** Uppercase token symbol, e.g. `USDC`, `EURC`, `USDT` */\n symbol: string;\n /** Token decimals — the amount in the authorization is in these units */\n decimals: number;\n /** EIP-712 domain of the token contract (the `extra` of the requirements) */\n eip712: {\n name: string;\n version: string;\n };\n}\n\n/**\n * Solana-specific payload in x402 header\n */\nexport interface X402SolanaPayload {\n transaction: string;\n}\n\n/**\n * Settlement account payload for Crossmint and other custodial wallets\n * that can only sendTransaction (not signTransaction).\n *\n * In this mode, the client already submitted the transaction on-chain.\n * The facilitator verifies the on-chain tx, then sweeps USDC from the\n * settlement account to the payTo address.\n *\n * Used by: Crossmint smart wallets via @faremeter/wallet-crossmint\n */\nexport interface X402SettlementAccountPayload {\n /** On-chain transaction signature (already submitted) */\n transactionSignature: string;\n /** Base58 secret key for sweeping settlement account (optional) */\n settleSecretKey?: string;\n /** Address to receive rent from closed settlement ATA (optional) */\n settlementRentDestination?: string;\n}\n\n/**\n * Stellar-specific payload in x402 header\n */\nexport interface X402StellarPayload {\n from: string;\n to: string;\n amount: string;\n tokenContract: string;\n authorizationEntryXdr: string;\n nonce: number;\n signatureExpirationLedger: number;\n}\n\n/**\n * NEAR-specific payload in x402 header\n */\nexport interface X402NEARPayload {\n signedDelegateAction: string;\n}\n\n/**\n * Algorand-specific payload in x402 header (atomic group format)\n */\nexport interface X402AlgorandPayload {\n /** Index of the payment transaction in the group (always 1) */\n paymentIndex: number;\n /** Array of base64-encoded msgpack transactions */\n paymentGroup: string[];\n}\n\n/**\n * Sui-specific payload in x402 header (sponsored transaction)\n */\nexport interface X402SuiPayload {\n /** BCS-encoded transaction bytes (base64) */\n transactionBytes: string;\n /** User's signature on the transaction (base64) */\n senderSignature: string;\n /** Sender's Sui address (0x...) */\n from: string;\n /** Recipient's Sui address (0x...) */\n to: string;\n /** Amount in smallest unit (string to avoid precision issues) */\n amount: string;\n /** Coin object ID used for the transfer (REQUIRED by facilitator) */\n coinObjectId: string;\n}\n\n/**\n * XRPL-specific payload in x402 header (t54 pre-signed Payment blob)\n *\n * The JSON field name is EXACTLY `signedTxBlob` (camelCase). The facilitator\n * decodes the blob to re-derive payer/amount/destination; no other fields are\n * carried in the payload.\n */\nexport interface X402XRPLPayload {\n /** Hex-encoded fully-signed XRPL Payment transaction blob (tx_blob) */\n signedTxBlob: string;\n}\n\n/**\n * Union of all x402 payload types\n */\nexport type X402PayloadData =\n | X402EVMPayload\n | X402SolanaPayload\n | X402SettlementAccountPayload\n | X402StellarPayload\n | X402NEARPayload\n | X402AlgorandPayload\n | X402SuiPayload\n | X402XRPLPayload;\n\n// ============================================================================\n// CLIENT CONFIGURATION\n// ============================================================================\n\n/**\n * Multi-payment configuration for supporting multiple networks\n */\nexport interface MultiPaymentConfig {\n /** Networks to support (e.g., ['base', 'solana', 'stellar', 'near']) */\n networks: string[];\n /** Default network if user hasn't selected one */\n defaultNetwork?: string;\n /** Whether to auto-detect user's preferred network based on wallet */\n autoDetect?: boolean;\n}\n\n/**\n * SDK client configuration options\n */\nexport interface X402ClientConfig {\n /** Facilitator URL (default: https://facilitator.ultravioletadao.xyz) */\n facilitatorUrl?: string;\n /** Default chain to connect to */\n defaultChain?: string;\n /** Auto-connect on initialization */\n autoConnect?: boolean;\n /** Enable debug logging */\n debug?: boolean;\n /** Custom chain configurations (override defaults) */\n customChains?: Record<string, Partial<ChainConfig>>;\n /** Wallet preference order */\n walletPreference?: string[];\n /** Custom RPC URLs (override defaults) */\n rpcOverrides?: Record<string, string>;\n /**\n * x402 protocol version to use\n * - 1: Classic format with network as string (e.g., \"base\")\n * - 2: CAIP-2 format with accepts array (e.g., \"eip155:8453\")\n * - 'auto': Auto-detect from 402 response (default)\n */\n x402Version?: X402Version | 'auto';\n /** Multi-payment configuration for supporting multiple networks */\n multiPayment?: MultiPaymentConfig;\n /**\n * Include a `token` block in the payload naming the asset, its decimals and\n * its EIP-712 domain.\n *\n * Needed when the resource accepts more than one stablecoin on the same\n * chain: the signature alone does not say which one was paid, so the server\n * cannot rebuild `paymentRequirements`. Off by default — the emitted header\n * stays byte-identical to previous versions.\n */\n includeTokenMetadata?: boolean;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: Required<Pick<X402ClientConfig, 'facilitatorUrl' | 'defaultChain' | 'autoConnect' | 'debug' | 'x402Version'>> = {\n facilitatorUrl: 'https://facilitator.ultravioletadao.xyz',\n defaultChain: 'base',\n autoConnect: false,\n debug: false,\n x402Version: 'auto',\n};\n\n// ============================================================================\n// BALANCE TYPES\n// ============================================================================\n\n/**\n * Balance information for a single network\n */\nexport interface NetworkBalance {\n /** Chain name */\n chainName: string;\n /** Human-readable display name */\n displayName: string;\n /** Formatted balance (e.g., \"15.50\") or null if loading/error */\n balance: string | null;\n /** Whether balance is currently being fetched */\n isLoading: boolean;\n /** Error message if fetch failed */\n error: string | null;\n}\n\n// ============================================================================\n// EVENT TYPES\n// ============================================================================\n\n/**\n * Events emitted by the SDK client\n */\nexport type X402Event =\n | 'connect'\n | 'disconnect'\n | 'chainChanged'\n | 'accountChanged'\n | 'balanceChanged'\n | 'paymentStarted'\n | 'paymentSigned'\n | 'paymentCompleted'\n | 'paymentFailed';\n\n/**\n * Event data types\n */\nexport interface X402EventData {\n connect: WalletState;\n disconnect: void;\n chainChanged: { chainId: number; chainName: string };\n accountChanged: { address: string };\n balanceChanged: { balance: string };\n paymentStarted: { amount: string; network: string };\n paymentSigned: { paymentHeader: string };\n paymentCompleted: PaymentResult;\n paymentFailed: { error: string; code: X402ErrorCode };\n}\n\n/**\n * Event handler type\n */\nexport type X402EventHandler<E extends X402Event> = (data: X402EventData[E]) => void;\n\n// ============================================================================\n// ERROR TYPES\n// ============================================================================\n\n/**\n * Error codes for categorizing errors\n */\nexport type X402ErrorCode =\n | 'WALLET_NOT_FOUND'\n | 'WALLET_NOT_CONNECTED'\n | 'WALLET_NOT_SUPPORTED'\n | 'WALLET_CONNECTION_FAILED'\n | 'WALLET_CONNECTION_REJECTED'\n | 'WALLET_CONNECTION_TIMEOUT'\n | 'CHAIN_NOT_SUPPORTED'\n | 'CHAIN_SWITCH_REJECTED'\n | 'INSUFFICIENT_BALANCE'\n | 'SIGNATURE_REJECTED'\n | 'PAYMENT_FAILED'\n | 'PAYMENT_TIMEOUT'\n | 'NETWORK_ERROR'\n | 'INVALID_CONFIG'\n | 'INVALID_AMOUNT'\n | 'INVALID_RECIPIENT'\n | 'UNKNOWN_ERROR';\n\n/**\n * SDK-specific error class\n */\nexport class X402Error extends Error {\n public readonly code: X402ErrorCode;\n public readonly details?: unknown;\n\n constructor(message: string, code: X402ErrorCode, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, X402Error);\n }\n }\n}\n","/**\n * uvd-x402-sdk - UTF-8 safe base64\n *\n * `btoa()` only accepts code points 0-255. Any character above that throws\n * `InvalidCharacterError`, and the X-PAYMENT payload is not guaranteed to be\n * ASCII: the EIP-712 domain name of USDT on Optimism and Arbitrum is literally\n * `USD₮0` (U+20AE). A header carrying that name crashes a plain `btoa()`.\n *\n * So the JSON is UTF-8 encoded to bytes first, and only then base64'd. Decoding\n * reverses it. For ASCII-only input the output is byte-identical to\n * `btoa(json)`, which is why swapping this in cannot change any existing header.\n *\n * `TextEncoder`/`TextDecoder` are available in every browser the SDK targets and\n * in Node 11+; `btoa`/`atob` are used for the byte<->base64 step because they\n * exist in both environments without pulling in `Buffer`.\n */\n\n/**\n * Encode a string as base64, handling non-ASCII characters correctly.\n *\n * @param value - Any UTF-8 string\n * @returns Base64-encoded value\n */\nexport function encodeBase64Utf8(value: string): string {\n const bytes = new TextEncoder().encode(value);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Decode a base64 string produced by {@link encodeBase64Utf8}.\n *\n * @param encoded - Base64-encoded value\n * @returns The original UTF-8 string\n */\nexport function decodeBase64Utf8(encoded: string): string {\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n\n/**\n * JSON-serialize a value and encode it as UTF-8 safe base64.\n *\n * This is the encoder for every X-PAYMENT header the SDK emits.\n *\n * @param value - Value to serialize\n * @returns Base64-encoded JSON\n */\nexport function encodeBase64Json(value: unknown): string {\n return encodeBase64Utf8(JSON.stringify(value));\n}\n","/**\n * uvd-x402-sdk - x402 Protocol Utilities\n *\n * Utilities for working with x402 v1 and v2 protocols.\n * Handles version detection, payload encoding, and CAIP-2 conversions.\n */\n\nimport type {\n X402Header,\n X402HeaderV1,\n X402HeaderV2,\n X402PayloadData,\n X402PaymentOption,\n X402Version,\n ChainConfig,\n} from '../types';\nimport { CAIP2_IDENTIFIERS, CAIP2_TO_CHAIN } from '../types';\nimport { getChainByName } from '../chains';\nimport { decodeBase64Utf8, encodeBase64Json } from './base64';\n\n/**\n * Detect x402 version from a response header or body\n *\n * @param data - The 402 response data (parsed JSON or header value)\n * @returns The detected version (1 or 2)\n */\nexport function detectX402Version(data: unknown): X402Version {\n if (typeof data === 'string') {\n // A `PAYMENT-REQUIRED` header value is base64 JSON, and the doc above\n // invites one. Returning 1 without decoding misread every v2 challenge as\n // v1 — silently, as a plausible value rather than an error, and the two\n // wire forms are structurally incompatible.\n //\n // This is not hypothetical: measured 2026-08-20, 36 of 36 live Bazaar\n // resources answering 402 carry the challenge in the header, and several\n // put a free content preview in the body, so the header is the only place\n // the version signal exists.\n const trimmed = data.trim();\n if (!trimmed) return 1;\n for (const decode of [\n () => JSON.parse(decodeBase64Utf8(trimmed)),\n () => JSON.parse(trimmed),\n ]) {\n try {\n const parsed = decode();\n if (typeof parsed === 'object' && parsed !== null) {\n return detectX402Version(parsed);\n }\n } catch {\n // not this encoding; try the next\n }\n }\n return 1; // undecodable: fall back to v1, as before\n }\n\n if (typeof data !== 'object' || data === null) {\n return 1; // Default to v1\n }\n\n const obj = data as Record<string, unknown>;\n\n // Check explicit version field\n if (obj.x402Version === 2) {\n return 2;\n }\n\n // Check for v2 indicators\n if (obj.accepts && Array.isArray(obj.accepts)) {\n return 2;\n }\n\n // `paymentRequirements` is the v1 spelling, so its presence points at v1 --\n // but only when there is no v2 signal, which the checks above already ruled\n // out. Recognised so the value is not treated as an unknown shape.\n if (Array.isArray(obj.paymentRequirements)) {\n return 1;\n }\n\n // Check if network is in CAIP-2 format\n if (typeof obj.network === 'string') {\n if (obj.network.includes(':')) {\n return 2;\n }\n }\n\n return 1;\n}\n\n/**\n * Convert chain name to CAIP-2 identifier\n *\n * @param chainName - Chain name (e.g., 'base', 'solana')\n * @returns CAIP-2 identifier (e.g., 'eip155:8453', 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')\n */\nexport function chainToCAIP2(chainName: string): string {\n const caip2 = CAIP2_IDENTIFIERS[chainName.toLowerCase()];\n if (caip2) {\n return caip2;\n }\n\n // Try to construct from chain config\n const chain = getChainByName(chainName);\n if (chain) {\n if (chain.networkType === 'evm') {\n return `eip155:${chain.chainId}`;\n }\n // For non-EVM, return the name as-is with network prefix\n return `${chain.networkType}:${chainName}`;\n }\n\n return chainName; // Return as-is if unknown\n}\n\n/**\n * Convert CAIP-2 identifier to chain name\n *\n * @param caip2 - CAIP-2 identifier\n * @returns Chain name or null if unknown\n */\nexport function caip2ToChain(caip2: string): string | null {\n // Check direct mapping\n if (CAIP2_TO_CHAIN[caip2]) {\n return CAIP2_TO_CHAIN[caip2];\n }\n\n // Try to extract from EIP-155 format\n const match = caip2.match(/^eip155:(\\d+)$/);\n if (match) {\n const chainId = parseInt(match[1], 10);\n // Find chain by ID\n for (const [name, _config] of Object.entries(CAIP2_IDENTIFIERS)) {\n const chain = getChainByName(name);\n if (chain?.chainId === chainId) {\n return name;\n }\n }\n }\n\n // Try to extract from network:name format\n const parts = caip2.split(':');\n if (parts.length === 2) {\n const networkName = parts[1];\n if (getChainByName(networkName)) {\n return networkName;\n }\n }\n\n return null;\n}\n\n/**\n * Parse network identifier from either v1 or v2 format\n *\n * @param network - Network identifier (v1 string or v2 CAIP-2)\n * @returns Normalized chain name\n */\nexport function parseNetworkIdentifier(network: string): string {\n // If it contains a colon, it's likely CAIP-2\n if (network.includes(':')) {\n return caip2ToChain(network) || network;\n }\n return network.toLowerCase();\n}\n\n/**\n * Encode x402 payload as base64 header value\n *\n * @param header - The x402 header object\n * @returns Base64-encoded string\n */\nexport function encodeX402Header(header: X402Header): string {\n return encodeBase64Json(header);\n}\n\n/**\n * Decode x402 header from base64 string\n *\n * @param encoded - Base64-encoded header value\n * @returns Parsed x402 header\n */\nexport function decodeX402Header(encoded: string): X402Header {\n const json = decodeBase64Utf8(encoded);\n return JSON.parse(json) as X402Header;\n}\n\n/**\n * Create x402 v1 header\n *\n * @param network - Chain name (e.g., 'base')\n * @param payload - Network-specific payload\n * @returns x402 v1 header object\n */\nexport function createX402V1Header(\n network: string,\n payload: X402PayloadData\n): X402HeaderV1 {\n return {\n x402Version: 1,\n scheme: 'exact',\n network,\n payload,\n };\n}\n\n/**\n * Create x402 v2 header\n *\n * @param network - CAIP-2 network identifier\n * @param payload - Network-specific payload\n * @param accepts - Optional array of payment options\n * @returns x402 v2 header object\n */\nexport function createX402V2Header(\n network: string,\n payload: X402PayloadData,\n accepts?: X402PaymentOption[]\n): X402HeaderV2 {\n const header: X402HeaderV2 = {\n x402Version: 2,\n scheme: 'exact',\n network: network.includes(':') ? network : chainToCAIP2(network),\n payload,\n };\n\n if (accepts && accepts.length > 0) {\n header.accepts = accepts;\n }\n\n return header;\n}\n\n/**\n * Create x402 header with automatic version selection\n *\n * @param chainConfig - Chain configuration\n * @param payload - Network-specific payload\n * @param version - Version to use (1, 2, or 'auto')\n * @returns x402 header object\n */\nexport function createX402Header(\n chainConfig: ChainConfig,\n payload: X402PayloadData,\n version: X402Version | 'auto' = 'auto'\n): X402Header {\n // Default to v1 for maximum compatibility\n const effectiveVersion = version === 'auto' ? 1 : version;\n\n if (effectiveVersion === 2) {\n return createX402V2Header(chainConfig.name, payload);\n }\n\n return createX402V1Header(chainConfig.name, payload);\n}\n\n/**\n * Generate payment options array for multi-network support\n *\n * @param chainConfigs - Array of chain configurations\n * @param amount - Amount in USDC (e.g., \"10.00\")\n * @param facilitator - Optional facilitator URL override\n * @returns Array of x402 v2 payment options\n */\nexport function generatePaymentOptions(\n chainConfigs: ChainConfig[],\n amount: string,\n facilitator?: string\n): X402PaymentOption[] {\n // Convert amount to atomic units for each chain\n return chainConfigs\n .filter(chain => chain.x402.enabled)\n .map(chain => {\n const atomicAmount = Math.floor(\n parseFloat(amount) * Math.pow(10, chain.usdc.decimals)\n ).toString();\n\n return {\n network: chainToCAIP2(chain.name),\n asset: chain.usdc.address,\n amount: atomicAmount,\n facilitator: facilitator || chain.x402.facilitatorUrl,\n };\n });\n}\n\n/**\n * Check if a network string is in CAIP-2 format\n *\n * @param network - Network identifier\n * @returns True if CAIP-2 format\n */\nexport function isCAIP2Format(network: string): boolean {\n return network.includes(':');\n}\n\n/**\n * Convert between x402 v1 and v2 header formats\n *\n * @param header - Source header\n * @param targetVersion - Target version\n * @returns Converted header\n */\nexport function convertX402Header(\n header: X402Header,\n targetVersion: X402Version\n): X402Header {\n if (header.x402Version === targetVersion) {\n return header;\n }\n\n if (targetVersion === 2) {\n // v1 -> v2\n return {\n x402Version: 2,\n scheme: 'exact',\n network: chainToCAIP2(header.network),\n payload: header.payload,\n };\n } else {\n // v2 -> v1\n const chainName = isCAIP2Format(header.network)\n ? caip2ToChain(header.network) || header.network\n : header.network;\n\n return {\n x402Version: 1,\n scheme: 'exact',\n network: chainName,\n payload: header.payload,\n };\n }\n}\n\n/**\n * Read a 402 payment challenge from wherever the seller put it.\n *\n * x402 allows BOTH transports and sellers pick freely:\n *\n * - base64 JSON in the `PAYMENT-REQUIRED` (or `X-PAYMENT-REQUIRED`) header\n * - JSON in the response body\n *\n * Measured against production on 2026-08-20: of 40 live Bazaar resources,\n * **36 of 36 that answered 402 carried the challenge in the header, and none in\n * the body**. Worse, sellers like Tenjin use the 402 body for a free preview of\n * the paid content — so the body is valid JSON that simply has no `accepts`, and\n * a body-only reader parses it happily and finds nothing.\n *\n * Reads the header first because that is where live sellers put it, and falls\n * back to the body so the sellers who use it keep working.\n *\n * Returns `null` when neither transport carries a challenge — a real \"no terms\n * here\", distinct from a challenge we failed to decode.\n */\nexport function paymentChallengeFrom(\n headers: { get(name: string): string | null } | Record<string, string>,\n body?: unknown,\n): Record<string, unknown> | null {\n const read = (name: string): string | null => {\n if (typeof (headers as { get?: unknown }).get === 'function') {\n return (headers as { get(n: string): string | null }).get(name);\n }\n const rec = headers as Record<string, string>;\n return rec[name] ?? rec[name.toLowerCase()] ?? rec[name.toUpperCase()] ?? null;\n };\n\n const raw = read('payment-required') ?? read('x-payment-required');\n if (raw) {\n const trimmed = raw.trim();\n for (const decode of [\n () => JSON.parse(decodeBase64Utf8(trimmed)),\n () => JSON.parse(trimmed),\n ]) {\n try {\n const parsed = decode();\n if (isChallenge(parsed)) return parsed as Record<string, unknown>;\n } catch {\n // not this encoding; try the next\n }\n }\n }\n\n const parsedBody = typeof body === 'string' ? tryJson(body) : body;\n return isChallenge(parsedBody) ? (parsedBody as Record<string, unknown>) : null;\n}\n\n/**\n * Whether a value actually looks like an x402 challenge.\n *\n * Deliberately stricter than \"is an object\": a 402 body carrying a free preview\n * is valid JSON with no payment terms in it, and treating that as a challenge is\n * how a body-only reader concludes it looked and found nothing wrong.\n */\nfunction isChallenge(v: unknown): boolean {\n if (typeof v !== 'object' || v === null) return false;\n const o = v as Record<string, unknown>;\n // `paymentRequirements` is the v1 spelling of `accepts`. Missing it made a\n // seller using it look like \"no terms here\" — the exact false negative this\n // function exists to prevent. Found in the Python SDK by KarmaKadabra's\n // buyer, which matched both keys in production, 2026-08-20.\n return (\n Array.isArray(o.accepts) ||\n Array.isArray(o.paymentRequirements) ||\n typeof o.payTo === 'string'\n );\n}\n\nfunction tryJson(s: string): unknown {\n try {\n return JSON.parse(s);\n } catch {\n return null;\n }\n}\n","/**\n * uvd-x402-sdk - Token metadata for payment payloads\n *\n * An EIP-3009 authorization is signed against a token contract, but the encoded\n * payload only carries the signature and the transfer fields. The token itself\n * is implicit — the server is expected to already know which asset it asked\n * for.\n *\n * That holds when a resource accepts exactly one token per chain. It breaks as\n * soon as it accepts several: a EURC payment and a USDC payment on Base produce\n * indistinguishable payloads, and the server cannot build the\n * `paymentRequirements` (`asset` + `extra`) the facilitator needs to settle.\n *\n * So the payment can opt into carrying the token with it.\n */\n\nimport { getTokenByAddress } from '../chains';\nimport type { PaymentTokenMetadata } from '../types';\n\n/**\n * Build the token metadata block for a payload, resolving the address against\n * the chain registry.\n *\n * @param chainName - Chain the payment was signed for\n * @param address - Token contract address from the signed payload\n * @returns Metadata block, or undefined if the address is not in the registry\n */\nexport function buildTokenMetadata(\n chainName: string,\n address: string\n): PaymentTokenMetadata | undefined {\n const match = getTokenByAddress(chainName, address);\n if (!match) return undefined;\n\n return {\n address: match.config.address,\n symbol: match.tokenType.toUpperCase(),\n decimals: match.config.decimals,\n eip712: {\n name: match.config.name,\n version: match.config.version,\n },\n };\n}\n","/**\n * uvd-x402-sdk - Validation and Payment Header Utilities\n *\n * Functions for validating payment parameters and creating\n * payment headers for HTTP requests.\n */\n\nimport type { X402HeaderName, PaymentHeaders } from '../types';\nimport { X402Error } from '../types';\n\n/**\n * Regular expression for validating Ethereum addresses\n */\nconst ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;\n\n/**\n * Regular expression for validating Solana addresses (base58, 32-44 chars)\n */\nconst SOLANA_ADDRESS_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\n/**\n * Regular expression for validating Stellar addresses (G... format)\n */\nconst STELLAR_ADDRESS_REGEX = /^G[A-Z2-7]{55}$/;\n\n/**\n * Regular expression for validating NEAR addresses\n */\nconst NEAR_ADDRESS_REGEX = /^[a-z0-9._-]+$/;\n\n/**\n * Regular expression for validating XRPL classic addresses (r... base58, Ripple alphabet)\n */\nconst XRPL_ADDRESS_REGEX = /^r[1-9A-HJ-NP-Za-km-z]{24,34}$/;\n\n/**\n * Validate that a recipient address is present and valid\n *\n * This function ensures that:\n * 1. The recipient is not null, undefined, or empty\n * 2. The recipient is not just whitespace\n * 3. For EVM, it's a valid checksummed or lowercase 0x address\n *\n * @param recipient - The recipient address to validate\n * @param networkType - Optional network type for format validation\n * @throws X402Error with code 'INVALID_RECIPIENT' if validation fails\n */\nexport function validateRecipient(\n recipient: string | undefined | null,\n networkType?: 'evm' | 'svm' | 'solana' | 'stellar' | 'near' | 'xrpl'\n): asserts recipient is string {\n // Check for null, undefined, or empty\n if (!recipient) {\n throw new X402Error(\n 'Recipient address is required. The payTo/recipient field cannot be empty. ' +\n 'Please provide a valid recipient address where payments should be sent.',\n 'INVALID_RECIPIENT'\n );\n }\n\n // Check for whitespace-only\n const trimmed = recipient.trim();\n if (trimmed === '') {\n throw new X402Error(\n 'Recipient address cannot be empty or whitespace. ' +\n 'Please provide a valid recipient address.',\n 'INVALID_RECIPIENT'\n );\n }\n\n // Network-specific validation\n if (networkType) {\n switch (networkType) {\n case 'evm':\n if (!ETH_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid EVM recipient address: \"${trimmed}\". ` +\n 'Expected a 40-character hexadecimal address starting with 0x.',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'svm':\n case 'solana':\n if (!SOLANA_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid Solana recipient address: \"${trimmed}\". ` +\n 'Expected a base58-encoded public key (32-44 characters).',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'stellar':\n if (!STELLAR_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid Stellar recipient address: \"${trimmed}\". ` +\n 'Expected a G-prefixed public key (56 characters).',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'near':\n if (!NEAR_ADDRESS_REGEX.test(trimmed) || trimmed.length > 64) {\n throw new X402Error(\n `Invalid NEAR recipient address: \"${trimmed}\". ` +\n 'Expected a valid NEAR account ID.',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n\n case 'xrpl':\n if (!XRPL_ADDRESS_REGEX.test(trimmed)) {\n throw new X402Error(\n `Invalid XRPL recipient address: \"${trimmed}\". ` +\n 'Expected a classic r-address (base58, Ripple alphabet).',\n 'INVALID_RECIPIENT'\n );\n }\n break;\n }\n }\n}\n\n/**\n * Validate payment amount\n *\n * Ensures the amount is a valid positive number string\n *\n * @param amount - The amount string to validate\n * @throws X402Error with code 'INVALID_AMOUNT' if validation fails\n */\nexport function validateAmount(amount: string | undefined | null): asserts amount is string {\n if (!amount) {\n throw new X402Error(\n 'Payment amount is required.',\n 'INVALID_AMOUNT'\n );\n }\n\n const trimmed = amount.trim();\n if (trimmed === '') {\n throw new X402Error(\n 'Payment amount cannot be empty.',\n 'INVALID_AMOUNT'\n );\n }\n\n // Parse as number\n const num = parseFloat(trimmed);\n if (isNaN(num)) {\n throw new X402Error(\n `Invalid payment amount: \"${trimmed}\". Expected a valid number.`,\n 'INVALID_AMOUNT'\n );\n }\n\n if (num <= 0) {\n throw new X402Error(\n `Payment amount must be positive. Got: ${trimmed}`,\n 'INVALID_AMOUNT'\n );\n }\n}\n\n// ============================================================================\n// PAYMENT HEADER UTILITIES\n// ============================================================================\n\n/**\n * Create payment headers object from a base64-encoded payload\n *\n * Returns an object with both X-PAYMENT and PAYMENT-SIGNATURE headers,\n * making it easy to use either header format.\n *\n * @param paymentHeader - Base64-encoded payment payload\n * @returns PaymentHeaders object with both header formats\n *\n * @example\n * ```ts\n * const headers = createPaymentHeaders(paymentHeader);\n *\n * // Use v1 header (most compatible)\n * fetch(url, { headers: { 'X-PAYMENT': headers['X-PAYMENT'] } });\n *\n * // Use v2 header\n * fetch(url, { headers: { 'PAYMENT-SIGNATURE': headers['PAYMENT-SIGNATURE'] } });\n * ```\n */\nexport function createPaymentHeaders(paymentHeader: string): PaymentHeaders {\n return {\n 'X-PAYMENT': paymentHeader,\n 'PAYMENT-SIGNATURE': paymentHeader,\n };\n}\n\n/**\n * Get a single payment header by name\n *\n * @param paymentHeader - Base64-encoded payment payload\n * @param headerName - Header name to use ('X-PAYMENT' or 'PAYMENT-SIGNATURE')\n * @returns Object with a single header entry\n *\n * @example\n * ```ts\n * // Use with fetch spread operator\n * fetch(url, {\n * headers: {\n * 'Content-Type': 'application/json',\n * ...getPaymentHeader(result.paymentHeader, 'X-PAYMENT'),\n * },\n * });\n * ```\n */\nexport function getPaymentHeader(\n paymentHeader: string,\n headerName: X402HeaderName = 'X-PAYMENT'\n): Record<X402HeaderName, string> {\n return { [headerName]: paymentHeader } as Record<X402HeaderName, string>;\n}\n\n/**\n * Default x402 payment header name\n *\n * Use 'X-PAYMENT' for maximum compatibility with all facilitators.\n * Use 'PAYMENT-SIGNATURE' for x402 v2 compliance.\n */\nexport const DEFAULT_PAYMENT_HEADER: X402HeaderName = 'X-PAYMENT';\n\n/**\n * All supported x402 payment header names\n */\nexport const PAYMENT_HEADER_NAMES: readonly X402HeaderName[] = [\n 'X-PAYMENT',\n 'PAYMENT-SIGNATURE',\n] as const;\n","/**\n * uvd-x402-sdk - Main Client\n *\n * The X402Client is the primary entry point for the SDK.\n * It manages wallet connections, chain switching, and payment creation.\n */\n\nimport { ethers } from 'ethers';\nimport type {\n ChainConfig,\n NetworkType,\n PaymentInfo,\n PaymentResult,\n WalletState,\n X402ClientConfig,\n X402Event,\n X402EventData,\n X402EventHandler,\n EVMPaymentPayload,\n TokenType,\n X402EVMPayload,\n} from '../types';\nimport { X402Error, DEFAULT_CONFIG } from '../types';\nimport {\n SUPPORTED_CHAINS,\n getChainByName,\n getChainById,\n getEnabledChains,\n getTokenConfig,\n} from '../chains';\nimport {\n validateRecipient,\n chainToCAIP2,\n encodeBase64Json,\n buildTokenMetadata,\n} from '../utils';\n\n/**\n * X402Client - Main SDK client for x402 payments\n *\n * @example\n * ```ts\n * import { X402Client } from 'uvd-x402-sdk';\n *\n * const client = new X402Client({ defaultChain: 'base' });\n *\n * // Connect wallet\n * await client.connect('base');\n *\n * // Create payment\n * const result = await client.createPayment({\n * recipient: '0x...',\n * amount: '10.00',\n * });\n *\n * // Use result.paymentHeader in your API request\n * ```\n */\nexport class X402Client {\n // Configuration\n private readonly config: Required<Pick<X402ClientConfig, 'facilitatorUrl' | 'defaultChain' | 'autoConnect' | 'debug'>> & X402ClientConfig;\n\n // Wallet state\n private provider: ethers.BrowserProvider | ethers.JsonRpcProvider | null = null;\n private signer: ethers.Signer | null = null;\n private connectedAddress: string | null = null;\n private currentChainId: number | null = null;\n private currentNetwork: NetworkType | null = null;\n private currentChainName: string | null = null;\n\n // Event emitter\n private eventHandlers: Map<X402Event, Set<X402EventHandler<X402Event>>> = new Map();\n\n constructor(config: X402ClientConfig = {}) {\n this.config = {\n ...DEFAULT_CONFIG,\n ...config,\n };\n\n // Apply custom RPC overrides\n if (config.rpcOverrides) {\n for (const [chainName, rpcUrl] of Object.entries(config.rpcOverrides)) {\n if (SUPPORTED_CHAINS[chainName]) {\n SUPPORTED_CHAINS[chainName].rpcUrl = rpcUrl;\n }\n }\n }\n\n // Apply custom chain configurations\n if (config.customChains) {\n for (const [chainName, chainConfig] of Object.entries(config.customChains)) {\n if (SUPPORTED_CHAINS[chainName]) {\n Object.assign(SUPPORTED_CHAINS[chainName], chainConfig);\n }\n }\n }\n\n this.log('X402Client initialized', { config: this.config });\n }\n\n // ============================================================================\n // PUBLIC API - Wallet Connection\n // ============================================================================\n\n /**\n * Connect to a wallet on the specified chain\n */\n async connect(chainName?: string): Promise<string> {\n const targetChain = chainName || this.config.defaultChain;\n const chain = getChainByName(targetChain);\n\n if (!chain) {\n throw new X402Error(`Unsupported chain: ${targetChain}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (!chain.x402.enabled) {\n throw new X402Error(`Chain ${targetChain} is not enabled for x402 payments`, 'CHAIN_NOT_SUPPORTED');\n }\n\n this.log(`Connecting wallet on ${chain.displayName}...`);\n\n // Route to appropriate connection method based on network type\n switch (chain.networkType) {\n case 'evm':\n return this.connectEVMWallet(chain);\n case 'solana':\n throw new X402Error(\n 'Solana support requires importing from \"uvd-x402-sdk/solana\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n case 'stellar':\n throw new X402Error(\n 'Stellar support requires importing from \"uvd-x402-sdk/stellar\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n case 'near':\n throw new X402Error(\n 'NEAR support requires importing from \"uvd-x402-sdk/near\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n case 'xrpl':\n throw new X402Error(\n 'XRPL support requires importing from \"uvd-x402-sdk/xrpl\"',\n 'CHAIN_NOT_SUPPORTED'\n );\n default:\n throw new X402Error(`Unknown network type for chain ${targetChain}`, 'CHAIN_NOT_SUPPORTED');\n }\n }\n\n /**\n * Connect using a private key (Node.js / server-side, no browser wallet needed)\n */\n async connectWithPrivateKey(privateKey: string, chainName?: string): Promise<string> {\n const targetChain = chainName || this.config.defaultChain;\n const chain = getChainByName(targetChain);\n\n if (!chain) {\n throw new X402Error(`Unsupported chain: ${targetChain}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (!chain.x402.enabled) {\n throw new X402Error(`Chain ${targetChain} is not enabled for x402 payments`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error('connectWithPrivateKey is only supported for EVM chains', 'CHAIN_NOT_SUPPORTED');\n }\n\n this.log(`Connecting with private key on ${chain.displayName}...`);\n\n const rpcProvider = new ethers.JsonRpcProvider(chain.rpcUrl);\n const wallet = new ethers.Wallet(privateKey, rpcProvider);\n\n this.provider = rpcProvider;\n this.signer = wallet;\n this.connectedAddress = wallet.address;\n this.currentChainId = chain.chainId;\n this.currentNetwork = 'evm';\n this.currentChainName = chain.name;\n\n const state = this.getState();\n this.emit('connect', state);\n this.log('Private key wallet connected', { address: this.connectedAddress, chain: chain.name });\n\n return this.connectedAddress;\n }\n\n /**\n * Disconnect the current wallet\n */\n async disconnect(): Promise<void> {\n this.provider = null;\n this.signer = null;\n this.connectedAddress = null;\n this.currentChainId = null;\n this.currentNetwork = null;\n this.currentChainName = null;\n\n this.emit('disconnect', undefined);\n this.log('Wallet disconnected');\n }\n\n /**\n * Switch to a different chain (EVM only)\n */\n async switchChain(chainName: string): Promise<void> {\n const chain = getChainByName(chainName);\n\n if (!chain) {\n throw new X402Error(`Unsupported chain: ${chainName}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error(\n 'switchChain is only supported for EVM networks. Reconnect with connect() for other networks.',\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n\n if (!this.provider) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n // Private key connections cannot use wallet_switchEthereumChain — re-create provider\n if (this.provider instanceof ethers.JsonRpcProvider && this.signer instanceof ethers.Wallet) {\n const rpcProvider = new ethers.JsonRpcProvider(chain.rpcUrl);\n const wallet = new ethers.Wallet(this.signer.privateKey, rpcProvider);\n this.provider = rpcProvider;\n this.signer = wallet;\n this.currentChainId = chain.chainId;\n this.currentChainName = chain.name;\n this.emit('chainChanged', { chainId: chain.chainId, chainName: chain.name });\n this.log('Switched chain (private key mode)', { chain: chain.name });\n return;\n }\n\n await this.switchEVMChain(chain);\n }\n\n // ============================================================================\n // PUBLIC API - Payment Creation\n // ============================================================================\n\n /**\n * Create a payment authorization\n *\n * @param paymentInfo - Payment information from 402 response\n * @returns Payment result with encoded X-PAYMENT header\n */\n async createPayment(paymentInfo: PaymentInfo): Promise<PaymentResult> {\n if (!this.connectedAddress) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n if (!this.currentChainName) {\n throw new X402Error('Chain not set', 'CHAIN_NOT_SUPPORTED');\n }\n\n const chain = getChainByName(this.currentChainName);\n if (!chain) {\n throw new X402Error(`Chain ${this.currentChainName} not found`, 'CHAIN_NOT_SUPPORTED');\n }\n\n this.emit('paymentStarted', { amount: paymentInfo.amount, network: chain.name });\n this.log('Creating payment...', { paymentInfo, chain: chain.name });\n\n try {\n // Route to appropriate payment method\n switch (chain.networkType) {\n case 'evm':\n return await this.createEVMPayment(paymentInfo, chain);\n default:\n throw new X402Error(\n `Payment creation for ${chain.networkType} requires the appropriate provider`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n } catch (error) {\n const x402Error = error instanceof X402Error\n ? error\n : new X402Error(\n error instanceof Error ? error.message : 'Unknown error',\n 'PAYMENT_FAILED',\n error\n );\n\n this.emit('paymentFailed', { error: x402Error.message, code: x402Error.code });\n throw x402Error;\n }\n }\n\n /**\n * Check USDC balance on current chain\n */\n async getBalance(): Promise<string> {\n if (!this.connectedAddress || !this.currentChainName) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n const chain = getChainByName(this.currentChainName);\n if (!chain) {\n throw new X402Error(`Chain ${this.currentChainName} not found`, 'CHAIN_NOT_SUPPORTED');\n }\n\n switch (chain.networkType) {\n case 'evm':\n return this.getEVMBalance(chain);\n default:\n throw new X402Error(\n `Balance check for ${chain.networkType} requires the appropriate provider`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n }\n\n // ============================================================================\n // PUBLIC API - Getters\n // ============================================================================\n\n /**\n * Get current wallet state\n */\n getState(): WalletState {\n return {\n connected: this.connectedAddress !== null,\n address: this.connectedAddress,\n chainId: this.currentChainId,\n network: this.currentChainName,\n networkType: this.currentNetwork,\n balance: null, // Call getBalance() separately\n };\n }\n\n /**\n * Get connected wallet address\n */\n getAddress(): string | null {\n return this.connectedAddress;\n }\n\n /**\n * Get current chain ID\n */\n getChainId(): number | null {\n return this.currentChainId;\n }\n\n /**\n * Get current chain name\n */\n getChainName(): string | null {\n return this.currentChainName;\n }\n\n /**\n * Get current chain display name\n */\n getChainDisplayName(): string | null {\n if (!this.currentChainName) return null;\n const chain = getChainByName(this.currentChainName);\n return chain?.displayName ?? null;\n }\n\n /**\n * Check if wallet is connected\n */\n isConnected(): boolean {\n return this.connectedAddress !== null;\n }\n\n /**\n * Get list of enabled chains\n */\n getEnabledChains(): ChainConfig[] {\n return getEnabledChains();\n }\n\n /**\n * Get chain config by name\n */\n getChain(name: string): ChainConfig | undefined {\n return getChainByName(name);\n }\n\n // ============================================================================\n // PUBLIC API - Events\n // ============================================================================\n\n /**\n * Subscribe to an event\n */\n on<E extends X402Event>(event: E, handler: X402EventHandler<E>): () => void {\n if (!this.eventHandlers.has(event)) {\n this.eventHandlers.set(event, new Set());\n }\n this.eventHandlers.get(event)!.add(handler as X402EventHandler<X402Event>);\n\n // Return unsubscribe function\n return () => this.off(event, handler);\n }\n\n /**\n * Unsubscribe from an event\n */\n off<E extends X402Event>(event: E, handler: X402EventHandler<E>): void {\n this.eventHandlers.get(event)?.delete(handler as X402EventHandler<X402Event>);\n }\n\n // ============================================================================\n // PRIVATE - EVM Wallet Connection\n // ============================================================================\n\n private async connectEVMWallet(chain: ChainConfig): Promise<string> {\n // Check for injected provider\n if (typeof window === 'undefined' || !window.ethereum) {\n throw new X402Error(\n 'No Ethereum wallet found. Please install MetaMask or another EVM wallet.',\n 'WALLET_NOT_FOUND'\n );\n }\n\n try {\n this.provider = new ethers.BrowserProvider(window.ethereum);\n\n // Request account access\n await this.provider.send('eth_requestAccounts', []);\n\n // Switch to target chain\n await this.switchEVMChain(chain);\n\n // Get signer and address\n this.signer = await this.provider.getSigner();\n this.connectedAddress = await this.signer.getAddress();\n this.currentChainId = chain.chainId;\n this.currentNetwork = 'evm';\n this.currentChainName = chain.name;\n\n // Setup event listeners\n this.setupEVMEventListeners();\n\n const state = this.getState();\n this.emit('connect', state);\n this.log('EVM wallet connected', { address: this.connectedAddress, chain: chain.name });\n\n return this.connectedAddress;\n } catch (error: unknown) {\n if (error instanceof Error) {\n if (error.message.includes('User rejected') || (error as { code?: number }).code === 4001) {\n throw new X402Error('Connection rejected by user', 'WALLET_CONNECTION_REJECTED');\n }\n }\n throw new X402Error(\n `Failed to connect wallet: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'UNKNOWN_ERROR',\n error\n );\n }\n }\n\n private async switchEVMChain(chain: ChainConfig): Promise<void> {\n if (!this.provider) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n try {\n await this.provider.send('wallet_switchEthereumChain', [{ chainId: chain.chainIdHex }]);\n } catch (switchError: unknown) {\n // Chain not added - try to add it\n if ((switchError as { code?: number }).code === 4902) {\n try {\n await this.provider.send('wallet_addEthereumChain', [\n {\n chainId: chain.chainIdHex,\n chainName: chain.displayName,\n nativeCurrency: chain.nativeCurrency,\n rpcUrls: [chain.rpcUrl],\n blockExplorerUrls: [chain.explorerUrl],\n },\n ]);\n } catch (addError) {\n throw new X402Error(\n `Failed to add ${chain.displayName} network`,\n 'CHAIN_SWITCH_REJECTED',\n addError\n );\n }\n } else if ((switchError as { code?: number }).code === 4001) {\n throw new X402Error('Network switch rejected by user', 'CHAIN_SWITCH_REJECTED');\n } else {\n throw new X402Error(\n `Failed to switch to ${chain.displayName}`,\n 'CHAIN_SWITCH_REJECTED',\n switchError\n );\n }\n }\n\n this.currentChainId = chain.chainId;\n this.currentChainName = chain.name;\n this.emit('chainChanged', { chainId: chain.chainId, chainName: chain.name });\n }\n\n private setupEVMEventListeners(): void {\n if (typeof window === 'undefined' || !window.ethereum) return;\n\n window.ethereum.on?.('accountsChanged', ((...args: unknown[]) => {\n const accounts = args[0] as string[];\n if (accounts.length === 0) {\n this.disconnect();\n } else if (accounts[0] !== this.connectedAddress) {\n this.connectedAddress = accounts[0];\n this.emit('accountChanged', { address: accounts[0] });\n }\n }) as (...args: unknown[]) => void);\n\n window.ethereum.on?.('chainChanged', ((...args: unknown[]) => {\n const chainIdHex = args[0] as string;\n const chainId = parseInt(chainIdHex, 16);\n const chain = getChainById(chainId);\n if (chain) {\n this.currentChainId = chainId;\n this.currentChainName = chain.name;\n this.emit('chainChanged', { chainId, chainName: chain.name });\n }\n }) as (...args: unknown[]) => void);\n }\n\n // ============================================================================\n // PRIVATE - EVM Payment Creation\n // ============================================================================\n\n private async createEVMPayment(paymentInfo: PaymentInfo, chain: ChainConfig): Promise<PaymentResult> {\n if (!this.signer) {\n throw new X402Error('Wallet not connected', 'WALLET_NOT_CONNECTED');\n }\n\n // Get recipient address for EVM\n const recipient = this.getRecipientForNetwork(paymentInfo, 'evm');\n\n // Validate recipient address - prevents empty/invalid addresses\n validateRecipient(recipient, 'evm');\n\n // Which stablecoin to charge. Defaults to USDC so existing callers are\n // unaffected; anything else is resolved from the chain's token registry.\n const tokenType: TokenType = paymentInfo.tokenType || 'usdc';\n const token = getTokenConfig(chain.name, tokenType);\n if (!token) {\n throw new X402Error(\n `Token ${tokenType} not supported on ${chain.name}`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n\n // Generate random nonce\n const nonceBytes = new Uint8Array(32);\n if (typeof window !== 'undefined' && window.crypto) {\n window.crypto.getRandomValues(nonceBytes);\n } else {\n for (let i = 0; i < 32; i++) {\n nonceBytes[i] = Math.floor(Math.random() * 256);\n }\n }\n const nonce = ethers.hexlify(nonceBytes);\n\n // Set validity window (5 minutes for congested networks, 1 minute otherwise)\n const validAfter = 0;\n const validityWindowSeconds = chain.name === 'base' ? 300 : 60;\n const validBefore = Math.floor(Date.now() / 1000) + validityWindowSeconds;\n\n // EIP-712 domain of the token being charged\n const domain = {\n name: token.name,\n version: token.version,\n chainId: chain.chainId,\n verifyingContract: token.address,\n };\n\n // EIP-712 types for TransferWithAuthorization (ERC-3009)\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 // Parse amount in the token's own decimals\n const value = ethers.parseUnits(paymentInfo.amount, token.decimals);\n const from = await this.signer.getAddress();\n const to = ethers.getAddress(recipient);\n\n // Message to sign\n const message = {\n from,\n to,\n value,\n validAfter,\n validBefore,\n nonce,\n };\n\n this.log('Signing EIP-712 message...', { domain, message });\n\n // Sign the EIP-712 message\n let signature: string;\n try {\n signature = await this.signer.signTypedData(domain, types, message);\n } catch (error: unknown) {\n if (error instanceof Error && (error.message.includes('User rejected') || (error as { code?: number }).code === 4001)) {\n throw new X402Error('Signature rejected by user', 'SIGNATURE_REJECTED');\n }\n throw new X402Error(\n `Failed to sign payment: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error\n );\n }\n\n const sig = ethers.Signature.from(signature);\n\n // Construct payload\n const payload: EVMPaymentPayload = {\n from,\n to,\n value: value.toString(),\n validAfter,\n validBefore,\n nonce,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n chainId: chain.chainId,\n token: token.address,\n };\n\n // Encode as X-PAYMENT header\n const paymentHeader = this.encodeEVMPaymentHeader(payload, chain);\n\n this.emit('paymentSigned', { paymentHeader });\n\n const result: PaymentResult = {\n success: true,\n paymentHeader,\n headers: {\n 'X-PAYMENT': paymentHeader,\n 'PAYMENT-SIGNATURE': paymentHeader,\n },\n network: chain.name,\n payer: from,\n };\n\n this.emit('paymentCompleted', result);\n this.log('Payment created successfully', { network: chain.name, from });\n\n return result;\n }\n\n private encodeEVMPaymentHeader(payload: EVMPaymentPayload, chain: ChainConfig): string {\n // Reconstruct full signature from v, r, s\n const fullSignature = payload.r + payload.s.slice(2) + payload.v.toString(16).padStart(2, '0');\n\n // Determine version to use (default to v1 for backward compatibility)\n const version = this.config.x402Version === 2 ? 2 : 1;\n\n // Build the payload data\n const payloadData: X402EVMPayload = {\n signature: fullSignature,\n authorization: {\n from: payload.from,\n to: payload.to,\n value: payload.value,\n validAfter: payload.validAfter.toString(),\n validBefore: payload.validBefore.toString(),\n nonce: payload.nonce,\n },\n };\n\n if (this.config.includeTokenMetadata) {\n const token = buildTokenMetadata(chain.name, payload.token);\n if (!token) {\n throw new X402Error(\n `Token ${payload.token} is not in the registry for ${chain.name}; cannot build token metadata`,\n 'CHAIN_NOT_SUPPORTED'\n );\n }\n payloadData.token = token;\n }\n\n // Format in x402 standard format (v1 or v2)\n const x402Payload = version === 2\n ? {\n x402Version: 2 as const,\n scheme: 'exact' as const,\n network: chainToCAIP2(chain.name), // CAIP-2 format for v2\n payload: payloadData,\n }\n : {\n x402Version: 1 as const,\n scheme: 'exact' as const,\n network: chain.name, // Plain chain name for v1\n payload: payloadData,\n };\n\n // Base64 encode (UTF-8 safe: token domain names like `USD₮0` are not ASCII)\n return encodeBase64Json(x402Payload);\n }\n\n // ============================================================================\n // PRIVATE - EVM Balance Check\n // ============================================================================\n\n private async getEVMBalance(chain: ChainConfig): Promise<string> {\n // Use public RPC for balance check (more reliable than wallet provider)\n const publicProvider = new ethers.JsonRpcProvider(chain.rpcUrl);\n\n const usdcAbi = ['function balanceOf(address owner) view returns (uint256)'];\n const usdcContract = new ethers.Contract(chain.usdc.address, usdcAbi, publicProvider);\n\n try {\n const balance = await usdcContract.balanceOf(this.connectedAddress);\n const formatted = ethers.formatUnits(balance, chain.usdc.decimals);\n return parseFloat(formatted).toFixed(2);\n } catch {\n return '0.00';\n }\n }\n\n // ============================================================================\n // PRIVATE - Utilities\n // ============================================================================\n\n private getRecipientForNetwork(paymentInfo: PaymentInfo, network: NetworkType): string {\n // Map SVM to solana for recipient lookup\n const lookupNetwork = network === 'svm' ? 'solana' : network;\n const recipients = paymentInfo.recipients as Record<string, string> | undefined;\n if (recipients?.[lookupNetwork]) {\n return recipients[lookupNetwork];\n }\n return paymentInfo.recipient;\n }\n\n private emit<E extends X402Event>(event: E, data: X402EventData[E]): void {\n this.eventHandlers.get(event)?.forEach(handler => {\n try {\n handler(data);\n } catch (error) {\n console.error(`Error in ${event} handler:`, error);\n }\n });\n }\n\n private log(message: string, data?: unknown): void {\n if (this.config.debug) {\n console.log(`[X402Client] ${message}`, data ?? '');\n }\n }\n}\n\n// Type augmentation for window.ethereum\ndeclare global {\n interface Window {\n ethereum?: {\n request: (args: { method: string; params?: unknown[] }) => Promise<unknown>;\n on?: (event: string, handler: (...args: unknown[]) => void) => void;\n removeListener?: (event: string, handler: (...args: unknown[]) => void) => void;\n };\n }\n}\n","/**\n * uvd-x402-sdk - EnvKeyAdapter\n *\n * SigningWalletAdapter implementation using a raw private key.\n * Reads the key from a constructor parameter or the WALLET_PRIVATE_KEY\n * environment variable.\n *\n * Intended for server-side / CLI / agent use cases where the\n * signing key is available in the environment. NEVER use this\n * in browser contexts -- use OWSWalletAdapter instead.\n *\n * @example Using environment variable\n * ```ts\n * // Reads process.env.WALLET_PRIVATE_KEY\n * const wallet = new EnvKeyAdapter();\n * console.log(wallet.getAddress()); // 0x...\n * ```\n *\n * @example Using explicit key\n * ```ts\n * const wallet = new EnvKeyAdapter(process.env.MY_AGENT_KEY!);\n * const auth = await wallet.signEIP3009({\n * to: '0xRecipient',\n * amountUsdc: 0.10,\n * network: 'base',\n * });\n * ```\n */\n\nimport { ethers } from 'ethers';\nimport { getChainByName } from '../chains';\nimport { X402Error } from '../types';\nimport type {\n SigningWalletAdapter,\n EIP3009Params,\n EIP3009Authorization,\n} from '../wallet';\n\n/**\n * EnvKeyAdapter -- SigningWalletAdapter backed by a raw private key.\n */\nexport class EnvKeyAdapter implements SigningWalletAdapter {\n private readonly wallet: ethers.Wallet;\n\n /**\n * Create an EnvKeyAdapter.\n *\n * @param privateKey - Hex-encoded private key (with or without 0x prefix).\n * If omitted, reads from `process.env.WALLET_PRIVATE_KEY`.\n * @throws {X402Error} if no private key is available\n */\n constructor(privateKey?: string) {\n const key = privateKey || (typeof process !== 'undefined' ? process.env.WALLET_PRIVATE_KEY : undefined);\n\n if (!key) {\n throw new X402Error(\n 'No private key provided. Pass it to the constructor or set WALLET_PRIVATE_KEY env var.',\n 'WALLET_NOT_CONNECTED',\n );\n }\n\n this.wallet = new ethers.Wallet(key);\n }\n\n /**\n * Get the checksummed EVM wallet address.\n */\n getAddress(): string {\n return this.wallet.address;\n }\n\n /**\n * Sign a message using EIP-191 personal_sign.\n *\n * @param message - The message string to sign\n * @returns Hex-encoded signature\n */\n async signMessage(message: string): Promise<string> {\n return this.wallet.signMessage(message);\n }\n\n /**\n * Sign EIP-712 typed structured data.\n *\n * @param typedData - JSON string with `domain`, `types`, `primaryType`, and `message` fields\n * @returns Object with signature and v/r/s components\n */\n async signTypedData(typedData: string): Promise<{\n signature: string;\n v: number;\n r: string;\n s: string;\n }> {\n const parsed = JSON.parse(typedData) as {\n domain: ethers.TypedDataDomain;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n };\n\n // ethers v6 signTypedData does not take primaryType -- it infers it\n // from the types object (the type not listed as a field of another type).\n // We pass domain, types (without EIP712Domain), and the message value.\n const { domain, types, message } = parsed;\n\n // Remove EIP712Domain from types if present (ethers handles it via domain)\n const cleanTypes = { ...types };\n delete cleanTypes['EIP712Domain'];\n\n const signature = await this.wallet.signTypedData(domain, cleanTypes, message);\n const sig = ethers.Signature.from(signature);\n\n return {\n signature,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n };\n }\n\n /**\n * Sign a serialized EVM transaction.\n *\n * Uses the raw private key via ethers.Wallet.signTransaction().\n * Used by AdvancedEscrowClient for on-chain operations (release,\n * refund, charge) when constructed with a SigningWalletAdapter.\n *\n * @param unsignedTx - Hex-encoded unsigned transaction (ethers serialized)\n * @returns Hex-encoded signed raw transaction, ready for broadcast\n */\n async signTransaction(unsignedTx: string): Promise<string> {\n const tx = ethers.Transaction.from(unsignedTx);\n return this.wallet.signTransaction(tx);\n }\n\n /**\n * Sign an EIP-3009 ReceiveWithAuthorization for USDC.\n *\n * @param params - EIP-3009 parameters\n * @returns Signed authorization ready for facilitator relay\n */\n async signEIP3009(params: EIP3009Params): Promise<EIP3009Authorization> {\n const chain = getChainByName(params.network);\n if (!chain) {\n throw new X402Error(`Unsupported network: ${params.network}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error(\n `EIP-3009 is only supported on EVM chains. ${params.network} is ${chain.networkType}.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n }\n\n const chainId = params.chainId ?? chain.chainId;\n const usdcAddress = params.usdcContract ?? chain.usdc.address;\n const from = this.wallet.address;\n const to = ethers.getAddress(params.to);\n const value = ethers.parseUnits(params.amountUsdc.toString(), chain.usdc.decimals);\n const validAfter = params.validAfter ?? 0;\n const validBefore = params.validBefore ?? Math.floor(Date.now() / 1000) + 300;\n\n // Generate random 32-byte nonce\n const nonce = ethers.hexlify(ethers.randomBytes(32));\n\n // EIP-712 domain (matches USDC contract's domain separator)\n const domain: ethers.TypedDataDomain = {\n name: chain.usdc.name,\n version: chain.usdc.version,\n chainId,\n verifyingContract: usdcAddress,\n };\n\n // EIP-712 types for TransferWithAuthorization (ERC-3009)\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 // Message to sign\n const message = {\n from,\n to,\n value,\n validAfter,\n validBefore,\n nonce,\n };\n\n // Sign the EIP-712 typed data\n let signature: string;\n try {\n signature = await this.wallet.signTypedData(domain, types, message);\n } catch (error: unknown) {\n throw new X402Error(\n `Failed to sign EIP-3009 authorization: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n\n const sig = ethers.Signature.from(signature);\n\n return {\n from,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n signature,\n };\n }\n}\n","/**\n * uvd-x402-sdk - OWSWalletAdapter\n *\n * SigningWalletAdapter implementation using the Open Wallet Standard (OWS).\n * Delegates all signing to an OWS wallet instance, which manages key\n * security (encrypted vault, hardware isolation, etc.).\n *\n * Requires `@open-wallet-standard/core` as an optional peer dependency.\n * If the package is not installed, the adapter throws a helpful error\n * at construction time.\n *\n * @example\n * ```ts\n * import { OWSWalletAdapter } from 'uvd-x402-sdk';\n *\n * // The OWS wallet object must implement signMessage and signTypedData\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const auth = await wallet.signEIP3009({\n * to: '0xRecipient',\n * amountUsdc: 0.50,\n * network: 'base',\n * });\n * ```\n */\n\nimport { ethers } from 'ethers';\nimport { getChainByName } from '../chains';\nimport { X402Error } from '../types';\nimport type {\n SigningWalletAdapter,\n EIP3009Params,\n EIP3009Authorization,\n} from '../wallet';\n\n// ============================================================================\n// OWS WALLET INTERFACE (minimal subset we need)\n// ============================================================================\n\n/**\n * Minimal OWS wallet interface for signing operations.\n *\n * This mirrors the subset of the Open Wallet Standard that we use,\n * avoiding a hard compile-time dependency on @open-wallet-standard/core.\n * Any object that satisfies this shape can be passed to OWSWalletAdapter.\n */\nexport interface OWSWallet {\n /** Get wallet accounts (at least one EVM account expected) */\n accounts: ReadonlyArray<{\n /** EVM address (0x...) */\n address: string;\n /** Chain identifiers this account supports */\n chains?: ReadonlyArray<string>;\n }>;\n\n /** Sign a personal message (EIP-191) */\n signMessage(params: {\n account: { address: string };\n message: string | Uint8Array;\n }): Promise<{ signature: string }>;\n\n /** Sign EIP-712 typed data */\n signTypedData(params: {\n account: { address: string };\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<{ signature: string }>;\n\n /** Sign a serialized EVM transaction (hex-encoded) */\n signTransaction(params: {\n account: { address: string };\n transaction: string;\n chainId: string;\n }): Promise<{ signedTransaction: string }>;\n}\n\n// ============================================================================\n// OWS WALLET ADAPTER\n// ============================================================================\n\n/**\n * OWSWalletAdapter -- SigningWalletAdapter backed by an Open Wallet Standard wallet.\n */\nexport class OWSWalletAdapter implements SigningWalletAdapter {\n private readonly owsWallet: OWSWallet;\n private readonly address: string;\n\n /**\n * Create an OWSWalletAdapter.\n *\n * @param owsWallet - An object implementing the OWSWallet interface\n * (typically from @open-wallet-standard/core or a compatible provider)\n * @param accountIndex - Which account to use if the wallet has multiple (default: 0)\n * @throws {X402Error} if the wallet has no accounts\n */\n constructor(owsWallet: OWSWallet, accountIndex = 0) {\n if (!owsWallet || !owsWallet.accounts || owsWallet.accounts.length === 0) {\n throw new X402Error(\n 'OWS wallet has no accounts. Create or import a wallet first.',\n 'WALLET_NOT_CONNECTED',\n );\n }\n\n const account = owsWallet.accounts[accountIndex];\n if (!account) {\n throw new X402Error(\n `OWS wallet account index ${accountIndex} does not exist. Wallet has ${owsWallet.accounts.length} account(s).`,\n 'WALLET_NOT_CONNECTED',\n );\n }\n\n this.owsWallet = owsWallet;\n this.address = ethers.getAddress(account.address);\n }\n\n /**\n * Get the checksummed EVM wallet address.\n */\n getAddress(): string {\n return this.address;\n }\n\n /**\n * Sign a message using EIP-191 personal_sign.\n *\n * @param message - The message string to sign\n * @returns Hex-encoded signature\n */\n async signMessage(message: string): Promise<string> {\n try {\n const result = await this.owsWallet.signMessage({\n account: { address: this.address },\n message,\n });\n return result.signature;\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signMessage failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n }\n\n /**\n * Sign EIP-712 typed structured data.\n *\n * @param typedData - JSON string with `domain`, `types`, `primaryType`, and `message` fields\n * @returns Object with signature and v/r/s components\n */\n async signTypedData(typedData: string): Promise<{\n signature: string;\n v: number;\n r: string;\n s: string;\n }> {\n const parsed = JSON.parse(typedData) as {\n domain: Record<string, unknown>;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n };\n\n try {\n const result = await this.owsWallet.signTypedData({\n account: { address: this.address },\n domain: parsed.domain,\n types: parsed.types,\n primaryType: parsed.primaryType,\n message: parsed.message,\n });\n\n const sig = ethers.Signature.from(result.signature);\n\n return {\n signature: result.signature,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n };\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signTypedData failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n }\n\n /**\n * Sign a serialized EVM transaction.\n *\n * Delegates to the OWS wallet's signTransaction method.\n * Used by AdvancedEscrowClient for on-chain operations (release,\n * refund, charge) where the wallet signs instead of a raw private key.\n *\n * @param unsignedTx - Hex-encoded unsigned transaction\n * @returns Hex-encoded signed raw transaction\n */\n async signTransaction(unsignedTx: string): Promise<string> {\n try {\n const result = await this.owsWallet.signTransaction({\n account: { address: this.address },\n transaction: unsignedTx,\n chainId: '1', // chainId is embedded in the serialized TX; this is a hint\n });\n return result.signedTransaction;\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signTransaction failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n }\n\n /**\n * Sign an EIP-3009 ReceiveWithAuthorization for USDC.\n *\n * @param params - EIP-3009 parameters\n * @returns Signed authorization ready for facilitator relay\n */\n async signEIP3009(params: EIP3009Params): Promise<EIP3009Authorization> {\n const chain = getChainByName(params.network);\n if (!chain) {\n throw new X402Error(`Unsupported network: ${params.network}`, 'CHAIN_NOT_SUPPORTED');\n }\n\n if (chain.networkType !== 'evm') {\n throw new X402Error(\n `EIP-3009 is only supported on EVM chains. ${params.network} is ${chain.networkType}.`,\n 'CHAIN_NOT_SUPPORTED',\n );\n }\n\n const chainId = params.chainId ?? chain.chainId;\n const usdcAddress = params.usdcContract ?? chain.usdc.address;\n const from = this.address;\n const to = ethers.getAddress(params.to);\n const value = ethers.parseUnits(params.amountUsdc.toString(), chain.usdc.decimals);\n const validAfter = params.validAfter ?? 0;\n const validBefore = params.validBefore ?? Math.floor(Date.now() / 1000) + 300;\n\n // Generate random 32-byte nonce\n const nonce = ethers.hexlify(ethers.randomBytes(32));\n\n // EIP-712 domain\n const domain: Record<string, unknown> = {\n name: chain.usdc.name,\n version: chain.usdc.version,\n chainId,\n verifyingContract: usdcAddress,\n };\n\n // EIP-712 types for TransferWithAuthorization (ERC-3009)\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 // Message to sign\n const message: Record<string, unknown> = {\n from,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n };\n\n let signatureResult: { signature: string };\n try {\n signatureResult = await this.owsWallet.signTypedData({\n account: { address: this.address },\n domain,\n types,\n primaryType: 'TransferWithAuthorization',\n message,\n });\n } catch (error: unknown) {\n throw new X402Error(\n `OWS signEIP3009 failed: ${error instanceof Error ? error.message : 'Unknown error'}`,\n 'PAYMENT_FAILED',\n error,\n );\n }\n\n const sig = ethers.Signature.from(signatureResult.signature);\n\n return {\n from,\n to,\n value: value.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n v: sig.v,\n r: sig.r,\n s: sig.s,\n signature: signatureResult.signature,\n };\n }\n}\n","/**\n * Facilitator Configuration\n *\n * This module contains the known facilitator addresses for each chain.\n * The SDK uses these automatically so users don't need to configure them.\n *\n * The facilitator (https://facilitator.ultravioletadao.xyz) has wallets\n * on each supported blockchain for:\n * - EVM: Signing EIP-3009 transferWithAuthorization transactions\n * - Solana: Paying transaction fees (fee payer)\n * - Algorand: Signing fee transactions in atomic groups\n * - Stellar: Signing authorization entries\n * - NEAR: Acting as relayer for meta-transactions\n * - Sui: Sponsoring transactions (paying gas via sponsored txs)\n * - XRPL: Submitting pre-signed Payment blobs (paying the network fee)\n */\n\n/**\n * Default facilitator URL\n */\nexport const DEFAULT_FACILITATOR_URL = 'https://facilitator.ultravioletadao.xyz';\n\n/**\n * Facilitator wallet addresses by chain type\n *\n * These are the public addresses of the facilitator's wallets.\n * The facilitator uses these to pay fees and sign transactions.\n */\nexport const FACILITATOR_ADDRESSES = {\n // ============================================\n // EVM Chains\n // ============================================\n /**\n * EVM facilitator address (mainnet)\n * Used for: Submitting EIP-3009 transferWithAuthorization transactions\n * Note: Same address across all EVM mainnet chains\n */\n evm: '0x103040545AC5031A11E8C03dd11324C7333a13C7',\n\n /**\n * EVM facilitator address (testnet)\n * Used for: All EVM testnet chains\n */\n 'evm-testnet': '0x34033041a5944B8F10f8E4D8496Bfb84f1A293A8',\n\n // ============================================\n // Solana\n // ============================================\n /**\n * Solana facilitator address (mainnet)\n * Used for: Paying transaction fees on Solana\n */\n solana: 'F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq',\n\n /**\n * Solana facilitator address (devnet)\n */\n 'solana-devnet': '6xNPewUdKRbEZDReQdpyfNUdgNg8QRc8Mt263T5GZSRv',\n\n // ============================================\n // Fogo (uses same addresses as Solana)\n // ============================================\n /**\n * Fogo facilitator address (mainnet)\n */\n fogo: 'F742C4VfFLQ9zRQyithoj5229ZgtX2WqKCSFKgH2EThq',\n\n /**\n * Fogo facilitator address (testnet)\n */\n 'fogo-testnet': '6xNPewUdKRbEZDReQdpyfNUdgNg8QRc8Mt263T5GZSRv',\n\n // ============================================\n // NEAR\n // ============================================\n /**\n * NEAR facilitator address (mainnet)\n * Used for: Relaying meta-transactions\n */\n near: 'uvd-facilitator.near',\n\n /**\n * NEAR facilitator address (testnet)\n */\n 'near-testnet': 'uvd-facilitator.testnet',\n\n // ============================================\n // Stellar\n // ============================================\n /**\n * Stellar facilitator address (mainnet)\n * Used for: Signing soroban authorization entries\n */\n stellar: 'GCHPGXJT2WFFRFCA5TV4G4E3PMMXLNIDUH27PKDYA4QJ2XGYZWGFZNHB',\n\n /**\n * Stellar facilitator address (testnet)\n */\n 'stellar-testnet': 'GBBFZMLUJEZVI32EN4XA2KPP445XIBTMTRBLYWFIL556RDTHS2OWFQ2Z',\n\n // ============================================\n // Algorand\n // ============================================\n /**\n * Algorand facilitator address (mainnet)\n * Used for: Signing Transaction 0 (fee tx) in atomic groups\n */\n algorand: 'KIMS5H6QLCUDL65L5UBTOXDPWLMTS7N3AAC3I6B2NCONEI5QIVK7LH2C2I',\n\n /**\n * Algorand facilitator address (testnet)\n */\n 'algorand-testnet': '5DPPDQNYUPCTXRZWRYSF3WPYU6RKAUR25F3YG4EKXQRHV5AUAI62H5GXL4',\n\n // ============================================\n // Sui\n // ============================================\n /**\n * Sui facilitator address (mainnet)\n * Used for: Sponsoring transactions (paying gas)\n */\n sui: '0xe7bbf2b13f7d72714760aa16e024fa1b35a978793f9893d0568a4fbf356a764a',\n\n /**\n * Sui facilitator address (testnet)\n */\n 'sui-testnet': '0xabbd16a2fab2a502c9cfe835195a6fc7d70bfc27cffb40b8b286b52a97006e67',\n\n // ============================================\n // XRPL (XRP Ledger)\n // ============================================\n /**\n * XRPL facilitator address (mainnet)\n * Used for: Submitting pre-signed Payment blobs and paying the network fee\n */\n 'xrpl-mainnet': 'rfADKkVXBNqK3z72tVSS3LVzAR3psYkonp',\n\n /**\n * XRPL facilitator address (testnet)\n */\n 'xrpl-testnet': 'rGhTioKAFHe75KgVnQtacRiKFuPv28Wbwk',\n} as const;\n\n/**\n * Get the facilitator address for a specific chain\n *\n * @param chainName - The chain name (e.g., 'algorand', 'solana', 'base')\n * @param networkType - The network type (e.g., 'evm', 'svm', 'algorand')\n * @returns The facilitator address for that chain, or undefined if not supported\n */\nexport function getFacilitatorAddress(\n chainName: string,\n networkType?: string\n): string | undefined {\n // Check for exact chain match first\n const exactMatch = FACILITATOR_ADDRESSES[chainName as keyof typeof FACILITATOR_ADDRESSES];\n if (exactMatch) {\n return exactMatch;\n }\n\n // Fall back to network type\n if (networkType === 'evm') {\n return FACILITATOR_ADDRESSES.evm;\n }\n if (networkType === 'svm' || networkType === 'solana') {\n return FACILITATOR_ADDRESSES.solana;\n }\n if (networkType === 'algorand') {\n return FACILITATOR_ADDRESSES.algorand;\n }\n if (networkType === 'stellar') {\n return FACILITATOR_ADDRESSES.stellar;\n }\n if (networkType === 'near') {\n return FACILITATOR_ADDRESSES.near;\n }\n if (networkType === 'sui') {\n return FACILITATOR_ADDRESSES.sui;\n }\n if (networkType === 'xrpl') {\n return FACILITATOR_ADDRESSES['xrpl-mainnet'];\n }\n\n return undefined;\n}\n\n/**\n * Type for facilitator addresses\n */\nexport type FacilitatorAddresses = typeof FACILITATOR_ADDRESSES;\n","/**\n * Live traffic stream client (`GET /events`, Server-Sent Events).\n *\n * The facilitator emits one event per operation it handles, so you can render or\n * react to live traffic without polling and without scraping logs.\n *\n * @example\n * ```ts\n * import { streamTrafficEvents } from '@ultravioletadao/x402-sdk';\n *\n * for await (const event of streamTrafficEvents()) {\n * console.log(event.kind, event.network, event.ok, event.tx);\n * }\n * ```\n *\n * @example Only settlements on the chains you care about. The facilitator has NO\n * server-side filter by network, so this is applied client-side.\n * ```ts\n * const stream = streamTrafficEvents({\n * networks: ['base', 'polygon'],\n * kinds: ['settle'],\n * });\n * for await (const event of stream) console.log(event.tx);\n * ```\n *\n * Three properties of this stream decide how you should use it:\n *\n * **It is lossy by design.** The facilitator will never slow down or fail a\n * payment to keep an observer in sync, so an event you were not connected for is\n * simply gone. Treat it as a live hint and use the chain as the source of truth.\n * Absence of events is NOT evidence that nothing happened.\n *\n * **Failed operations are not published.** Only operations that resolved emit an\n * event, so `ok: false` means \"resolved and came back negative\", never \"blew up\".\n * A stream that looks healthy is not proof that the rail is.\n *\n * **Admission is bounded.** The endpoint is public and unauthenticated, so it\n * sheds with HTTP 503 + `Retry-After` once too many subscribers are connected,\n * and returns 404 when the operator disabled it.\n */\n\nimport { DEFAULT_FACILITATOR_URL } from './facilitator';\n\n/** Operations the facilitator publishes. */\nexport type TrafficEventKind = 'verify' | 'settle';\n\n/** Operations the facilitator publishes, as a value. */\nexport const EVENT_KINDS: readonly TrafficEventKind[] = ['verify', 'settle'] as const;\n\n/**\n * The stream sends a `:keepalive` comment on this cadence, so any read timeout\n * you add must comfortably exceed it or you will kill healthy connections on an\n * idle rail.\n */\nexport const KEEPALIVE_INTERVAL_MS = 15_000;\n\n/**\n * One facilitator operation, as seen by an observer.\n *\n * Optional fields are *omitted* by the facilitator rather than sent as null, and\n * they are all absent when the operator runs the stream in `minimal` detail\n * mode. Never assume `payer` or `amount` is present.\n */\nexport interface TrafficEvent {\n /** Unix epoch **milliseconds**, UTC. Note: milliseconds, not seconds. */\n ts: number;\n kind: TrafficEventKind | string;\n /**\n * The facilitator's canonical network slug, the same one `/supported` uses.\n *\n * Beware: this is the *canonical* name, which is not always the alias you are\n * allowed to send. `skale` is accepted on the way in, but this field always\n * says `skale-base`. Match on the canonical form or you will silently drop\n * every event for that chain.\n */\n network: string;\n /** Resolved successfully? False means resolved-negative, not errored. */\n ok: boolean;\n payer?: string;\n /** Present on `settle`, absent on `verify` — nothing settled yet. */\n tx?: string;\n amount?: string;\n asset?: string;\n /**\n * The protected endpoint being bought.\n *\n * Answers \"what was paid for\", which the amount alone never does — two\n * 1-USDC settles are indistinguishable without it.\n */\n resource?: string;\n /** The seller receiving the payment. */\n payTo?: string;\n /** Human-readable description the seller advertised. */\n description?: string;\n /** Payment scheme: `exact`, `escrow`, `commerce`, `upto`. */\n scheme?: string;\n /**\n * Why the operation failed, as a BOUNDED CATEGORY — never the error text.\n *\n * Present only on operations that errored, and only where the operator set\n * `X402_EVENTS_PUBLISH_FAILURES=true`. A closed set (`contract_revert`,\n * `invalid_signature`, `insufficient_funds`, `invalid_timing`,\n * `blocked_address`, …, `other`) precisely so it can never carry an address\n * or an RPC URL.\n *\n * Note the distinction it makes visible: `ok: false` with no `error` means the\n * operation RESOLVED and came back negative; `error` set means it blew up.\n * Before this existed the second case produced no event at all.\n */\n error?: string;\n}\n\n/** Raised when the stream cannot be opened. Carries the HTTP status. */\nexport class TrafficStreamError extends Error {\n readonly status: number;\n /** Seconds to wait before retrying, when the server said so (503). */\n readonly retryAfter?: number;\n\n constructor(message: string, status: number, retryAfter?: number) {\n super(message);\n this.name = 'TrafficStreamError';\n this.status = status;\n this.retryAfter = retryAfter;\n }\n}\n\nexport interface StreamTrafficEventsOptions {\n /** Facilitator to subscribe to. Defaults to the Ultravioleta DAO facilitator. */\n facilitatorUrl?: string;\n /**\n * Only yield events for these networks. Applied client-side — the facilitator\n * has no per-network filter, so every event still crosses the wire. Match the\n * canonical slug (`skale-base`, not `skale`).\n */\n networks?: string[];\n /** Only yield these operations. */\n kinds?: TrafficEventKind[];\n /** Abort the stream. Without one, iteration ends only when the server closes. */\n signal?: AbortSignal;\n /** Extra headers, for a deployment that gates the stream behind authorization. */\n headers?: Record<string, string>;\n}\n\n/** One decoded SSE frame: the event name and its raw data payload. */\nexport interface SSEFrame {\n event: string;\n data: string;\n}\n\n/**\n * Incremental Server-Sent Events parser.\n *\n * Kept separate from the network layer so the framing can be tested without a\n * socket — which matters, because the case that breaks in production is an idle\n * rail sending nothing but keepalive comments for minutes.\n */\nexport class SSEParser {\n private buffer = '';\n private eventName = '';\n private dataLines: string[] = [];\n\n /** Feed a chunk of the response body; get back whatever frames completed. */\n push(chunk: string): SSEFrame[] {\n this.buffer += chunk;\n const frames: SSEFrame[] = [];\n\n let newlineIndex: number;\n while ((newlineIndex = this.buffer.indexOf('\\n')) !== -1) {\n const line = this.buffer.slice(0, newlineIndex).replace(/\\r$/, '');\n this.buffer = this.buffer.slice(newlineIndex + 1);\n\n if (line === '') {\n // Blank line dispatches. A dispatch with no data is a no-op per spec.\n if (this.dataLines.length > 0) {\n frames.push({\n event: this.eventName || 'message',\n data: this.dataLines.join('\\n'),\n });\n }\n this.eventName = '';\n this.dataLines = [];\n continue;\n }\n\n if (line.startsWith(':')) {\n // Comment. This is what a keepalive looks like — deliberately silent.\n continue;\n }\n\n const colon = line.indexOf(':');\n const field = colon === -1 ? line : line.slice(0, colon);\n let value = colon === -1 ? '' : line.slice(colon + 1);\n // A single leading space after the colon is framing, not value.\n if (value.startsWith(' ')) value = value.slice(1);\n\n if (field === 'event') this.eventName = value;\n else if (field === 'data') this.dataLines.push(value);\n // id / retry: accepted and ignored, so a future facilitator that starts\n // sending them does not break this parser.\n }\n\n return frames;\n }\n}\n\n/**\n * Decode one SSE frame into a {@link TrafficEvent}.\n *\n * Returns null for anything malformed: a single bad message must never tear down\n * a long-lived stream — the connection is worth more than the message.\n */\nexport function parseTrafficEvent(frame: SSEFrame): TrafficEvent | null {\n let payload: unknown;\n try {\n payload = JSON.parse(frame.data);\n } catch {\n return null;\n }\n if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {\n return null;\n }\n\n const raw = payload as Record<string, unknown>;\n // The SSE event name is authoritative for `kind`; the body carries it too and\n // they agree, but the framing is the contract.\n const kind = (raw.kind as string) || frame.event;\n\n if (typeof raw.ts !== 'number' || typeof raw.network !== 'string' || typeof raw.ok !== 'boolean') {\n return null;\n }\n\n const event: TrafficEvent = {\n ts: raw.ts,\n kind,\n network: raw.network,\n ok: raw.ok,\n };\n if (typeof raw.payer === 'string') event.payer = raw.payer;\n if (typeof raw.tx === 'string') event.tx = raw.tx;\n if (typeof raw.amount === 'string') event.amount = raw.amount;\n if (typeof raw.asset === 'string') event.asset = raw.asset;\n if (typeof raw.resource === 'string') event.resource = raw.resource;\n if (typeof raw.payTo === 'string') event.payTo = raw.payTo;\n if (typeof raw.description === 'string') event.description = raw.description;\n if (typeof raw.scheme === 'string') event.scheme = raw.scheme;\n if (typeof raw.error === 'string') event.error = raw.error;\n return event;\n}\n\n/** Does this event pass the caller's client-side filters? */\nexport function matchesFilters(\n event: TrafficEvent,\n options: Pick<StreamTrafficEventsOptions, 'networks' | 'kinds'>\n): boolean {\n if (options.kinds && options.kinds.length > 0) {\n if (!options.kinds.some((k) => k.toLowerCase() === event.kind.toLowerCase())) return false;\n }\n if (options.networks && options.networks.length > 0) {\n if (!options.networks.some((n) => n.toLowerCase() === event.network.toLowerCase())) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Subscribe to the facilitator's live traffic stream.\n *\n * Works in Node 18+ and in browsers: it uses `fetch` and the response body\n * stream rather than `EventSource`, so it also works where custom headers are\n * needed (`EventSource` cannot send them).\n *\n * Iteration ends when the server closes the connection or the `signal` aborts.\n * It does NOT reconnect on its own — reconnect policy belongs to the caller, who\n * is the only one who knows whether a gap matters.\n *\n * @throws {TrafficStreamError} 404 when the operator disabled the stream, 503\n * with `retryAfter` when it is at subscriber capacity.\n */\nexport async function* streamTrafficEvents(\n options: StreamTrafficEventsOptions = {}\n): AsyncGenerator<TrafficEvent, void, undefined> {\n const baseUrl = (options.facilitatorUrl || DEFAULT_FACILITATOR_URL).replace(/\\/$/, '');\n const response = await fetch(`${baseUrl}/events`, {\n method: 'GET',\n headers: { Accept: 'text/event-stream', ...(options.headers || {}) },\n signal: options.signal,\n });\n\n if (!response.ok) {\n const body = await response.text().catch(() => '');\n if (response.status === 404) {\n throw new TrafficStreamError(\n `GET /events is disabled on this facilitator (operator set X402_EVENTS_ENABLED=false): ${body}`,\n 404\n );\n }\n if (response.status === 503) {\n const header = response.headers.get('retry-after');\n const retryAfter = header ? Number(header) : undefined;\n throw new TrafficStreamError(\n `GET /events is at subscriber capacity; retry after ${header ?? 'unknown'}s. ` +\n `This is admission control, not an outage.`,\n 503,\n Number.isFinite(retryAfter) ? retryAfter : undefined\n );\n }\n throw new TrafficStreamError(`GET /events failed: ${response.status} - ${body}`, response.status);\n }\n\n if (!response.body) {\n throw new TrafficStreamError('GET /events returned no body to stream', response.status);\n }\n\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n const parser = new SSEParser();\n\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) return;\n for (const frame of parser.push(decoder.decode(value, { stream: true }))) {\n const event = parseTrafficEvent(frame);\n if (event && matchesFilters(event, options)) yield event;\n }\n }\n } finally {\n // Releasing the lock lets the caller's `break` actually close the socket\n // instead of leaking a half-read response.\n reader.releaseLock();\n }\n}\n","/**\n * uvd-x402-sdk - ERC-8128 HTTP Message Signature Signer\n *\n * Signs HTTP requests per ERC-8128 (Signed HTTP Requests with Ethereum,\n * RFC 9421 profile) so agents can authenticate against APIs that reject\n * API keys and only accept wallet signing (e.g. Execution Market, where\n * `EM_API_KEYS_ENABLED=false` in production).\n *\n * Flow:\n * 1. Fetch a fresh single-use nonce from the server (`fetchNonce`)\n * 2. Build the RFC 9421 signature base from request components\n * 3. Sign with EIP-191 personal_sign\n * 4. Produce `Signature` + `Signature-Input` (+ `Content-Digest`) headers\n *\n * Wire format: pinned by the F3-1 golden vectors (`src/erc8128.vectors.json`)\n * — `alg=\"eip191\"` always emitted, keyid ALWAYS lowercase, params in the\n * order `created;expires;nonce;keyid;alg`. Byte-equality against the vectors\n * is enforced in `src/erc8128.test.ts`.\n *\n * Three signing entry points:\n * - {@link signRequest} — raw private key (ethers Wallet), for scripts /\n * bots that hold the key in env.\n * - {@link signRequestWithWallet} — any {@link SigningWalletAdapter}\n * (EnvKeyAdapter, OWSWalletAdapter, custom); only `getAddress()` and\n * `signMessage()` are used, the key never leaves the adapter.\n * - {@link signRequestWithSigner} — callback-based, for browser wallets or\n * out-of-process signers that expose a bare EIP-191 personal_sign.\n *\n * @example Sign a single request\n * ```typescript\n * import { signRequest, fetchNonce } from 'uvd-x402-sdk';\n *\n * const nonce = await fetchNonce('https://api.execution.market');\n * const headers = await signRequest({\n * privateKey: process.env.WALLET_PRIVATE_KEY!,\n * method: 'POST',\n * url: 'https://api.execution.market/api/v1/tasks',\n * body: '{\"title\": \"test\"}',\n * nonce,\n * chainId: 8453,\n * });\n * // headers = { Signature: '...', 'Signature-Input': '...', 'Content-Digest': '...' }\n * ```\n *\n * @example Auto-signing fetch wrapper\n * ```typescript\n * import { createSignedFetch, EnvKeyAdapter } from 'uvd-x402-sdk';\n *\n * const signedFetch = createSignedFetch({\n * wallet: new EnvKeyAdapter(), // or privateKey: '...'\n * apiBase: 'https://api.execution.market',\n * });\n *\n * const resp = await signedFetch('/api/v1/tasks', {\n * method: 'POST',\n * body: JSON.stringify({ title: 'test' }),\n * });\n * ```\n *\n * Reference:\n * - ERC-8128: https://eip.tools/eip/8128\n * - RFC 9421: https://www.rfc-editor.org/rfc/rfc9421\n * - ERC-191: https://eips.ethereum.org/EIPS/eip-191\n */\n\nimport { ethers } from 'ethers';\nimport { X402Error } from './types';\nimport type { SigningWalletAdapter } from './wallet';\n\n/** Default label for ERC-8128 signatures */\nconst DEFAULT_LABEL = 'eth';\n\n/** Signature algorithm parameter — pinned by F3-1 (always emitted) */\nconst ALG = 'eip191';\n\n/** Default validity window (seconds) — server policy typically caps at 300 */\nconst DEFAULT_VALIDITY_SEC = 300;\n\n/** Default EVM chain ID for the keyid (Base mainnet, the production auth chain) */\nconst DEFAULT_CHAIN_ID = 8453;\n\n/**\n * Request components shared by every ERC-8128 signing entry point.\n */\nexport interface ERC8128RequestOptions {\n /** HTTP method (GET, POST, etc.) */\n method: string;\n /** Full URL of the request (authority + path + query are covered) */\n url: string;\n /**\n * Request body (for POST/PUT/PATCH). Omit for bodyless requests.\n * Must be byte-identical to what is sent on the wire — the\n * `Content-Digest` covers it.\n */\n body?: string;\n /** Single-use nonce from the server. Required by most servers. */\n nonce?: string;\n /** EVM chain ID for the keyid (default: 8453 = Base) */\n chainId?: number;\n /** Signature label (default: \"eth\") */\n label?: string;\n /** Signature validity window in seconds (default: 300) */\n validitySec?: number;\n}\n\nexport interface SignRequestOptions extends ERC8128RequestOptions {\n /** Hex-encoded private key (with or without 0x prefix) */\n privateKey: string;\n}\n\nexport interface SignRequestWithSignerOptions extends ERC8128RequestOptions {\n /** Signer address (any case — lowercased for the keyid per F3-1) */\n address: string;\n /**\n * EIP-191 personal_sign callback over the RFC 9421 signature base.\n * Must return the 65-byte signature (r||s||v) as 0x-prefixed hex.\n * The private key never leaves the signer (OWS vault, browser wallet).\n */\n signMessage: (signatureBase: string) => Promise<string> | string;\n}\n\nexport interface SignatureHeaders {\n Signature: string;\n 'Signature-Input': string;\n 'Content-Digest'?: string;\n}\n\n/**\n * Configuration for {@link createSignedFetch}. Provide exactly one signer:\n * a raw `privateKey` or a `wallet` adapter.\n */\nexport interface CreateSignedFetchConfig {\n /** Origin of the API (e.g. \"https://api.execution.market\") */\n apiBase: string;\n /** EVM chain ID for the keyid (default: 8453 = Base) */\n chainId?: number;\n /** Hex-encoded private key (with or without 0x prefix) */\n privateKey?: string;\n /** SigningWalletAdapter — the key never leaves the adapter */\n wallet?: SigningWalletAdapter;\n}\n\n/**\n * Sign an HTTP request per ERC-8128 with a raw private key.\n *\n * Thin wrapper over {@link signRequestWithSigner} using an ethers Wallet.\n *\n * @returns Headers to merge into the request (Signature, Signature-Input, Content-Digest).\n */\nexport async function signRequest(options: SignRequestOptions): Promise<SignatureHeaders> {\n const key = options.privateKey.startsWith('0x')\n ? options.privateKey\n : `0x${options.privateKey}`;\n const wallet = new ethers.Wallet(key);\n return signRequestWithSigner({\n address: wallet.address,\n signMessage: (signatureBase) => wallet.signMessage(signatureBase),\n method: options.method,\n url: options.url,\n body: options.body,\n nonce: options.nonce,\n chainId: options.chainId,\n label: options.label,\n validitySec: options.validitySec,\n });\n}\n\n/**\n * Sign an HTTP request per ERC-8128 with a {@link SigningWalletAdapter}.\n *\n * Only `getAddress()` and `signMessage()` (EIP-191 personal_sign) are used —\n * the private key never leaves the adapter. Works with EnvKeyAdapter,\n * OWSWalletAdapter, or any custom adapter.\n *\n * @returns Headers to merge into the request (Signature, Signature-Input, Content-Digest).\n */\nexport async function signRequestWithWallet(\n wallet: SigningWalletAdapter,\n options: ERC8128RequestOptions\n): Promise<SignatureHeaders> {\n return signRequestWithSigner({\n ...options,\n address: wallet.getAddress(),\n signMessage: (signatureBase) => wallet.signMessage(signatureBase),\n });\n}\n\n/**\n * Sign an HTTP request per ERC-8128 with a signing callback.\n *\n * For signers that never expose the raw key (OWS vault, browser wallets):\n * the callback receives the RFC 9421 signature base and returns the EIP-191\n * personal_sign signature as 0x-hex.\n *\n * @returns Headers to merge into the request (Signature, Signature-Input, Content-Digest).\n */\nexport async function signRequestWithSigner(\n options: SignRequestWithSignerOptions\n): Promise<SignatureHeaders> {\n const {\n address: rawAddress,\n signMessage,\n method,\n url,\n body,\n nonce,\n chainId = DEFAULT_CHAIN_ID,\n label = DEFAULT_LABEL,\n validitySec = DEFAULT_VALIDITY_SEC,\n } = options;\n\n // CRITICAL: lowercase — checksummed keyid caused the v9.x silent-auth INC.\n const address = rawAddress.toLowerCase();\n\n const parsed = new URL(url);\n const authority = parsed.host;\n const path = parsed.pathname || '/';\n const query = parsed.search || undefined; // includes '?' prefix\n\n const now = Math.floor(Date.now() / 1000);\n const created = now;\n const expires = now + validitySec;\n\n const keyid = `erc8128:${chainId}:${address}`;\n\n // Determine covered components\n const covered: string[] = ['@method', '@authority', '@path'];\n if (query) {\n covered.push('@query');\n }\n\n const headers: SignatureHeaders = {\n Signature: '',\n 'Signature-Input': '',\n };\n\n if (body !== undefined) {\n const digest = computeContentDigest(body);\n headers['Content-Digest'] = digest;\n covered.push('content-digest');\n }\n\n // Build signature base\n const sigBase = buildSignatureBase({\n method,\n authority,\n path,\n query,\n contentDigest: headers['Content-Digest'],\n covered,\n created,\n expires,\n nonce,\n keyid,\n });\n\n // EIP-191 personal_sign via the callback — the key stays in the signer\n const sigHex = await signMessage(sigBase);\n\n // Encode signature as base64 (RFC 8941 byte sequence)\n const sigBytes = ethers.getBytes(sigHex.startsWith('0x') ? sigHex : `0x${sigHex}`);\n const sigB64 = ethers.encodeBase64(sigBytes);\n\n // Build headers\n const sigParams = buildSignatureParams({ covered, created, expires, nonce, keyid });\n\n headers.Signature = `${label}=:${sigB64}:`;\n headers['Signature-Input'] = `${label}=${sigParams}`;\n\n return headers;\n}\n\n/**\n * Fetch a fresh single-use nonce from the server.\n *\n * @param apiBase - Origin of the API (e.g. \"https://api.execution.market\")\n * — the `/api/v1/auth/erc8128/nonce` path is appended here.\n * @param timeoutMs - Request timeout in milliseconds (default: 10000).\n * @returns The nonce value (single-use, short TTL — fetch one per request).\n */\nexport async function fetchNonce(apiBase: string, timeoutMs = 10000): Promise<string> {\n const url = `${apiBase.replace(/\\/$/, '')}/api/v1/auth/erc8128/nonce`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const resp = await fetch(url, { signal: controller.signal });\n if (!resp.ok) {\n throw new Error(`Failed to fetch nonce: ${resp.status} ${resp.statusText}`);\n }\n const data = (await resp.json()) as { nonce: string };\n return data.nonce;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/**\n * Create a fetch wrapper that auto-signs requests with ERC-8128\n * (nonce fetch + signature headers on every call).\n *\n * @example\n * ```typescript\n * const signedFetch = createSignedFetch({\n * wallet: new EnvKeyAdapter(), // or privateKey: '...'\n * apiBase: 'https://api.execution.market',\n * chainId: 8453,\n * });\n *\n * const resp = await signedFetch('/api/v1/tasks', {\n * method: 'POST',\n * body: JSON.stringify({ title: 'test' }),\n * });\n * ```\n */\nexport function createSignedFetch(config: CreateSignedFetchConfig) {\n const { apiBase, chainId, privateKey, wallet } = config;\n\n if (!privateKey && !wallet) {\n throw new X402Error(\n 'createSignedFetch requires a signer: pass privateKey or wallet.',\n 'WALLET_NOT_CONNECTED'\n );\n }\n\n return async (path: string, init?: RequestInit): Promise<Response> => {\n const url = `${apiBase.replace(/\\/$/, '')}${path}`;\n const method = (init?.method || 'GET').toUpperCase();\n const body = init?.body ? String(init.body) : undefined;\n\n // Fresh single-use nonce per request\n const nonce = await fetchNonce(apiBase);\n\n // Sign request\n const requestOptions: ERC8128RequestOptions = { method, url, body, nonce, chainId };\n const sigHeaders = wallet\n ? await signRequestWithWallet(wallet, requestOptions)\n : await signRequest({ ...requestOptions, privateKey: privateKey! });\n\n // Merge headers\n const headers = new Headers(init?.headers);\n headers.set('Signature', sigHeaders.Signature);\n headers.set('Signature-Input', sigHeaders['Signature-Input']);\n if (sigHeaders['Content-Digest']) {\n headers.set('Content-Digest', sigHeaders['Content-Digest']);\n }\n if (body) {\n headers.set('Content-Type', headers.get('Content-Type') || 'application/json');\n }\n\n return fetch(url, { ...init, headers, method });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Signature-base construction (exported: browser / out-of-process signers\n// build the exact same base and sign it elsewhere)\n// ---------------------------------------------------------------------------\n\nfunction computeContentDigest(body: string): string {\n const hash = ethers.sha256(ethers.toUtf8Bytes(body));\n // hash is 0x-prefixed hex, convert to raw bytes then base64\n const b64 = ethers.encodeBase64(ethers.getBytes(hash));\n return `sha-256=:${b64}:`;\n}\n\nexport interface SignatureBaseParams {\n method: string;\n authority: string;\n path: string;\n query?: string;\n contentDigest?: string;\n covered: string[];\n created: number;\n expires: number;\n nonce?: string;\n keyid: string;\n}\n\n/**\n * Build the RFC 9421 signature base — the exact string that gets EIP-191\n * personal_signed. Exported so external signers (OWS, browser) can reproduce\n * it byte-for-byte; pinned by the F3-1 golden vectors.\n */\nexport function buildSignatureBase(params: SignatureBaseParams): string {\n const lines: string[] = [];\n\n for (const component of params.covered) {\n switch (component) {\n case '@method':\n lines.push(`\"@method\": ${params.method.toUpperCase()}`);\n break;\n case '@authority':\n lines.push(`\"@authority\": ${params.authority}`);\n break;\n case '@path':\n lines.push(`\"@path\": ${params.path}`);\n break;\n case '@query':\n lines.push(`\"@query\": ${params.query || '?'}`);\n break;\n case 'content-digest':\n lines.push(`\"content-digest\": ${params.contentDigest || ''}`);\n break;\n }\n }\n\n const sigParams = buildSignatureParams({\n covered: params.covered,\n created: params.created,\n expires: params.expires,\n nonce: params.nonce,\n keyid: params.keyid,\n });\n lines.push(`\"@signature-params\": ${sigParams}`);\n\n return lines.join('\\n');\n}\n\nexport interface SignatureParamsInput {\n covered: string[];\n created: number;\n expires: number;\n nonce?: string;\n keyid: string;\n}\n\n/**\n * Build the `@signature-params` value per RFC 9421, in the pinned order\n * `created;expires;nonce;keyid;alg` (F3-1).\n */\nexport function buildSignatureParams(params: SignatureParamsInput): string {\n const compStr = params.covered.map((c) => `\"${c}\"`).join(' ');\n const parts: string[] = [`(${compStr})`];\n parts.push(`created=${params.created}`);\n parts.push(`expires=${params.expires}`);\n if (params.nonce) {\n parts.push(`nonce=\"${params.nonce}\"`);\n }\n parts.push(`keyid=\"${params.keyid}\"`);\n parts.push(`alg=\"${ALG}\"`);\n return parts.join(';');\n}\n","/**\n * EIP-7702: make a DELEGATED EOA's EIP-3009 signature settle again.\n *\n * **THE PROBLEM.** A gasless-wallet provider's first sponsored operation on a\n * chain may delegate the user's EOA (EIP-7702) to a smart-account\n * implementation — Alchemy's `SemiModularAccount7702` (`0x69007702…`) is the one\n * seen in the wild. From then on the address HAS code, so Circle's USDC (and any\n * `SignatureChecker` consumer) verifies signatures via **ERC-1271 only**. A raw\n * ECDSA authorization, however perfect, is rejected: `0x151d90fe`. The account is\n * not broken and the signature is not wrong — they simply no longer speak the\n * same dialect.\n *\n * Consequence for anything x402: a delegated payer's `transferWithAuthorization`\n * / `receiveWithAuthorization` becomes **unsettleable on-chain**, so direct x402\n * payments AND marketplace escrow locks both fail. Measured in production\n * 2026-07-31: 14 of 14 delegated agents failed their escrow lock; the one\n * non-delegated agent locked fine. The failure is silent in the worst way — the\n * sellers looked broken and they were correct.\n *\n * **THE FIX** (verified on-chain; the wallet provider needs to change nothing).\n * That account's `isValidSignature` DOES accept the EOA's own ECDSA — it just\n * wants it in the account's envelope. Two steps, both provable against the\n * verified source (`SemiModularAccountBase._exec1271Validation` +\n * `SparseCalldataSegmentLib`):\n *\n * 1. The account does not check `hash` directly; it checks a REPLAY-SAFE hash =\n * EIP-712 over the account's OWN domain\n * `EIP712Domain(uint256 chainId, address verifyingContract=account)` with\n * struct `ReplaySafeHash(bytes32 hash)`. Sign THAT, not the transfer digest.\n * 2. Wrap the 65-byte signature with the account's fallback-validation locator:\n * `0x00 00000000` (validation type 0, entity id 0 = FALLBACK_VALIDATION_ID)\n * `FF` (RESERVED_VALIDATION_DATA_INDEX, the final segment) `00`\n * (SignatureType.EOA).\n *\n * Because step 1 is still an ordinary typed-data signature, a REMOTE signer (a\n * delegated agentic wallet) can produce it: the private key is never needed\n * locally.\n *\n * **THE WRAP IS DELEGATE-SPECIFIC, NOT \"delegated == wrap\".** This is the part\n * that bit us on 2026-08-25, and it is why this module exists in TypeScript at\n * all: the moment a worker rates an agent through the facilitator's EIP-7702\n * feedback rail, their EOA becomes delegated to Execution Market's\n * `FeedbackDelegate` — which validates PLAIN ECDSA\n * (`ECDSA.recover(hash, sig) == address(this)`). Wrapping that signature makes it\n * invalid, so *the act of rating would break the rater's next payment*. Same\n * silent-at-lock-time failure the wrap was built to fix, now caused by\n * over-applying it.\n *\n * **DETECTION IS INJECTABLE, ON PURPOSE.** Knowing whether an address is\n * delegated needs one `eth_getCode` — a chain read, and this SDK does not own an\n * RPC policy. So detection is a callable you pass in ({@link DelegationResolver}).\n * {@link rpcDelegationResolver} ships a default over `fetch`; a caller with its\n * own endpoints, proxy or rotation passes its own.\n *\n * **THE THIRD STATE IS LOAD-BEARING.** A resolver returns `true` / `false` /\n * **`null` = could not tell**. `null` must never collapse to \"not delegated\":\n * that is exactly how the original bug survived eight days — the resolver failed,\n * returned nothing, and the caller's `if (delegated)` read it as falsy and signed\n * raw. **An unreadable answer is not a negative answer.**\n *\n * Port of `uvd_x402_sdk.erc7702` (Python). Keep the two in step: they are the\n * same protocol seen from two languages, and a divergence here is a signature\n * that cannot settle.\n */\n\n/** EIP-7702 delegation designator. */\nexport const DELEGATE_PREFIX = 'ef0100';\n\n/**\n * Delegate targets whose ERC-1271 needs the account-envelope wrap.\n *\n * Only a known Alchemy SMA implementation needs it. Every other delegate signs\n * PLAIN (the standard 1271 \"smart-EOA\" pattern accepts the EOA's own ECDSA), and\n * if some exotic future delegate needs a third dialect it fails VISIBLY at lock\n * time — never silently.\n *\n * Notably NOT here: Execution Market's `FeedbackDelegate` (all nine deploys). An\n * account that has rated through the facilitator's rail is delegated to it and\n * must sign plain.\n */\nexport const SMA_WRAP_TARGETS: readonly string[] = [\n '0x69007702764179f14f51cdce752f4f775d74e139', // Alchemy SemiModularAccount7702\n];\n\n/**\n * `true` only when this delegate target needs the account-envelope wrap.\n *\n * A plain EOA (`target` null/undefined) and any other delegate — FeedbackDelegate,\n * a standard 1271 smart-EOA — do NOT: they take the ordinary ECDSA signature.\n */\nexport function needsAccountWrap(target: string | null | undefined): boolean {\n return !!target && SMA_WRAP_TARGETS.includes(target.toLowerCase());\n}\n\n/**\n * Account fallback-validation locator + final-segment marker + EOA signature type.\n *\n * - `0x00 00000000` — validation type 0, entity id 0 (FALLBACK_VALIDATION_LOOKUP_KEY)\n * - `0xFF` — RESERVED_VALIDATION_DATA_INDEX (getFinalSegment)\n * - `0x00` — SignatureType.EOA\n */\nconst WRAP_PREFIX = '00000000' + '00' + 'ff' + '00';\n\n/**\n * The delegate target this EOA's EIP-7702 code points at, or `null`.\n *\n * `null` for a plain EOA, for non-7702 code, and for anything unparseable — the\n * caller confirms the implementation before applying the wrap.\n */\nexport function delegateTarget(code: string | null | undefined): string | null {\n if (!code) return null;\n const h = (code.startsWith('0x') ? code.slice(2) : code).toLowerCase();\n if (!h.startsWith(DELEGATE_PREFIX) || h.length < 46) return null;\n return `0x${h.slice(6, 46)}`;\n}\n\n/** Wrap a 65-byte ECDSA signature in the account's fallback-EOA envelope. */\nexport function wrapSignature(innerSignature: string): string {\n const s = innerSignature.startsWith('0x') ? innerSignature.slice(2) : innerSignature;\n return `0x${WRAP_PREFIX}${s}`;\n}\n\n/**\n * The typed data whose signature the delegated account accepts.\n *\n * The domain is the ACCOUNT's own — `chainId` + `verifyingContract=account`, the\n * two fields its typehash declares — and the struct is\n * `ReplaySafeHash(bytes32 hash)` over the inner EIP-3009 digest. Signing THIS,\n * not the digest, is what validates.\n */\nexport function replaySafeTypedData(\n innerDigest: string,\n chainId: number,\n account: string\n): { domain: Record<string, unknown>; types: Record<string, unknown>; message: Record<string, unknown> } {\n return {\n domain: { chainId, verifyingContract: account },\n types: { ReplaySafeHash: [{ name: 'hash', type: 'bytes32' }] },\n message: { hash: innerDigest },\n };\n}\n\n/**\n * `(address, network) -> target | true | false | null`.\n *\n * Four answers, richer than a boolean on purpose: a resolver MAY return the\n * delegate **target address** (a string) instead of just `true` — that is what\n * lets the caller pick the right signing dialect (SMA wrap vs plain). `true` =\n * delegated, target unknown; `false` = not delegated; `null` = UNKNOWN\n * (unreadable chain), never \"no\".\n */\nexport type DelegationResolver = (\n address: string,\n network: string\n) => Promise<string | boolean | null> | (string | boolean | null);\n\n/**\n * A default resolver over plain JSON-RPC `eth_getCode`, using `fetch`.\n *\n * Rotates through `urls` and returns `null` when **every** endpoint failed: an\n * unreadable chain is not a \"not delegated\" verdict.\n *\n * A caller with its own RPC policy (a signed proxy, paid endpoints, per-chain\n * routing) should pass its own resolver instead; that is the whole point of the\n * injection.\n */\nexport function rpcDelegationResolver(\n urls: string | string[],\n timeoutMs = 6000\n): DelegationResolver {\n const endpoints = typeof urls === 'string' ? [urls] : [...urls];\n\n return async (address: string): Promise<string | boolean | null> => {\n const addr = (address || '').trim();\n if (!addr || endpoints.length === 0) return null;\n\n for (const url of endpoints) {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = 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_getCode',\n params: [addr.toLowerCase(), 'latest'],\n }),\n signal: controller.signal,\n });\n clearTimeout(timer);\n if (!res.ok) continue;\n const code = (await res.json())?.result;\n if (typeof code === 'string' && code.startsWith('0x')) {\n // Return the TARGET when delegated, so the caller can pick the signing\n // dialect; `false` for a plain EOA (readable, no delegation).\n return delegateTarget(code) ?? false;\n }\n } catch {\n clearTimeout(timer);\n // Rotate to the next endpoint. Exhausting them all is UNKNOWN, below.\n }\n }\n return null;\n };\n}\n\n/** `{ delegated, target }` for one address on one network. */\nexport interface DelegationVerdict {\n /** `null` = UNKNOWN. Never treat it as `false`. */\n delegated: boolean | null;\n /** The delegate implementation, when the resolver could name it. */\n target: string | null;\n}\n\n/**\n * Resolve one address's delegation on one network.\n *\n * - `{delegated: null, target: null}` — unknown (no resolver, or an unreadable\n * chain). NEVER \"no\".\n * - `{delegated: false, target: null}` — a plain EOA.\n * - `{delegated: true, target: '0x…'}` — delegated, and we know to WHAT (pick the\n * dialect from it).\n * - `{delegated: true, target: null}` — delegated, target unknown (a legacy\n * boolean-only resolver).\n */\nexport async function resolveDelegation(\n address: string,\n network: string,\n resolver?: DelegationResolver\n): Promise<DelegationVerdict> {\n if (!resolver) return { delegated: null, target: null };\n\n let v: string | boolean | null;\n try {\n v = await resolver(address, network);\n } catch {\n // A broken resolver is UNKNOWN, not a negative.\n return { delegated: null, target: null };\n }\n\n if (typeof v === 'string') {\n const t = v.trim();\n // Only a real 20-byte address counts as a target. A non-address string is\n // garbage, and garbage is UNKNOWN — never a verdict we sign on.\n if (/^0x[0-9a-fA-F]{40}$/.test(t)) return { delegated: true, target: t };\n return { delegated: null, target: null };\n }\n if (typeof v === 'boolean') return { delegated: v, target: null };\n return { delegated: null, target: null };\n}\n\n/**\n * `true` / `false` / `null` (**unknown**) for one address on one network.\n *\n * Without a resolver the answer is `null`, never `false`: \"nobody asked\" and \"the\n * address is a plain EOA\" are different facts and only one of them is safe to\n * sign on.\n */\nexport async function isDelegated(\n address: string,\n network: string,\n resolver?: DelegationResolver\n): Promise<boolean | null> {\n return (await resolveDelegation(address, network, resolver)).delegated;\n}\n","/**\n * uvd-x402-sdk - Escrow Pre-Auth Builder (sign-on-assignment)\n *\n * Builds and signs the EIP-3009 `ReceiveWithAuthorization` that locks a\n * bounty in the x402r AuthCaptureEscrow, and packs it into the raw-JSON\n * `X-Payment-Auth` wrapper the Ultravioleta Facilitator's `/settle` expects.\n * Used by marketplaces built on the escrow rail (e.g. Execution Market's\n * universal escrow, ADR-002).\n *\n * >>> PROTOCOL CONSTRAINT <<<\n * The EIP-3009 nonce is `AuthCaptureEscrow.getHash(paymentInfo)` which\n * INCLUDES the receiver — the escrow signature can only be created AT\n * ASSIGNMENT, when the worker/payee is known. Never design flows that sign\n * an escrow auth before the receiver is chosen (\"stored pre-auth with late\n * receiver fill\" is on-chain unsound).\n *\n * Fail-loud policy: an incomplete network config, an unknown tier, a bounty\n * outside the on-chain deposit limit, or a `maxFeeBps` that cannot cover the\n * operator's static fee all throw instead of falling back — a silent\n * fallback would sign an EIP-3009 authorization with the WRONG EIP-712\n * domain (chainId + verifyingContract): a mismatched, wallet-draining auth.\n *\n * Wire format is pinned by golden vectors (`src/escrow-preauth.vectors.json`):\n * payer-zeroed raw-keccak nonce (`keccak(chainId, escrow,\n * keccak(PAYMENT_INFO_TYPEHASH, paymentInfo tuple with payer=0))`),\n * `ReceiveWithAuthorization` typed data, raw JSON (NOT base64) wrapper.\n * Byte-parity with the production references is enforced in\n * `src/escrow-preauth.test.ts`.\n *\n * @example Sign the escrow lock at assignment time\n * ```typescript\n * import { buildEscrowPreAuth, EnvKeyAdapter } from 'uvd-x402-sdk';\n *\n * // Server-published escrow config (e.g. GET /api/v1/h2a/payment-config\n * // on Execution Market — escrow_networks[network]).\n * const paymentAuth = await buildEscrowPreAuth(new EnvKeyAdapter(), {\n * networkConfig: config.escrow.networks.base,\n * payerWallet: '0xPublisher...',\n * workerWallet: '0xWorker...', // committed by the nonce\n * bountyAtomic: '100000', // $0.10 in 6-decimal USDC\n * reviewDeadlineSec: taskDeadlineEpoch,\n * });\n * // Send as the X-Payment-Auth header (raw JSON, NOT base64).\n * ```\n *\n * Reference implementations (kept in byte-parity via the shared vectors):\n * - Python: `em_plugin_sdk.escrow_signing.build_escrow_pre_auth`\n * (production reference, derived from `uvd_x402_sdk.advanced_escrow`)\n * - Browser (viem): Execution Market `dashboard/src/services/h2aSigning.ts`\n */\n\nimport { ethers } from 'ethers';\nimport { X402Error } from './types';\nimport {\n needsAccountWrap,\n replaySafeTypedData,\n resolveDelegation,\n wrapSignature,\n type DelegationResolver,\n} from './erc7702.js';\n\nconst ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\nconst USDC_DECIMALS = 6;\n\n/** AuthCaptureEscrow deposit condition: $100 max per deposit. */\nexport const ESCROW_DEPOSIT_LIMIT_USD = 100;\n\n/**\n * StaticFeeCalculator: canonical 13% flat fee. The signed maxFeeBps MUST\n * cover it or the on-chain release reverts.\n */\nexport const OPERATOR_FEE_BPS = 1300;\n\n/** Fee-bound defaults for optional config keys only — never for the domain. */\nconst DEFAULT_MIN_FEE_BPS = 0;\nconst DEFAULT_MAX_FEE_BPS = 1800;\n\n/**\n * EIP-712 type for the escrow flow. The token collector pulls the funds, so\n * the scheme is ReceiveWithAuthorization (not TransferWithAuthorization).\n */\nconst RECEIVE_WITH_AUTHORIZATION_TYPES = {\n ReceiveWithAuthorization: [\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/**\n * ABI type of the paymentInfo tuple — mirrors AdvancedEscrowClient /\n * em_plugin_sdk.escrow_signing (unnamed components, positional encoding).\n */\nconst PAYMENT_INFO_TUPLE =\n 'tuple(address,address,address,address,uint120,uint48,uint48,uint48,uint16,uint16,address,uint256)';\n\n/** Per-tier expiry windows in seconds, relative to now() at signing. */\nexport interface EscrowTierWindows {\n pre: number;\n auth: number;\n refund: number;\n}\n\n/** Canonical fallback — mirrors uvd_x402_sdk TIER_TIMINGS. */\nexport const ESCROW_TIER_WINDOWS: Record<string, EscrowTierWindows> = {\n micro: { pre: 3600, auth: 7200, refund: 86400 },\n standard: { pre: 7200, auth: 86400, refund: 604800 },\n};\n\n/**\n * Human review windows. Agents approve in seconds, so the short SDK tier\n * windows (micro auth = 2h) work for them. A HUMAN publisher reviews on\n * their own schedule — if authorizationExpiry passes before approval, the\n * on-chain release REVERTS (AfterAuthorizationExpiry). So release/refund\n * windows are extended to comfortably outlast the deadline + review buffer.\n */\nexport const REVIEW_WINDOW_SEC = 7 * 24 * 3600; // >=7 days to approve after the deadline\nexport const REFUND_WINDOW_SEC = 7 * 24 * 3600; // +7 days to refund after that\n\n/**\n * One network's escrow parameters, as published by the marketplace server\n * (e.g. Execution Market's `GET /api/v1/h2a/payment-config` →\n * `escrow_networks[network]`). Snake_case on purpose: pass the server's\n * JSON straight through so the SDK builds the paymentInfo EXACTLY like the\n * production reference.\n */\nexport interface EscrowNetworkConfig {\n chain_id: number;\n operator: string;\n escrow: string;\n token_collector: string;\n usdc: string;\n usdc_domain_name: string;\n usdc_domain_version: string;\n /** 32-byte hex PAYMENT_INFO_TYPEHASH (with or without 0x prefix). */\n payment_info_typehash: string;\n /** Server-published tier windows; falls back to ESCROW_TIER_WINDOWS. */\n tiers?: Record<string, EscrowTierWindows>;\n min_fee_bps?: number;\n max_fee_bps?: number;\n}\n\n/** paymentInfo exactly as serialized in the X-Payment-Auth wrapper. */\nexport interface EscrowPaymentInfo {\n operator: string;\n receiver: string;\n token: string;\n /** Atomic units, as string (uint120 on-chain). */\n maxAmount: string;\n preApprovalExpiry: number;\n authorizationExpiry: number;\n refundExpiry: number;\n minFeeBps: number;\n maxFeeBps: number;\n feeReceiver: string;\n /** 32-byte hex. */\n salt: string;\n}\n\nconst REQUIRED_NETWORK_KEYS: Array<keyof EscrowNetworkConfig> = [\n 'chain_id',\n 'operator',\n 'escrow',\n 'token_collector',\n 'usdc',\n 'usdc_domain_name',\n 'usdc_domain_version',\n 'payment_info_typehash',\n];\n\nfunction hex32(value: string): string {\n return value.startsWith('0x') ? value : `0x${value}`;\n}\n\n/** 32 random bytes as 0x-hex (WebCrypto when available, ethers otherwise). */\nfunction randomSalt(): string {\n const webCrypto = (globalThis as { crypto?: Crypto }).crypto;\n if (webCrypto?.getRandomValues) {\n const bytes = new Uint8Array(32);\n webCrypto.getRandomValues(bytes);\n return ethers.hexlify(bytes);\n }\n return ethers.hexlify(ethers.randomBytes(32));\n}\n\n/**\n * Compute the escrow EIP-3009 nonce = `AuthCaptureEscrow.getHash(paymentInfo)`.\n *\n * `keccak(chainId, escrow, keccak(PAYMENT_INFO_TYPEHASH, paymentInfo tuple\n * with payer=0))` — the payer slot is zeroed for the payer-agnostic hash;\n * the RECEIVER is part of the hash, which is why the signature commits to\n * the chosen worker. Port of `AdvancedEscrowClient._compute_nonce` /\n * `em_plugin_sdk.escrow_signing.compute_escrow_nonce`.\n *\n * @param chainId - EVM chain id.\n * @param escrowAddress - AuthCaptureEscrow contract on that chain.\n * @param paymentInfoTypehash - 32-byte hex typehash from the server config.\n * @param pi - paymentInfo exactly as serialized on the wire.\n * @returns 32-byte hex nonce (0x-prefixed, lowercase).\n */\nexport function computeEscrowNonce(\n chainId: number,\n escrowAddress: string,\n paymentInfoTypehash: string,\n pi: EscrowPaymentInfo\n): string {\n const coder = ethers.AbiCoder.defaultAbiCoder();\n\n const piTuple = [\n ethers.getAddress(pi.operator),\n ZERO_ADDRESS, // payer = 0 for the payer-agnostic hash\n ethers.getAddress(pi.receiver),\n ethers.getAddress(pi.token),\n BigInt(pi.maxAmount), // uint120\n pi.preApprovalExpiry, // uint48\n pi.authorizationExpiry, // uint48\n pi.refundExpiry, // uint48\n pi.minFeeBps, // uint16\n pi.maxFeeBps, // uint16\n ethers.getAddress(pi.feeReceiver),\n BigInt(hex32(pi.salt)), // uint256\n ];\n\n const piHash = ethers.keccak256(\n coder.encode(['bytes32', PAYMENT_INFO_TUPLE], [hex32(paymentInfoTypehash), piTuple])\n );\n return ethers.keccak256(\n coder.encode(\n ['uint256', 'address', 'bytes32'],\n [chainId, ethers.getAddress(escrowAddress), piHash]\n )\n );\n}\n\n/**\n * Minimal signer for {@link buildEscrowPreAuth}: EIP-712 typed-data signing\n * over the full typed-data JSON string (`domain`, `types`, `primaryType`,\n * `message`) — the same contract as `SigningWalletAdapter.signTypedData`,\n * so every adapter (EnvKeyAdapter, OWSWalletAdapter, custom) satisfies it\n * structurally. Browser wallets can wrap their own signTypedData in this\n * shape; the key never leaves the signer.\n */\nexport interface EscrowPreAuthSigner {\n signTypedData(typedData: string): Promise<{ signature: string }>;\n}\n\nexport interface EscrowPreAuthParams {\n /** Network escrow config as published by the marketplace server. */\n networkConfig: EscrowNetworkConfig;\n /**\n * Publisher wallet (payer). Not checked against the signer's address —\n * payer binding is enforced on-chain and by the backend, not here.\n */\n payerWallet: string;\n /** Chosen worker's wallet (escrow receiver — committed by the nonce). */\n workerWallet: string;\n /** Bounty in atomic units (6-decimal USDC). */\n bountyAtomic: string | bigint;\n /** Expiry tier; windows come from config when present. Default 'micro'. */\n tier?: string;\n /**\n * Task deadline (epoch seconds). The release/refund windows are extended\n * to outlast it + a review buffer so a human publisher can still approve\n * after the worker delivers. When omitted, falls back to now()-based\n * windows.\n */\n reviewDeadlineSec?: number;\n /**\n * On-chain deposit limit in USD (AuthCaptureEscrow deposit condition).\n * Default {@link ESCROW_DEPOSIT_LIMIT_USD}; override only when the server\n * publishes a different limit.\n */\n depositLimitUsd?: number;\n /**\n * How to find out whether `payerWallet` is EIP-7702-delegated, and to what.\n *\n * Optional, and its absence is honest rather than convenient: with no resolver\n * the verdict is UNKNOWN and this function signs the ordinary way, exactly as\n * it did before. Pass one — {@link rpcDelegationResolver} or your own — as soon\n * as your payers can be delegated accounts, because a delegated payer signing\n * the wrong dialect produces an authorization that **cannot settle on-chain**\n * and only fails at lock time.\n *\n * When a resolver IS supplied and it reaches no verdict, this throws instead of\n * guessing: an unreadable chain is not a \"not delegated\" answer.\n */\n delegationResolver?: DelegationResolver;\n}\n\n/**\n * Build + sign the escrow lock authorization AT ASSIGNMENT time and return\n * the raw JSON string for the `X-Payment-Auth` header (NOT base64 — the\n * backend relays it verbatim to the Facilitator `/settle`). Mirror of\n * `AdvancedEscrowClient.authorize()`'s /settle payload and of\n * `em_plugin_sdk.escrow_signing.build_escrow_pre_auth`.\n *\n * @throws {X402Error} `INVALID_CONFIG` on an incomplete network config,\n * unknown tier, or a `maxFeeBps` that cannot cover the operator's static\n * fee; `INVALID_AMOUNT` on a bounty outside (0, deposit limit].\n */\nexport async function buildEscrowPreAuth(\n wallet: EscrowPreAuthSigner,\n params: EscrowPreAuthParams\n): Promise<string> {\n const cfg = params.networkConfig;\n\n const missing = REQUIRED_NETWORK_KEYS.filter((key) => !cfg[key]);\n if (missing.length > 0) {\n throw new X402Error(\n `Incomplete escrow network config (missing ${missing.join(', ')}) — ` +\n 'refusing to sign an EIP-3009 authorization with a mismatched domain.',\n 'INVALID_CONFIG'\n );\n }\n\n const maxAmount = BigInt(params.bountyAtomic);\n if (maxAmount <= 0n) {\n throw new X402Error(\n `Bounty must be positive, got ${maxAmount} atomic units`,\n 'INVALID_AMOUNT'\n );\n }\n const depositLimitUsd = params.depositLimitUsd ?? ESCROW_DEPOSIT_LIMIT_USD;\n const depositLimitAtomic = BigInt(Math.round(depositLimitUsd * 10 ** USDC_DECIMALS));\n if (maxAmount > depositLimitAtomic) {\n throw new X402Error(\n `Bounty ${maxAmount} atomic units exceeds the on-chain escrow deposit ` +\n `limit ($${depositLimitUsd}).`,\n 'INVALID_AMOUNT'\n );\n }\n\n const minFeeBps = cfg.min_fee_bps ?? DEFAULT_MIN_FEE_BPS;\n const maxFeeBps = cfg.max_fee_bps ?? DEFAULT_MAX_FEE_BPS;\n if (maxFeeBps < OPERATOR_FEE_BPS) {\n throw new X402Error(\n `maxFeeBps=${maxFeeBps} cannot cover the operator's ${OPERATOR_FEE_BPS} ` +\n 'bps static fee — the on-chain release would revert.',\n 'INVALID_CONFIG'\n );\n }\n\n const tierKey = params.tier ?? 'micro';\n const windows = cfg.tiers?.[tierKey] ?? ESCROW_TIER_WINDOWS[tierKey];\n if (!windows) {\n const known = [...new Set([...Object.keys(cfg.tiers ?? {}), ...Object.keys(ESCROW_TIER_WINDOWS)])].sort();\n throw new X402Error(\n `Unknown escrow tier '${tierKey}' — known tiers: ${known.join(', ')}`,\n 'INVALID_CONFIG'\n );\n }\n\n const now = Math.floor(Date.now() / 1000);\n\n // The release window must outlast the human review. Base it on the task\n // deadline (the worker delivers near it) plus a generous buffer, and never\n // shorter than the SDK tier window. preApprovalExpiry stays short — the\n // lock executes immediately at assignment.\n const reviewBase = Math.max(now, params.reviewDeadlineSec ?? now);\n const authExpiry = Math.max(now + windows.auth, reviewBase + REVIEW_WINDOW_SEC);\n const refundExpiry = Math.max(now + windows.refund, authExpiry + REFUND_WINDOW_SEC);\n\n const paymentInfo: EscrowPaymentInfo = {\n operator: ethers.getAddress(cfg.operator),\n receiver: ethers.getAddress(params.workerWallet),\n token: ethers.getAddress(cfg.usdc),\n maxAmount: maxAmount.toString(),\n preApprovalExpiry: now + windows.pre,\n authorizationExpiry: authExpiry,\n refundExpiry: refundExpiry,\n minFeeBps: minFeeBps,\n maxFeeBps: maxFeeBps,\n feeReceiver: ethers.getAddress(cfg.operator),\n salt: randomSalt(),\n };\n\n const nonce = computeEscrowNonce(\n cfg.chain_id,\n cfg.escrow,\n cfg.payment_info_typehash,\n paymentInfo\n );\n\n const payer = ethers.getAddress(params.payerWallet);\n const tokenCollector = ethers.getAddress(cfg.token_collector);\n\n // String-valued message fields: the typed data travels as JSON to the\n // adapter (SigningWalletAdapter.signTypedData contract), and ethers\n // accepts decimal strings for uint256 / 0x-hex for bytes32.\n const typedData = {\n domain: {\n name: cfg.usdc_domain_name,\n version: cfg.usdc_domain_version,\n chainId: cfg.chain_id,\n verifyingContract: ethers.getAddress(cfg.usdc),\n },\n types: RECEIVE_WITH_AUTHORIZATION_TYPES,\n primaryType: 'ReceiveWithAuthorization',\n message: {\n from: payer,\n to: tokenCollector,\n value: maxAmount.toString(),\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce: nonce,\n },\n };\n\n // ── EIP-7702: a DELEGATED payer cannot settle a raw ECDSA authorization ──\n //\n // Once the payer's EOA carries code, USDC validates via ERC-1271 only and raw\n // ECDSA reverts (0x151d90fe) — the lock fails on-chain. Measured in production\n // 2026-07-31: 14 of 14 delegated payers failed; the one plain EOA locked fine.\n //\n // THREE STATES, and the third is the one that matters: an UNKNOWN delegation is\n // NOT \"not delegated\". Collapsing it to false is exactly how the original bug\n // survived eight days — signing raw for an account that can never settle it,\n // silently.\n //\n // AND THE DIALECT DEPENDS ON THE TARGET. \"Delegated\" is not one signature\n // scheme: the account-envelope wrap is Alchemy-SMA-specific. A delegate that\n // validates plain ECDSA through ERC-1271 — Execution Market's FeedbackDelegate,\n // which every account that has rated through the facilitator's rail is pointed\n // at — needs the ORDINARY signature. Wrapping it is as unsettleable as signing\n // raw for an SMA.\n const { delegated, target } = await resolveDelegation(\n payer,\n `eip155:${cfg.chain_id}`,\n params.delegationResolver\n );\n if (delegated === null && params.delegationResolver) {\n throw new X402Error(\n `Could not determine whether ${payer} is EIP-7702-delegated on chain ` +\n `${cfg.chain_id} (the resolver gave no verdict) — refusing to sign an ` +\n 'escrow authorization blindly: the wrong dialect is unsettleable ' +\n 'on-chain and the failure only shows up at lock time. Retry when the ' +\n 'chain is readable.',\n 'INVALID_CONFIG'\n );\n }\n\n let signature: string;\n if (delegated && (needsAccountWrap(target) || target === null)) {\n // SMA-wrap: the known Alchemy account, OR a legacy boolean-only resolver that\n // could not name the target — for which we keep the conservative behaviour\n // rather than silently changing what such callers got. A resolver that\n // returns the target lands any non-SMA delegate in the plain branch below.\n const innerDigest = ethers.TypedDataEncoder.hash(\n typedData.domain,\n typedData.types,\n typedData.message\n );\n const replaySafe = replaySafeTypedData(innerDigest, cfg.chain_id, payer);\n const wrapped = await wallet.signTypedData(\n JSON.stringify({ ...replaySafe, primaryType: 'ReplaySafeHash' })\n );\n if (!wrapped?.signature) {\n throw new X402Error(\n 'The wallet returned no signature for the replay-safe wrap — refusing ' +\n 'to build an unsettleable authorization.',\n 'INVALID_CONFIG'\n );\n }\n signature = wrapSignature(wrapped.signature);\n } else {\n // Plain EOA, unknown-with-no-resolver, or a delegate that takes ordinary\n // ECDSA (FeedbackDelegate and the standard 1271 smart-EOA pattern).\n signature = (await wallet.signTypedData(JSON.stringify(typedData))).signature;\n }\n\n // Raw JSON (NOT base64): the backend relays this verbatim to the\n // Facilitator /settle after validating payer/amount/receiver.\n return JSON.stringify({\n x402Version: 2,\n scheme: 'escrow',\n payload: {\n authorization: {\n from: payer,\n to: tokenCollector,\n value: maxAmount.toString(),\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce: nonce,\n },\n signature: signature,\n paymentInfo: paymentInfo,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${cfg.chain_id}`,\n },\n });\n}\n","/**\n * Reading a facilitator refusal as DATA instead of prose.\n *\n * # Why this file exists\n *\n * `402` and `503` say opposite things and the SDK used to collapse both into\n * `success: false` plus an English sentence.\n *\n * - **402** means the payment was REJECTED. The credential is spent; sign a new\n * authorization.\n * - **503** means NO VERDICT WAS REACHED. Nothing was rejected and nothing was\n * executed; retry the SAME credential.\n *\n * Turning a 503 into a 402 makes the buyer sign and send a second payment for a\n * money movement that was never refused — they pay twice. That is the most\n * expensive mistake this SDK can make, so every facilitator edge now reports the\n * status, the facilitator's own `reason`, and whether the request may be\n * replayed.\n *\n * # The writer lease\n *\n * The facilitator serialises every EVM write through the one process that holds\n * the EVM writer lease, because they all spend gas from the same EOA and the\n * nonce for it is allocated in memory. A task that does not hold the lease\n * forwards the request to the one that does; when it cannot, it answers\n * `503` + `Retry-After: 5` + `{\"error\": \"...\", \"reason\": \"<why>\"}`.\n *\n * The five reasons do NOT share retry semantics, which is the whole point of\n * surfacing them:\n *\n * | reason | did the write run? | replay? |\n * |----------------------------|--------------------|---------|\n * | `holder_unknown` | no | yes |\n * | `forwarding_disabled` | no | yes |\n * | `forwarded_but_not_writer` | no | yes |\n * | `body_unreadable` | no | yes |\n * | `forward_failed` | **maybe** | **no** |\n *\n * `forward_failed` is emitted after the forward was attempted: the holder may\n * have executed the write and the response been lost on the way back. It is a\n * timeout wearing a status code. Replaying a `/register` on it is exactly the\n * sequence that once minted five duplicate agents — reconcile with\n * `GET /identity/{network}/owner/{recipient}` or `getRegisterStatus` instead.\n *\n * Source of the shape: x402-rs `src/handlers.rs` `writer_lease_unavailable()`\n * and `require_writer_lease()`.\n */\n\n/**\n * A `reason` the facilitator attaches to a writer-lease 503.\n *\n * Typed as a union for discrimination but never used to VALIDATE: the fields\n * that carry it are plain `string`, so a reason added on the server does not\n * break compilation here.\n */\nexport type WriterLeaseReason =\n | 'holder_unknown'\n | 'forwarding_disabled'\n | 'forwarded_but_not_writer'\n | 'body_unreadable'\n | 'forward_failed';\n\n/** Every writer-lease reason the facilitator emits today. */\nexport const WRITER_LEASE_REASONS: readonly WriterLeaseReason[] = [\n 'holder_unknown',\n 'forwarding_disabled',\n 'forwarded_but_not_writer',\n 'body_unreadable',\n 'forward_failed',\n];\n\n/**\n * The reasons returned BEFORE the write is handed to anyone.\n *\n * The facilitator refuses these in its router, so the request provably did not\n * execute and re-sending the identical body is safe — including a mint.\n */\nexport const REPLAYABLE_LEASE_REASONS: readonly WriterLeaseReason[] = [\n 'holder_unknown',\n 'forwarding_disabled',\n 'forwarded_but_not_writer',\n 'body_unreadable',\n];\n\n/**\n * The reason that is ambiguous: the write may already have happened.\n *\n * Still `retryable` — the credential was not rejected — but never replayed\n * automatically. Resolve it by reading state, not by re-POSTing.\n */\nexport const AMBIGUOUS_LEASE_REASONS: readonly WriterLeaseReason[] = ['forward_failed'];\n\n/**\n * Ceiling, in seconds, on how long an automatic retry will wait.\n *\n * `Retry-After` is a hint from a server that may be misconfigured. Honouring a\n * literal `Retry-After: 3600` would hang the caller's request for an hour\n * inside a function documented as returning promptly, so the header is honoured\n * only up to this bound.\n */\nexport const MAX_RETRY_AFTER_SECONDS = 15;\n\n/** Wait used when a 503 carries no usable `Retry-After`. */\nexport const DEFAULT_RETRY_AFTER_SECONDS = 5;\n\n/** How many EXTRA attempts a retryable facilitator refusal gets by default. */\nexport const DEFAULT_FACILITATOR_RETRIES = 2;\n\n/**\n * A non-2xx answer from the facilitator, kept structured.\n *\n * `error` is byte-identical to the string this SDK has always produced, so\n * callers matching on it keep working; everything else is new and optional.\n */\nexport interface FacilitatorErrorInfo {\n /** Legacy flattened message: `Facilitator error: <status> - <body>`. */\n error: string;\n /** HTTP status the facilitator answered with. */\n status: number;\n /** The facilitator's own `reason`, when the body carried one. */\n reason?: string;\n /**\n * Seconds to wait before retrying, already clamped to\n * {@link MAX_RETRY_AFTER_SECONDS}. Absent when the answer is not retryable.\n */\n retryAfterSeconds?: number;\n /**\n * The request reached no verdict; the credential is untouched and the SAME\n * request may be sent again. Never surface this as a payment rejection.\n */\n retryable: boolean;\n /**\n * The facilitator NAMED a reason that proves it executed nothing, so an\n * automatic replay cannot double-write.\n *\n * False for `forward_failed`, whose write may already have landed, and false\n * for an unattributed 5xx from a proxy — \"something in front answered\" is not\n * evidence that nothing ran.\n */\n safeToReplay: boolean;\n /** Raw response body, for logs. */\n body: string;\n}\n\n/** Fields every facilitator response type gained so a 503 stops looking terminal. */\nexport interface FacilitatorFailureFields {\n /** HTTP status, when the failure was transport-level rather than a verdict. */\n status?: number;\n /** The facilitator's `reason` for the refusal (see {@link WriterLeaseReason}). */\n reason?: string;\n /** True when the same request may be sent again without re-signing anything. */\n retryable?: boolean;\n /** Seconds to wait before retrying, clamped to {@link MAX_RETRY_AFTER_SECONDS}. */\n retryAfterSeconds?: number;\n /** True when the facilitator provably executed nothing. */\n safeToReplay?: boolean;\n}\n\n/** A 503/429 that carries a reason known to be pre-execution. */\nexport function isReplayableLeaseReason(reason?: string): boolean {\n return REPLAYABLE_LEASE_REASONS.includes(reason as WriterLeaseReason);\n}\n\n/** A 503 whose write may already have run. Reconcile, do not re-POST. */\nexport function isAmbiguousLeaseReason(reason?: string): boolean {\n return AMBIGUOUS_LEASE_REASONS.includes(reason as WriterLeaseReason);\n}\n\n/**\n * Read `Retry-After` and clamp it.\n *\n * Tolerates a `Response`-shaped object with no `headers` at all: test doubles\n * and non-standard fetch polyfills routinely omit it, and throwing there would\n * turn a readable refusal into an unreadable crash.\n */\nexport function parseRetryAfterSeconds(response: {\n headers?: { get?: (name: string) => string | null };\n}): number | undefined {\n let raw: string | null | undefined;\n try {\n raw = response?.headers?.get?.('retry-after');\n } catch {\n return undefined;\n }\n if (raw === null || raw === undefined || raw === '') return undefined;\n const seconds = Number(raw);\n if (!Number.isFinite(seconds) || seconds < 0) return undefined;\n return Math.min(seconds, MAX_RETRY_AFTER_SECONDS);\n}\n\n/** Pull `reason` out of a JSON error body, if there is one and it is a string. */\nfunction reasonFrom(body: string): string | undefined {\n try {\n const parsed = JSON.parse(body) as { reason?: unknown };\n if (parsed && typeof parsed === 'object' && typeof parsed.reason === 'string') {\n return parsed.reason;\n }\n } catch {\n /* an HTML 503 from a load balancer is still a 503 */\n }\n return undefined;\n}\n\n/**\n * Turn a non-2xx facilitator response into {@link FacilitatorErrorInfo}.\n *\n * Reads the body exactly once. The `error` string keeps the historical format\n * verbatim; reformatting it would break callers that match on it.\n */\nexport async function readFacilitatorError(response: {\n status: number;\n text: () => Promise<string>;\n headers?: { get?: (name: string) => string | null };\n}): Promise<FacilitatorErrorInfo> {\n let body = '';\n try {\n body = await response.text();\n } catch {\n body = '';\n }\n const status = response.status;\n const reason = reasonFrom(body);\n // 429 is admission control and 502/503/504 are \"no verdict\". None of them is\n // a rejection of the payment, so none of them may be reported as one.\n const retryable = status === 429 || status === 502 || status === 503 || status === 504;\n const retryAfterSeconds = retryable\n ? (parseRetryAfterSeconds(response) ?? DEFAULT_RETRY_AFTER_SECONDS)\n : undefined;\n // Replay only what the facilitator SAID it did not execute.\n //\n // A 429 is admission control: the request was counted, never handled. A 503\n // that names one of the pre-execution writer-lease reasons is refused in the\n // router before any signing. Everything else — an unattributed 503 from a\n // load balancer, a 502, a 504, `forward_failed` — is merely retryable: the\n // caller may resend after reconciling, but this SDK will not do it for them,\n // because \"a proxy answered\" is not evidence that nothing ran.\n const safeToReplay = status === 429 || (status === 503 && isReplayableLeaseReason(reason));\n\n return {\n error: `Facilitator error: ${status} - ${body}`,\n status,\n reason,\n retryAfterSeconds,\n retryable,\n safeToReplay,\n body,\n };\n}\n\n/** The subset of {@link FacilitatorErrorInfo} that is copied onto a response. */\nexport function failureFields(info: FacilitatorErrorInfo): Required<\n Pick<FacilitatorFailureFields, 'status' | 'retryable' | 'safeToReplay'>\n> &\n FacilitatorFailureFields {\n return {\n status: info.status,\n retryable: info.retryable,\n safeToReplay: info.safeToReplay,\n ...(info.reason !== undefined ? { reason: info.reason } : {}),\n ...(info.retryAfterSeconds !== undefined\n ? { retryAfterSeconds: info.retryAfterSeconds }\n : {}),\n };\n}\n\n/**\n * Copy the failure fields off one response onto another.\n *\n * Used where a wrapper returns its own shape: without this the wrapper flattens\n * a `503` back into a bare failure and reintroduces, one level up, exactly the\n * ambiguity the fields exist to remove.\n */\nexport function carryFailureFields(\n source: FacilitatorFailureFields,\n): FacilitatorFailureFields {\n return {\n ...(source.status !== undefined ? { status: source.status } : {}),\n ...(source.reason !== undefined ? { reason: source.reason } : {}),\n ...(source.retryable !== undefined ? { retryable: source.retryable } : {}),\n ...(source.retryAfterSeconds !== undefined\n ? { retryAfterSeconds: source.retryAfterSeconds }\n : {}),\n ...(source.safeToReplay !== undefined ? { safeToReplay: source.safeToReplay } : {}),\n };\n}\n\n/** Options for {@link facilitatorFetch}. */\nexport interface FacilitatorFetchOptions {\n /** Abort the request after this many milliseconds. */\n timeoutMs: number;\n /** Extra attempts after the first. Default {@link DEFAULT_FACILITATOR_RETRIES}. */\n retries?: number;\n /**\n * Whether this particular refusal may be replayed.\n *\n * Default: only when the facilitator proved it executed nothing\n * (`info.safeToReplay`). Pass a stricter predicate on paths where even a\n * proven-safe replay is unwanted.\n */\n canReplay?: (info: FacilitatorErrorInfo) => boolean;\n /** Injected for tests. */\n fetchImpl?: typeof fetch;\n /** Injected for tests, so a retry does not really sleep. */\n sleepImpl?: (ms: number) => Promise<void>;\n}\n\nconst defaultSleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * POST/GET the facilitator, replaying a refusal that provably executed nothing.\n *\n * Returns the response plus, when it was not ok, the structured refusal — the\n * body has already been consumed to build it, so callers must not read it\n * again.\n *\n * Network errors and timeouts still THROW, exactly as before: callers already\n * have `catch` blocks that turn them into `{ success: false }`, and an\n * `AbortError` on the escrow paths triggers an on-chain reconciliation that\n * must keep firing.\n */\nexport async function facilitatorFetch(\n url: string,\n init: RequestInit,\n options: FacilitatorFetchOptions,\n): Promise<{ response: Response; error?: FacilitatorErrorInfo }> {\n const retries = options.retries ?? DEFAULT_FACILITATOR_RETRIES;\n const canReplay = options.canReplay ?? ((info: FacilitatorErrorInfo) => info.safeToReplay);\n const doFetch = options.fetchImpl ?? fetch;\n const sleep = options.sleepImpl ?? defaultSleep;\n\n let attempt = 0;\n for (;;) {\n // A fresh controller per attempt: an aborted signal stays aborted, so\n // reusing one would make every retry fail instantly.\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), options.timeoutMs);\n let response: Response;\n try {\n response = await doFetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timeoutId);\n }\n\n if (response.ok) return { response };\n\n const error = await readFacilitatorError(response);\n if (attempt >= retries || !error.retryable || !canReplay(error)) {\n return { response, error };\n }\n\n attempt += 1;\n await sleep((error.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS) * 1000);\n }\n}\n","/**\n * uvd-x402-sdk - Backend Utilities\n *\n * Server-side utilities for building x402 payment APIs.\n * These utilities help backend developers:\n * - Build verify/settle requests for the facilitator\n * - Parse X-PAYMENT headers from incoming requests\n * - Configure CORS for x402 payment flows\n * - Create atomic payment handlers\n * - Discover and register resources via Bazaar Discovery API\n * - Manage escrow payments with refund and dispute resolution\n *\n * @example Basic payment flow\n * ```ts\n * import {\n * parsePaymentHeader,\n * FacilitatorClient,\n * X402_CORS_HEADERS,\n * } from 'uvd-x402-sdk/backend';\n *\n * // Parse payment from request header\n * const payment = parsePaymentHeader(req.headers['x-payment']);\n *\n * // Verify with facilitator\n * const client = new FacilitatorClient();\n * const verifyResult = await client.verify(payment, paymentRequirements);\n *\n * // If valid, provide service then settle\n * const settleResult = await client.settle(payment, paymentRequirements);\n * ```\n *\n * @example Escrow payment with refund support\n * ```ts\n * import { EscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const escrow = new EscrowClient();\n *\n * // Hold payment in escrow\n * const escrowPayment = await escrow.createEscrow({\n * paymentHeader: req.headers['x-payment'],\n * requirements: paymentRequirements,\n * escrowDuration: 86400, // 24 hours\n * });\n *\n * // After service delivered, release to recipient\n * await escrow.release(escrowPayment.id);\n *\n * // Or if service failed, request refund\n * await escrow.requestRefund({\n * escrowId: escrowPayment.id,\n * reason: 'Service not delivered',\n * });\n * ```\n *\n * @example Resource discovery\n * ```ts\n * import { BazaarClient } from 'uvd-x402-sdk/backend';\n *\n * const bazaar = new BazaarClient();\n * const resources = await bazaar.discover({\n * category: 'ai',\n * network: 'base',\n * maxPrice: '0.10',\n * });\n * ```\n */\n\nimport type {\n X402Header,\n X402PayloadData,\n X402Version,\n} from '../types';\nimport { decodeX402Header, chainToCAIP2, parseNetworkIdentifier } from '../utils';\nimport { REVIEW_WINDOW_SEC, REFUND_WINDOW_SEC } from '../escrow-preauth';\nimport { getChainByName } from '../chains';\nimport {\n DEFAULT_RETRY_AFTER_SECONDS,\n carryFailureFields,\n isReplayableLeaseReason,\n facilitatorFetch,\n failureFields,\n readFacilitatorError,\n} from './facilitator-error';\nimport type { FacilitatorErrorInfo, FacilitatorFailureFields } from './facilitator-error';\n\n// A facilitator refusal is DATA, not prose. `402` and `503` say opposite things\n// and this file used to answer both with `success: false` plus a sentence --\n// see ./facilitator-error.ts for why that costs the buyer a second payment.\nexport {\n AMBIGUOUS_LEASE_REASONS,\n DEFAULT_FACILITATOR_RETRIES,\n DEFAULT_RETRY_AFTER_SECONDS,\n MAX_RETRY_AFTER_SECONDS,\n REPLAYABLE_LEASE_REASONS,\n WRITER_LEASE_REASONS,\n carryFailureFields,\n facilitatorFetch,\n isAmbiguousLeaseReason,\n isReplayableLeaseReason,\n parseRetryAfterSeconds,\n readFacilitatorError,\n} from './facilitator-error';\nexport type {\n FacilitatorErrorInfo,\n FacilitatorFailureFields,\n FacilitatorFetchOptions,\n WriterLeaseReason,\n} from './facilitator-error';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\n/**\n * Payment requirements sent to the facilitator\n */\nexport interface PaymentRequirements {\n /** Payment scheme */\n scheme: 'exact' | 'escrow' | 'commerce';\n /** Network name (v1) or CAIP-2 identifier (v2) */\n network: string;\n /** Maximum amount required in atomic units (e.g., \"1000000\" for 1 USDC) */\n maxAmountRequired: string;\n /** Resource URL being paid for */\n resource: string;\n /** Description of what's being paid for */\n description: string;\n /** MIME type of the resource */\n mimeType: string;\n /** Recipient address for payment */\n payTo: string;\n /** Maximum timeout in seconds */\n maxTimeoutSeconds: number;\n /** Token contract address */\n asset: string;\n /** Optional output schema for the resource */\n outputSchema?: unknown;\n /** Optional extra data */\n extra?: unknown;\n}\n\n/**\n * Verify request body for the facilitator /verify endpoint\n */\nexport interface VerifyRequest {\n x402Version: X402Version;\n paymentPayload: X402Header;\n paymentRequirements: PaymentRequirements;\n}\n\n/**\n * Settle request body for the facilitator /settle endpoint\n */\nexport interface SettleRequest {\n x402Version: X402Version;\n paymentPayload: X402Header;\n paymentRequirements: PaymentRequirements;\n}\n\n/**\n * Verify response from the facilitator\n */\nexport interface VerifyResponse extends FacilitatorFailureFields {\n isValid: boolean;\n /**\n * Why the payment is not valid.\n *\n * Read `retryable` before showing this to anyone. When `retryable` is true the\n * facilitator reached NO VERDICT -- it did not reject the payment, so this\n * string is a transport diagnosis, not a rejection, and re-signing on it makes\n * the buyer pay twice.\n */\n invalidReason?: string;\n payer?: string;\n network?: string;\n}\n\n/**\n * Settle response from the facilitator\n */\nexport interface SettleResponse extends FacilitatorFailureFields {\n success: boolean;\n transactionHash?: string;\n network?: string;\n /**\n * Transport-level failure (unreachable facilitator, non-2xx, timeout).\n *\n * `success: false` with `retryable: true` is NOT a rejected payment. The\n * authorization is untouched and the same one must be resent; treating it as\n * a refusal and asking for a new signature charges the buyer twice.\n */\n error?: string;\n /**\n * The facilitator's own reason when it settled nothing — e.g. a transfer that\n * mined and reverted. Distinct from `error` above, which is this client\n * failing to ask; this one is the facilitator answering \"no\".\n */\n errorReason?: string;\n /** The address the facilitator confirmed as the payer. */\n payer?: string;\n /**\n * Settlement proof, present when the ERC-8004 extension asked for it.\n *\n * Typed here rather than only on {@link SettleResponseWithProof} because\n * `settle()` returns it whenever the facilitator sends it, and it is what\n * DX402's `anchorEvidence` needs to reach `verified: true`.\n */\n proofOfPayment?: ProofOfPayment;\n}\n\n/**\n * Options for building payment requirements\n */\nexport interface PaymentRequirementsOptions {\n /** Amount in human-readable format (e.g., \"1.00\") */\n amount: string;\n /** Recipient address */\n recipient: string;\n /** Resource URL being protected */\n resource: string;\n /** Chain name (e.g., \"base\") */\n chainName?: string;\n /** Description of the resource */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n /** Timeout in seconds (default: 300) */\n timeoutSeconds?: number;\n /** x402 version to use */\n x402Version?: X402Version;\n}\n\n/**\n * x402 payment option advertised in a 402 response.\n *\n * The SDK keeps the response shape richer than the minimal protocol fields so\n * servers can preserve settlement-critical metadata such as payTo and extra.\n */\nexport interface PaymentAcceptance {\n network: string;\n asset: string;\n amount: string;\n /**\n * Payment scheme. REQUIRED by the facilitator's v2 `PaymentRequirementsV2`.\n *\n * Optional here only so existing callers keep compiling — when it is absent,\n * `buildRequirementFromAcceptance` defaults it to `'exact'`. Do not treat its\n * optionality as \"the facilitator does not need it\": an accepts[] entry that\n * reaches a v2 client without a scheme is unpayable.\n */\n scheme?: string;\n payTo?: string;\n facilitator?: string;\n resource?: string;\n description?: string;\n mimeType?: string;\n maxTimeoutSeconds?: number;\n outputSchema?: unknown;\n extra?: unknown;\n}\n\n/**\n * Verified payment context attached by server middleware.\n */\nexport interface VerifiedPaymentState {\n payment: X402Header;\n requirements: PaymentRequirements;\n verifyResult: VerifyResponse;\n settle: () => Promise<SettleResponse>;\n}\n\n/**\n * Shared server middleware options.\n */\nexport interface PaymentMiddlewareOptions extends FacilitatorClientOptions {\n /** Alias for baseUrl to keep middleware options ergonomic */\n facilitatorUrl?: string;\n /**\n * Settlement behavior after verification.\n * - manual: verify only; caller settles explicitly\n * - before-handler: settle immediately before calling next()\n */\n settlementStrategy?: 'manual' | 'before-handler';\n}\n\n/**\n * Custom resolver for selecting the correct payment requirement when multiple\n * accepts are advertised.\n */\nexport type PaymentRequirementResolver = (\n payment: X402Header,\n requirements: PaymentRequirements[]\n) => PaymentRequirements | null | Promise<PaymentRequirements | null>;\n\n// ============================================================================\n// HEADER PARSING\n// ============================================================================\n\n/**\n * Parse X-PAYMENT or PAYMENT-SIGNATURE header value\n *\n * @param headerValue - Base64-encoded header value (or undefined/null)\n * @returns Parsed x402 header object, or null if invalid\n *\n * @example\n * ```ts\n * // Express.js\n * const payment = parsePaymentHeader(req.headers['x-payment']);\n * if (!payment) {\n * return res.status(400).json({ error: 'Invalid payment header' });\n * }\n * ```\n */\nexport function parsePaymentHeader(\n headerValue: string | undefined | null\n): X402Header | null {\n if (!headerValue) {\n return null;\n }\n\n try {\n return decodeX402Header(headerValue);\n } catch {\n return null;\n }\n}\n\n/**\n * Extract payment header from request headers object\n *\n * Checks both X-PAYMENT and PAYMENT-SIGNATURE headers.\n *\n * @param headers - Request headers object (case-insensitive)\n * @returns Parsed x402 header object, or null if not found/invalid\n *\n * @example\n * ```ts\n * const payment = extractPaymentFromHeaders(req.headers);\n * ```\n */\nexport function extractPaymentFromHeaders(\n headers: Record<string, string | string[] | undefined>\n): X402Header | null {\n // Normalize header keys to lowercase\n const normalizedHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (typeof value === 'string') {\n normalizedHeaders[key.toLowerCase()] = value;\n } else if (Array.isArray(value) && value.length > 0) {\n normalizedHeaders[key.toLowerCase()] = value[0];\n }\n }\n\n // Try X-PAYMENT first, then PAYMENT-SIGNATURE\n const headerValue =\n normalizedHeaders['x-payment'] ||\n normalizedHeaders['payment-signature'];\n\n return parsePaymentHeader(headerValue);\n}\n\n// ============================================================================\n// REQUEST BUILDERS\n// ============================================================================\n\n/**\n * Build payment requirements for the facilitator\n *\n * @param options - Payment requirements options\n * @returns PaymentRequirements object ready for verify/settle\n *\n * @example\n * ```ts\n * const requirements = buildPaymentRequirements({\n * amount: '1.00',\n * recipient: '0x1234...',\n * resource: 'https://api.example.com/premium-data',\n * chainName: 'base',\n * });\n * ```\n */\nexport function buildPaymentRequirements(\n options: PaymentRequirementsOptions\n): PaymentRequirements {\n const {\n amount,\n recipient,\n resource,\n chainName = 'base',\n description = 'Payment for resource access',\n mimeType = 'application/json',\n timeoutSeconds = 300,\n x402Version = 1,\n } = options;\n\n const chain = getChainByName(chainName);\n if (!chain) {\n throw new Error(`Unsupported chain: ${chainName}`);\n }\n\n // Convert amount to atomic units\n const atomicAmount = Math.floor(\n parseFloat(amount) * Math.pow(10, chain.usdc.decimals)\n ).toString();\n\n // Use CAIP-2 for v2, chain name for v1\n const network = x402Version === 2 ? chainToCAIP2(chainName) : chainName;\n\n return {\n scheme: 'exact',\n network,\n maxAmountRequired: atomicAmount,\n resource,\n description,\n mimeType,\n payTo: recipient,\n maxTimeoutSeconds: timeoutSeconds,\n asset: chain.usdc.address,\n };\n}\n\n/**\n * Build a verify request for the facilitator /verify endpoint\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns VerifyRequest body ready for fetch/axios\n *\n * @example\n * ```ts\n * const payment = parsePaymentHeader(req.headers['x-payment']);\n * const verifyBody = buildVerifyRequest(payment, requirements);\n *\n * const response = await fetch('https://facilitator.uvd.xyz/verify', {\n * method: 'POST',\n * headers: { 'Content-Type': 'application/json' },\n * body: JSON.stringify(verifyBody),\n * });\n * ```\n */\nexport function buildVerifyRequest(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n): VerifyRequest {\n return {\n x402Version: paymentHeader.x402Version,\n paymentPayload: paymentHeader,\n paymentRequirements: requirements,\n };\n}\n\n/**\n * Build a settle request for the facilitator /settle endpoint\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns SettleRequest body ready for fetch/axios\n */\n/**\n * Describes the protected resource, as x402 v2 expects it.\n *\n * Note this is an OBJECT in v2. Sending a bare URL string here is the single\n * most common v2 mistake and it fails as an unhelpful \"no variant matched\"\n * deserialization error at the facilitator, naming no field.\n */\nexport interface ResourceInfoV2 {\n url: string;\n description: string;\n mimeType: string;\n}\n\n/**\n * Payment requirements in x402 v2 form.\n *\n * Differences from v1 that actually bite:\n * - `network` is CAIP-2 (`eip155:8453`), NOT a plain name (`base`). Mixing a v1\n * name into a v2 request fails deserialization, and vice versa.\n * - `maxAmountRequired` is renamed to `amount`.\n * - `resource` / `description` / `mimeType` moved out to {@link ResourceInfoV2}.\n */\nexport interface PaymentRequirementsV2 {\n scheme: string;\n /** CAIP-2 chain id, e.g. `eip155:8453`. */\n network: string;\n asset: string;\n amount: string;\n payTo: string;\n maxTimeoutSeconds: number;\n extra?: unknown;\n}\n\n/** The v2 payment payload — note it carries no top-level scheme/network. */\nexport interface PaymentPayloadV2 {\n x402Version: 2;\n resource: ResourceInfoV2;\n accepted: PaymentRequirementsV2;\n payload: X402PayloadData;\n extensions?: Record<string, unknown>;\n}\n\n/**\n * Verify request body in x402 v2 form.\n *\n * There is deliberately NO `paymentRequirements` key: that is the v1 envelope.\n * v2 carries `resource` and `accepted` at the top level instead.\n */\nexport interface VerifyRequestV2 {\n x402Version: 2;\n paymentPayload: PaymentPayloadV2;\n resource: ResourceInfoV2;\n accepted: PaymentRequirementsV2;\n}\n\n/** Settle request body in x402 v2 form. Same shape as {@link VerifyRequestV2}. */\nexport type SettleRequestV2 = VerifyRequestV2;\n\nfunction buildV2Envelope(\n payload: X402PayloadData,\n resource: ResourceInfoV2,\n accepted: PaymentRequirementsV2\n): VerifyRequestV2 {\n return {\n x402Version: 2,\n // The facilitator reads the payload from here; `resource` and `accepted` are\n // repeated at the top level because the v2 envelope declares both.\n paymentPayload: { x402Version: 2, resource, accepted, payload },\n resource,\n accepted,\n };\n}\n\n/**\n * Build a verify request for the facilitator `/verify` endpoint, in **v2** form.\n *\n * Use this whenever your 402 advertises CAIP-2 networks. {@link buildVerifyRequest}\n * emits the v1 envelope `{x402Version, paymentPayload, paymentRequirements}` and\n * cannot express v2 — putting a v2 payload inside it matches no variant at the\n * facilitator and fails with an error that names no field.\n *\n * @example\n * ```ts\n * const body = buildVerifyRequestV2(\n * payment.payload,\n * { url: 'https://api.example.com/thing', description: 'Thing', mimeType: 'application/json' },\n * { scheme: 'exact', network: 'eip155:8453', asset: '0x8335...', amount: '100000',\n * payTo: '0xabc...', maxTimeoutSeconds: 300 }\n * );\n * ```\n */\nexport function buildVerifyRequestV2(\n payload: X402PayloadData,\n resource: ResourceInfoV2,\n accepted: PaymentRequirementsV2\n): VerifyRequestV2 {\n return buildV2Envelope(payload, resource, accepted);\n}\n\n/**\n * Build a settle request for the facilitator `/settle` endpoint, in **v2** form.\n *\n * See {@link buildVerifyRequestV2} — the envelope is identical.\n */\nexport function buildSettleRequestV2(\n payload: X402PayloadData,\n resource: ResourceInfoV2,\n accepted: PaymentRequirementsV2\n): SettleRequestV2 {\n return buildV2Envelope(payload, resource, accepted);\n}\n\nexport function buildSettleRequest(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n): SettleRequest {\n return {\n x402Version: paymentHeader.x402Version,\n paymentPayload: paymentHeader,\n paymentRequirements: requirements,\n };\n}\n\n// ============================================================================\n// CORS CONFIGURATION\n// ============================================================================\n\n/**\n * Recommended CORS headers for x402 payment APIs\n *\n * These headers allow browsers to send payment headers in cross-origin requests.\n */\nexport const X402_CORS_HEADERS = {\n 'Access-Control-Allow-Headers':\n 'Content-Type, X-PAYMENT, PAYMENT-SIGNATURE, Authorization',\n 'Access-Control-Expose-Headers':\n 'X-PAYMENT-RESPONSE, PAYMENT-RESPONSE, PAYMENT-REQUIRED',\n 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',\n} as const;\n\n/**\n * All x402 custom header names that should be allowed in CORS\n */\nexport const X402_HEADER_NAMES = [\n 'X-PAYMENT',\n 'PAYMENT-SIGNATURE',\n 'X-PAYMENT-RESPONSE',\n 'PAYMENT-RESPONSE',\n 'PAYMENT-REQUIRED',\n] as const;\n\n/**\n * Get CORS headers with custom origin\n *\n * @param origin - Allowed origin (use '*' for any, or specific domain)\n * @returns Complete CORS headers object\n *\n * @example\n * ```ts\n * // Express.js middleware\n * app.use((req, res, next) => {\n * const corsHeaders = getCorsHeaders('https://myapp.com');\n * Object.entries(corsHeaders).forEach(([key, value]) => {\n * res.setHeader(key, value);\n * });\n * if (req.method === 'OPTIONS') {\n * return res.status(204).end();\n * }\n * next();\n * });\n * ```\n */\nexport function getCorsHeaders(origin: string = '*'): Record<string, string> {\n return {\n 'Access-Control-Allow-Origin': origin,\n ...X402_CORS_HEADERS,\n };\n}\n\n// ============================================================================\n// FACILITATOR CLIENT\n// ============================================================================\n\n/**\n * Options for the FacilitatorClient\n */\nexport interface FacilitatorClientOptions {\n /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */\n baseUrl?: string;\n /**\n * Request timeout in milliseconds (default: auto per network).\n * When not set, the client uses per-network defaults from ESCROW_TIMEOUT_MS\n * (960s for Ethereum L1, 90s for L2s, 30s for others).\n * Set explicitly to override per-network auto-detection.\n */\n timeout?: number;\n /**\n * Extra attempts after the first when the facilitator answers a refusal it\n * proved it did not execute (`safeToReplay`). Default 2; `0` disables.\n *\n * Only ever spent on `429` and on a `503` naming a pre-execution writer-lease\n * reason. An ambiguous `forward_failed` -- whose write may already have landed\n * -- is never replayed here, at any setting.\n */\n retries?: number;\n}\n\n/**\n * Client for interacting with the x402 facilitator API\n *\n * @example\n * ```ts\n * const client = new FacilitatorClient();\n *\n * // Verify a payment\n * const verifyResult = await client.verify(paymentHeader, requirements);\n * if (!verifyResult.isValid) {\n * return res.status(402).json({ error: verifyResult.invalidReason });\n * }\n *\n * // Provide the service, then settle\n * const settleResult = await client.settle(paymentHeader, requirements);\n * if (!settleResult.success) {\n * // Handle settlement failure (maybe refund or retry)\n * }\n * ```\n */\nexport class FacilitatorClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly explicitTimeout: boolean;\n private readonly retries: number | undefined;\n\n constructor(options: FacilitatorClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';\n this.explicitTimeout = options.timeout !== undefined;\n this.timeout = options.timeout || 30000;\n this.retries = options.retries;\n }\n\n /**\n * Get timeout for a specific network, using per-chain defaults when no explicit timeout was set.\n */\n private getTimeout(network?: string): number {\n if (this.explicitTimeout) return this.timeout;\n if (!network) return this.timeout;\n // Extract chainId from CAIP-2 format (eip155:1) or legacy names\n const match = network.match(/^eip155:(\\d+)$/);\n if (match) {\n const chainId = parseInt(match[1], 10);\n return ESCROW_TIMEOUT_MS[chainId] || this.timeout;\n }\n // Legacy network name mapping for Ethereum\n if (network === 'ethereum' || network === 'ethereum-mainnet') return ESCROW_TIMEOUT_MS[1];\n return this.timeout;\n }\n\n /**\n * Verify a payment with the facilitator\n *\n * Call this before providing the paid resource to validate the payment.\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns Verification result\n */\n async verify(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n ): Promise<VerifyResponse> {\n const body = buildVerifyRequest(paymentHeader, requirements);\n\n try {\n const { response, error } = await facilitatorFetch(\n `${this.baseUrl}/verify`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n\n if (error) {\n // `isValid: false` is unavoidable -- nothing was validated -- but it is\n // no longer the whole story. A caller that answers 402 on this without\n // reading `retryable` tells the buyer their payment was REFUSED and\n // asks them to sign another one, for a payment the facilitator never\n // looked at. That is the double-charge this field exists to prevent.\n return {\n isValid: false,\n invalidReason: error.error,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // A thrown error is a transport failure (timeout, DNS, connection reset).\n // No verdict was reached either, so it is retryable for exactly the same\n // reason a 503 is -- and it used to be reported as an invalid payment.\n return {\n isValid: false,\n invalidReason: error instanceof Error ? error.message : 'Unknown error',\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Settle a payment with the facilitator\n *\n * Call this after providing the paid resource to execute the on-chain transfer.\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns Settlement result with transaction hash\n */\n async settle(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n ): Promise<SettleResponse> {\n const body = buildSettleRequest(paymentHeader, requirements);\n const settleTimeout = this.getTimeout(requirements.network);\n\n try {\n // A `/settle` refusal that the facilitator proved it did not execute is\n // replayed here with the SAME authorization. That is safe twice over: the\n // facilitator refused in its router before signing anything, and the\n // authorization carries a single-use nonce the chain rejects on a real\n // duplicate. What is NOT replayed is `forward_failed` -- the hop to the\n // lease holder died after handing the write over, so the transfer may\n // already be mining.\n const { response, error } = await facilitatorFetch(\n `${this.baseUrl}/settle`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n },\n { timeoutMs: settleTimeout, retries: this.retries },\n );\n\n if (error) {\n return {\n success: false,\n error: error.error,\n ...failureFields(error),\n };\n }\n\n const result = await response.json();\n // Read all three spellings. The facilitator's canonical name for this\n // field is `transaction`, and this client used to read only the two\n // camel/snake variants — so it silently returned `undefined` for the\n // most important field a settle produces. A consumer failed closed on\n // that and revoked access to a payment that had already settled\n // on-chain: the money moved, the receipt was unreadable.\n //\n // The server now emits all three, but this fallback stays: it makes the\n // client work against facilitators that have not deployed that yet, and\n // against any that only ever emitted the canonical name.\n const transactionHash =\n result.transaction ?? result.transactionHash ?? result.transaction_hash;\n if (result.success && !transactionHash) {\n // Never let a missing hash pass as a normal success. A caller that\n // gates access on the receipt needs to know the receipt is absent,\n // not infer it from an undefined field.\n console.warn(\n '[x402] settle reported success but carried no transaction hash under ' +\n 'transaction/transactionHash/transaction_hash — treat delivery as unconfirmed'\n );\n }\n return {\n // Read the facilitator's verdict instead of asserting one.\n //\n // This was the literal `true`, so a settle was reported successful\n // whenever the HTTP call was — and \"the request arrived\" is not \"the\n // money moved\". A payment that MINES AND THEN REVERTS is answered with\n // 200 and `success: false` (x402-rs src/chain/evm.rs:1343, serialised\n // through StatusCode::OK), which is precisely the case a caller most\n // needs to hear about. Every consumer doing `result.success === true`\n // was reading a constant, so a reverted payment was booked as settled\n // and no reconciliation path could ever fire.\n //\n // Absent `success` is treated as NOT successful: a facilitator that\n // does not say it worked has not said it worked.\n success: result.success === true,\n transactionHash,\n network: result.network,\n // Why it failed, when it did. Without this the caller gets `success:\n // false` and no way to tell a reverted transfer from a rejected\n // authorization except by parsing prose.\n errorReason: result.errorReason ?? result.error_reason,\n // The settlement proof, when the facilitator attached one (it does for\n // the ERC-8004 extension). Dropping it here made `verified: true`\n // unreachable for DX402 anchoring through this client: `anchorEvidence`\n // documents proofOfPayment as the only thing that gets there, the\n // facilitator returns it, and this method threw it away — so a seller\n // using the SDK end to end could only ever produce provisional anchors.\n proofOfPayment: result.proofOfPayment ?? result.proof_of_payment,\n payer: result.payer,\n };\n } catch (error) {\n // Timeout or connection failure. The write may have landed -- this is the\n // same ambiguity as `forward_failed`, so it is retryable but never\n // replayed automatically. Reconcile on-chain, or by transaction hash,\n // before sending anything again.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Verify and settle atomically\n *\n * Convenience method that verifies first, then settles if valid.\n * Use this for simple payment flows where you don't need custom logic between verify and settle.\n *\n * @param paymentHeader - Parsed x402 payment header\n * @param requirements - Payment requirements\n * @returns Combined result with verify and settle status\n */\n async verifyAndSettle(\n paymentHeader: X402Header,\n requirements: PaymentRequirements\n ): Promise<\n {\n verified: boolean;\n settled: boolean;\n transactionHash?: string;\n error?: string;\n } & FacilitatorFailureFields\n > {\n // Verify first\n const verifyResult = await this.verify(paymentHeader, requirements);\n if (!verifyResult.isValid) {\n // Carry the refusal's shape up. Flattening it to `verified: false` here\n // would undo the whole point one level below: the caller could not tell a\n // rejected authorization from a facilitator that never answered.\n return {\n verified: false,\n settled: false,\n error: verifyResult.invalidReason,\n ...carryFailureFields(verifyResult),\n };\n }\n\n // Settle\n const settleResult = await this.settle(paymentHeader, requirements);\n return {\n verified: true,\n settled: settleResult.success,\n transactionHash: settleResult.transactionHash,\n error: settleResult.error,\n ...carryFailureFields(settleResult),\n };\n }\n\n /**\n * Check if the facilitator is healthy\n *\n * @returns True if the facilitator is responding\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/health`, {\n method: 'GET',\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n\n /**\n * Get the facilitator version info\n *\n * @returns Version info (e.g., { version: \"1.37.0\" })\n */\n async getVersion(): Promise<{ version: string; [key: string]: unknown }> {\n const response = await fetch(`${this.baseUrl}/version`, {\n method: 'GET',\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /version failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Get the facilitator's supported networks and payment schemes\n *\n * @returns Supported networks/schemes with 'kinds' array\n *\n * @example\n * ```ts\n * const supported = await client.getSupported();\n * for (const kind of supported.kinds) {\n * console.log(`${kind.network} - ${kind.scheme}`);\n * }\n * ```\n */\n async getSupported(): Promise<{\n kinds: Array<{ network: string; scheme: string; [key: string]: unknown }>;\n [key: string]: unknown;\n }> {\n const response = await fetch(`${this.baseUrl}/supported`, {\n method: 'GET',\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /supported failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Aggregated totals per network and asset (`GET /api/stats`).\n *\n * **An index, not a ledger.** Records are written best-effort AFTER\n * settlement, so an outage loses rows while payments proceed — verify\n * anything that matters against the transaction hash. Counting starts when\n * the operator enabled the store, so earlier operations are UNKNOWN, not\n * zero. And unless `X402_EVENTS_PUBLISH_FAILURES=true`, operations that ERROR\n * are not recorded at all: a 100% success rate means \"no failures were\n * recorded\".\n *\n * `volumeAtomic` is a STRING (u256-shaped; a JS number loses precision above\n * 2^53) and each row carries its own `decimals`. **Use that, never a\n * constant** — USDC is 6 decimals nearly everywhere and 18 on BSC, so scaling\n * by 6 there overstates volume by 10^12. `decimals` is null when the asset is\n * unrecognised; render the atomic value rather than guessing a scale.\n */\n async getStats(): Promise<{\n totals: { settlesOk: number; settlesFailed: number; verifies: number; networks: number };\n byNetworkAndAsset: Array<{\n network: string;\n asset: string;\n settlesOk: number;\n settlesFailed: number;\n verifies: number;\n volumeAtomic: string;\n decimals: number | null;\n lastTs: number;\n }>;\n [key: string]: unknown;\n }> {\n const response = await fetch(`${this.baseUrl}/api/stats`, { method: 'GET' });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /api/stats failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Recent recorded operations, newest first (`GET /transactions`).\n *\n * There is **no pagination and no cursor**: this returns the newest N,\n * walking back at most 30 days. With 10,000 rows you get the newest 200, not\n * page one of fifty. `limit` is clamped to 200 by the facilitator.\n *\n * `network` matches the canonical slug `/supported` uses, which is not always\n * the alias you may send — `skale` is accepted inbound but records say\n * `skale-base`.\n */\n async getTransactions(options: { limit?: number; network?: string } = {}): Promise<{\n transactions: Array<Record<string, unknown>>;\n count: number;\n [key: string]: unknown;\n }> {\n const params = new URLSearchParams();\n if (options.limit !== undefined) params.set('limit', String(options.limit));\n if (options.network) params.set('network', options.network);\n const query = params.toString();\n const response = await fetch(\n `${this.baseUrl}/transactions${query ? `?${query}` : ''}`,\n { method: 'GET' }\n );\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /transactions failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Get the facilitator's blocked/sanctioned addresses\n *\n * @returns Blacklist info (totalBlocked, loadedAtStartup, addresses)\n *\n * @example\n * ```ts\n * const bl = await client.getBlacklist();\n * console.log(`Blocked: ${bl.totalBlocked} addresses`);\n * ```\n */\n async getBlacklist(): Promise<{\n totalBlocked: number;\n loadedAtStartup: boolean;\n [key: string]: unknown;\n }> {\n const response = await fetch(`${this.baseUrl}/blacklist`, {\n method: 'GET',\n });\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`GET /blacklist failed: ${response.status} - ${errorText}`);\n }\n return await response.json();\n }\n\n /**\n * Negotiate payment requirements with the facilitator via POST /accepts.\n *\n * Sends merchant payment requirements to the facilitator, which matches\n * them against its supported capabilities and returns enriched requirements\n * with facilitator data (feePayer, tokens, escrow configuration).\n *\n * This is used by Faremeter middleware and clients that need to discover\n * what the facilitator can settle before constructing payment authorizations.\n *\n * @param paymentRequirements - List of payment requirement objects\n * @param x402Version - x402 protocol version (default: 2)\n * @returns List of enriched payment requirements with facilitator extras\n *\n * @example\n * ```ts\n * const enriched = await client.accepts([\n * {\n * scheme: 'exact',\n * network: 'base-mainnet',\n * maxAmountRequired: '1000000',\n * resource: 'https://api.example.com/data',\n * payTo: '0xMerchant...',\n * },\n * ]);\n * // enriched[0].extra.feePayer is now set\n * ```\n */\n async accepts(\n paymentRequirements: PaymentRequirements[],\n x402Version: number = 2\n ): Promise<PaymentRequirements[]> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/accepts`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n x402Version,\n accepts: paymentRequirements,\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Facilitator /accepts error: ${response.status} - ${errorText}`);\n }\n\n const data = await response.json();\n return data.accepts || [];\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n}\n\n// ============================================================================\n// ATOMIC PAYMENT HELPERS\n// ============================================================================\n\n/**\n * Create a 402 Payment Required response\n *\n * @param requirements - Payment requirements\n * @param options - Additional response options\n * @returns Object with status code, headers, and body for the 402 response\n *\n * @example\n * ```ts\n * // Express.js\n * app.get('/premium-data', (req, res) => {\n * const payment = extractPaymentFromHeaders(req.headers);\n *\n * if (!payment) {\n * const { status, headers, body } = create402Response({\n * amount: '1.00',\n * recipient: '0x...',\n * resource: 'https://api.example.com/premium-data',\n * });\n * return res.status(status).set(headers).json(body);\n * }\n *\n * // Verify and serve...\n * });\n * ```\n */\nexport function create402Response(\n requirements: PaymentRequirementsOptions,\n options: {\n accepts?: PaymentAcceptance[];\n } = {}\n): {\n status: 402;\n headers: Record<string, string>;\n body: Record<string, unknown>;\n} {\n const primaryRequirement = buildPaymentRequirements(requirements);\n const version = requirements.x402Version\n || ((options.accepts && options.accepts.length > 0)\n || primaryRequirement.network.includes(':')\n || (options.accepts || []).some((accept) => accept.network.includes(':'))\n ? 2\n : 1);\n const advertisedRequirements = [\n normalizeRequirementForVersion(primaryRequirement, version),\n ...(options.accepts || []).map((accept) =>\n buildRequirementFromAcceptance(accept, primaryRequirement.resource, version, primaryRequirement)\n ),\n ];\n const body = create402ResponseBody(advertisedRequirements[0], advertisedRequirements, version);\n\n return {\n status: 402,\n headers: {\n 'Content-Type': 'application/json',\n ...X402_CORS_HEADERS,\n },\n body,\n };\n}\n\nconst DEFAULT_PAYMENT_DESCRIPTION = 'Payment required';\nconst DEFAULT_PAYMENT_MIME_TYPE = 'application/json';\nconst DEFAULT_PAYMENT_TIMEOUT_SECONDS = 300;\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction resolveAdvertisedVersion(\n accepts: PaymentAcceptance[],\n requestedVersion?: X402Version | 'auto'\n): X402Version {\n if (requestedVersion && requestedVersion !== 'auto') {\n return requestedVersion;\n }\n\n if (accepts.length > 1 || accepts.some((accept) => accept.network.includes(':'))) {\n return 2;\n }\n\n return 1;\n}\n\nfunction normalizeRequirementForVersion(\n requirements: PaymentRequirements,\n version: X402Version\n): PaymentRequirements {\n return {\n ...requirements,\n network: version === 2\n ? (requirements.network.includes(':') ? requirements.network : chainToCAIP2(requirements.network))\n : (requirements.network.includes(':') ? parseNetworkIdentifier(requirements.network) : requirements.network),\n };\n}\n\nfunction buildRequirementFromAcceptance(\n accept: PaymentAcceptance,\n resource: string,\n version: X402Version,\n defaults?: PaymentRequirements\n): PaymentRequirements {\n const payTo = accept.payTo ?? defaults?.payTo;\n if (!payTo) {\n throw new Error('Payment accepts entries must include payTo');\n }\n\n return normalizeRequirementForVersion({\n // Honour a caller-supplied scheme; 'exact' is the default, not an override.\n // Hardcoding it silently discarded 'escrow' / 'commerce' accepts.\n scheme: (accept.scheme as PaymentRequirements['scheme']) ?? 'exact',\n network: accept.network,\n maxAmountRequired: accept.amount,\n resource: accept.resource ?? defaults?.resource ?? resource,\n description: accept.description ?? defaults?.description ?? DEFAULT_PAYMENT_DESCRIPTION,\n mimeType: accept.mimeType ?? defaults?.mimeType ?? DEFAULT_PAYMENT_MIME_TYPE,\n payTo,\n asset: accept.asset,\n maxTimeoutSeconds: accept.maxTimeoutSeconds ?? defaults?.maxTimeoutSeconds ?? DEFAULT_PAYMENT_TIMEOUT_SECONDS,\n ...(accept.outputSchema !== undefined\n ? { outputSchema: accept.outputSchema }\n : defaults?.outputSchema !== undefined\n ? { outputSchema: defaults.outputSchema }\n : {}),\n ...(accept.extra !== undefined\n ? { extra: accept.extra }\n : defaults?.extra !== undefined\n ? { extra: defaults.extra }\n : {}),\n }, version);\n}\n\nfunction toPaymentAcceptance(\n requirements: PaymentRequirements,\n facilitator?: string\n): PaymentAcceptance {\n return {\n network: requirements.network,\n asset: requirements.asset,\n amount: requirements.maxAmountRequired,\n // scheme is REQUIRED by the facilitator's v2 PaymentRequirementsV2. Dropping it\n // here produced an accepts[] entry that no v2 client could pay: the spec makes\n // the client echo the accept verbatim, so the omission travelled downstream and\n // died in deserialization with an error naming no field.\n scheme: requirements.scheme,\n payTo: requirements.payTo,\n resource: requirements.resource,\n description: requirements.description,\n mimeType: requirements.mimeType,\n maxTimeoutSeconds: requirements.maxTimeoutSeconds,\n ...(facilitator ? { facilitator } : {}),\n ...(requirements.outputSchema !== undefined ? { outputSchema: requirements.outputSchema } : {}),\n ...(requirements.extra !== undefined ? { extra: requirements.extra } : {}),\n };\n}\n\nfunction create402ResponseBody(\n primaryRequirement: PaymentRequirements,\n advertisedRequirements: PaymentRequirements[],\n version: X402Version,\n facilitator?: string\n): Record<string, unknown> {\n const normalizedPrimary = normalizeRequirementForVersion(primaryRequirement, version);\n const normalizedAdvertised = advertisedRequirements.map((requirements) =>\n normalizeRequirementForVersion(requirements, version)\n );\n\n const body: Record<string, unknown> = {\n x402Version: version,\n ...normalizedPrimary,\n };\n\n if (version === 2 && normalizedAdvertised.length > 1) {\n body.accepts = normalizedAdvertised.map((requirements) =>\n toPaymentAcceptance(requirements, facilitator)\n );\n }\n\n return body;\n}\n\nfunction getComparableNetwork(network: string): string {\n return parseNetworkIdentifier(network).toLowerCase();\n}\n\nfunction getPaymentRecipient(payment: X402Header): string | undefined {\n const payload = payment.payload as unknown;\n if (!isObject(payload)) {\n return undefined;\n }\n const authorization = payload.authorization;\n\n if (isObject(authorization) && typeof authorization.to === 'string') {\n return authorization.to.toLowerCase();\n }\n\n if (typeof payload.to === 'string') {\n return payload.to.toLowerCase();\n }\n\n return undefined;\n}\n\nfunction getPaymentAmount(payment: X402Header): string | undefined {\n const payload = payment.payload as unknown;\n if (!isObject(payload)) {\n return undefined;\n }\n const authorization = payload.authorization;\n\n if (isObject(authorization) && typeof authorization.value === 'string') {\n return authorization.value;\n }\n\n if (typeof payload.amount === 'string') {\n return payload.amount;\n }\n\n return undefined;\n}\n\nfunction getPaymentAsset(payment: X402Header): string | undefined {\n const payload = payment.payload as unknown;\n if (!isObject(payload)) {\n return undefined;\n }\n\n if (typeof payload.tokenContract === 'string') {\n return payload.tokenContract.toLowerCase();\n }\n\n return undefined;\n}\n\nasync function resolvePaymentRequirement(\n payment: X402Header,\n requirements: PaymentRequirements[],\n resolver?: PaymentRequirementResolver\n): Promise<{ requirement: PaymentRequirements | null; reason?: string }> {\n const normalizedRequirements = requirements.map((requirements) =>\n normalizeRequirementForVersion(requirements, payment.x402Version)\n );\n\n if (resolver) {\n const resolved = await resolver(payment, normalizedRequirements);\n return {\n requirement: resolved\n ? normalizeRequirementForVersion(resolved, payment.x402Version)\n : null,\n ...(resolved ? {} : { reason: 'Custom requirement resolver did not return a matching requirement.' }),\n };\n }\n\n const networkMatches = normalizedRequirements.filter((requirements) =>\n getComparableNetwork(requirements.network) === getComparableNetwork(payment.network)\n );\n\n if (networkMatches.length === 0) {\n return {\n requirement: null,\n reason: `No advertised payment requirement matched network ${payment.network}.`,\n };\n }\n\n let matches = networkMatches;\n\n const paymentRecipient = getPaymentRecipient(payment);\n if (paymentRecipient) {\n const recipientMatches = matches.filter((requirements) =>\n requirements.payTo.toLowerCase() === paymentRecipient\n );\n if (recipientMatches.length === 0) {\n return {\n requirement: null,\n reason: 'Payment recipient does not match any advertised requirement.',\n };\n }\n matches = recipientMatches;\n }\n\n const paymentAmount = getPaymentAmount(payment);\n if (paymentAmount) {\n const amountMatches = matches.filter((requirements) =>\n requirements.maxAmountRequired === paymentAmount\n );\n if (amountMatches.length === 0) {\n return {\n requirement: null,\n reason: 'Payment amount does not match any advertised requirement.',\n };\n }\n matches = amountMatches;\n }\n\n const paymentAsset = getPaymentAsset(payment);\n if (paymentAsset) {\n const assetMatches = matches.filter((requirements) =>\n requirements.asset.toLowerCase() === paymentAsset\n );\n if (assetMatches.length === 0) {\n return {\n requirement: null,\n reason: 'Payment asset does not match any advertised requirement.',\n };\n }\n matches = assetMatches;\n }\n\n if (matches.length !== 1) {\n return {\n requirement: null,\n reason: 'Payment matched multiple advertised requirements. Advertise unique network/payTo/amount combinations or provide resolveRequirement().',\n };\n }\n\n return { requirement: matches[0] };\n}\n\nfunction createVerifiedPaymentState(\n client: FacilitatorClient,\n payment: X402Header,\n requirements: PaymentRequirements,\n verifyResult: VerifyResponse\n): VerifiedPaymentState {\n let settlePromise: Promise<SettleResponse> | null = null;\n return {\n payment,\n requirements,\n verifyResult,\n settle: () => {\n if (!settlePromise) {\n settlePromise = client.settle(payment, requirements);\n }\n return settlePromise;\n },\n };\n}\n\n/**\n * Answer a no-verdict facilitator refusal as 503 + `Retry-After`.\n *\n * The body repeats the facilitator's own `reason` and a `retryable` flag so a\n * client that only reads JSON still learns the payment was not rejected. The\n * header is a whole-second integer, as RFC 9110 requires.\n */\nfunction respondUnavailable(\n res: {\n status: (code: number) => {\n json: (body: unknown) => void;\n set: (headers: Record<string, string>) => { json: (body: unknown) => void };\n };\n },\n message: string,\n failure: FacilitatorFailureFields & { error?: string; invalidReason?: string },\n): void {\n const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));\n const body = {\n error: message,\n reason: failure.reason ?? failure.invalidReason ?? failure.error,\n retryable: true,\n retryAfterSeconds: seconds,\n // False for `forward_failed` and for a bare timeout: the write may already\n // have landed, so the caller must reconcile before resending.\n safeToReplay: failure.safeToReplay === true,\n };\n const staged = res.status(503);\n if (typeof staged.set === 'function') {\n staged.set({ 'Retry-After': String(seconds) }).json(body);\n return;\n }\n staged.json(body);\n}\n\n/**\n * Create an Express-compatible middleware for x402 payments\n *\n * @param getRequirements - Function to get payment requirements for a request\n * @param options - Middleware options\n * @returns Express middleware function\n *\n * @example\n * ```ts\n * const paymentMiddleware = createPaymentMiddleware(\n * (req) => ({\n * amount: '1.00',\n * recipient: process.env.PAYMENT_RECIPIENT,\n * resource: `${req.protocol}://${req.get('host')}${req.originalUrl}`,\n * }),\n * { facilitatorUrl: 'https://facilitator.uvd.xyz' }\n * );\n *\n * app.get('/premium/*', paymentMiddleware, async (req, res) => {\n * const settleResult = await req.x402?.settle();\n * if (!settleResult?.success) {\n * return res.status(500).json({ error: settleResult?.error });\n * }\n *\n * res.json({ premium: 'data' });\n * });\n * ```\n */\nexport function createPaymentMiddleware(\n getRequirements: (req: { headers: Record<string, string | string[] | undefined> }) => PaymentRequirementsOptions,\n options: PaymentMiddlewareOptions = {}\n): (\n req: { headers: Record<string, string | string[] | undefined>; x402?: VerifiedPaymentState },\n res: { status: (code: number) => { json: (body: unknown) => void; set: (headers: Record<string, string>) => { json: (body: unknown) => void } } },\n next: () => void\n) => Promise<void> {\n const client = new FacilitatorClient({\n baseUrl: options.facilitatorUrl || options.baseUrl,\n timeout: options.timeout,\n retries: options.retries,\n });\n const settlementStrategy = options.settlementStrategy || 'before-handler';\n\n return async (req, res, next) => {\n // Extract payment header\n const payment = extractPaymentFromHeaders(req.headers);\n\n // If no payment, return 402\n if (!payment) {\n const reqOptions = getRequirements(req);\n const { status, headers, body } = create402Response(reqOptions);\n res.status(status).set(headers).json(body);\n return;\n }\n\n // Build requirements and verify\n const reqOptions = getRequirements(req);\n const requirements = buildPaymentRequirements(reqOptions);\n const verifyResult = await client.verify(payment, requirements);\n\n if (!verifyResult.isValid) {\n // 402 says \"your payment was REJECTED, sign a new authorization\". Sending\n // it for a facilitator that never reached a verdict is what makes the\n // buyer pay twice: their first authorization was never refused and is\n // still perfectly good. A no-verdict answer must keep the credential\n // alive, so it goes out as 503 + Retry-After instead.\n if (verifyResult.retryable) {\n respondUnavailable(res, 'Payment verification unavailable', verifyResult);\n return;\n }\n res.status(402).json({\n error: 'Payment verification failed',\n reason: verifyResult.invalidReason,\n });\n return;\n }\n\n req.x402 = createVerifiedPaymentState(client, payment, requirements, verifyResult);\n\n if (settlementStrategy === 'before-handler') {\n const settleResult = await req.x402.settle();\n if (!settleResult.success) {\n // Same distinction on the settle side. A 500 tells a client its request\n // is broken and to stop; a settle that reached no verdict is the one\n // case where retrying the identical request is correct.\n if (settleResult.retryable) {\n respondUnavailable(res, 'Payment settlement unavailable', settleResult);\n return;\n }\n res.status(500).json({\n error: 'Payment settlement failed',\n reason: settleResult.error || 'Unknown settlement error',\n });\n return;\n }\n }\n\n next();\n };\n}\n\n// ============================================================================\n// HONO MIDDLEWARE\n// ============================================================================\n\n/**\n * Options for creating a Hono x402 payment middleware\n */\nexport interface HonoMiddlewareOptions extends PaymentMiddlewareOptions {\n /** Payment requirements to advertise */\n accepts: PaymentAcceptance[];\n /** Response version to advertise (defaults to auto) */\n x402Version?: X402Version | 'auto';\n /** Custom requirement resolver for ambiguous multi-accept flows */\n resolveRequirement?: PaymentRequirementResolver;\n}\n\n/**\n * Create a Hono-compatible middleware for x402 payments.\n *\n * Handles the x402 payment flow:\n * 1. Returns 402 with payment requirements if no X-PAYMENT header\n * 2. Verifies the payment with the facilitator\n * 3. Optionally settles before the handler when settlementStrategy is set\n * 4. Passes control to the next handler on success\n *\n * @param options - Middleware options with facilitator URL and payment accepts\n * @returns Hono middleware function\n *\n * @example\n * ```ts\n * import { createHonoMiddleware } from 'uvd-x402-sdk';\n *\n * const paywall = createHonoMiddleware({\n * accepts: [{\n * network: 'skale-base',\n * asset: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n * amount: '1000000',\n * payTo: '0xYourWallet',\n * extra: { name: 'Bridged USDC (SKALE Bridge)', version: '2' },\n * }],\n * });\n *\n * app.get('/api/premium', paywall, (c) => {\n * return c.json({ message: 'Premium content!' });\n * });\n * ```\n */\n/** {@link respondUnavailable} for a Hono context. */\nfunction honoUnavailable(\n c: {\n json: (body: unknown, status?: number) => unknown;\n header?: (name: string, value: string) => void;\n },\n message: string,\n failure: FacilitatorFailureFields & { error?: string; invalidReason?: string },\n): unknown {\n const seconds = Math.max(1, Math.ceil(failure.retryAfterSeconds ?? DEFAULT_RETRY_AFTER_SECONDS));\n c.header?.('Retry-After', String(seconds));\n return c.json(\n {\n error: message,\n reason: failure.reason ?? failure.invalidReason ?? failure.error,\n retryable: true,\n retryAfterSeconds: seconds,\n safeToReplay: failure.safeToReplay === true,\n },\n 503,\n );\n}\n\nexport function createHonoMiddleware(options: HonoMiddlewareOptions) {\n const client = new FacilitatorClient({\n baseUrl: options.facilitatorUrl || options.baseUrl,\n timeout: options.timeout,\n retries: options.retries,\n });\n const settlementStrategy = options.settlementStrategy || 'before-handler';\n\n if (!options.accepts[0]) {\n throw new Error('At least one accept entry is required');\n }\n\n return async (\n c: {\n req: { header: (name: string) => string | undefined; url: string };\n json: (body: unknown, status?: number) => unknown;\n set?: (key: string, value: unknown) => void;\n /** Hono's response-header setter. Optional so older context doubles still fit. */\n header?: (name: string, value: string) => void;\n },\n next: () => Promise<void>\n ) => {\n const paymentHeader = c.req.header('X-PAYMENT') || c.req.header('x-payment');\n const advertisedVersion = resolveAdvertisedVersion(options.accepts, options.x402Version);\n const advertisedRequirements = options.accepts.map((accept) =>\n buildRequirementFromAcceptance(accept, c.req.url, advertisedVersion)\n );\n\n if (!paymentHeader) {\n return c.json(\n create402ResponseBody(\n advertisedRequirements[0],\n advertisedRequirements,\n advertisedVersion,\n options.facilitatorUrl\n ),\n 402\n );\n }\n\n const parsed = parsePaymentHeader(paymentHeader);\n if (!parsed) {\n return c.json({ error: 'Invalid X-PAYMENT header' }, 400);\n }\n\n const { requirement, reason } = await resolvePaymentRequirement(\n parsed,\n advertisedRequirements,\n options.resolveRequirement\n );\n\n if (!requirement) {\n return c.json({\n error: 'Payment verification failed',\n reason,\n }, 402);\n }\n\n const verifyResult = await client.verify(parsed, requirement);\n if (!verifyResult.isValid) {\n // See respondUnavailable: 402 here would tell the buyer to sign again for\n // an authorization the facilitator never rejected.\n if (verifyResult.retryable) {\n return honoUnavailable(c, 'Payment verification unavailable', verifyResult);\n }\n return c.json({\n error: 'Payment verification failed',\n reason: verifyResult.invalidReason,\n }, 402);\n }\n\n const verifiedPayment = createVerifiedPaymentState(client, parsed, requirement, verifyResult);\n c.set?.('x402', verifiedPayment);\n\n if (settlementStrategy === 'before-handler') {\n const settleResult = await verifiedPayment.settle();\n if (!settleResult.success) {\n if (settleResult.retryable) {\n return honoUnavailable(c, 'Payment settlement unavailable', settleResult);\n }\n return c.json({\n error: 'Payment settlement failed',\n reason: settleResult.error || 'Unknown error',\n }, 500);\n }\n }\n\n await next();\n };\n}\n\n// ============================================================================\n// BAZAAR DISCOVERY API\n// ============================================================================\n//\n// The Bazaar is the discovery registry served by the facilitator itself, under\n// `/discovery/*`. There is no separate Bazaar host.\n\n/**\n * Maximum length of the free-text `q` filter.\n *\n * Mirrors the facilitator's `MAX_SEARCH_LEN`; a longer needle is rejected\n * server-side with a 400.\n */\nexport const MAX_SEARCH_LEN = 128;\n\n/**\n * Liveness of a registered resource, as measured by the facilitator's prober.\n *\n * Resources that stop answering are quarantined rather than deleted, so filter\n * on this before paying anyone.\n */\nexport type DiscoveryHealthStatus =\n | 'alive'\n | 'degraded'\n | 'auth_gated'\n | 'quarantined'\n | 'unknown'\n | 'unprobeable';\n\n/** Values accepted by the `health` filter, including the `any` escape hatch. */\nexport const HEALTH_FILTERS = [\n 'alive',\n 'degraded',\n 'auth_gated',\n 'quarantined',\n 'unknown',\n 'unprobeable',\n 'any',\n] as const;\n\n/** Curated tier, in descending order of trust. */\nexport type DiscoveryTier = 'first_party' | 'vip' | 'verified' | 'listed';\n\n/** Values accepted by the `tier` filter. */\nexport const TIER_FILTERS = [\n 'first_party',\n 'vip',\n 'verified',\n 'listed',\n] as const;\n\n/** How a resource got into the registry. */\nexport type DiscoverySource =\n | 'self_registered'\n | 'settlement'\n | 'crawled'\n | 'aggregated';\n\n/** Health of a single resource, as reported by the registry's prober. */\nexport interface DiscoveryHealth {\n /** Last observed liveness */\n status?: DiscoveryHealthStatus;\n /** Unix epoch seconds of the last probe */\n lastChecked?: number;\n /** HTTP status the probe got back (402 is the healthy answer for x402) */\n httpStatus?: number;\n /** Round-trip time of the last probe, in milliseconds */\n latencyMs?: number;\n}\n\n/** Curation metadata attached to a resource. */\nexport interface DiscoveryCuration {\n /** Curated tier */\n tier?: DiscoveryTier;\n /** Human-readable name of the curated set */\n label?: string;\n}\n\n/** One payment method a resource declares. */\nexport interface DiscoveryAccepts {\n /** Payment scheme (\"exact\", \"escrow\", \"commerce\") */\n scheme: string;\n /** CAIP-2 network id, e.g. \"eip155:8453\" */\n network: string;\n /** Token contract address */\n asset?: string;\n /** Price in atomic units of `asset` */\n amount?: string;\n /** Recipient address */\n payTo?: string;\n /** Settlement deadline in seconds */\n maxTimeoutSeconds?: number;\n /** Scheme-specific extras (EIP-712 domain, etc.) */\n extra?: Record<string, unknown>;\n /** Anything the registry adds later */\n [key: string]: unknown;\n}\n\n/**\n * A discoverable paid resource, exactly as `GET /discovery/resources` serves it.\n *\n * Timestamps are Unix epoch **seconds**, not ISO strings and not milliseconds.\n */\nexport interface DiscoveryResource {\n /** Resource URL. This is the registry's primary key -- there is no `id` */\n url: string;\n /** Resource type (\"http\", \"mcp\", \"a2a\") */\n type: string;\n /** x402 protocol version the resource speaks */\n x402Version: number;\n /** Human-readable description */\n description?: string;\n /** Payment methods the resource accepts */\n accepts: DiscoveryAccepts[];\n /** Free-form metadata (category, provider, tags) */\n metadata?: Record<string, unknown>;\n /** How this resource entered the registry */\n source?: DiscoverySource;\n /** Facilitator this resource was aggregated from */\n sourceFacilitator?: string;\n /** Unix epoch seconds when the registry first saw this resource */\n firstSeen?: number;\n /** Unix epoch seconds when the registry last saw this resource */\n lastSeen?: number;\n /** Unix epoch seconds of the last change to this record */\n lastUpdated?: number;\n /** Liveness, when the resource has been probed */\n health?: DiscoveryHealth;\n /** Curation tier, when the resource has been curated */\n curation?: DiscoveryCuration;\n /** Anything the registry adds later */\n [key: string]: unknown;\n}\n\n/** Pagination envelope of `GET /discovery/resources`. */\nexport interface DiscoveryPagination {\n /** Page size that was applied */\n limit: number;\n /** Offset that was applied */\n offset: number;\n /** Total number of resources matching the filters, across all pages */\n total: number;\n}\n\n/** Paginated response from `GET /discovery/resources`. */\nexport interface DiscoveryResponse {\n /** x402 protocol version of the response envelope */\n x402Version: number;\n /** Resources on this page */\n items: DiscoveryResource[];\n /** Pagination state */\n pagination: DiscoveryPagination;\n}\n\n/**\n * Filters for `listResources()`.\n *\n * Every one of these is applied server-side over the whole catalog, so\n * `pagination.total` reflects the filtered set. Filtering a page after the\n * fact is not the same thing and will under-report.\n */\nexport interface DiscoveryListOptions {\n /** Page size (default: 10, max: 100) */\n limit?: number;\n /** Number of resources to skip */\n offset?: number;\n /** Filter by category */\n category?: string;\n /** Filter by network, CAIP-2 or v1 name */\n network?: string;\n /** Filter by provider name */\n provider?: string;\n /** Filter by tag */\n tag?: string;\n /** Filter by how the resource was discovered */\n source?: DiscoverySource;\n /** Filter by originating facilitator */\n sourceFacilitator?: string;\n /** Filter by liveness, or 'any' to opt out of the default visibility rules */\n health?: DiscoveryHealthStatus | 'any';\n /** Filter by curated tier */\n tier?: DiscoveryTier;\n /** Free-text search over url / description / provider / category / tags */\n q?: string;\n}\n\n/** Options for `registerResource()`. */\nexport interface DiscoveryRegisterOptions {\n /** URL of the paid resource. Doubles as its identity in the registry */\n url: string;\n /** Resource type (default: \"http\") */\n type?: string;\n /** Human-readable description */\n description?: string;\n /** Payment methods the resource accepts */\n accepts?: DiscoveryAccepts[];\n /** Free-form metadata (category, provider, tags) */\n metadata?: Record<string, unknown>;\n}\n\n/** Aggregate catalog metrics from `GET /discovery/stats`. */\nexport interface DiscoveryStats {\n /** Every record the registry holds, including quarantined ones */\n total: number;\n /** Records served by default listings */\n visible: number;\n /** Counts by discovery source */\n bySource: Record<string, number>;\n /** Counts by originating facilitator */\n bySourceFacilitator: Record<string, number>;\n /** Counts by CAIP-2 network */\n byNetwork: Record<string, number>;\n /** Counts by curated tier */\n byTier: Record<string, number>;\n /** Counts by liveness */\n byHealth: Record<string, number>;\n /** Unix epoch seconds this snapshot was computed (60s cache) */\n generatedAt?: number;\n}\n\n/** Options for the {@link BazaarClient}. */\nexport interface BazaarClientOptions {\n /** Facilitator base URL (default: https://facilitator.ultravioletadao.xyz) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\n/** Render an epoch-seconds field as a `Date`. */\nexport function epochToDate(seconds?: number): Date | undefined {\n return seconds === undefined ? undefined : new Date(seconds * 1000);\n}\n\n/** True when the last probe reached this resource. */\nexport function isAlive(resource: DiscoveryResource): boolean {\n return resource.health?.status === 'alive';\n}\n\n/**\n * Client for the x402 Bazaar Discovery API.\n *\n * The Bazaar is the facilitator's own registry of x402-enabled resources.\n * Providers register their endpoints and consumers discover them, with a\n * liveness probe and a curation tier attached to every record.\n *\n * @example\n * ```ts\n * const bazaar = new BazaarClient();\n *\n * // Only endpoints a probe actually reached, best-curated first\n * const page = await bazaar.listResources({ limit: 20, health: 'alive', tier: 'vip' });\n * for (const r of page.items) {\n * console.log(r.url, r.health?.status, r.health?.latencyMs, r.curation?.label);\n * }\n *\n * // Free-text search runs server-side over the whole catalog\n * const hits = await bazaar.listResources({ q: 'logs' });\n * console.log(hits.pagination.total);\n *\n * // Register your own\n * await bazaar.registerResource({\n * url: 'https://api.example.com/v1/generate',\n * description: 'Generate images with AI',\n * accepts: [{\n * scheme: 'exact',\n * network: 'eip155:8453',\n * asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * amount: '10000',\n * payTo: '0xYourWallet...',\n * maxTimeoutSeconds: 60,\n * }],\n * metadata: { category: 'ai', tags: ['image'] },\n * });\n * ```\n */\nexport class BazaarClient {\n private readonly baseUrl: string;\n private readonly timeout: number;\n\n constructor(options: BazaarClientOptions = {}) {\n this.baseUrl = (\n options.baseUrl || 'https://facilitator.ultravioletadao.xyz'\n ).replace(/\\/+$/, '');\n this.timeout = options.timeout || 30000;\n }\n\n /**\n * Issue a request against the facilitator with the configured timeout.\n */\n private async request<T>(path: string, init?: RequestInit): Promise<T> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: { Accept: 'application/json', ...(init?.headers || {}) },\n signal: controller.signal,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(\n `Bazaar API error: ${response.status} - ${errorText}`\n );\n }\n\n return (await response.json()) as T;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * List resources from the discovery registry.\n *\n * @param options - Server-side filters and pagination\n * @returns One page of resources plus the total across all pages\n *\n * @example\n * ```ts\n * const page = await bazaar.listResources({ network: 'eip155:8453', health: 'alive' });\n * ```\n */\n async listResources(\n options: DiscoveryListOptions = {}\n ): Promise<DiscoveryResponse> {\n if (options.q !== undefined && options.q.length > MAX_SEARCH_LEN) {\n throw new Error(`q must be at most ${MAX_SEARCH_LEN} characters`);\n }\n\n const params = new URLSearchParams();\n params.set('limit', String(options.limit ?? 10));\n params.set('offset', String(options.offset ?? 0));\n if (options.category) params.set('category', options.category);\n if (options.network) params.set('network', options.network);\n if (options.provider) params.set('provider', options.provider);\n if (options.tag) params.set('tag', options.tag);\n if (options.source) params.set('source', options.source);\n if (options.sourceFacilitator)\n params.set('sourceFacilitator', options.sourceFacilitator);\n if (options.health) params.set('health', options.health);\n if (options.tier) params.set('tier', options.tier);\n if (options.q) params.set('q', options.q);\n\n return this.request<DiscoveryResponse>(\n `/discovery/resources?${params.toString()}`\n );\n }\n\n /**\n * Walk the whole filtered catalog, one page at a time.\n *\n * Pages are fetched in sequence rather than in parallel: the read routes are\n * rate limited, and a burst of parallel pages is how a legitimate catalog\n * walk turns into a wall of 429s.\n *\n * @param options - Same filters as {@link listResources}; `limit` is the page size\n *\n * @example\n * ```ts\n * for await (const r of bazaar.iterateResources({ health: 'alive' })) {\n * console.log(r.url);\n * }\n * ```\n */\n async *iterateResources(\n options: DiscoveryListOptions = {}\n ): AsyncGenerator<DiscoveryResource, void, undefined> {\n const pageSize = options.limit ?? 100;\n let offset = options.offset ?? 0;\n\n for (;;) {\n const page = await this.listResources({\n ...options,\n limit: pageSize,\n offset,\n });\n if (page.items.length === 0) return;\n\n for (const item of page.items) yield item;\n\n offset += page.items.length;\n if (offset >= page.pagination.total) return;\n }\n }\n\n /**\n * Look up a single resource by its URL.\n *\n * The registry keys on URL and has no by-id lookup, so this searches and\n * then matches exactly.\n *\n * @param resourceUrl - Exact URL of the resource\n * @returns The resource, or null when it is not registered\n */\n async getResourceByUrl(\n resourceUrl: string\n ): Promise<DiscoveryResource | null> {\n const page = await this.listResources({\n q: resourceUrl.slice(0, MAX_SEARCH_LEN),\n limit: 100,\n health: 'any',\n });\n return page.items.find((item) => item.url === resourceUrl) ?? null;\n }\n\n /**\n * Register a paid resource in the discovery registry.\n *\n * Registration is open and rate limited; re-registering a known URL updates\n * the existing record rather than creating a duplicate.\n *\n * @param options - Resource details\n * @returns The registry's acknowledgement\n */\n async registerResource(\n options: DiscoveryRegisterOptions\n ): Promise<Record<string, unknown>> {\n const payload: Record<string, unknown> = {\n url: options.url,\n type: options.type || 'http',\n description: options.description || '',\n };\n if (options.accepts) payload.accepts = options.accepts;\n if (options.metadata) payload.metadata = options.metadata;\n\n return this.request<Record<string, unknown>>('/discovery/register', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n }\n\n /**\n * Aggregate catalog metrics (60s cached server-side).\n *\n * @returns Counts by source, facilitator, network, tier and liveness\n */\n async getStats(): Promise<DiscoveryStats> {\n return this.request<DiscoveryStats>('/discovery/stats');\n }\n\n /**\n * Check that the facilitator serving the registry is up.\n *\n * @returns True when the facilitator answers its health check\n */\n async healthCheck(): Promise<boolean> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n try {\n const response = await fetch(`${this.baseUrl}/health`, {\n method: 'GET',\n signal: controller.signal,\n });\n return response.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * @deprecated Renamed to {@link listResources}, which returns the registry's\n * real `{ items, pagination }` envelope. The old `discover()` returned a\n * `{ resources, page, totalPages }` shape that no endpoint ever served.\n */\n async discover(options: DiscoveryListOptions = {}): Promise<DiscoveryResponse> {\n return this.listResources(options);\n }\n}\n\n/**\n * @deprecated Use {@link DiscoveryResource}. The old shape (`id`, `name`,\n * `pricePerRequest`, `isActive`, ISO `createdAt`) described an API that was\n * never deployed.\n */\nexport type BazaarResource = DiscoveryResource;\n\n/** @deprecated Use {@link DiscoveryResponse}. */\nexport type BazaarDiscoverResponse = DiscoveryResponse;\n\n/** @deprecated Use {@link DiscoveryListOptions}. */\nexport type BazaarDiscoverOptions = DiscoveryListOptions;\n\n/** @deprecated Use {@link DiscoveryRegisterOptions}. */\nexport type BazaarRegisterOptions = DiscoveryRegisterOptions;\n\n// ============================================================================\n// ESCROW & REFUND EXTENSION\n// ============================================================================\n\n/**\n * Escrow payment status\n */\nexport type EscrowStatus =\n | 'pending' // Payment initiated, awaiting confirmation\n | 'held' // Funds held in escrow\n | 'released' // Funds released to recipient\n | 'refunded' // Funds returned to payer\n | 'disputed' // Dispute in progress\n | 'expired'; // Escrow expired without resolution\n\n/**\n * Refund request status\n */\nexport type RefundStatus =\n | 'pending' // Refund requested, awaiting processing\n | 'approved' // Refund approved\n | 'rejected' // Refund rejected\n | 'processed' // Refund completed on-chain\n | 'disputed'; // Under dispute review\n\n/**\n * Dispute resolution outcome\n */\nexport type DisputeOutcome =\n | 'pending' // Dispute under review\n | 'payer_wins' // Payer gets refund\n | 'recipient_wins' // Recipient keeps funds\n | 'split'; // Funds split between parties\n\n/**\n * Escrow payment record\n */\nexport interface EscrowPayment {\n /** Unique escrow ID */\n id: string;\n /** Original payment header (base64 encoded) */\n paymentHeader: string;\n /** Current status */\n status: EscrowStatus;\n /** Network where payment was made */\n network: string;\n /** Payer address */\n payer: string;\n /** Recipient address */\n recipient: string;\n /** Amount in atomic units */\n amount: string;\n /** Token/asset contract */\n asset: string;\n /** Resource URL being paid for */\n resource: string;\n /** Escrow expiration timestamp (ISO) */\n expiresAt: string;\n /** Release conditions (optional) */\n releaseConditions?: {\n /** Minimum time before release (seconds) */\n minHoldTime?: number;\n /** Required confirmations */\n confirmations?: number;\n /** Custom condition metadata */\n custom?: unknown;\n };\n /** Transaction hash if released/refunded */\n transactionHash?: string;\n /** Creation timestamp (ISO) */\n createdAt: string;\n /** Last update timestamp (ISO) */\n updatedAt: string;\n}\n\n/**\n * Refund request record\n */\nexport interface RefundRequest {\n /** Unique refund request ID */\n id: string;\n /** Related escrow ID */\n escrowId: string;\n /** Current status */\n status: RefundStatus;\n /** Reason for refund request */\n reason: string;\n /** Additional evidence/details */\n evidence?: string;\n /** Amount requested (may be partial) */\n amountRequested: string;\n /** Amount approved (if any) */\n amountApproved?: string;\n /** Requester (payer) address */\n requester: string;\n /** Transaction hash if processed */\n transactionHash?: string;\n /** Response from recipient/facilitator */\n response?: {\n status: 'approved' | 'rejected';\n reason?: string;\n respondedAt: string;\n };\n /** Creation timestamp (ISO) */\n createdAt: string;\n /** Last update timestamp (ISO) */\n updatedAt: string;\n}\n\n/**\n * Dispute record\n */\nexport interface Dispute {\n /** Unique dispute ID */\n id: string;\n /** Related escrow ID */\n escrowId: string;\n /** Related refund request ID (if any) */\n refundRequestId?: string;\n /** Dispute outcome */\n outcome: DisputeOutcome;\n /** Initiator (payer or recipient) */\n initiator: 'payer' | 'recipient';\n /** Reason for dispute */\n reason: string;\n /** Evidence from payer */\n payerEvidence?: string;\n /** Evidence from recipient */\n recipientEvidence?: string;\n /** Arbitration notes */\n arbitrationNotes?: string;\n /** Amount resolved to payer */\n payerAmount?: string;\n /** Amount resolved to recipient */\n recipientAmount?: string;\n /** Transaction hash(es) for resolution */\n transactionHashes?: string[];\n /** Creation timestamp (ISO) */\n createdAt: string;\n /** Resolution timestamp (ISO) */\n resolvedAt?: string;\n}\n\n/**\n * Options for creating an escrow payment\n */\nexport interface CreateEscrowOptions {\n /** Payment header (from client SDK) */\n paymentHeader: string;\n /** Payment requirements */\n requirements: PaymentRequirements;\n /** Escrow duration in seconds (default: 86400 = 24h) */\n escrowDuration?: number;\n /** Release conditions */\n releaseConditions?: {\n minHoldTime?: number;\n confirmations?: number;\n custom?: unknown;\n };\n}\n\n/**\n * Options for requesting a refund\n */\nexport interface RequestRefundOptions {\n /** Escrow ID to refund */\n escrowId: string;\n /** Reason for refund */\n reason: string;\n /** Amount to refund (full amount if not specified) */\n amount?: string;\n /** Supporting evidence */\n evidence?: string;\n}\n\n/**\n * Options for the EscrowClient\n */\nexport interface EscrowClientOptions {\n /** Base URL of the Escrow API (default: https://escrow.ultravioletadao.xyz) */\n baseUrl?: string;\n /** API key for authenticated operations */\n apiKey?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\n/**\n * Client for x402 Escrow & Refund operations\n *\n * The Escrow system holds payments until service is verified,\n * enabling refunds and dispute resolution.\n *\n * @example\n * ```ts\n * // Create escrow payment (backend)\n * const escrow = new EscrowClient();\n * const escrowPayment = await escrow.createEscrow({\n * paymentHeader: req.headers['x-payment'],\n * requirements: paymentRequirements,\n * escrowDuration: 86400, // 24 hours\n * });\n *\n * // After service is provided, release the escrow\n * await escrow.release(escrowPayment.id);\n *\n * // If service not provided, payer can request refund\n * await escrow.requestRefund({\n * escrowId: escrowPayment.id,\n * reason: 'Service not delivered within expected timeframe',\n * });\n * ```\n */\nexport class EscrowClient {\n private readonly baseUrl: string;\n private readonly apiKey?: string;\n private readonly timeout: number;\n\n constructor(options: EscrowClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://escrow.ultravioletadao.xyz';\n this.apiKey = options.apiKey;\n this.timeout = options.timeout || 30000;\n }\n\n private getHeaders(authenticated: boolean = false): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n };\n if (authenticated && this.apiKey) {\n headers['Authorization'] = `Bearer ${this.apiKey}`;\n }\n return headers;\n }\n\n /**\n * Create an escrow payment\n *\n * Holds the payment in escrow until released or refunded.\n *\n * @param options - Escrow creation options\n * @returns Created escrow payment\n */\n async createEscrow(options: CreateEscrowOptions): Promise<EscrowPayment> {\n const url = `${this.baseUrl}/escrow`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({\n paymentHeader: options.paymentHeader,\n paymentRequirements: options.requirements,\n escrowDuration: options.escrowDuration || 86400,\n releaseConditions: options.releaseConditions,\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get escrow payment by ID\n *\n * @param escrowId - Escrow payment ID\n * @returns Escrow payment details\n */\n async getEscrow(escrowId: string): Promise<EscrowPayment> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(escrowId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Release escrow funds to recipient\n *\n * Call this after service has been successfully provided.\n *\n * @param escrowId - Escrow payment ID\n * @returns Updated escrow payment with transaction hash\n */\n async release(escrowId: string): Promise<EscrowPayment> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(escrowId)}/release`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Request a refund for an escrow payment\n *\n * Initiates a refund request that must be approved.\n *\n * @param options - Refund request options\n * @returns Created refund request\n */\n async requestRefund(options: RequestRefundOptions): Promise<RefundRequest> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(options.escrowId)}/refund`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({\n reason: options.reason,\n amount: options.amount,\n evidence: options.evidence,\n }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Approve a refund request (for recipients)\n *\n * @param refundId - Refund request ID\n * @param amount - Amount to approve (may be less than requested)\n * @returns Updated refund request\n */\n async approveRefund(refundId: string, amount?: string): Promise<RefundRequest> {\n const url = `${this.baseUrl}/refund/${encodeURIComponent(refundId)}/approve`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ amount }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Reject a refund request (for recipients)\n *\n * @param refundId - Refund request ID\n * @param reason - Reason for rejection\n * @returns Updated refund request\n */\n async rejectRefund(refundId: string, reason: string): Promise<RefundRequest> {\n const url = `${this.baseUrl}/refund/${encodeURIComponent(refundId)}/reject`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ reason }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get refund request by ID\n *\n * @param refundId - Refund request ID\n * @returns Refund request details\n */\n async getRefund(refundId: string): Promise<RefundRequest> {\n const url = `${this.baseUrl}/refund/${encodeURIComponent(refundId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Open a dispute for an escrow payment\n *\n * Initiates arbitration when payer and recipient disagree.\n *\n * @param escrowId - Escrow payment ID\n * @param reason - Reason for dispute\n * @param evidence - Supporting evidence\n * @returns Created dispute\n */\n async openDispute(\n escrowId: string,\n reason: string,\n evidence?: string\n ): Promise<Dispute> {\n const url = `${this.baseUrl}/escrow/${encodeURIComponent(escrowId)}/dispute`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ reason, evidence }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Submit evidence to a dispute\n *\n * @param disputeId - Dispute ID\n * @param evidence - Evidence to submit\n * @returns Updated dispute\n */\n async submitEvidence(disputeId: string, evidence: string): Promise<Dispute> {\n const url = `${this.baseUrl}/dispute/${encodeURIComponent(disputeId)}/evidence`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(true),\n body: JSON.stringify({ evidence }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get dispute by ID\n *\n * @param disputeId - Dispute ID\n * @returns Dispute details\n */\n async getDispute(disputeId: string): Promise<Dispute> {\n const url = `${this.baseUrl}/dispute/${encodeURIComponent(disputeId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * List escrow payments (with filters)\n *\n * @param options - Filter and pagination options\n * @returns Paginated list of escrow payments\n */\n async listEscrows(options: {\n status?: EscrowStatus;\n payer?: string;\n recipient?: string;\n page?: number;\n limit?: number;\n } = {}): Promise<{\n escrows: EscrowPayment[];\n total: number;\n page: number;\n limit: number;\n hasMore: boolean;\n }> {\n const params = new URLSearchParams();\n if (options.status) params.set('status', options.status);\n if (options.payer) params.set('payer', options.payer);\n if (options.recipient) params.set('recipient', options.recipient);\n if (options.page) params.set('page', options.page.toString());\n if (options.limit) params.set('limit', options.limit.toString());\n\n const url = `${this.baseUrl}/escrow${params.toString() ? `?${params}` : ''}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: this.getHeaders(true),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Query on-chain escrow state from the facilitator\n *\n * Calls POST /escrow/state to read current escrow state without settlement.\n *\n * @param options - Escrow state query parameters\n * @returns On-chain escrow state (status, balance, timestamps)\n *\n * @example\n * ```ts\n * const state = await escrow.getEscrowState({\n * network: 'base-mainnet',\n * payer: '0xPayer...',\n * recipient: '0xRecipient...',\n * nonce: '0x1234...',\n * });\n * console.log(`Status: ${state.status}`);\n * ```\n */\n async getEscrowState(options: {\n network: string;\n payer: string;\n recipient: string;\n nonce: string;\n }): Promise<Record<string, unknown>> {\n const url = `${this.baseUrl}/escrow/state`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: this.getHeaders(),\n body: JSON.stringify(options),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Check Escrow API health\n *\n * @returns True if healthy\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await fetch(`${this.baseUrl}/health`, {\n method: 'GET',\n });\n return response.ok;\n } catch {\n return false;\n }\n }\n}\n\n// ============================================================================\n// ESCROW HELPER FUNCTIONS\n// ============================================================================\n\n/**\n * Check if an escrow can be released\n *\n * @param escrow - Escrow payment to check\n * @returns True if the escrow can be released\n */\nexport function canReleaseEscrow(escrow: EscrowPayment): boolean {\n if (escrow.status !== 'held') {\n return false;\n }\n\n // Check expiration\n if (new Date(escrow.expiresAt) < new Date()) {\n return false;\n }\n\n // Check minimum hold time if specified\n if (escrow.releaseConditions?.minHoldTime) {\n const createdAt = new Date(escrow.createdAt);\n const minReleaseTime = new Date(\n createdAt.getTime() + escrow.releaseConditions.minHoldTime * 1000\n );\n if (new Date() < minReleaseTime) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Check if an escrow can be refunded\n *\n * @param escrow - Escrow payment to check\n * @returns True if the escrow can be refunded\n */\nexport function canRefundEscrow(escrow: EscrowPayment): boolean {\n // Can only refund held or pending escrows\n return escrow.status === 'held' || escrow.status === 'pending';\n}\n\n/**\n * Check if an escrow is expired\n *\n * @param escrow - Escrow payment to check\n * @returns True if the escrow is expired\n */\nexport function isEscrowExpired(escrow: EscrowPayment): boolean {\n return new Date(escrow.expiresAt) < new Date();\n}\n\n/**\n * Calculate time remaining until escrow expires\n *\n * @param escrow - Escrow payment to check\n * @returns Milliseconds until expiration (negative if expired)\n */\nexport function escrowTimeRemaining(escrow: EscrowPayment): number {\n return new Date(escrow.expiresAt).getTime() - Date.now();\n}\n\n// ============================================================================\n// ERC-8004 TRUSTLESS AGENTS\n// ============================================================================\n\n/**\n * ERC-8004 extension identifier\n */\nexport const ERC8004_EXTENSION_ID = '8004-reputation';\n\n/**\n * Agent ID type: EVM uses sequential uint256 (number), Solana uses base58 pubkey (string)\n */\nexport type AgentId = number | string;\n\n/**\n * ERC-8004 contract addresses per network\n */\n// Mainnet addresses (CREATE2 deterministic - same on all mainnets)\nconst MAINNET_IDENTITY = '0x8004A169FB4a3325136EB29fA0ceB6D2e539a432';\nconst MAINNET_REPUTATION = '0x8004BAa17C55a88189AE136b182e5fdA19dE9b63';\n// Deployed after the identity/reputation pair, which is why it was missing here.\n// Verified live on all ten EVM mainnets; SKALE Base has no code at this address\n// and is the one mainnet that legitimately has no validation registry.\nconst MAINNET_VALIDATION = '0x8004Cc8439f36fd5F9F049D9fF86523Df6dAAB58';\n\n// Testnet addresses (same on all testnets)\nconst TESTNET_IDENTITY = '0x8004A818BFB912233c491871b3d84c89A494BD9e';\nconst TESTNET_REPUTATION = '0x8004B663056A597Dffe9eCcC1965A193B7388713';\nconst TESTNET_VALIDATION = '0x8004Cb1BF31DAf7788923b405b754f57acEB4272';\n\n// Solana program IDs (QuantuLabs 8004-solana)\nconst SOLANA_AGENT_REGISTRY = '8oo4dC4JvBLwy5tGgiH3WwK4B9PWxL9Z4XjA2jzkQMbQ';\nconst SOLANA_ATOM_ENGINE = 'AToMw53aiPQ8j7iHVb4fGt6nzUNxUhcPc3tbPBZuzVVb';\n\n/**\n * ERC-8004 contract addresses per network (21 networks: 19 EVM + 2 Solana)\n */\nexport const ERC8004_CONTRACTS: Record<string, {\n identityRegistry?: string;\n reputationRegistry?: string;\n validationRegistry?: string;\n agentRegistryProgram?: string;\n atomEngineProgram?: string;\n}> = {\n // Mainnets (11)\n ethereum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n base: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n polygon: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n arbitrum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n optimism: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n celo: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n bsc: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n monad: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n avalanche: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n scroll: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n // SKALE Base is the one mainnet without a validation registry (no code at\n // the canonical address), so leaving it out is correct, not an omission.\n 'skale-base': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n // Deprecated alias for 'base' -- kept so existing lookups keep resolving.\n 'base-mainnet': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n validationRegistry: MAINNET_VALIDATION,\n },\n // Testnets (8)\n 'ethereum-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'base-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'polygon-amoy': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'arbitrum-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'optimism-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'celo-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'avalanche-fuji': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n 'skale-base-sepolia': {\n identityRegistry: TESTNET_IDENTITY,\n reputationRegistry: TESTNET_REPUTATION,\n validationRegistry: TESTNET_VALIDATION,\n },\n // Solana (2) - uses QuantuLabs 8004-solana Anchor program + ATOM Engine\n solana: {\n agentRegistryProgram: SOLANA_AGENT_REGISTRY,\n atomEngineProgram: SOLANA_ATOM_ENGINE,\n },\n 'solana-devnet': {\n agentRegistryProgram: SOLANA_AGENT_REGISTRY,\n atomEngineProgram: SOLANA_ATOM_ENGINE,\n },\n};\n\n/**\n * Return the network name the facilitator actually accepts.\n *\n * `base-mainnet` reads like the canonical spelling and is not: the facilitator\n * answers `400 {\"error\": \"Invalid network: base-mainnet\"}`. Every name is passed\n * through here before it reaches a URL or a request body, so callers holding the\n * old spelling keep working instead of being rejected at the edge.\n */\nexport function wireNetwork(network: string): string {\n return network === 'base-mainnet' ? 'base' : network;\n}\n\n/**\n * Network type for ERC-8004 operations (21 networks: 19 EVM + 2 Solana)\n *\n * These are the names the FACILITATOR accepts, verified against\n * GET /feedback -> supportedNetworks. 'base-mainnet' is kept only as a\n * deprecated alias: the facilitator rejects it outright (400 \"Invalid network\"),\n * so anything passed through this module is normalised to 'base' before it\n * reaches the wire. Use 'base'.\n */\nexport type Erc8004Network =\n // EVM Mainnets\n | 'ethereum' | 'base' | 'polygon' | 'arbitrum' | 'optimism' | 'celo' | 'bsc' | 'monad' | 'avalanche' | 'scroll' | 'skale-base'\n // Deprecated alias, rewritten to 'base' before it reaches the wire\n | 'base-mainnet'\n // EVM Testnets\n | 'ethereum-sepolia' | 'base-sepolia' | 'polygon-amoy' | 'arbitrum-sepolia' | 'optimism-sepolia' | 'celo-sepolia' | 'avalanche-fuji' | 'skale-base-sepolia'\n // Solana (uses QuantuLabs 8004-solana Anchor program + ATOM Engine)\n | 'solana' | 'solana-devnet';\n\n/**\n * Networks where the facilitator serves the RELAYED feedback rail, i.e. where\n * Execution Market has deployed a `FeedbackDelegate` and the facilitator\n * verified it on-chain (code present, and its `REPUTATION_REGISTRY()` reads\n * back that network's registry).\n *\n * Anywhere else `POST /feedback/evm/prepare` answers 400 — and it should. An\n * invented delegate address would send a type-4 transaction to an account with\n * no code behind it, and in the EVM a `.call()` to an address with no code\n * RETURNS SUCCESS. The failure would look exactly like a rating that rated\n * nobody.\n *\n * `avalanche` is absent and is not waiting to join: the C-Chain rejects the\n * transaction type itself (`-32000 transaction type not supported`), so there\n * is nothing to deploy against. Anchor the rating on a chain that supports\n * EIP-7702; the payment stays where it was made.\n */\nexport const RELAYED_FEEDBACK_NETWORKS: readonly Erc8004Network[] = [\n 'base',\n 'ethereum',\n 'polygon',\n 'arbitrum',\n 'optimism',\n 'celo',\n 'bsc',\n 'monad',\n 'base-sepolia',\n] as const;\n\n/**\n * Whether `network` serves the rater-authored feedback rail.\n *\n * Lets a caller route without paying a round trip for a 400. The facilitator\n * re-checks the delegate on-chain on every request regardless — this list is a\n * routing hint, never the authority.\n */\nexport function supportsRelayedFeedback(network: string): boolean {\n return (RELAYED_FEEDBACK_NETWORKS as readonly string[]).includes(wireNetwork(network));\n}\n\n/**\n * An EIP-7702 authorization, as a wallet produces it.\n *\n * Needed only the first time a rater rates: it points their EOA at the\n * `FeedbackDelegate`. Once delegated, `prepare` answers `delegated: true` and\n * the submission carries no authorization at all.\n */\nexport interface RelayAuthorizationParams {\n /**\n * Chain the authorization is for.\n *\n * `0` is EIP-7702's wildcard and is valid on EVERY chain — a far broader\n * grant than pinning this one. Send the chain id `prepare` returned.\n */\n chainId: number;\n /**\n * The delegate the account is pointed at. Must be the address `prepare`\n * offered; the facilitator refuses anything else before it pays for a\n * transaction.\n */\n address: string;\n /** The rater account's nonce at the moment the authorization executes */\n nonce: number;\n yParity: number;\n r: string;\n s: string;\n}\n\n/**\n * Request body for `POST /feedback/evm/prepare`.\n *\n * `rater` is the address that will appear on-chain as the author, which is the\n * whole point of this rail.\n */\nexport interface PrepareRelayFeedbackRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n feedback: FeedbackParams & { rater: string };\n}\n\n/**\n * Response from `POST /feedback/evm/prepare`.\n *\n * Everything the rater has to sign so the CHAIN records them as the author\n * while the facilitator pays the gas.\n */\nexport interface PrepareRelayFeedbackResponse {\n success: boolean;\n /** The `FeedbackDelegate` the rater's EOA must be delegated to */\n delegate?: string;\n /** Registry calldata the rater is authorising, hex-encoded */\n data?: string;\n /**\n * The value the rater's signature must recover against.\n *\n * **The EIP-191 envelope is already applied here.** A holder of a raw key\n * signs this directly as a prehash (viem's `sign({ hash })`, ethers'\n * `signingKey.sign`). A WALLET must not be handed this value: `personal_sign`\n * applies the envelope itself, so it gets wrapped twice and recovers an\n * address that is not the rater. Wallets sign {@link signingPayload}.\n */\n digest?: string;\n /**\n * The same hash with the envelope still OFF — what a wallet signs.\n *\n * `keccak256('\\x19Ethereum Signed Message:\\n32' || signingPayload)` is\n * exactly {@link digest}, so a client can check the two against each other\n * rather than rebuilding the preimage from `data`.\n *\n * Requires facilitator v1.95.0+. Older facilitators omit it; a client that\n * needs it should fail loudly rather than fall back to signing `digest`\n * through a wallet, which produces a well-formed signature that authorises\n * nobody.\n */\n signingPayload?: string;\n /**\n * The full `eth_signTypedData_v4` payload. **v4 delegates only.**\n *\n * Present exactly when the delegate deployed on that chain is v4, which the\n * facilitator reads from the chain per request rather than assuming from a\n * release. **When it is present, sign IT** — the wallet renders the agent, the\n * score, the tags and the deadline as named fields, so the rater sees what\n * they authorise instead of a hex blob.\n *\n * v4 carries no {@link signingPayload} and needs none: `signTypedData` has no\n * envelope to apply twice, which is the entire class of bug that kept the v3\n * rail at zero signatures for days.\n *\n * Requires facilitator v1.96.0+.\n */\n typedData?: Record<string, unknown>;\n /**\n * Unix seconds after which the authorisation is void. Short on purpose:\n * relaying is permissionless, so a signed authorisation is live in the wild\n * until it expires.\n */\n deadline?: number;\n /** Single-use value binding this authorisation. Echo it back on submit */\n nonce?: string;\n /**\n * Whether the account is already delegated. When `false` the submission MUST\n * carry an `authorization`.\n */\n delegated: boolean;\n /** The account nonce to put in the EIP-7702 authorization, when needed */\n accountNonce?: number;\n chainId: number;\n error?: string;\n network: Erc8004Network;\n}\n\n/**\n * Request body for `POST /feedback/evm/submit`.\n *\n * The feedback parameters are not redundant with `prepare`: the facilitator\n * rebuilds the registry calldata from them and requires the rater's signature\n * to cover exactly that. It does not relay calldata it was handed.\n */\nexport interface SubmitRelayFeedbackRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n feedback: FeedbackParams & { rater: string };\n /** The deadline `prepare` returned */\n deadline: number;\n /** The single-use nonce `prepare` returned */\n nonce: string;\n /**\n * The rater's signature. It must recover to `rater` over `digest` — so\n * either a raw-key prehash signature over `digest`, or a wallet\n * `personal_sign` over `signingPayload`. Not `personal_sign` over `digest`.\n */\n signature: string;\n /** Required only when `prepare` answered `delegated: false` */\n authorization?: RelayAuthorizationParams;\n}\n\n/**\n * Request body for `POST /feedback/response/evm/prepare`.\n *\n * `responder` is the address the chain will record as the author.\n */\nexport interface PrepareRelayResponseRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n responder: string;\n agentId: number | string;\n /** WHOSE feedback is being answered — inside the signed struct. */\n clientAddress: string;\n /** Which feedback (1-indexed) — also inside the struct. */\n feedbackIndex: number;\n responseUri: string;\n responseHash?: string;\n}\n\n/** Request body for `POST /feedback/response/evm/submit`. */\nexport interface SubmitRelayResponseRequest {\n x402Version: 1 | 2;\n network: Erc8004Network;\n responder: string;\n agentId: number | string;\n clientAddress: string;\n feedbackIndex: number;\n responseUri: string;\n responseHash?: string;\n deadline: number;\n nonce: string;\n /** The responder's signature over the typed data. */\n signature: string;\n authorization?: RelayAuthorizationParams;\n}\n\n/**\n * Proof of payment returned when settling with ERC-8004 extension\n */\nexport interface ProofOfPayment {\n /** Transaction hash of the settled payment */\n transactionHash: string;\n /** Block number where the transaction was included */\n blockNumber: number;\n /** Network where the payment was settled */\n network: string;\n /** The payer (consumer/client) address */\n payer: string;\n /** The payee (agent/resource owner) address */\n payee: string;\n /** Amount paid in token base units */\n amount: string;\n /** Token contract address */\n token: string;\n /** Unix timestamp of the block */\n timestamp: number;\n /** Keccak256 hash of the payment data for verification */\n paymentHash: string;\n}\n\n/**\n * Extended settle response with ERC-8004 proof of payment\n */\nexport interface SettleResponseWithProof extends SettleResponse {\n /** Proof of payment for ERC-8004 reputation submission */\n proofOfPayment?: ProofOfPayment;\n}\n\n/**\n * Agent identity from the Identity Registry\n */\nexport interface AgentIdentity {\n /** The agent's ID (EVM: sequential uint256, Solana: base58 pubkey string) */\n agentId: AgentId;\n /** Owner address of the agent NFT */\n owner: string;\n /** URI pointing to agent registration file */\n agentUri: string;\n /** Payment wallet address (if set) */\n agentWallet?: string;\n /** Network where the agent is registered */\n network: Erc8004Network;\n}\n\n/**\n * Agent registration file structure (resolved from agentURI)\n */\nexport interface AgentRegistrationFile {\n /** Type identifier */\n type: string;\n /** Agent name */\n name: string;\n /** Agent description */\n description: string;\n /** Image URL */\n image?: string;\n /** List of services the agent provides */\n services: AgentService[];\n /** Whether x402 payments are supported */\n x402Support: boolean;\n /** Whether the agent is active */\n active: boolean;\n /** List of registrations across chains */\n registrations: AgentRegistration[];\n /** Supported trust models */\n supportedTrust: string[];\n}\n\n/**\n * Agent service entry\n */\nexport interface AgentService {\n name: string;\n endpoint: string;\n version?: string;\n}\n\n/**\n * Agent registration reference\n */\nexport interface AgentRegistration {\n agentId: AgentId;\n agentRegistry: string; // Format: {namespace}:{chainId}:{address}\n}\n\n/**\n * Reputation summary for an agent\n */\nexport interface ReputationSummary {\n /** Agent ID (EVM: number, Solana: string) */\n agentId: AgentId;\n /** Number of feedback entries */\n count: number;\n /** Aggregated value */\n summaryValue: number;\n /** Decimal places for summaryValue */\n summaryValueDecimals: number;\n /** Network */\n network: Erc8004Network;\n}\n\n/**\n * Individual feedback entry\n */\nexport interface FeedbackEntry {\n /** Client who submitted the feedback */\n client: string;\n /** Feedback index (1-indexed) */\n feedbackIndex: number;\n /** Feedback value */\n value: number;\n /** Value decimals */\n valueDecimals: number;\n /** Primary tag */\n tag1: string;\n /** Secondary tag */\n tag2: string;\n /** Whether this feedback was revoked */\n isRevoked: boolean;\n}\n\n/**\n * Parameters for submitting reputation feedback\n */\nexport interface FeedbackParams {\n /** The agent's ID (EVM: tokenId number, Solana: base58 pubkey string) */\n agentId: AgentId;\n /** Feedback value (e.g., 87 for 87/100) */\n value: number;\n /** Decimal places for value interpretation (0-18) */\n valueDecimals?: number;\n /** Primary categorization tag (e.g., \"starred\", \"uptime\") */\n tag1?: string;\n /** Secondary categorization tag */\n tag2?: string;\n /** Service endpoint that was used */\n endpoint?: string;\n /** URI to off-chain feedback file (IPFS, HTTPS) */\n feedbackUri?: string;\n /** Keccak256 hash of feedback content (for integrity) */\n feedbackHash?: string;\n /**\n * Quality score 0-100.\n *\n * Solana only, and effectively required there: the ATOM Engine ignores an\n * unscored feedback. It is written to the agent but contributes nothing to\n * reputation, and the program reports `had_impact=false`. This is not\n * retroactive — reputation stays at zero however much unscored feedback\n * accumulates.\n */\n score?: number;\n /** Proof of payment (required for authorized feedback) */\n proof?: ProofOfPayment;\n}\n\n/**\n * Feedback request body for POST /feedback\n */\nexport interface FeedbackRequest {\n /** x402 protocol version */\n x402Version: 1 | 2;\n /** Network where feedback will be submitted */\n network: Erc8004Network;\n /** Feedback parameters */\n feedback: FeedbackParams;\n}\n\n/**\n * Feedback response from POST /feedback\n */\nexport interface FeedbackResponse extends FacilitatorFailureFields {\n /** Whether the feedback was successfully submitted */\n success: boolean;\n /** Transaction hash of the feedback submission */\n transaction?: string;\n /** Feedback index assigned (1-indexed) */\n feedbackIndex?: number;\n /** Error message (if failed) */\n error?: string;\n /** Network where feedback was submitted */\n network: Erc8004Network;\n}\n\n/**\n * Reputation query response\n */\n/**\n * Error from an ERC-8004 lookup, carrying the HTTP status as a field.\n *\n * `notFound` and `retryable` are mutually exclusive and must stay that way in\n * calling code: the facilitator answers 404 for \"this address owns no agent\"\n * and 503 for \"I could not find out\", usually an RPC failure behind it.\n * Treating a 503 as absence is how a transient failure becomes a permanent\n * wrong answer — on a registration path it mints a second agent for an owner\n * who already has one, burning gas and leaving an orphan.\n */\nexport class Erc8004LookupError extends Error {\n /** HTTP status returned by the facilitator */\n readonly status: number;\n /** Raw response body, for debugging */\n readonly body: string;\n /**\n * `Retry-After`, already clamped, when the facilitator sent one.\n *\n * Optional so every existing three-argument construction keeps compiling; it\n * falls back to the default wait rather than to zero, because a caller that\n * retries instantly on a 503 is the load that caused it.\n */\n private readonly retryAfterHint: number | undefined;\n\n constructor(message: string, status: number, body: string, retryAfterSeconds?: number) {\n super(message);\n this.name = 'Erc8004LookupError';\n this.status = status;\n this.body = body;\n this.retryAfterHint = retryAfterSeconds;\n }\n\n /** The address genuinely owns no agent on this network. */\n get notFound(): boolean {\n return this.status === 404;\n }\n\n /**\n * The lookup reached no verdict. Retry; never read as \"owns nothing\".\n *\n * `502` and `504` join `503` and `429` here: a gateway that answered on the\n * facilitator's behalf is exactly as silent about the agent's existence, and\n * reading either as absence has the same consequence -- a duplicate mint.\n */\n get retryable(): boolean {\n return (\n this.status === 429 ||\n this.status === 502 ||\n this.status === 503 ||\n this.status === 504\n );\n }\n\n /**\n * The facilitator's own `reason`, when the body carried one.\n *\n * On a WRITE route this is the writer-lease reason and it decides whether the\n * request may be re-sent; see {@link isReplayableLeaseReason}.\n */\n get reason(): string | undefined {\n try {\n const parsed = JSON.parse(this.body) as { reason?: unknown };\n if (parsed && typeof parsed === 'object' && typeof parsed.reason === 'string') {\n return parsed.reason;\n }\n } catch {\n /* a non-JSON body is still a status */\n }\n return undefined;\n }\n\n /**\n * The facilitator NAMED a reason proving it executed nothing.\n *\n * False for `forward_failed` and for every unattributed 5xx: \"something\n * answered\" is not evidence that nothing ran. On `/register`, replaying when\n * this is false is the sequence that minted five duplicate agents.\n */\n get safeToReplay(): boolean {\n return this.status === 429 || (this.status === 503 && isReplayableLeaseReason(this.reason));\n }\n\n /** Seconds to wait before retrying, clamped. Absent when not retryable. */\n get retryAfterSeconds(): number | undefined {\n if (!this.retryable) return undefined;\n return this.retryAfterHint ?? DEFAULT_RETRY_AFTER_SECONDS;\n }\n}\n\n/**\n * ATOM Engine reputation analytics (Solana only).\n *\n * Present only when the agent's `atom_stats` account has been initialized. The\n * facilitator does that during `registerAgent`; agents registered elsewhere may\n * never have it, in which case their feedback is never scored.\n *\n * The engine measures quality through EMA scores, so there are no\n * positive/negative tallies.\n */\nexport interface AtomStats {\n /** Trust tier 0-4 */\n trustTier: number;\n /** Human-readable trust tier */\n trustTierName: string;\n /** Cached quality score */\n qualityScore: number;\n /** Cached loyalty score */\n loyaltyScore: number;\n /** Statistical confidence */\n confidence: number;\n /** Risk assessment (lower is better) */\n riskScore: number;\n /** Client diversity from HyperLogLog */\n diversityRatio: number;\n /** Lowest score ever recorded */\n minScore: number;\n /** Highest score ever recorded */\n maxScore: number;\n /** Most recent score recorded */\n lastScore: number;\n /** Total feedback counted by the engine */\n feedbackCount: number;\n /** Slot of the most recent feedback */\n lastFeedbackSlot: number;\n}\n\nexport interface ReputationResponse {\n agentId: AgentId;\n summary: ReputationSummary;\n feedback?: FeedbackEntry[];\n /** ATOM Engine analytics; absent when the agent has no initialized stats */\n atomStats?: AtomStats | null;\n network: Erc8004Network;\n}\n\n/**\n * Key-value metadata entry for agent registration\n */\nexport interface MetadataEntryParam {\n /** Metadata key */\n key: string;\n /** Metadata value (hex-encoded bytes or UTF-8 string) */\n value: string;\n}\n\n/**\n * Request body for POST /register\n */\nexport interface RegisterAgentRequest {\n /** x402 protocol version */\n x402Version: 1 | 2;\n /** Network where agent will be registered */\n network: Erc8004Network;\n /** URI pointing to agent registration file (IPFS, HTTPS) */\n agentUri: string;\n /** Optional metadata key-value pairs */\n metadata?: MetadataEntryParam[];\n /** Optional recipient address - NFT is transferred to this address after minting */\n recipient?: string;\n}\n\n/**\n * Response from POST /register\n */\nexport interface RegisterAgentResponse extends FacilitatorFailureFields {\n /** Whether registration succeeded */\n success: boolean;\n /** The newly assigned agent ID (EVM: tokenId number, Solana: base58 pubkey string) */\n agentId?: AgentId;\n /** Registration transaction hash */\n transaction?: string;\n /** Transfer transaction hash (if recipient was specified) */\n transferTransaction?: string;\n /** Owner address of the agent NFT */\n owner?: string;\n /** Error message if failed */\n error?: string;\n /** Network where agent was registered */\n network: string;\n}\n\n/**\n * Response from GET /identity/{network}/owner/{address}\n */\nexport interface IdentityByOwnerResponse {\n /** First (lowest) token ID owned by this address */\n agentId: AgentId;\n /** The queried address (checksummed) */\n owner: string;\n /** Agent's registration URI (may be empty) */\n agentUri: string;\n /** Network name */\n network: string;\n /** Total number of agent NFTs owned (as string) */\n balance: string;\n}\n\n/**\n * Response from GET /identity/{network}/{agent_id}/metadata/{key}\n */\n/**\n * Lifecycle of an async registration. `mint_confirmed` and `done` carry an\n * `agentId`; `failed` carries an `error`.\n */\nexport type RegisterJobStatus = 'pending' | 'mint_confirmed' | 'done' | 'failed';\n\n/**\n * Status of an asynchronous registration.\n *\n * Returned by `POST /register` with `Prefer: respond-async` (HTTP 202) and by\n * `GET /register/status/{jobId}`.\n *\n * Terminal jobs are retained for one hour and then age out, after which the\n * status endpoint 404s. Read the agent id before then, or it is only\n * recoverable from the chain.\n */\nexport interface RegisterJobResponse {\n jobId: string;\n status: RegisterJobStatus;\n network?: string;\n agentId?: AgentId;\n transaction?: string;\n transferTransaction?: string;\n owner?: string;\n error?: string;\n}\n\n/** Whether polling can stop: the job either finished or failed. */\nexport function isRegisterJobTerminal(job: RegisterJobResponse): boolean {\n return job.status === 'done' || job.status === 'failed';\n}\n\n/**\n * Thrown when a registration is still running after the wait elapsed.\n *\n * This is emphatically **not** a failure. The mint may still land. `jobId` is a\n * field rather than only part of the message, because the correct recovery is to\n * keep polling `getRegisterStatus(jobId)` — and a caller who cannot reach the id\n * without parsing a string will re-register instead, minting a duplicate agent.\n * That is the exact sequence that once produced five duplicate mints.\n *\n * Never map this to \"registration failed\".\n */\nexport class RegistrationPendingError extends Error {\n readonly jobId: string;\n readonly lastStatus: RegisterJobStatus;\n readonly timeoutMs: number;\n readonly retryable = true;\n\n constructor(jobId: string, lastStatus: RegisterJobStatus, timeoutMs: number) {\n super(\n `Registration job ${jobId} still '${lastStatus}' after ${Math.round(\n timeoutMs / 1000,\n )}s. It may still complete: poll getRegisterStatus('${jobId}') rather than registering again.`,\n );\n this.name = 'RegistrationPendingError';\n this.jobId = jobId;\n this.lastStatus = lastStatus;\n this.timeoutMs = timeoutMs;\n }\n}\n\n/**\n * Present a finished async job in the shape the synchronous call returns.\n *\n * Keeping the return type identical is the whole point of `asyncTransport`:\n * switching transports must not force callers to rewrite anything downstream.\n */\nfunction jobToRegisterResponse(\n job: RegisterJobResponse,\n network: Erc8004Network,\n): RegisterAgentResponse {\n return {\n success: job.status !== 'failed',\n agentId: job.agentId,\n transaction: job.transaction,\n transferTransaction: job.transferTransaction,\n owner: job.owner,\n error: job.error,\n network: (job.network as Erc8004Network) ?? network,\n };\n}\n\nexport interface IdentityMetadataResponse {\n /** Agent ID (EVM: number, Solana: string) */\n agentId: AgentId;\n /** Metadata key */\n key: string;\n /**\n * Raw hex-encoded value. The facilitator sends this as `value`; this field\n * used to be declared as `valueHex`, which no response ever carried, so it\n * was always undefined at runtime.\n */\n value: string;\n /** UTF-8 decoded value (if decodable) */\n valueUtf8?: string;\n /** Whether the entry can still be changed */\n immutable?: boolean;\n /** Network */\n network: string;\n}\n\n/**\n * Response from GET /identity/{network}/total-supply\n *\n * On Solana the counts come from the Metaplex Core collection, not the registry,\n * which keeps no counter of its own.\n */\nexport interface IdentityTotalSupplyResponse {\n /** Registered agents, net of burns */\n totalSupply: number;\n /** All-time mint count (Solana) */\n numMinted?: number;\n /** Metaplex Core collection backing the count (Solana) */\n collection?: string;\n /** Network */\n network: string;\n}\n\n/**\n * Options for the ERC8004Client\n */\nexport interface Erc8004ClientOptions {\n /** Base URL of the facilitator (default: https://facilitator.ultravioletadao.xyz) */\n baseUrl?: string;\n /** Request timeout in milliseconds (default: 30000) */\n timeout?: number;\n /**\n * Extra attempts after the first, spent only on a refusal the facilitator\n * proved it did not execute. Default 2; `0` disables. An ambiguous\n * `forward_failed` is never replayed at any setting.\n */\n retries?: number;\n}\n\n/**\n * Client for ERC-8004 Trustless Agents API\n *\n * Provides methods for:\n * - Registering new agents (gasless, facilitator pays gas)\n * - Registering agents on behalf of users (gasless delegation)\n * - Querying agent identity, metadata, and total supply\n * - Querying agent reputation\n * - Submitting reputation feedback\n * - Revoking feedback\n *\n * @example\n * ```ts\n * const client = new Erc8004Client();\n *\n * // Get agent identity\n * const identity = await client.getIdentity('ethereum', 42);\n * console.log(identity.agentUri);\n *\n * // Get agent reputation\n * const reputation = await client.getReputation('ethereum', 42);\n * console.log(`Score: ${reputation.summary.summaryValue}`);\n *\n * // Submit feedback after payment\n * const result = await client.submitFeedback({\n * x402Version: 1,\n * network: 'ethereum',\n * feedback: {\n * agentId: 42,\n * value: 95,\n * valueDecimals: 0,\n * tag1: 'quality',\n * proof: settleResponse.proofOfPayment,\n * },\n * });\n * ```\n */\nexport class Erc8004Client {\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly retries: number | undefined;\n\n constructor(options: Erc8004ClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';\n this.timeout = options.timeout || 30000;\n this.retries = options.retries;\n }\n\n /**\n * POST a write route, keeping a refusal readable.\n *\n * Every ERC-8004 write goes through the facilitator's EVM writer lease, so\n * every one of them can answer `503` + `reason`. Flattened to a string, those\n * are indistinguishable from \"the registry rejected your feedback\" — and on\n * `/register` the wrong reading re-POSTs a mint that may already have landed,\n * which is precisely how five duplicate agents were once created.\n *\n * A refusal the facilitator proved it did not execute is replayed\n * automatically (`safeToReplay`); `forward_failed` never is.\n */\n private async writeJson(\n url: string,\n body: unknown,\n extraHeaders: Record<string, string> = {},\n ): Promise<{ response: Response; error?: FacilitatorErrorInfo }> {\n return facilitatorFetch(\n url,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n ...extraHeaders,\n },\n body: JSON.stringify(body),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n }\n\n /**\n * Get agent identity from the Identity Registry\n *\n * @param network - Network where agent is registered\n * @param agentId - Agent's tokenId\n * @returns Agent identity information\n */\n async getIdentity(network: Erc8004Network, agentId: AgentId): Promise<AgentIdentity> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/${agentId}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get agent identity by owner address\n *\n * Resolves the first ERC-8004 agent ID owned by a wallet address on a given network.\n *\n * @param network - Network to query\n * @param address - Owner wallet address\n * @returns Agent identity information including balance\n *\n * @example\n * ```ts\n * const identity = await client.getIdentityByOwner('base-mainnet', '0x52E0...');\n * console.log(`Agent #${identity.agentId}, balance: ${identity.balance}`);\n * ```\n */\n async getIdentityByOwner(network: Erc8004Network, address: string): Promise<IdentityByOwnerResponse> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/owner/${address}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n }).finally(() => clearTimeout(timeoutId));\n\n if (!response.ok) {\n // 404 and 503 are different answers: \"owns nothing\" versus \"could not\n // find out\". Reading the status out of a message string is how they get\n // collapsed, and collapsing them mints a duplicate agent for an owner\n // who already has one. Carry the status, the reason and the wait as\n // fields.\n const info = await readFacilitatorError(response);\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${info.status} - ${info.body}`,\n info.status,\n info.body,\n info.retryAfterSeconds,\n );\n }\n\n return await response.json();\n }\n\n /**\n * Resolve agent registration file from agentURI\n *\n * @param agentUri - URI pointing to agent registration file\n * @returns Resolved agent registration file\n */\n async resolveAgentUri(agentUri: string): Promise<AgentRegistrationFile> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n // Handle IPFS URIs\n let url = agentUri;\n if (agentUri.startsWith('ipfs://')) {\n const cid = agentUri.replace('ipfs://', '');\n url = `https://ipfs.io/ipfs/${cid}`;\n }\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`Failed to resolve agentURI: ${response.status}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get agent reputation from the Reputation Registry\n *\n * @param network - Network where agent is registered\n * @param agentId - Agent's tokenId\n * @param options - Query options (tag filters, include individual feedback, client addresses)\n * @param options.clientAddresses - Comma-separated client addresses to filter by.\n * If omitted, the facilitator auto-discovers all clients via getClients().\n * @returns Reputation summary and optionally individual feedback entries\n */\n async getReputation(\n network: Erc8004Network,\n agentId: AgentId,\n options: {\n tag1?: string;\n tag2?: string;\n includeFeedback?: boolean;\n clientAddresses?: string;\n } = {}\n ): Promise<ReputationResponse> {\n const params = new URLSearchParams();\n if (options.tag1) params.set('tag1', options.tag1);\n if (options.tag2) params.set('tag2', options.tag2);\n if (options.includeFeedback) params.set('includeFeedback', 'true');\n if (options.clientAddresses) params.set('clientAddresses', options.clientAddresses);\n\n const url = `${this.baseUrl}/reputation/${wireNetwork(network)}/${agentId}${params.toString() ? `?${params}` : ''}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Submit reputation feedback for an agent\n *\n * Requires proof of payment for authorized feedback submission.\n *\n * @deprecated On this route the facilitator is the AUTHOR: the registry\n * records `msg.sender`, and that is the facilitator's wallet — which can also\n * revoke what it wrote. On the networks in {@link RELAYED_FEEDBACK_NETWORKS}\n * use {@link Erc8004Client.prepareRelayedFeedback} +\n * {@link Erc8004Client.submitRelayedFeedback} instead, which record the RATER\n * as author. This route still works and is not going away without notice: it\n * is the only one available where no `FeedbackDelegate` is deployed.\n *\n * @param request - Feedback request with agent ID, value, and proof\n * @returns Feedback response with transaction hash\n *\n * @example\n * ```ts\n * // After settling a payment with ERC-8004 extension\n * const settleResult = await facilitator.settle(payment, {\n * ...requirements,\n * extra: { '8004-reputation': { includeProof: true } },\n * });\n *\n * // Submit feedback with proof of payment\n * const feedback = await erc8004.submitFeedback({\n * x402Version: 1,\n * network: 'ethereum',\n * feedback: {\n * agentId: 42,\n * value: 95, // 95/100\n * valueDecimals: 0,\n * tag1: 'quality',\n * tag2: 'response-time',\n * proof: settleResult.proofOfPayment,\n * },\n * });\n * ```\n */\n async submitFeedback(request: FeedbackRequest): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback`;\n\n try {\n const { response, error } = await this.writeJson(url, {\n ...request,\n network: wireNetwork(request.network),\n });\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network: request.network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // Timeout or connection failure: the write may already be on-chain.\n // Retryable, never replayable -- reconcile before resending.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Ask the facilitator what the rater must sign to author a rating.\n *\n * Step 1 of the rater-authored rail. Writes nothing on-chain and costs\n * nothing: it reads the delegate, the rater's delegation state and their\n * account nonce, then hands back a digest, a deadline and a single-use nonce.\n *\n * Why this exists: the ERC-8004 Reputation Registry records `msg.sender` as\n * the author, and the deployed implementation has no delegation path — no\n * `giveFeedbackWithSignature`, no ERC-2771 forwarder. So a rating the\n * facilitator relays the ordinary way is a rating attributed to the\n * FACILITATOR. EIP-7702 fixes it without touching the registry: the rater\n * delegates their own EOA to the `FeedbackDelegate` and the transaction is\n * sent TO THE RATER'S ADDRESS, so the registry sees the rater while the\n * facilitator pays.\n *\n * What to do with the answer:\n * 1. Produce the rater's signature. **Which value you sign depends on how you\n * sign it**, and getting it wrong yields a well-formed signature that\n * authorises nobody:\n * - raw key: sign `digest` as a **prehash**. It already carries the\n * EIP-191 envelope.\n * - wallet: `personal_sign` over `signingPayload`. `personal_sign` adds the\n * envelope itself, so signing `digest` with it wraps the value TWICE and\n * recovers a stranger — the only symptom is `relay_bad_signature`.\n * - **unless `typedData` came back** — that chain runs a v4 delegate. Then\n * sign THAT with `eth_signTypedData_v4` and ignore the other two: it is\n * the only form the rater can read, and it has no envelope ambiguity.\n * 2. If `delegated` is `false`, also produce an EIP-7702 authorization over\n * `(chainId, delegate, accountNonce)`.\n * 3. Hand both to {@link submitRelayedFeedback} with the SAME feedback\n * parameters, `deadline` and `nonce`.\n *\n * @param request - Network, rater address and feedback parameters\n * @returns Everything needed to sign, including whether an EIP-7702\n * authorization is still required\n *\n * @example\n * ```ts\n * const prep = await erc8004.prepareRelayedFeedback({\n * x402Version: 1,\n * network: 'base',\n * feedback: { agentId: 18896, value: 95, tag1: 'quality', rater: raterAddress },\n * });\n * // prep.delegated === false -> an EIP-7702 authorization is required\n * ```\n */\n async prepareRelayedFeedback(\n request: PrepareRelayFeedbackRequest,\n ): Promise<PrepareRelayFeedbackResponse> {\n const url = `${this.baseUrl}/feedback/evm/prepare`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify({ ...request, network: wireNetwork(request.network) }),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n success: false,\n delegated: false,\n chainId: 0,\n error: `Facilitator error: ${response.status} - ${errorText}`,\n network: request.network,\n };\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n delegated: false,\n chainId: 0,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n };\n }\n }\n\n /**\n * Relay a rater-authored rating; the facilitator pays the gas.\n *\n * Step 2 of the rater-authored rail. The on-chain record that comes out of it\n * has the RATER as `msg.sender`, so `getClients(agentId)` shows the rater\n * rather than the facilitator.\n *\n * Pass back the same feedback parameters, `deadline` and `nonce` that\n * {@link prepareRelayedFeedback} returned. They are not redundant: the\n * facilitator rebuilds the registry calldata from them and requires the\n * rater's signature to cover exactly that.\n *\n * `authorization` is required only when `prepare` answered\n * `delegated: false`. One that names a different delegate than the one\n * `prepare` offered is refused before any gas is spent.\n *\n * @param request - Feedback parameters plus the rater's signature\n * @returns Feedback response with the transaction hash\n */\n async submitRelayedFeedback(\n request: SubmitRelayFeedbackRequest,\n ): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback/evm/submit`;\n\n try {\n const { response, error } = await this.writeJson(url, {\n ...request,\n network: wireNetwork(request.network),\n });\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network: request.network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // Timeout or connection failure: the write may already be on-chain.\n // Retryable, never replayable -- reconcile before resending.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Revoke previously submitted feedback\n *\n * Only the original submitter can revoke their feedback.\n *\n * @param network - Network where feedback was submitted\n * @param agentId - Agent ID\n * @param feedbackIndex - Index of feedback to revoke\n * @returns Revocation result\n */\n async revokeFeedback(\n network: Erc8004Network,\n agentId: AgentId,\n feedbackIndex: number,\n options?: { sealHash?: string; originalFeedback?: Omit<FeedbackParams, 'agentId' | 'proof'> }\n ): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback/revoke`;\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n network: wireNetwork(network),\n agentId,\n feedbackIndex,\n };\n // Solana revocations need the SEAL hash of the feedback being revoked. Pass\n // originalFeedback and the facilitator derives it; computing it yourself\n // means reimplementing the program's keccak256 layout exactly.\n if (options?.sealHash) {\n payload.sealHash = options.sealHash;\n } else if (options?.originalFeedback) {\n payload.originalFeedback = options.originalFeedback;\n }\n\n try {\n const { response, error } = await this.writeJson(url, payload);\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Get ERC-8004 contract addresses for a network\n *\n * @param network - Network to get contracts for\n * @returns Contract addresses or undefined if not deployed\n */\n getContracts(network: Erc8004Network): typeof ERC8004_CONTRACTS[Erc8004Network] | undefined {\n return ERC8004_CONTRACTS[network];\n }\n\n /**\n * Check if ERC-8004 is available on a network\n *\n * @param network - Network to check\n * @returns True if ERC-8004 contracts are deployed\n */\n isAvailable(network: string): network is Erc8004Network {\n return network in ERC8004_CONTRACTS;\n }\n\n /**\n * Get feedback endpoint metadata\n *\n * @returns Endpoint information for /feedback\n */\n async getFeedbackMetadata(): Promise<{\n endpoint: string;\n supportedNetworks: Erc8004Network[];\n version: string;\n }> {\n const url = `${this.baseUrl}/feedback`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n throw new Error(`Failed to get feedback metadata: ${response.status}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Ask what the RESPONDER must sign to author a response on-chain.\n *\n * The mirror of {@link prepareRelayedFeedback}, for the other write the\n * registry accepts from anybody. `appendResponse` is not agent-only — the\n * registry takes it from any address — so on the plain {@link appendResponse}\n * route the `responder` recorded on-chain is the FACILITATOR. That does not\n * destroy anyone's reputation the way a revoke would; it ties the\n * facilitator's on-chain identity to a third party's content, which is its own\n * kind of wrong.\n *\n * **v4 delegates only.** The v3 delegate accepts exactly two selectors and\n * `appendResponse` is not one of them, so a v3 network answers 400\n * `relay_response_needs_v4` rather than silently falling back to the route\n * this replaces.\n *\n * `clientAddress` and `feedbackIndex` are inside the signed struct: without\n * them one signature would answer any client's rating, or any rating at that\n * index.\n */\n async prepareRelayedResponse(\n request: PrepareRelayResponseRequest\n ): Promise<PrepareRelayFeedbackResponse> {\n return this.postRelay('/feedback/response/evm/prepare', request, {\n success: false,\n delegated: false,\n chainId: 0,\n network: request.network,\n });\n }\n\n /**\n * Relay a responder-authored response; the facilitator pays the gas.\n *\n * Pass back the same parameters, `deadline` and `nonce` that\n * {@link prepareRelayedResponse} returned: the facilitator rebuilds the struct\n * from them and refuses to relay anything the signature does not cover.\n */\n async submitRelayedResponse(\n request: SubmitRelayResponseRequest\n ): Promise<FeedbackResponse> {\n return this.postRelay('/feedback/response/evm/submit', request, {\n success: false,\n network: request.network,\n });\n }\n\n /** Shared POST for the relay routes: a refusal is data, never a throw. */\n private async postRelay<T>(path: string, request: { network: Erc8004Network }, onError: T): Promise<T> {\n try {\n const { response, error } = await this.writeJson(`${this.baseUrl}${path}`, {\n ...request,\n network: wireNetwork(request.network),\n });\n if (error) {\n return { ...onError, error: error.error, ...failureFields(error) };\n }\n return await response.json();\n } catch (error) {\n return {\n ...onError,\n error: error instanceof Error ? error.message : 'Unknown error',\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Append a response to existing feedback\n *\n * @deprecated On this route the facilitator is the AUTHOR: the registry\n * records `msg.sender` as the `responder`, and that is the facilitator's\n * wallet. Where the delegate is **v4**, use {@link prepareRelayedResponse} +\n * {@link submitRelayedResponse} instead. This route still works and is the\n * only one available where the delegate is still v3.\n *\n * **This is NOT agent-only**, despite what this comment claimed until\n * 2026-08-25. Verified on-chain on 2026-08-18: the registry accepts\n * `appendResponse` from ANY address. There is no identity-owner check, here or\n * in the contract.\n *\n * @param network - Network where feedback was submitted\n * @param agentId - Agent ID\n * @param feedbackIndex - Index of feedback to respond to\n * @param response - Response content\n * @param responseUri - Optional URI to off-chain response file\n * @returns Response result\n *\n * @example\n * ```ts\n * // Agent responds to feedback\n * const result = await erc8004.appendResponse(\n * 'ethereum',\n * 42,\n * 1,\n * 'Thank you for your feedback! We have addressed the issue.',\n * );\n * ```\n */\n async appendResponse(\n network: Erc8004Network,\n agentId: AgentId,\n feedbackIndex: number,\n response: string,\n options?: { responseUri?: string; sealHash?: string }\n ): Promise<FeedbackResponse> {\n const url = `${this.baseUrl}/feedback/response`;\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n network: wireNetwork(network),\n agentId,\n feedbackIndex,\n response,\n };\n if (options?.responseUri) {\n payload.responseUri = options.responseUri;\n }\n if (options?.sealHash) {\n payload.sealHash = options.sealHash;\n }\n\n try {\n const { response: fetchResponse, error } = await this.writeJson(url, payload);\n\n if (error) {\n return {\n success: false,\n error: error.error,\n network,\n ...failureFields(error),\n };\n }\n\n return await fetchResponse.json();\n } catch (error) {\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Register an agent on the Identity Registry (idempotent)\n *\n * If the recipient already owns an agent on the target network, returns the\n * existing one instead of minting a duplicate. The facilitator pays gas fees.\n * Optionally transfer the NFT to a recipient address (gasless delegation).\n *\n * @param request - Registration request\n * @returns Registration response with agent ID and transaction hash\n *\n * @example\n * ```ts\n * // Register agent owned by facilitator\n * const result = await client.registerAgent({\n * x402Version: 1,\n * network: 'ethereum',\n * agentUri: 'ipfs://QmYourAgentFile',\n * });\n * console.log(`Agent #${result.agentId} registered`);\n *\n * // Register agent and transfer to user\n * const result = await client.registerAgent({\n * x402Version: 1,\n * network: 'ethereum',\n * agentUri: 'ipfs://QmYourAgentFile',\n * recipient: '0xUserAddress...',\n * });\n * console.log(`Agent #${result.agentId} transferred to user`);\n * ```\n */\n async registerAgent(\n request: RegisterAgentRequest,\n options?: { asyncTransport?: boolean; pollIntervalMs?: number; timeoutMs?: number },\n ): Promise<RegisterAgentResponse> {\n // asyncTransport changes how the wait is carried out, not what comes back.\n // The synchronous call holds one HTTP request open for the whole mint, which\n // on a congested chain outlives proxy timeouts; each poll here is short, so\n // nothing in the path can time out ambiguously.\n if (options?.asyncTransport) {\n const job = await this.registerAgentAsync(request);\n const terminal = await this.waitForRegistration(job.jobId, {\n pollIntervalMs: options.pollIntervalMs,\n timeoutMs: options.timeoutMs,\n });\n return jobToRegisterResponse(terminal, request.network);\n }\n\n const url = `${this.baseUrl}/register`;\n\n try {\n const { response, error } = await this.writeJson(url, {\n ...request,\n network: wireNetwork(request.network),\n });\n\n if (error) {\n // The facilitator answers 4xx with a structured RegisterAgentResponse,\n // and on 409 - a registration for this agent is ALREADY IN FLIGHT -\n // that body carries the agent id and tx of the run already underway,\n // plus an explicit \"poll GET /register/status/{jobId}\" hint.\n //\n // Flattening it into a bare string threw away the only thing that lets\n // a caller resolve instead of re-POSTing, and re-POSTing a mint is\n // exactly how duplicate agents get created. Keep the body.\n try {\n const parsed = JSON.parse(error.body) as RegisterAgentResponse;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return {\n ...parsed,\n // Never let a non-2xx body claim success, whatever it says.\n success: false,\n error: parsed.error ?? `Facilitator error: ${error.status}`,\n network: parsed.network ?? request.network,\n ...failureFields(error),\n };\n }\n } catch {\n // Not JSON - fall through to the flattened error.\n }\n return {\n success: false,\n error: error.error,\n network: request.network,\n ...failureFields(error),\n };\n }\n\n return await response.json();\n } catch (error) {\n // A MINT that timed out is the single most dangerous ambiguity in this\n // SDK: the transaction may be mining right now. `safeToReplay: false`\n // says so out loud. Resolve with\n // `GET /identity/{network}/owner/{recipient}` -- honouring its 404-vs-503\n // distinction -- or with `getRegisterStatus`, never by re-POSTing.\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\n retryable: true,\n safeToReplay: false,\n retryAfterSeconds: DEFAULT_RETRY_AFTER_SECONDS,\n };\n }\n }\n\n /**\n * Start a registration without waiting for the chain to confirm it.\n *\n * Registration waits on a mint receipt, which on a congested chain outlives\n * client and proxy timeouts. A timed-out synchronous call is genuinely\n * ambiguous — the mint may well have landed — and retrying it is how five\n * duplicate agents once got minted. This returns immediately with a job id\n * instead; poll {@link getRegisterStatus} or use {@link waitForRegistration}.\n *\n * On Solana, `recipient` is a base58 address: the facilitator mints,\n * initializes the ATOM stats and transfers, paying every fee.\n */\n async registerAgentAsync(request: RegisterAgentRequest): Promise<RegisterJobResponse> {\n const url = `${this.baseUrl}/register`;\n\n // A 503 here is the SAFE half of the register story: the job was never\n // created, so a replay creates one job, not two. `writeJson` replays only\n // what the facilitator proved it did not execute, and never\n // `forward_failed`.\n const { response, error } = await this.writeJson(\n url,\n { ...request, network: wireNetwork(request.network) },\n { Prefer: 'respond-async' },\n );\n\n if (error) {\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${error.status} - ${error.body}`,\n error.status,\n error.body,\n error.retryAfterSeconds,\n );\n }\n\n return await response.json();\n }\n\n /**\n * Read the current state of an asynchronous registration.\n *\n * Throws {@link Erc8004LookupError} with `notFound` when the job is unknown or\n * has aged out — terminal jobs are kept for one hour.\n */\n async getRegisterStatus(jobId: string): Promise<RegisterJobResponse> {\n const url = `${this.baseUrl}/register/status/${encodeURIComponent(jobId)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const response = await fetch(url, {\n method: 'GET',\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n }).finally(() => clearTimeout(timeoutId));\n\n if (!response.ok) {\n const info = await readFacilitatorError(response);\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${info.status} - ${info.body}`,\n info.status,\n info.body,\n info.retryAfterSeconds,\n );\n }\n\n return await response.json();\n }\n\n /**\n * Poll an asynchronous registration until it finishes.\n *\n * Rejects on timeout rather than resolving with the last non-terminal status,\n * so \"still pending\" is never mistaken for \"did not happen\": the mint may\n * still land afterwards, and treating a timeout as failure is what leads to\n * registering the same agent twice. Keep the job id and poll again rather\n * than re-registering.\n */\n async waitForRegistration(\n jobId: string,\n options?: { pollIntervalMs?: number; timeoutMs?: number },\n ): Promise<RegisterJobResponse> {\n const pollIntervalMs = options?.pollIntervalMs ?? 2000;\n const timeoutMs = options?.timeoutMs ?? 300_000;\n const deadline = Date.now() + timeoutMs;\n\n for (;;) {\n const job = await this.getRegisterStatus(jobId);\n if (isRegisterJobTerminal(job)) {\n return job;\n }\n if (Date.now() >= deadline) {\n throw new RegistrationPendingError(jobId, job.status, timeoutMs);\n }\n await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));\n }\n }\n\n /**\n * Get registration endpoint metadata\n *\n * @returns Endpoint information for POST /register\n */\n async getRegisterInfo(): Promise<Record<string, unknown>> {\n const url = `${this.baseUrl}/register`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get a specific metadata entry for an agent\n *\n * @param network - Network where agent is registered\n * @param agentId - Agent's tokenId\n * @param key - Metadata key to retrieve\n * @returns Metadata value (hex-encoded and UTF-8 decoded if possible)\n */\n async getIdentityMetadata(\n network: Erc8004Network,\n agentId: AgentId,\n key: string,\n ): Promise<IdentityMetadataResponse> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/${agentId}/metadata/${encodeURIComponent(key)}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n\n /**\n * Get total number of registered agents on a network\n *\n * @param network - Network to query\n * @returns Total supply count\n */\n async getIdentityTotalSupply(network: Erc8004Network): Promise<IdentityTotalSupplyResponse> {\n const url = `${this.baseUrl}/identity/${wireNetwork(network)}/total-supply`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'GET',\n headers: { 'Accept': 'application/json' },\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`ERC-8004 API error: ${response.status} - ${errorText}`);\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\n }\n}\n\n/**\n * Build payment requirements with ERC-8004 extension\n *\n * Adds the 8004-reputation extension to include proof of payment\n * in settlement responses for reputation submission.\n *\n * @param options - Base payment requirements options\n * @returns Payment requirements with ERC-8004 extension\n *\n * @example\n * ```ts\n * const requirements = buildErc8004PaymentRequirements({\n * amount: '1.00',\n * recipient: '0x...',\n * resource: 'https://api.example.com/service',\n * chainName: 'ethereum',\n * });\n *\n * // Settlement will include proofOfPayment\n * const result = await facilitator.settle(payment, requirements);\n * console.log(result.proofOfPayment);\n * ```\n */\nexport function buildErc8004PaymentRequirements(\n options: PaymentRequirementsOptions\n): PaymentRequirements & { extra: { '8004-reputation': { includeProof: boolean } } } {\n const base = buildPaymentRequirements(options);\n return {\n ...base,\n extra: {\n [ERC8004_EXTENSION_ID]: {\n includeProof: true,\n },\n },\n };\n}\n\n// ============================================================================\n// ADVANCED ESCROW (PaymentOperator - On-Chain Escrow)\n// ============================================================================\n//\n// The 5 Advanced Escrow flows via the PaymentOperator contract:\n// 1. AUTHORIZE - Lock funds in escrow (via facilitator)\n// 2. RELEASE - Capture escrowed funds to receiver (on-chain)\n// 3. REFUND IN ESCROW - Return escrowed funds to payer (on-chain)\n// 4. CHARGE - Direct instant payment without escrow (on-chain)\n// 5. REFUND POST ESCROW - Dispute refund after release (on-chain)\n//\n// Contract mapping:\n// operator.authorize() -> escrow.authorize() (lock funds)\n// operator.release() -> escrow.capture() (pay receiver)\n// operator.refundInEscrow() -> escrow.partialVoid() (refund payer)\n// operator.charge() -> escrow.charge() (direct payment)\n// operator.refundPostEscrow() -> escrow.refund() (dispute refund)\n// ============================================================================\n\n/**\n * PAYMENT_INFO_TYPEHASH used for nonce computation.\n * Must match the on-chain AuthCaptureEscrow contract.\n */\nexport const PAYMENT_INFO_TYPEHASH =\n '0xae68ac7ce30c86ece8196b61a7c486d8f0061f575037fbd34e7fe4e2820c6591';\n\nexport const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';\n\n/**\n * Contract deposit limit (enforced by PaymentOperator condition).\n * As of 2026-02-03, commerce-payments contracts enforce $100 max per deposit.\n */\nexport const DEPOSIT_LIMIT_USDC = '100000000'; // $100 in atomic units (6 decimals)\n\n/**\n * Default facilitator request timeout per chain in milliseconds.\n * Ethereum L1 (~12s blocks) needs much longer than L2s (~2s blocks).\n * Timeout chain: Client > SDK > Facilitator. The facilitator uses 900s for Ethereum L1.\n */\nexport const ESCROW_TIMEOUT_MS: Record<number, number> = {\n 1: 960_000, // Ethereum L1: 960s (facilitator uses 900s TxWatcher)\n 11155111: 960_000, // Ethereum Sepolia: same as L1\n 137: 90_000, // Polygon: 90s\n 8453: 90_000, // Base: 90s\n 84532: 90_000, // Base Sepolia: 90s\n 42161: 90_000, // Arbitrum: 90s\n 10: 90_000, // Optimism: 90s\n 43114: 90_000, // Avalanche: 90s\n 42220: 90_000, // Celo: 90s\n 143: 90_000, // Monad: 90s\n};\n\n/** Default timeout when chain is not in ESCROW_TIMEOUT_MS */\nconst DEFAULT_ESCROW_TIMEOUT_MS = 30_000;\n\n/**\n * USDC EIP-712 domain name per chain.\n * Most chains use \"USD Coin\", but some (Celo, Monad, HyperEVM) use \"USDC\".\n * This must match the on-chain token's name() for EIP-712 signing to work.\n */\nexport const USDC_DOMAIN_NAME: Record<number, string> = {\n 8453: 'USD Coin', // Base Mainnet\n 84532: 'USD Coin', // Base Sepolia\n 1: 'USD Coin', // Ethereum Mainnet\n 11155111: 'USD Coin', // Ethereum Sepolia\n 137: 'USD Coin', // Polygon\n 42161: 'USD Coin', // Arbitrum\n 43114: 'USD Coin', // Avalanche\n 42220: 'USDC', // Celo\n 143: 'USDC', // Monad\n};\n\n/**\n * Multi-chain escrow contract addresses for the Advanced Escrow system.\n * Keyed by EVM chain ID. Source: x402r-sdk A1igator/multichain-config deployment.\n */\nexport const ESCROW_CONTRACTS: Record<number, AdvancedEscrowContracts> = {\n // Base Sepolia (testnet, chain 84532)\n 84532: {\n operator: '0x97d53e63A9CB97556c00BeFd325AF810c9b267B2',\n escrow: '0x29025c0E9D4239d438e169570818dB9FE0A80873',\n tokenCollector: '0x5cA789000070DF15b4663DB64a50AeF5D49c5Ee0',\n protocolFeeConfig: '0x8F96C493bAC365E41f0315cf45830069EBbDCaCe',\n refundRequest: '0x1C2Ab244aC8bDdDB74d43389FF34B118aF2E90F4',\n usdc: '0x036CbD53842c5426634e7929541eC2318f3dCF7e',\n },\n // Base Mainnet (chain 8453)\n 8453: {\n operator: '0x3D0837fF8Ea36F417261577b9BA568400A840260',\n escrow: '0xb9488351E48b23D798f24e8174514F28B741Eb4f',\n tokenCollector: '0x48ADf6E37F9b31dC2AAD0462C5862B5422C736B8',\n protocolFeeConfig: '0x59314674BAbb1a24Eb2704468a9cCdD50668a1C6',\n refundRequest: '0x35fb2EFEfAc3Ee9f6E52A9AAE5C9655bC08dEc00',\n usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n },\n // Ethereum Sepolia (testnet, chain 11155111)\n 11155111: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',\n },\n // Ethereum Mainnet (chain 1) - Updated from Ali's redeploy (commit e6cf29d)\n 1: {\n operator: '0x69B67962ffb7c5C7078ff348a87DF604dfA8001b',\n escrow: '0x9D4146EF898c8E60B3e865AE254ef438E7cEd2A0',\n tokenCollector: '0x206D4DbB6E7b876e4B5EFAAD2a04e7d7813FB6ba',\n protocolFeeConfig: '0x5b3e33791C1764cF7e2573Bf8116F1D361FD97Cd',\n refundRequest: '0xFa8C4Cb156053b867Ae7489220A29b5939E3Df70',\n usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n },\n // Polygon (chain 137)\n 137: {\n operator: '0xb33D6502EdBbC47201cd1E53C49d703EC0a660b8',\n escrow: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n tokenCollector: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n protocolFeeConfig: '0xE78648e7af7B1BaDE717FF6E410B922F92adE80f',\n refundRequest: '0xed02d3E5167BCc9582D851885A89b050AB816a56',\n usdc: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n },\n // Arbitrum (chain 42161)\n 42161: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831',\n },\n // Celo (chain 42220)\n 42220: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C',\n },\n // Monad (chain 143)\n 143: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0x754704Bc059F8C67012fEd69BC8a327a5aafb603',\n },\n // Avalanche (chain 43114)\n 43114: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n },\n // Optimism (chain 10)\n 10: {\n operator: '0x32d6AC59BCe8DFB3026F10BcaDB8D00AB218f5b6',\n escrow: '0x320a3c35F131E5D2Fb36af56345726B298936037',\n tokenCollector: '0x230fd3A171750FA45db2976121376b7F47Cba308',\n protocolFeeConfig: '0xD979dBfBdA5f4b16AAF60Eaab32A44f352076838',\n refundRequest: '0xc1256Bb30bd0cdDa07D8C8Cf67a59105f2EA1b98',\n usdc: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85',\n },\n // SKALE Base (chain 1187947933) - CREATE3 deployment, operator via factory\n 1187947933: {\n operator: '0x28c23AE8f55aDe5Ea10a5353FC40418D0c1B3d33',\n escrow: '0xBC151792f80C0EB1973d56b0235e6bee2A60e245',\n tokenCollector: '0x9A12A116a44636F55c9e135189A1321Abcfe2f30',\n protocolFeeConfig: '0xf62788834C99B2E85a6891C0b46D1EB996f8f596',\n refundRequest: '0x69e9BF2b40Ed472b55E47e9D4205d93Ed673093F',\n usdc: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n },\n};\n\n/**\n * Base Mainnet contract addresses for the Advanced Escrow system.\n * @deprecated Use ESCROW_CONTRACTS[8453] or getEscrowContractsByChainId(8453) instead.\n */\nexport const BASE_MAINNET_CONTRACTS: AdvancedEscrowContracts = ESCROW_CONTRACTS[8453];\n\n/**\n * Get escrow contract addresses for a given chain ID.\n *\n * @param chainId - EVM chain ID (e.g., 8453 for Base, 1 for Ethereum)\n * @returns Contract addresses or undefined if chain is not supported\n */\nexport function getEscrowContractsByChainId(chainId: number): AdvancedEscrowContracts | undefined {\n return ESCROW_CONTRACTS[chainId];\n}\n\n/**\n * Get all chain IDs that have escrow contracts deployed.\n *\n * @returns Array of chain IDs with escrow support\n */\nexport function getEscrowSupportedChainIds(): number[] {\n return Object.keys(ESCROW_CONTRACTS).map(Number);\n}\n\n/**\n * Check if escrow contracts are deployed on a given chain.\n *\n * @param chainId - EVM chain ID\n * @returns True if escrow is supported on this chain\n */\nexport function isEscrowSupportedOnChain(chainId: number): boolean {\n return chainId in ESCROW_CONTRACTS;\n}\n\n/**\n * Task tiers determine timing parameters for escrow operations.\n */\nexport type AdvancedEscrowTaskTier = 'micro' | 'standard' | 'premium' | 'enterprise';\n\n/**\n * Timing configuration per task tier (in seconds).\n */\nexport const TIER_TIMINGS: Record<AdvancedEscrowTaskTier, { pre: number; auth: number; refund: number }> = {\n micro: { pre: 3600, auth: 7200, refund: 86400 },\n standard: { pre: 7200, auth: 86400, refund: 604800 },\n premium: { pre: 14400, auth: 172800, refund: 1209600 },\n enterprise: { pre: 86400, auth: 604800, refund: 2592000 },\n};\n\n/**\n * PaymentInfo struct matching the on-chain PaymentOperator contract.\n */\nexport interface AdvancedPaymentInfo {\n operator: string;\n receiver: string;\n token: string;\n maxAmount: string;\n preApprovalExpiry: number;\n authorizationExpiry: number;\n refundExpiry: number;\n minFeeBps: number;\n maxFeeBps: number;\n feeReceiver: string;\n salt: string;\n}\n\n/**\n * Result of an AUTHORIZE operation.\n */\nexport interface AdvancedAuthorizationResult {\n success: boolean;\n transactionHash?: string;\n paymentInfo?: AdvancedPaymentInfo;\n salt?: string;\n error?: string;\n}\n\n/**\n * Result of an on-chain transaction (release, refund, charge).\n */\nexport interface AdvancedTransactionResult extends FacilitatorFailureFields {\n success: boolean;\n transactionHash?: string;\n gasUsed?: number;\n /**\n * Why it failed.\n *\n * On the gasless (`*ViaFacilitator`) paths, check `retryable` first: a\n * facilitator that could not hand the write to its lease holder rejected\n * nothing on-chain, and the escrow is exactly as it was. Reporting that as a\n * failed refund is how funds get written off while they are still sitting in\n * escrow, recoverable.\n */\n error?: string;\n}\n\n/**\n * Response from the facilitator's /escrow/state endpoint.\n * Represents the on-chain state of an escrow for a given paymentInfo + payer.\n */\nexport interface EscrowStateResponse {\n /** Whether the payment has already been collected (released) */\n hasCollectedPayment: boolean;\n /** Amount that can still be captured/released (in atomic units) */\n capturableAmount: string;\n /** Amount that can still be refunded to the payer (in atomic units) */\n refundableAmount: string;\n /** Keccak256 hash of the paymentInfo struct */\n paymentInfoHash: string;\n /** Network in CAIP-2 format (e.g., \"eip155:8453\") */\n network: string;\n}\n\n/**\n * Contract addresses configuration for AdvancedEscrowClient.\n *\n * Maps to the on-chain x402r escrow contracts:\n * - operator: PaymentOperatorFactory\n * - escrow: AuthCaptureEscrow\n * - tokenCollector: TokenCollector\n * - protocolFeeConfig: ProtocolFeeConfig\n * - refundRequest: RefundRequest\n * - usdc: USDC token contract\n */\nexport interface AdvancedEscrowContracts {\n /** PaymentOperatorFactory contract address */\n operator: string;\n /** AuthCaptureEscrow contract address */\n escrow: string;\n /** TokenCollector contract address */\n tokenCollector: string;\n /** ProtocolFeeConfig contract address */\n protocolFeeConfig: string;\n /** RefundRequest contract address */\n refundRequest: string;\n /** USDC token contract address */\n usdc: string;\n}\n\n/**\n * Configuration options for AdvancedEscrowClient.\n */\nexport interface AdvancedEscrowClientOptions {\n /** Facilitator URL for AUTHORIZE operations */\n facilitatorUrl?: string;\n /** JSON-RPC URL for on-chain operations (required when using SigningWalletAdapter) */\n rpcUrl?: string;\n /**\n * Chain ID (default: 8453 for Base Mainnet).\n * Supported chains: 8453 (Base), 84532 (Base Sepolia), 1 (Ethereum),\n * 11155111 (Ethereum Sepolia), 137 (Polygon), 42161 (Arbitrum),\n * 10 (Optimism), 42220 (Celo), 143 (Monad), 43114 (Avalanche).\n */\n chainId?: number;\n /** Contract addresses (auto-resolved from chainId if not provided) */\n contracts?: AdvancedEscrowContracts;\n /** Gas limit for transactions (default: 300000) */\n gasLimit?: number;\n /**\n * Request timeout in milliseconds for facilitator HTTP calls (authorize, gasless release/refund).\n * Default is per-network: 960s for Ethereum L1, 90s for L2s.\n * Ethereum L1 confirmations can take several minutes under congestion.\n */\n timeout?: number;\n /**\n * SigningWalletAdapter for OWS wallet signing (v2.36.0+).\n *\n * When provided, the client uses the adapter for all signing operations\n * instead of requiring a raw ethers.Signer. The first constructor argument\n * is ignored when `wallet` is set.\n *\n * Requires `rpcUrl` to be set for on-chain transaction building.\n *\n * @example\n * ```typescript\n * import { OWSWalletAdapter, AdvancedEscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const client = new AdvancedEscrowClient(null, {\n * wallet,\n * rpcUrl: 'https://mainnet.base.org',\n * chainId: 8453,\n * });\n * ```\n */\n wallet?: import('../wallet').SigningWalletAdapter;\n /**\n * Extra attempts on the gasless facilitator paths when the facilitator proved\n * it executed nothing. Default 2; `0` disables.\n */\n retries?: number;\n}\n\n/**\n * Minimal PaymentOperator ABI for the 4 on-chain functions.\n * (AUTHORIZE goes through the facilitator, not directly on-chain)\n */\nexport const OPERATOR_ABI = [\n 'function release(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount)',\n 'function refundInEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint120 amount)',\n 'function charge(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n 'function refundPostEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n];\n\n/**\n * CREATE3-deployed operators (SKALE, future chains) use updated ABI with extra `bytes data` param\n * on release() and refundInEscrow(). Pass empty bytes (0x) for the data parameter.\n */\nexport const OPERATOR_ABI_CREATE3 = [\n 'function release(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, bytes data)',\n 'function refundInEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint120 amount, bytes data)',\n 'function charge(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n 'function refundPostEscrow(tuple(address operator, address payer, address receiver, address token, uint120 maxAmount, uint48 preApprovalExpiry, uint48 authorizationExpiry, uint48 refundExpiry, uint16 minFeeBps, uint16 maxFeeBps, address feeReceiver, uint256 salt) paymentInfo, uint256 amount, address tokenCollector, bytes collectorData)',\n];\n\n/** Chain IDs using CREATE3-deployed operators with updated ABI */\nconst CREATE3_CHAIN_IDS = new Set([1187947933]);\n\n/**\n * AdvancedEscrowClient provides the 5 Advanced Escrow flows via the\n * PaymentOperator contract on 9 supported EVM networks.\n *\n * Supported chains: Base (8453), Base Sepolia (84532), Ethereum (1),\n * Ethereum Sepolia (11155111), Polygon (137), Arbitrum (42161),\n * Optimism (10), Celo (42220), Monad (143), Avalanche (43114).\n *\n * Contract addresses are auto-resolved from the chain ID.\n * Pass custom contracts to override.\n *\n * Two signer modes (v2.36.0+):\n * - **Legacy**: Pass an ethers.Signer as the first argument.\n * - **OWS Wallet**: Pass a SigningWalletAdapter via `options.wallet`.\n * The adapter signs transactions offline (no raw private key needed).\n * Requires `rpcUrl` for transaction building and broadcast.\n *\n * @example Legacy mode (ethers.Signer)\n * ```typescript\n * import { ethers } from 'ethers';\n * import { AdvancedEscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const provider = new ethers.JsonRpcProvider('https://mainnet.base.org');\n * const signer = new ethers.Wallet(process.env.KEY!, provider);\n * const client = new AdvancedEscrowClient(signer, { chainId: 8453 });\n * ```\n *\n * @example OWS Wallet mode (SigningWalletAdapter)\n * ```typescript\n * import { OWSWalletAdapter } from 'uvd-x402-sdk';\n * import { AdvancedEscrowClient } from 'uvd-x402-sdk/backend';\n *\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const client = new AdvancedEscrowClient(null, {\n * wallet,\n * rpcUrl: 'https://mainnet.base.org',\n * chainId: 8453,\n * });\n * await client.init();\n *\n * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');\n * const auth = await client.authorize(pi);\n * const release = await client.release(pi);\n * ```\n */\nexport class AdvancedEscrowClient {\n private facilitatorUrl: string;\n private chainId: number;\n private gasLimit: number;\n private readonly timeout: number;\n private readonly retries: number | undefined;\n private contracts: AdvancedEscrowContracts;\n private signer: any; // ethers.Signer (legacy mode)\n private walletAdapter: import('../wallet').SigningWalletAdapter | null; // OWS mode (v2.36.0+)\n private rpcUrl: string | undefined;\n private payerAddress: string = '';\n\n /**\n * Create an AdvancedEscrowClient.\n *\n * Two modes of operation:\n *\n * 1. **Legacy (ethers.Signer)**: Pass an ethers Signer as the first argument.\n * ```ts\n * const client = new AdvancedEscrowClient(signer, { rpcUrl, chainId });\n * ```\n *\n * 2. **OWS Wallet (SigningWalletAdapter)**: Pass `wallet` in options. The\n * first argument is ignored (pass `null`). Requires `rpcUrl` for on-chain\n * transaction building and broadcast.\n * ```ts\n * const wallet = new OWSWalletAdapter(owsWallet);\n * const client = new AdvancedEscrowClient(null, { wallet, rpcUrl, chainId });\n * ```\n *\n * @param signer - ethers.Signer instance (ignored when options.wallet is set)\n * @param options - Configuration options\n */\n constructor(signer: any, options: AdvancedEscrowClientOptions = {}) {\n this.walletAdapter = options.wallet || null;\n this.signer = this.walletAdapter ? null : signer;\n this.rpcUrl = options.rpcUrl;\n this.facilitatorUrl = (options.facilitatorUrl || 'https://facilitator.ultravioletadao.xyz').replace(/\\/$/, '');\n this.chainId = options.chainId || 8453;\n this.gasLimit = options.gasLimit || 300000;\n this.timeout = options.timeout || ESCROW_TIMEOUT_MS[this.chainId] || DEFAULT_ESCROW_TIMEOUT_MS;\n this.retries = options.retries;\n\n if (this.walletAdapter && !this.rpcUrl) {\n throw new Error(\n 'AdvancedEscrowClient: rpcUrl is required when using a SigningWalletAdapter. ' +\n 'The adapter signs transactions offline; an RPC provider is needed to build ' +\n 'and broadcast them.'\n );\n }\n\n if (options.contracts) {\n this.contracts = options.contracts;\n } else {\n const resolved = ESCROW_CONTRACTS[this.chainId];\n if (!resolved) {\n throw new Error(\n `No escrow contracts found for chain ID ${this.chainId}. ` +\n `Supported chains: ${getEscrowSupportedChainIds().join(', ')}. ` +\n `Pass custom contracts via options.contracts to use an unsupported chain.`\n );\n }\n this.contracts = resolved;\n }\n }\n\n /**\n * Initialize the client (resolves payer address).\n * Call this before using any methods.\n */\n async init(): Promise<void> {\n if (this.walletAdapter) {\n this.payerAddress = this.walletAdapter.getAddress();\n } else {\n this.payerAddress = await this.signer.getAddress();\n }\n }\n\n /**\n * Build a PaymentInfo struct with appropriate timing for the task tier.\n *\n * @param receiver - Worker's wallet address\n * @param amount - Amount in token atomic units (e.g., '5000000' for $5 USDC)\n * @param tier - Task tier determines timing parameters\n * @param salt - Random salt (auto-generated if not provided)\n */\n buildPaymentInfo(\n receiver: string,\n amount: string,\n tier: AdvancedEscrowTaskTier = 'standard',\n salt?: string,\n opts?: { deadline?: number; reviewWindowSec?: number },\n ): AdvancedPaymentInfo {\n const now = Math.floor(Date.now() / 1000);\n const t = TIER_TIMINGS[tier];\n // The release window must outlast the REVIEW, not just the tier. `micro`\n // alone gives two hours; a buyer approving later gets\n // `AfterAuthorizationExpiry` on-chain — the release reverts and the worker\n // is not paid. Measured in production 2026-08-19: a release attempted 26.2\n // HOURS past expiry, 8 escrows stuck on one network in 24h.\n //\n // This comment used to add \"and only the payer's `reclaim()` can move the\n // funds\". That is FALSE and it is why those escrows were treated as lost:\n // `AuthCaptureEscrow.partialVoid` is `onlySender(operator)` — the operator\n // is the facilitator — pays the PAYER, and does not look at\n // `authorizationExpiry`. `refundViaFacilitator` reaches it with no gas and\n // no payer. Widening the window still matters: it is what pays the WORKER,\n // and a refund does not.\n //\n // buildEscrowPreAuth — the other escrow path in this same SDK — already\n // floors both windows this way and says why. This path never got the memo,\n // and it is the one the marketplace documents as recommended.\n const reviewWindow = opts?.reviewWindowSec ?? REVIEW_WINDOW_SEC;\n const reviewBase = Math.max(now, opts?.deadline ?? now);\n const authorizationExpiry = Math.max(now + t.auth, reviewBase + reviewWindow);\n const refundExpiry = Math.max(now + t.refund, authorizationExpiry + REFUND_WINDOW_SEC);\n // Use crypto-safe randomness (Node.js crypto or Web Crypto API)\n let generatedSalt = salt;\n if (!generatedSalt) {\n const bytes = new Uint8Array(32);\n if (typeof globalThis.crypto !== 'undefined' && globalThis.crypto.getRandomValues) {\n globalThis.crypto.getRandomValues(bytes);\n } else {\n // Node.js fallback\n const nodeCrypto = require('crypto');\n const buf = nodeCrypto.randomBytes(32);\n bytes.set(new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength));\n }\n generatedSalt = '0x' + Array.from(bytes).map(b => b.toString(16).padStart(2, '0')).join('');\n }\n\n return {\n operator: this.contracts.operator,\n receiver,\n token: this.contracts.usdc,\n maxAmount: amount,\n preApprovalExpiry: now + t.pre,\n authorizationExpiry,\n refundExpiry,\n minFeeBps: 0,\n maxFeeBps: 800,\n feeReceiver: this.contracts.operator,\n salt: generatedSalt,\n };\n }\n\n /**\n * Compute the correct nonce (with PAYMENT_INFO_TYPEHASH).\n * Matches the on-chain AuthCaptureEscrow nonce derivation.\n */\n private async computeNonce(paymentInfo: AdvancedPaymentInfo): Promise<string> {\n // Dynamic import of ethers to avoid hard dependency at module level\n const { ethers } = await import('ethers');\n\n const piTuple = ethers.AbiCoder.defaultAbiCoder().encode(\n ['bytes32', 'tuple(address,address,address,address,uint120,uint48,uint48,uint48,uint16,uint16,address,uint256)'],\n [\n PAYMENT_INFO_TYPEHASH,\n [\n paymentInfo.operator,\n ZERO_ADDRESS, // payer = 0 for payer-agnostic hash\n paymentInfo.receiver,\n paymentInfo.token,\n paymentInfo.maxAmount,\n paymentInfo.preApprovalExpiry,\n paymentInfo.authorizationExpiry,\n paymentInfo.refundExpiry,\n paymentInfo.minFeeBps,\n paymentInfo.maxFeeBps,\n paymentInfo.feeReceiver,\n paymentInfo.salt,\n ],\n ],\n );\n const piHash = ethers.keccak256(piTuple);\n\n const finalEncoded = ethers.AbiCoder.defaultAbiCoder().encode(\n ['uint256', 'address', 'bytes32'],\n [this.chainId, this.contracts.escrow, piHash],\n );\n return ethers.keccak256(finalEncoded);\n }\n\n /**\n * Sign ReceiveWithAuthorization for ERC-3009.\n *\n * Uses SigningWalletAdapter.signTypedData() when in OWS mode,\n * or ethers Signer.signTypedData() in legacy mode.\n */\n private async signErc3009(auth: Record<string, string>): Promise<string> {\n const domain = {\n name: USDC_DOMAIN_NAME[this.chainId] || 'USD Coin',\n version: '2',\n chainId: this.chainId,\n verifyingContract: this.contracts.usdc,\n };\n\n const types = {\n ReceiveWithAuthorization: [\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 const message = {\n from: auth.from,\n to: auth.to,\n value: auth.value,\n validAfter: auth.validAfter,\n validBefore: auth.validBefore,\n nonce: auth.nonce,\n };\n\n // OWS wallet adapter mode: serialize to JSON and use adapter.signTypedData()\n if (this.walletAdapter) {\n const typedData = JSON.stringify({\n domain,\n types,\n primaryType: 'ReceiveWithAuthorization',\n message,\n });\n const result = await this.walletAdapter.signTypedData(typedData);\n return result.signature;\n }\n\n // Legacy ethers.Signer mode\n return this.signer.signTypedData(domain, types, message);\n }\n\n /**\n * Build the on-chain PaymentInfo tuple for contract calls.\n */\n private buildTuple(pi: AdvancedPaymentInfo): any[] {\n return [\n pi.operator,\n this.payerAddress,\n pi.receiver,\n pi.token,\n pi.maxAmount,\n pi.preApprovalExpiry,\n pi.authorizationExpiry,\n pi.refundExpiry,\n pi.minFeeBps,\n pi.maxFeeBps,\n pi.feeReceiver,\n pi.salt,\n ];\n }\n\n /**\n * AUTHORIZE: Lock funds in escrow via the facilitator.\n *\n * Sends an ERC-3009 ReceiveWithAuthorization to the facilitator,\n * which calls PaymentOperator.authorize() on-chain.\n */\n async authorize(paymentInfo: AdvancedPaymentInfo): Promise<AdvancedAuthorizationResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const nonce = await this.computeNonce(paymentInfo);\n\n const auth = {\n from: this.payerAddress,\n to: this.contracts.tokenCollector,\n value: paymentInfo.maxAmount,\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce,\n };\n const signature = await this.signErc3009(auth);\n\n const payload = {\n x402Version: 2,\n scheme: 'escrow',\n payload: {\n authorization: auth,\n signature,\n paymentInfo: paymentInfo,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${this.chainId}`,\n maxAmountRequired: paymentInfo.maxAmount,\n asset: this.contracts.usdc,\n payTo: paymentInfo.receiver,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n },\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.facilitatorUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n clearTimeout(timeoutId);\n const result = await response.json();\n\n if (result.success) {\n return {\n success: true,\n transactionHash: result.transaction,\n paymentInfo,\n salt: paymentInfo.salt,\n };\n }\n return { success: false, error: result.errorReason };\n } catch (fetchErr: any) {\n clearTimeout(timeoutId);\n\n // On timeout, check on-chain state as fallback\n if (fetchErr.name === 'AbortError') {\n try {\n const state = await this.queryEscrowState(paymentInfo);\n if (state.capturableAmount && BigInt(state.capturableAmount) > 0n) {\n return {\n success: true,\n paymentInfo,\n salt: paymentInfo.salt,\n };\n }\n } catch { /* fallback query failed, report original timeout */ }\n return { success: false, error: `Authorize timed out after ${this.timeout}ms. On-chain state could not confirm escrow lock.` };\n }\n throw fetchErr;\n }\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * RELEASE: Capture escrowed funds to receiver (worker gets paid).\n *\n * Calls PaymentOperator.release() -> escrow.capture()\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to release (defaults to maxAmount)\n */\n async release(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const isCreate3 = CREATE3_CHAIN_IDS.has(this.chainId);\n const abi = isCreate3 ? OPERATOR_ABI_CREATE3 : OPERATOR_ABI;\n const amt = amount || paymentInfo.maxAmount;\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode: build unsigned TX, sign via adapter, broadcast\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, abi, (iface) => {\n return isCreate3\n ? iface.encodeFunctionData('release', [tuple, amt, '0x'])\n : iface.encodeFunctionData('release', [tuple, amt]);\n });\n }\n\n // Legacy ethers.Signer mode: contract sends directly\n const contract = new ethers.Contract(this.contracts.operator, abi, this.signer);\n const tx = isCreate3\n ? await contract.release(tuple, amt, '0x', { gasLimit: this.gasLimit })\n : await contract.release(tuple, amt, { gasLimit: this.gasLimit });\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * REFUND IN ESCROW: Return escrowed funds to payer (cancel task).\n *\n * Calls PaymentOperator.refundInEscrow() -> escrow.partialVoid()\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to refund (defaults to maxAmount)\n */\n async refundInEscrow(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const isCreate3 = CREATE3_CHAIN_IDS.has(this.chainId);\n const abi = isCreate3 ? OPERATOR_ABI_CREATE3 : OPERATOR_ABI;\n const amt = amount || paymentInfo.maxAmount;\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode: build unsigned TX, sign via adapter, broadcast\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, abi, (iface) => {\n return isCreate3\n ? iface.encodeFunctionData('refundInEscrow', [tuple, amt, '0x'])\n : iface.encodeFunctionData('refundInEscrow', [tuple, amt]);\n });\n }\n\n // Legacy ethers.Signer mode\n const contract = new ethers.Contract(this.contracts.operator, abi, this.signer);\n const tx = isCreate3\n ? await contract.refundInEscrow(tuple, amt, '0x', { gasLimit: this.gasLimit })\n : await contract.refundInEscrow(tuple, amt, { gasLimit: this.gasLimit });\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n // ==========================================================================\n // GASLESS FACILITATOR METHODS\n // ==========================================================================\n\n /**\n * GASLESS RELEASE: Release escrowed funds via the facilitator.\n *\n * Instead of calling the PaymentOperator contract directly (which requires\n * gas), this sends a release request to the facilitator, which submits\n * the transaction on your behalf.\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to release in atomic units (defaults to maxAmount)\n * @returns Transaction result from the facilitator\n *\n * @example\n * ```typescript\n * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');\n * await client.authorize(pi);\n * // Worker completes task...\n * const result = await client.releaseViaFacilitator(pi);\n * console.log(result.transactionHash);\n * ```\n */\n async releaseViaFacilitator(\n paymentInfo: AdvancedPaymentInfo,\n amount?: string,\n ): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const payload = {\n x402Version: 2,\n scheme: 'escrow',\n action: 'release',\n payload: {\n paymentInfo: {\n operator: paymentInfo.operator,\n receiver: paymentInfo.receiver,\n token: paymentInfo.token,\n maxAmount: paymentInfo.maxAmount,\n preApprovalExpiry: paymentInfo.preApprovalExpiry,\n authorizationExpiry: paymentInfo.authorizationExpiry,\n refundExpiry: paymentInfo.refundExpiry,\n minFeeBps: paymentInfo.minFeeBps,\n maxFeeBps: paymentInfo.maxFeeBps,\n feeReceiver: paymentInfo.feeReceiver,\n salt: paymentInfo.salt,\n },\n payer: this.payerAddress,\n amount: amount || paymentInfo.maxAmount,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${this.chainId}`,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n },\n };\n\n try {\n // A 503 from the writer lease is NOT a refused release. The facilitator\n // never reached the chain, so the escrow still holds every token and\n // the same request is the right thing to send again. Reading it as a\n // refusal is how a recoverable escrow gets written off.\n const { response, error } = await facilitatorFetch(\n `${this.facilitatorUrl}/settle`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n if (error) {\n return { success: false, error: error.error, ...failureFields(error) };\n }\n const result = await response.json();\n\n if (result.success) {\n return {\n success: true,\n transactionHash: result.transaction || result.transactionHash || result.transaction_hash,\n };\n }\n // Parity with the Python SDK (2026-08-22): a last-resort message that\n // says only \"Release failed\" is the same dead end as an empty string —\n // name the status and what the body DID carry so the caller has a\n // thread to pull. Divergence between the two SDKs is exactly what let\n // the escrow-window bug live in one of them for weeks.\n return {\n success: false,\n error:\n result.errorReason ||\n result.error ||\n `Release refused with no reason (HTTP ${response.status}, body keys: ${Object.keys(result ?? {}).sort().join(', ') || 'none'})`,\n };\n } catch (fetchErr: any) {\n // On timeout, check on-chain state as fallback\n if (fetchErr.name === 'AbortError') {\n try {\n const state = await this.queryEscrowState(paymentInfo);\n if (state.capturableAmount === '0' && state.hasCollectedPayment) {\n return { success: true };\n }\n } catch { /* fallback query failed */ }\n return { success: false, error: `Gasless release timed out after ${this.timeout}ms. Check escrow state on-chain.` };\n }\n throw fetchErr;\n }\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * GASLESS REFUND: return escrowed funds to the payer via the facilitator.\n *\n * Sends `action: \"refundInEscrow\"` to `POST /settle`; the facilitator's\n * PaymentOperator calls `AuthCaptureEscrow.partialVoid`.\n *\n * # This is how an EXPIRED escrow is recovered\n *\n * A widely repeated claim — including in this SDK's own comments until now —\n * says that once `authorizationExpiry` passes, only the payer's `reclaim()`\n * can move the funds. **That is false, and believing it has left real money\n * stranded.**\n *\n * Read the contract (`AuthCaptureEscrow.sol`):\n *\n * - `partialVoid` is `onlySender(paymentInfo.operator)` — the operator is the\n * FACILITATOR, not the payer — it sends the tokens **to the payer**, and it\n * **does not check `authorizationExpiry` at all**. It works before expiry\n * and after it, and the payer never has to appear.\n * - `reclaim` is `onlySender(paymentInfo.payer)` and only after expiry. It is\n * a payer's self-service escape hatch, which is why this facilitator does\n * not expose it — **not** the only way out.\n *\n * So a release that reverted with `AfterAuthorizationExpiry` is recoverable\n * from here, with no gas and no cooperation from the payer. Get the amount\n * from {@link queryEscrowState}'s `capturableAmount`.\n *\n * # A refusal that is not a refusal\n *\n * Check `retryable` before writing an escrow off. A `503` means the\n * facilitator never reached the chain — the escrow is untouched and the same\n * request should be sent again.\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to refund in atomic units (defaults to maxAmount).\n * For a stuck escrow pass `capturableAmount` from {@link queryEscrowState}.\n * @returns Transaction result from the facilitator\n *\n * @example Recovering an escrow whose release window already closed\n * ```typescript\n * const state = await client.queryEscrowState(pi);\n * if (state.capturableAmount !== '0') {\n * // No payer needed, no gas, and expiry is irrelevant to partialVoid.\n * const result = await client.refundViaFacilitator(pi, state.capturableAmount);\n * if (!result.success && result.retryable) {\n * // No verdict was reached. The funds are still there; send it again.\n * }\n * }\n * ```\n */\n async refundViaFacilitator(\n paymentInfo: AdvancedPaymentInfo,\n amount?: string,\n ): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const payload = {\n x402Version: 2,\n scheme: 'escrow',\n action: 'refundInEscrow',\n payload: {\n paymentInfo: {\n operator: paymentInfo.operator,\n receiver: paymentInfo.receiver,\n token: paymentInfo.token,\n maxAmount: paymentInfo.maxAmount,\n preApprovalExpiry: paymentInfo.preApprovalExpiry,\n authorizationExpiry: paymentInfo.authorizationExpiry,\n refundExpiry: paymentInfo.refundExpiry,\n minFeeBps: paymentInfo.minFeeBps,\n maxFeeBps: paymentInfo.maxFeeBps,\n feeReceiver: paymentInfo.feeReceiver,\n salt: paymentInfo.salt,\n },\n payer: this.payerAddress,\n amount: amount || paymentInfo.maxAmount,\n },\n paymentRequirements: {\n scheme: 'escrow',\n network: `eip155:${this.chainId}`,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n },\n };\n\n try {\n // The non-2xx branch used to be missing entirely: `response.json()` on\n // a 503 body yields `{error, reason}`, `result.success` is undefined,\n // and the refund was reported as failed. That is a recoverable escrow\n // declared lost on a facilitator hiccup.\n const { response, error } = await facilitatorFetch(\n `${this.facilitatorUrl}/settle`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n },\n { timeoutMs: this.timeout, retries: this.retries },\n );\n if (error) {\n return { success: false, error: error.error, ...failureFields(error) };\n }\n const result = await response.json();\n\n if (result.success) {\n return {\n success: true,\n transactionHash: result.transaction || result.transactionHash || result.transaction_hash,\n };\n }\n return {\n success: false,\n error:\n result.errorReason ||\n result.error ||\n `Refund refused with no reason (HTTP ${response.status}, body keys: ${Object.keys(result ?? {}).sort().join(', ') || 'none'})`,\n };\n } catch (fetchErr: any) {\n // On timeout, check on-chain state as fallback\n if (fetchErr.name === 'AbortError') {\n try {\n const state = await this.queryEscrowState(paymentInfo);\n if (state.refundableAmount === '0') {\n return { success: true };\n }\n } catch { /* fallback query failed */ }\n return { success: false, error: `Gasless refund timed out after ${this.timeout}ms. Check escrow state on-chain.` };\n }\n throw fetchErr;\n }\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * QUERY ESCROW STATE: Read on-chain escrow state via the facilitator.\n *\n * This is a read-only operation that queries the facilitator for the\n * current escrow state without requiring gas or a signer.\n *\n * @param paymentInfo - PaymentInfo to query state for\n * @returns Escrow state including capturable/refundable amounts\n *\n * @example\n * ```typescript\n * const pi = client.buildPaymentInfo('0xWorker...', '5000000', 'standard');\n * await client.authorize(pi);\n *\n * const state = await client.queryEscrowState(pi);\n * console.log(`Capturable: ${state.capturableAmount}`);\n * console.log(`Refundable: ${state.refundableAmount}`);\n * console.log(`Already collected: ${state.hasCollectedPayment}`);\n * ```\n */\n async queryEscrowState(paymentInfo: AdvancedPaymentInfo): Promise<EscrowStateResponse> {\n if (!this.payerAddress) await this.init();\n\n const payload = {\n paymentInfo: {\n operator: paymentInfo.operator,\n receiver: paymentInfo.receiver,\n token: paymentInfo.token,\n maxAmount: paymentInfo.maxAmount,\n preApprovalExpiry: paymentInfo.preApprovalExpiry,\n authorizationExpiry: paymentInfo.authorizationExpiry,\n refundExpiry: paymentInfo.refundExpiry,\n minFeeBps: paymentInfo.minFeeBps,\n maxFeeBps: paymentInfo.maxFeeBps,\n feeReceiver: paymentInfo.feeReceiver,\n salt: paymentInfo.salt,\n },\n payer: this.payerAddress,\n network: `eip155:${this.chainId}`,\n extra: {\n escrowAddress: this.contracts.escrow,\n operatorAddress: this.contracts.operator,\n tokenCollector: this.contracts.tokenCollector,\n },\n };\n\n const response = await fetch(`${this.facilitatorUrl}/escrow/state`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Escrow state query failed: ${response.status} - ${errorText}`);\n }\n\n return await response.json() as EscrowStateResponse;\n }\n\n /**\n * CHARGE: Direct instant payment (no escrow hold).\n *\n * Calls PaymentOperator.charge() -> escrow.charge()\n * Funds go directly from payer to receiver.\n *\n * @param paymentInfo - PaymentInfo with receiver and amount\n * @param amount - Amount to charge (defaults to maxAmount)\n */\n async charge(paymentInfo: AdvancedPaymentInfo, amount?: string): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const nonce = await this.computeNonce(paymentInfo);\n const amt = amount || paymentInfo.maxAmount;\n\n const auth = {\n from: this.payerAddress,\n to: this.contracts.tokenCollector,\n value: String(amt),\n validAfter: '0',\n validBefore: String(paymentInfo.preApprovalExpiry),\n nonce,\n };\n const signature = await this.signErc3009(auth);\n // Pass raw signature bytes as collectorData (ethers handles hex -> bytes)\n const collectorData = ethers.getBytes(signature);\n\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, OPERATOR_ABI, (iface) => {\n return iface.encodeFunctionData('charge', [\n tuple, amt, this.contracts.tokenCollector, collectorData,\n ]);\n });\n }\n\n // Legacy ethers.Signer mode\n const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);\n const tx = await contract.charge(\n tuple,\n amt,\n this.contracts.tokenCollector,\n collectorData,\n { gasLimit: this.gasLimit },\n );\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n /**\n * REFUND POST ESCROW: Dispute refund after funds were released.\n *\n * Calls PaymentOperator.refundPostEscrow() -> escrow.refund()\n *\n * WARNING: NOT FUNCTIONAL IN PRODUCTION (as of 2026-02-03).\n * The protocol team has not implemented the required tokenCollector\n * contract. This call will fail on-chain.\n *\n * For dispute resolution, use refundInEscrow() instead: keep funds\n * in escrow and refund before releasing. This guarantees funds are\n * available and under arbiter control.\n *\n * Kept for future use when tokenCollector is implemented.\n *\n * @param paymentInfo - PaymentInfo from the original authorization\n * @param amount - Amount to refund (defaults to maxAmount)\n * @param tokenCollector - Address of token collector for refund sourcing\n * @param collectorData - Data for the token collector\n */\n async refundPostEscrow(\n paymentInfo: AdvancedPaymentInfo,\n amount?: string,\n tokenCollector?: string,\n collectorData?: string,\n ): Promise<AdvancedTransactionResult> {\n if (!this.payerAddress) await this.init();\n\n try {\n const { ethers } = await import('ethers');\n const amt = amount || paymentInfo.maxAmount;\n const tuple = this.buildTuple(paymentInfo);\n\n // OWS wallet adapter mode\n if (this.walletAdapter) {\n return this.sendViaAdapter(ethers, OPERATOR_ABI, (iface) => {\n return iface.encodeFunctionData('refundPostEscrow', [\n tuple, amt, tokenCollector || ZERO_ADDRESS, collectorData || '0x',\n ]);\n });\n }\n\n // Legacy ethers.Signer mode\n const contract = new ethers.Contract(this.contracts.operator, OPERATOR_ABI, this.signer);\n const tx = await contract.refundPostEscrow(\n tuple,\n amt,\n tokenCollector || ZERO_ADDRESS,\n collectorData || '0x',\n { gasLimit: this.gasLimit },\n );\n const receipt = await tx.wait();\n\n return {\n success: receipt.status === 1,\n transactionHash: receipt.hash,\n gasUsed: Number(receipt.gasUsed),\n error: receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n } catch (e: any) {\n return { success: false, error: e.message || String(e) };\n }\n }\n\n // ==========================================================================\n // INTERNAL: Adapter-based transaction signing and broadcast\n // ==========================================================================\n\n /**\n * Build an unsigned transaction, sign via SigningWalletAdapter, and broadcast.\n *\n * Used by release(), refundInEscrow(), charge(), refundPostEscrow() when\n * operating in OWS wallet adapter mode. The adapter signs the serialized\n * transaction offline; the RPC provider broadcasts the signed raw TX.\n *\n * @param ethersModule - ethers namespace (from `const { ethers } = await import('ethers')`)\n * @param abi - Contract ABI (OPERATOR_ABI or OPERATOR_ABI_CREATE3)\n * @param encodeCalldata - Function that encodes the calldata using the interface\n * @returns Transaction result\n */\n private async sendViaAdapter(\n ethersModule: any,\n abi: string[],\n encodeCalldata: (iface: any) => string,\n ): Promise<AdvancedTransactionResult> {\n const provider = new ethersModule.JsonRpcProvider(this.rpcUrl);\n const iface = new ethersModule.Interface(abi);\n const data = encodeCalldata(iface);\n\n // Build unsigned transaction\n const nonce = await provider.getTransactionCount(this.payerAddress);\n const feeData = await provider.getFeeData();\n\n const unsignedTx = ethersModule.Transaction.from({\n to: this.contracts.operator,\n data,\n gasLimit: this.gasLimit,\n nonce,\n chainId: this.chainId,\n maxFeePerGas: feeData.maxFeePerGas,\n maxPriorityFeePerGas: feeData.maxPriorityFeePerGas,\n type: 2, // EIP-1559\n });\n\n // Sign via adapter\n const signedTxHex = await this.walletAdapter!.signTransaction(unsignedTx.unsignedSerialized);\n\n // Broadcast\n const txResponse = await provider.broadcastTransaction(signedTxHex);\n const receipt = await txResponse.wait();\n\n return {\n success: receipt !== null && receipt.status === 1,\n transactionHash: txResponse.hash,\n gasUsed: receipt ? Number(receipt.gasUsed) : undefined,\n error: receipt && receipt.status !== 1 ? 'Transaction reverted' : undefined,\n };\n }\n}\n"]}