@payai/x402-evm 2.3.6 → 2.4.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.
Files changed (78) hide show
  1. package/dist/cjs/exact/client/index.d.ts +3 -2
  2. package/dist/cjs/exact/client/index.js +173 -194
  3. package/dist/cjs/exact/client/index.js.map +1 -1
  4. package/dist/cjs/exact/facilitator/index.js +199 -185
  5. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  6. package/dist/cjs/exact/server/index.d.ts +18 -17
  7. package/dist/cjs/exact/server/index.js +100 -55
  8. package/dist/cjs/exact/server/index.js.map +1 -1
  9. package/dist/cjs/exact/v1/client/index.js +3 -1
  10. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  11. package/dist/cjs/exact/v1/facilitator/index.js +3 -1
  12. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  13. package/dist/cjs/index.d.ts +38 -2
  14. package/dist/cjs/index.js +441 -191
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/{permit2-U9Zolx3O.d.ts → permit2-CyZxwngN.d.ts} +278 -87
  17. package/dist/cjs/scheme-CXDF0D2A.d.ts +47 -0
  18. package/dist/cjs/upto/client/index.d.ts +32 -0
  19. package/dist/cjs/upto/client/index.js +507 -0
  20. package/dist/cjs/upto/client/index.js.map +1 -0
  21. package/dist/cjs/upto/facilitator/index.d.ts +52 -0
  22. package/dist/cjs/upto/facilitator/index.js +1233 -0
  23. package/dist/cjs/upto/facilitator/index.js.map +1 -0
  24. package/dist/cjs/upto/server/index.d.ts +77 -0
  25. package/dist/cjs/upto/server/index.js +246 -0
  26. package/dist/cjs/upto/server/index.js.map +1 -0
  27. package/dist/cjs/v1/index.d.ts +2 -0
  28. package/dist/cjs/v1/index.js +3 -1
  29. package/dist/cjs/v1/index.js.map +1 -1
  30. package/dist/esm/chunk-C4ZQMS77.mjs +629 -0
  31. package/dist/esm/chunk-C4ZQMS77.mjs.map +1 -0
  32. package/dist/esm/chunk-CRT6YNY5.mjs +529 -0
  33. package/dist/esm/chunk-CRT6YNY5.mjs.map +1 -0
  34. package/dist/esm/chunk-D6RXZXOS.mjs +158 -0
  35. package/dist/esm/chunk-D6RXZXOS.mjs.map +1 -0
  36. package/dist/esm/chunk-GJ57SZGI.mjs +121 -0
  37. package/dist/esm/chunk-GJ57SZGI.mjs.map +1 -0
  38. package/dist/esm/chunk-JII456TS.mjs +34 -0
  39. package/dist/esm/chunk-JII456TS.mjs.map +1 -0
  40. package/dist/esm/chunk-NSFLAANF.mjs +80 -0
  41. package/dist/esm/chunk-NSFLAANF.mjs.map +1 -0
  42. package/dist/esm/{chunk-PCJKIY5G.mjs → chunk-RYT6M3PA.mjs} +29 -501
  43. package/dist/esm/chunk-RYT6M3PA.mjs.map +1 -0
  44. package/dist/esm/chunk-WKBC5YMI.mjs +291 -0
  45. package/dist/esm/chunk-WKBC5YMI.mjs.map +1 -0
  46. package/dist/esm/exact/client/index.d.mts +3 -2
  47. package/dist/esm/exact/client/index.mjs +8 -5
  48. package/dist/esm/exact/facilitator/index.mjs +84 -430
  49. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  50. package/dist/esm/exact/server/index.d.mts +18 -17
  51. package/dist/esm/exact/server/index.mjs +28 -55
  52. package/dist/esm/exact/server/index.mjs.map +1 -1
  53. package/dist/esm/exact/v1/client/index.mjs +2 -1
  54. package/dist/esm/exact/v1/facilitator/index.mjs +2 -1
  55. package/dist/esm/index.d.mts +38 -2
  56. package/dist/esm/index.mjs +21 -8
  57. package/dist/esm/index.mjs.map +1 -1
  58. package/dist/esm/{permit2-Bbh3a8_h.d.mts → permit2-CyZxwngN.d.mts} +278 -87
  59. package/dist/esm/scheme-DCR7hsa3.d.mts +47 -0
  60. package/dist/esm/upto/client/index.d.mts +32 -0
  61. package/dist/esm/upto/client/index.mjs +18 -0
  62. package/dist/esm/upto/client/index.mjs.map +1 -0
  63. package/dist/esm/upto/facilitator/index.d.mts +52 -0
  64. package/dist/esm/upto/facilitator/index.mjs +473 -0
  65. package/dist/esm/upto/facilitator/index.mjs.map +1 -0
  66. package/dist/esm/upto/server/index.d.mts +77 -0
  67. package/dist/esm/upto/server/index.mjs +145 -0
  68. package/dist/esm/upto/server/index.mjs.map +1 -0
  69. package/dist/esm/v1/index.d.mts +2 -0
  70. package/dist/esm/v1/index.mjs +2 -1
  71. package/package.json +31 -1
  72. package/dist/esm/chunk-GD4MKCN7.mjs +0 -57
  73. package/dist/esm/chunk-GD4MKCN7.mjs.map +0 -1
  74. package/dist/esm/chunk-LWO35IGS.mjs +0 -518
  75. package/dist/esm/chunk-LWO35IGS.mjs.map +0 -1
  76. package/dist/esm/chunk-PCJKIY5G.mjs.map +0 -1
  77. package/dist/esm/chunk-TKN5V2BV.mjs +0 -13
  78. package/dist/esm/chunk-TKN5V2BV.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/upto/client/index.ts","../../../../src/constants.ts","../../../../src/utils.ts","../../../../src/upto/client/permit2.ts","../../../../src/exact/client/permit2.ts","../../../../src/exact/extensions.ts","../../../../src/shared/permit2.ts","../../../../src/multicall.ts","../../../../src/shared/erc20approval.ts","../../../../src/shared/extensions.ts","../../../../src/exact/client/eip2612.ts","../../../../src/exact/client/erc20approval.ts","../../../../src/shared/rpc.ts","../../../../src/upto/client/scheme.ts"],"sourcesContent":["// Note: The upto scheme does not provide register.ts convenience helpers (unlike exact).\n// The exact scheme's register helpers exist primarily for V1 backward compatibility,\n// which is not needed for upto. Use direct class instantiation instead:\n// client.register(\"eip155:*\", new UptoEvmScheme(signer, options))\nexport { UptoEvmScheme } from \"./scheme\";\nexport type {\n UptoEvmSchemeConfig,\n UptoEvmSchemeConfigByChainId,\n UptoEvmSchemeOptions,\n} from \"./rpc\";\nexport {\n createPermit2ApprovalTx,\n getPermit2AllowanceReadParams,\n type Permit2AllowanceParams,\n} from \"./permit2\";\nexport { erc20AllowanceAbi } from \"../../constants\";\n","// EIP-3009 TransferWithAuthorization types for EIP-712 signing\nexport const authorizationTypes = {\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} as const;\n\n/**\n * Permit2 EIP-712 types for signing PermitWitnessTransferFrom (exact scheme).\n * Must match the exact format expected by the Permit2 contract.\n * Note: Types must be in ALPHABETICAL order after the primary type (TokenPermissions < Witness).\n */\nexport const permit2WitnessTypes = {\n PermitWitnessTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n { name: \"witness\", type: \"Witness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n Witness: [\n { name: \"to\", type: \"address\" },\n { name: \"validAfter\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Permit2 EIP-712 types for signing PermitWitnessTransferFrom (upto scheme).\n * The upto witness includes a `facilitator` field that the exact witness does not.\n * This ensures only the authorized facilitator can settle the payment.\n * Must match: Witness(address to,address facilitator,uint256 validAfter)\n */\nexport const uptoPermit2WitnessTypes = {\n PermitWitnessTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n { name: \"witness\", type: \"Witness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n Witness: [\n { name: \"to\", type: \"address\" },\n { name: \"facilitator\", type: \"address\" },\n { name: \"validAfter\", type: \"uint256\" },\n ],\n} as const;\n\n// EIP3009 ABI for transferWithAuthorization function\nexport const eip3009ABI = [\n {\n inputs: [\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 { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n name: \"transferWithAuthorization\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [\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 { name: \"signature\", type: \"bytes\" },\n ],\n name: \"transferWithAuthorization\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [{ name: \"account\", type: \"address\" }],\n name: \"balanceOf\",\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [],\n name: \"version\",\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [],\n name: \"name\",\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"authorizer\", type: \"address\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n name: \"authorizationState\",\n outputs: [{ name: \"\", type: \"bool\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\n/**\n * EIP-2612 Permit EIP-712 types for signing token.permit().\n */\nexport const eip2612PermitTypes = {\n Permit: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * EIP-2612 nonces ABI for querying current nonce.\n */\nexport const eip2612NoncesAbi = [\n {\n type: \"function\",\n name: \"nonces\",\n inputs: [{ name: \"owner\", type: \"address\" }],\n outputs: [{ type: \"uint256\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/** ERC-20 approve(address,uint256) ABI for encoding/decoding approval calldata. */\nexport const erc20ApproveAbi = [\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ type: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n] as const;\n\n/** ERC-20 allowance(address,address) ABI for checking spender approval. */\nexport const erc20AllowanceAbi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [{ type: \"uint256\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/** Gas limit for a standard ERC-20 approve() transaction. */\nexport const ERC20_APPROVE_GAS_LIMIT = 70_000n;\n\n/** Fallback max fee per gas (1 gwei) when fee estimation fails. */\nexport const DEFAULT_MAX_FEE_PER_GAS = 1_000_000_000n;\n\n/** Fallback max priority fee per gas (0.1 gwei) when fee estimation fails. */\nexport const DEFAULT_MAX_PRIORITY_FEE_PER_GAS = 100_000_000n;\n\n/**\n * Canonical Permit2 contract address.\n * Same address on all EVM chains via CREATE2 deployment.\n *\n * @see https://github.com/Uniswap/permit2\n */\nexport const PERMIT2_ADDRESS = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\" as const;\n\n/**\n * x402ExactPermit2Proxy contract address.\n * Vanity address: 0x4020...0001 for easy recognition.\n * This address is deterministic based on:\n * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C)\n * - Vanity-mined salt for prefix 0x4020 and suffix 0001\n * - Contract bytecode + constructor args (PERMIT2_ADDRESS)\n */\nexport const x402ExactPermit2ProxyAddress = \"0x402085c248EeA27D92E8b30b2C58ed07f9E20001\" as const;\n\n/**\n * x402UptoPermit2Proxy contract address.\n * Vanity address: 0x4020...0002 for easy recognition.\n * This address is deterministic based on:\n * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C)\n * - Vanity-mined salt for prefix 0x4020 and suffix 0002\n * - Contract bytecode + constructor args (PERMIT2_ADDRESS)\n */\nexport const x402UptoPermit2ProxyAddress = \"0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002\" as const;\n\n/**\n * ABI components for the exact Permit2 witness tuple: Witness(address to, uint256 validAfter).\n */\nconst permit2WitnessABIComponents = [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n] as const;\n\n/**\n * ABI components for the upto Permit2 witness tuple:\n * Witness(address to, address facilitator, uint256 validAfter).\n */\nconst uptoPermit2WitnessABIComponents = [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"facilitator\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n] as const;\n\n/**\n * x402UptoPermit2Proxy ABI — settle/settleWithPermit for the upto payment scheme.\n * Key differences from exact: settle() takes a `uint256 amount` parameter, and the\n * Witness struct includes an `address facilitator` field.\n */\nexport const x402UptoPermit2ProxyABI = [\n {\n type: \"function\",\n name: \"PERMIT2\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\", internalType: \"contract ISignatureTransfer\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPE_STRING\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.Witness\",\n components: uptoPermit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settleWithPermit\",\n inputs: [\n {\n name: \"permit2612\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.EIP2612Permit\",\n components: [\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"r\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"s\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"v\", type: \"uint8\", internalType: \"uint8\" },\n ],\n },\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.Witness\",\n components: uptoPermit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n { type: \"event\", name: \"Settled\", inputs: [], anonymous: false },\n { type: \"event\", name: \"SettledWithPermit\", inputs: [], anonymous: false },\n { type: \"error\", name: \"AmountExceedsPermitted\", inputs: [] },\n { type: \"error\", name: \"InvalidDestination\", inputs: [] },\n { type: \"error\", name: \"InvalidOwner\", inputs: [] },\n { type: \"error\", name: \"InvalidPermit2Address\", inputs: [] },\n { type: \"error\", name: \"PaymentTooEarly\", inputs: [] },\n { type: \"error\", name: \"Permit2612AmountMismatch\", inputs: [] },\n { type: \"error\", name: \"ReentrancyGuardReentrantCall\", inputs: [] },\n { type: \"error\", name: \"UnauthorizedFacilitator\", inputs: [] },\n] as const;\n\n/**\n * x402ExactPermit2Proxy ABI - settle function for exact payment scheme.\n */\nexport const x402ExactPermit2ProxyABI = [\n {\n type: \"function\",\n name: \"PERMIT2\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\", internalType: \"contract ISignatureTransfer\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPE_STRING\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.Witness\",\n components: permit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settleWithPermit\",\n inputs: [\n {\n name: \"permit2612\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.EIP2612Permit\",\n components: [\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"r\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"s\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"v\", type: \"uint8\", internalType: \"uint8\" },\n ],\n },\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.Witness\",\n components: permit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n { type: \"event\", name: \"Settled\", inputs: [], anonymous: false },\n { type: \"event\", name: \"SettledWithPermit\", inputs: [], anonymous: false },\n { type: \"error\", name: \"InvalidAmount\", inputs: [] },\n { type: \"error\", name: \"InvalidDestination\", inputs: [] },\n { type: \"error\", name: \"InvalidOwner\", inputs: [] },\n { type: \"error\", name: \"InvalidPermit2Address\", inputs: [] },\n { type: \"error\", name: \"PaymentTooEarly\", inputs: [] },\n { type: \"error\", name: \"Permit2612AmountMismatch\", inputs: [] },\n { type: \"error\", name: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\n\n/**\n * Extract chain ID from a CAIP-2 network identifier (eip155:CHAIN_ID).\n *\n * @param network - The network identifier in CAIP-2 format (e.g., \"eip155:8453\")\n * @returns The numeric chain ID\n * @throws Error if the network format is invalid\n */\nexport function getEvmChainId(network: string): number {\n if (network.startsWith(\"eip155:\")) {\n const idStr = network.split(\":\")[1];\n const chainId = parseInt(idStr, 10);\n if (isNaN(chainId)) {\n throw new Error(`Invalid CAIP-2 chain ID: ${network}`);\n }\n return chainId;\n }\n\n throw new Error(`Unsupported network format: ${network} (expected eip155:CHAIN_ID)`);\n}\n\n/**\n * Get the crypto object from the global scope.\n *\n * @returns The crypto object\n * @throws Error if crypto API is not available\n */\nfunction getCrypto(): Crypto {\n const cryptoObj = globalThis.crypto as Crypto | undefined;\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n return cryptoObj;\n}\n\n/**\n * Create a random 32-byte nonce for EIP-3009 authorization.\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n return toHex(getCrypto().getRandomValues(new Uint8Array(32)));\n}\n\n/**\n * Creates a random 256-bit nonce for Permit2.\n * Permit2 uses uint256 nonces (not bytes32 like EIP-3009).\n *\n * @returns A string representation of the random nonce\n */\nexport function createPermit2Nonce(): string {\n const randomBytes = getCrypto().getRandomValues(new Uint8Array(32));\n return BigInt(toHex(randomBytes)).toString();\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@payai/x402/types\";\nimport {\n PERMIT2_ADDRESS,\n uptoPermit2WitnessTypes,\n x402UptoPermit2ProxyAddress,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { UptoPermit2Authorization } from \"../../types\";\nimport { createPermit2Nonce, getEvmChainId } from \"../../utils\";\nimport { getAddress } from \"viem\";\n\n// Re-export Permit2-generic approval helpers\nexport { createPermit2ApprovalTx, getPermit2AllowanceReadParams } from \"../../exact/client/permit2\";\nexport type { Permit2AllowanceParams } from \"../../exact/client/permit2\";\n\n/**\n * Creates a signed upto Permit2 payment payload for the given requirements.\n *\n * Constructs a Permit2 authorization with an upto witness (including facilitator address)\n * and signs it using EIP-712 typed data.\n *\n * @param signer - The EVM client signer for signing typed data\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements including asset, amount, and payTo\n * @returns Promise resolving to a payment payload result with the signed authorization\n */\nexport async function createUptoPermit2Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const facilitatorAddress = paymentRequirements.extra?.facilitatorAddress as\n | `0x${string}`\n | undefined;\n if (!facilitatorAddress) {\n throw new Error(\n \"upto scheme requires facilitatorAddress in paymentRequirements.extra. \" +\n \"Ensure the server is configured with an upto facilitator that provides getExtra().\",\n );\n }\n\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n const validAfter = (now - 600).toString();\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n if (BigInt(deadline) <= BigInt(validAfter)) {\n throw new Error(\n `Invalid time window: deadline (${deadline}) must be after validAfter (${validAfter}). ` +\n `Check that maxTimeoutSeconds (${paymentRequirements.maxTimeoutSeconds}) is positive.`,\n );\n }\n\n const permit2Authorization: UptoPermit2Authorization & { from: `0x${string}` } = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: x402UptoPermit2ProxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n facilitator: getAddress(facilitatorAddress),\n validAfter,\n },\n };\n\n const chainId = getEvmChainId(paymentRequirements.network);\n\n const signature = await signer.signTypedData({\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: uptoPermit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message: {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n facilitator: getAddress(permit2Authorization.witness.facilitator),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n },\n },\n });\n\n return {\n x402Version,\n payload: { signature, permit2Authorization },\n };\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@payai/x402/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport {\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n erc20ApproveAbi,\n erc20AllowanceAbi,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { createPermit2PayloadForProxy } from \"../../shared/permit2\";\n\n/** Maximum uint256 value for unlimited approval. */\nconst MAX_UINT256 = BigInt(\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\");\n\n/**\n * Creates a Permit2 payload using the x402Permit2Proxy witness pattern.\n * The spender is set to x402Permit2Proxy, which enforces that funds\n * can only be sent to the witness.to address.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n return createPermit2PayloadForProxy(\n x402ExactPermit2ProxyAddress,\n signer,\n x402Version,\n paymentRequirements,\n );\n}\n\n/**\n * Creates transaction data to approve Permit2 to spend tokens.\n * The user sends this transaction (paying gas) before using Permit2 flow.\n *\n * @param tokenAddress - The ERC20 token contract address\n * @returns Transaction data to send for approval\n *\n * @example\n * ```typescript\n * const tx = createPermit2ApprovalTx(\"0x...\");\n * await walletClient.sendTransaction({\n * to: tx.to,\n * data: tx.data,\n * });\n * ```\n */\nexport function createPermit2ApprovalTx(tokenAddress: `0x${string}`): {\n to: `0x${string}`;\n data: `0x${string}`;\n} {\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [PERMIT2_ADDRESS, MAX_UINT256],\n });\n\n return {\n to: getAddress(tokenAddress),\n data,\n };\n}\n\n/**\n * Parameters for checking Permit2 allowance.\n * Application provides these to check if approval is needed.\n */\nexport interface Permit2AllowanceParams {\n tokenAddress: `0x${string}`;\n ownerAddress: `0x${string}`;\n}\n\n/**\n * Returns contract read parameters for checking Permit2 allowance.\n * Use with a public client to check if the user has approved Permit2.\n *\n * @param params - The allowance check parameters\n * @returns Contract read parameters for checking allowance\n *\n * @example\n * ```typescript\n * const readParams = getPermit2AllowanceReadParams({\n * tokenAddress: \"0x...\",\n * ownerAddress: \"0x...\",\n * });\n *\n * const allowance = await publicClient.readContract(readParams);\n * const needsApproval = allowance < requiredAmount;\n * ```\n */\nexport function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): {\n address: `0x${string}`;\n abi: typeof erc20AllowanceAbi;\n functionName: \"allowance\";\n args: [`0x${string}`, `0x${string}`];\n} {\n return {\n address: getAddress(params.tokenAddress),\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [getAddress(params.ownerAddress), PERMIT2_ADDRESS],\n };\n}\n","import type { PaymentPayload } from \"@payai/x402/types\";\nimport type { FacilitatorEvmSigner } from \"../signer\";\n\nexport const EIP2612_GAS_SPONSORING_KEY = \"eip2612GasSponsoring\" as const;\nexport const ERC20_APPROVAL_GAS_SPONSORING_KEY = \"erc20ApprovalGasSponsoring\" as const;\nexport const ERC20_APPROVAL_GAS_SPONSORING_VERSION = \"1\" as const;\n\nexport interface Eip2612GasSponsoringInfo {\n [key: string]: unknown;\n from: string;\n asset: string;\n spender: string;\n amount: string;\n nonce: string;\n deadline: string;\n signature: string;\n version: string;\n}\n\nexport interface Erc20ApprovalGasSponsoringInfo {\n [key: string]: unknown;\n from: `0x${string}`;\n asset: `0x${string}`;\n spender: `0x${string}`;\n amount: string;\n signedTransaction: `0x${string}`;\n version: string;\n}\n\n/**\n * A single transaction to be executed by the signer.\n * - `0x${string}`: a pre-signed serialized transaction (broadcast as-is via sendRawTransaction)\n * - `{ to, data, gas? }`: an unsigned call intent (signer signs and broadcasts)\n */\nexport type TransactionRequest =\n | `0x${string}`\n | { to: `0x${string}`; data: `0x${string}`; gas?: bigint };\n\nexport type Erc20ApprovalGasSponsoringSigner = FacilitatorEvmSigner & {\n sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>;\n simulateTransactions?(transactions: TransactionRequest[]): Promise<boolean>;\n};\n\nexport interface Erc20ApprovalGasSponsoringFacilitatorExtension {\n key: typeof ERC20_APPROVAL_GAS_SPONSORING_KEY;\n signer?: Erc20ApprovalGasSponsoringSigner;\n signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined;\n}\n\n/**\n * Extracts a typed `info` payload from an extension entry.\n *\n * @param payload - Payment payload containing optional extensions.\n * @param extensionKey - Extension key to extract.\n * @returns The extension `info` object when present; otherwise null.\n */\nfunction _extractInfo(\n payload: PaymentPayload,\n extensionKey: string,\n): Record<string, unknown> | null {\n const extensions = payload.extensions;\n if (!extensions) return null;\n const extension = extensions[extensionKey] as { info?: Record<string, unknown> } | undefined;\n if (!extension?.info) return null;\n return extension.info;\n}\n\n/**\n * Extracts and validates required EIP-2612 gas sponsoring fields.\n *\n * @param payload - Payment payload returned by the client scheme.\n * @returns Parsed EIP-2612 gas sponsoring info when available and complete.\n */\nexport function extractEip2612GasSponsoringInfo(\n payload: PaymentPayload,\n): Eip2612GasSponsoringInfo | null {\n const info = _extractInfo(payload, EIP2612_GAS_SPONSORING_KEY);\n if (!info) return null;\n if (\n !info.from ||\n !info.asset ||\n !info.spender ||\n !info.amount ||\n !info.nonce ||\n !info.deadline ||\n !info.signature ||\n !info.version\n ) {\n return null;\n }\n return info as unknown as Eip2612GasSponsoringInfo;\n}\n\n/**\n * Validates the structure and formatting of EIP-2612 sponsoring info.\n *\n * @param info - EIP-2612 extension info to validate.\n * @returns True when all required fields match expected patterns.\n */\nexport function validateEip2612GasSponsoringInfo(info: Eip2612GasSponsoringInfo): boolean {\n const addressPattern = /^0x[a-fA-F0-9]{40}$/;\n const numericPattern = /^[0-9]+$/;\n const hexPattern = /^0x[a-fA-F0-9]+$/;\n const versionPattern = /^[0-9]+(\\.[0-9]+)*$/;\n return (\n addressPattern.test(info.from) &&\n addressPattern.test(info.asset) &&\n addressPattern.test(info.spender) &&\n numericPattern.test(info.amount) &&\n numericPattern.test(info.nonce) &&\n numericPattern.test(info.deadline) &&\n hexPattern.test(info.signature) &&\n versionPattern.test(info.version)\n );\n}\n\n/**\n * Extracts and validates required ERC-20 approval sponsoring fields.\n *\n * @param payload - Payment payload returned by the client scheme.\n * @returns Parsed ERC-20 approval sponsoring info when available and complete.\n */\nexport function extractErc20ApprovalGasSponsoringInfo(\n payload: PaymentPayload,\n): Erc20ApprovalGasSponsoringInfo | null {\n const info = _extractInfo(payload, ERC20_APPROVAL_GAS_SPONSORING_KEY);\n if (!info) return null;\n if (\n !info.from ||\n !info.asset ||\n !info.spender ||\n !info.amount ||\n !info.signedTransaction ||\n !info.version\n ) {\n return null;\n }\n return info as unknown as Erc20ApprovalGasSponsoringInfo;\n}\n\n/**\n * Validates the structure and formatting of ERC-20 approval sponsoring info.\n *\n * @param info - ERC-20 approval extension info to validate.\n * @returns True when all required fields match expected patterns.\n */\nexport function validateErc20ApprovalGasSponsoringInfo(\n info: Erc20ApprovalGasSponsoringInfo,\n): boolean {\n const addressPattern = /^0x[a-fA-F0-9]{40}$/;\n const numericPattern = /^[0-9]+$/;\n const hexPattern = /^0x[a-fA-F0-9]+$/;\n const versionPattern = /^[0-9]+(\\.[0-9]+)*$/;\n return (\n addressPattern.test(info.from) &&\n addressPattern.test(info.asset) &&\n addressPattern.test(info.spender) &&\n numericPattern.test(info.amount) &&\n hexPattern.test(info.signedTransaction) &&\n versionPattern.test(info.version)\n );\n}\n\n/**\n * Resolves the ERC-20 approval extension signer for a specific network.\n *\n * @param extension - Optional facilitator extension config.\n * @param network - CAIP-2 network identifier.\n * @returns A network-specific signer when available, else the default signer.\n */\nexport function resolveErc20ApprovalExtensionSigner(\n extension: Erc20ApprovalGasSponsoringFacilitatorExtension | undefined,\n network: string,\n): Erc20ApprovalGasSponsoringSigner | undefined {\n if (!extension) return undefined;\n return extension.signerForNetwork?.(network) ?? extension.signer;\n}\n","import {\n PaymentPayload,\n PaymentPayloadResult,\n PaymentRequirements,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@payai/x402/types\";\nimport {\n extractEip2612GasSponsoringInfo,\n validateEip2612GasSponsoringInfo,\n extractErc20ApprovalGasSponsoringInfo,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n type Eip2612GasSponsoringInfo,\n type Erc20ApprovalGasSponsoringFacilitatorExtension,\n type Erc20ApprovalGasSponsoringSigner,\n} from \"../exact/extensions\";\nimport { getAddress, encodeFunctionData } from \"viem\";\nimport { PERMIT2_ADDRESS, eip3009ABI, erc20AllowanceAbi, permit2WitnessTypes } from \"../constants\";\nimport { multicall, ContractCall } from \"../multicall\";\nimport { createPermit2Nonce, getEvmChainId } from \"../utils\";\nimport {\n ErrPermit2612AmountMismatch,\n ErrPermit2InvalidAmount,\n ErrPermit2InvalidDestination,\n ErrPermit2InvalidNonce,\n ErrPermit2InvalidOwner,\n ErrPermit2InvalidSignature,\n ErrPermit2PaymentTooEarly,\n ErrPermit2AllowanceRequired,\n ErrPermit2SimulationFailed,\n ErrPermit2InsufficientBalance,\n ErrPermit2ProxyNotDeployed,\n ErrInvalidTransactionState,\n ErrTransactionFailed,\n ErrInvalidEip2612ExtensionFormat,\n ErrEip2612FromMismatch,\n ErrEip2612AssetMismatch,\n ErrEip2612SpenderNotPermit2,\n ErrEip2612DeadlineExpired,\n ErrErc20ApprovalTxFailed,\n} from \"../exact/facilitator/errors\";\nimport { ClientEvmSigner, FacilitatorEvmSigner } from \"../signer\";\nimport { ExactPermit2Payload, Permit2Authorization, UptoPermit2Payload } from \"../types\";\nimport { validateErc20ApprovalForPayment } from \"./erc20approval\";\nimport {\n ErrUptoAmountExceedsPermitted,\n ErrUptoUnauthorizedFacilitator,\n} from \"../upto/facilitator/errors\";\n\n/**\n * Base type for Permit2 payloads shared between exact and upto schemes.\n * Both {@link ExactPermit2Payload} and {@link UptoPermit2Payload} satisfy this type.\n */\nexport type Permit2PayloadBase = ExactPermit2Payload | UptoPermit2Payload;\n\n/**\n * Configuration for the Permit2 proxy contract used during settlement.\n * The exact and upto schemes use different proxy addresses and ABIs.\n */\nexport type Permit2ProxyConfig = {\n /** The deployed proxy contract address. */\n proxyAddress: `0x${string}`;\n /** The proxy contract ABI (must include settle and settleWithPermit functions). */\n proxyABI: readonly Record<string, unknown>[];\n};\n\n/**\n * Checks Permit2 allowance and validates gas sponsoring extensions if allowance is insufficient.\n *\n * When the on-chain ERC-20 allowance to the Permit2 contract is below the required amount,\n * this function falls back to validating EIP-2612 or ERC-20 approval gas sponsoring extensions\n * attached to the payment payload.\n *\n * @param signer - The facilitator signer for on-chain reads\n * @param payload - The payment payload\n * @param requirements - The payment requirements\n * @param payer - The payer address\n * @param tokenAddress - The token contract address\n * @param context - Optional facilitator context for extension lookup\n * @returns A VerifyResponse if verification should stop (failure), or null to continue\n */\nexport async function verifyPermit2Allowance(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n context?: FacilitatorContext,\n): Promise<VerifyResponse | null> {\n try {\n const allowance = (await signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return null; // Sufficient allowance, continue verification\n }\n\n // Allowance insufficient — try EIP-2612 gas sponsoring first\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null; // EIP-2612 is valid, allowance will be set atomically during settlement\n }\n\n // Try ERC-20 approval gas sponsoring as fallback\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null; // ERC-20 approval is valid, will be broadcast before settlement\n }\n }\n\n return { isValid: false, invalidReason: \"permit2_allowance_required\", payer };\n } catch {\n // Allowance check failed — validate extensions if present; fail closed if none valid\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null;\n }\n\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null;\n }\n }\n\n return { isValid: false, invalidReason: \"permit2_allowance_required\", payer };\n }\n}\n\n/**\n * Waits for a transaction receipt and returns the appropriate SettleResponse.\n *\n * @param signer - Signer with waitForTransactionReceipt capability\n * @param tx - The transaction hash to wait for\n * @param payload - The payment payload (for network info)\n * @param payer - The payer address\n * @returns Promise resolving to a settlement response indicating success or failure\n */\nexport async function waitAndReturnSettleResponse(\n signer: Pick<FacilitatorEvmSigner, \"waitForTransactionReceipt\">,\n tx: `0x${string}`,\n payload: PaymentPayload,\n payer: `0x${string}`,\n): Promise<SettleResponse> {\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: ErrInvalidTransactionState,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n}\n\n/**\n * Maps contract revert errors to structured SettleResponse error reasons.\n *\n * Inspects the error message for known contract revert strings and maps them\n * to the corresponding error reason constants. Falls back to a generic\n * \"transaction_failed\" reason with truncated message for unrecognized errors.\n *\n * @param error - The caught error (typically from a contract write)\n * @param payload - The payment payload (for network info)\n * @param payer - The payer address\n * @returns A failed SettleResponse with the mapped error reason\n */\nexport function mapSettleError(\n error: unknown,\n payload: PaymentPayload,\n payer: `0x${string}`,\n): SettleResponse {\n let errorReason: string = ErrTransactionFailed;\n if (error instanceof Error) {\n const message = error.message;\n if (message.includes(\"Permit2612AmountMismatch\")) {\n errorReason = ErrPermit2612AmountMismatch;\n } else if (message.includes(\"InvalidAmount\")) {\n errorReason = ErrPermit2InvalidAmount;\n } else if (message.includes(\"InvalidDestination\")) {\n errorReason = ErrPermit2InvalidDestination;\n } else if (message.includes(\"InvalidOwner\")) {\n errorReason = ErrPermit2InvalidOwner;\n } else if (message.includes(\"PaymentTooEarly\")) {\n errorReason = ErrPermit2PaymentTooEarly;\n } else if (message.includes(\"InvalidSignature\") || message.includes(\"SignatureExpired\")) {\n errorReason = ErrPermit2InvalidSignature;\n } else if (message.includes(\"InvalidNonce\")) {\n errorReason = ErrPermit2InvalidNonce;\n } else if (message.includes(\"erc20_approval_tx_failed\")) {\n errorReason = ErrErc20ApprovalTxFailed;\n } else if (message.includes(\"AmountExceedsPermitted\")) {\n errorReason = ErrUptoAmountExceedsPermitted;\n } else if (message.includes(\"UnauthorizedFacilitator\")) {\n errorReason = ErrUptoUnauthorizedFacilitator;\n } else {\n errorReason = `${ErrTransactionFailed}: ${message.slice(0, 500)}`;\n }\n }\n return {\n success: false,\n errorReason,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n}\n\n/**\n * Validates EIP-2612 permit extension data for a Permit2 payment.\n *\n * Checks that the permit extension has a valid format and that the from address,\n * asset address, spender address, and deadline all match expectations.\n *\n * @param info - The EIP-2612 gas sponsoring info extracted from the payment payload\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result with isValid flag and optional invalidReason string\n */\nexport function validateEip2612PermitForPayment(\n info: Eip2612GasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): { isValid: boolean; invalidReason?: string } {\n if (!validateEip2612GasSponsoringInfo(info)) {\n return { isValid: false, invalidReason: ErrInvalidEip2612ExtensionFormat };\n }\n\n if (getAddress(info.from as `0x${string}`) !== getAddress(payer)) {\n return { isValid: false, invalidReason: ErrEip2612FromMismatch };\n }\n\n if (getAddress(info.asset as `0x${string}`) !== tokenAddress) {\n return { isValid: false, invalidReason: ErrEip2612AssetMismatch };\n }\n\n if (getAddress(info.spender as `0x${string}`) !== getAddress(PERMIT2_ADDRESS)) {\n return { isValid: false, invalidReason: ErrEip2612SpenderNotPermit2 };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(info.deadline) < BigInt(now + 6)) {\n return { isValid: false, invalidReason: ErrEip2612DeadlineExpired };\n }\n\n return { isValid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Simulation helpers (shared across exact and upto)\n// ---------------------------------------------------------------------------\n\n/**\n * Simulates settle() via eth_call (readContract).\n * Returns true if simulation succeeded, false if it failed.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulatePermit2Settle(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n settleArgs: readonly unknown[],\n): Promise<boolean> {\n try {\n await signer.readContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settle\",\n args: settleArgs,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Simulates settleWithPermit() via eth_call (readContract).\n * The contract atomically calls token.permit() then PERMIT2.permitTransferFrom(),\n * so simulation covers allowance + balance + nonces.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @param eip2612Info - EIP-2612 gas sponsoring info from the payload extension\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulatePermit2SettleWithPermit(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n settleArgs: readonly unknown[],\n eip2612Info: Eip2612GasSponsoringInfo,\n): Promise<boolean> {\n try {\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n\n await signer.readContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settleWithPermit\",\n args: [\n {\n value: BigInt(eip2612Info.amount),\n deadline: BigInt(eip2612Info.deadline),\n r,\n s,\n v,\n },\n ...settleArgs,\n ],\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Delegates the full approve+settle simulation flow to the extension signer via simulateTransactions.\n * The signer owns execution strategy.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param extensionSigner - The extension signer with simulateTransactions capability\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @param erc20Info - Object containing the signed approval transaction\n * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction hex string\n * @returns true if the bundle simulation succeeded, false otherwise\n */\nexport async function simulatePermit2SettleWithErc20Approval(\n config: Permit2ProxyConfig,\n extensionSigner: Erc20ApprovalGasSponsoringSigner,\n settleArgs: readonly unknown[],\n erc20Info: { signedTransaction: string },\n): Promise<boolean> {\n if (!extensionSigner.simulateTransactions) {\n return false;\n }\n\n try {\n const settleData = encodeFunctionData({\n abi: config.proxyABI,\n functionName: \"settle\",\n args: settleArgs,\n });\n\n return await extensionSigner.simulateTransactions([\n erc20Info.signedTransaction as `0x${string}`,\n { to: config.proxyAddress, data: settleData, gas: BigInt(300_000) },\n ]);\n } catch {\n return false;\n }\n}\n\n/**\n * Diagnoses a Permit2 simulation failure by performing a multicall to check the proxy deployment, balance and allowance.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param tokenAddress - ERC-20 token contract address\n * @param permit2Payload - The Permit2 authorization payload\n * @param amountRequired - Required payment amount (as string)\n * @returns VerifyResponse with the most specific failure reason\n */\nexport async function diagnosePermit2SimulationFailure(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n tokenAddress: `0x${string}`,\n permit2Payload: Permit2PayloadBase,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n const diagnosticCalls: ContractCall[] = [\n {\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"PERMIT2\",\n },\n {\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n },\n {\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [proxyResult, balanceResult, allowanceResult] = results;\n\n if (proxyResult.status === \"failure\") {\n return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };\n }\n }\n\n if (allowanceResult.status === \"success\") {\n const allowance = allowanceResult.result as bigint;\n if (allowance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2AllowanceRequired, payer };\n }\n }\n } catch {\n // Diagnostic multicall itself failed — fall through to generic error\n }\n\n return { isValid: false, invalidReason: ErrPermit2SimulationFailed, payer };\n}\n\n/**\n * Targeted multicall for the ERC-20 approval path where simulation cannot be used\n * (the approval hasn't been broadcast yet, so settle() would fail for expected reasons).\n * Checks proxy deployment, payer token balance and payer ETH balance for gas.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param tokenAddress - ERC-20 token contract address\n * @param payer - The payer address\n * @param amountRequired - Required payment amount (as string)\n * @returns VerifyResponse — valid if checks pass, otherwise the most specific failure\n */\nexport async function checkPermit2Prerequisites(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n tokenAddress: `0x${string}`,\n payer: `0x${string}`,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const diagnosticCalls: ContractCall[] = [\n {\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"PERMIT2\",\n },\n {\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [proxyResult, balanceResult] = results;\n\n if (proxyResult.status === \"failure\") {\n return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };\n }\n }\n } catch {\n // Multicall failed — fall through to valid (fail open for prerequisites-only check)\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n}\n\n/**\n * Builds args for exact settle(permit, owner, witness, signature).\n *\n * @param permit2Payload - The Permit2 payload containing authorization and signature data\n * @returns Tuple of contract call arguments for the exact settle function\n */\nexport function buildExactPermit2SettleArgs(permit2Payload: Permit2PayloadBase) {\n return [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n permit2Payload.signature,\n ] as const;\n}\n\n/**\n * Builds args for upto settle(permit, amount, owner, witness, signature).\n * The upto contract's settle() takes an additional `amount` parameter and the witness\n * includes a `facilitator` field.\n *\n * @param permit2Payload - The upto Permit2 payload containing authorization and signature data\n * @param settlementAmount - The amount to settle on-chain\n * @param facilitatorAddress - The facilitator address authorized in the witness\n * @returns Tuple of contract call arguments for the upto settle function\n */\nexport function buildUptoPermit2SettleArgs(\n permit2Payload: UptoPermit2Payload,\n settlementAmount: bigint,\n facilitatorAddress: `0x${string}`,\n) {\n return [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n settlementAmount,\n getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n facilitator: getAddress(facilitatorAddress),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n permit2Payload.signature,\n ] as const;\n}\n\n/**\n * Splits a 65-byte EIP-2612 signature into v, r, s components.\n *\n * @param signature - The hex-encoded 65-byte signature (with or without 0x prefix)\n * @returns Object with v (uint8), r (bytes32 hex), s (bytes32 hex)\n * @throws Error if the signature is not exactly 65 bytes (130 hex chars)\n */\nexport function splitEip2612Signature(signature: string): {\n v: number;\n r: `0x${string}`;\n s: `0x${string}`;\n} {\n const sig = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n\n if (sig.length !== 130) {\n throw new Error(\n `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`,\n );\n }\n\n const r = `0x${sig.slice(0, 64)}` as `0x${string}`;\n const s = `0x${sig.slice(64, 128)}` as `0x${string}`;\n const v = parseInt(sig.slice(128, 130), 16);\n\n return { v, r, s };\n}\n\n// ---------------------------------------------------------------------------\n// Client-side helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a Permit2 payload for any scheme (exact or upto).\n * The only scheme-specific input is the proxy address used as the spender.\n *\n * @param proxyAddress - The x402 proxy contract address to set as spender\n * @param signer - The EVM client signer\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2PayloadForProxy(\n proxyAddress: `0x${string}`,\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n\n // Lower time bound - allow some clock skew\n const validAfter = (now - 600).toString();\n // Upper time bound is enforced by Permit2's deadline field\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n const permit2Authorization: Permit2Authorization & { from: `0x${string}` } = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: proxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n validAfter,\n },\n };\n\n const signature = await signPermit2Authorization(\n signer,\n permit2Authorization,\n paymentRequirements,\n );\n\n return {\n x402Version,\n payload: { signature, permit2Authorization },\n };\n}\n\n/**\n * Signs a Permit2 authorization using EIP-712 with witness data.\n * The signature authorizes the proxy contract to transfer tokens on behalf of the signer.\n *\n * @param signer - The EVM client signer\n * @param permit2Authorization - The Permit2 authorization parameters\n * @param requirements - The payment requirements\n * @returns Promise resolving to the hex-encoded signature\n */\nasync function signPermit2Authorization(\n signer: ClientEvmSigner,\n permit2Authorization: Permit2Authorization & { from: `0x${string}` },\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(requirements.network);\n\n return await signer.signTypedData({\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message: {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n },\n },\n });\n}\n","import { encodeFunctionData, decodeFunctionResult } from \"viem\";\n\n/**\n * Multicall3 contract address.\n * Same address on all EVM chains via CREATE2 deployment.\n *\n * @see https://github.com/mds1/multicall\n */\nexport const MULTICALL3_ADDRESS = \"0xcA11bde05977b3631167028862bE2a173976CA11\" as const;\n\n/** Multicall3 getEthBalance ABI for querying native token balance. */\nexport const multicall3GetEthBalanceAbi = [\n {\n name: \"getEthBalance\",\n inputs: [{ name: \"addr\", type: \"address\" }],\n outputs: [{ name: \"balance\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\n/** Multicall3 tryAggregate ABI for batching calls. */\nconst multicall3ABI = [\n {\n inputs: [\n { name: \"requireSuccess\", type: \"bool\" },\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"callData\", type: \"bytes\" },\n ],\n },\n ],\n name: \"tryAggregate\",\n outputs: [\n {\n name: \"returnData\",\n type: \"tuple[]\",\n components: [\n { name: \"success\", type: \"bool\" },\n { name: \"returnData\", type: \"bytes\" },\n ],\n },\n ],\n stateMutability: \"payable\",\n type: \"function\",\n },\n] as const;\n\nexport type ContractCall = {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n};\n\nexport type RawContractCall = {\n address: `0x${string}`;\n callData: `0x${string}`;\n};\n\nexport type MulticallSuccess = { status: \"success\"; result: unknown };\nexport type MulticallFailure = { status: \"failure\"; error: Error };\nexport type MulticallResult = MulticallSuccess | MulticallFailure;\n\n/**\n * Batches contract calls via Multicall3 `tryAggregate(false, ...)`.\n *\n * Accepts a mix of typed ContractCall (ABI-encoded + decoded) and\n * RawContractCall (pre-encoded calldata, no decoding) entries.\n * Raw calls are useful for the EIP-6492 factory deployment case\n * where calldata is pre-encoded with no ABI available.\n */\ntype ReadContractFn = (args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n}) => Promise<unknown>;\n\n/**\n * Executes multiple contract read calls in a single RPC round-trip using Multicall3.\n *\n * @param readContract - Function that performs a single contract read (e.g. viem readContract)\n * @param calls - Array of contract calls to batch (ContractCall or RawContractCall)\n * @returns A promise that resolves to an array of decoded results, one per call\n */\nexport async function multicall(\n readContract: ReadContractFn,\n calls: ReadonlyArray<ContractCall | RawContractCall>,\n): Promise<MulticallResult[]> {\n const aggregateCalls = calls.map(call => {\n if (\"callData\" in call) {\n return { target: call.address, callData: call.callData };\n }\n const callData = encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args as unknown[],\n });\n return { target: call.address, callData };\n });\n\n const rawResults = (await readContract({\n address: MULTICALL3_ADDRESS,\n abi: multicall3ABI,\n functionName: \"tryAggregate\",\n args: [false, aggregateCalls],\n })) as { success: boolean; returnData: `0x${string}` }[];\n\n return rawResults.map((raw, i) => {\n if (!raw.success) {\n return {\n status: \"failure\" as const,\n error: new Error(`multicall: call reverted (returnData: ${raw.returnData})`),\n };\n }\n\n const call = calls[i];\n if (\"callData\" in call) {\n return { status: \"success\" as const, result: undefined };\n }\n\n try {\n const decoded = decodeFunctionResult({\n abi: call.abi,\n functionName: call.functionName,\n data: raw.returnData,\n });\n return { status: \"success\" as const, result: decoded };\n } catch (err) {\n return {\n status: \"failure\" as const,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n });\n}\n","import {\n getAddress,\n parseTransaction,\n decodeFunctionData,\n recoverTransactionAddress,\n type TransactionSerialized,\n} from \"viem\";\nimport type { VerifyResponse } from \"@payai/x402/types\";\nimport {\n validateErc20ApprovalGasSponsoringInfo,\n type Erc20ApprovalGasSponsoringInfo,\n} from \"../exact/extensions\";\nimport { PERMIT2_ADDRESS, erc20ApproveAbi } from \"../constants\";\nimport {\n ErrErc20ApprovalInvalidFormat,\n ErrErc20ApprovalFromMismatch,\n ErrErc20ApprovalAssetMismatch,\n ErrErc20ApprovalSpenderNotPermit2,\n ErrErc20ApprovalTxWrongTarget,\n ErrErc20ApprovalTxWrongSelector,\n ErrErc20ApprovalTxWrongSpender,\n ErrErc20ApprovalTxInvalidCalldata,\n ErrErc20ApprovalTxSignerMismatch,\n ErrErc20ApprovalTxInvalidSignature,\n ErrErc20ApprovalTxParseFailed,\n} from \"../exact/facilitator/errors\";\n\n/** The approve(address,uint256) function selector */\nconst APPROVE_SELECTOR = \"0x095ea7b3\";\n\n/**\n * Validates ERC-20 approval extension data for a Permit2 payment.\n *\n * Performs comprehensive validation:\n * - Format validation via validateErc20ApprovalGasSponsoringInfo (JSON Schema)\n * - `from` matches payer\n * - `asset` matches token\n * - `spender` is PERMIT2_ADDRESS\n * - Transaction `to` matches token address\n * - Transaction calldata is a valid approve(PERMIT2_ADDRESS, ...) call\n * - Recovered transaction signer matches `from`\n *\n * @param info - The ERC-20 approval gas sponsoring info\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result with invalidReason and invalidMessage on failure\n */\nexport async function validateErc20ApprovalForPayment(\n info: Erc20ApprovalGasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): Promise<Pick<VerifyResponse, \"isValid\" | \"invalidReason\" | \"invalidMessage\">> {\n if (!validateErc20ApprovalGasSponsoringInfo(info)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalInvalidFormat,\n invalidMessage: \"ERC-20 approval extension info failed schema validation\",\n };\n }\n\n if (getAddress(info.from) !== getAddress(payer)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalFromMismatch,\n invalidMessage: `Expected from=${payer}, got ${info.from}`,\n };\n }\n\n if (getAddress(info.asset) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalAssetMismatch,\n invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`,\n };\n }\n\n if (getAddress(info.spender) !== getAddress(PERMIT2_ADDRESS)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalSpenderNotPermit2,\n invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`,\n };\n }\n\n try {\n const serializedTx = info.signedTransaction as TransactionSerialized;\n const tx = parseTransaction(serializedTx);\n\n if (!tx.to || getAddress(tx.to) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongTarget,\n invalidMessage: `Transaction targets ${tx.to ?? \"null\"}, expected ${tokenAddress}`,\n };\n }\n\n const data = tx.data ?? \"0x\";\n if (!data.startsWith(APPROVE_SELECTOR)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongSelector,\n invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`,\n };\n }\n\n try {\n const decoded = decodeFunctionData({\n abi: erc20ApproveAbi,\n data: data as `0x${string}`,\n });\n const calldataSpender = getAddress(decoded.args[0] as `0x${string}`);\n if (calldataSpender !== getAddress(PERMIT2_ADDRESS)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongSpender,\n invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxInvalidCalldata,\n invalidMessage: \"Failed to decode approve() calldata from the signed transaction\",\n };\n }\n\n try {\n const recoveredAddress = await recoverTransactionAddress({\n serializedTransaction: serializedTx,\n });\n if (getAddress(recoveredAddress) !== getAddress(payer)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxSignerMismatch,\n invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxInvalidSignature,\n invalidMessage: \"Failed to recover signer from the signed transaction\",\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxParseFailed,\n invalidMessage: \"Failed to parse the signed transaction\",\n };\n }\n\n return { isValid: true };\n}\n","import { PaymentRequirements, PaymentPayloadResult, PaymentPayloadContext } from \"@payai/x402/types\";\nimport { EIP2612_GAS_SPONSORING_KEY, ERC20_APPROVAL_GAS_SPONSORING_KEY } from \"../exact/extensions\";\nimport { getAddress } from \"viem\";\nimport { PERMIT2_ADDRESS, erc20AllowanceAbi } from \"../constants\";\nimport { getEvmChainId } from \"../utils\";\nimport { ClientEvmSigner } from \"../signer\";\nimport { signEip2612Permit } from \"../exact/client/eip2612\";\nimport { signErc20ApprovalTransaction } from \"../exact/client/erc20approval\";\nimport { resolveExtensionRpcCapabilities, type ExactEvmSchemeOptions } from \"./rpc\";\n\n/**\n * Attempts to sign an EIP-2612 permit for gasless Permit2 approval.\n *\n * @param signer - The EVM client signer\n * @param options - Optional RPC configuration for backfilling capabilities\n * @param requirements - The payment requirements from the server\n * @param result - The payment payload result from the scheme\n * @param context - Optional context containing server extensions and metadata\n * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable\n */\nexport async function trySignEip2612PermitExtension(\n signer: ClientEvmSigner,\n options: ExactEvmSchemeOptions | undefined,\n requirements: PaymentRequirements,\n result: PaymentPayloadResult,\n context?: PaymentPayloadContext,\n): Promise<Record<string, unknown> | undefined> {\n const capabilities = resolveExtensionRpcCapabilities(requirements.network, signer, options);\n\n if (!capabilities.readContract) {\n return undefined;\n }\n\n if (!context?.extensions?.[EIP2612_GAS_SPONSORING_KEY]) {\n return undefined;\n }\n\n const tokenName = requirements.extra?.name as string | undefined;\n const tokenVersion = requirements.extra?.version as string | undefined;\n if (!tokenName || !tokenVersion) {\n return undefined;\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n\n try {\n const allowance = (await capabilities.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return undefined;\n }\n } catch {\n // Allowance check failed, proceed with signing\n }\n\n const permit2Auth = result.payload?.permit2Authorization as Record<string, unknown> | undefined;\n const deadline =\n (permit2Auth?.deadline as string) ??\n Math.floor(Date.now() / 1000 + requirements.maxTimeoutSeconds).toString();\n\n const info = await signEip2612Permit(\n {\n address: signer.address,\n signTypedData: msg => signer.signTypedData(msg),\n readContract: capabilities.readContract,\n },\n tokenAddress,\n tokenName,\n tokenVersion,\n chainId,\n deadline,\n requirements.amount,\n );\n\n return {\n [EIP2612_GAS_SPONSORING_KEY]: { info },\n };\n}\n\n/**\n * Attempts to sign an ERC-20 approval transaction for gasless Permit2 approval.\n *\n * @param signer - The EVM client signer\n * @param options - Optional RPC configuration for backfilling capabilities\n * @param requirements - The payment requirements from the server\n * @param context - Optional context containing server extensions and metadata\n * @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable\n */\nexport async function trySignErc20ApprovalExtension(\n signer: ClientEvmSigner,\n options: ExactEvmSchemeOptions | undefined,\n requirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n): Promise<Record<string, unknown> | undefined> {\n const capabilities = resolveExtensionRpcCapabilities(requirements.network, signer, options);\n\n if (!capabilities.readContract) {\n return undefined;\n }\n\n if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING_KEY]) {\n return undefined;\n }\n\n if (!capabilities.signTransaction || !capabilities.getTransactionCount) {\n return undefined;\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n\n try {\n const allowance = (await capabilities.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return undefined;\n }\n } catch {\n // Allowance check failed, proceed with signing\n }\n\n const info = await signErc20ApprovalTransaction(\n {\n address: signer.address,\n signTransaction: capabilities.signTransaction,\n getTransactionCount: capabilities.getTransactionCount,\n estimateFeesPerGas: capabilities.estimateFeesPerGas,\n },\n tokenAddress,\n chainId,\n );\n\n return {\n [ERC20_APPROVAL_GAS_SPONSORING_KEY]: { info },\n };\n}\n","import { getAddress } from \"viem\";\nimport { eip2612PermitTypes, eip2612NoncesAbi, PERMIT2_ADDRESS } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport type { Eip2612GasSponsoringInfo } from \"../extensions\";\n\nexport type Eip2612PermitSigner = Pick<ClientEvmSigner, \"address\" | \"signTypedData\"> & {\n readContract: NonNullable<ClientEvmSigner[\"readContract\"]>;\n};\n\n/**\n * Signs an EIP-2612 permit authorizing the Permit2 contract to spend tokens.\n *\n * This creates a gasless off-chain signature that the facilitator can submit\n * on-chain via `x402Permit2Proxy.settleWithPermit()`.\n *\n * The `permittedAmount` must match the Permit2 `permitted.amount` exactly, as the\n * proxy contract enforces `permit2612.value == permittedAmount`.\n *\n * @param signer - The client EVM signer (must support readContract for nonce query)\n * @param tokenAddress - The ERC-20 token contract address\n * @param tokenName - The token name (from paymentRequirements.extra.name)\n * @param tokenVersion - The token version (from paymentRequirements.extra.version)\n * @param chainId - The chain ID\n * @param deadline - The deadline for the permit (unix timestamp as string)\n * @param permittedAmount - The Permit2 permitted amount (must match exactly)\n * @returns The EIP-2612 gas sponsoring info object\n */\nexport async function signEip2612Permit(\n signer: Eip2612PermitSigner,\n tokenAddress: `0x${string}`,\n tokenName: string,\n tokenVersion: string,\n chainId: number,\n deadline: string,\n permittedAmount: string,\n): Promise<Eip2612GasSponsoringInfo> {\n const owner = signer.address;\n const spender = getAddress(PERMIT2_ADDRESS);\n\n // Query the current EIP-2612 nonce from the token contract\n const nonce = (await signer.readContract({\n address: tokenAddress,\n abi: eip2612NoncesAbi,\n functionName: \"nonces\",\n args: [owner],\n })) as bigint;\n\n // Construct EIP-712 domain for the token's permit function\n const domain = {\n name: tokenName,\n version: tokenVersion,\n chainId,\n verifyingContract: tokenAddress,\n };\n\n const approvalAmount = BigInt(permittedAmount);\n\n const message = {\n owner,\n spender,\n value: approvalAmount,\n nonce,\n deadline: BigInt(deadline),\n };\n\n // Sign the EIP-2612 permit\n const signature = await signer.signTypedData({\n domain,\n types: eip2612PermitTypes,\n primaryType: \"Permit\",\n message,\n });\n\n return {\n from: owner,\n asset: tokenAddress,\n spender,\n amount: approvalAmount.toString(),\n nonce: nonce.toString(),\n deadline,\n signature,\n version: \"1\",\n };\n}\n","import { encodeFunctionData, getAddress, maxUint256 } from \"viem\";\nimport {\n PERMIT2_ADDRESS,\n erc20ApproveAbi,\n ERC20_APPROVE_GAS_LIMIT,\n DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_MAX_PRIORITY_FEE_PER_GAS,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport {\n ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n type Erc20ApprovalGasSponsoringInfo,\n} from \"../extensions\";\n\nexport type Erc20ApprovalTxSigner = Pick<ClientEvmSigner, \"address\"> & {\n signTransaction: NonNullable<ClientEvmSigner[\"signTransaction\"]>;\n getTransactionCount: NonNullable<ClientEvmSigner[\"getTransactionCount\"]>;\n estimateFeesPerGas?: NonNullable<ClientEvmSigner[\"estimateFeesPerGas\"]>;\n};\n\n/**\n * Signs an EIP-1559 `approve(Permit2, MaxUint256)` transaction for the given token.\n *\n * The signed transaction is NOT broadcast here — the facilitator broadcasts it\n * atomically before settling the Permit2 payment. This enables Permit2 payments\n * for generic ERC-20 tokens that do NOT implement EIP-2612.\n *\n * Always approves MaxUint256 regardless of the payment amount.\n *\n * @param signer - The client EVM signer (must support signTransaction, getTransactionCount)\n * @param tokenAddress - The ERC-20 token contract address\n * @param chainId - The chain ID\n * @returns The ERC-20 approval gas sponsoring info object\n */\nexport async function signErc20ApprovalTransaction(\n signer: Erc20ApprovalTxSigner,\n tokenAddress: `0x${string}`,\n chainId: number,\n): Promise<Erc20ApprovalGasSponsoringInfo> {\n const from = signer.address;\n const spender = getAddress(PERMIT2_ADDRESS);\n\n // Encode approve(PERMIT2_ADDRESS, MaxUint256) calldata\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [spender, maxUint256],\n });\n\n // Get current nonce for the sender\n const nonce = await signer.getTransactionCount({ address: from });\n\n // Get current fee estimates, with fallback values\n let maxFeePerGas: bigint;\n let maxPriorityFeePerGas: bigint;\n try {\n const fees = await signer.estimateFeesPerGas?.();\n if (!fees) {\n throw new Error(\"no fee estimates available\");\n }\n maxFeePerGas = fees.maxFeePerGas;\n maxPriorityFeePerGas = fees.maxPriorityFeePerGas;\n } catch {\n maxFeePerGas = DEFAULT_MAX_FEE_PER_GAS;\n maxPriorityFeePerGas = DEFAULT_MAX_PRIORITY_FEE_PER_GAS;\n }\n\n // Sign the EIP-1559 transaction (not broadcast)\n const signedTransaction = await signer.signTransaction({\n to: tokenAddress,\n data,\n nonce,\n gas: ERC20_APPROVE_GAS_LIMIT,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chainId,\n });\n\n return {\n from,\n asset: tokenAddress,\n spender,\n amount: maxUint256.toString(),\n signedTransaction,\n version: ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n };\n}\n","import { createPublicClient, http } from \"viem\";\nimport type { ClientEvmSigner } from \"../signer\";\nimport { getEvmChainId } from \"../utils\";\n\nexport type EvmSchemeConfig = {\n rpcUrl?: string;\n};\n\nexport type EvmSchemeConfigByChainId = Record<number, EvmSchemeConfig>;\n\nexport type EvmSchemeOptions = EvmSchemeConfig | EvmSchemeConfigByChainId;\n\n/** @deprecated Use EvmSchemeConfig */\nexport type ExactEvmSchemeConfig = EvmSchemeConfig;\n/** @deprecated Use EvmSchemeConfigByChainId */\nexport type ExactEvmSchemeConfigByChainId = EvmSchemeConfigByChainId;\n/** @deprecated Use EvmSchemeOptions */\nexport type ExactEvmSchemeOptions = EvmSchemeOptions;\n\ntype ExtensionRpcCapabilities = Pick<\n ClientEvmSigner,\n \"readContract\" | \"signTransaction\" | \"getTransactionCount\" | \"estimateFeesPerGas\"\n>;\n\nconst rpcClientCache = new Map<string, ReturnType<typeof createPublicClient>>();\n\n/**\n * Check if options is a per-chain-id configuration map.\n *\n * @param options - The EVM scheme options to check\n * @returns True if the options are keyed by chain ID\n */\nfunction isConfigByChainId(options: EvmSchemeOptions): options is EvmSchemeConfigByChainId {\n const keys = Object.keys(options);\n return keys.length > 0 && keys.every(key => /^\\d+$/.test(key));\n}\n\n/**\n * Get or create a cached viem public client for the given RPC URL.\n *\n * @param rpcUrl - The JSON-RPC endpoint URL\n * @returns A viem PublicClient instance\n */\nfunction getRpcClient(rpcUrl: string): ReturnType<typeof createPublicClient> {\n const existing = rpcClientCache.get(rpcUrl);\n if (existing) {\n return existing;\n }\n\n const client = createPublicClient({\n transport: http(rpcUrl),\n });\n rpcClientCache.set(rpcUrl, client);\n return client;\n}\n\n/**\n * Resolve an RPC URL from scheme options for the given network.\n *\n * @param network - The CAIP-2 network identifier\n * @param options - Optional EVM scheme options (flat or per-chain-id)\n * @returns The resolved RPC URL, or undefined if not configured\n */\nexport function resolveRpcUrl(network: string, options?: EvmSchemeOptions): string | undefined {\n if (!options) {\n return undefined;\n }\n\n if (isConfigByChainId(options)) {\n const chainId = getEvmChainId(network);\n const optionsByChainId = options as EvmSchemeConfigByChainId;\n return optionsByChainId[chainId]?.rpcUrl;\n }\n\n return (options as EvmSchemeConfig).rpcUrl;\n}\n\n/**\n * Resolve RPC capabilities for extensions, backfilling from a public RPC client when the signer lacks them.\n *\n * @param network - The CAIP-2 network identifier\n * @param signer - The client EVM signer\n * @param options - Optional EVM scheme options for RPC URL resolution\n * @returns Extension RPC capabilities (readContract, signTransaction, etc.)\n */\nexport function resolveExtensionRpcCapabilities(\n network: string,\n signer: ClientEvmSigner,\n options?: EvmSchemeOptions,\n): ExtensionRpcCapabilities {\n const capabilities: ExtensionRpcCapabilities = {\n signTransaction: signer.signTransaction,\n readContract: signer.readContract,\n getTransactionCount: signer.getTransactionCount,\n estimateFeesPerGas: signer.estimateFeesPerGas,\n };\n\n const needsRpcBackfill =\n !capabilities.readContract ||\n !capabilities.getTransactionCount ||\n !capabilities.estimateFeesPerGas;\n if (!needsRpcBackfill) {\n return capabilities;\n }\n\n const rpcUrl = resolveRpcUrl(network, options);\n if (!rpcUrl) {\n return capabilities;\n }\n const rpcClient = getRpcClient(rpcUrl);\n if (!capabilities.readContract) {\n capabilities.readContract = args => rpcClient.readContract(args as never) as Promise<unknown>;\n }\n if (!capabilities.getTransactionCount) {\n capabilities.getTransactionCount = async args =>\n rpcClient.getTransactionCount({ address: args.address });\n }\n if (!capabilities.estimateFeesPerGas) {\n capabilities.estimateFeesPerGas = async () => rpcClient.estimateFeesPerGas();\n }\n\n return capabilities;\n}\n","import {\n SchemeNetworkClient,\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@payai/x402/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { createUptoPermit2Payload } from \"./permit2\";\nimport {\n trySignEip2612PermitExtension,\n trySignErc20ApprovalExtension,\n} from \"../../shared/extensions\";\nimport { UptoEvmSchemeOptions } from \"./rpc\";\n\n/**\n * EVM client implementation for the Upto payment scheme.\n * Handles Permit2-based payment payload creation and gas-sponsoring extensions.\n */\nexport class UptoEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"upto\";\n\n /**\n * Creates a new UptoEvmScheme instance.\n *\n * @param signer - The EVM signer for client operations\n * @param options - Optional RPC configuration\n */\n constructor(\n private readonly signer: ClientEvmSigner,\n private readonly options?: UptoEvmSchemeOptions,\n ) {}\n\n /**\n * Creates a payment payload for the Upto scheme using Permit2.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @param context - Optional context with server-declared extensions\n * @returns Promise resolving to a payment payload result\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const result = await createUptoPermit2Payload(this.signer, x402Version, paymentRequirements);\n\n const eip2612Extensions = await trySignEip2612PermitExtension(\n this.signer,\n this.options,\n paymentRequirements,\n result,\n context,\n );\n if (eip2612Extensions) {\n return { ...result, extensions: eip2612Extensions };\n }\n\n const erc20Extensions = await trySignErc20ApprovalExtension(\n this.signer,\n this.options,\n paymentRequirements,\n context,\n );\n if (erc20Extensions) {\n return { ...result, extensions: erc20Extensions };\n }\n\n return result;\n }\n}\n"],"mappings":"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","names":["import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem"]}
@@ -0,0 +1,52 @@
1
+ import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, FacilitatorContext, VerifyResponse, SettleResponse } from '@payai/x402/types';
2
+ import { F as FacilitatorEvmSigner } from '../../signer-D912R4mq.js';
3
+
4
+ /**
5
+ * EVM facilitator implementation for the Upto payment scheme.
6
+ * Handles verification and settlement of Permit2-based payments.
7
+ */
8
+ declare class UptoEvmScheme implements SchemeNetworkFacilitator {
9
+ private readonly signer;
10
+ readonly scheme = "upto";
11
+ readonly caipFamily = "eip155:*";
12
+ /**
13
+ * Creates a new UptoEvmScheme facilitator instance.
14
+ *
15
+ * @param signer - The EVM signer for facilitator operations
16
+ */
17
+ constructor(signer: FacilitatorEvmSigner);
18
+ /**
19
+ * Returns extra metadata required by the upto scheme, including the facilitator address.
20
+ *
21
+ * @param _ - The network identifier (unused)
22
+ * @returns Object with facilitatorAddress, or undefined if no signer addresses are available
23
+ */
24
+ getExtra(_: string): Record<string, unknown> | undefined;
25
+ /**
26
+ * Returns the list of facilitator signer addresses for the upto scheme.
27
+ *
28
+ * @param _ - The network identifier (unused)
29
+ * @returns Array of facilitator signer addresses
30
+ */
31
+ getSigners(_: string): string[];
32
+ /**
33
+ * Verifies an upto Permit2 payment payload against the given requirements.
34
+ *
35
+ * @param payload - The payment payload to verify
36
+ * @param requirements - The payment requirements to verify against
37
+ * @param context - Optional facilitator context
38
+ * @returns Promise resolving to a verification response
39
+ */
40
+ verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
41
+ /**
42
+ * Settles an upto Permit2 payment on-chain.
43
+ *
44
+ * @param payload - The payment payload to settle
45
+ * @param requirements - The payment requirements
46
+ * @param context - Optional facilitator context
47
+ * @returns Promise resolving to a settlement response
48
+ */
49
+ settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
50
+ }
51
+
52
+ export { UptoEvmScheme };