@payai/x402-evm 2.4.1 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/batch-settlement/client/file-storage.d.ts +47 -0
- package/dist/cjs/batch-settlement/client/file-storage.js +116 -0
- package/dist/cjs/batch-settlement/client/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/client/index.d.ts +111 -0
- package/dist/cjs/batch-settlement/client/index.js +1565 -0
- package/dist/cjs/batch-settlement/client/index.js.map +1 -0
- package/dist/cjs/batch-settlement/facilitator/index.d.ts +71 -0
- package/dist/cjs/batch-settlement/facilitator/index.js +2032 -0
- package/dist/cjs/batch-settlement/facilitator/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/file-storage.d.ts +53 -0
- package/dist/cjs/batch-settlement/server/file-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/file-storage.js.map +1 -0
- package/dist/cjs/batch-settlement/server/index.d.ts +491 -0
- package/dist/cjs/batch-settlement/server/index.js +1960 -0
- package/dist/cjs/batch-settlement/server/index.js.map +1 -0
- package/dist/cjs/batch-settlement/server/redis-storage.d.ts +87 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js +181 -0
- package/dist/cjs/batch-settlement/server/redis-storage.js.map +1 -0
- package/dist/cjs/exact/client/index.d.ts +6 -4
- package/dist/cjs/exact/client/index.js +7 -5
- package/dist/cjs/exact/client/index.js.map +1 -1
- package/dist/cjs/exact/facilitator/index.d.ts +16 -9
- package/dist/cjs/exact/facilitator/index.js +35 -7
- package/dist/cjs/exact/facilitator/index.js.map +1 -1
- package/dist/cjs/exact/server/index.js +40 -1
- package/dist/cjs/exact/server/index.js.map +1 -1
- package/dist/cjs/exact/v1/client/index.d.ts +2 -1
- package/dist/cjs/exact/v1/client/index.js.map +1 -1
- package/dist/cjs/exact/v1/facilitator/index.d.ts +11 -5
- package/dist/cjs/exact/v1/facilitator/index.js +16 -2
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -1
- package/dist/cjs/index.d.ts +113 -7
- package/dist/cjs/index.js +1353 -5
- package/dist/cjs/index.js.map +1 -1
- package/dist/{esm/permit2-CyZxwngN.d.mts → cjs/permit2-DhJRUcgY.d.ts} +1 -13
- package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
- package/dist/cjs/scheme-CvkPJXBD.d.ts +307 -0
- package/dist/{esm/scheme-DCR7hsa3.d.mts → cjs/scheme-DTQFE9xp.d.ts} +2 -2
- package/dist/{esm/signer-D912R4mq.d.mts → cjs/signer-tYS6Y46X.d.ts} +3 -0
- package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
- package/dist/cjs/storage-Bl6aD0Xg.d.ts +81 -0
- package/dist/cjs/types-CF8P2-NM.d.ts +180 -0
- package/dist/cjs/upto/client/index.d.ts +5 -3
- package/dist/cjs/upto/client/index.js +7 -5
- package/dist/cjs/upto/client/index.js.map +1 -1
- package/dist/cjs/upto/facilitator/index.d.ts +2 -1
- package/dist/cjs/upto/facilitator/index.js +2 -1
- package/dist/cjs/upto/facilitator/index.js.map +1 -1
- package/dist/cjs/upto/server/index.js +40 -1
- package/dist/cjs/upto/server/index.js.map +1 -1
- package/dist/cjs/v1/index.d.ts +2 -1
- package/dist/cjs/v1/index.js.map +1 -1
- package/dist/esm/batch-settlement/client/file-storage.d.mts +47 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs +63 -0
- package/dist/esm/batch-settlement/client/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/client/index.d.mts +111 -0
- package/dist/esm/batch-settlement/client/index.mjs +59 -0
- package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/facilitator/index.d.mts +71 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs +1235 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/file-storage.d.mts +53 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs +128 -0
- package/dist/esm/batch-settlement/server/file-storage.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/index.d.mts +491 -0
- package/dist/esm/batch-settlement/server/index.mjs +1645 -0
- package/dist/esm/batch-settlement/server/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/server/redis-storage.d.mts +87 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs +156 -0
- package/dist/esm/batch-settlement/server/redis-storage.mjs.map +1 -0
- package/dist/esm/chunk-2EUQTNJO.mjs +38 -0
- package/dist/esm/chunk-2EUQTNJO.mjs.map +1 -0
- package/dist/esm/chunk-53USC5VE.mjs +47 -0
- package/dist/esm/chunk-53USC5VE.mjs.map +1 -0
- package/dist/esm/{chunk-GJ57SZGI.mjs → chunk-6WQOGWBE.mjs} +7 -5
- package/dist/esm/{chunk-GJ57SZGI.mjs.map → chunk-6WQOGWBE.mjs.map} +1 -1
- package/dist/esm/{chunk-F3OOHBAW.mjs → chunk-BTYNCDNS.mjs} +42 -2
- package/dist/esm/{chunk-F3OOHBAW.mjs.map → chunk-BTYNCDNS.mjs.map} +1 -1
- package/dist/esm/{chunk-ERK2ZPOY.mjs → chunk-CSQS7ZON.mjs} +27 -7
- package/dist/esm/chunk-CSQS7ZON.mjs.map +1 -0
- package/dist/esm/chunk-GD4MKCN7.mjs +57 -0
- package/dist/esm/chunk-GD4MKCN7.mjs.map +1 -0
- package/dist/esm/chunk-HYABYUBD.mjs +432 -0
- package/dist/esm/chunk-HYABYUBD.mjs.map +1 -0
- package/dist/esm/chunk-IN5YIT5C.mjs +159 -0
- package/dist/esm/chunk-IN5YIT5C.mjs.map +1 -0
- package/dist/esm/{chunk-JII456TS.mjs → chunk-JK7SLLF7.mjs} +1 -1
- package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
- package/dist/esm/{chunk-C4ZQMS77.mjs → chunk-MACPBXCT.mjs} +2 -216
- package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
- package/dist/esm/chunk-NKYVYGRA.mjs +911 -0
- package/dist/esm/chunk-NKYVYGRA.mjs.map +1 -0
- package/dist/esm/{chunk-FQJR4RCF.mjs → chunk-R7I3RZFF.mjs} +10 -6
- package/dist/esm/{chunk-FQJR4RCF.mjs.map → chunk-R7I3RZFF.mjs.map} +1 -1
- package/dist/esm/{chunk-CRT6YNY5.mjs → chunk-RWLVVO3B.mjs} +21 -61
- package/dist/esm/chunk-RWLVVO3B.mjs.map +1 -0
- package/dist/esm/chunk-TGFAVNUD.mjs +111 -0
- package/dist/esm/chunk-TGFAVNUD.mjs.map +1 -0
- package/dist/esm/chunk-TW7Z65AO.mjs +34 -0
- package/dist/esm/chunk-TW7Z65AO.mjs.map +1 -0
- package/dist/esm/chunk-U4HCGTLU.mjs +35 -0
- package/dist/esm/chunk-U4HCGTLU.mjs.map +1 -0
- package/dist/esm/chunk-VS3RYAYE.mjs +80 -0
- package/dist/esm/chunk-VS3RYAYE.mjs.map +1 -0
- package/dist/esm/chunk-W6ON4LG2.mjs +39 -0
- package/dist/esm/chunk-W6ON4LG2.mjs.map +1 -0
- package/dist/esm/{chunk-WKBC5YMI.mjs → chunk-YMQCTKDU.mjs} +23 -55
- package/dist/esm/chunk-YMQCTKDU.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +6 -4
- package/dist/esm/exact/client/index.mjs +10 -5
- package/dist/esm/exact/facilitator/index.d.mts +16 -9
- package/dist/esm/exact/facilitator/index.mjs +36 -14
- package/dist/esm/exact/facilitator/index.mjs.map +1 -1
- package/dist/esm/exact/server/index.mjs +1 -1
- package/dist/esm/exact/v1/client/index.d.mts +2 -1
- package/dist/esm/exact/v1/client/index.mjs +5 -2
- package/dist/esm/exact/v1/facilitator/index.d.mts +11 -5
- package/dist/esm/exact/v1/facilitator/index.mjs +5 -2
- package/dist/esm/index.d.mts +113 -7
- package/dist/esm/index.mjs +53 -7
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
- package/dist/esm/rpc-DULZzRne.d.mts +13 -0
- package/dist/esm/scheme-DtbSS4Fk.d.mts +307 -0
- package/dist/esm/scheme-gtqAIYPJ.d.mts +47 -0
- package/dist/esm/signer-tYS6Y46X.d.mts +170 -0
- package/dist/esm/storage-6W5MO46W.d.mts +50 -0
- package/dist/esm/storage-sZ1CDS4P.d.mts +81 -0
- package/dist/esm/types-CF8P2-NM.d.mts +180 -0
- package/dist/esm/upto/client/index.d.mts +5 -3
- package/dist/esm/upto/client/index.mjs +9 -4
- package/dist/esm/upto/facilitator/index.d.mts +2 -1
- package/dist/esm/upto/facilitator/index.mjs +17 -9
- package/dist/esm/upto/facilitator/index.mjs.map +1 -1
- package/dist/esm/upto/server/index.mjs +1 -1
- package/dist/esm/v1/index.d.mts +2 -1
- package/dist/esm/v1/index.mjs +5 -2
- package/package.json +5 -5
- package/dist/esm/chunk-C4ZQMS77.mjs.map +0 -1
- package/dist/esm/chunk-CRT6YNY5.mjs.map +0 -1
- package/dist/esm/chunk-ERK2ZPOY.mjs.map +0 -1
- package/dist/esm/chunk-JII456TS.mjs.map +0 -1
- package/dist/esm/chunk-WKBC5YMI.mjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/batch-settlement/client/index.ts","../../../../src/batch-settlement/client/scheme.ts","../../../../src/batch-settlement/constants.ts","../../../../src/batch-settlement/utils.ts","../../../../src/utils.ts","../../../../src/exact/extensions.ts","../../../../src/shared/extensions.ts","../../../../src/constants.ts","../../../../src/exact/client/eip2612.ts","../../../../src/exact/client/erc20approval.ts","../../../../src/shared/rpc.ts","../../../../src/batch-settlement/client/eip3009.ts","../../../../src/batch-settlement/client/voucher.ts","../../../../src/batch-settlement/encoding.ts","../../../../src/batch-settlement/client/permit2.ts","../../../../src/batch-settlement/client/storage.ts","../../../../src/batch-settlement/client/config.ts","../../../../src/batch-settlement/client/refund.ts","../../../../src/batch-settlement/errors.ts","../../../../src/batch-settlement/client/channel.ts","../../../../src/batch-settlement/abi.ts","../../../../src/batch-settlement/types.ts","../../../../src/batch-settlement/client/recovery.ts","../../../../src/batch-settlement/client/hooks.ts"],"sourcesContent":["export { BatchSettlementEvmScheme } from \"./scheme\";\nexport type {\n BatchSettlementClientContext,\n BatchSettlementDepositPolicy,\n BatchSettlementDepositStrategy,\n BatchSettlementDepositStrategyContext,\n BatchSettlementDepositStrategyResult,\n BatchSettlementEvmSchemeOptions,\n} from \"./scheme\";\nexport type { ClientChannelStorage } from \"./storage\";\nexport { InMemoryClientChannelStorage } from \"./storage\";\nexport { createBatchSettlementEIP3009DepositPayload } from \"./eip3009\";\nexport { signVoucher } from \"./voucher\";\nexport { refundChannel } from \"./refund\";\nexport type { RefundOptions } from \"./refund\";\nexport { createBatchSettlementClientHooks, handleBatchSettlementPaymentResponse } from \"./hooks\";\nexport { computeChannelId } from \"../utils\";\n\nexport {\n depositAmountForRequest,\n isBatchSettlementEvmSchemeOptions,\n resolveClientOptions,\n validateDepositPolicy,\n} from \"./config\";\nexport type { ResolvedClientOptions } from \"./config\";\n\nexport {\n buildChannelConfig,\n getChannel,\n hasChannel,\n processPaymentResponse,\n processSettleResponse,\n readChannelBalanceAndTotalClaimed,\n recoverChannel,\n updateChannelAfterRefund,\n} from \"./channel\";\nexport type { BatchSettlementClientDeps } from \"./channel\";\n\nexport {\n processCorrectivePaymentRequired,\n recoverFromOnChainState,\n recoverFromSignature,\n} from \"./recovery\";\n","import {\n SchemeNetworkClient,\n SchemeClientHooks,\n PaymentRequired,\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n SettleResponse,\n} from \"@payai/x402/types\";\nimport { getAddress } from \"viem\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { BATCH_SETTLEMENT_SCHEME } from \"../constants\";\nimport {\n BatchSettlementAssetTransferMethod,\n BatchSettlementVoucherPayload,\n ChannelConfig,\n} from \"../types\";\nimport { computeChannelId } from \"../utils\";\nimport {\n trySignEip2612PermitExtension,\n trySignErc20ApprovalExtension,\n} from \"../../shared/extensions\";\nimport type { EvmSchemeOptions } from \"../../shared/rpc\";\nimport { createBatchSettlementEIP3009DepositPayload } from \"./eip3009\";\nimport { createBatchSettlementPermit2DepositPayload } from \"./permit2\";\nimport {\n type BatchSettlementDepositStrategy,\n type BatchSettlementDepositStrategyContext,\n type BatchSettlementDepositPolicy,\n type BatchSettlementEvmSchemeOptions,\n depositAmountForRequest,\n resolveClientOptions,\n validateDepositPolicy,\n} from \"./config\";\nimport { refundChannel, type RefundOptions } from \"./refund\";\nimport {\n type BatchSettlementClientDeps,\n buildChannelConfig,\n processSettleResponse,\n recoverChannel,\n} from \"./channel\";\nimport { createBatchSettlementClientHooks } from \"./hooks\";\nimport { processCorrectivePaymentRequired } from \"./recovery\";\nimport type { ClientChannelStorage } from \"./storage\";\nimport { signVoucher } from \"./voucher\";\n\nexport type { BatchSettlementClientContext } from \"./storage\";\nexport type {\n BatchSettlementDepositPolicy,\n BatchSettlementDepositStrategy,\n BatchSettlementDepositStrategyContext,\n BatchSettlementDepositStrategyResult,\n BatchSettlementEvmSchemeOptions,\n} from \"./config\";\nexport type { RefundOptions } from \"./refund\";\n\n/**\n * Client-side implementation of the `batch-settlement` scheme for EVM networks.\n *\n * Builds payment payloads (deposit + voucher or voucher-only), processes server\n * responses to update local session state via {@link processSettleResponse},\n * handles corrective 402 resynchronisation via\n * {@link processCorrectivePaymentRequired}, and supports on-demand cooperative\n * refund requests via {@link refundChannel}.\n */\nexport class BatchSettlementEvmScheme implements SchemeNetworkClient {\n readonly scheme = BATCH_SETTLEMENT_SCHEME;\n\n readonly schemeHooks: SchemeClientHooks;\n\n private readonly storage: ClientChannelStorage;\n private readonly depositPolicy: BatchSettlementDepositPolicy | undefined;\n private readonly depositStrategy: BatchSettlementDepositStrategy | undefined;\n private readonly salt: `0x${string}`;\n private readonly payerAuthorizer: `0x${string}` | undefined;\n private readonly voucherSigner: ClientEvmSigner | undefined;\n private readonly extensionRpcOptions: EvmSchemeOptions | undefined;\n\n /**\n * Constructs a batched client scheme.\n *\n * @param signer - Client EVM wallet used for signing vouchers and ERC-3009 authorizations.\n * @param optionsOrPolicy - Either a full options object or a bare deposit-policy.\n */\n constructor(\n private readonly signer: ClientEvmSigner,\n optionsOrPolicy?: BatchSettlementEvmSchemeOptions | BatchSettlementDepositPolicy,\n ) {\n const {\n storage,\n depositPolicy,\n depositStrategy,\n salt,\n payerAuthorizer,\n voucherSigner,\n extensionRpcOptions,\n } = resolveClientOptions(optionsOrPolicy);\n this.storage = storage;\n this.depositPolicy = depositPolicy;\n this.depositStrategy = depositStrategy;\n this.salt = salt;\n this.payerAuthorizer = payerAuthorizer;\n this.voucherSigner = voucherSigner;\n this.extensionRpcOptions = extensionRpcOptions;\n\n if (\n payerAuthorizer !== undefined &&\n voucherSigner !== undefined &&\n getAddress(payerAuthorizer) !== getAddress(voucherSigner.address)\n ) {\n throw new Error(\"payerAuthorizer address must match voucherSigner.address\");\n }\n\n validateDepositPolicy(depositPolicy);\n this.schemeHooks = createBatchSettlementClientHooks(this.deps());\n }\n\n /**\n * Creates the payment payload for a batched request.\n *\n * If the channel has no onchain deposit (or needs a top-up), builds an\n * ERC-3009 deposit payload bundled with a voucher. Otherwise, signs and\n * returns a voucher-only payload.\n *\n * @param x402Version - Protocol version for the payload envelope.\n * @param paymentRequirements - Server payment requirements (scheme, network, asset, amount).\n * @param context - Optional payment payload context with extension hints.\n * @returns A {@link PaymentPayloadResult} ready to be sent as the `X-PAYMENT` header.\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const deps = this.deps();\n const config = buildChannelConfig(deps, paymentRequirements);\n const channelId = computeChannelId(config, paymentRequirements.network);\n const key = channelId.toLowerCase();\n\n let batchedCtx = await this.storage.get(key);\n if (batchedCtx === undefined && this.signer.readContract) {\n batchedCtx = await recoverChannel(deps, paymentRequirements);\n }\n batchedCtx = batchedCtx ?? {};\n\n const needsInitialDeposit = !batchedCtx.balance || batchedCtx.balance === \"0\";\n\n const baseCumulative = BigInt(batchedCtx.chargedCumulativeAmount ?? \"0\");\n const requestAmount = BigInt(paymentRequirements.amount);\n const maxClaimableAmount = (baseCumulative + requestAmount).toString();\n\n const currentBalance = BigInt(batchedCtx.balance ?? \"0\");\n const needsTopUp = !needsInitialDeposit && BigInt(maxClaimableAmount) > currentBalance;\n\n if (needsInitialDeposit || needsTopUp) {\n const computedDeposit = depositAmountForRequest(this.depositPolicy, requestAmount);\n const minimumDepositAmount = BigInt(maxClaimableAmount) - currentBalance;\n const depositAmount = await this.resolveDepositAmount({\n paymentRequirements,\n channelConfig: config,\n channelId,\n clientContext: batchedCtx,\n requestAmount: requestAmount.toString(),\n maxClaimableAmount,\n currentBalance: currentBalance.toString(),\n minimumDepositAmount: minimumDepositAmount.toString(),\n depositAmount: computedDeposit,\n });\n if (depositAmount === false) {\n return this.createVoucherPayload(\n x402Version,\n channelId,\n maxClaimableAmount,\n paymentRequirements.network,\n config,\n );\n }\n\n const assetTransferMethod =\n (paymentRequirements.extra?.assetTransferMethod as BatchSettlementAssetTransferMethod) ??\n \"eip3009\";\n\n if (assetTransferMethod === \"eip3009\") {\n return createBatchSettlementEIP3009DepositPayload(\n this.signer,\n x402Version,\n paymentRequirements,\n config,\n depositAmount,\n maxClaimableAmount,\n this.voucherSigner,\n );\n }\n\n if (assetTransferMethod !== \"permit2\") {\n throw new Error(`unsupported batch-settlement assetTransferMethod: ${assetTransferMethod}`);\n }\n\n const result = await createBatchSettlementPermit2DepositPayload(\n this.signer,\n x402Version,\n paymentRequirements,\n config,\n depositAmount,\n maxClaimableAmount,\n this.voucherSigner,\n );\n\n const eip2612Extensions = await trySignEip2612PermitExtension(\n this.signer,\n this.extensionRpcOptions,\n paymentRequirements,\n result,\n context,\n depositAmount,\n );\n if (eip2612Extensions) {\n return { ...result, extensions: eip2612Extensions };\n }\n\n const erc20Extensions = await trySignErc20ApprovalExtension(\n this.signer,\n this.extensionRpcOptions,\n paymentRequirements,\n context,\n depositAmount,\n );\n if (erc20Extensions) {\n return { ...result, extensions: erc20Extensions };\n }\n\n return result;\n }\n\n return this.createVoucherPayload(\n x402Version,\n channelId,\n maxClaimableAmount,\n paymentRequirements.network,\n config,\n );\n }\n\n /**\n * Sends a cooperative refund request.\n *\n * @param url - The route URL backing the channel to refund.\n * @param options - Optional `amount` (partial refund) and `fetch` override.\n * @returns The settle response describing the refund outcome.\n */\n async refund(url: string, options?: RefundOptions): Promise<SettleResponse> {\n return refundChannel(this.deps(), url, options);\n }\n\n /**\n * Updates local channel state from a settle response.\n *\n * @param settle - The parsed settle response from the server.\n * @returns Resolves when local channel state has been updated.\n */\n async processSettleResponse(settle: SettleResponse): Promise<void> {\n return processSettleResponse(this.storage, settle);\n }\n\n /**\n * Resyncs local channel state from a corrective 402 response.\n *\n * @param paymentRequired - The decoded 402 response body.\n * @returns `true` if local state was successfully resynced and a retry is warranted.\n */\n async processCorrectivePaymentRequired(paymentRequired: PaymentRequired): Promise<boolean> {\n return processCorrectivePaymentRequired(this.deps(), paymentRequired);\n }\n\n /**\n * Builds the immutable {@link ChannelConfig} for a given set of payment\n * requirements, using the scheme's own signer and salt.\n *\n * @param paymentRequirements - Server payment requirements for the channel.\n * @returns The channel config that uniquely identifies the payment channel.\n */\n buildChannelConfig(paymentRequirements: PaymentRequirements): ChannelConfig {\n return buildChannelConfig(this.deps(), paymentRequirements);\n }\n\n /**\n * Resolves the deposit amount after applying the optional custom strategy.\n *\n * @param context - Deposit attempt context exposed to the strategy.\n * @returns The deposit amount to sign, or `false` to skip this deposit attempt.\n */\n private async resolveDepositAmount(\n context: BatchSettlementDepositStrategyContext,\n ): Promise<string | false> {\n const strategyResult = await this.depositStrategy?.(context);\n if (strategyResult === false) return false;\n if (strategyResult === undefined) return context.depositAmount;\n\n const depositAmount = this.normalizeStrategyDepositAmount(strategyResult);\n if (BigInt(depositAmount) < BigInt(context.minimumDepositAmount)) {\n throw new Error(\n `depositStrategy returned ${depositAmount}, below required top-up ${context.minimumDepositAmount}`,\n );\n }\n return depositAmount;\n }\n\n /**\n * Normalizes and validates a strategy-provided base-unit deposit amount.\n *\n * @param value - Strategy-provided string or bigint amount.\n * @returns Normalized decimal string.\n */\n private normalizeStrategyDepositAmount(value: string | bigint): string {\n if (typeof value === \"bigint\") {\n if (value <= 0n) {\n throw new Error(\"depositStrategy must return a positive integer deposit amount\");\n }\n return value.toString();\n }\n\n if (/^\\d+$/.test(value) && BigInt(value) > 0n) {\n return BigInt(value).toString();\n }\n\n throw new Error(\"depositStrategy must return a positive integer deposit amount\");\n }\n\n /**\n * Signs a voucher-only payment payload for the current channel.\n *\n * @param x402Version - Protocol version for the payload envelope.\n * @param channelId - Channel identifier for the voucher.\n * @param maxClaimableAmount - Cumulative ceiling for the voucher.\n * @param network - CAIP-2 network identifier.\n * @param config - Immutable channel configuration.\n * @returns Voucher-only payment payload.\n */\n private async createVoucherPayload(\n x402Version: number,\n channelId: `0x${string}`,\n maxClaimableAmount: string,\n network: string,\n config: ChannelConfig,\n ): Promise<PaymentPayloadResult> {\n const voucherSigner = this.voucherSigner ?? this.signer;\n const voucher = await signVoucher(voucherSigner, channelId, maxClaimableAmount, network);\n\n const payload: BatchSettlementVoucherPayload = {\n type: \"voucher\",\n channelConfig: config,\n voucher,\n };\n\n return {\n x402Version,\n payload,\n };\n }\n\n /**\n * Bundles the class state into the {@link BatchSettlementClientDeps} shape\n * consumed by the `channel`, `recovery`, and `refund` modules.\n *\n * @returns Client deps wrapping the scheme's own signer and storage.\n */\n private deps(): BatchSettlementClientDeps {\n return {\n signer: this.signer,\n storage: this.storage,\n salt: this.salt,\n payerAuthorizer: this.payerAuthorizer,\n voucherSigner: this.voucherSigner,\n };\n }\n}\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 { 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 { 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 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 { PaymentRequirements, PaymentPayloadResult, PaymentPayloadContext } from \"@payai/x402/types\";\nimport { EIP2612_GAS_SPONSORING_KEY, ERC20_APPROVAL_GAS_SPONSORING_KEY } from \"../exact/extensions\";\nimport { getAddress } from \"viem\";\nimport { PERMIT2_ADDRESS, erc20AllowanceAbi } from \"../constants\";\nimport { getEvmChainId } from \"../utils\";\nimport { ClientEvmSigner } from \"../signer\";\nimport { signEip2612Permit } from \"../exact/client/eip2612\";\nimport { signErc20ApprovalTransaction } from \"../exact/client/erc20approval\";\nimport { resolveExtensionRpcCapabilities, type ExactEvmSchemeOptions } from \"./rpc\";\n\n/**\n * Attempts to sign an EIP-2612 permit for gasless Permit2 approval.\n *\n * @param signer - The EVM client signer\n * @param options - Optional RPC configuration for backfilling capabilities\n * @param requirements - The payment requirements from the server\n * @param result - The payment payload result from the scheme\n * @param context - Optional context containing server extensions and metadata\n * @param approvalAmount - Optional amount to approve instead of `requirements.amount`\n * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable\n */\nexport async function trySignEip2612PermitExtension(\n signer: ClientEvmSigner,\n options: ExactEvmSchemeOptions | undefined,\n requirements: PaymentRequirements,\n result: PaymentPayloadResult,\n context?: PaymentPayloadContext,\n approvalAmount?: string,\n): Promise<Record<string, unknown> | undefined> {\n const capabilities = resolveExtensionRpcCapabilities(requirements.network, signer, options);\n\n if (!capabilities.readContract) {\n return undefined;\n }\n\n if (!context?.extensions?.[EIP2612_GAS_SPONSORING_KEY]) {\n return undefined;\n }\n\n const tokenName = requirements.extra?.name as string | undefined;\n const tokenVersion = requirements.extra?.version as string | undefined;\n if (!tokenName || !tokenVersion) {\n return undefined;\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n const requiredAllowance = approvalAmount ?? requirements.amount;\n\n try {\n const allowance = (await capabilities.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requiredAllowance)) {\n return undefined;\n }\n } catch {\n // Allowance check failed, proceed with signing\n }\n\n const permit2Auth = result.payload?.permit2Authorization as Record<string, unknown> | undefined;\n const deadline =\n (permit2Auth?.deadline as string) ??\n Math.floor(Date.now() / 1000 + requirements.maxTimeoutSeconds).toString();\n\n const info = await signEip2612Permit(\n {\n address: signer.address,\n signTypedData: msg => signer.signTypedData(msg),\n readContract: capabilities.readContract,\n },\n tokenAddress,\n tokenName,\n tokenVersion,\n chainId,\n deadline,\n requiredAllowance,\n );\n\n return {\n [EIP2612_GAS_SPONSORING_KEY]: { info },\n };\n}\n\n/**\n * Attempts to sign an ERC-20 approval transaction for gasless Permit2 approval.\n *\n * @param signer - The EVM client signer\n * @param options - Optional RPC configuration for backfilling capabilities\n * @param requirements - The payment requirements from the server\n * @param context - Optional context containing server extensions and metadata\n * @param approvalAmount - Optional amount to check for Permit2 allowance\n * @returns Extension data for ERC-20 approval gas sponsoring, or undefined if not applicable\n */\nexport async function trySignErc20ApprovalExtension(\n signer: ClientEvmSigner,\n options: ExactEvmSchemeOptions | undefined,\n requirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n approvalAmount?: string,\n): Promise<Record<string, unknown> | undefined> {\n const capabilities = resolveExtensionRpcCapabilities(requirements.network, signer, options);\n\n if (!capabilities.readContract) {\n return undefined;\n }\n\n if (!context?.extensions?.[ERC20_APPROVAL_GAS_SPONSORING_KEY]) {\n return undefined;\n }\n\n if (!capabilities.signTransaction || !capabilities.getTransactionCount) {\n return undefined;\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n const requiredAllowance = approvalAmount ?? requirements.amount;\n\n try {\n const allowance = (await capabilities.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requiredAllowance)) {\n return undefined;\n }\n } catch {\n // Allowance check failed, proceed with signing\n }\n\n const info = await signErc20ApprovalTransaction(\n {\n address: signer.address,\n signTransaction: capabilities.signTransaction,\n getTransactionCount: capabilities.getTransactionCount,\n estimateFeesPerGas: capabilities.estimateFeesPerGas,\n },\n tokenAddress,\n chainId,\n );\n\n return {\n [ERC20_APPROVAL_GAS_SPONSORING_KEY]: { info },\n };\n}\n","// EIP-3009 TransferWithAuthorization types for EIP-712 signing\nexport const authorizationTypes = {\n TransferWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n} as const;\n\n/**\n * Permit2 EIP-712 types for signing PermitWitnessTransferFrom (exact scheme).\n * Must match the exact format expected by the Permit2 contract.\n * Note: Types must be in ALPHABETICAL order after the primary type (TokenPermissions < Witness).\n */\nexport const permit2WitnessTypes = {\n PermitWitnessTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n { name: \"witness\", type: \"Witness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n Witness: [\n { name: \"to\", type: \"address\" },\n { name: \"validAfter\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * Permit2 EIP-712 types for signing PermitWitnessTransferFrom (upto scheme).\n * The upto witness includes a `facilitator` field that the exact witness does not.\n * This ensures only the authorized facilitator can settle the payment.\n * Must match: Witness(address to,address facilitator,uint256 validAfter)\n */\nexport const uptoPermit2WitnessTypes = {\n PermitWitnessTransferFrom: [\n { name: \"permitted\", type: \"TokenPermissions\" },\n { name: \"spender\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n { name: \"witness\", type: \"Witness\" },\n ],\n TokenPermissions: [\n { name: \"token\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n Witness: [\n { name: \"to\", type: \"address\" },\n { name: \"facilitator\", type: \"address\" },\n { name: \"validAfter\", type: \"uint256\" },\n ],\n} as const;\n\n// EIP3009 ABI for transferWithAuthorization function\nexport const eip3009ABI = [\n {\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n name: \"transferWithAuthorization\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"signature\", type: \"bytes\" },\n ],\n name: \"transferWithAuthorization\",\n outputs: [],\n stateMutability: \"nonpayable\",\n type: \"function\",\n },\n {\n inputs: [{ name: \"account\", type: \"address\" }],\n name: \"balanceOf\",\n outputs: [{ name: \"\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [],\n name: \"version\",\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [],\n name: \"name\",\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n {\n inputs: [\n { name: \"authorizer\", type: \"address\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n name: \"authorizationState\",\n outputs: [{ name: \"\", type: \"bool\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\n/**\n * EIP-2612 Permit EIP-712 types for signing token.permit().\n */\nexport const eip2612PermitTypes = {\n Permit: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"nonce\", type: \"uint256\" },\n { name: \"deadline\", type: \"uint256\" },\n ],\n} as const;\n\n/**\n * EIP-2612 nonces ABI for querying current nonce.\n */\nexport const eip2612NoncesAbi = [\n {\n type: \"function\",\n name: \"nonces\",\n inputs: [{ name: \"owner\", type: \"address\" }],\n outputs: [{ type: \"uint256\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/** ERC-20 approve(address,uint256) ABI for encoding/decoding approval calldata. */\nexport const erc20ApproveAbi = [\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\" },\n { name: \"amount\", type: \"uint256\" },\n ],\n outputs: [{ type: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n] as const;\n\n/** ERC-20 allowance(address,address) ABI for checking spender approval. */\nexport const erc20AllowanceAbi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\" },\n { name: \"spender\", type: \"address\" },\n ],\n outputs: [{ type: \"uint256\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/** Gas limit for a standard ERC-20 approve() transaction. */\nexport const ERC20_APPROVE_GAS_LIMIT = 70_000n;\n\n/** Fallback max fee per gas (1 gwei) when fee estimation fails. */\nexport const DEFAULT_MAX_FEE_PER_GAS = 1_000_000_000n;\n\n/** Fallback max priority fee per gas (0.1 gwei) when fee estimation fails. */\nexport const DEFAULT_MAX_PRIORITY_FEE_PER_GAS = 100_000_000n;\n\n/**\n * Canonical Permit2 contract address.\n * Same address on all EVM chains via CREATE2 deployment.\n *\n * @see https://github.com/Uniswap/permit2\n */\nexport const PERMIT2_ADDRESS = \"0x000000000022D473030F116dDEE9F6B43aC78BA3\" as const;\n\n/**\n * x402ExactPermit2Proxy contract address.\n * Vanity address: 0x4020...0001 for easy recognition.\n * This address is deterministic based on:\n * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C)\n * - Vanity-mined salt for prefix 0x4020 and suffix 0001\n * - Contract bytecode + constructor args (PERMIT2_ADDRESS)\n */\nexport const x402ExactPermit2ProxyAddress = \"0x402085c248EeA27D92E8b30b2C58ed07f9E20001\" as const;\n\n/**\n * x402UptoPermit2Proxy contract address.\n * Vanity address: 0x4020...0002 for easy recognition.\n * This address is deterministic based on:\n * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C)\n * - Vanity-mined salt for prefix 0x4020 and suffix 0002\n * - Contract bytecode + constructor args (PERMIT2_ADDRESS)\n */\nexport const x402UptoPermit2ProxyAddress = \"0x4020A4f3b7b90ccA423B9fabCc0CE57C6C240002\" as const;\n\n/**\n * ABI components for the exact Permit2 witness tuple: Witness(address to, uint256 validAfter).\n */\nconst permit2WitnessABIComponents = [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n] as const;\n\n/**\n * ABI components for the upto Permit2 witness tuple:\n * Witness(address to, address facilitator, uint256 validAfter).\n */\nconst uptoPermit2WitnessABIComponents = [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"facilitator\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n] as const;\n\n/**\n * x402UptoPermit2Proxy ABI — settle/settleWithPermit for the upto payment scheme.\n * Key differences from exact: settle() takes a `uint256 amount` parameter, and the\n * Witness struct includes an `address facilitator` field.\n */\nexport const x402UptoPermit2ProxyABI = [\n {\n type: \"function\",\n name: \"PERMIT2\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\", internalType: \"contract ISignatureTransfer\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPE_STRING\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.Witness\",\n components: uptoPermit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settleWithPermit\",\n inputs: [\n {\n name: \"permit2612\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.EIP2612Permit\",\n components: [\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"r\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"s\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"v\", type: \"uint8\", internalType: \"uint8\" },\n ],\n },\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402UptoPermit2Proxy.Witness\",\n components: uptoPermit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n { type: \"event\", name: \"Settled\", inputs: [], anonymous: false },\n { type: \"event\", name: \"SettledWithPermit\", inputs: [], anonymous: false },\n { type: \"error\", name: \"AmountExceedsPermitted\", inputs: [] },\n { type: \"error\", name: \"InvalidDestination\", inputs: [] },\n { type: \"error\", name: \"InvalidOwner\", inputs: [] },\n { type: \"error\", name: \"InvalidPermit2Address\", inputs: [] },\n { type: \"error\", name: \"PaymentTooEarly\", inputs: [] },\n { type: \"error\", name: \"Permit2612AmountMismatch\", inputs: [] },\n { type: \"error\", name: \"ReentrancyGuardReentrantCall\", inputs: [] },\n { type: \"error\", name: \"UnauthorizedFacilitator\", inputs: [] },\n] as const;\n\n/**\n * x402ExactPermit2Proxy ABI - settle function for exact payment scheme.\n */\nexport const x402ExactPermit2ProxyABI = [\n {\n type: \"function\",\n name: \"PERMIT2\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\", internalType: \"contract ISignatureTransfer\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPEHASH\",\n inputs: [],\n outputs: [{ name: \"\", type: \"bytes32\", internalType: \"bytes32\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"WITNESS_TYPE_STRING\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\", internalType: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"settle\",\n inputs: [\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.Witness\",\n components: permit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"settleWithPermit\",\n inputs: [\n {\n name: \"permit2612\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.EIP2612Permit\",\n components: [\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"r\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"s\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"v\", type: \"uint8\", internalType: \"uint8\" },\n ],\n },\n {\n name: \"permit\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.PermitTransferFrom\",\n components: [\n {\n name: \"permitted\",\n type: \"tuple\",\n internalType: \"struct ISignatureTransfer.TokenPermissions\",\n components: [\n { name: \"token\", type: \"address\", internalType: \"address\" },\n { name: \"amount\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"nonce\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"deadline\", type: \"uint256\", internalType: \"uint256\" },\n ],\n },\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n {\n name: \"witness\",\n type: \"tuple\",\n internalType: \"struct x402ExactPermit2Proxy.Witness\",\n components: permit2WitnessABIComponents,\n },\n { name: \"signature\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n { type: \"event\", name: \"Settled\", inputs: [], anonymous: false },\n { type: \"event\", name: \"SettledWithPermit\", inputs: [], anonymous: false },\n { type: \"error\", name: \"InvalidAmount\", inputs: [] },\n { type: \"error\", name: \"InvalidDestination\", inputs: [] },\n { type: \"error\", name: \"InvalidOwner\", inputs: [] },\n { type: \"error\", name: \"InvalidPermit2Address\", inputs: [] },\n { type: \"error\", name: \"PaymentTooEarly\", inputs: [] },\n { type: \"error\", name: \"Permit2612AmountMismatch\", inputs: [] },\n { type: \"error\", name: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { getAddress } from \"viem\";\nimport { eip2612PermitTypes, eip2612NoncesAbi, PERMIT2_ADDRESS } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport type { Eip2612GasSponsoringInfo } from \"../extensions\";\n\nexport type Eip2612PermitSigner = Pick<ClientEvmSigner, \"address\" | \"signTypedData\"> & {\n readContract: NonNullable<ClientEvmSigner[\"readContract\"]>;\n};\n\n/**\n * Signs an EIP-2612 permit authorizing the Permit2 contract to spend tokens.\n *\n * This creates a gasless off-chain signature that the facilitator can submit\n * on-chain via `x402Permit2Proxy.settleWithPermit()`.\n *\n * The `permittedAmount` must match the Permit2 `permitted.amount` exactly, as the\n * proxy contract enforces `permit2612.value == permittedAmount`.\n *\n * @param signer - The client EVM signer (must support readContract for nonce query)\n * @param tokenAddress - The ERC-20 token contract address\n * @param tokenName - The token name (from paymentRequirements.extra.name)\n * @param tokenVersion - The token version (from paymentRequirements.extra.version)\n * @param chainId - The chain ID\n * @param deadline - The deadline for the permit (unix timestamp as string)\n * @param permittedAmount - The Permit2 permitted amount (must match exactly)\n * @returns The EIP-2612 gas sponsoring info object\n */\nexport async function signEip2612Permit(\n signer: Eip2612PermitSigner,\n tokenAddress: `0x${string}`,\n tokenName: string,\n tokenVersion: string,\n chainId: number,\n deadline: string,\n permittedAmount: string,\n): Promise<Eip2612GasSponsoringInfo> {\n const owner = signer.address;\n const spender = getAddress(PERMIT2_ADDRESS);\n\n // Query the current EIP-2612 nonce from the token contract\n const nonce = (await signer.readContract({\n address: tokenAddress,\n abi: eip2612NoncesAbi,\n functionName: \"nonces\",\n args: [owner],\n })) as bigint;\n\n // Construct EIP-712 domain for the token's permit function\n const domain = {\n name: tokenName,\n version: tokenVersion,\n chainId,\n verifyingContract: tokenAddress,\n };\n\n const approvalAmount = BigInt(permittedAmount);\n\n const message = {\n owner,\n spender,\n value: approvalAmount,\n nonce,\n deadline: BigInt(deadline),\n };\n\n // Sign the EIP-2612 permit\n const signature = await signer.signTypedData({\n domain,\n types: eip2612PermitTypes,\n primaryType: \"Permit\",\n message,\n });\n\n return {\n from: owner,\n asset: tokenAddress,\n spender,\n amount: approvalAmount.toString(),\n nonce: nonce.toString(),\n deadline,\n signature,\n version: \"1\",\n };\n}\n","import { encodeFunctionData, getAddress, maxUint256 } from \"viem\";\nimport {\n PERMIT2_ADDRESS,\n erc20ApproveAbi,\n ERC20_APPROVE_GAS_LIMIT,\n DEFAULT_MAX_FEE_PER_GAS,\n DEFAULT_MAX_PRIORITY_FEE_PER_GAS,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport {\n ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n type Erc20ApprovalGasSponsoringInfo,\n} from \"../extensions\";\n\nexport type Erc20ApprovalTxSigner = Pick<ClientEvmSigner, \"address\"> & {\n signTransaction: NonNullable<ClientEvmSigner[\"signTransaction\"]>;\n getTransactionCount: NonNullable<ClientEvmSigner[\"getTransactionCount\"]>;\n estimateFeesPerGas?: NonNullable<ClientEvmSigner[\"estimateFeesPerGas\"]>;\n};\n\n/**\n * Signs an EIP-1559 `approve(Permit2, MaxUint256)` transaction for the given token.\n *\n * The signed transaction is NOT broadcast here — the facilitator broadcasts it\n * atomically before settling the Permit2 payment. This enables Permit2 payments\n * for generic ERC-20 tokens that do NOT implement EIP-2612.\n *\n * Always approves MaxUint256 regardless of the payment amount.\n *\n * @param signer - The client EVM signer (must support signTransaction, getTransactionCount)\n * @param tokenAddress - The ERC-20 token contract address\n * @param chainId - The chain ID\n * @returns The ERC-20 approval gas sponsoring info object\n */\nexport async function signErc20ApprovalTransaction(\n signer: Erc20ApprovalTxSigner,\n tokenAddress: `0x${string}`,\n chainId: number,\n): Promise<Erc20ApprovalGasSponsoringInfo> {\n const from = signer.address;\n const spender = getAddress(PERMIT2_ADDRESS);\n\n // Encode approve(PERMIT2_ADDRESS, MaxUint256) calldata\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [spender, maxUint256],\n });\n\n // Get current nonce for the sender\n const nonce = await signer.getTransactionCount({ address: from });\n\n // Get current fee estimates, with fallback values\n let maxFeePerGas: bigint;\n let maxPriorityFeePerGas: bigint;\n try {\n const fees = await signer.estimateFeesPerGas?.();\n if (!fees) {\n throw new Error(\"no fee estimates available\");\n }\n maxFeePerGas = fees.maxFeePerGas;\n maxPriorityFeePerGas = fees.maxPriorityFeePerGas;\n } catch {\n maxFeePerGas = DEFAULT_MAX_FEE_PER_GAS;\n maxPriorityFeePerGas = DEFAULT_MAX_PRIORITY_FEE_PER_GAS;\n }\n\n // Sign the EIP-1559 transaction (not broadcast)\n const signedTransaction = await signer.signTransaction({\n to: tokenAddress,\n data,\n nonce,\n gas: ERC20_APPROVE_GAS_LIMIT,\n maxFeePerGas,\n maxPriorityFeePerGas,\n chainId,\n });\n\n return {\n from,\n asset: tokenAddress,\n spender,\n amount: maxUint256.toString(),\n signedTransaction,\n version: ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n };\n}\n","import { createPublicClient, http } from \"viem\";\nimport type { ClientEvmSigner } from \"../signer\";\nimport { getEvmChainId } from \"../utils\";\n\nexport type EvmSchemeConfig = {\n rpcUrl?: string;\n};\n\nexport type EvmSchemeConfigByChainId = Record<number, EvmSchemeConfig>;\n\nexport type EvmSchemeOptions = EvmSchemeConfig | EvmSchemeConfigByChainId;\n\n/** @deprecated Use EvmSchemeConfig */\nexport type ExactEvmSchemeConfig = EvmSchemeConfig;\n/** @deprecated Use EvmSchemeConfigByChainId */\nexport type ExactEvmSchemeConfigByChainId = EvmSchemeConfigByChainId;\n/** @deprecated Use EvmSchemeOptions */\nexport type ExactEvmSchemeOptions = EvmSchemeOptions;\n\ntype ExtensionRpcCapabilities = Pick<\n ClientEvmSigner,\n \"readContract\" | \"signTransaction\" | \"getTransactionCount\" | \"estimateFeesPerGas\"\n>;\n\nconst rpcClientCache = new Map<string, ReturnType<typeof createPublicClient>>();\n\n/**\n * Check if options is a per-chain-id configuration map.\n *\n * @param options - The EVM scheme options to check\n * @returns True if the options are keyed by chain ID\n */\nfunction isConfigByChainId(options: EvmSchemeOptions): options is EvmSchemeConfigByChainId {\n const keys = Object.keys(options);\n return keys.length > 0 && keys.every(key => /^\\d+$/.test(key));\n}\n\n/**\n * Get or create a cached viem public client for the given RPC URL.\n *\n * @param rpcUrl - The JSON-RPC endpoint URL\n * @returns A viem PublicClient instance\n */\nfunction getRpcClient(rpcUrl: string): ReturnType<typeof createPublicClient> {\n const existing = rpcClientCache.get(rpcUrl);\n if (existing) {\n return existing;\n }\n\n const client = createPublicClient({\n transport: http(rpcUrl),\n });\n rpcClientCache.set(rpcUrl, client);\n return client;\n}\n\n/**\n * Resolve an RPC URL from scheme options for the given network.\n *\n * @param network - The CAIP-2 network identifier\n * @param options - Optional EVM scheme options (flat or per-chain-id)\n * @returns The resolved RPC URL, or undefined if not configured\n */\nexport function resolveRpcUrl(network: string, options?: EvmSchemeOptions): string | undefined {\n if (!options) {\n return undefined;\n }\n\n if (isConfigByChainId(options)) {\n const chainId = getEvmChainId(network);\n const optionsByChainId = options as EvmSchemeConfigByChainId;\n return optionsByChainId[chainId]?.rpcUrl;\n }\n\n return (options as EvmSchemeConfig).rpcUrl;\n}\n\n/**\n * Resolve RPC capabilities for extensions, backfilling from a public RPC client when the signer lacks them.\n *\n * @param network - The CAIP-2 network identifier\n * @param signer - The client EVM signer\n * @param options - Optional EVM scheme options for RPC URL resolution\n * @returns Extension RPC capabilities (readContract, signTransaction, etc.)\n */\nexport function resolveExtensionRpcCapabilities(\n network: string,\n signer: ClientEvmSigner,\n options?: EvmSchemeOptions,\n): ExtensionRpcCapabilities {\n const capabilities: ExtensionRpcCapabilities = {\n signTransaction: signer.signTransaction,\n readContract: signer.readContract,\n getTransactionCount: signer.getTransactionCount,\n estimateFeesPerGas: signer.estimateFeesPerGas,\n };\n\n const needsRpcBackfill =\n !capabilities.readContract ||\n !capabilities.getTransactionCount ||\n !capabilities.estimateFeesPerGas;\n if (!needsRpcBackfill) {\n return capabilities;\n }\n\n const rpcUrl = resolveRpcUrl(network, options);\n if (!rpcUrl) {\n return capabilities;\n }\n const rpcClient = getRpcClient(rpcUrl);\n if (!capabilities.readContract) {\n capabilities.readContract = args => rpcClient.readContract(args as never) as Promise<unknown>;\n }\n if (!capabilities.getTransactionCount) {\n capabilities.getTransactionCount = async args =>\n rpcClient.getTransactionCount({ address: args.address });\n }\n if (!capabilities.estimateFeesPerGas) {\n capabilities.estimateFeesPerGas = async () => rpcClient.estimateFeesPerGas();\n }\n\n return capabilities;\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@payai/x402/types\";\nimport { getAddress } from \"viem\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ChannelConfig, BatchSettlementDepositPayload } from \"../types\";\nimport { ERC3009_DEPOSIT_COLLECTOR_ADDRESS, receiveAuthorizationTypes } from \"../constants\";\nimport { createNonce, getEvmChainId } from \"../../utils\";\nimport { signVoucher } from \"./voucher\";\nimport { computeChannelId } from \"../utils\";\nimport { buildErc3009DepositNonce } from \"../encoding\";\n\n/**\n * Creates a deposit payload that bundles an ERC-3009 `receiveWithAuthorization` approval\n * together with a cumulative voucher signature.\n *\n * When the facilitator submits this payload onchain, the contract atomically transfers\n * tokens from the payer into the channel and records the initial voucher.\n *\n * @param signer - Client wallet used to sign the ERC-3009 authorization (`from` = payer).\n * @param x402Version - Protocol version to embed in the payload envelope.\n * @param paymentRequirements - Server-provided payment requirements (asset, network, amount, etc.).\n * @param channelConfig - Immutable channel configuration (payer, receiver, token, …).\n * @param depositAmount - Number of tokens (decimal string) to deposit into the channel.\n * @param maxClaimableAmount - Cumulative ceiling for the accompanying voucher.\n * @param voucherSigner - Optional key that signs the voucher; defaults to `signer` (same as payer).\n * @returns A {@link PaymentPayloadResult} containing the signed deposit + voucher payload.\n */\nexport async function createBatchSettlementEIP3009DepositPayload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n channelConfig: ChannelConfig,\n depositAmount: string,\n maxClaimableAmount: string,\n voucherSigner?: ClientEvmSigner,\n): Promise<PaymentPayloadResult> {\n const salt = createNonce();\n const now = Math.floor(Date.now() / 1000);\n const chainId = getEvmChainId(paymentRequirements.network);\n\n if (!paymentRequirements.extra?.name || !paymentRequirements.extra?.version) {\n throw new Error(\n `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${paymentRequirements.asset}`,\n );\n }\n\n const { name, version } = paymentRequirements.extra;\n\n const channelId = computeChannelId(channelConfig, paymentRequirements.network);\n\n const erc3009Nonce = buildErc3009DepositNonce(channelId, salt);\n\n const signature = await signer.signTypedData({\n domain: {\n name,\n version,\n chainId,\n verifyingContract: getAddress(paymentRequirements.asset),\n },\n types: receiveAuthorizationTypes,\n primaryType: \"ReceiveWithAuthorization\",\n message: {\n from: getAddress(signer.address),\n to: getAddress(ERC3009_DEPOSIT_COLLECTOR_ADDRESS),\n value: BigInt(depositAmount),\n validAfter: BigInt(now - 600),\n validBefore: BigInt(now + paymentRequirements.maxTimeoutSeconds),\n nonce: erc3009Nonce,\n },\n });\n\n const vSigner = voucherSigner ?? signer;\n const voucher = await signVoucher(\n vSigner,\n channelId,\n maxClaimableAmount,\n paymentRequirements.network,\n );\n\n const payload: BatchSettlementDepositPayload = {\n type: \"deposit\",\n channelConfig,\n voucher,\n deposit: {\n amount: depositAmount,\n authorization: {\n erc3009Authorization: {\n validAfter: (now - 600).toString(),\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n salt,\n signature,\n },\n },\n },\n };\n\n return {\n x402Version,\n payload,\n };\n}\n","import { ClientEvmSigner } from \"../../signer\";\nimport { voucherTypes } from \"../constants\";\nimport { BatchSettlementVoucherFields } from \"../types\";\nimport { getEvmChainId } from \"../../utils\";\nimport { getBatchSettlementEip712Domain } from \"../utils\";\n\n/**\n * Signs a cumulative voucher using the client's wallet.\n *\n * The voucher authorises the receiver to claim up to `maxClaimableAmount` from the\n * channel identified by `channelId`. The signature covers the EIP-712 `Voucher` struct\n * under the batched domain.\n *\n * @param signer - Client wallet used to produce the EIP-712 signature.\n * @param channelId - Identifier of the payment channel. This is the EIP-712\n * hash of the `ChannelConfig` typed data for the batch settlement domain; see\n * `computeChannelId`.\n * @param maxClaimableAmount - Cumulative ceiling the receiver may claim (decimal string in token units).\n * @param network - CAIP-2 network identifier (e.g. `eip155:84532`).\n * @returns Signed voucher fields ready to be included in a payment payload.\n */\nexport async function signVoucher(\n signer: ClientEvmSigner,\n channelId: `0x${string}`,\n maxClaimableAmount: string,\n network: string,\n): Promise<BatchSettlementVoucherFields> {\n const chainId = getEvmChainId(network);\n\n const signature = await signer.signTypedData({\n domain: getBatchSettlementEip712Domain(chainId),\n types: voucherTypes,\n primaryType: \"Voucher\",\n message: {\n channelId,\n maxClaimableAmount: BigInt(maxClaimableAmount),\n },\n });\n\n return {\n channelId,\n maxClaimableAmount,\n signature,\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 { PaymentRequirements, PaymentPayloadResult } from \"@payai/x402/types\";\nimport { getAddress } from \"viem\";\nimport { PERMIT2_ADDRESS } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { createPermit2Nonce, getEvmChainId } from \"../../utils\";\nimport { PERMIT2_DEPOSIT_COLLECTOR_ADDRESS, batchPermit2WitnessTypes } from \"../constants\";\nimport { ChannelConfig, BatchSettlementDepositPayload } from \"../types\";\nimport { computeChannelId } from \"../utils\";\nimport { signVoucher } from \"./voucher\";\n\n/**\n * Builds a batch deposit payload using a channel-bound Permit2 witness transfer.\n *\n * @param signer - Payer signer for the Permit2 authorization.\n * @param x402Version - Protocol version for the payment envelope.\n * @param paymentRequirements - Server-provided payment requirements.\n * @param channelConfig - Channel configuration bound into the voucher and witness.\n * @param depositAmount - Token amount deposited into the channel.\n * @param maxClaimableAmount - Cumulative amount signed in the voucher.\n * @param voucherSigner - Optional signer for the voucher.\n * @returns Signed deposit payload and voucher.\n */\nexport async function createBatchSettlementPermit2DepositPayload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n channelConfig: ChannelConfig,\n depositAmount: string,\n maxClaimableAmount: string,\n voucherSigner?: ClientEvmSigner,\n): Promise<PaymentPayloadResult> {\n const chainId = getEvmChainId(paymentRequirements.network);\n const nonce = createPermit2Nonce();\n const deadline = Math.floor(Date.now() / 1000 + paymentRequirements.maxTimeoutSeconds).toString();\n const channelId = computeChannelId(channelConfig, paymentRequirements.network);\n\n const permit2Authorization = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: depositAmount,\n },\n spender: getAddress(PERMIT2_DEPOSIT_COLLECTOR_ADDRESS),\n nonce,\n deadline,\n witness: {\n channelId,\n },\n };\n\n const signature = await signer.signTypedData({\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: batchPermit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message: {\n permitted: {\n token: permit2Authorization.permitted.token,\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: permit2Authorization.spender,\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n channelId,\n },\n },\n });\n\n const voucher = await signVoucher(\n voucherSigner ?? signer,\n channelId,\n maxClaimableAmount,\n paymentRequirements.network,\n );\n\n const payload: BatchSettlementDepositPayload = {\n type: \"deposit\",\n channelConfig,\n voucher,\n deposit: {\n amount: depositAmount,\n authorization: {\n permit2Authorization: {\n ...permit2Authorization,\n signature,\n },\n },\n },\n };\n\n return { x402Version, payload };\n}\n","/**\n * Client-side channel fields mirrored from PAYMENT-RESPONSE / recovery flows.\n */\nexport interface BatchSettlementClientContext {\n /** Current cumulative amount charged by the server for this channel */\n chargedCumulativeAmount?: string;\n /** Current onchain channel balance */\n balance?: string;\n /** Total claimed onchain */\n totalClaimed?: string;\n /** Latest client-signed maxClaimableAmount cap (after corrective recovery, optional) */\n signedMaxClaimable?: string;\n /** Client voucher signature for {@link signedMaxClaimable} (optional) */\n signature?: `0x${string}`;\n}\n\nexport interface ClientChannelStorage {\n get(key: string): Promise<BatchSettlementClientContext | undefined>;\n set(key: string, context: BatchSettlementClientContext): Promise<void>;\n delete(key: string): Promise<void>;\n}\n\n/**\n * Default in-memory {@link ClientChannelStorage} (channel records do not survive process restart).\n */\nexport class InMemoryClientChannelStorage implements ClientChannelStorage {\n private readonly channels = new Map<string, BatchSettlementClientContext>();\n\n /**\n * Returns the channel record for `key` if present.\n *\n * @param key - Channel storage key (channelId).\n * @returns Persisted context or undefined.\n */\n async get(key: string): Promise<BatchSettlementClientContext | undefined> {\n return this.channels.get(key);\n }\n\n /**\n * Stores or replaces the channel record for `key`.\n *\n * @param key - Channel storage key.\n * @param context - Channel fields to persist.\n * @returns Resolves when stored.\n */\n async set(key: string, context: BatchSettlementClientContext): Promise<void> {\n this.channels.set(key, context);\n }\n\n /**\n * Removes the channel record for `key` if it exists.\n *\n * @param key - Channel storage key.\n * @returns Resolves when removed.\n */\n async delete(key: string): Promise<void> {\n this.channels.delete(key);\n }\n}\n","import type { PaymentRequirements } from \"@payai/x402/types\";\nimport type { ClientEvmSigner } from \"../../signer\";\nimport type { EvmSchemeOptions } from \"../../shared/rpc\";\nimport type { ChannelConfig } from \"../types\";\nimport { type ClientChannelStorage, InMemoryClientChannelStorage } from \"./storage\";\nimport type { BatchSettlementClientContext } from \"./storage\";\n\nconst DEFAULT_SALT =\n \"0x0000000000000000000000000000000000000000000000000000000000000000\" as `0x${string}`;\n\n/**\n * Caller-tunable policy controlling how the client sizes channel deposits.\n */\nexport interface BatchSettlementDepositPolicy {\n depositMultiplier?: number;\n}\n\n/**\n * Return shape for custom deposit sizing.\n */\nexport type BatchSettlementDepositStrategyResult = string | bigint | false | undefined;\n\n/**\n * Information supplied before the client signs a deposit authorization.\n */\nexport interface BatchSettlementDepositStrategyContext {\n paymentRequirements: PaymentRequirements;\n channelConfig: ChannelConfig;\n channelId: `0x${string}`;\n clientContext: BatchSettlementClientContext;\n requestAmount: string;\n maxClaimableAmount: string;\n currentBalance: string;\n minimumDepositAmount: string;\n depositAmount: string;\n}\n\n/**\n * Custom deposit sizing callback for initial deposits and top-ups.\n */\nexport type BatchSettlementDepositStrategy = (\n context: BatchSettlementDepositStrategyContext,\n) => BatchSettlementDepositStrategyResult | Promise<BatchSettlementDepositStrategyResult>;\n\n/**\n * Full options object accepted by `BatchSettlementEvmScheme`. Either this or a\n * bare {@link BatchSettlementDepositPolicy} can be passed as the second\n * constructor argument.\n */\nexport interface BatchSettlementEvmSchemeOptions {\n depositPolicy?: BatchSettlementDepositPolicy;\n /** Optional callback for app-specific deposit sizing or skipping. */\n depositStrategy?: BatchSettlementDepositStrategy;\n storage?: ClientChannelStorage;\n salt?: `0x${string}`;\n payerAuthorizer?: `0x${string}`;\n rpcUrl?: string;\n /** When set, EIP-712 vouchers are signed with this key; deposits still use the main `signer`. */\n voucherSigner?: ClientEvmSigner;\n}\n\n/**\n * Resolved options after merging defaults — used internally by the scheme,\n * recovery, and refund modules.\n */\nexport interface ResolvedClientOptions {\n depositPolicy?: BatchSettlementDepositPolicy;\n depositStrategy?: BatchSettlementDepositStrategy;\n storage: ClientChannelStorage;\n salt: `0x${string}`;\n payerAuthorizer?: `0x${string}`;\n voucherSigner?: ClientEvmSigner;\n extensionRpcOptions?: EvmSchemeOptions;\n}\n\n/**\n * Discriminates a full options object from a bare deposit-policy object.\n *\n * @param o - Constructor argument that may be options, deposit policy only, or undefined.\n * @returns `true` when `o` is a {@link BatchSettlementEvmSchemeOptions} object.\n */\nexport function isBatchSettlementEvmSchemeOptions(\n o: BatchSettlementEvmSchemeOptions | BatchSettlementDepositPolicy | undefined,\n): o is BatchSettlementEvmSchemeOptions {\n return (\n o !== undefined &&\n typeof o === \"object\" &&\n (\"storage\" in o ||\n \"depositPolicy\" in o ||\n \"depositStrategy\" in o ||\n \"salt\" in o ||\n \"payerAuthorizer\" in o ||\n \"rpcUrl\" in o ||\n \"voucherSigner\" in o)\n );\n}\n\n/**\n * Normalises the constructor's second argument into a uniform options shape.\n *\n * @param second - Optional second constructor argument (options or deposit policy).\n * @returns Resolved storage, salt, deposit policy, and optional payer authorizer.\n */\nexport function resolveClientOptions(\n second?: BatchSettlementEvmSchemeOptions | BatchSettlementDepositPolicy,\n): ResolvedClientOptions {\n if (second === undefined) {\n return { storage: new InMemoryClientChannelStorage(), salt: DEFAULT_SALT };\n }\n if (isBatchSettlementEvmSchemeOptions(second)) {\n return {\n storage: second.storage ?? new InMemoryClientChannelStorage(),\n depositPolicy: second.depositPolicy,\n depositStrategy: second.depositStrategy,\n salt: second.salt ?? DEFAULT_SALT,\n payerAuthorizer: second.payerAuthorizer,\n voucherSigner: second.voucherSigner,\n extensionRpcOptions: second.rpcUrl ? { rpcUrl: second.rpcUrl } : undefined,\n };\n }\n return {\n storage: new InMemoryClientChannelStorage(),\n depositPolicy: second,\n salt: DEFAULT_SALT,\n };\n}\n\n/**\n * Validates a {@link BatchSettlementDepositPolicy}, throwing on invalid fields.\n *\n * @param policy - The policy to validate (no-op when undefined).\n */\nexport function validateDepositPolicy(policy: BatchSettlementDepositPolicy | undefined): void {\n if (!policy) return;\n\n const m = policy.depositMultiplier;\n if (m !== undefined && (!Number.isInteger(m) || m < 3)) {\n throw new Error(\"depositMultiplier must be an integer >= 3\");\n }\n}\n\n/**\n * Computes the deposit amount based on the deposit multiplier.\n *\n * @param policy - Deposit policy controlling multiplier (may be undefined).\n * @param requestAmount - Amount requested for this operation, in token base units.\n * @returns Deposit amount string in token base units.\n */\nexport function depositAmountForRequest(\n policy: BatchSettlementDepositPolicy | undefined,\n requestAmount: bigint,\n): string {\n const mult = BigInt(policy?.depositMultiplier ?? 5);\n return (mult * requestAmount).toString();\n}\n","import { decodePaymentRequiredHeader, decodePaymentResponseHeader } from \"@payai/x402/http\";\nimport { x402Client, x402HTTPClient } from \"@payai/x402/client\";\nimport type {\n PaymentPayload,\n PaymentRequired,\n PaymentRequirements,\n SettleResponse,\n} from \"@payai/x402/types\";\nimport { BATCH_SETTLEMENT_SCHEME } from \"../constants\";\nimport * as Errors from \"../errors\";\nimport type {\n BatchSettlementPaymentRequirementsExtra,\n BatchSettlementRefundPayload,\n} from \"../types\";\nimport { computeChannelId } from \"../utils\";\nimport { type BatchSettlementClientDeps, buildChannelConfig, recoverChannel } from \"./channel\";\nimport { createBatchSettlementClientHooks } from \"./hooks\";\nimport { signVoucher } from \"./voucher\";\n\n/**\n * Refund-specific server errors that the client cannot recover from automatically.\n * Seeing any of these means the user should adjust their request (or accept that the\n * channel has nothing left to refund) — retrying will not help.\n */\nconst NON_RECOVERABLE_REFUND_ERRORS: ReadonlySet<string> = new Set([\n Errors.ErrRefundNoBalance,\n Errors.ErrRefundAmountInvalid,\n]);\n\ninterface RefundRequirementsProbe {\n paymentRequired: PaymentRequired;\n requirements: PaymentRequirements;\n}\n\n/**\n * Caller-facing options for {@link refundChannel}.\n */\nexport interface RefundOptions {\n /** Token base units to refund; omit for a full refund (drains remaining balance). */\n amount?: string;\n /** Custom fetch implementation (defaults to `globalThis.fetch`). */\n fetch?: typeof fetch;\n}\n\n/**\n * Sends a cooperative refund request to the channel that backs `url`.\n *\n * Flow:\n * 1. Probe the URL with `GET` (no payment) to obtain the route's payment requirements.\n * 2. Build the `ChannelConfig` and resolve the local session (or recover it).\n * 3. Sign a zero-charge refund voucher (`maxClaimableAmount = chargedCumulativeAmount`).\n * 4. Send the voucher via `PAYMENT-SIGNATURE`. On a corrective 402, run the\n * standard recovery path and retry once.\n * 5. Return the parsed `SettleResponse` from the server.\n *\n * @param ctx - Identity inputs (storage, signers, salt, payerAuthorizer).\n * @param url - Any protected route on the channel to refund (the resource handler is bypassed).\n * @param options - Optional `amount` (partial refund) and `fetch` override.\n * @returns The settle response describing the refund outcome.\n * @throws When the probe fails, the receiver lacks an authorizer, or recovery fails.\n */\nexport async function refundChannel(\n ctx: BatchSettlementClientDeps,\n url: string,\n options?: RefundOptions,\n): Promise<SettleResponse> {\n const fetchImpl = options?.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new Error(\"refund requires a fetch implementation (globalThis.fetch unavailable)\");\n }\n\n const refundAmount = normalizeRefundAmount(options?.amount);\n const probe = await probeRefundRequirements(url, fetchImpl);\n return executeRefund(ctx, url, probe, refundAmount, fetchImpl);\n}\n\n/**\n * Probes a URL with an unauthenticated GET to retrieve batch-settlement payment\n * requirements via the 402 PAYMENT-REQUIRED header.\n *\n * @param url - The protected URL to probe.\n * @param fetchImpl - Fetch implementation used for the probe.\n * @returns Matching batch-settlement payment requirements for the route.\n */\nasync function probeRefundRequirements(\n url: string,\n fetchImpl: typeof fetch,\n): Promise<RefundRequirementsProbe> {\n const probe = await fetchImpl(url, { method: \"GET\" });\n if (probe.status !== 402) {\n throw new Error(`Refund probe expected 402, got ${probe.status}`);\n }\n\n const header = probe.headers.get(\"PAYMENT-REQUIRED\");\n if (!header) {\n throw new Error(\"Refund probe response missing PAYMENT-REQUIRED header\");\n }\n\n const paymentRequired = decodePaymentRequiredHeader(header);\n const requirements = paymentRequired.accepts.find(a => a.scheme === BATCH_SETTLEMENT_SCHEME);\n if (!requirements) {\n throw new Error(`No ${BATCH_SETTLEMENT_SCHEME} payment option at ${url}`);\n }\n\n const extra = requirements.extra as Partial<BatchSettlementPaymentRequirementsExtra> | undefined;\n if (!extra?.receiverAuthorizer) {\n throw new Error(\"Refund requires a configured receiverAuthorizer on the receiver\");\n }\n\n return { paymentRequired, requirements };\n}\n\n/**\n * Builds and submits the refund voucher, retrying once after a corrective 402.\n *\n * @param ctx - Identity inputs (storage, signers, salt, payerAuthorizer).\n * @param url - The protected URL to send the refund voucher to.\n * @param probe - Resolved payment requirements and probe metadata for this channel.\n * @param refundAmount - Optional partial refund amount in token base units.\n * @param fetchImpl - Fetch implementation used for the request.\n * @returns The parsed settle response.\n */\nasync function executeRefund(\n ctx: BatchSettlementClientDeps,\n url: string,\n probe: RefundRequirementsProbe,\n refundAmount: string | undefined,\n fetchImpl: typeof fetch,\n): Promise<SettleResponse> {\n const maxAttempts = 2;\n const { paymentRequired, requirements } = probe;\n const httpClient = createRefundHttpClient(ctx, requirements);\n\n for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {\n const paymentPayload = await buildRefundPaymentPayload(\n ctx,\n paymentRequired,\n requirements,\n refundAmount,\n );\n const headers = httpClient.encodePaymentSignatureHeader(paymentPayload);\n\n const response = await fetchImpl(url, { method: \"GET\", headers });\n\n if (response.status === 402) {\n const nonRecoverable = getNonRecoverableRefundFailure(response);\n if (nonRecoverable) {\n throw new Error(nonRecoverable);\n }\n }\n\n const result = await httpClient.processPaymentResult(\n paymentPayload,\n name => response.headers.get(name),\n response.status,\n );\n\n if (response.status === 402) {\n if (result.recovered && attempt < maxAttempts) {\n continue;\n }\n if (result.recovered) {\n throw new Error(`Refund failed: server returned 402 after ${attempt} attempt(s)`);\n }\n\n const corrective = getRefundPaymentRequired(response);\n throw new Error(`Refund failed: ${corrective.error ?? \"unknown\"}`);\n }\n\n if (!result.settleResponse) {\n throw new Error(\n `Refund response missing PAYMENT-RESPONSE header (status ${response.status})`,\n );\n }\n\n return result.settleResponse;\n }\n\n throw new Error(\"Refund failed: retry budget exhausted\");\n}\n\n/**\n * Builds the refund payload with a zero-charge `maxClaimableAmount`.\n *\n * @param ctx - Identity inputs (storage, signers, salt, payerAuthorizer).\n * @param paymentRequired - Decoded 402 body from the probe (resource, extensions, etc.).\n * @param requirements - Resolved payment requirements for the channel.\n * @param refundAmount - Optional partial refund amount in token base units.\n * @returns A full payment payload wrapping the signed refund request.\n */\nasync function buildRefundPaymentPayload(\n ctx: BatchSettlementClientDeps,\n paymentRequired: PaymentRequired,\n requirements: PaymentRequirements,\n refundAmount: string | undefined,\n): Promise<PaymentPayload> {\n const config = buildChannelConfig(ctx, requirements);\n const channelId = computeChannelId(config, requirements.network);\n const key = channelId.toLowerCase();\n\n let channel = await ctx.storage.get(key);\n if (channel === undefined && ctx.signer.readContract) {\n channel = await recoverChannel(ctx, requirements);\n }\n if (channel === undefined) {\n throw new Error(\n \"Refund requires an existing channel record; deposit first or call from a context with an EVM RPC\",\n );\n }\n\n // Avoid a refund request when local state shows the channel has no refundable balance.\n const charged = channel.chargedCumulativeAmount ?? \"0\";\n if (channel.balance !== undefined && BigInt(channel.balance) <= BigInt(charged)) {\n throw new Error(\n `Refund failed: channel has no remaining balance (balance=${channel.balance}, chargedCumulativeAmount=${charged})`,\n );\n }\n\n const voucherSigner = ctx.voucherSigner ?? ctx.signer;\n const voucher = await signVoucher(voucherSigner, channelId, charged, requirements.network);\n\n const payload: BatchSettlementRefundPayload = {\n type: \"refund\",\n channelConfig: config,\n voucher,\n ...(refundAmount !== undefined ? { amount: refundAmount } : {}),\n };\n\n return {\n x402Version: 2,\n accepted: requirements,\n payload: payload as unknown as Record<string, unknown>,\n ...(paymentRequired.resource ? { resource: paymentRequired.resource } : {}),\n ...(paymentRequired.extensions ? { extensions: paymentRequired.extensions } : {}),\n };\n}\n\n/**\n * Creates an x402 HTTP client for batch settlement with hooks; refund payloads are supplied\n * by {@link refundChannel} instead of the default payment builder.\n *\n * @param ctx - Identity inputs (storage, signers, salt, payerAuthorizer).\n * @param requirements - Resolved payment requirements for the channel network.\n * @returns An `x402HTTPClient` wired for batch-settlement scheme hooks.\n */\nfunction createRefundHttpClient(\n ctx: BatchSettlementClientDeps,\n requirements: PaymentRequirements,\n): x402HTTPClient {\n const client = new x402Client().register(requirements.network, {\n scheme: BATCH_SETTLEMENT_SCHEME,\n schemeHooks: createBatchSettlementClientHooks(ctx),\n createPaymentPayload: async () => {\n throw new Error(\"Refund payloads are built by refundChannel\");\n },\n });\n return new x402HTTPClient(client);\n}\n\n/**\n * If the refund HTTP response cannot be recovered by retrying, returns a user-facing message;\n * otherwise returns `undefined`.\n *\n * @param response - The refund request response (402 with headers or settle failure).\n * @returns A formatted failure string, or `undefined` when retry may succeed.\n */\nfunction getNonRecoverableRefundFailure(response: Response): string | undefined {\n const settleHeader = response.headers.get(\"PAYMENT-RESPONSE\");\n if (settleHeader) {\n return formatRefundFailure(decodePaymentResponseHeader(settleHeader));\n }\n\n const paymentRequired = getRefundPaymentRequired(response);\n const errorCode = paymentRequired.error;\n if (errorCode && NON_RECOVERABLE_REFUND_ERRORS.has(errorCode)) {\n return `Refund failed: ${errorCode}`;\n }\n}\n\n/**\n * Reads and decodes the `PAYMENT-REQUIRED` header from a refund-related 402 response.\n *\n * @param response - HTTP response that must include `PAYMENT-REQUIRED`.\n * @returns The decoded {@link PaymentRequired} payload.\n * @throws When the header is missing.\n */\nfunction getRefundPaymentRequired(response: Response): PaymentRequired {\n const requiredHeader = response.headers.get(\"PAYMENT-REQUIRED\");\n if (!requiredHeader) {\n throw new Error(\"Refund 402 missing PAYMENT-REQUIRED header\");\n }\n return decodePaymentRequiredHeader(requiredHeader);\n}\n\n/**\n * Builds a human-readable error message from a settle failure response.\n *\n * @param settle - The decoded SettleResponse from the server's 402 reply.\n * @returns A formatted error string suitable for `throw new Error(...)`.\n */\nfunction formatRefundFailure(settle: SettleResponse): string {\n const reason = settle.errorReason ?? \"unknown_settlement_error\";\n const message = settle.errorMessage;\n if (message && message !== reason) {\n return `Refund failed: ${reason}: ${message}`;\n }\n return `Refund failed: ${reason}`;\n}\n\n/**\n * Validates and normalises the optional `refundAmount` argument.\n *\n * @param amount - Raw amount from caller (string of base units).\n * @returns The same string when valid, or `undefined` when omitted.\n */\nfunction normalizeRefundAmount(amount: string | undefined): string | undefined {\n if (amount === undefined) return undefined;\n if (!/^\\d+$/.test(amount) || amount === \"0\") {\n throw new Error(`Invalid refund amount \"${amount}\": must be a positive integer string`);\n }\n return amount;\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 { decodePaymentResponseHeader } from \"@payai/x402/http\";\nimport type { PaymentRequirements, SettleResponse } from \"@payai/x402/types\";\nimport { getAddress } from \"viem\";\nimport type { ClientEvmSigner } from \"../../signer\";\nimport { batchSettlementABI } from \"../abi\";\nimport { BATCH_SETTLEMENT_ADDRESS, MIN_WITHDRAW_DELAY } from \"../constants\";\nimport type {\n BatchSettlementPaymentRequirementsExtra,\n BatchSettlementPaymentResponseExtra,\n ChannelConfig,\n} from \"../types\";\nimport { computeChannelId } from \"../utils\";\nimport type { BatchSettlementClientContext, ClientChannelStorage } from \"./storage\";\n\ntype ResponseChannelState = NonNullable<BatchSettlementPaymentResponseExtra[\"channelState\"]>;\n\n/**\n * Reads the nested channel state from a settlement response extra object.\n *\n * @param extra - Settlement response extra fields.\n * @returns Channel state fields, or undefined when absent.\n */\nfunction readResponseChannelState(\n extra: Record<string, unknown>,\n): ResponseChannelState | undefined {\n const channelState = extra.channelState;\n if (typeof channelState !== \"object\" || channelState === null) {\n return undefined;\n }\n return channelState as ResponseChannelState;\n}\n\n/**\n * Runtime dependency bag shared by every storage-bound client helper (channel,\n * recovery, refund) and the {@link BatchSettlementEvmScheme} class.\n */\nexport interface BatchSettlementClientDeps {\n signer: ClientEvmSigner;\n storage: ClientChannelStorage;\n salt: `0x${string}`;\n payerAuthorizer?: `0x${string}`;\n voucherSigner?: ClientEvmSigner;\n}\n\n/**\n * Constructs the immutable {@link ChannelConfig} from payment requirements and\n * a client deps bag (signer, salt, optional payerAuthorizer / voucherSigner).\n *\n * @param deps - Client identity inputs.\n * @param paymentRequirements - Server payment requirements providing receiver, asset, and extra fields.\n * @returns The ChannelConfig that uniquely identifies this payment channel.\n */\nexport function buildChannelConfig(\n deps: BatchSettlementClientDeps,\n paymentRequirements: PaymentRequirements,\n): ChannelConfig {\n const extra = paymentRequirements.extra as\n | Partial<BatchSettlementPaymentRequirementsExtra>\n | undefined;\n const receiverAuthorizer = extra?.receiverAuthorizer;\n if (\n !receiverAuthorizer ||\n getAddress(receiverAuthorizer) === \"0x0000000000000000000000000000000000000000\"\n ) {\n throw new Error(\"Payment requirements must include a non-zero extra.receiverAuthorizer\");\n }\n\n return {\n payer: deps.signer.address,\n payerAuthorizer: getAddress(\n deps.payerAuthorizer ?? deps.voucherSigner?.address ?? deps.signer.address,\n ),\n receiver: paymentRequirements.payTo as `0x${string}`,\n receiverAuthorizer: getAddress(receiverAuthorizer),\n token: paymentRequirements.asset as `0x${string}`,\n withdrawDelay:\n typeof extra?.withdrawDelay === \"number\" ? extra.withdrawDelay : MIN_WITHDRAW_DELAY,\n salt: deps.salt,\n };\n}\n\n/**\n * Updates local channel state from a parsed `SettleResponse`.\n *\n * @param storage - Client channel storage.\n * @param settle - The parsed settle response.\n */\nexport async function processSettleResponse(\n storage: ClientChannelStorage,\n settle: SettleResponse,\n): Promise<void> {\n const extra = settle.extra ?? {};\n const channelState = readResponseChannelState(extra);\n if (!channelState) return;\n\n const channelId = channelState.channelId;\n const key = channelId.toLowerCase();\n\n const prev = await storage.get(key);\n const next: BatchSettlementClientContext = { ...(prev ?? {}) };\n\n if (channelState.chargedCumulativeAmount !== undefined) {\n next.chargedCumulativeAmount = String(channelState.chargedCumulativeAmount);\n }\n if (channelState.balance !== undefined) {\n next.balance = String(channelState.balance);\n }\n if (channelState.totalClaimed !== undefined) {\n next.totalClaimed = String(channelState.totalClaimed);\n }\n\n await storage.set(key, next);\n}\n\n/**\n * Reconciles local channel state with the outcome of a cooperative refund.\n *\n * Deletes the channel record when the post-refund balance is zero (full refund),\n * otherwise updates local state from the server snapshot.\n *\n * @param storage - Client channel storage.\n * @param channelKey - Lowercased channel id used as the storage key.\n * @param settleExtra - The `extra` block from the refund settle response.\n */\nexport async function updateChannelAfterRefund(\n storage: ClientChannelStorage,\n channelKey: string,\n settleExtra: Record<string, unknown>,\n): Promise<void> {\n const channelState = readResponseChannelState(settleExtra);\n if (!channelState) {\n await storage.delete(channelKey);\n return;\n }\n\n const balanceAfter =\n channelState.balance !== undefined ? BigInt(String(channelState.balance)) : undefined;\n\n if (balanceAfter === undefined || balanceAfter <= 0n) {\n await storage.delete(channelKey);\n return;\n }\n\n const prev = await storage.get(channelKey);\n const next: BatchSettlementClientContext = { ...(prev ?? {}) };\n next.balance = balanceAfter.toString();\n if (channelState.chargedCumulativeAmount !== undefined) {\n next.chargedCumulativeAmount = String(channelState.chargedCumulativeAmount);\n }\n if (channelState.totalClaimed !== undefined) {\n next.totalClaimed = String(channelState.totalClaimed);\n }\n await storage.set(channelKey, next);\n}\n\n/**\n * Processes the `PAYMENT-RESPONSE` header after a successful request.\n *\n * Decodes the header into a `SettleResponse` and delegates to\n * {@link processSettleResponse}.\n *\n * @param storage - Client channel storage.\n * @param getHeader - Function to retrieve a response header by name.\n */\nexport async function processPaymentResponse(\n storage: ClientChannelStorage,\n getHeader: (name: string) => string | null | undefined,\n): Promise<void> {\n const raw = getHeader(\"PAYMENT-RESPONSE\");\n if (!raw) return;\n\n const settle = decodePaymentResponseHeader(raw);\n await processSettleResponse(storage, settle);\n}\n\n/**\n * Recovers a channel record from onchain state (useful after a cold start or\n * channel record loss).\n *\n * @param deps - Signer + storage + identity inputs.\n * @param paymentRequirements - Server payment requirements used to derive the ChannelConfig.\n * @returns The recovered client context.\n */\nexport async function recoverChannel(\n deps: BatchSettlementClientDeps,\n paymentRequirements: PaymentRequirements,\n): Promise<BatchSettlementClientContext> {\n if (!deps.signer.readContract) {\n throw new Error(\"recoverChannel requires ClientEvmSigner.readContract\");\n }\n\n const config = buildChannelConfig(deps, paymentRequirements);\n const channelId = computeChannelId(config, paymentRequirements.network);\n\n const [chBalance, chTotalClaimed] = await readChannelBalanceAndTotalClaimed(\n deps.signer,\n channelId,\n );\n\n const ctx: BatchSettlementClientContext = {\n chargedCumulativeAmount: chTotalClaimed.toString(),\n balance: chBalance.toString(),\n totalClaimed: chTotalClaimed.toString(),\n };\n\n await deps.storage.set(channelId.toLowerCase(), ctx);\n return ctx;\n}\n\n/**\n * Reads `channels(channelId)` returning `[balance, totalClaimed]`.\n *\n * @param signer - Signer providing `readContract`.\n * @param channelId - The `bytes32` channel id to query.\n * @returns Tuple of `[balance, totalClaimed]` as bigints.\n */\nexport async function readChannelBalanceAndTotalClaimed(\n signer: ClientEvmSigner,\n channelId: `0x${string}`,\n): Promise<[bigint, bigint]> {\n if (!signer.readContract) {\n throw new Error(\"readChannelBalanceAndTotalClaimed requires ClientEvmSigner.readContract\");\n }\n return (await signer.readContract({\n address: BATCH_SETTLEMENT_ADDRESS,\n abi: batchSettlementABI,\n functionName: \"channels\",\n args: [channelId],\n })) as [bigint, bigint];\n}\n\n/**\n * Returns whether a local channel record exists for the given channel.\n *\n * @param storage - Client channel storage.\n * @param channelId - The channel identifier to check.\n * @returns `true` when a channel record is stored.\n */\nexport async function hasChannel(\n storage: ClientChannelStorage,\n channelId: string,\n): Promise<boolean> {\n const channel = await storage.get(channelId.toLowerCase());\n return channel !== undefined;\n}\n\n/**\n * Returns the local channel context for a channel, if present.\n *\n * @param storage - Client channel storage.\n * @param channelId - The channel identifier.\n * @returns Stored context or `undefined`.\n */\nexport async function getChannel(\n storage: ClientChannelStorage,\n channelId: string,\n): Promise<BatchSettlementClientContext | undefined> {\n return storage.get(channelId.toLowerCase());\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 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 type { PaymentRequired, PaymentRequirements } from \"@payai/x402/types\";\nimport { getAddress, recoverTypedDataAddress } from \"viem\";\nimport { BATCH_SETTLEMENT_SCHEME, voucherTypes } from \"../constants\";\nimport type { BatchSettlementClientContext } from \"./storage\";\nimport { computeChannelId, getBatchSettlementEip712Domain } from \"../utils\";\nimport { getEvmChainId } from \"../../utils\";\nimport {\n type BatchSettlementClientDeps,\n buildChannelConfig,\n readChannelBalanceAndTotalClaimed,\n} from \"./channel\";\nimport * as Errors from \"../errors\";\nimport type { BatchSettlementChannelStateExtra, BatchSettlementVoucherStateExtra } from \"../types\";\n\n/**\n * Handles a corrective 402 response from the server when the client's\n * cumulative base is out of sync.\n *\n * Validates the server-provided state (chargedCumulativeAmount,\n * signedMaxClaimable, signature) against onchain data and the client's own\n * signing key, then updates the local channel state if everything checks out.\n *\n * @param deps - Signer + storage + identity inputs.\n * @param paymentRequired - The decoded 402 response body.\n * @returns `true` if the channel state was successfully resynced and the request can be retried.\n */\nexport async function processCorrectivePaymentRequired(\n deps: BatchSettlementClientDeps,\n paymentRequired: PaymentRequired,\n): Promise<boolean> {\n if (\n paymentRequired.error !== Errors.ErrCumulativeAmountMismatch &&\n paymentRequired.error !== Errors.ErrCumulativeAmountBelowClaimed\n ) {\n return false;\n }\n\n const accept = paymentRequired.accepts.find(a => a.scheme === BATCH_SETTLEMENT_SCHEME);\n if (!accept) {\n return false;\n }\n\n const channelState = accept.extra.channelState as BatchSettlementChannelStateExtra | undefined;\n const voucherState = accept.extra.voucherState as BatchSettlementVoucherStateExtra | undefined;\n const hasSig =\n channelState?.chargedCumulativeAmount !== undefined &&\n voucherState?.signedMaxClaimable !== undefined &&\n voucherState.signature !== undefined;\n\n if (!hasSig) {\n return recoverFromOnChainState(deps, accept);\n }\n\n return recoverFromSignature(deps, accept, channelState, voucherState);\n}\n\n/**\n * Recovers channel state from a corrective 402 that includes a server-provided\n * voucher signature. Verifies the signature matches the client's own signing\n * key before accepting.\n *\n * @param deps - Signer + storage + identity inputs.\n * @param accept - Batch settlement payment requirements from the corrective 402.\n * @param channelState - Server channel snapshot from `accept.extra.channelState`.\n * @param voucherState - Latest signed voucher proof from `accept.extra.voucherState`.\n * @returns `true` when local channel state was updated successfully.\n */\nexport async function recoverFromSignature(\n deps: BatchSettlementClientDeps,\n accept: PaymentRequirements,\n channelState: BatchSettlementChannelStateExtra,\n voucherState: BatchSettlementVoucherStateExtra,\n): Promise<boolean> {\n const chargedRaw = channelState.chargedCumulativeAmount;\n const signedRaw = voucherState.signedMaxClaimable;\n const sig = voucherState.signature as `0x${string}`;\n\n const charged = BigInt(String(chargedRaw));\n const signed = BigInt(String(signedRaw));\n\n if (charged > signed) {\n return false;\n }\n\n const config = buildChannelConfig(deps, accept);\n const channelId = computeChannelId(config, accept.network);\n\n if (!deps.signer.readContract) {\n return false;\n }\n\n const [chBalance, chTotalClaimed] = await readChannelBalanceAndTotalClaimed(\n deps.signer,\n channelId,\n );\n\n if (charged < chTotalClaimed) {\n return false;\n }\n\n const chainId = getEvmChainId(accept.network);\n const recovered = await recoverTypedDataAddress({\n domain: getBatchSettlementEip712Domain(chainId),\n types: voucherTypes,\n primaryType: \"Voucher\",\n message: {\n channelId,\n maxClaimableAmount: signed,\n },\n signature: sig,\n });\n\n const expectedSigner = getAddress(\n deps.payerAuthorizer ?? deps.voucherSigner?.address ?? deps.signer.address,\n );\n if (recovered.toLowerCase() !== expectedSigner.toLowerCase()) {\n return false;\n }\n\n const ctx: BatchSettlementClientContext = {\n chargedCumulativeAmount: charged.toString(),\n signedMaxClaimable: signed.toString(),\n signature: sig,\n balance: chBalance.toString(),\n totalClaimed: chTotalClaimed.toString(),\n };\n\n await deps.storage.set(channelId.toLowerCase(), ctx);\n return true;\n}\n\n/**\n * Recovers channel state purely from onchain state when the server has no stored\n * voucher (e.g. after a cooperative refund deleted the channel record). The onchain\n * `totalClaimed` becomes the new baseline — no signature verification is\n * needed because the contract is the source of truth when no outstanding\n * voucher exists.\n *\n * @param deps - Signer + storage + identity inputs.\n * @param accept - Batch settlement payment requirements from the corrective 402.\n * @returns `true` when local channel state was updated from onchain data.\n */\nexport async function recoverFromOnChainState(\n deps: BatchSettlementClientDeps,\n accept: PaymentRequirements,\n): Promise<boolean> {\n if (!deps.signer.readContract) {\n return false;\n }\n\n const config = buildChannelConfig(deps, accept);\n const channelId = computeChannelId(config, accept.network);\n\n const [chBalance, chTotalClaimed] = await readChannelBalanceAndTotalClaimed(\n deps.signer,\n channelId,\n );\n\n const ctx: BatchSettlementClientContext = {\n chargedCumulativeAmount: chTotalClaimed.toString(),\n balance: chBalance.toString(),\n totalClaimed: chTotalClaimed.toString(),\n };\n\n await deps.storage.set(channelId.toLowerCase(), ctx);\n return true;\n}\n","import type { PaymentResponseContext } from \"@payai/x402/client\";\nimport type { SchemeClientHooks } from \"@payai/x402/types\";\nimport { isBatchSettlementRefundPayload } from \"../types\";\nimport type { BatchSettlementClientDeps } from \"./channel\";\nimport { processSettleResponse, updateChannelAfterRefund } from \"./channel\";\nimport { processCorrectivePaymentRequired } from \"./recovery\";\n\n/**\n * Creates storage-aware client hooks for batch-settlement payment responses.\n *\n * @param deps - Client identity and storage inputs.\n * @returns Scheme hooks for response reconciliation and corrective recovery.\n */\nexport function createBatchSettlementClientHooks(\n deps: BatchSettlementClientDeps,\n): SchemeClientHooks {\n return {\n onPaymentResponse: ctx => handleBatchSettlementPaymentResponse(deps, ctx),\n };\n}\n\n/**\n * Reconciles batch-settlement client state after a paid request or refund attempt.\n *\n * @param deps - Client identity and storage inputs.\n * @param ctx - Core payment response context.\n * @returns A recovery signal when corrective recovery succeeds.\n */\nexport async function handleBatchSettlementPaymentResponse(\n deps: BatchSettlementClientDeps,\n ctx: PaymentResponseContext,\n): Promise<void | { recovered: true }> {\n if (ctx.settleResponse) {\n if (isBatchSettlementRefundPayload(ctx.paymentPayload.payload)) {\n const extra = ctx.settleResponse.extra ?? {};\n const channelState = extra.channelState;\n const channelId =\n typeof channelState === \"object\" && channelState !== null && \"channelId\" in channelState\n ? channelState.channelId\n : undefined;\n if (typeof channelId === \"string\" && channelId) {\n await updateChannelAfterRefund(deps.storage, channelId.toLowerCase(), extra);\n }\n return;\n }\n\n await processSettleResponse(deps.storage, ctx.settleResponse);\n return;\n }\n\n if (ctx.paymentRequired) {\n const recovered = await processCorrectivePaymentRequired(deps, ctx.paymentRequired);\n return recovered ? { recovered: true } : undefined;\n }\n}\n"],"mappings":"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","names":["import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_http","import_viem","import_viem"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, FacilitatorContext, VerifyResponse, SettleResponse } from '@payai/x402/types';
|
|
2
|
+
import { F as FacilitatorEvmSigner } from '../../signer-tYS6Y46X.js';
|
|
3
|
+
import { A as AuthorizerSigner } from '../../types-CF8P2-NM.js';
|
|
4
|
+
import 'viem';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Facilitator-side implementation of the `batch-settlement` scheme for EVM networks.
|
|
8
|
+
*
|
|
9
|
+
* Routes incoming verify/settle requests to the appropriate handler based on payload
|
|
10
|
+
* type (deposit, voucher, claim, settle, refund).
|
|
11
|
+
*/
|
|
12
|
+
declare class BatchSettlementEvmScheme implements SchemeNetworkFacilitator {
|
|
13
|
+
private readonly signer;
|
|
14
|
+
private readonly authorizerSigner;
|
|
15
|
+
readonly scheme: "batch-settlement";
|
|
16
|
+
readonly caipFamily = "eip155:*";
|
|
17
|
+
/**
|
|
18
|
+
* Creates a facilitator scheme for verifying and settling batch-settlement payments.
|
|
19
|
+
*
|
|
20
|
+
* @param signer - Facilitator EVM signer(s) used for tx submission and onchain reads.
|
|
21
|
+
* @param authorizerSigner - Dedicated key that provides EIP-712 signatures for
|
|
22
|
+
* `claimWithSignature` / `refundWithSignature`. The facilitator will sign missing
|
|
23
|
+
* authorizer signatures using this key when the server omits them.
|
|
24
|
+
*/
|
|
25
|
+
constructor(signer: FacilitatorEvmSigner, authorizerSigner: AuthorizerSigner);
|
|
26
|
+
/**
|
|
27
|
+
* Returns facilitator-specific extra fields to be merged into payment requirements.
|
|
28
|
+
*
|
|
29
|
+
* Exposes the configured `receiverAuthorizer` address so the server and client can
|
|
30
|
+
* embed it in `ChannelConfig`.
|
|
31
|
+
*
|
|
32
|
+
* @param _ - Network identifier (unused).
|
|
33
|
+
* @returns Extra fields containing `receiverAuthorizer`.
|
|
34
|
+
*/
|
|
35
|
+
getExtra(_: string): {
|
|
36
|
+
receiverAuthorizer: `0x${string}`;
|
|
37
|
+
} | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Returns all facilitator signer addresses available for the given network.
|
|
40
|
+
*
|
|
41
|
+
* @param _ - Network identifier (unused).
|
|
42
|
+
* @returns Array of hex addresses.
|
|
43
|
+
*/
|
|
44
|
+
getSigners(_: string): `0x${string}`[];
|
|
45
|
+
/**
|
|
46
|
+
* Verifies a payment payload (deposit or voucher) without executing settlement.
|
|
47
|
+
*
|
|
48
|
+
* @param payload - The x402 payment payload envelope.
|
|
49
|
+
* @param requirements - Server payment requirements (scheme, network, asset, amount).
|
|
50
|
+
* @param context - Optional facilitator extension context.
|
|
51
|
+
* @returns A {@link VerifyResponse} indicating validity with payer and channel state in `extra`.
|
|
52
|
+
*/
|
|
53
|
+
verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
|
|
54
|
+
/**
|
|
55
|
+
* Executes settlement for a payment payload.
|
|
56
|
+
*
|
|
57
|
+
* Dispatches to the correct handler based on payload settle action:
|
|
58
|
+
* - `deposit` → onchain `deposit(config, amount, collector, collectorData)`
|
|
59
|
+
* - `claim` → onchain `claimWithSignature(VoucherClaim[], bytes)`
|
|
60
|
+
* - `settle` → onchain `settle(receiver, token)`
|
|
61
|
+
* - `refund` → optional claim + onchain `refundWithSignature(config, amount, nonce, sig)`
|
|
62
|
+
*
|
|
63
|
+
* @param payload - The x402 payment payload envelope.
|
|
64
|
+
* @param requirements - Server payment requirements.
|
|
65
|
+
* @param context - Optional facilitator extension context.
|
|
66
|
+
* @returns A {@link SettleResponse} with the transaction hash on success.
|
|
67
|
+
*/
|
|
68
|
+
settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { BatchSettlementEvmScheme };
|