uvd-x402-sdk 2.63.0 → 2.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -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/escrow-preauth.ts","../src/backend/index.ts"],"names":["nobleHexToBytes","bytesToHex","keccak_256","secp256k1","sha512","x25519","hkdf","sha256","gcm","edwardsToMontgomeryPub","randomBytes","paymentId","contentHash","ed25519","ethers","DEFAULT_FACILITATOR_URL","ZERO_ADDRESS","requirements","reqOptions"],"mappings":"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","file":"index.js","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 * `(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 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\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` stays empty on both branches: this call sends `sealed`, so the\n * facilitator issues the pointer and you cannot sign what you have not seen.\n */\nexport function sellerDigestFor(\n paymentId: string,\n contentHash: string,\n payee: string,\n network: string,\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, '', payee, chainId);\n }\n return anchorDigest(paymentId, contentHash, '', 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\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 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 sealed: toBase64(blob),\n backend: '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.sign) {\n const digest = sellerDigestFor(opts.paymentId, hash, opts.payee, opts.network);\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 const wire = JSON.stringify(payload);\n if (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/** 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 !== '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 // 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 * 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 * 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';\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\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 { signature } = await wallet.signTypedData(\n JSON.stringify({\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\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 * 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';\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 {\n isValid: boolean;\n invalidReason?: string;\n payer?: string;\n network?: string;\n}\n\n/**\n * Settle response from the facilitator\n */\nexport interface SettleResponse {\n success: boolean;\n transactionHash?: string;\n network?: string;\n error?: string;\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\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\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 }\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 const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n isValid: false,\n invalidReason: `Facilitator error: ${response.status} - ${errorText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n isValid: false,\n invalidReason: error instanceof Error ? error.message : 'Unknown error',\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 const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), settleTimeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\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 error: `Facilitator error: ${response.status} - ${errorText}`,\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 success: true,\n transactionHash,\n network: result.network,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\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 verified: boolean;\n settled: boolean;\n transactionHash?: string;\n error?: string;\n }> {\n // Verify first\n const verifyResult = await this.verify(paymentHeader, requirements);\n if (!verifyResult.isValid) {\n return {\n verified: false,\n settled: false,\n error: verifyResult.invalidReason,\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 };\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 * 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 });\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 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 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 */\nexport function createHonoMiddleware(options: HonoMiddlewareOptions) {\n const client = new FacilitatorClient({\n baseUrl: options.facilitatorUrl || options.baseUrl,\n timeout: options.timeout,\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 },\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 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 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\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 (20 networks: 18 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 (10)\n ethereum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n 'base-mainnet': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n polygon: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n arbitrum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n optimism: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n celo: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n bsc: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n monad: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n avalanche: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n 'skale-base': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\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 * Network type for ERC-8004 operations (20 networks: 18 EVM + 2 Solana)\n */\nexport type Erc8004Network =\n // EVM Mainnets\n | 'ethereum' | 'base-mainnet' | 'polygon' | 'arbitrum' | 'optimism' | 'celo' | 'bsc' | 'monad' | 'avalanche' | 'skale-base'\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 * 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 {\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 constructor(message: string, status: number, body: string) {\n super(message);\n this.name = 'Erc8004LookupError';\n this.status = status;\n this.body = body;\n }\n\n /** The address genuinely owns no agent on this network. */\n get notFound(): boolean {\n return this.status === 404;\n }\n\n /** The lookup reached no verdict. Retry; never read as \"owns nothing\". */\n get retryable(): boolean {\n return this.status === 503;\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 {\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\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\n constructor(options: Erc8004ClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';\n this.timeout = options.timeout || 30000;\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/${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/${network}/owner/${address}`;\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 // 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 as a field.\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${response.status} - ${errorText}`,\n response.status,\n errorText,\n );\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\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/${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 * @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 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),\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 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 error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\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 controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n 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 = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify(payload),\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 error: `Facilitator error: ${response.status} - ${errorText}`,\n network,\n };\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\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 * Append a response to existing feedback\n *\n * Allows agents to respond to feedback they received.\n * Only the agent (identity owner) can append responses.\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 controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n 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 fetchResponse = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!fetchResponse.ok) {\n const errorText = await fetchResponse.text();\n return {\n success: false,\n error: `Facilitator error: ${fetchResponse.status} - ${errorText}`,\n network,\n };\n }\n\n return await fetchResponse.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\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 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),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\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(errorText) as RegisterAgentResponse;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return {\n ...parsed,\n // Never let a 4xx body claim success, whatever it says.\n success: false,\n error: parsed.error ?? `Facilitator error: ${response.status}`,\n network: parsed.network ?? request.network,\n };\n }\n } catch {\n // Not JSON - fall through to the flattened error.\n }\n return {\n success: false,\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 error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\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 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 'Prefer': 'respond-async',\n },\n body: JSON.stringify(request),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${response.status} - ${errorText}`,\n response.status,\n errorText,\n );\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\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 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 Erc8004LookupError(\n `ERC-8004 API error: ${response.status} - ${errorText}`,\n response.status,\n errorText,\n );\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\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/${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/${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 {\n success: boolean;\n transactionHash?: string;\n gasUsed?: number;\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\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 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\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, the worker is\n // not paid, and only the payer's `reclaim()` can move the funds. Measured in\n // production 2026-08-19: a release attempted 26.2 HOURS past expiry, 8\n // escrows stuck on one network in 24h.\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 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 || result.transactionHash || result.transaction_hash,\n };\n }\n return { success: false, error: result.errorReason || result.error || 'Release failed' };\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 === '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: Refund escrowed funds via the facilitator.\n *\n * Instead of calling the PaymentOperator contract directly (which requires\n * gas), this sends a refundInEscrow request to the facilitator, which\n * submits the transaction on your behalf.\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to refund 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 * // Task cancelled...\n * const result = await client.refundViaFacilitator(pi);\n * console.log(result.transactionHash);\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 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 || result.transactionHash || result.transaction_hash,\n };\n }\n return { success: false, error: result.errorReason || result.error || 'Refund failed' };\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.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/escrow-preauth.ts","../src/backend/index.ts"],"names":["nobleHexToBytes","bytesToHex","keccak_256","secp256k1","sha512","x25519","hkdf","sha256","gcm","edwardsToMontgomeryPub","randomBytes","paymentId","contentHash","ed25519","ethers","DEFAULT_FACILITATOR_URL","ZERO_ADDRESS","requirements","reqOptions"],"mappings":"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","file":"index.js","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 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\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` stays empty on both branches: this call sends `sealed`, so the\n * facilitator issues the pointer and you cannot sign what you have not seen.\n */\nexport function sellerDigestFor(\n paymentId: string,\n contentHash: string,\n payee: string,\n network: string,\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, '', payee, chainId);\n }\n return anchorDigest(paymentId, contentHash, '', 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\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 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 sealed: toBase64(blob),\n backend: '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 const digest = sellerDigestFor(opts.paymentId, hash, opts.payee, opts.network);\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 const wire = JSON.stringify(payload);\n if (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 !== '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 // 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 * 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 * 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';\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\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 { signature } = await wallet.signTypedData(\n JSON.stringify({\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\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 * 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';\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 {\n isValid: boolean;\n invalidReason?: string;\n payer?: string;\n network?: string;\n}\n\n/**\n * Settle response from the facilitator\n */\nexport interface SettleResponse {\n success: boolean;\n transactionHash?: string;\n network?: string;\n error?: string;\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\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\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 }\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 const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n return {\n isValid: false,\n invalidReason: `Facilitator error: ${response.status} - ${errorText}`,\n };\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n isValid: false,\n invalidReason: error instanceof Error ? error.message : 'Unknown error',\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 const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), settleTimeout);\n\n try {\n const response = await fetch(`${this.baseUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\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 error: `Facilitator error: ${response.status} - ${errorText}`,\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 success: true,\n transactionHash,\n network: result.network,\n };\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\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 verified: boolean;\n settled: boolean;\n transactionHash?: string;\n error?: string;\n }> {\n // Verify first\n const verifyResult = await this.verify(paymentHeader, requirements);\n if (!verifyResult.isValid) {\n return {\n verified: false,\n settled: false,\n error: verifyResult.invalidReason,\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 };\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 * 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 });\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 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 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 */\nexport function createHonoMiddleware(options: HonoMiddlewareOptions) {\n const client = new FacilitatorClient({\n baseUrl: options.facilitatorUrl || options.baseUrl,\n timeout: options.timeout,\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 },\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 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 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\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 (20 networks: 18 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 (10)\n ethereum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n 'base-mainnet': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n polygon: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n arbitrum: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n optimism: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n celo: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n bsc: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n monad: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n avalanche: {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\n },\n 'skale-base': {\n identityRegistry: MAINNET_IDENTITY,\n reputationRegistry: MAINNET_REPUTATION,\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 * Network type for ERC-8004 operations (20 networks: 18 EVM + 2 Solana)\n */\nexport type Erc8004Network =\n // EVM Mainnets\n | 'ethereum' | 'base-mainnet' | 'polygon' | 'arbitrum' | 'optimism' | 'celo' | 'bsc' | 'monad' | 'avalanche' | 'skale-base'\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 * 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 {\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 constructor(message: string, status: number, body: string) {\n super(message);\n this.name = 'Erc8004LookupError';\n this.status = status;\n this.body = body;\n }\n\n /** The address genuinely owns no agent on this network. */\n get notFound(): boolean {\n return this.status === 404;\n }\n\n /** The lookup reached no verdict. Retry; never read as \"owns nothing\". */\n get retryable(): boolean {\n return this.status === 503;\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 {\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\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\n constructor(options: Erc8004ClientOptions = {}) {\n this.baseUrl = options.baseUrl || 'https://facilitator.ultravioletadao.xyz';\n this.timeout = options.timeout || 30000;\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/${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/${network}/owner/${address}`;\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 // 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 as a field.\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${response.status} - ${errorText}`,\n response.status,\n errorText,\n );\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\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/${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 * @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 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),\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 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 error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\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 controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n 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 = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify(payload),\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 error: `Facilitator error: ${response.status} - ${errorText}`,\n network,\n };\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\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 * Append a response to existing feedback\n *\n * Allows agents to respond to feedback they received.\n * Only the agent (identity owner) can append responses.\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 controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n const payload: Record<string, unknown> = {\n x402Version: 1,\n 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 fetchResponse = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!fetchResponse.ok) {\n const errorText = await fetchResponse.text();\n return {\n success: false,\n error: `Facilitator error: ${fetchResponse.status} - ${errorText}`,\n network,\n };\n }\n\n return await fetchResponse.json();\n } catch (error) {\n clearTimeout(timeoutId);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n network,\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 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),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\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(errorText) as RegisterAgentResponse;\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return {\n ...parsed,\n // Never let a 4xx body claim success, whatever it says.\n success: false,\n error: parsed.error ?? `Facilitator error: ${response.status}`,\n network: parsed.network ?? request.network,\n };\n }\n } catch {\n // Not JSON - fall through to the flattened error.\n }\n return {\n success: false,\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 error: error instanceof Error ? error.message : 'Unknown error',\n network: request.network,\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 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 'Prefer': 'respond-async',\n },\n body: JSON.stringify(request),\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Erc8004LookupError(\n `ERC-8004 API error: ${response.status} - ${errorText}`,\n response.status,\n errorText,\n );\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\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 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 Erc8004LookupError(\n `ERC-8004 API error: ${response.status} - ${errorText}`,\n response.status,\n errorText,\n );\n }\n\n return await response.json();\n } catch (error) {\n clearTimeout(timeoutId);\n throw error;\n }\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/${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/${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 {\n success: boolean;\n transactionHash?: string;\n gasUsed?: number;\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\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 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\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, the worker is\n // not paid, and only the payer's `reclaim()` can move the funds. Measured in\n // production 2026-08-19: a release attempted 26.2 HOURS past expiry, 8\n // escrows stuck on one network in 24h.\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 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 || result.transactionHash || result.transaction_hash,\n };\n }\n return { success: false, error: result.errorReason || result.error || 'Release failed' };\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 === '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: Refund escrowed funds via the facilitator.\n *\n * Instead of calling the PaymentOperator contract directly (which requires\n * gas), this sends a refundInEscrow request to the facilitator, which\n * submits the transaction on your behalf.\n *\n * @param paymentInfo - PaymentInfo from the authorize step\n * @param amount - Amount to refund 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 * // Task cancelled...\n * const result = await client.refundViaFacilitator(pi);\n * console.log(result.transactionHash);\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 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 || result.transactionHash || result.transaction_hash,\n };\n }\n return { success: false, error: result.errorReason || result.error || 'Refund failed' };\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.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"]}