@payai/x402-evm 2.4.1 → 2.4.3

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 (143) hide show
  1. package/dist/cjs/batch-settlement/client/file-storage.d.ts +47 -0
  2. package/dist/cjs/batch-settlement/client/file-storage.js +116 -0
  3. package/dist/cjs/batch-settlement/client/file-storage.js.map +1 -0
  4. package/dist/cjs/batch-settlement/client/index.d.ts +111 -0
  5. package/dist/cjs/batch-settlement/client/index.js +1565 -0
  6. package/dist/cjs/batch-settlement/client/index.js.map +1 -0
  7. package/dist/cjs/batch-settlement/facilitator/index.d.ts +71 -0
  8. package/dist/cjs/batch-settlement/facilitator/index.js +2032 -0
  9. package/dist/cjs/batch-settlement/facilitator/index.js.map +1 -0
  10. package/dist/cjs/batch-settlement/server/file-storage.d.ts +53 -0
  11. package/dist/cjs/batch-settlement/server/file-storage.js +181 -0
  12. package/dist/cjs/batch-settlement/server/file-storage.js.map +1 -0
  13. package/dist/cjs/batch-settlement/server/index.d.ts +491 -0
  14. package/dist/cjs/batch-settlement/server/index.js +1960 -0
  15. package/dist/cjs/batch-settlement/server/index.js.map +1 -0
  16. package/dist/cjs/batch-settlement/server/redis-storage.d.ts +87 -0
  17. package/dist/cjs/batch-settlement/server/redis-storage.js +181 -0
  18. package/dist/cjs/batch-settlement/server/redis-storage.js.map +1 -0
  19. package/dist/cjs/exact/client/index.d.ts +6 -4
  20. package/dist/cjs/exact/client/index.js +7 -5
  21. package/dist/cjs/exact/client/index.js.map +1 -1
  22. package/dist/cjs/exact/facilitator/index.d.ts +16 -9
  23. package/dist/cjs/exact/facilitator/index.js +35 -7
  24. package/dist/cjs/exact/facilitator/index.js.map +1 -1
  25. package/dist/cjs/exact/server/index.js +40 -1
  26. package/dist/cjs/exact/server/index.js.map +1 -1
  27. package/dist/cjs/exact/v1/client/index.d.ts +2 -1
  28. package/dist/cjs/exact/v1/client/index.js.map +1 -1
  29. package/dist/cjs/exact/v1/facilitator/index.d.ts +11 -5
  30. package/dist/cjs/exact/v1/facilitator/index.js +16 -2
  31. package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
  32. package/dist/cjs/index.d.ts +113 -7
  33. package/dist/cjs/index.js +1353 -5
  34. package/dist/cjs/index.js.map +1 -1
  35. package/dist/{esm/permit2-CyZxwngN.d.mts → cjs/permit2-DhJRUcgY.d.ts} +1 -13
  36. package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
  37. package/dist/cjs/scheme-CvkPJXBD.d.ts +307 -0
  38. package/dist/{esm/scheme-DCR7hsa3.d.mts → cjs/scheme-DTQFE9xp.d.ts} +2 -2
  39. package/dist/{esm/signer-D912R4mq.d.mts → cjs/signer-tYS6Y46X.d.ts} +3 -0
  40. package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
  41. package/dist/cjs/storage-Bl6aD0Xg.d.ts +81 -0
  42. package/dist/cjs/types-CF8P2-NM.d.ts +180 -0
  43. package/dist/cjs/upto/client/index.d.ts +5 -3
  44. package/dist/cjs/upto/client/index.js +7 -5
  45. package/dist/cjs/upto/client/index.js.map +1 -1
  46. package/dist/cjs/upto/facilitator/index.d.ts +2 -1
  47. package/dist/cjs/upto/facilitator/index.js +2 -1
  48. package/dist/cjs/upto/facilitator/index.js.map +1 -1
  49. package/dist/cjs/upto/server/index.js +40 -1
  50. package/dist/cjs/upto/server/index.js.map +1 -1
  51. package/dist/cjs/v1/index.d.ts +2 -1
  52. package/dist/cjs/v1/index.js.map +1 -1
  53. package/dist/esm/batch-settlement/client/file-storage.d.mts +47 -0
  54. package/dist/esm/batch-settlement/client/file-storage.mjs +63 -0
  55. package/dist/esm/batch-settlement/client/file-storage.mjs.map +1 -0
  56. package/dist/esm/batch-settlement/client/index.d.mts +111 -0
  57. package/dist/esm/batch-settlement/client/index.mjs +59 -0
  58. package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
  59. package/dist/esm/batch-settlement/facilitator/index.d.mts +71 -0
  60. package/dist/esm/batch-settlement/facilitator/index.mjs +1235 -0
  61. package/dist/esm/batch-settlement/facilitator/index.mjs.map +1 -0
  62. package/dist/esm/batch-settlement/server/file-storage.d.mts +53 -0
  63. package/dist/esm/batch-settlement/server/file-storage.mjs +128 -0
  64. package/dist/esm/batch-settlement/server/file-storage.mjs.map +1 -0
  65. package/dist/esm/batch-settlement/server/index.d.mts +491 -0
  66. package/dist/esm/batch-settlement/server/index.mjs +1645 -0
  67. package/dist/esm/batch-settlement/server/index.mjs.map +1 -0
  68. package/dist/esm/batch-settlement/server/redis-storage.d.mts +87 -0
  69. package/dist/esm/batch-settlement/server/redis-storage.mjs +156 -0
  70. package/dist/esm/batch-settlement/server/redis-storage.mjs.map +1 -0
  71. package/dist/esm/chunk-2EUQTNJO.mjs +38 -0
  72. package/dist/esm/chunk-2EUQTNJO.mjs.map +1 -0
  73. package/dist/esm/chunk-53USC5VE.mjs +47 -0
  74. package/dist/esm/chunk-53USC5VE.mjs.map +1 -0
  75. package/dist/esm/{chunk-GJ57SZGI.mjs → chunk-6WQOGWBE.mjs} +7 -5
  76. package/dist/esm/{chunk-GJ57SZGI.mjs.map → chunk-6WQOGWBE.mjs.map} +1 -1
  77. package/dist/esm/{chunk-F3OOHBAW.mjs → chunk-BTYNCDNS.mjs} +42 -2
  78. package/dist/esm/{chunk-F3OOHBAW.mjs.map → chunk-BTYNCDNS.mjs.map} +1 -1
  79. package/dist/esm/{chunk-ERK2ZPOY.mjs → chunk-CSQS7ZON.mjs} +27 -7
  80. package/dist/esm/chunk-CSQS7ZON.mjs.map +1 -0
  81. package/dist/esm/chunk-GD4MKCN7.mjs +57 -0
  82. package/dist/esm/chunk-GD4MKCN7.mjs.map +1 -0
  83. package/dist/esm/chunk-HYABYUBD.mjs +432 -0
  84. package/dist/esm/chunk-HYABYUBD.mjs.map +1 -0
  85. package/dist/esm/chunk-IN5YIT5C.mjs +159 -0
  86. package/dist/esm/chunk-IN5YIT5C.mjs.map +1 -0
  87. package/dist/esm/{chunk-JII456TS.mjs → chunk-JK7SLLF7.mjs} +1 -1
  88. package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
  89. package/dist/esm/{chunk-C4ZQMS77.mjs → chunk-MACPBXCT.mjs} +2 -216
  90. package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
  91. package/dist/esm/chunk-NKYVYGRA.mjs +911 -0
  92. package/dist/esm/chunk-NKYVYGRA.mjs.map +1 -0
  93. package/dist/esm/{chunk-FQJR4RCF.mjs → chunk-R7I3RZFF.mjs} +10 -6
  94. package/dist/esm/{chunk-FQJR4RCF.mjs.map → chunk-R7I3RZFF.mjs.map} +1 -1
  95. package/dist/esm/{chunk-CRT6YNY5.mjs → chunk-RWLVVO3B.mjs} +21 -61
  96. package/dist/esm/chunk-RWLVVO3B.mjs.map +1 -0
  97. package/dist/esm/chunk-TGFAVNUD.mjs +111 -0
  98. package/dist/esm/chunk-TGFAVNUD.mjs.map +1 -0
  99. package/dist/esm/chunk-TW7Z65AO.mjs +34 -0
  100. package/dist/esm/chunk-TW7Z65AO.mjs.map +1 -0
  101. package/dist/esm/chunk-U4HCGTLU.mjs +35 -0
  102. package/dist/esm/chunk-U4HCGTLU.mjs.map +1 -0
  103. package/dist/esm/chunk-VS3RYAYE.mjs +80 -0
  104. package/dist/esm/chunk-VS3RYAYE.mjs.map +1 -0
  105. package/dist/esm/chunk-W6ON4LG2.mjs +39 -0
  106. package/dist/esm/chunk-W6ON4LG2.mjs.map +1 -0
  107. package/dist/esm/{chunk-WKBC5YMI.mjs → chunk-YMQCTKDU.mjs} +23 -55
  108. package/dist/esm/chunk-YMQCTKDU.mjs.map +1 -0
  109. package/dist/esm/exact/client/index.d.mts +6 -4
  110. package/dist/esm/exact/client/index.mjs +10 -5
  111. package/dist/esm/exact/facilitator/index.d.mts +16 -9
  112. package/dist/esm/exact/facilitator/index.mjs +36 -14
  113. package/dist/esm/exact/facilitator/index.mjs.map +1 -1
  114. package/dist/esm/exact/server/index.mjs +1 -1
  115. package/dist/esm/exact/v1/client/index.d.mts +2 -1
  116. package/dist/esm/exact/v1/client/index.mjs +5 -2
  117. package/dist/esm/exact/v1/facilitator/index.d.mts +11 -5
  118. package/dist/esm/exact/v1/facilitator/index.mjs +5 -2
  119. package/dist/esm/index.d.mts +113 -7
  120. package/dist/esm/index.mjs +53 -7
  121. package/dist/esm/index.mjs.map +1 -1
  122. package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
  123. package/dist/esm/rpc-DULZzRne.d.mts +13 -0
  124. package/dist/esm/scheme-DtbSS4Fk.d.mts +307 -0
  125. package/dist/esm/scheme-gtqAIYPJ.d.mts +47 -0
  126. package/dist/esm/signer-tYS6Y46X.d.mts +170 -0
  127. package/dist/esm/storage-6W5MO46W.d.mts +50 -0
  128. package/dist/esm/storage-sZ1CDS4P.d.mts +81 -0
  129. package/dist/esm/types-CF8P2-NM.d.mts +180 -0
  130. package/dist/esm/upto/client/index.d.mts +5 -3
  131. package/dist/esm/upto/client/index.mjs +9 -4
  132. package/dist/esm/upto/facilitator/index.d.mts +2 -1
  133. package/dist/esm/upto/facilitator/index.mjs +17 -9
  134. package/dist/esm/upto/facilitator/index.mjs.map +1 -1
  135. package/dist/esm/upto/server/index.mjs +1 -1
  136. package/dist/esm/v1/index.d.mts +2 -1
  137. package/dist/esm/v1/index.mjs +5 -2
  138. package/package.json +5 -5
  139. package/dist/esm/chunk-C4ZQMS77.mjs.map +0 -1
  140. package/dist/esm/chunk-CRT6YNY5.mjs.map +0 -1
  141. package/dist/esm/chunk-ERK2ZPOY.mjs.map +0 -1
  142. package/dist/esm/chunk-JII456TS.mjs.map +0 -1
  143. package/dist/esm/chunk-WKBC5YMI.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/batch-settlement/facilitator/index.ts","../../../../src/batch-settlement/constants.ts","../../../../src/batch-settlement/types.ts","../../../../src/batch-settlement/facilitator/deposit.ts","../../../../src/batch-settlement/abi.ts","../../../../src/utils.ts","../../../../src/multicall.ts","../../../../src/batch-settlement/errors.ts","../../../../src/batch-settlement/facilitator/utils.ts","../../../../src/batch-settlement/utils.ts","../../../../src/batch-settlement/facilitator/deposit-eip3009.ts","../../../../src/batch-settlement/encoding.ts","../../../../src/batch-settlement/facilitator/deposit-permit2.ts","../../../../src/exact/extensions.ts","../../../../src/shared/erc20approval.ts","../../../../src/constants.ts","../../../../src/exact/facilitator/errors.ts","../../../../src/shared/permit2.ts","../../../../src/batch-settlement/facilitator/voucher.ts","../../../../src/batch-settlement/facilitator/claim.ts","../../../../src/batch-settlement/authorizerSigner.ts","../../../../src/batch-settlement/facilitator/settle.ts","../../../../src/batch-settlement/facilitator/refund.ts","../../../../src/batch-settlement/facilitator/scheme.ts"],"sourcesContent":["export { BatchSettlementEvmScheme } from \"./scheme\";\n","import { keccak256, toBytes } from \"viem\";\n\n/** Scheme identifier for the batch-settlement payment scheme. */\nexport const BATCH_SETTLEMENT_SCHEME = \"batch-settlement\" as const;\n\n/** Deployed address of the x402BatchSettlement contract. */\nexport const BATCH_SETTLEMENT_ADDRESS = \"0x4020074e9dF2ce1deE5A9C1b5c3f541D02a10003\" as const;\n\n/** Deployed address of the ERC3009DepositCollector contract. */\nexport const ERC3009_DEPOSIT_COLLECTOR_ADDRESS =\n \"0x4020806089470a89826cB9fB1f4059150b550004\" as const;\n\n/** Deployed address of the Permit2DepositCollector contract. */\nexport const PERMIT2_DEPOSIT_COLLECTOR_ADDRESS =\n \"0x4020425FAf3B746C082C2f942b4E5159887B0005\" as const;\n\n/** Minimum withdraw delay in seconds (15 minutes), matching the onchain constant. */\nexport const MIN_WITHDRAW_DELAY = 900;\n\n/** Maximum withdraw delay in seconds (30 days), matching the onchain constant. */\nexport const MAX_WITHDRAW_DELAY = 2_592_000;\n\n/** EIP-712 domain fields shared across all batch-settlement typed-data signatures. */\nexport const BATCH_SETTLEMENT_DOMAIN = {\n name: \"x402 Batch Settlement\",\n version: \"1\",\n} as const;\n\n/** EIP-712 type hash for channel identity. */\nexport const CHANNEL_CONFIG_TYPEHASH = keccak256(\n toBytes(\n \"ChannelConfig(address payer,address payerAuthorizer,address receiver,address receiverAuthorizer,address token,uint40 withdrawDelay,bytes32 salt)\",\n ),\n);\n\n/** EIP-712 type definition for a channel configuration. */\nexport const channelConfigTypes = {\n ChannelConfig: [\n { name: \"payer\", type: \"address\" },\n { name: \"payerAuthorizer\", type: \"address\" },\n { name: \"receiver\", type: \"address\" },\n { name: \"receiverAuthorizer\", type: \"address\" },\n { name: \"token\", type: \"address\" },\n { name: \"withdrawDelay\", type: \"uint40\" },\n { name: \"salt\", type: \"bytes32\" },\n ],\n} as const;\n\n/** EIP-712 type definition for a cumulative voucher: `Voucher(bytes32 channelId, uint128 maxClaimableAmount)`. */\nexport const voucherTypes = {\n Voucher: [\n { name: \"channelId\", type: \"bytes32\" },\n { name: \"maxClaimableAmount\", type: \"uint128\" },\n ],\n} as const;\n\n/** EIP-712 type definition for cooperative refund: `Refund(bytes32 channelId, uint256 nonce, uint128 amount)`. */\nexport const refundTypes = {\n Refund: [\n { name: \"channelId\", type: \"bytes32\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"amount\", type: \"uint128\" },\n ],\n} as const;\n\n/** EIP-712 type definitions for a receiver-authorizer claim batch (nested ClaimEntry). */\nexport const claimBatchTypes = {\n ClaimBatch: [{ name: \"claims\", type: \"ClaimEntry[]\" }],\n ClaimEntry: [\n { name: \"channelId\", type: \"bytes32\" },\n { name: \"maxClaimableAmount\", type: \"uint128\" },\n { name: \"totalClaimed\", type: \"uint128\" },\n ],\n} as const;\n\n/** EIP-712 type definition for ERC-3009 `ReceiveWithAuthorization` (used for gasless deposits). */\nexport const receiveAuthorizationTypes = {\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} as const;\n\n/** Permit2 typed data for channel-bound batch deposits. */\nexport const batchPermit2WitnessTypes = {\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: \"DepositWitness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n DepositWitness: [{ name: \"channelId\", type: \"bytes32\" }],\n} as const;\n","import type { TypedData } from \"viem\";\n\nexport interface AuthorizerSigner {\n address: `0x${string}`;\n signTypedData(params: {\n domain: Record<string, unknown>;\n types: TypedData;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<`0x${string}`>;\n}\n\nexport type ChannelState = {\n balance: bigint;\n totalClaimed: bigint;\n withdrawRequestedAt: number;\n refundNonce: bigint;\n};\n\nexport type ChannelConfig = {\n payer: `0x${string}`;\n payerAuthorizer: `0x${string}`;\n receiver: `0x${string}`;\n receiverAuthorizer: `0x${string}`;\n token: `0x${string}`;\n withdrawDelay: number;\n salt: `0x${string}`;\n};\n\nexport type BatchSettlementErc3009Authorization = {\n validAfter: string;\n validBefore: string;\n salt: `0x${string}`;\n signature: `0x${string}`;\n};\n\nexport type BatchSettlementPermit2Authorization = {\n from: `0x${string}`;\n permitted: {\n token: `0x${string}`;\n amount: string;\n };\n spender: `0x${string}`;\n nonce: string;\n deadline: string;\n witness: {\n channelId: `0x${string}`;\n };\n signature: `0x${string}`;\n};\n\nexport type BatchSettlementAssetTransferMethod = \"eip3009\" | \"permit2\";\n\nexport type BatchSettlementDepositAuthorization =\n | {\n erc3009Authorization: BatchSettlementErc3009Authorization;\n permit2Authorization?: never;\n }\n | {\n erc3009Authorization?: never;\n permit2Authorization: BatchSettlementPermit2Authorization;\n };\n\nexport type BatchSettlementDepositPayload = {\n type: \"deposit\";\n channelConfig: ChannelConfig;\n voucher: BatchSettlementVoucherFields;\n deposit: {\n amount: string;\n authorization: BatchSettlementDepositAuthorization;\n };\n};\n\nexport type BatchSettlementVoucherPayload = {\n type: \"voucher\";\n channelConfig: ChannelConfig;\n voucher: BatchSettlementVoucherFields;\n};\n\nexport type BatchSettlementRefundPayload = {\n type: \"refund\";\n channelConfig: ChannelConfig;\n voucher: BatchSettlementVoucherFields;\n amount?: string;\n};\n\nexport type BatchSettlementVoucherFields = {\n channelId: `0x${string}`;\n maxClaimableAmount: string;\n signature: `0x${string}`;\n};\n\nexport type BatchSettlementVoucherClaim = {\n voucher: {\n channel: ChannelConfig;\n maxClaimableAmount: string;\n };\n signature: `0x${string}`;\n totalClaimed: string;\n};\n\nexport type BatchSettlementChannelStateExtra = {\n channelId: `0x${string}`;\n balance: string;\n totalClaimed: string;\n withdrawRequestedAt: number;\n refundNonce: string;\n chargedCumulativeAmount?: string;\n};\n\nexport type BatchSettlementVoucherStateExtra = {\n signedMaxClaimable?: string;\n signature?: `0x${string}`;\n};\n\nexport type BatchSettlementPaymentRequirementsExtra = {\n receiverAuthorizer: `0x${string}`;\n withdrawDelay: number;\n name: string;\n version: string;\n assetTransferMethod?: BatchSettlementAssetTransferMethod;\n channelState?: BatchSettlementChannelStateExtra;\n voucherState?: BatchSettlementVoucherStateExtra;\n};\n\nexport type FileChannelStorageOptions = {\n /** Root directory; channels are stored under `{directory}/{client|server}/{channelId}.json`. */\n directory: string;\n};\n\nexport type BatchSettlementPaymentResponseExtra = {\n chargedAmount?: string;\n channelState?: BatchSettlementChannelStateExtra;\n voucherState?: BatchSettlementVoucherStateExtra;\n};\n\nexport type BatchSettlementClaimPayload = {\n type: \"claim\";\n claims: BatchSettlementVoucherClaim[];\n claimAuthorizerSignature?: `0x${string}`;\n};\n\nexport type BatchSettlementSettlePayload = {\n type: \"settle\";\n receiver: `0x${string}`;\n token: `0x${string}`;\n};\n\nexport type BatchSettlementEnrichedRefundPayload = BatchSettlementRefundPayload & {\n amount: string;\n refundNonce: string;\n claims: BatchSettlementVoucherClaim[];\n refundAuthorizerSignature?: `0x${string}`;\n claimAuthorizerSignature?: `0x${string}`;\n};\n\nexport type BatchSettlementPayload =\n | BatchSettlementDepositPayload\n | BatchSettlementVoucherPayload\n | BatchSettlementRefundPayload;\n\nexport type BatchSettlementFacilitatorSettlePayload =\n | BatchSettlementDepositPayload\n | BatchSettlementClaimPayload\n | BatchSettlementSettlePayload\n | BatchSettlementEnrichedRefundPayload;\n\n/**\n * Returns true when the value is a non-null object (a usable record).\n *\n * @param payload - Value of unknown shape.\n * @returns True if `payload` is an object that can be indexed by string keys.\n */\nfunction isObject(payload: unknown): payload is Record<string, unknown> {\n return typeof payload === \"object\" && payload !== null;\n}\n\n/**\n * Type guard for internal voucher field shape (channel, amount, signature).\n *\n * @param payload - Unknown value to check.\n * @returns True if `payload` is an object with `channelId`, `maxClaimableAmount`, and `signature`.\n */\nfunction isVoucherFields(payload: unknown): payload is BatchSettlementVoucherFields {\n return (\n isObject(payload) &&\n \"channelId\" in payload &&\n \"maxClaimableAmount\" in payload &&\n \"signature\" in payload\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementDepositPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a deposit payload (carries `deposit` and `voucher`).\n */\nexport function isBatchSettlementDepositPayload(\n payload: unknown,\n): payload is BatchSettlementDepositPayload {\n return (\n isObject(payload) &&\n payload.type === \"deposit\" &&\n \"channelConfig\" in payload &&\n isVoucherFields(payload.voucher) &&\n isObject(payload.deposit) &&\n typeof payload.deposit.amount === \"string\" &&\n isObject(payload.deposit.authorization)\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementVoucherPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a voucher payload with channel and signature fields.\n */\nexport function isBatchSettlementVoucherPayload(\n payload: unknown,\n): payload is BatchSettlementVoucherPayload {\n return (\n isObject(payload) &&\n payload.type === \"voucher\" &&\n \"channelConfig\" in payload &&\n isVoucherFields(payload.voucher)\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementRefundPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a refund payload with channel config and voucher fields.\n */\nexport function isBatchSettlementRefundPayload(\n payload: unknown,\n): payload is BatchSettlementRefundPayload {\n return (\n isObject(payload) &&\n payload.type === \"refund\" &&\n \"channelConfig\" in payload &&\n isVoucherFields(payload.voucher)\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementClaimPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a settle-action `claimWithSignature` payload.\n */\nexport function isBatchSettlementClaimPayload(\n payload: unknown,\n): payload is BatchSettlementClaimPayload {\n return isObject(payload) && payload.type === \"claim\" && \"claims\" in payload;\n}\n\n/**\n * Type guard for {@link BatchSettlementSettlePayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a settle-action `settle` payload.\n */\nexport function isBatchSettlementSettlePayload(\n payload: unknown,\n): payload is BatchSettlementSettlePayload {\n return (\n isObject(payload) && payload.type === \"settle\" && \"receiver\" in payload && \"token\" in payload\n );\n}\n\n/**\n * Type guard for {@link BatchSettlementEnrichedRefundPayload}.\n *\n * @param payload - Unknown payload to check.\n * @returns True if `payload` is a settle-action `refundWithSignature` payload.\n */\nexport function isBatchSettlementEnrichedRefundPayload(\n payload: unknown,\n): payload is BatchSettlementEnrichedRefundPayload {\n return (\n isBatchSettlementRefundPayload(payload) &&\n \"amount\" in payload &&\n \"refundNonce\" in payload &&\n \"claims\" in payload\n );\n}\n","import {\n FacilitatorContext,\n PaymentPayload,\n PaymentRequirements,\n VerifyResponse,\n SettleResponse,\n} from \"@payai/x402/types\";\nimport { getAddress } from \"viem\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport type { TransactionRequest } from \"../../exact/extensions\";\nimport { BatchSettlementAssetTransferMethod, BatchSettlementDepositPayload } from \"../types\";\nimport { batchSettlementABI, erc20BalanceOfABI } from \"../abi\";\nimport { BATCH_SETTLEMENT_ADDRESS } from \"../constants\";\nimport { getEvmChainId } from \"../../utils\";\nimport { multicall } from \"../../multicall\";\nimport * as Errors from \"../errors\";\nimport {\n readChannelState,\n toContractChannelConfig,\n validateChannelConfig,\n verifyBatchSettlementVoucherTypedData,\n} from \"./utils\";\nimport {\n buildEip3009DepositCollectorData,\n getEip3009DepositCollectorAddress,\n verifyEip3009DepositAuthorization,\n} from \"./deposit-eip3009\";\nimport {\n buildDepositTransaction,\n getPermit2DepositCollectorAddress,\n resolvePermit2DepositBranch,\n verifyPermit2DepositAuthorization,\n} from \"./deposit-permit2\";\n\n/**\n * Verifies a deposit payload (authorization + voucher) without executing any\n * onchain transaction.\n *\n * Performs the following validations:\n * - Token in channelConfig matches the payment requirements asset.\n * - Deposit authorization is valid for the selected transfer method.\n * - Accompanying voucher signature is valid (ECDSA or ERC-1271).\n * - Payer has sufficient token balance for the deposit.\n * - Resulting `maxClaimableAmount` does not exceed effective balance (existing + deposit).\n *\n * @param signer - Facilitator signer for onchain reads and signature verification.\n * @param payment - Full payment envelope containing optional extensions.\n * @param payload - The full deposit payload including channelConfig, amount, authorization, and voucher.\n * @param requirements - Server payment requirements (asset, EIP-712 domain info, timeout, etc.).\n * @param context - Optional facilitator extension context.\n * @returns A {@link VerifyResponse} with channel state in `extra` on success.\n */\nexport async function verifyDeposit(\n signer: FacilitatorEvmSigner,\n payment: PaymentPayload,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n): Promise<VerifyResponse> {\n const payer = payload.channelConfig.payer;\n const chainId = getEvmChainId(requirements.network);\n const configErr = validateChannelConfig(\n payload.channelConfig,\n payload.voucher.channelId,\n requirements,\n );\n if (configErr) {\n return { isValid: false, invalidReason: configErr, payer };\n }\n\n const transferMethod = resolveDepositTransferMethod(payload, requirements);\n if (transferMethod === \"permit2\" && !payload.deposit.authorization.permit2Authorization) {\n return { isValid: false, invalidReason: Errors.ErrInvalidPayloadType, payer };\n }\n\n const methodErr =\n transferMethod === \"permit2\"\n ? await verifyPermit2DepositAuthorization(\n signer,\n payment,\n payload,\n requirements,\n chainId,\n context,\n )\n : await verifyEip3009DepositAuthorization(signer, payload, requirements, chainId);\n\n if (methodErr) {\n return methodErr;\n }\n\n const shared = await verifySharedDepositState(signer, payload, requirements);\n if (!shared.ok) {\n return shared.response;\n }\n\n const { depositAmount, chBalance, chTotalClaimed, wdInitiatedAt, refundNonceVal } = shared;\n\n const execution = await resolveDepositExecution(signer, payment, payload, requirements, context);\n if (\"isValid\" in execution) {\n return execution;\n }\n\n if (!execution.skipDirectSimulation) {\n try {\n await signer.readContract({\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"deposit\",\n args: [\n toContractChannelConfig(payload.channelConfig),\n depositAmount,\n execution.collector,\n execution.collectorData,\n ],\n });\n } catch (e) {\n return {\n isValid: false,\n invalidReason: Errors.ErrDepositSimulationFailed,\n invalidMessage: e instanceof Error ? e.message : String(e),\n payer,\n };\n }\n }\n\n return {\n isValid: true,\n payer,\n extra: {\n channelId: payload.voucher.channelId,\n balance: chBalance.toString(),\n totalClaimed: chTotalClaimed.toString(),\n withdrawRequestedAt: Number(wdInitiatedAt),\n refundNonce: refundNonceVal.toString(),\n },\n };\n}\n\n/**\n * Verifies channel, voucher, balance, and cumulative amount invariants.\n *\n * @param signer - Facilitator signer for reads and voucher verification.\n * @param payload - Batch deposit payload.\n * @param requirements - Payment requirements for the request.\n * @returns Shared channel state on success, or a verification failure.\n */\nasync function verifySharedDepositState(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n): Promise<\n | {\n ok: true;\n chainId: number;\n depositAmount: bigint;\n payer: `0x${string}`;\n chBalance: bigint;\n chTotalClaimed: bigint;\n wdInitiatedAt: bigint;\n refundNonceVal: bigint;\n }\n | { ok: false; response: VerifyResponse }\n> {\n const { deposit, voucher } = payload;\n const config = payload.channelConfig;\n const payer = config.payer;\n const chainId = getEvmChainId(requirements.network);\n\n const configErr = validateChannelConfig(config, voucher.channelId, requirements);\n if (configErr) {\n return { ok: false, response: { isValid: false, invalidReason: configErr, payer } };\n }\n\n const voucherOk = await verifyBatchSettlementVoucherTypedData(\n signer,\n {\n channelId: voucher.channelId,\n maxClaimableAmount: voucher.maxClaimableAmount,\n payerAuthorizer: config.payerAuthorizer,\n payer: config.payer,\n signature: voucher.signature,\n },\n chainId,\n );\n if (!voucherOk) {\n return {\n ok: false,\n response: { isValid: false, invalidReason: Errors.ErrInvalidVoucherSignature, payer },\n };\n }\n\n const mcResults = await multicall(signer.readContract.bind(signer), [\n {\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"channels\",\n args: [voucher.channelId],\n },\n {\n address: getAddress(requirements.asset),\n abi: erc20BalanceOfABI,\n functionName: \"balanceOf\",\n args: [getAddress(payer)],\n },\n {\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"pendingWithdrawals\",\n args: [voucher.channelId],\n },\n {\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"refundNonce\",\n args: [voucher.channelId],\n },\n ]);\n\n const [chRes, balRes, wdRes, rnRes] = mcResults;\n if (\n chRes.status === \"failure\" ||\n balRes.status === \"failure\" ||\n wdRes.status === \"failure\" ||\n rnRes.status === \"failure\"\n ) {\n return {\n ok: false,\n response: { isValid: false, invalidReason: Errors.ErrRpcReadFailed, payer },\n };\n }\n\n const [chBalance, chTotalClaimed] = chRes.result as [bigint, bigint];\n const payerBalance = balRes.result as bigint;\n const [, wdInitiatedAt] = wdRes.result as [bigint, bigint];\n const refundNonceVal = rnRes.result as bigint;\n const depositAmount = BigInt(deposit.amount);\n\n if (payerBalance < depositAmount) {\n return {\n ok: false,\n response: { isValid: false, invalidReason: Errors.ErrInsufficientBalance, payer },\n };\n }\n\n const effectiveBalance = chBalance + depositAmount;\n const maxClaimableAmount = BigInt(voucher.maxClaimableAmount);\n\n if (maxClaimableAmount > effectiveBalance) {\n return {\n ok: false,\n response: { isValid: false, invalidReason: Errors.ErrCumulativeExceedsBalance, payer },\n };\n }\n\n if (maxClaimableAmount <= chTotalClaimed) {\n return {\n ok: false,\n response: { isValid: false, invalidReason: Errors.ErrCumulativeAmountBelowClaimed, payer },\n };\n }\n\n return {\n ok: true,\n chainId,\n depositAmount,\n payer,\n chBalance,\n chTotalClaimed,\n wdInitiatedAt,\n refundNonceVal,\n };\n}\n\n/**\n * Executes a deposit onchain through the collector for the selected transfer method.\n *\n * The deposit is first verified via {@link verifyDeposit}; if invalid the returned\n * {@link SettleResponse} will have `success: false` with the verification reason.\n *\n * @param signer - Facilitator signer used to submit the onchain transaction.\n * @param payment - Full payment envelope containing optional extensions.\n * @param payload - The deposit payload (channelConfig, amount, authorization, voucher).\n * @param requirements - Server payment requirements.\n * @param context - Optional facilitator extension context.\n * @returns A {@link SettleResponse} with the transaction hash and updated channel state in `extra`.\n */\nexport async function settleDeposit(\n signer: FacilitatorEvmSigner,\n payment: PaymentPayload,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n): Promise<SettleResponse> {\n const { deposit, voucher } = payload;\n const config = payload.channelConfig;\n const payer = config.payer;\n\n const verified = await verifyDeposit(signer, payment, payload, requirements, context);\n if (!verified.isValid) {\n const reason = verified.invalidReason ?? Errors.ErrInvalidPayloadType;\n return {\n success: false,\n errorReason: reason,\n errorMessage: verified.invalidMessage ?? reason,\n transaction: \"\",\n network: requirements.network,\n payer: verified.payer,\n };\n }\n\n try {\n const execution = await resolveDepositExecution(\n signer,\n payment,\n payload,\n requirements,\n context,\n );\n if (\"isValid\" in execution) {\n const reason = execution.invalidReason ?? Errors.ErrInvalidPayloadType;\n return {\n success: false,\n errorReason: reason,\n errorMessage: execution.invalidMessage ?? reason,\n transaction: \"\",\n network: requirements.network,\n payer: execution.payer,\n };\n }\n\n const depositTx = buildDepositTransaction(payload, execution.collectorData);\n const tx =\n execution.kind === \"erc20Approval\"\n ? (\n await execution.extensionSigner.sendTransactions([\n execution.signedTransaction,\n depositTx,\n ])\n )[1]\n : await signer.writeContract({\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"deposit\",\n args: [\n toContractChannelConfig(config),\n BigInt(deposit.amount),\n execution.collector,\n execution.collectorData,\n ],\n });\n\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrDepositTransactionFailed,\n errorMessage: `transaction reverted (receipt status ${receipt.status})`,\n transaction: tx,\n network: requirements.network,\n payer,\n };\n }\n\n const optimisticExtra = {\n channelState: {\n channelId: voucher.channelId,\n balance: (\n BigInt(String(verified.extra?.balance ?? \"0\")) + BigInt(deposit.amount)\n ).toString(),\n totalClaimed: String(verified.extra?.totalClaimed ?? \"0\"),\n withdrawRequestedAt: Number(verified.extra?.withdrawRequestedAt ?? 0),\n refundNonce: String(verified.extra?.refundNonce ?? \"0\"),\n },\n };\n\n // Poll the RPC until it reflects the just-confirmed deposit, so subsequent verify reads are guaranteed to see this balance\n const expectedMinBalance = BigInt(optimisticExtra.channelState.balance);\n const rpcDeadline = Date.now() + 2_000;\n let postState = await readChannelState(signer, voucher.channelId);\n while (postState.balance < expectedMinBalance && Date.now() < rpcDeadline) {\n await new Promise(resolve => setTimeout(resolve, 150));\n postState = await readChannelState(signer, voucher.channelId);\n }\n\n const rpcCaughtUp = postState.balance >= expectedMinBalance;\n\n return {\n success: true,\n transaction: tx,\n network: requirements.network,\n payer,\n amount: deposit.amount,\n extra: rpcCaughtUp\n ? {\n ...optimisticExtra,\n channelState: {\n channelId: voucher.channelId,\n balance: postState.balance.toString(),\n totalClaimed: postState.totalClaimed.toString(),\n withdrawRequestedAt: postState.withdrawRequestedAt,\n refundNonce: postState.refundNonce.toString(),\n },\n }\n : optimisticExtra,\n };\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrDepositTransactionFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network: requirements.network,\n payer,\n };\n }\n}\n\ntype DepositExecution =\n | {\n kind: \"direct\";\n collector: `0x${string}`;\n collectorData: `0x${string}`;\n skipDirectSimulation?: false;\n }\n | {\n kind: \"erc20Approval\";\n collector: `0x${string}`;\n collectorData: `0x${string}`;\n signedTransaction: `0x${string}`;\n extensionSigner: {\n sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>;\n };\n skipDirectSimulation: true;\n };\n\n/**\n * Resolves the collector address and collector data for a deposit payload.\n *\n * @param signer - Facilitator signer for Permit2 allowance reads.\n * @param payment - Full payment envelope containing optional extensions.\n * @param payload - Batch deposit payload.\n * @param requirements - Payment requirements for the request.\n * @param context - Optional facilitator extension context.\n * @returns Execution details, or a verification failure response.\n */\nasync function resolveDepositExecution(\n signer: FacilitatorEvmSigner,\n payment: PaymentPayload,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n): Promise<DepositExecution | VerifyResponse> {\n const transferMethod = resolveDepositTransferMethod(payload, requirements);\n if (transferMethod === \"eip3009\") {\n return {\n kind: \"direct\",\n collector: getEip3009DepositCollectorAddress(),\n collectorData: buildEip3009DepositCollectorData(payload),\n };\n }\n\n const branch = await resolvePermit2DepositBranch(signer, payment, payload, requirements, context);\n if (\"isValid\" in branch) {\n return branch;\n }\n\n if (branch.kind === \"erc20Approval\") {\n return {\n kind: \"erc20Approval\",\n collector: getPermit2DepositCollectorAddress(),\n collectorData: branch.collectorData,\n signedTransaction: branch.signedTransaction,\n extensionSigner: branch.extensionSigner,\n skipDirectSimulation: true,\n };\n }\n\n return {\n kind: \"direct\",\n collector: getPermit2DepositCollectorAddress(),\n collectorData: branch.collectorData,\n };\n}\n\n/**\n * Selects the transfer method from requirements, falling back to payload shape.\n *\n * @param payload - Batch deposit payload.\n * @param requirements - Payment requirements for the request.\n * @returns Selected batch-settlement transfer method.\n */\nfunction resolveDepositTransferMethod(\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n): BatchSettlementAssetTransferMethod {\n const hinted = (\n requirements.extra as { assetTransferMethod?: BatchSettlementAssetTransferMethod }\n )?.assetTransferMethod;\n if (hinted) {\n return hinted;\n }\n return payload.deposit.authorization.permit2Authorization ? \"permit2\" : \"eip3009\";\n}\n","export const channelConfigComponents = [\n { name: \"payer\", type: \"address\" },\n { name: \"payerAuthorizer\", type: \"address\" },\n { name: \"receiver\", type: \"address\" },\n { name: \"receiverAuthorizer\", type: \"address\" },\n { name: \"token\", type: \"address\" },\n { name: \"withdrawDelay\", type: \"uint40\" },\n { name: \"salt\", type: \"bytes32\" },\n] as const;\n\nconst voucherClaimComponents = [\n {\n name: \"voucher\",\n type: \"tuple\",\n components: [\n {\n name: \"channel\",\n type: \"tuple\",\n components: channelConfigComponents,\n },\n { name: \"maxClaimableAmount\", type: \"uint128\" },\n ],\n },\n { name: \"signature\", type: \"bytes\" },\n { name: \"totalClaimed\", type: \"uint128\" },\n] as const;\n\nexport const batchSettlementABI = [\n {\n type: \"function\",\n name: \"multicall\",\n inputs: [{ name: \"data\", type: \"bytes[]\" }],\n outputs: [{ name: \"results\", type: \"bytes[]\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"deposit\",\n inputs: [\n { name: \"config\", type: \"tuple\", components: channelConfigComponents },\n { name: \"amount\", type: \"uint128\" },\n { name: \"collector\", type: \"address\" },\n { name: \"collectorData\", type: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"claim\",\n inputs: [{ name: \"voucherClaims\", type: \"tuple[]\", components: voucherClaimComponents }],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"claimWithSignature\",\n inputs: [\n { name: \"voucherClaims\", type: \"tuple[]\", components: voucherClaimComponents },\n { name: \"authorizerSignature\", type: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n { name: \"receiver\", type: \"address\" },\n { name: \"token\", type: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"initiateWithdraw\",\n inputs: [\n { name: \"config\", type: \"tuple\", components: channelConfigComponents },\n { name: \"amount\", type: \"uint128\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"finalizeWithdraw\",\n inputs: [{ name: \"config\", type: \"tuple\", components: channelConfigComponents }],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"refund\",\n inputs: [\n { name: \"config\", type: \"tuple\", components: channelConfigComponents },\n { name: \"amount\", type: \"uint128\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"refundWithSignature\",\n inputs: [\n { name: \"config\", type: \"tuple\", components: channelConfigComponents },\n { name: \"amount\", type: \"uint128\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"receiverAuthorizerSignature\", type: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"getChannelId\",\n inputs: [{ name: \"config\", type: \"tuple\", components: channelConfigComponents }],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"CHANNEL_CONFIG_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"channels\",\n inputs: [{ name: \"channelId\", type: \"bytes32\" }],\n outputs: [\n { name: \"balance\", type: \"uint128\" },\n { name: \"totalClaimed\", type: \"uint128\" },\n ],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"pendingWithdrawals\",\n inputs: [{ name: \"channelId\", type: \"bytes32\" }],\n outputs: [\n { name: \"amount\", type: \"uint128\" },\n { name: \"initiatedAt\", type: \"uint40\" },\n ],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"receivers\",\n inputs: [\n { name: \"receiver\", type: \"address\" },\n { name: \"token\", type: \"address\" },\n ],\n outputs: [\n { name: \"totalClaimed\", type: \"uint128\" },\n { name: \"totalSettled\", type: \"uint128\" },\n ],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"getVoucherDigest\",\n inputs: [\n { name: \"channelId\", type: \"bytes32\" },\n { name: \"maxClaimableAmount\", type: \"uint128\" },\n ],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"getRefundDigest\",\n inputs: [\n { name: \"channelId\", type: \"bytes32\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"amount\", type: \"uint128\" },\n ],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"refundNonce\",\n inputs: [{ name: \"channelId\", type: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"getClaimBatchDigest\",\n inputs: [{ name: \"voucherClaims\", type: \"tuple[]\", components: voucherClaimComponents }],\n outputs: [{ name: \"\", type: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"event\",\n name: \"Settled\",\n inputs: [\n { name: \"receiver\", type: \"address\", indexed: true },\n { name: \"token\", type: \"address\", indexed: true },\n { name: \"sender\", type: \"address\", indexed: true },\n { name: \"amount\", type: \"uint128\", indexed: false },\n ],\n anonymous: false,\n },\n] as const;\n\nexport const erc20BalanceOfABI = [\n {\n type: \"function\",\n name: \"balanceOf\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n },\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 { 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","/** Error codes for the batch-settlement EVM scheme (see scheme_batch_settlement_evm2.md). */\n\nexport const ErrChannelNotFound = \"invalid_batch_settlement_evm_channel_not_found\";\nexport const ErrTokenMismatch = \"invalid_batch_settlement_evm_token_mismatch\";\nexport const ErrInvalidVoucherSignature = \"invalid_batch_settlement_evm_voucher_signature\";\nexport const ErrCumulativeExceedsBalance =\n \"invalid_batch_settlement_evm_cumulative_exceeds_balance\";\nexport const ErrCumulativeAmountBelowClaimed =\n \"invalid_batch_settlement_evm_cumulative_below_claimed\";\nexport const ErrInsufficientBalance = \"invalid_batch_settlement_evm_insufficient_balance\";\nexport const ErrDepositTransactionFailed =\n \"invalid_batch_settlement_evm_deposit_transaction_failed\";\nexport const ErrClaimTransactionFailed = \"invalid_batch_settlement_evm_claim_transaction_failed\";\nexport const ErrSettleTransactionFailed = \"invalid_batch_settlement_evm_settle_transaction_failed\";\nexport const ErrInvalidScheme = \"invalid_batch_settlement_evm_scheme\";\nexport const ErrNetworkMismatch = \"invalid_batch_settlement_evm_network_mismatch\";\nexport const ErrMissingEip712Domain = \"invalid_batch_settlement_evm_missing_eip712_domain\";\nexport const ErrValidBeforeExpired =\n \"invalid_batch_settlement_evm_payload_authorization_valid_before\";\nexport const ErrValidAfterInFuture =\n \"invalid_batch_settlement_evm_payload_authorization_valid_after\";\nexport const ErrInvalidReceiveAuthorizationSignature =\n \"invalid_batch_settlement_evm_receive_authorization_signature\";\nexport const ErrErc3009AuthorizationRequired =\n \"invalid_batch_settlement_evm_erc3009_authorization_required\";\nexport const ErrRefundTransactionFailed = \"invalid_batch_settlement_evm_refund_transaction_failed\";\nexport const ErrInvalidPayloadType = \"invalid_batch_settlement_evm_payload_type\";\nexport const ErrWithdrawDelayOutOfRange =\n \"invalid_batch_settlement_evm_withdraw_delay_out_of_range\";\nexport const ErrChannelIdMismatch = \"invalid_batch_settlement_evm_channel_id_mismatch\";\nexport const ErrReceiverMismatch = \"invalid_batch_settlement_evm_receiver_mismatch\";\nexport const ErrReceiverAuthorizerMismatch =\n \"invalid_batch_settlement_evm_receiver_authorizer_mismatch\";\nexport const ErrWithdrawDelayMismatch = \"invalid_batch_settlement_evm_withdraw_delay_mismatch\";\nexport const ErrAuthorizerAddressMismatch =\n \"invalid_batch_settlement_evm_authorizer_address_mismatch\";\nexport const ErrDepositSimulationFailed = \"invalid_batch_settlement_evm_deposit_simulation_failed\";\nexport const ErrClaimSimulationFailed = \"invalid_batch_settlement_evm_claim_simulation_failed\";\nexport const ErrSettleSimulationFailed = \"invalid_batch_settlement_evm_settle_simulation_failed\";\nexport const ErrNothingToSettle = \"invalid_batch_settlement_evm_nothing_to_settle\";\nexport const ErrRefundPayload = \"invalid_batch_settlement_evm_refund_payload\";\nexport const ErrRefundSimulationFailed = \"invalid_batch_settlement_evm_refund_simulation_failed\";\nexport const ErrRpcReadFailed = \"invalid_batch_settlement_evm_rpc_read_failed\";\nexport const ErrPermit2AuthorizationRequired =\n \"invalid_batch_settlement_evm_permit2_authorization_required\";\nexport const ErrPermit2InvalidSpender = \"invalid_batch_settlement_evm_permit2_invalid_spender\";\nexport const ErrPermit2AmountMismatch = \"invalid_batch_settlement_evm_permit2_amount_mismatch\";\nexport const ErrPermit2DeadlineExpired = \"invalid_batch_settlement_evm_permit2_deadline_expired\";\nexport const ErrPermit2InvalidSignature = \"invalid_batch_settlement_evm_permit2_invalid_signature\";\nexport const ErrPermit2AllowanceRequired =\n \"invalid_batch_settlement_evm_permit2_allowance_required\";\nexport const ErrEip2612AmountMismatch = \"invalid_batch_settlement_evm_eip2612_amount_mismatch\";\nexport const ErrEip2612OwnerMismatch = \"invalid_batch_settlement_evm_eip2612_owner_mismatch\";\nexport const ErrEip2612AssetMismatch = \"invalid_batch_settlement_evm_eip2612_asset_mismatch\";\nexport const ErrEip2612SpenderMismatch = \"invalid_batch_settlement_evm_eip2612_spender_mismatch\";\nexport const ErrEip2612DeadlineExpired = \"invalid_batch_settlement_evm_eip2612_deadline_expired\";\nexport const ErrErc20ApprovalUnavailable =\n \"invalid_batch_settlement_evm_erc20_approval_unavailable\";\n\n/** Resource server: 402 `error` and lifecycle `reason` (same strings as the spec). */\nexport const ErrCumulativeAmountMismatch =\n \"invalid_batch_settlement_evm_cumulative_amount_mismatch\";\nexport const ErrChannelBusy = \"invalid_batch_settlement_evm_channel_busy\";\nexport const ErrChargeExceedsSignedCumulative =\n \"invalid_batch_settlement_evm_charge_exceeds_signed_cumulative\";\nexport const ErrMissingChannel = \"invalid_batch_settlement_evm_missing_channel\";\nexport const ErrRefundNoBalance = \"invalid_batch_settlement_evm_refund_no_balance\";\nexport const ErrRefundAmountInvalid = \"invalid_batch_settlement_evm_refund_amount_invalid\";\n","import { getAddress, verifyTypedData as viemVerifyTypedData } from \"viem\";\nimport type { PaymentRequirements } from \"@payai/x402/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { multicall } from \"../../multicall\";\nimport {\n BATCH_SETTLEMENT_ADDRESS,\n MIN_WITHDRAW_DELAY,\n MAX_WITHDRAW_DELAY,\n voucherTypes,\n} from \"../constants\";\nimport { batchSettlementABI } from \"../abi\";\nimport type {\n BatchSettlementPaymentRequirementsExtra,\n ChannelConfig,\n ChannelState,\n} from \"../types\";\nimport { computeChannelId, getBatchSettlementEip712Domain } from \"../utils\";\nimport * as Errors from \"../errors\";\n\n/**\n * Normalises a {@link ChannelConfig} into the checksummed-address tuple expected by the\n * batch-settlement contract's `deposit` / `refundWithSignature` / `claimWithSignature` calls.\n *\n * @param config - In-memory channel configuration.\n * @returns Channel config tuple with all address fields checksummed via `getAddress`.\n */\nexport function toContractChannelConfig(config: ChannelConfig) {\n return {\n payer: getAddress(config.payer),\n payerAuthorizer: getAddress(config.payerAuthorizer),\n receiver: getAddress(config.receiver),\n receiverAuthorizer: getAddress(config.receiverAuthorizer),\n token: getAddress(config.token),\n withdrawDelay: config.withdrawDelay,\n salt: config.salt,\n };\n}\n\n/**\n * Case-insensitive comparison of two channel id hex strings.\n *\n * @param a - First channel id.\n * @param b - Second channel id (may be any unknown value).\n * @returns `true` when both ids refer to the same channel.\n */\nexport function channelIdsEqual(a: `0x${string}`, b: unknown): boolean {\n if (typeof b !== \"string\" || b.length === 0) return false;\n const norm = (x: string) => {\n let s = x.toLowerCase();\n if (s.startsWith(\"0x\")) s = s.slice(2);\n return `0x${s}`;\n };\n return norm(a) === norm(b);\n}\n\n/**\n * Validates the time window of an ERC-3009 `ReceiveWithAuthorization`.\n *\n * @param validAfter - Earliest unix timestamp the authorization is valid (in seconds).\n * @param validBefore - Latest unix timestamp before which the authorization is valid.\n * @returns An error code string if the time window is invalid, otherwise `undefined`.\n */\nexport function erc3009AuthorizationTimeInvalidReason(\n validAfter: bigint,\n validBefore: bigint,\n): string | undefined {\n const now = Math.floor(Date.now() / 1000);\n if (validBefore < BigInt(now + 6)) return Errors.ErrValidBeforeExpired;\n if (validAfter > BigInt(now)) return Errors.ErrValidAfterInFuture;\n return undefined;\n}\n\n/**\n * Dual-path voucher signature verification.\n *\n * When `payerAuthorizer` is a non-zero address, the signature is verified off-chain via\n * ECDSA recovery against that address (no RPC call). When `payerAuthorizer` is `address(0)`,\n * verification falls back to an ERC-1271 `isValidSignature` call against the payer contract\n * (smart-wallet path).\n *\n * @param signer - Facilitator signer providing `verifyTypedData` (may issue RPC for ERC-1271).\n * @param params - Voucher fields and authorizer addresses needed for verification.\n * @param params.channelId - EIP-712 voucher channel id (`bytes32` hex).\n * @param params.maxClaimableAmount - Max cumulative claimable amount as a decimal string.\n * @param params.payerAuthorizer - Address that signed the voucher; zero address selects ERC-1271 verification.\n * @param params.payer - Payer contract address (used for ERC-1271).\n * @param params.signature - EIP-712 signature bytes over the voucher.\n * @param chainId - Numeric EVM chain id for the EIP-712 domain.\n * @returns `true` when the voucher signature is valid.\n */\nexport async function verifyBatchSettlementVoucherTypedData(\n signer: FacilitatorEvmSigner,\n params: {\n channelId: `0x${string}`;\n maxClaimableAmount: string;\n payerAuthorizer: `0x${string}`;\n payer: `0x${string}`;\n signature: `0x${string}`;\n },\n chainId: number,\n): Promise<boolean> {\n const domain = getBatchSettlementEip712Domain(chainId);\n const message = {\n channelId: params.channelId,\n maxClaimableAmount: BigInt(params.maxClaimableAmount),\n };\n\n const zeroAddress = \"0x0000000000000000000000000000000000000000\";\n\n if (params.payerAuthorizer !== zeroAddress) {\n return viemVerifyTypedData({\n address: getAddress(params.payerAuthorizer),\n domain,\n types: voucherTypes,\n primaryType: \"Voucher\",\n message,\n signature: params.signature,\n });\n }\n\n return signer.verifyTypedData({\n address: getAddress(params.payer),\n domain,\n types: voucherTypes,\n primaryType: \"Voucher\",\n message,\n signature: params.signature,\n });\n}\n\n/**\n * Validates that a {@link ChannelConfig} is consistent with the claimed `channelId` and\n * the server's {@link PaymentRequirements}.\n *\n * @param config - The channel configuration from the payload.\n * @param channelId - The `channelId` claimed in the payload.\n * @param requirements - Server payment requirements to cross-check against.\n * @returns An error code string if validation fails, otherwise `undefined`.\n */\nexport function validateChannelConfig(\n config: ChannelConfig,\n channelId: `0x${string}`,\n requirements: PaymentRequirements,\n): string | undefined {\n const computedId = computeChannelId(config, requirements.network);\n if (computedId.toLowerCase() !== channelId.toLowerCase()) {\n return Errors.ErrChannelIdMismatch;\n }\n\n if (getAddress(config.receiver) !== getAddress(requirements.payTo)) {\n return Errors.ErrReceiverMismatch;\n }\n\n const extra = requirements.extra as Partial<BatchSettlementPaymentRequirementsExtra> | undefined;\n const requiredReceiverAuthorizer = extra?.receiverAuthorizer;\n\n if (\n !requiredReceiverAuthorizer ||\n getAddress(requiredReceiverAuthorizer) === \"0x0000000000000000000000000000000000000000\" ||\n getAddress(config.receiverAuthorizer) !== getAddress(requiredReceiverAuthorizer)\n ) {\n return Errors.ErrReceiverAuthorizerMismatch;\n }\n\n if (getAddress(config.token) !== getAddress(requirements.asset)) {\n return Errors.ErrTokenMismatch;\n }\n\n if (extra?.withdrawDelay !== undefined && config.withdrawDelay !== Number(extra.withdrawDelay)) {\n return Errors.ErrWithdrawDelayMismatch;\n }\n\n if (config.withdrawDelay < MIN_WITHDRAW_DELAY || config.withdrawDelay > MAX_WITHDRAW_DELAY) {\n return Errors.ErrWithdrawDelayOutOfRange;\n }\n\n return undefined;\n}\n\n/**\n * Reads onchain channel state via a 3-call multicall:\n * `channels(channelId)`, `pendingWithdrawals(channelId)`, `refundNonce(channelId)`.\n *\n * Throws when any sub-call fails so callers can distinguish RPC failures\n * from missing channels (which return zero balance/totalClaimed/refundNonce).\n *\n * @param signer - Facilitator signer for onchain reads.\n * @param channelId - The `bytes32` channel id.\n * @returns Fresh {@link ChannelState}.\n */\nexport async function readChannelState(\n signer: FacilitatorEvmSigner,\n channelId: `0x${string}`,\n): Promise<ChannelState> {\n const target = getAddress(BATCH_SETTLEMENT_ADDRESS);\n const mcResults = await multicall(signer.readContract.bind(signer), [\n { address: target, abi: batchSettlementABI, functionName: \"channels\", args: [channelId] },\n {\n address: target,\n abi: batchSettlementABI,\n functionName: \"pendingWithdrawals\",\n args: [channelId],\n },\n { address: target, abi: batchSettlementABI, functionName: \"refundNonce\", args: [channelId] },\n ]);\n\n const [chRes, wdRes, rnRes] = mcResults;\n if (chRes.status === \"failure\" || wdRes.status === \"failure\" || rnRes.status === \"failure\") {\n throw new Error(`${Errors.ErrRpcReadFailed}: multicall returned failure for ${channelId}`);\n }\n\n const [balance, totalClaimed] = chRes.result as [bigint, bigint];\n const [, wdInitiatedAt] = wdRes.result as [bigint, bigint];\n const refundNonce = rnRes.result as bigint;\n\n return { balance, totalClaimed, withdrawRequestedAt: Number(wdInitiatedAt), refundNonce };\n}\n","import { getAddress, hashTypedData } from \"viem\";\nimport { BATCH_SETTLEMENT_ADDRESS, BATCH_SETTLEMENT_DOMAIN, channelConfigTypes } from \"./constants\";\nimport type { ChannelConfig } from \"./types\";\nimport { getEvmChainId } from \"../utils\";\n\n/**\n * Computes the chain-bound channel id from a {@link ChannelConfig} struct.\n *\n * @param config - The immutable channel configuration.\n * @param networkOrChainId - CAIP-2 network identifier or numeric EVM chain id.\n * @returns The `bytes32` channel id as a hex string.\n */\nexport function computeChannelId(\n config: ChannelConfig,\n networkOrChainId: string | number,\n): `0x${string}` {\n const chainId =\n typeof networkOrChainId === \"number\" ? networkOrChainId : getEvmChainId(networkOrChainId);\n return hashTypedData({\n domain: getBatchSettlementEip712Domain(chainId),\n types: channelConfigTypes,\n primaryType: \"ChannelConfig\",\n message: {\n payer: config.payer,\n payerAuthorizer: config.payerAuthorizer,\n receiver: config.receiver,\n receiverAuthorizer: config.receiverAuthorizer,\n token: config.token,\n withdrawDelay: config.withdrawDelay,\n salt: config.salt,\n },\n });\n}\n\n/**\n * Returns the full EIP-712 domain for the batch-settlement contract on the given chain.\n *\n * @param chainId - Numeric EVM chain id.\n * @returns EIP-712 domain with `name`, `version`, `chainId`, and checksummed `verifyingContract`.\n */\nexport function getBatchSettlementEip712Domain(chainId: number) {\n return {\n ...BATCH_SETTLEMENT_DOMAIN,\n chainId,\n verifyingContract: getAddress(BATCH_SETTLEMENT_ADDRESS),\n } as const;\n}\n","import { PaymentRequirements, VerifyResponse } from \"@payai/x402/types\";\nimport { getAddress, parseErc6492Signature } from \"viem\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { BatchSettlementDepositPayload } from \"../types\";\nimport { ERC3009_DEPOSIT_COLLECTOR_ADDRESS, receiveAuthorizationTypes } from \"../constants\";\nimport { buildErc3009CollectorData, buildErc3009DepositNonce } from \"../encoding\";\nimport * as Errors from \"../errors\";\nimport { erc3009AuthorizationTimeInvalidReason } from \"./utils\";\n\n/**\n * Returns the collector contract used for EIP-3009 deposits.\n *\n * @returns ERC-3009 deposit collector address.\n */\nexport function getEip3009DepositCollectorAddress(): `0x${string}` {\n return getAddress(ERC3009_DEPOSIT_COLLECTOR_ADDRESS);\n}\n\n/**\n * Encodes collector data for an EIP-3009 deposit payload.\n *\n * @param payload - Deposit payload containing the ERC-3009 authorization.\n * @returns ABI-encoded collector data.\n */\nexport function buildEip3009DepositCollectorData(\n payload: BatchSettlementDepositPayload,\n): `0x${string}` {\n const auth = payload.deposit.authorization.erc3009Authorization;\n if (!auth) {\n throw new Error(Errors.ErrErc3009AuthorizationRequired);\n }\n\n const { signature } = parseErc6492Signature(auth.signature);\n return buildErc3009CollectorData(auth.validAfter, auth.validBefore, auth.salt, signature);\n}\n\n/**\n * Verifies the ERC-3009 authorization fields and typed-data signature.\n *\n * @param signer - Facilitator signer for typed-data verification.\n * @param payload - Deposit payload to verify.\n * @param requirements - Payment requirements containing token domain metadata.\n * @param chainId - EVM chain id.\n * @returns A failure response, or `null` when valid.\n */\nexport async function verifyEip3009DepositAuthorization(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n chainId: number,\n): Promise<VerifyResponse | null> {\n const { deposit, voucher } = payload;\n const payer = payload.channelConfig.payer;\n const auth = deposit.authorization.erc3009Authorization;\n\n if (!auth) {\n return { isValid: false, invalidReason: Errors.ErrErc3009AuthorizationRequired, payer };\n }\n\n const extra = requirements.extra as { name?: string; version?: string } | undefined;\n if (!extra?.name || !extra?.version) {\n return { isValid: false, invalidReason: Errors.ErrMissingEip712Domain, payer };\n }\n\n const validAfter = BigInt(auth.validAfter);\n const validBefore = BigInt(auth.validBefore);\n const timeInvalid = erc3009AuthorizationTimeInvalidReason(validAfter, validBefore);\n if (timeInvalid) {\n return { isValid: false, invalidReason: timeInvalid, payer };\n }\n\n const erc3009Nonce = buildErc3009DepositNonce(voucher.channelId, auth.salt);\n const receiveAuthOk = await verifyReceiveAuth(signer, {\n payer,\n asset: requirements.asset,\n name: extra.name,\n version: extra.version,\n chainId,\n amount: deposit.amount,\n validAfter,\n validBefore,\n nonce: erc3009Nonce,\n signature: auth.signature,\n });\n\n if (!receiveAuthOk) {\n return { isValid: false, invalidReason: Errors.ErrInvalidReceiveAuthorizationSignature, payer };\n }\n\n return null;\n}\n\n/**\n * Verifies a `ReceiveWithAuthorization` signature.\n *\n * @param signer - Facilitator signer used for typed-data verification.\n * @param params - Authorization fields and signature.\n * @param params.payer - Expected authorization signer.\n * @param params.asset - ERC-20 verifying contract.\n * @param params.name - ERC-20 EIP-712 domain name.\n * @param params.version - ERC-20 EIP-712 domain version.\n * @param params.chainId - EVM chain id.\n * @param params.amount - Authorized token amount.\n * @param params.validAfter - Earliest valid timestamp.\n * @param params.validBefore - Expiration timestamp.\n * @param params.nonce - ERC-3009 nonce.\n * @param params.signature - Receive authorization signature.\n * @returns True when the signature matches the expected payer.\n */\nasync function verifyReceiveAuth(\n signer: FacilitatorEvmSigner,\n params: {\n payer: `0x${string}`;\n asset: string;\n name: string;\n version: string;\n chainId: number;\n amount: string;\n validAfter: bigint;\n validBefore: bigint;\n nonce: `0x${string}`;\n signature: `0x${string}`;\n },\n): Promise<boolean> {\n try {\n return await signer.verifyTypedData({\n address: getAddress(params.payer),\n domain: {\n name: params.name,\n version: params.version,\n chainId: params.chainId,\n verifyingContract: getAddress(params.asset),\n },\n types: receiveAuthorizationTypes,\n primaryType: \"ReceiveWithAuthorization\",\n message: {\n from: getAddress(params.payer),\n to: getAddress(ERC3009_DEPOSIT_COLLECTOR_ADDRESS),\n value: BigInt(params.amount),\n validAfter: params.validAfter,\n validBefore: params.validBefore,\n nonce: params.nonce,\n },\n signature: params.signature,\n });\n } catch {\n return false;\n }\n}\n","/**\n * @file Encoding helpers for batch-settlement deposit collectors.\n */\nimport { encodeAbiParameters, keccak256 } from \"viem\";\n\n/**\n * Computes the ERC-3009 nonce used by the deposit collector:\n * `keccak256(abi.encode(channelId, salt))`.\n *\n * @param channelId - The `bytes32` channel id binding the authorization to a channel.\n * @param salt - Random salt provided by the client to make the nonce unique per deposit.\n * @returns The `bytes32` ERC-3009 nonce.\n */\nexport function buildErc3009DepositNonce(\n channelId: `0x${string}`,\n salt: `0x${string}`,\n): `0x${string}` {\n return keccak256(\n encodeAbiParameters([{ type: \"bytes32\" }, { type: \"uint256\" }], [channelId, BigInt(salt)]),\n );\n}\n\n/**\n * Encodes the `collectorData` payload for `ERC3009DepositCollector.collect()`:\n * `abi.encode(validAfter, validBefore, salt, signature)`.\n *\n * @param validAfter - Earliest unix timestamp the authorization is valid (decimal string).\n * @param validBefore - Latest unix timestamp the authorization is valid (decimal string).\n * @param salt - Random salt provided by the client (hex string).\n * @param signature - ERC-3009 `ReceiveWithAuthorization` signature.\n * @returns ABI-encoded collector data passed to `deposit(..., collector, collectorData)`.\n */\nexport function buildErc3009CollectorData(\n validAfter: string,\n validBefore: string,\n salt: `0x${string}`,\n signature: `0x${string}`,\n): `0x${string}` {\n return encodeAbiParameters(\n [{ type: \"uint256\" }, { type: \"uint256\" }, { type: \"uint256\" }, { type: \"bytes\" }],\n [BigInt(validAfter), BigInt(validBefore), BigInt(salt), signature],\n );\n}\n\n/**\n * Encodes optional EIP-2612 permit data consumed by `Permit2DepositCollector`.\n *\n * @param params - Permit amount, deadline, and split signature fields.\n * @param params.value - Approved Permit2 allowance value.\n * @param params.deadline - EIP-2612 permit deadline.\n * @param params.v - Signature recovery id.\n * @param params.r - Signature `r` value.\n * @param params.s - Signature `s` value.\n * @returns ABI-encoded permit segment.\n */\nexport function buildEip2612PermitData(params: {\n value: string;\n deadline: string;\n v: number;\n r: `0x${string}`;\n s: `0x${string}`;\n}): `0x${string}` {\n return encodeAbiParameters(\n [\n { type: \"uint256\" },\n { type: \"uint256\" },\n { type: \"uint8\" },\n { type: \"bytes32\" },\n { type: \"bytes32\" },\n ],\n [BigInt(params.value), BigInt(params.deadline), params.v, params.r, params.s],\n );\n}\n\n/**\n * Encodes the `collectorData` payload for `Permit2DepositCollector.collect()`.\n *\n * @param nonce - Permit2 transfer nonce.\n * @param deadline - Permit2 transfer deadline.\n * @param permit2Signature - Signature over the channel-bound Permit2 authorization.\n * @param eip2612PermitData - Optional encoded EIP-2612 permit segment.\n * @returns ABI-encoded collector data passed to `deposit`.\n */\nexport function buildPermit2CollectorData(\n nonce: string,\n deadline: string,\n permit2Signature: `0x${string}`,\n eip2612PermitData: `0x${string}` = \"0x\",\n): `0x${string}` {\n return encodeAbiParameters(\n [{ type: \"uint256\" }, { type: \"uint256\" }, { type: \"bytes\" }, { type: \"bytes\" }],\n [BigInt(nonce), BigInt(deadline), permit2Signature, eip2612PermitData],\n );\n}\n","import {\n FacilitatorContext,\n PaymentPayload,\n PaymentRequirements,\n VerifyResponse,\n} from \"@payai/x402/types\";\nimport { encodeFunctionData, getAddress, parseErc6492Signature } from \"viem\";\nimport {\n extractEip2612GasSponsoringInfo,\n extractErc20ApprovalGasSponsoringInfo,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n resolveErc20ApprovalExtensionSigner,\n type Eip2612GasSponsoringInfo,\n type Erc20ApprovalGasSponsoringFacilitatorExtension,\n type Erc20ApprovalGasSponsoringSigner,\n} from \"../../exact/extensions\";\nimport { validateErc20ApprovalForPayment } from \"../../shared/erc20approval\";\nimport { validateEip2612PermitForPayment, splitEip2612Signature } from \"../../shared/permit2\";\nimport { PERMIT2_ADDRESS, erc20AllowanceAbi } from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { batchSettlementABI } from \"../abi\";\nimport {\n BATCH_SETTLEMENT_ADDRESS,\n PERMIT2_DEPOSIT_COLLECTOR_ADDRESS,\n batchPermit2WitnessTypes,\n} from \"../constants\";\nimport { buildEip2612PermitData, buildPermit2CollectorData } from \"../encoding\";\nimport { BatchSettlementDepositPayload } from \"../types\";\nimport { toContractChannelConfig } from \"./utils\";\nimport * as Errors from \"../errors\";\n\nexport type Permit2DepositBranch =\n | {\n kind: \"standard\";\n collectorData: `0x${string}`;\n }\n | {\n kind: \"eip2612\";\n collectorData: `0x${string}`;\n }\n | {\n kind: \"erc20Approval\";\n collectorData: `0x${string}`;\n signedTransaction: `0x${string}`;\n extensionSigner: Erc20ApprovalGasSponsoringSigner;\n };\n\n/**\n * Returns the collector contract used for Permit2 deposits.\n *\n * @returns Permit2 deposit collector address.\n */\nexport function getPermit2DepositCollectorAddress(): `0x${string}` {\n return getAddress(PERMIT2_DEPOSIT_COLLECTOR_ADDRESS);\n}\n\n/**\n * Encodes collector data for a Permit2 deposit payload.\n *\n * @param payload - Deposit payload containing the Permit2 authorization.\n * @param eip2612PermitData - Optional encoded EIP-2612 permit segment.\n * @returns ABI-encoded collector data.\n */\nexport function buildPermit2DepositCollectorData(\n payload: BatchSettlementDepositPayload,\n eip2612PermitData: `0x${string}` = \"0x\",\n): `0x${string}` {\n const auth = payload.deposit.authorization.permit2Authorization;\n if (!auth) {\n throw new Error(Errors.ErrPermit2AuthorizationRequired);\n }\n\n const { signature } = parseErc6492Signature(auth.signature);\n return buildPermit2CollectorData(auth.nonce, auth.deadline, signature, eip2612PermitData);\n}\n\n/**\n * Verifies Permit2 authorization fields, setup branch, and approval-bundle simulation.\n *\n * @param signer - Facilitator signer for reads and signature verification.\n * @param payment - Full payment envelope containing optional extensions.\n * @param payload - Batch deposit payload.\n * @param requirements - Payment requirements for the request.\n * @param chainId - EVM chain id.\n * @param context - Optional facilitator extension context.\n * @returns A failure response, or `null` when valid.\n */\nexport async function verifyPermit2DepositAuthorization(\n signer: FacilitatorEvmSigner,\n payment: PaymentPayload,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n chainId: number,\n context?: FacilitatorContext,\n): Promise<VerifyResponse | null> {\n const authResult = await verifyPermit2TypedData(signer, payload, requirements, chainId);\n if (authResult) {\n return authResult;\n }\n\n const branchResult = await resolvePermit2DepositBranch(\n signer,\n payment,\n payload,\n requirements,\n context,\n );\n if (\"isValid\" in branchResult) {\n return branchResult;\n }\n\n if (branchResult.kind !== \"erc20Approval\" || !branchResult.extensionSigner.simulateTransactions) {\n return null;\n }\n\n const ok = await branchResult.extensionSigner.simulateTransactions([\n branchResult.signedTransaction,\n buildDepositTransaction(payload, branchResult.collectorData),\n ]);\n if (!ok) {\n return {\n isValid: false,\n invalidReason: Errors.ErrDepositSimulationFailed,\n payer: payload.channelConfig.payer,\n };\n }\n\n return null;\n}\n\n/**\n * Resolves the Permit2 setup branch and collector data for verification or settlement.\n *\n * @param signer - Facilitator signer for allowance reads.\n * @param payment - Full payment envelope containing optional extensions.\n * @param payload - Batch deposit payload.\n * @param requirements - Payment requirements for the request.\n * @param context - Optional facilitator extension context.\n * @returns Resolved branch, or a verification failure response.\n */\nexport async function resolvePermit2DepositBranch(\n signer: FacilitatorEvmSigner,\n payment: PaymentPayload,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n): Promise<Permit2DepositBranch | VerifyResponse> {\n const payer = payload.channelConfig.payer;\n const tokenAddress = getAddress(requirements.asset);\n const eip2612Info = extractEip2612GasSponsoringInfo(payment);\n if (eip2612Info) {\n const result = validateBatchEip2612Permit(\n eip2612Info,\n payer,\n tokenAddress,\n payload.deposit.amount,\n );\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason, payer };\n }\n\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n return {\n kind: \"eip2612\",\n collectorData: buildPermit2DepositCollectorData(\n payload,\n buildEip2612PermitData({\n value: eip2612Info.amount,\n deadline: eip2612Info.deadline,\n v,\n r,\n s,\n }),\n ),\n };\n }\n\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payment);\n if (erc20Info) {\n const extensionSigner = resolveErc20ApprovalExtensionSigner(\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n ),\n requirements.network,\n );\n if (!extensionSigner) {\n return { isValid: false, invalidReason: Errors.ErrErc20ApprovalUnavailable, payer };\n }\n\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return {\n isValid: false,\n invalidReason: result.invalidReason,\n invalidMessage: result.invalidMessage,\n payer,\n };\n }\n\n return {\n kind: \"erc20Approval\",\n collectorData: buildPermit2DepositCollectorData(payload),\n signedTransaction: erc20Info.signedTransaction,\n extensionSigner,\n };\n }\n\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(payload.deposit.amount)) {\n return { isValid: false, invalidReason: Errors.ErrPermit2AllowanceRequired, payer };\n }\n } catch {\n return { isValid: false, invalidReason: Errors.ErrPermit2AllowanceRequired, payer };\n }\n\n return {\n kind: \"standard\",\n collectorData: buildPermit2DepositCollectorData(payload),\n };\n}\n\n/**\n * Builds the unsigned batch `deposit` transaction used after a sponsored approval.\n *\n * @param payload - Batch deposit payload.\n * @param collectorData - Encoded Permit2 collector data.\n * @returns Transaction request for the extension signer.\n */\nexport function buildDepositTransaction(\n payload: BatchSettlementDepositPayload,\n collectorData: `0x${string}`,\n): { to: `0x${string}`; data: `0x${string}`; gas: bigint } {\n return {\n to: getAddress(BATCH_SETTLEMENT_ADDRESS),\n data: encodeFunctionData({\n abi: batchSettlementABI,\n functionName: \"deposit\",\n args: [\n toContractChannelConfig(payload.channelConfig),\n BigInt(payload.deposit.amount),\n getPermit2DepositCollectorAddress(),\n collectorData,\n ],\n }),\n gas: 300_000n,\n };\n}\n\n/**\n * Verifies the channel-bound Permit2 typed-data authorization.\n *\n * @param signer - Facilitator signer for typed-data verification.\n * @param payload - Batch deposit payload.\n * @param requirements - Payment requirements for token matching.\n * @param chainId - EVM chain id.\n * @returns A failure response, or `null` when valid.\n */\nasync function verifyPermit2TypedData(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementDepositPayload,\n requirements: PaymentRequirements,\n chainId: number,\n): Promise<VerifyResponse | null> {\n const auth = payload.deposit.authorization.permit2Authorization;\n const payer = payload.channelConfig.payer;\n\n if (!auth) {\n return { isValid: false, invalidReason: Errors.ErrPermit2AuthorizationRequired, payer };\n }\n\n if (getAddress(auth.from) !== getAddress(payer)) {\n return { isValid: false, invalidReason: Errors.ErrPermit2InvalidSignature, payer };\n }\n\n if (getAddress(auth.spender) !== getPermit2DepositCollectorAddress()) {\n return { isValid: false, invalidReason: Errors.ErrPermit2InvalidSpender, payer };\n }\n\n if (getAddress(auth.permitted.token) !== getAddress(requirements.asset)) {\n return { isValid: false, invalidReason: Errors.ErrTokenMismatch, payer };\n }\n\n if (BigInt(auth.permitted.amount) !== BigInt(payload.deposit.amount)) {\n return { isValid: false, invalidReason: Errors.ErrPermit2AmountMismatch, payer };\n }\n\n if (auth.witness.channelId !== payload.voucher.channelId) {\n return { isValid: false, invalidReason: Errors.ErrChannelIdMismatch, payer };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(auth.deadline) < BigInt(now + 6)) {\n return { isValid: false, invalidReason: Errors.ErrPermit2DeadlineExpired, payer };\n }\n\n try {\n const ok = await signer.verifyTypedData({\n address: getAddress(auth.from),\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: batchPermit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message: {\n permitted: {\n token: getAddress(auth.permitted.token),\n amount: BigInt(auth.permitted.amount),\n },\n spender: getAddress(auth.spender),\n nonce: BigInt(auth.nonce),\n deadline: BigInt(auth.deadline),\n witness: {\n channelId: auth.witness.channelId,\n },\n },\n signature: auth.signature,\n });\n if (!ok) {\n return { isValid: false, invalidReason: Errors.ErrPermit2InvalidSignature, payer };\n }\n } catch {\n return { isValid: false, invalidReason: Errors.ErrPermit2InvalidSignature, payer };\n }\n\n return null;\n}\n\n/**\n * Applies batch-specific EIP-2612 validation on top of the shared Permit2 checks.\n *\n * @param info - EIP-2612 sponsoring info from the payment envelope.\n * @param payer - Expected token owner.\n * @param tokenAddress - Expected token contract.\n * @param depositAmount - Required approval amount.\n * @returns Validation result.\n */\nfunction validateBatchEip2612Permit(\n info: Eip2612GasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n depositAmount: string,\n): { isValid: true } | { isValid: false; invalidReason: string } {\n const baseline = validateEip2612PermitForPayment(info, payer, tokenAddress);\n if (!baseline.isValid) {\n return {\n isValid: false,\n invalidReason: baseline.invalidReason ?? Errors.ErrInvalidPayloadType,\n };\n }\n\n if (BigInt(info.amount) !== BigInt(depositAmount)) {\n return { isValid: false, invalidReason: Errors.ErrEip2612AmountMismatch };\n }\n\n return { isValid: true };\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 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","// 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","/**\n * Named error reason constants for the exact EVM facilitator.\n *\n * These strings must be character-for-character identical to the Go constants in\n * go/mechanisms/evm/exact/facilitator/errors.go to maintain cross-SDK parity.\n */\n\nexport const ErrInvalidScheme = \"invalid_exact_evm_scheme\";\nexport const ErrNetworkMismatch = \"invalid_exact_evm_network_mismatch\";\nexport const ErrMissingEip712Domain = \"invalid_exact_evm_missing_eip712_domain\";\nexport const ErrRecipientMismatch = \"invalid_exact_evm_recipient_mismatch\";\nexport const ErrInvalidSignature = \"invalid_exact_evm_signature\";\nexport const ErrValidBeforeExpired = \"invalid_exact_evm_payload_authorization_valid_before\";\nexport const ErrValidAfterInFuture = \"invalid_exact_evm_payload_authorization_valid_after\";\nexport const ErrInvalidAuthorizationValue = \"invalid_exact_evm_authorization_value\";\nexport const ErrUndeployedSmartWallet = \"invalid_exact_evm_payload_undeployed_smart_wallet\";\nexport const ErrTransactionFailed = \"invalid_exact_evm_transaction_failed\";\n\n// EIP-3009 verify errors\nexport const ErrEip3009TokenNameMismatch = \"invalid_exact_evm_token_name_mismatch\";\nexport const ErrEip3009TokenVersionMismatch = \"invalid_exact_evm_token_version_mismatch\";\nexport const ErrEip3009NotSupported = \"invalid_exact_evm_eip3009_not_supported\";\nexport const ErrEip3009NonceAlreadyUsed = \"invalid_exact_evm_nonce_already_used\";\nexport const ErrEip3009InsufficientBalance = \"invalid_exact_evm_insufficient_balance\";\nexport const ErrEip3009SimulationFailed = \"invalid_exact_evm_transaction_simulation_failed\";\n\n// Permit2 verify errors\nexport const ErrPermit2InvalidSpender = \"invalid_permit2_spender\";\nexport const ErrPermit2RecipientMismatch = \"invalid_permit2_recipient_mismatch\";\nexport const ErrPermit2DeadlineExpired = \"permit2_deadline_expired\";\nexport const ErrPermit2NotYetValid = \"permit2_not_yet_valid\";\nexport const ErrPermit2AmountMismatch = \"permit2_amount_mismatch\";\nexport const ErrPermit2TokenMismatch = \"permit2_token_mismatch\";\nexport const ErrPermit2InvalidSignature = \"invalid_permit2_signature\";\nexport const ErrPermit2AllowanceRequired = \"permit2_allowance_required\";\nexport const ErrPermit2SimulationFailed = \"permit2_simulation_failed\";\nexport const ErrPermit2InsufficientBalance = \"permit2_insufficient_balance\";\nexport const ErrPermit2ProxyNotDeployed = \"permit2_proxy_not_deployed\";\n\n// Permit2 settle errors (from contract reverts)\nexport const ErrPermit2InvalidAmount = \"permit2_invalid_amount\";\nexport const ErrPermit2InvalidDestination = \"permit2_invalid_destination\";\nexport const ErrPermit2InvalidOwner = \"permit2_invalid_owner\";\nexport const ErrPermit2PaymentTooEarly = \"permit2_payment_too_early\";\nexport const ErrPermit2InvalidNonce = \"permit2_invalid_nonce\";\nexport const ErrPermit2612AmountMismatch = \"permit2_2612_amount_mismatch\";\n\n// ERC-20 approval gas sponsoring verify errors\nexport const ErrErc20ApprovalInvalidFormat = \"invalid_erc20_approval_extension_format\";\nexport const ErrErc20ApprovalFromMismatch = \"erc20_approval_from_mismatch\";\nexport const ErrErc20ApprovalAssetMismatch = \"erc20_approval_asset_mismatch\";\nexport const ErrErc20ApprovalSpenderNotPermit2 = \"erc20_approval_spender_not_permit2\";\nexport const ErrErc20ApprovalTxWrongTarget = \"erc20_approval_tx_wrong_target\";\nexport const ErrErc20ApprovalTxWrongSelector = \"erc20_approval_tx_wrong_selector\";\nexport const ErrErc20ApprovalTxWrongSpender = \"erc20_approval_tx_wrong_spender\";\nexport const ErrErc20ApprovalTxInvalidCalldata = \"erc20_approval_tx_invalid_calldata\";\nexport const ErrErc20ApprovalTxSignerMismatch = \"erc20_approval_tx_signer_mismatch\";\nexport const ErrErc20ApprovalTxInvalidSignature = \"erc20_approval_tx_invalid_signature\";\nexport const ErrErc20ApprovalTxParseFailed = \"erc20_approval_tx_parse_failed\";\nexport const ErrErc20ApprovalTxFailed = \"erc20_approval_tx_failed\";\n\n// EIP-2612 gas sponsoring verify errors\nexport const ErrInvalidEip2612ExtensionFormat = \"invalid_eip2612_extension_format\";\nexport const ErrEip2612FromMismatch = \"eip2612_from_mismatch\";\nexport const ErrEip2612AssetMismatch = \"eip2612_asset_mismatch\";\nexport const ErrEip2612SpenderNotPermit2 = \"eip2612_spender_not_permit2\";\nexport const ErrEip2612DeadlineExpired = \"eip2612_deadline_expired\";\n\n// Shared settle errors\nexport const ErrUnsupportedPayloadType = \"unsupported_payload_type\";\nexport const ErrInvalidTransactionState = \"invalid_transaction_state\";\nexport const ErrFactoryNotAllowed = \"eip6492_factory_not_allowed\";\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, parseErc6492Signature } 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 const { signature } = parseErc6492Signature(permit2Payload.signature);\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 getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n 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 const { signature } = parseErc6492Signature(permit2Payload.signature);\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 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 { PaymentRequirements, VerifyResponse } from \"@payai/x402/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport {\n BatchSettlementRefundPayload,\n BatchSettlementVoucherPayload,\n ChannelConfig,\n} from \"../types\";\nimport { getEvmChainId } from \"../../utils\";\nimport * as Errors from \"../errors\";\nimport {\n validateChannelConfig,\n verifyBatchSettlementVoucherTypedData,\n readChannelState,\n} from \"./utils\";\n\n/**\n * Verifies a cumulative voucher payload against onchain channel state.\n *\n * @param signer - Facilitator signer used for onchain reads and signature verification.\n * @param payload - Voucher or refund payload with signed voucher fields.\n * @param requirements - Server payment requirements (asset, network, amount).\n * @param channelConfig - Reconstructed channel configuration for the payer/receiver pair.\n * @returns A {@link VerifyResponse} indicating validity and returning channel state in `extra`.\n */\nexport async function verifyVoucher(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementVoucherPayload | BatchSettlementRefundPayload,\n requirements: PaymentRequirements,\n channelConfig: ChannelConfig,\n): Promise<VerifyResponse> {\n const { voucher } = payload;\n const channelId = voucher.channelId;\n const chainId = getEvmChainId(requirements.network);\n\n const configErr = validateChannelConfig(channelConfig, channelId, requirements);\n if (configErr) {\n return { isValid: false, invalidReason: configErr, payer: channelConfig.payer };\n }\n\n const voucherOk = await verifyBatchSettlementVoucherTypedData(\n signer,\n {\n channelId,\n maxClaimableAmount: voucher.maxClaimableAmount,\n payerAuthorizer: channelConfig.payerAuthorizer,\n payer: channelConfig.payer,\n signature: voucher.signature,\n },\n chainId,\n );\n if (!voucherOk) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidVoucherSignature,\n payer: channelConfig.payer,\n };\n }\n\n const state = await readChannelState(signer, channelId);\n\n if (state.balance === 0n) {\n return { isValid: false, invalidReason: Errors.ErrChannelNotFound, payer: channelConfig.payer };\n }\n\n const maxClaimableAmount = BigInt(voucher.maxClaimableAmount);\n\n if (maxClaimableAmount > state.balance) {\n return {\n isValid: false,\n invalidReason: Errors.ErrCumulativeExceedsBalance,\n payer: channelConfig.payer,\n };\n }\n\n const belowClaimed =\n payload.type === \"refund\"\n ? maxClaimableAmount < state.totalClaimed\n : maxClaimableAmount <= state.totalClaimed;\n if (belowClaimed) {\n return {\n isValid: false,\n invalidReason: Errors.ErrCumulativeAmountBelowClaimed,\n payer: channelConfig.payer,\n };\n }\n\n return {\n isValid: true,\n payer: channelConfig.payer,\n extra: {\n channelId,\n balance: state.balance.toString(),\n totalClaimed: state.totalClaimed.toString(),\n withdrawRequestedAt: state.withdrawRequestedAt,\n refundNonce: state.refundNonce.toString(),\n },\n };\n}\n","import { SettleResponse, PaymentRequirements } from \"@payai/x402/types\";\nimport { getAddress } from \"viem\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport type { AuthorizerSigner, BatchSettlementClaimPayload } from \"../types\";\nimport { batchSettlementABI } from \"../abi\";\nimport { BATCH_SETTLEMENT_ADDRESS } from \"../constants\";\nimport { signClaimBatch } from \"../authorizerSigner\";\nimport * as Errors from \"../errors\";\nimport { toContractChannelConfig } from \"./utils\";\n\n/**\n * Converts an array of {@link BatchSettlementVoucherClaim} into the onchain tuple format\n * expected by the contract's `claimWithSignature()` function.\n *\n * @param claims - Typed voucher claims with channel config, amounts, and signatures.\n * @returns Contract-ready VoucherClaim argument array.\n */\nexport function buildVoucherClaimArgs(claims: BatchSettlementClaimPayload[\"claims\"]) {\n return claims.map(c => ({\n voucher: {\n channel: toContractChannelConfig(c.voucher.channel),\n maxClaimableAmount: BigInt(c.voucher.maxClaimableAmount),\n },\n signature: c.signature,\n totalClaimed: BigInt(c.totalClaimed),\n }));\n}\n\n/**\n * Submits a batch claim via `claimWithSignature()`.\n *\n * When `claimAuthorizerSignature` is present in the payload it is used directly.\n * When absent the facilitator signs the `ClaimBatch` EIP-712 digest using\n * `authorizerSigner`, after verifying that every claim's `receiverAuthorizer`\n * matches `authorizerSigner.address`.\n *\n * @param signer - Facilitator signer used to submit the claim transaction.\n * @param payload - Claim payload containing voucher claims and optional authorizer signature.\n * @param requirements - Payment requirements for network identification.\n * @param authorizerSigner - Dedicated key for producing `ClaimBatch` EIP-712 signatures.\n * @returns A {@link SettleResponse} with the transaction hash on success.\n */\nexport async function executeClaimWithSignature(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementClaimPayload,\n requirements: PaymentRequirements,\n authorizerSigner: AuthorizerSigner,\n): Promise<SettleResponse> {\n const network = requirements.network;\n const claimArgs = buildVoucherClaimArgs(payload.claims);\n\n let sig = payload.claimAuthorizerSignature;\n\n if (!sig) {\n for (const claim of payload.claims) {\n if (\n getAddress(claim.voucher.channel.receiverAuthorizer) !==\n getAddress(authorizerSigner.address)\n ) {\n return {\n success: false,\n errorReason: Errors.ErrAuthorizerAddressMismatch,\n transaction: \"\",\n network,\n };\n }\n }\n sig = await signClaimBatch(authorizerSigner, payload.claims, network);\n }\n\n try {\n await signer.readContract({\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"claimWithSignature\",\n args: [claimArgs, sig],\n });\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrClaimSimulationFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n\n try {\n const tx = await signer.writeContract({\n address: getAddress(BATCH_SETTLEMENT_ADDRESS),\n abi: batchSettlementABI,\n functionName: \"claimWithSignature\",\n args: [claimArgs, sig],\n });\n\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrClaimTransactionFailed,\n errorMessage: `transaction reverted (receipt status ${receipt.status})`,\n transaction: tx,\n network,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network,\n amount: \"\",\n };\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrClaimTransactionFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n}\n","import type { AuthorizerSigner, BatchSettlementVoucherClaim } from \"./types\";\nimport { claimBatchTypes, refundTypes } from \"./constants\";\nimport { computeChannelId, getBatchSettlementEip712Domain } from \"./utils\";\nimport { getEvmChainId } from \"../utils\";\n\n/**\n * Signs a `ClaimBatch` EIP-712 digest for `claimWithSignature()`.\n *\n * @param signer - Authorizer signer holding the `receiverAuthorizer` key.\n * @param claims - Voucher claims to include in the batch.\n * @param network - CAIP-2 network identifier (e.g. `\"eip155:84532\"`).\n * @returns EIP-712 signature over `ClaimBatch(ClaimEntry[] claims)`.\n */\nexport async function signClaimBatch(\n signer: AuthorizerSigner,\n claims: BatchSettlementVoucherClaim[],\n network: string,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(network);\n\n const claimEntries = claims.map(c => ({\n channelId: computeChannelId(c.voucher.channel, chainId),\n maxClaimableAmount: BigInt(c.voucher.maxClaimableAmount),\n totalClaimed: BigInt(c.totalClaimed),\n }));\n\n return signer.signTypedData({\n domain: getBatchSettlementEip712Domain(chainId),\n types: claimBatchTypes,\n primaryType: \"ClaimBatch\",\n message: {\n claims: claimEntries,\n },\n });\n}\n\n/**\n * Signs a `Refund` EIP-712 digest for `refundWithSignature()`.\n *\n * @param signer - Authorizer signer holding the `receiverAuthorizer` key.\n * @param channelId - Channel to authorize refund for.\n * @param amount - Refund amount (capped to unclaimed escrow onchain).\n * @param nonce - Must match onchain `refundNonce(channelId)`.\n * @param network - CAIP-2 network identifier (e.g. `\"eip155:84532\"`).\n * @returns EIP-712 signature over `Refund(channelId, nonce, amount)`.\n */\nexport async function signRefund(\n signer: AuthorizerSigner,\n channelId: `0x${string}`,\n amount: string,\n nonce: string,\n network: string,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(network);\n\n return signer.signTypedData({\n domain: getBatchSettlementEip712Domain(chainId),\n types: refundTypes,\n primaryType: \"Refund\",\n message: {\n channelId,\n nonce: BigInt(nonce),\n amount: BigInt(amount),\n },\n });\n}\n","import { SettleResponse, PaymentRequirements } from \"@payai/x402/types\";\nimport { getAddress, isAddressEqual, parseEventLogs } from \"viem\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { BatchSettlementSettlePayload } from \"../types\";\nimport { batchSettlementABI } from \"../abi\";\nimport { BATCH_SETTLEMENT_ADDRESS } from \"../constants\";\nimport * as Errors from \"../errors\";\n\n/**\n * Transfers claimed funds from the contract.\n *\n * This should be called after one or more `claim()` transactions have updated the\n * receiver's `totalClaimed` accounting onchain.\n *\n * @param signer - Facilitator signer used to submit the settlement transaction.\n * @param payload - Settle payload containing the receiver address and token address.\n * @param requirements - Payment requirements for network identification.\n * @returns A {@link SettleResponse} with the transaction hash on success.\n */\nexport async function executeSettle(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementSettlePayload,\n requirements: PaymentRequirements,\n): Promise<SettleResponse> {\n const network = requirements.network;\n const contractAddr = getAddress(BATCH_SETTLEMENT_ADDRESS);\n const receiver = getAddress(payload.receiver);\n const token = getAddress(payload.token);\n\n // Check if there is anything to settle\n try {\n const [totalClaimed, totalSettled] = (await signer.readContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"receivers\",\n args: [receiver, token],\n })) as readonly [bigint, bigint];\n\n if (totalClaimed <= totalSettled) {\n return {\n success: false,\n errorReason: Errors.ErrNothingToSettle,\n errorMessage: \"nothing to settle for receiver and token\",\n transaction: \"\",\n network,\n };\n }\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrRpcReadFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n\n // Simulate the settle transaction\n try {\n await signer.readContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"settle\",\n args: [receiver, token],\n });\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrSettleSimulationFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n\n try {\n const tx = await signer.writeContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"settle\",\n args: [receiver, token],\n });\n\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrSettleTransactionFailed,\n errorMessage: `transaction reverted (receipt status ${receipt.status})`,\n transaction: tx,\n network,\n };\n }\n\n let amount = \"\";\n if (receipt.logs) {\n const logs = parseEventLogs({\n abi: batchSettlementABI,\n eventName: \"Settled\",\n logs: receipt.logs.filter(log => isAddressEqual(log.address, contractAddr)),\n });\n const settledLog = logs.find(\n log => isAddressEqual(log.args.receiver, receiver) && isAddressEqual(log.args.token, token),\n );\n amount = settledLog?.args.amount.toString() ?? \"0\";\n }\n\n return {\n success: true,\n transaction: tx,\n network,\n amount,\n };\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrSettleTransactionFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n}\n","import { SettleResponse, PaymentRequirements } from \"@payai/x402/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport type {\n AuthorizerSigner,\n BatchSettlementEnrichedRefundPayload,\n ChannelState,\n} from \"../types\";\nimport { batchSettlementABI } from \"../abi\";\nimport { BATCH_SETTLEMENT_ADDRESS } from \"../constants\";\nimport { computeChannelId } from \"../utils\";\nimport { signClaimBatch, signRefund } from \"../authorizerSigner\";\nimport * as Errors from \"../errors\";\nimport { buildVoucherClaimArgs } from \"./claim\";\nimport { readChannelState, toContractChannelConfig } from \"./utils\";\n\ntype RefundSettlementExtra = {\n channelState: {\n channelId: `0x${string}`;\n balance: string;\n totalClaimed: string;\n withdrawRequestedAt: number;\n refundNonce: string;\n };\n};\n\ntype RefundSettlementDetails = {\n amount: string;\n extra: RefundSettlementExtra;\n};\n\nconst REFUND_STATE_POLL_MS = 2_000;\nconst REFUND_STATE_POLL_INTERVAL_MS = 150;\n\n/**\n * Computes the token amount that `refundWithSignature` would transfer after any\n * bundled claims are applied.\n *\n * @param payload - Refund payload containing requested refund amount and claims.\n * @param preState - Onchain channel state before the refund transaction.\n * @param channelId - Channel being refunded.\n * @param network - Network identifier used to compute claim channel ids.\n * @returns Refund amount if it can be determined, or `null` when claim data should be left to simulation.\n */\nfunction getRefundableAmount(\n payload: BatchSettlementEnrichedRefundPayload,\n preState: ChannelState,\n channelId: `0x${string}`,\n network: string,\n): bigint | null {\n const postClaimTotalClaimed = payload.claims.reduce((max, claim) => {\n const claimChannelId = computeChannelId(claim.voucher.channel, network);\n if (claimChannelId.toLowerCase() !== channelId.toLowerCase()) {\n return max;\n }\n\n const totalClaimed = BigInt(claim.totalClaimed);\n return totalClaimed > max ? totalClaimed : max;\n }, preState.totalClaimed);\n\n if (postClaimTotalClaimed > preState.balance) {\n return null;\n }\n\n const requestedAmount = BigInt(payload.amount);\n if (requestedAmount === 0n) {\n return null;\n }\n\n const available = preState.balance - postClaimTotalClaimed;\n return requestedAmount > available ? available : requestedAmount;\n}\n\n/**\n * Builds facilitator-owned response details for a refund settlement after applying the refund amount.\n *\n * @param payload - Refund payload containing claims and amount.\n * @param channelId - Canonical channel id for the refund.\n * @param preState - Onchain channel state before this refund, or null if unknown.\n * @returns Actual refund amount and extra fields for the settlement response.\n */\nfunction buildRefundExtra(\n payload: BatchSettlementEnrichedRefundPayload,\n channelId: `0x${string}`,\n preState: ChannelState | null,\n): RefundSettlementDetails {\n const preTotalClaimed = preState?.totalClaimed ?? 0n;\n const preBalance = preState?.balance ?? 0n;\n\n const lastClaimTotal =\n payload.claims.length > 0\n ? BigInt(payload.claims[payload.claims.length - 1].totalClaimed)\n : preTotalClaimed;\n const postClaimTotalClaimed = lastClaimTotal > preTotalClaimed ? lastClaimTotal : preTotalClaimed;\n\n const available = preBalance - postClaimTotalClaimed;\n const requestedAmount = BigInt(payload.amount);\n const actualRefund = requestedAmount > available ? available : requestedAmount;\n\n return {\n amount: actualRefund.toString(),\n extra: {\n channelState: {\n channelId,\n balance: (preBalance - actualRefund).toString(),\n totalClaimed: postClaimTotalClaimed.toString(),\n withdrawRequestedAt: 0,\n refundNonce: String((preState?.refundNonce ?? 0n) + 1n),\n },\n },\n };\n}\n\n/**\n * Reads the post-refund state when pending withdrawal state can be affected.\n *\n * @param signer - Facilitator signer used for onchain reads.\n * @param channelId - Channel that was refunded.\n * @param submittedNonce - Nonce used for this refund transaction.\n * @returns Fresh channel state once the nonce advances, or `null` if RPC reads lag.\n */\nasync function readPostRefundState(\n signer: FacilitatorEvmSigner,\n channelId: `0x${string}`,\n submittedNonce: string,\n): Promise<ChannelState | null> {\n const expectedNonce = BigInt(submittedNonce) + 1n;\n const deadline = Date.now() + REFUND_STATE_POLL_MS;\n\n do {\n let state: ChannelState;\n try {\n state = await readChannelState(signer, channelId);\n } catch {\n return null;\n }\n if (state.refundNonce >= expectedNonce) {\n return state;\n }\n await new Promise(resolve => setTimeout(resolve, REFUND_STATE_POLL_INTERVAL_MS));\n } while (Date.now() < deadline);\n\n return null;\n}\n\n/**\n * Builds refund response details from confirmed post-transaction state.\n *\n * @param channelId - Canonical channel id for the refund.\n * @param preState - Onchain state read before the transaction.\n * @param postState - Onchain state after the transaction.\n * @returns Actual refund amount and extra fields for the settlement response.\n */\nfunction buildRefundExtraFromPostState(\n channelId: `0x${string}`,\n preState: ChannelState,\n postState: ChannelState,\n): RefundSettlementDetails {\n const actualRefund =\n preState.balance > postState.balance ? preState.balance - postState.balance : 0n;\n\n return {\n amount: actualRefund.toString(),\n extra: {\n channelState: {\n channelId,\n balance: postState.balance.toString(),\n totalClaimed: postState.totalClaimed.toString(),\n withdrawRequestedAt: postState.withdrawRequestedAt,\n refundNonce: postState.refundNonce.toString(),\n },\n },\n };\n}\n\n/**\n * Executes a cooperative refund via `refundWithSignature`.\n *\n * When `refundAuthorizerSignature` / `claimAuthorizerSignature` are present they are used\n * directly. When absent the facilitator signs the missing digests using\n * `authorizerSigner`, after verifying that `config.receiverAuthorizer` matches\n * `authorizerSigner.address`.\n *\n * If `payload.claims` is non-empty, the claim and refund are batched atomically via\n * the contract's `multicall`.\n *\n * @param signer - Facilitator signer used to submit the onchain transactions.\n * @param payload - Refund payload with optional signatures, amount, and nonce.\n * @param requirements - Payment requirements for network identification.\n * @param authorizerSigner - Dedicated key for producing EIP-712 signatures.\n * @returns A {@link SettleResponse} with the transaction hash on success.\n */\nexport async function executeRefundWithSignature(\n signer: FacilitatorEvmSigner,\n payload: BatchSettlementEnrichedRefundPayload,\n requirements: PaymentRequirements,\n authorizerSigner: AuthorizerSigner,\n): Promise<SettleResponse> {\n const network = requirements.network;\n\n try {\n const channelId = computeChannelId(payload.channelConfig, network);\n const preState = await readChannelState(signer, channelId);\n const contractAddr = getAddress(BATCH_SETTLEMENT_ADDRESS);\n const refundableAmount = getRefundableAmount(payload, preState, channelId, network);\n\n if (refundableAmount === 0n) {\n return {\n success: false,\n errorReason: Errors.ErrRefundNoBalance,\n errorMessage: \"Nothing to refund\",\n transaction: \"\",\n network,\n };\n }\n\n const hasClientSig = payload.refundAuthorizerSignature !== undefined;\n const authorizerMismatch =\n getAddress(payload.channelConfig.receiverAuthorizer) !== getAddress(authorizerSigner.address);\n\n if (!hasClientSig && authorizerMismatch) {\n return {\n success: false,\n errorReason: Errors.ErrAuthorizerAddressMismatch,\n transaction: \"\",\n network,\n };\n }\n\n const refundSig =\n payload.refundAuthorizerSignature ??\n (await signRefund(authorizerSigner, channelId, payload.amount, payload.refundNonce, network));\n\n const refundCalldata = encodeFunctionData({\n abi: batchSettlementABI,\n functionName: \"refundWithSignature\",\n args: [\n toContractChannelConfig(payload.channelConfig),\n BigInt(payload.amount),\n BigInt(payload.refundNonce),\n refundSig,\n ],\n });\n\n let tx: `0x${string}`;\n\n if (payload.claims.length > 0) {\n let claimSig = payload.claimAuthorizerSignature;\n if (!claimSig) {\n claimSig = await signClaimBatch(authorizerSigner, payload.claims, network);\n }\n\n const claimCalldata = encodeFunctionData({\n abi: batchSettlementABI,\n functionName: \"claimWithSignature\",\n args: [buildVoucherClaimArgs(payload.claims), claimSig],\n });\n\n try {\n await signer.readContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"multicall\",\n args: [[claimCalldata, refundCalldata]],\n });\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrRefundSimulationFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n\n tx = await signer.writeContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"multicall\",\n args: [[claimCalldata, refundCalldata]],\n });\n } else {\n try {\n await signer.readContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"refundWithSignature\",\n args: [\n toContractChannelConfig(payload.channelConfig),\n BigInt(payload.amount),\n BigInt(payload.refundNonce),\n refundSig,\n ],\n });\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrRefundSimulationFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n\n tx = await signer.writeContract({\n address: contractAddr,\n abi: batchSettlementABI,\n functionName: \"refundWithSignature\",\n args: [\n toContractChannelConfig(payload.channelConfig),\n BigInt(payload.amount),\n BigInt(payload.refundNonce),\n refundSig,\n ],\n });\n }\n\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrRefundTransactionFailed,\n errorMessage: `transaction reverted (receipt status ${receipt.status})`,\n transaction: tx,\n network,\n };\n }\n\n const postState =\n preState && preState.withdrawRequestedAt !== 0\n ? await readPostRefundState(signer, channelId, payload.refundNonce)\n : null;\n const refundDetails =\n preState && postState\n ? buildRefundExtraFromPostState(channelId, preState, postState)\n : buildRefundExtra(payload, channelId, preState);\n\n return {\n success: true,\n transaction: tx,\n network,\n payer: payload.channelConfig.payer,\n amount: refundDetails.amount,\n extra: refundDetails.extra,\n };\n } catch (e) {\n return {\n success: false,\n errorReason: Errors.ErrRefundTransactionFailed,\n errorMessage: e instanceof Error ? e.message : String(e),\n transaction: \"\",\n network,\n };\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@payai/x402/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { BATCH_SETTLEMENT_SCHEME } from \"../constants\";\nimport {\n isBatchSettlementDepositPayload,\n isBatchSettlementVoucherPayload,\n isBatchSettlementClaimPayload,\n isBatchSettlementSettlePayload,\n isBatchSettlementRefundPayload,\n isBatchSettlementEnrichedRefundPayload,\n} from \"../types\";\nimport type { AuthorizerSigner } from \"../types\";\nimport { verifyDeposit, settleDeposit } from \"./deposit\";\nimport { verifyVoucher } from \"./voucher\";\nimport { executeClaimWithSignature } from \"./claim\";\nimport { executeSettle } from \"./settle\";\nimport { executeRefundWithSignature } from \"./refund\";\nimport * as Errors from \"../errors\";\n\n/**\n * Facilitator-side implementation of the `batch-settlement` scheme for EVM networks.\n *\n * Routes incoming verify/settle requests to the appropriate handler based on payload\n * type (deposit, voucher, claim, settle, refund).\n */\nexport class BatchSettlementEvmScheme implements SchemeNetworkFacilitator {\n readonly scheme = BATCH_SETTLEMENT_SCHEME;\n readonly caipFamily = \"eip155:*\";\n\n /**\n * Creates a facilitator scheme for verifying and settling batch-settlement payments.\n *\n * @param signer - Facilitator EVM signer(s) used for tx submission and onchain reads.\n * @param authorizerSigner - Dedicated key that provides EIP-712 signatures for\n * `claimWithSignature` / `refundWithSignature`. The facilitator will sign missing\n * authorizer signatures using this key when the server omits them.\n */\n constructor(\n private readonly signer: FacilitatorEvmSigner,\n private readonly authorizerSigner: AuthorizerSigner,\n ) {}\n\n /**\n * Returns facilitator-specific extra fields to be merged into payment requirements.\n *\n * Exposes the configured `receiverAuthorizer` address so the server and client can\n * embed it in `ChannelConfig`.\n *\n * @param _ - Network identifier (unused).\n * @returns Extra fields containing `receiverAuthorizer`.\n */\n getExtra(_: string): { receiverAuthorizer: `0x${string}` } | undefined {\n return { receiverAuthorizer: this.authorizerSigner.address };\n }\n\n /**\n * Returns all facilitator signer addresses available for the given network.\n *\n * @param _ - Network identifier (unused).\n * @returns Array of hex addresses.\n */\n getSigners(_: string): `0x${string}`[] {\n return [...this.signer.getAddresses()];\n }\n\n /**\n * Verifies a payment payload (deposit or voucher) without executing settlement.\n *\n * @param payload - The x402 payment payload envelope.\n * @param requirements - Server payment requirements (scheme, network, asset, amount).\n * @param context - Optional facilitator extension context.\n * @returns A {@link VerifyResponse} indicating validity with payer and channel state in `extra`.\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<VerifyResponse> {\n const rawPayload = payload.payload;\n\n if (\n payload.accepted.scheme !== BATCH_SETTLEMENT_SCHEME ||\n requirements.scheme !== BATCH_SETTLEMENT_SCHEME\n ) {\n return { isValid: false, invalidReason: Errors.ErrInvalidScheme };\n }\n\n if (payload.accepted.network !== requirements.network) {\n return { isValid: false, invalidReason: Errors.ErrNetworkMismatch };\n }\n\n if (isBatchSettlementDepositPayload(rawPayload)) {\n return verifyDeposit(this.signer, payload, rawPayload, requirements, context);\n }\n\n if (isBatchSettlementVoucherPayload(rawPayload)) {\n return verifyVoucher(this.signer, rawPayload, requirements, rawPayload.channelConfig);\n }\n\n if (isBatchSettlementRefundPayload(rawPayload)) {\n return verifyVoucher(this.signer, rawPayload, requirements, rawPayload.channelConfig);\n }\n\n return { isValid: false, invalidReason: Errors.ErrInvalidPayloadType };\n }\n\n /**\n * Executes settlement for a payment payload.\n *\n * Dispatches to the correct handler based on payload settle action:\n * - `deposit` → onchain `deposit(config, amount, collector, collectorData)`\n * - `claim` → onchain `claimWithSignature(VoucherClaim[], bytes)`\n * - `settle` → onchain `settle(receiver, token)`\n * - `refund` → optional claim + onchain `refundWithSignature(config, amount, nonce, sig)`\n *\n * @param payload - The x402 payment payload envelope.\n * @param requirements - Server payment requirements.\n * @param context - Optional facilitator extension context.\n * @returns A {@link SettleResponse} with the transaction hash on success.\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<SettleResponse> {\n const rawPayload = payload.payload;\n\n if (isBatchSettlementDepositPayload(rawPayload)) {\n return settleDeposit(this.signer, payload, rawPayload, requirements, context);\n }\n\n if (isBatchSettlementClaimPayload(rawPayload)) {\n return executeClaimWithSignature(\n this.signer,\n rawPayload,\n requirements,\n this.authorizerSigner,\n );\n }\n\n if (isBatchSettlementEnrichedRefundPayload(rawPayload)) {\n return executeRefundWithSignature(\n this.signer,\n rawPayload,\n requirements,\n this.authorizerSigner,\n );\n }\n\n if (isBatchSettlementSettlePayload(rawPayload)) {\n return executeSettle(this.signer, rawPayload, requirements);\n }\n\n return {\n success: false,\n errorReason: Errors.ErrInvalidPayloadType,\n transaction: \"\",\n network: requirements.network,\n };\n }\n}\n"],"mappings":"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","names":["import_viem","import_viem","import_viem","import_viem","import_viem","viemVerifyTypedData","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem"]}
@@ -0,0 +1,53 @@
1
+ import { F as FileChannelStorageOptions } from '../../types-CF8P2-NM.js';
2
+ import { C as ChannelStorage, a as Channel, b as ChannelUpdateResult } from '../../storage-Bl6aD0Xg.js';
3
+ import 'viem';
4
+
5
+ /**
6
+ * Node.js file-backed {@link ChannelStorage} for the batched server scheme.
7
+ */
8
+ declare class FileChannelStorage implements ChannelStorage {
9
+ private readonly root;
10
+ /**
11
+ * Creates file-backed server channel storage under the given root directory.
12
+ *
13
+ * @param options - Configuration including the storage root directory.
14
+ */
15
+ constructor(options: FileChannelStorageOptions);
16
+ /**
17
+ * Loads a persisted channel record, if present.
18
+ *
19
+ * @param channelId - The channel identifier (path segment is lowercased).
20
+ * @returns Parsed channel record or `undefined` when the file is missing.
21
+ */
22
+ get(channelId: string): Promise<Channel | undefined>;
23
+ /**
24
+ * Lists all stored channel records by reading the server directory.
25
+ *
26
+ * @returns Channel records sorted by channelId; empty array if the directory is missing.
27
+ */
28
+ list(): Promise<Channel[]>;
29
+ /**
30
+ * Atomically inspects and mutates a channel record under a cross-process file lock.
31
+ *
32
+ * @param channelId - The channel identifier.
33
+ * @param update - Mutation callback. Return `undefined` to delete, or `current` to leave unchanged.
34
+ * @returns The final stored channel and whether storage updated, stayed unchanged, or deleted.
35
+ */
36
+ updateChannel(channelId: string, update: (current: Channel | undefined) => Channel | undefined): Promise<ChannelUpdateResult>;
37
+ /**
38
+ * Absolute path to the JSON file for a channel.
39
+ *
40
+ * @param channelId - The channel identifier.
41
+ * @returns Filesystem path under `{root}/server/...`.
42
+ */
43
+ private filePath;
44
+ /**
45
+ * Creates an exclusive lock file, polling until no other process holds it.
46
+ *
47
+ * @param lockPath - Absolute path for the lock file (created with `O_EXCL`).
48
+ * @returns Writable file handle for the lock file; caller must close it to release.
49
+ */
50
+ private acquireLock;
51
+ }
52
+
53
+ export { FileChannelStorage, FileChannelStorageOptions };