@bankofai/x402-evm 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -0
- package/dist/cjs/auth-capture/client/index.d.ts +44 -0
- package/dist/cjs/auth-capture/client/index.js +298 -0
- package/dist/cjs/auth-capture/client/index.js.map +1 -0
- 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 +72 -0
- package/dist/cjs/batch-settlement/facilitator/index.js +2102 -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 +1978 -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/client/agent-wallet.d.ts +69 -0
- package/dist/cjs/client/agent-wallet.js +84 -0
- package/dist/cjs/client/agent-wallet.js.map +1 -0
- package/dist/cjs/exact/client/index.d.ts +63 -0
- package/dist/cjs/exact/client/index.js +739 -0
- package/dist/cjs/exact/client/index.js.map +1 -0
- package/dist/cjs/exact/facilitator/index.d.ts +141 -0
- package/dist/cjs/exact/facilitator/index.js +1989 -0
- package/dist/cjs/exact/facilitator/index.js.map +1 -0
- package/dist/cjs/exact/server/index.d.ts +118 -0
- package/dist/cjs/exact/server/index.js +326 -0
- package/dist/cjs/exact/server/index.js.map +1 -0
- package/dist/cjs/exact/v1/client/index.d.ts +38 -0
- package/dist/cjs/exact/v1/client/index.js +193 -0
- package/dist/cjs/exact/v1/client/index.js.map +1 -0
- package/dist/cjs/exact/v1/facilitator/index.d.ts +84 -0
- package/dist/cjs/exact/v1/facilitator/index.js +739 -0
- package/dist/cjs/exact/v1/facilitator/index.js.map +1 -0
- package/dist/cjs/facilitator/agent-wallet.d.ts +109 -0
- package/dist/cjs/facilitator/agent-wallet.js +105 -0
- package/dist/cjs/facilitator/agent-wallet.js.map +1 -0
- package/dist/cjs/index.d.ts +338 -0
- package/dist/cjs/index.js +2860 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/permit2-DK5A8alk.d.ts +729 -0
- package/dist/cjs/permit2-DhJRUcgY.d.ts +729 -0
- package/dist/cjs/rpc-DULZzRne.d.ts +13 -0
- package/dist/cjs/scheme-7ehldYoO.d.ts +307 -0
- package/dist/cjs/scheme-BjBJzHF7.d.ts +307 -0
- package/dist/cjs/scheme-DWgpkDgz.d.ts +47 -0
- package/dist/cjs/signer-BFelv8DL.d.ts +170 -0
- package/dist/cjs/storage-6W5MO46W.d.ts +50 -0
- package/dist/cjs/storage-CHNote8s.d.ts +81 -0
- package/dist/cjs/storage-DjCv5IPh.d.ts +81 -0
- package/dist/cjs/types-CKd3Xoi1.d.ts +180 -0
- package/dist/cjs/types-DIt9uAUy.d.ts +180 -0
- package/dist/cjs/upto/client/index.d.ts +34 -0
- package/dist/cjs/upto/client/index.js +509 -0
- package/dist/cjs/upto/client/index.js.map +1 -0
- package/dist/cjs/upto/facilitator/index.d.ts +54 -0
- package/dist/cjs/upto/facilitator/index.js +1313 -0
- package/dist/cjs/upto/facilitator/index.js.map +1 -0
- package/dist/cjs/upto/server/index.d.ts +69 -0
- package/dist/cjs/upto/server/index.js +296 -0
- package/dist/cjs/upto/server/index.js.map +1 -0
- package/dist/cjs/v1/index.d.ts +40 -0
- package/dist/cjs/v1/index.js +199 -0
- package/dist/cjs/v1/index.js.map +1 -0
- package/dist/esm/auth-capture/client/index.d.mts +44 -0
- package/dist/esm/auth-capture/client/index.mjs +8 -0
- package/dist/esm/auth-capture/client/index.mjs.map +1 -0
- 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 +58 -0
- package/dist/esm/batch-settlement/client/index.mjs.map +1 -0
- package/dist/esm/batch-settlement/facilitator/index.d.mts +72 -0
- package/dist/esm/batch-settlement/facilitator/index.mjs +1252 -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 +1640 -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-3WZF6722.mjs +36 -0
- package/dist/esm/chunk-3WZF6722.mjs.map +1 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs +275 -0
- package/dist/esm/chunk-E4Z7PNXC.mjs.map +1 -0
- package/dist/esm/chunk-GQVMVP4N.mjs +911 -0
- package/dist/esm/chunk-GQVMVP4N.mjs.map +1 -0
- package/dist/esm/chunk-H2EYJIZL.mjs +489 -0
- package/dist/esm/chunk-H2EYJIZL.mjs.map +1 -0
- package/dist/esm/chunk-H3KPLYGI.mjs +152 -0
- package/dist/esm/chunk-H3KPLYGI.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-I2DVUHM5.mjs +123 -0
- package/dist/esm/chunk-I2DVUHM5.mjs.map +1 -0
- package/dist/esm/chunk-JK7SLLF7.mjs +34 -0
- package/dist/esm/chunk-JK7SLLF7.mjs.map +1 -0
- package/dist/esm/chunk-JNT7C46S.mjs +352 -0
- package/dist/esm/chunk-JNT7C46S.mjs.map +1 -0
- package/dist/esm/chunk-MACPBXCT.mjs +415 -0
- package/dist/esm/chunk-MACPBXCT.mjs.map +1 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs +113 -0
- package/dist/esm/chunk-P3QOX3QZ.mjs.map +1 -0
- package/dist/esm/chunk-QVATVA3J.mjs +47 -0
- package/dist/esm/chunk-QVATVA3J.mjs.map +1 -0
- package/dist/esm/chunk-SHJFA25H.mjs +159 -0
- package/dist/esm/chunk-SHJFA25H.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-XG2JLZVJ.mjs +627 -0
- package/dist/esm/chunk-XG2JLZVJ.mjs.map +1 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs +162 -0
- package/dist/esm/chunk-ZCJRY5LQ.mjs.map +1 -0
- package/dist/esm/client/agent-wallet.d.mts +69 -0
- package/dist/esm/client/agent-wallet.mjs +36 -0
- package/dist/esm/client/agent-wallet.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +63 -0
- package/dist/esm/exact/client/index.mjs +25 -0
- package/dist/esm/exact/client/index.mjs.map +1 -0
- package/dist/esm/exact/facilitator/index.d.mts +141 -0
- package/dist/esm/exact/facilitator/index.mjs +694 -0
- package/dist/esm/exact/facilitator/index.mjs.map +1 -0
- package/dist/esm/exact/server/index.d.mts +118 -0
- package/dist/esm/exact/server/index.mjs +153 -0
- package/dist/esm/exact/server/index.mjs.map +1 -0
- package/dist/esm/exact/v1/client/index.d.mts +38 -0
- package/dist/esm/exact/v1/client/index.mjs +12 -0
- package/dist/esm/exact/v1/client/index.mjs.map +1 -0
- package/dist/esm/exact/v1/facilitator/index.d.mts +84 -0
- package/dist/esm/exact/v1/facilitator/index.mjs +12 -0
- package/dist/esm/exact/v1/facilitator/index.mjs.map +1 -0
- package/dist/esm/facilitator/agent-wallet.d.mts +109 -0
- package/dist/esm/facilitator/agent-wallet.mjs +74 -0
- package/dist/esm/facilitator/agent-wallet.mjs.map +1 -0
- package/dist/esm/index.d.mts +338 -0
- package/dist/esm/index.mjs +144 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/permit2-DhJRUcgY.d.mts +729 -0
- package/dist/esm/rpc-DULZzRne.d.mts +13 -0
- package/dist/esm/scheme-CkNhpXrG.d.mts +307 -0
- package/dist/esm/scheme-D8ZbykGV.d.mts +47 -0
- package/dist/esm/signer-BFelv8DL.d.mts +170 -0
- package/dist/esm/storage-6W5MO46W.d.mts +50 -0
- package/dist/esm/storage-BEzTEiUr.d.mts +81 -0
- package/dist/esm/types-DIt9uAUy.d.mts +180 -0
- package/dist/esm/upto/client/index.d.mts +34 -0
- package/dist/esm/upto/client/index.mjs +22 -0
- package/dist/esm/upto/client/index.mjs.map +1 -0
- package/dist/esm/upto/facilitator/index.d.mts +54 -0
- package/dist/esm/upto/facilitator/index.mjs +507 -0
- package/dist/esm/upto/facilitator/index.mjs.map +1 -0
- package/dist/esm/upto/server/index.d.mts +69 -0
- package/dist/esm/upto/server/index.mjs +124 -0
- package/dist/esm/upto/server/index.mjs.map +1 -0
- package/dist/esm/v1/index.d.mts +40 -0
- package/dist/esm/v1/index.mjs +18 -0
- package/dist/esm/v1/index.mjs.map +1 -0
- package/package.json +250 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/exact/v1/facilitator/index.ts","../../../../../src/shared/extensions/gasSponsoring.ts","../../../../../src/constants.ts","../../../../../src/utils.ts","../../../../../src/exact/client/eip2612.ts","../../../../../src/exact/client/erc20approval.ts","../../../../../src/shared/rpc.ts","../../../../../src/shared/extensions/builderCode.ts","../../../../../src/exact/v1/facilitator/scheme.ts","../../../../../src/exact/v1/client/scheme.ts","../../../../../src/v1/index.ts","../../../../../src/exact/facilitator/errors.ts","../../../../../src/exact/facilitator/eip3009-utils.ts","../../../../../src/multicall.ts"],"sourcesContent":["export { ExactEvmSchemeV1 } from \"./scheme\";\nexport type { ExactEvmSchemeV1Config } from \"./scheme\";\n","import type {\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@bankofai/x402-core/types\";\nimport {\n EIP2612_GAS_SPONSORING_KEY,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n} 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 { 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 { 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 type {\n FacilitatorContext,\n FacilitatorExtension,\n PaymentPayload,\n PaymentRequirements,\n} from \"@bankofai/x402-core/types\";\nimport type { Hex } from \"viem\";\n\nexport const BUILDER_CODE_KEY = \"builder-code\" as const;\n\nexport interface DataSuffixContext {\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n}\n\nexport interface BuilderCodeFacilitatorExtension extends FacilitatorExtension {\n key: typeof BUILDER_CODE_KEY;\n buildDataSuffix?(ctx: DataSuffixContext): Hex | undefined | Promise<Hex | undefined>;\n}\n\ntype DataSuffixResolver = (\n context: FacilitatorContext,\n ctx: DataSuffixContext,\n) => Promise<Hex | undefined>;\n\nconst BUILDER_CODE_RESOLVER: DataSuffixResolver = async (context, ctx) => {\n const ext = context.getExtension<BuilderCodeFacilitatorExtension>(BUILDER_CODE_KEY);\n if (!ext?.buildDataSuffix) {\n return undefined;\n }\n\n return ext.buildDataSuffix(ctx);\n};\n\nconst DATA_SUFFIX_RESOLVERS: DataSuffixResolver[] = [BUILDER_CODE_RESOLVER];\n\n/**\n * Resolves and concatenates data suffixes from registered extensions.\n *\n * @param context - Facilitator context with registered extensions\n * @param ctx - Data suffix context passed to extension resolvers\n * @returns Hex-encoded suffix to append to settlement calldata, or undefined if none\n */\nexport async function resolveDataSuffix(\n context: FacilitatorContext | undefined,\n ctx: DataSuffixContext,\n): Promise<Hex | undefined> {\n if (!context) {\n return undefined;\n }\n\n const parts: Hex[] = [];\n for (const resolver of DATA_SUFFIX_RESOLVERS) {\n const suffix = await resolver(context, ctx);\n if (suffix && suffix !== \"0x\" && suffix.length > 2) {\n parts.push(suffix);\n }\n }\n\n if (parts.length === 0) {\n return undefined;\n }\n\n if (parts.length === 1) {\n return parts[0];\n }\n\n return parts.reduce((acc, part, index) => {\n if (index === 0) {\n return part;\n }\n const stripped = part.startsWith(\"0x\") ? part.slice(2) : part;\n return `${acc}${stripped}` as Hex;\n });\n}\n\n/**\n * Appends a hex data suffix to encoded contract calldata.\n *\n * @param calldata - Base encoded function calldata\n * @param suffix - Optional hex suffix (with or without 0x prefix)\n * @returns Calldata with suffix appended, or the original calldata when suffix is empty\n */\nexport function appendDataSuffix(calldata: Hex, suffix?: Hex): Hex {\n if (!suffix || suffix === \"0x\" || suffix.length <= 2) {\n return calldata;\n }\n const suffixHex = suffix.startsWith(\"0x\") ? suffix.slice(2) : suffix;\n return `${calldata}${suffixHex}` as Hex;\n}\n","import {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@bankofai/x402-core/types\";\nimport { resolveDataSuffix } from \"../../../shared/extensions\";\nimport { PaymentRequirementsV1 } from \"@bankofai/x402-core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { EvmNetworkV1, getEvmChainIdV1 } from \"../../../v1\";\nimport * as Errors from \"../../facilitator/errors\";\nimport {\n diagnoseEip3009SimulationFailure,\n executeTransferWithAuthorization,\n simulateEip3009Transfer,\n} from \"../../facilitator/eip3009-utils\";\n\nexport interface VerifyV1Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. Facilitators must\n * explicitly list every factory they trust to prevent arbitrary transaction injection via\n * attacker-controlled ERC-6492 signature wrappers. An empty or omitted list denies all factory\n * deployment calls.\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme (V1).\n */\nexport class ExactEvmSchemeV1 implements SchemeNetworkFacilitator {\n readonly scheme = \"exact\";\n readonly caipFamily = \"eip155:*\";\n private readonly config: Required<ExactEvmSchemeV1Config>;\n\n /**\n * Creates a new ExactEvmFacilitatorV1 instance.\n *\n * @param signer - The EVM signer for facilitator operations\n * @param config - Optional configuration for the facilitator\n */\n constructor(\n private readonly signer: FacilitatorEvmSigner,\n config?: ExactEvmSchemeV1Config,\n ) {\n this.config = {\n eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],\n simulateInSettle: config?.simulateInSettle ?? false,\n };\n }\n\n /**\n * Get mechanism-specific extra data for the supported kinds endpoint.\n * For EVM, no extra data is needed.\n *\n * @param _ - The network identifier (unused for EVM)\n * @returns undefined (EVM has no extra data)\n */\n getExtra(_: string): Record<string, unknown> | undefined {\n return undefined;\n }\n\n /**\n * Get signer addresses used by this facilitator.\n * Returns all addresses this facilitator can use for signing/settling transactions.\n *\n * @param _ - The network identifier (unused for EVM, addresses are network-agnostic)\n * @returns Array of facilitator wallet addresses\n */\n getSigners(_: string): string[] {\n return [...this.signer.getAddresses()];\n }\n\n /**\n * Verifies a payment payload (V1).\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n return this._verify(payload, requirements);\n }\n\n /**\n * Settles a payment by executing the transfer (V1).\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<SettleResponse> {\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Re-verify before settling\n const valid = await this._verify(payload, requirements, {\n simulate: this.config.simulateInSettle ?? false,\n });\n if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable (for optional deployment)\n const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature(\n exactEvmPayload.signature!,\n );\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if factory is in the allowlist\n if (\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n const normalizedFactory = factoryAddress.toLowerCase();\n const isAllowed = (this.config.eip6492AllowedFactories ?? []).some(\n allowed => allowed.toLowerCase() === normalizedFactory,\n );\n if (!isAllowed) {\n return {\n success: false,\n errorReason: Errors.ErrFactoryNotAllowed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Send the factory calldata directly as a transaction\n // The factoryCalldata already contains the complete encoded function call\n const deployTx = await this.signer.sendTransaction({\n to: factoryAddress as Hex,\n data: factoryCalldata as Hex,\n });\n\n // Wait for deployment transaction\n await this.signer.waitForTransactionReceipt({ hash: deployTx });\n }\n }\n\n // V1 payloads carry no extensions, so the builder-code suffix can only contain the\n // facilitator's own wallet code (`w`); client app (`a`) and service (`s`) codes are\n // always absent.\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n const tx = await executeTransferWithAuthorization(\n this.signer,\n getAddress(requirements.asset),\n exactEvmPayload,\n dataSuffix,\n );\n\n // Wait for transaction confirmation\n const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrTransactionFailed,\n transaction: tx,\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n } catch (error) {\n return {\n success: false,\n errorReason: error instanceof Error ? error.message : Errors.ErrTransactionFailed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n }\n\n /**\n * Internal verify with optional simulation control.\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param options - Verification options (e.g. simulate)\n * @returns Promise resolving to verification response\n */\n private async _verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n options?: VerifyV1Options,\n ): Promise<VerifyResponse> {\n const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n const payer = exactEvmPayload.authorization.from;\n let eip6492Deployment:\n | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` }\n | undefined;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainIdV1(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: Errors.ErrMissingEip712Domain,\n payer,\n };\n }\n\n const { name, version } = requirements.extra;\n const erc20Address = getAddress(requirements.asset);\n\n // Verify network matches\n if (payloadV1.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n // Build typed data for signature verification\n const permitTypedData = {\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\" as const,\n domain: {\n name,\n version,\n chainId,\n verifyingContract: erc20Address,\n },\n message: {\n from: exactEvmPayload.authorization.from,\n to: exactEvmPayload.authorization.to,\n value: BigInt(exactEvmPayload.authorization.value),\n validAfter: BigInt(exactEvmPayload.authorization.validAfter),\n validBefore: BigInt(exactEvmPayload.authorization.validBefore),\n nonce: exactEvmPayload.authorization.nonce,\n },\n };\n\n // Verify signature (flatten EIP-6492 handling out of catch block)\n let isValid = false;\n try {\n isValid = await this.signer.verifyTypedData({\n address: payer,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n } catch {\n isValid = false;\n }\n\n const signature = exactEvmPayload.signature!;\n const sigLen = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n\n // Extract EIP-6492 deployment info (factory address + calldata) if present\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (hasDeploymentInfo) {\n eip6492Deployment = {\n factoryAddress: erc6492Data.address!,\n factoryCalldata: erc6492Data.data!,\n };\n }\n\n if (!isValid) {\n const isSmartWallet = sigLen > 130; // 65 bytes = 130 hex chars for EOA\n\n if (!isSmartWallet) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidSignature,\n payer,\n };\n }\n\n const bytecode = await this.signer.getCode({ address: payer });\n const isDeployed = bytecode && bytecode !== \"0x\";\n\n if (!isDeployed && !hasDeploymentInfo) {\n return {\n isValid: false,\n invalidReason: Errors.ErrUndeployedSmartWallet,\n payer,\n };\n }\n }\n\n // Verify payment recipient matches\n if (getAddress(exactEvmPayload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrRecipientMismatch,\n payer,\n };\n }\n\n // Verify validBefore is in the future (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidBeforeExpired,\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidAfterInFuture,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidAuthorizationValue,\n payer,\n };\n }\n\n // Transaction simulation\n if (options?.simulate !== false) {\n const simulationSucceeded = await simulateEip3009Transfer(\n this.signer,\n erc20Address,\n exactEvmPayload,\n eip6492Deployment,\n );\n if (!simulationSucceeded) {\n return diagnoseEip3009SimulationFailure(\n this.signer,\n erc20Address,\n exactEvmPayload,\n requirements,\n requirementsV1.maxAmountRequired,\n );\n }\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n }\n}\n","import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@bankofai/x402-core/types\";\nimport { PaymentRequirementsV1 } from \"@bankofai/x402-core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce } from \"../../../utils\";\nimport { EvmNetworkV1, getEvmChainIdV1 } from \"../../../v1\";\n\n/**\n * EVM client implementation for the Exact payment scheme (V1).\n */\nexport class ExactEvmSchemeV1 implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClientV1 instance.\n *\n * @param signer - The EVM signer for client operations\n */\n constructor(private readonly signer: ClientEvmSigner) {}\n\n /**\n * Creates a payment payload for the Exact scheme (V1).\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n ): Promise<\n Pick<PaymentPayload, \"x402Version\" | \"payload\"> & { scheme: string; network: Network }\n > {\n const selectedV1 = paymentRequirements as unknown as PaymentRequirementsV1;\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEvmPayloadV1[\"authorization\"] = {\n from: this.signer.address,\n to: getAddress(selectedV1.payTo),\n value: selectedV1.maxAmountRequired,\n validAfter: (now - 600).toString(), // 10 minutes before\n validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n // Sign the authorization\n const signature = await this.signAuthorization(authorization, selectedV1);\n\n const payload: ExactEvmPayloadV1 = {\n authorization,\n signature,\n };\n\n return {\n x402Version,\n scheme: selectedV1.scheme,\n network: selectedV1.network,\n payload,\n };\n }\n\n /**\n * Sign the EIP-3009 authorization using EIP-712\n *\n * @param authorization - The authorization to sign\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\n private async signAuthorization(\n authorization: ExactEvmPayloadV1[\"authorization\"],\n requirements: PaymentRequirementsV1,\n ): Promise<`0x${string}`> {\n const chainId = getEvmChainIdV1(requirements.network as EvmNetworkV1);\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n throw new Error(\n `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n );\n }\n\n const { name, version } = requirements.extra;\n\n const domain = {\n name,\n version,\n chainId,\n verifyingContract: getAddress(requirements.asset),\n };\n\n const message = {\n from: getAddress(authorization.from),\n to: getAddress(authorization.to),\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce,\n };\n\n return await this.signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n }\n}\n","export { ExactEvmSchemeV1 } from \"../exact/v1\";\n\nexport const EVM_NETWORK_CHAIN_ID_MAP = {\n ethereum: 1,\n sepolia: 11155111,\n abstract: 2741,\n \"abstract-testnet\": 11124,\n \"base-sepolia\": 84532,\n base: 8453,\n \"avalanche-fuji\": 43113,\n avalanche: 43114,\n iotex: 4689,\n sei: 1329,\n \"sei-testnet\": 1328,\n polygon: 137,\n \"polygon-amoy\": 80002,\n peaq: 3338,\n story: 1514,\n educhain: 41923,\n \"skale-base-sepolia\": 324705682,\n megaeth: 4326,\n monad: 143,\n stable: 988,\n \"stable-testnet\": 2201,\n} as const;\n\nexport type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP;\n\nexport const NETWORKS: string[] = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);\n\n/**\n * Extract chain ID from a v1 legacy network name.\n *\n * @param network - The v1 network name (e.g., \"base-sepolia\", \"polygon\")\n * @returns The numeric chain ID\n * @throws Error if the network name is not a known v1 network\n */\nexport function getEvmChainIdV1(network: string): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network as EvmNetworkV1];\n if (!chainId) {\n throw new Error(`Unsupported v1 network: ${network}`);\n }\n return chainId;\n}\n","/**\n * Named error reason constants for the exact EVM facilitator.\n *\n * These strings must be character-for-character identical to the Go constants in\n * go/mechanisms/evm/exact/facilitator/errors.go to maintain cross-SDK parity.\n */\n\nexport const ErrAssetNotDeployedContract = \"asset_not_deployed_contract\";\n\nexport const ErrInvalidScheme = \"invalid_exact_evm_scheme\";\nexport const ErrNetworkMismatch = \"invalid_exact_evm_network_mismatch\";\nexport const ErrMissingEip712Domain = \"invalid_exact_evm_missing_eip712_domain\";\nexport const ErrRecipientMismatch = \"invalid_exact_evm_recipient_mismatch\";\nexport const ErrInvalidSignature = \"invalid_exact_evm_signature\";\nexport const ErrValidBeforeExpired = \"invalid_exact_evm_payload_authorization_valid_before\";\nexport const ErrValidAfterInFuture = \"invalid_exact_evm_payload_authorization_valid_after\";\nexport const ErrInvalidAuthorizationValue = \"invalid_exact_evm_authorization_value\";\nexport const ErrUndeployedSmartWallet = \"invalid_exact_evm_payload_undeployed_smart_wallet\";\nexport const ErrTransactionFailed = \"invalid_exact_evm_transaction_failed\";\n\n// EIP-3009 verify errors\nexport const ErrEip3009TokenNameMismatch = \"invalid_exact_evm_token_name_mismatch\";\nexport const ErrEip3009TokenVersionMismatch = \"invalid_exact_evm_token_version_mismatch\";\nexport const ErrEip3009NotSupported = \"invalid_exact_evm_eip3009_not_supported\";\nexport const ErrEip3009NonceAlreadyUsed = \"invalid_exact_evm_nonce_already_used\";\nexport const ErrEip3009InsufficientBalance = \"invalid_exact_evm_insufficient_balance\";\nexport const ErrEip3009SimulationFailed = \"invalid_exact_evm_transaction_simulation_failed\";\n\n// Permit2 verify errors\nexport const ErrPermit2InvalidSpender = \"invalid_permit2_spender\";\nexport const ErrPermit2RecipientMismatch = \"invalid_permit2_recipient_mismatch\";\nexport const ErrPermit2DeadlineExpired = \"permit2_deadline_expired\";\nexport const ErrPermit2NotYetValid = \"permit2_not_yet_valid\";\nexport const ErrPermit2AmountMismatch = \"permit2_amount_mismatch\";\nexport const ErrPermit2TokenMismatch = \"permit2_token_mismatch\";\nexport const ErrPermit2InvalidSignature = \"invalid_permit2_signature\";\nexport const ErrPermit2AllowanceRequired = \"permit2_allowance_required\";\nexport const ErrPermit2SimulationFailed = \"permit2_simulation_failed\";\nexport const ErrPermit2InsufficientBalance = \"permit2_insufficient_balance\";\nexport const ErrPermit2ProxyNotDeployed = \"permit2_proxy_not_deployed\";\n\n// Permit2 settle errors (from contract reverts)\nexport const ErrPermit2InvalidAmount = \"permit2_invalid_amount\";\nexport const ErrPermit2InvalidDestination = \"permit2_invalid_destination\";\nexport const ErrPermit2InvalidOwner = \"permit2_invalid_owner\";\nexport const ErrPermit2PaymentTooEarly = \"permit2_payment_too_early\";\nexport const ErrPermit2InvalidNonce = \"permit2_invalid_nonce\";\nexport const ErrPermit2612AmountMismatch = \"permit2_2612_amount_mismatch\";\n\n// ERC-20 approval gas sponsoring verify errors\nexport const ErrErc20ApprovalInvalidFormat = \"invalid_erc20_approval_extension_format\";\nexport const ErrErc20ApprovalFromMismatch = \"erc20_approval_from_mismatch\";\nexport const ErrErc20ApprovalAssetMismatch = \"erc20_approval_asset_mismatch\";\nexport const ErrErc20ApprovalSpenderNotPermit2 = \"erc20_approval_spender_not_permit2\";\nexport const ErrErc20ApprovalTxWrongTarget = \"erc20_approval_tx_wrong_target\";\nexport const ErrErc20ApprovalTxWrongSelector = \"erc20_approval_tx_wrong_selector\";\nexport const ErrErc20ApprovalTxWrongSpender = \"erc20_approval_tx_wrong_spender\";\nexport const ErrErc20ApprovalTxInvalidCalldata = \"erc20_approval_tx_invalid_calldata\";\nexport const ErrErc20ApprovalTxSignerMismatch = \"erc20_approval_tx_signer_mismatch\";\nexport const ErrErc20ApprovalTxInvalidSignature = \"erc20_approval_tx_invalid_signature\";\nexport const ErrErc20ApprovalTxParseFailed = \"erc20_approval_tx_parse_failed\";\nexport const ErrErc20ApprovalTxFailed = \"erc20_approval_tx_failed\";\n\n// EIP-2612 gas sponsoring verify errors\nexport const ErrInvalidEip2612ExtensionFormat = \"invalid_eip2612_extension_format\";\nexport const ErrEip2612FromMismatch = \"eip2612_from_mismatch\";\nexport const ErrEip2612AssetMismatch = \"eip2612_asset_mismatch\";\nexport const ErrEip2612SpenderNotPermit2 = \"eip2612_spender_not_permit2\";\nexport const ErrEip2612DeadlineExpired = \"eip2612_deadline_expired\";\n\n// Shared settle errors\nexport const ErrUnsupportedPayloadType = \"unsupported_payload_type\";\nexport const ErrInvalidTransactionState = \"invalid_transaction_state\";\nexport const ErrFactoryNotAllowed = \"eip6492_factory_not_allowed\";\n","import { PaymentRequirements, VerifyResponse } from \"@bankofai/x402-core/types\";\nimport { encodeFunctionData, getAddress, Hex, parseErc6492Signature, parseSignature } from \"viem\";\nimport { eip3009ABI } from \"../../constants\";\nimport { multicall, ContractCall, RawContractCall } from \"../../multicall\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport * as Errors from \"./errors\";\n\nexport interface Eip6492Deployment {\n factoryAddress: `0x${string}`;\n factoryCalldata: `0x${string}`;\n}\n\n/**\n * Simulates transferWithAuthorization via eth_call.\n * Returns true if simulation succeeded, false if it failed.\n *\n * @param signer - EVM signer for contract reads\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param eip6492Deployment - Optional EIP-6492 factory info for undeployed smart wallets\n *\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulateEip3009Transfer(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n eip6492Deployment?: Eip6492Deployment,\n): Promise<boolean> {\n const auth = payload.authorization;\n const transferArgs = [\n getAddress(auth.from),\n getAddress(auth.to),\n BigInt(auth.value),\n BigInt(auth.validAfter),\n BigInt(auth.validBefore),\n auth.nonce,\n ] as const;\n\n if (eip6492Deployment) {\n const { signature: innerSignature } = parseErc6492Signature(payload.signature!);\n const transferCalldata = encodeFunctionData({\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...transferArgs, innerSignature],\n });\n\n try {\n const results = await multicall(signer.readContract.bind(signer), [\n {\n address: getAddress(eip6492Deployment.factoryAddress),\n callData: eip6492Deployment.factoryCalldata,\n } satisfies RawContractCall,\n {\n address: erc20Address,\n callData: transferCalldata,\n } satisfies RawContractCall,\n ]);\n\n return results[1]?.status === \"success\";\n } catch {\n return false;\n }\n }\n\n const sig = payload.signature!;\n const sigLength = sig.startsWith(\"0x\") ? sig.length - 2 : sig.length;\n const isECDSA = sigLength === 130;\n\n try {\n if (isECDSA) {\n const parsedSig = parseSignature(sig);\n await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n ...transferArgs,\n (parsedSig.v as number | undefined) ?? parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...transferArgs, sig],\n });\n }\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * After simulation fails, runs a single diagnostic multicall to determine the most specific error reason.\n * Checks balanceOf, name, version and authorizationState in one RPC round-trip.\n *\n * @param signer - EVM signer used for the payment\n * @param erc20Address - Address of the ERC-20 token contract\n * @param payload - The EIP-3009 transfer authorization payload\n * @param requirements - Payment requirements to validate against\n * @param amountRequired - Required amount for the payment (balance check)\n *\n * @returns Promise resolving to the verification result with validity and optional invalid reason\n */\nexport async function diagnoseEip3009SimulationFailure(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n requirements: PaymentRequirements,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const payer = payload.authorization.from;\n\n const diagnosticCalls: ContractCall[] = [\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payload.authorization.from],\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"name\",\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"version\",\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"authorizationState\",\n args: [payload.authorization.from, payload.authorization.nonce],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [balanceResult, nameResult, versionResult, authStateResult] = results;\n\n if (authStateResult.status === \"failure\") {\n return { isValid: false, invalidReason: Errors.ErrEip3009NotSupported, payer };\n }\n\n if (authStateResult.status === \"success\" && authStateResult.result === true) {\n return { isValid: false, invalidReason: Errors.ErrEip3009NonceAlreadyUsed, payer };\n }\n\n if (\n nameResult.status === \"success\" &&\n requirements.extra?.name &&\n nameResult.result !== requirements.extra.name\n ) {\n return { isValid: false, invalidReason: Errors.ErrEip3009TokenNameMismatch, payer };\n }\n\n if (\n versionResult.status === \"success\" &&\n requirements.extra?.version &&\n versionResult.result !== requirements.extra.version\n ) {\n return { isValid: false, invalidReason: Errors.ErrEip3009TokenVersionMismatch, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrEip3009InsufficientBalance,\n payer,\n };\n }\n }\n } catch {\n // Diagnostic multicall failed — fall through to generic error\n }\n\n return { isValid: false, invalidReason: Errors.ErrEip3009SimulationFailed, payer };\n}\n\n/**\n * Maps an EIP-3009 contract revert error to a specific error code.\n * Falls back to ErrTransactionFailed when the revert reason is unknown.\n *\n * @param error - The error thrown during transfer execution\n * @returns A specific error reason string\n */\nexport function parseEip3009TransferError(error: unknown): string {\n const msg = error instanceof Error ? error.message : String(error);\n if (/authorization.*(expired|valid before)/i.test(msg) || /AuthorizationExpired/i.test(msg)) {\n return Errors.ErrValidBeforeExpired;\n }\n if (/authorization.*not.*valid|AuthorizationNotYetValid/i.test(msg)) {\n return Errors.ErrValidAfterInFuture;\n }\n if (/authorization.*used|AuthorizationAlreadyUsed|AuthorizationUsedOrCanceled/i.test(msg)) {\n return Errors.ErrEip3009NonceAlreadyUsed;\n }\n if (/transfer.*exceeds.*balance|insufficient.*balance|ERC20InsufficientBalance/i.test(msg)) {\n return Errors.ErrEip3009InsufficientBalance;\n }\n if (/invalid.*signature|SignerMismatch|InvalidSignatureV|InvalidSignatureS/i.test(msg)) {\n return Errors.ErrInvalidSignature;\n }\n return Errors.ErrTransactionFailed;\n}\n\n/**\n * Executes transferWithAuthorization onchain.\n *\n * @param signer - EVM signer for contract writes\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param dataSuffix - Optional hex bytes to append after the ABI-encoded calldata\n *\n * @returns Transaction hash\n */\nexport async function executeTransferWithAuthorization(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n dataSuffix?: Hex,\n): Promise<Hex> {\n const { signature } = parseErc6492Signature(payload.signature!);\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n const auth = payload.authorization;\n const baseArgs = [\n getAddress(auth.from),\n getAddress(auth.to),\n BigInt(auth.value),\n BigInt(auth.validAfter),\n BigInt(auth.validBefore),\n auth.nonce,\n ] as const;\n\n let signatureArgs: readonly unknown[];\n if (isECDSA) {\n const parsedSig = parseSignature(signature);\n signatureArgs = [\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ];\n } else {\n signatureArgs = [signature];\n }\n\n return signer.writeContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...baseArgs, ...signatureArgs],\n dataSuffix,\n });\n}\n","import { encodeFunctionData, decodeFunctionResult } from \"viem\";\n\n/**\n * Multicall3 contract address.\n * Same address on all EVM chains via CREATE2 deployment.\n *\n * @see https://github.com/mds1/multicall\n */\nexport const MULTICALL3_ADDRESS = \"0xcA11bde05977b3631167028862bE2a173976CA11\" as const;\n\n/** Multicall3 getEthBalance ABI for querying native token balance. */\nexport const multicall3GetEthBalanceAbi = [\n {\n name: \"getEthBalance\",\n inputs: [{ name: \"addr\", type: \"address\" }],\n outputs: [{ name: \"balance\", type: \"uint256\" }],\n stateMutability: \"view\",\n type: \"function\",\n },\n] as const;\n\n/** Multicall3 tryAggregate ABI for batching calls. */\nconst multicall3ABI = [\n {\n inputs: [\n { name: \"requireSuccess\", type: \"bool\" },\n {\n name: \"calls\",\n type: \"tuple[]\",\n components: [\n { name: \"target\", type: \"address\" },\n { name: \"callData\", type: \"bytes\" },\n ],\n },\n ],\n name: \"tryAggregate\",\n outputs: [\n {\n name: \"returnData\",\n type: \"tuple[]\",\n components: [\n { name: \"success\", type: \"bool\" },\n { name: \"returnData\", type: \"bytes\" },\n ],\n },\n ],\n stateMutability: \"payable\",\n type: \"function\",\n },\n] as const;\n\nexport type ContractCall = {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n};\n\nexport type RawContractCall = {\n address: `0x${string}`;\n callData: `0x${string}`;\n};\n\nexport type MulticallSuccess = { status: \"success\"; result: unknown };\nexport type MulticallFailure = { status: \"failure\"; error: Error };\nexport type MulticallResult = MulticallSuccess | MulticallFailure;\n\n/**\n * Batches contract calls via Multicall3 `tryAggregate(false, ...)`.\n *\n * Accepts a mix of typed ContractCall (ABI-encoded + decoded) and\n * RawContractCall (pre-encoded calldata, no decoding) entries.\n * Raw calls are useful for the EIP-6492 factory deployment case\n * where calldata is pre-encoded with no ABI available.\n */\ntype ReadContractFn = (args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n}) => Promise<unknown>;\n\n/**\n * Executes multiple contract read calls in a single RPC round-trip using Multicall3.\n *\n * @param readContract - Function that performs a single contract read (e.g. viem readContract)\n * @param calls - Array of contract calls to batch (ContractCall or RawContractCall)\n * @returns A promise that resolves to an array of decoded results, one per call\n */\nexport async function multicall(\n readContract: ReadContractFn,\n calls: ReadonlyArray<ContractCall | RawContractCall>,\n): Promise<MulticallResult[]> {\n const aggregateCalls = calls.map(call => {\n if (\"callData\" in call) {\n return { target: call.address, callData: call.callData };\n }\n const callData = encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args as unknown[],\n });\n return { target: call.address, callData };\n });\n\n const rawResults = (await readContract({\n address: MULTICALL3_ADDRESS,\n abi: multicall3ABI,\n functionName: \"tryAggregate\",\n args: [false, aggregateCalls],\n })) as { success: boolean; returnData: `0x${string}` }[];\n\n return rawResults.map((raw, i) => {\n if (!raw.success) {\n return {\n status: \"failure\" as const,\n error: new Error(`multicall: call reverted (returnData: ${raw.returnData})`),\n };\n }\n\n const call = calls[i];\n if (\"callData\" in call) {\n return { status: \"success\" as const, result: undefined };\n }\n\n try {\n const decoded = decodeFunctionResult({\n abi: call.abi,\n functionName: call.functionName,\n data: raw.returnData,\n });\n return { status: \"success\" as const, result: decoded };\n } catch (err) {\n return {\n status: \"failure\" as const,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n });\n}\n"],"mappings":"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","names":["ExactEvmSchemeV1","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","import_viem","ExactEvmSchemeV1"]}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { PublicClient } from 'viem';
|
|
2
|
+
import { F as FacilitatorEvmSigner } from '../signer-BFelv8DL.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* BankofAI overlay — NOT from upstream @x402/evm.
|
|
6
|
+
*
|
|
7
|
+
* Adds a wallet-bridge factory for facilitators, symmetric to TRON's
|
|
8
|
+
* `createFacilitatorTronSigner`. Upstream only ships `toFacilitatorEvmSigner`,
|
|
9
|
+
* which requires the integrator to hand-wire every on-chain op
|
|
10
|
+
* (readContract / writeContract / sendTransaction / waitForTransactionReceipt /
|
|
11
|
+
* getCode / verifyTypedData). This module builds all of that from a viem
|
|
12
|
+
* public client + a key-custody wallet, so non-custodial signing is collected
|
|
13
|
+
* in one place.
|
|
14
|
+
*
|
|
15
|
+
* Upgrade safety: this file ONLY consumes upstream's public surface
|
|
16
|
+
* (`toFacilitatorEvmSigner` + the `FacilitatorEvmSigner` type). It never edits
|
|
17
|
+
* `signer.ts` or `index.ts`, so pulling a newer upstream is conflict-free as
|
|
18
|
+
* long as that public surface is unchanged. The agent-wallet dependency is kept
|
|
19
|
+
* out via the structural {@link FacilitatorEvmWallet} interface — any object of
|
|
20
|
+
* that shape works (agent-wallet's `EvmSigner`, a keystore, hardware, etc.).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A wallet that signs EIP-1559 settlement transactions without ever exposing
|
|
25
|
+
* its private key to the SDK — structurally compatible with
|
|
26
|
+
* `@bankofai/agent-wallet`'s `EvmSigner`, but intentionally not coupled to it.
|
|
27
|
+
*
|
|
28
|
+
* `signTransaction` returns a serialized signed transaction hex. The `0x`
|
|
29
|
+
* prefix is optional: agent-wallet currently strips it (see SDK issue #2), so
|
|
30
|
+
* the broadcast path normalizes defensively.
|
|
31
|
+
*/
|
|
32
|
+
interface FacilitatorEvmWallet {
|
|
33
|
+
/** Facilitator EVM address (0x-prefixed, checksummed or lowercase). */
|
|
34
|
+
readonly address: `0x${string}`;
|
|
35
|
+
/**
|
|
36
|
+
* Sign a fully-specified EIP-1559 transaction and return the serialized
|
|
37
|
+
* signed tx hex (with or without the `0x` prefix).
|
|
38
|
+
*/
|
|
39
|
+
signTransaction(tx: {
|
|
40
|
+
to: `0x${string}`;
|
|
41
|
+
data: `0x${string}`;
|
|
42
|
+
value: bigint;
|
|
43
|
+
nonce: number;
|
|
44
|
+
gas: bigint;
|
|
45
|
+
maxFeePerGas: bigint;
|
|
46
|
+
maxPriorityFeePerGas: bigint;
|
|
47
|
+
chainId: number;
|
|
48
|
+
}): Promise<string>;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The viem public-client surface this factory needs. Defined as a `Pick` of
|
|
52
|
+
* viem's `PublicClient` so a real client is assignable WITHOUT a cast — using a
|
|
53
|
+
* hand-rolled structural interface with wider param types (e.g.
|
|
54
|
+
* `verifyTypedData`'s `types: Record<string, unknown>`) would fail under
|
|
55
|
+
* `strictFunctionTypes` and force every integrator to cast (see SDK issue #5).
|
|
56
|
+
*
|
|
57
|
+
* In tests, pass a mock via `as unknown as FacilitatorEvmPublicClient`.
|
|
58
|
+
*/
|
|
59
|
+
type FacilitatorEvmPublicClient = Pick<PublicClient, "getChainId" | "getTransactionCount" | "estimateFeesPerGas" | "estimateGas" | "sendRawTransaction" | "readContract" | "verifyTypedData" | "getCode" | "waitForTransactionReceipt">;
|
|
60
|
+
/** Options for {@link createFacilitatorEvmSigner}. */
|
|
61
|
+
interface FacilitatorEvmSignerOptions {
|
|
62
|
+
/**
|
|
63
|
+
* Gas limit to use when a per-call `gas` is not supplied. When unset, gas is
|
|
64
|
+
* estimated per transaction via `estimateGas`.
|
|
65
|
+
*/
|
|
66
|
+
defaultGas?: bigint;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* One transaction for {@link GasSponsoringFacilitatorEvmSigner.sendTransactions}:
|
|
70
|
+
* either a pre-signed serialized tx (broadcast as-is) or an unsigned call intent
|
|
71
|
+
* (signed by the facilitator wallet, then broadcast). Mirrors the
|
|
72
|
+
* `@bankofai/x402-extensions` `TransactionRequest` shape without importing it,
|
|
73
|
+
* so this overlay stays dependency-free.
|
|
74
|
+
*/
|
|
75
|
+
type EvmTransactionRequest = `0x${string}` | {
|
|
76
|
+
to: `0x${string}`;
|
|
77
|
+
data: `0x${string}`;
|
|
78
|
+
gas?: bigint;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* {@link FacilitatorEvmSigner} plus `sendTransactions` — the shape the ERC-20
|
|
82
|
+
* approval gas-sponsoring extension expects (it broadcasts the client's
|
|
83
|
+
* pre-signed `approve` bundled with `settle`).
|
|
84
|
+
*/
|
|
85
|
+
type GasSponsoringFacilitatorEvmSigner = FacilitatorEvmSigner & {
|
|
86
|
+
sendTransactions(transactions: readonly EvmTransactionRequest[]): Promise<`0x${string}`[]>;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Creates a {@link FacilitatorEvmSigner} from a viem public client and a
|
|
90
|
+
* key-custody wallet — the EVM counterpart of `createFacilitatorTronSigner`.
|
|
91
|
+
*
|
|
92
|
+
* The transaction is built (nonce / EIP-1559 fees / gas), handed to the wallet
|
|
93
|
+
* to sign (the private key never enters the SDK), then broadcast — collecting
|
|
94
|
+
* all on-chain ops so each integrator no longer re-implements them.
|
|
95
|
+
*
|
|
96
|
+
* @param publicClient - viem public client used for reads, verification, and broadcast.
|
|
97
|
+
* @param wallet - The wallet that signs settlement transactions.
|
|
98
|
+
* @param options - Optional default gas limit.
|
|
99
|
+
* @returns A {@link FacilitatorEvmSigner} backed by the public client + wallet.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* const publicClient = createPublicClient({ chain: base, transport: http() });
|
|
104
|
+
* const signer = createFacilitatorEvmSigner(publicClient, agentWallet);
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
declare function createFacilitatorEvmSigner(publicClient: FacilitatorEvmPublicClient, wallet: FacilitatorEvmWallet, options?: FacilitatorEvmSignerOptions): GasSponsoringFacilitatorEvmSigner;
|
|
108
|
+
|
|
109
|
+
export { type EvmTransactionRequest, type FacilitatorEvmPublicClient, type FacilitatorEvmSignerOptions, type FacilitatorEvmWallet, type GasSponsoringFacilitatorEvmSigner, createFacilitatorEvmSigner };
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/facilitator/agent-wallet.ts
|
|
21
|
+
var agent_wallet_exports = {};
|
|
22
|
+
__export(agent_wallet_exports, {
|
|
23
|
+
createFacilitatorEvmSigner: () => createFacilitatorEvmSigner
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(agent_wallet_exports);
|
|
26
|
+
var import_viem = require("viem");
|
|
27
|
+
|
|
28
|
+
// src/signer.ts
|
|
29
|
+
function toFacilitatorEvmSigner(client) {
|
|
30
|
+
return {
|
|
31
|
+
...client,
|
|
32
|
+
getAddresses: () => [client.address]
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// src/facilitator/agent-wallet.ts
|
|
37
|
+
function appendDataSuffix(data, suffix) {
|
|
38
|
+
if (!suffix || suffix === "0x") {
|
|
39
|
+
return data;
|
|
40
|
+
}
|
|
41
|
+
return `${data}${suffix.slice(2)}`;
|
|
42
|
+
}
|
|
43
|
+
function createFacilitatorEvmSigner(publicClient, wallet, options = {}) {
|
|
44
|
+
const client = publicClient;
|
|
45
|
+
async function buildSignBroadcast(to, data, gasOverride) {
|
|
46
|
+
const value = 0n;
|
|
47
|
+
const [chainId, nonce, fees] = await Promise.all([
|
|
48
|
+
client.getChainId(),
|
|
49
|
+
client.getTransactionCount({ address: wallet.address }),
|
|
50
|
+
client.estimateFeesPerGas()
|
|
51
|
+
]);
|
|
52
|
+
const gas = gasOverride ?? options.defaultGas ?? await client.estimateGas({ account: wallet.address, to, data, value });
|
|
53
|
+
const signed = await wallet.signTransaction({
|
|
54
|
+
to,
|
|
55
|
+
data,
|
|
56
|
+
value,
|
|
57
|
+
nonce,
|
|
58
|
+
gas,
|
|
59
|
+
maxFeePerGas: fees.maxFeePerGas,
|
|
60
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas,
|
|
61
|
+
chainId
|
|
62
|
+
});
|
|
63
|
+
const serializedTransaction = `0x${signed.replace(/^0x/, "")}`;
|
|
64
|
+
return client.sendRawTransaction({ serializedTransaction });
|
|
65
|
+
}
|
|
66
|
+
const base = toFacilitatorEvmSigner({
|
|
67
|
+
address: wallet.address,
|
|
68
|
+
readContract: (args) => client.readContract(args),
|
|
69
|
+
verifyTypedData: (args) => client.verifyTypedData(args),
|
|
70
|
+
getCode: (args) => client.getCode(args),
|
|
71
|
+
waitForTransactionReceipt: (args) => client.waitForTransactionReceipt(args),
|
|
72
|
+
writeContract: (args) => {
|
|
73
|
+
const data = appendDataSuffix(
|
|
74
|
+
(0, import_viem.encodeFunctionData)({
|
|
75
|
+
abi: args.abi,
|
|
76
|
+
functionName: args.functionName,
|
|
77
|
+
args: args.args
|
|
78
|
+
}),
|
|
79
|
+
args.dataSuffix
|
|
80
|
+
);
|
|
81
|
+
return buildSignBroadcast(args.address, data, args.gas);
|
|
82
|
+
},
|
|
83
|
+
sendTransaction: (args) => buildSignBroadcast(args.to, args.data)
|
|
84
|
+
});
|
|
85
|
+
return {
|
|
86
|
+
...base,
|
|
87
|
+
async sendTransactions(transactions) {
|
|
88
|
+
const hashes = [];
|
|
89
|
+
for (const tx of transactions) {
|
|
90
|
+
if (typeof tx === "string") {
|
|
91
|
+
const serializedTransaction = `0x${tx.replace(/^0x/, "")}`;
|
|
92
|
+
hashes.push(await client.sendRawTransaction({ serializedTransaction }));
|
|
93
|
+
} else {
|
|
94
|
+
hashes.push(await buildSignBroadcast(tx.to, tx.data, tx.gas));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return hashes;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
102
|
+
0 && (module.exports = {
|
|
103
|
+
createFacilitatorEvmSigner
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=agent-wallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/facilitator/agent-wallet.ts","../../../src/signer.ts"],"sourcesContent":["/**\n * BankofAI overlay — NOT from upstream @x402/evm.\n *\n * Adds a wallet-bridge factory for facilitators, symmetric to TRON's\n * `createFacilitatorTronSigner`. Upstream only ships `toFacilitatorEvmSigner`,\n * which requires the integrator to hand-wire every on-chain op\n * (readContract / writeContract / sendTransaction / waitForTransactionReceipt /\n * getCode / verifyTypedData). This module builds all of that from a viem\n * public client + a key-custody wallet, so non-custodial signing is collected\n * in one place.\n *\n * Upgrade safety: this file ONLY consumes upstream's public surface\n * (`toFacilitatorEvmSigner` + the `FacilitatorEvmSigner` type). It never edits\n * `signer.ts` or `index.ts`, so pulling a newer upstream is conflict-free as\n * long as that public surface is unchanged. The agent-wallet dependency is kept\n * out via the structural {@link FacilitatorEvmWallet} interface — any object of\n * that shape works (agent-wallet's `EvmSigner`, a keystore, hardware, etc.).\n */\nimport { encodeFunctionData, type Abi, type Log, type PublicClient } from \"viem\";\n\nimport { toFacilitatorEvmSigner, type FacilitatorEvmSigner } from \"../signer\";\n\n/**\n * A wallet that signs EIP-1559 settlement transactions without ever exposing\n * its private key to the SDK — structurally compatible with\n * `@bankofai/agent-wallet`'s `EvmSigner`, but intentionally not coupled to it.\n *\n * `signTransaction` returns a serialized signed transaction hex. The `0x`\n * prefix is optional: agent-wallet currently strips it (see SDK issue #2), so\n * the broadcast path normalizes defensively.\n */\nexport interface FacilitatorEvmWallet {\n /** Facilitator EVM address (0x-prefixed, checksummed or lowercase). */\n readonly address: `0x${string}`;\n /**\n * Sign a fully-specified EIP-1559 transaction and return the serialized\n * signed tx hex (with or without the `0x` prefix).\n */\n signTransaction(tx: {\n to: `0x${string}`;\n data: `0x${string}`;\n value: bigint;\n nonce: number;\n gas: bigint;\n maxFeePerGas: bigint;\n maxPriorityFeePerGas: bigint;\n chainId: number;\n }): Promise<string>;\n}\n\n/**\n * The viem public-client surface this factory needs. Defined as a `Pick` of\n * viem's `PublicClient` so a real client is assignable WITHOUT a cast — using a\n * hand-rolled structural interface with wider param types (e.g.\n * `verifyTypedData`'s `types: Record<string, unknown>`) would fail under\n * `strictFunctionTypes` and force every integrator to cast (see SDK issue #5).\n *\n * In tests, pass a mock via `as unknown as FacilitatorEvmPublicClient`.\n */\nexport type FacilitatorEvmPublicClient = Pick<\n PublicClient,\n | \"getChainId\"\n | \"getTransactionCount\"\n | \"estimateFeesPerGas\"\n | \"estimateGas\"\n | \"sendRawTransaction\"\n | \"readContract\"\n | \"verifyTypedData\"\n | \"getCode\"\n | \"waitForTransactionReceipt\"\n>;\n\n/**\n * Loose view of the public client for internal forwarding. viem's read/verify\n * methods are generic and strict, while upstream's `FacilitatorEvmSigner` shape\n * is loose; we narrow once here (the runtime client provides all these methods)\n * so the loose/strict impedance is resolved inside the SDK, not by integrators.\n */\ntype LooseEvmPublicClient = {\n getChainId(): Promise<number>;\n getTransactionCount(args: { address: `0x${string}` }): Promise<number>;\n estimateFeesPerGas(): Promise<{ maxFeePerGas: bigint; maxPriorityFeePerGas: bigint }>;\n estimateGas(args: {\n account: `0x${string}`;\n to: `0x${string}`;\n data: `0x${string}`;\n value?: bigint;\n }): Promise<bigint>;\n sendRawTransaction(args: { serializedTransaction: `0x${string}` }): Promise<`0x${string}`>;\n readContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\n verifyTypedData(args: {\n address: `0x${string}`;\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n primaryType: string;\n message: Record<string, unknown>;\n signature: `0x${string}`;\n }): Promise<boolean>;\n getCode(args: { address: `0x${string}` }): Promise<`0x${string}` | undefined>;\n waitForTransactionReceipt(args: {\n hash: `0x${string}`;\n }): Promise<{ status: string; logs?: readonly Log[] }>;\n};\n\n/** Options for {@link createFacilitatorEvmSigner}. */\nexport interface FacilitatorEvmSignerOptions {\n /**\n * Gas limit to use when a per-call `gas` is not supplied. When unset, gas is\n * estimated per transaction via `estimateGas`.\n */\n defaultGas?: bigint;\n}\n\n/**\n * One transaction for {@link GasSponsoringFacilitatorEvmSigner.sendTransactions}:\n * either a pre-signed serialized tx (broadcast as-is) or an unsigned call intent\n * (signed by the facilitator wallet, then broadcast). Mirrors the\n * `@bankofai/x402-extensions` `TransactionRequest` shape without importing it,\n * so this overlay stays dependency-free.\n */\nexport type EvmTransactionRequest =\n | `0x${string}`\n | { to: `0x${string}`; data: `0x${string}`; gas?: bigint };\n\n/**\n * {@link FacilitatorEvmSigner} plus `sendTransactions` — the shape the ERC-20\n * approval gas-sponsoring extension expects (it broadcasts the client's\n * pre-signed `approve` bundled with `settle`).\n */\nexport type GasSponsoringFacilitatorEvmSigner = FacilitatorEvmSigner & {\n sendTransactions(transactions: readonly EvmTransactionRequest[]): Promise<`0x${string}`[]>;\n};\n\n/**\n * Appends an extension data suffix (e.g. a builder code) to encoded calldata.\n *\n * @param data - The encoded function calldata.\n * @param suffix - Optional `0x`-prefixed suffix to append.\n * @returns The calldata with the suffix appended, or `data` unchanged.\n */\nfunction appendDataSuffix(data: `0x${string}`, suffix?: `0x${string}`): `0x${string}` {\n if (!suffix || suffix === \"0x\") {\n return data;\n }\n return `${data}${suffix.slice(2)}` as `0x${string}`;\n}\n\n/**\n * Creates a {@link FacilitatorEvmSigner} from a viem public client and a\n * key-custody wallet — the EVM counterpart of `createFacilitatorTronSigner`.\n *\n * The transaction is built (nonce / EIP-1559 fees / gas), handed to the wallet\n * to sign (the private key never enters the SDK), then broadcast — collecting\n * all on-chain ops so each integrator no longer re-implements them.\n *\n * @param publicClient - viem public client used for reads, verification, and broadcast.\n * @param wallet - The wallet that signs settlement transactions.\n * @param options - Optional default gas limit.\n * @returns A {@link FacilitatorEvmSigner} backed by the public client + wallet.\n *\n * @example\n * ```typescript\n * const publicClient = createPublicClient({ chain: base, transport: http() });\n * const signer = createFacilitatorEvmSigner(publicClient, agentWallet);\n * ```\n */\nexport function createFacilitatorEvmSigner(\n publicClient: FacilitatorEvmPublicClient,\n wallet: FacilitatorEvmWallet,\n options: FacilitatorEvmSignerOptions = {},\n): GasSponsoringFacilitatorEvmSigner {\n // Narrow once: viem's strict generic methods → the loose shape we forward to\n // upstream's FacilitatorEvmSigner. Keeps the cast inside the SDK (issue #5).\n const client = publicClient as unknown as LooseEvmPublicClient;\n\n // Build → wallet-sign → broadcast. Shared by writeContract and sendTransaction.\n async function buildSignBroadcast(\n to: `0x${string}`,\n data: `0x${string}`,\n gasOverride?: bigint,\n ): Promise<`0x${string}`> {\n const value = 0n; // x402 settlement never transfers native value.\n const [chainId, nonce, fees] = await Promise.all([\n client.getChainId(),\n client.getTransactionCount({ address: wallet.address }),\n client.estimateFeesPerGas(),\n ]);\n const gas =\n gasOverride ??\n options.defaultGas ??\n (await client.estimateGas({ account: wallet.address, to, data, value }));\n\n const signed = await wallet.signTransaction({\n to,\n data,\n value,\n nonce,\n gas,\n maxFeePerGas: fees.maxFeePerGas,\n maxPriorityFeePerGas: fees.maxPriorityFeePerGas,\n chainId,\n });\n\n // agent-wallet strips the `0x` prefix (SDK issue #2); strip-then-prefix is\n // robust whether or not the prefix is present, so it survives an upstream\n // fix that restores it. Carried over from the v1 facilitator signer.\n const serializedTransaction = `0x${signed.replace(/^0x/, \"\")}` as `0x${string}`;\n return client.sendRawTransaction({ serializedTransaction });\n }\n\n const base = toFacilitatorEvmSigner({\n address: wallet.address,\n readContract: args => client.readContract(args),\n verifyTypedData: args => client.verifyTypedData(args),\n getCode: args => client.getCode(args),\n waitForTransactionReceipt: args => client.waitForTransactionReceipt(args),\n writeContract: args => {\n const data = appendDataSuffix(\n encodeFunctionData({\n abi: args.abi as Abi,\n functionName: args.functionName,\n args: args.args,\n }),\n args.dataSuffix,\n );\n return buildSignBroadcast(args.address, data, args.gas);\n },\n sendTransaction: args => buildSignBroadcast(args.to, args.data),\n });\n\n // Batch broadcast for the ERC-20 approval gas-sponsoring extension: the\n // client's pre-signed `approve` (a serialized tx) is broadcast as-is; the\n // `settle` call intent is signed by the facilitator wallet and broadcast.\n // Executed sequentially; hashes returned in order (settle is last).\n return {\n ...base,\n async sendTransactions(transactions) {\n const hashes: `0x${string}`[] = [];\n for (const tx of transactions) {\n if (typeof tx === \"string\") {\n const serializedTransaction = `0x${tx.replace(/^0x/, \"\")}` as `0x${string}`;\n hashes.push(await client.sendRawTransaction({ serializedTransaction }));\n } else {\n hashes.push(await buildSignBroadcast(tx.to, tx.data, tx.gas));\n }\n }\n return hashes;\n },\n };\n}\n","import type { Log } from \"viem\";\n\n/**\n * ClientEvmSigner - Used by x402 clients to sign payment authorizations.\n *\n * Typically a viem WalletClient extended with publicActions:\n * ```typescript\n * const client = createWalletClient({\n * account: privateKeyToAccount('0x...'),\n * chain: baseSepolia,\n * transport: http(),\n * }).extend(publicActions);\n * ```\n *\n * Or composed via `toClientEvmSigner(account, publicClient)`.\n */\nexport type ClientEvmSigner = {\n readonly address: `0x${string}`;\n signTypedData(message: {\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n primaryType: string;\n message: Record<string, unknown>;\n }): Promise<`0x${string}`>;\n /**\n * Optional on-chain reads.\n * Required only for extension enrichment (EIP-2612 / ERC-20 approval).\n */\n readContract?(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\n /**\n * Optional: Signs a raw EIP-1559 transaction without broadcasting.\n * Required for ERC-20 approval gas sponsoring when the token lacks EIP-2612.\n */\n signTransaction?(args: {\n to: `0x${string}`;\n data: `0x${string}`;\n nonce: number;\n gas: bigint;\n maxFeePerGas: bigint;\n maxPriorityFeePerGas: bigint;\n chainId: number;\n }): Promise<`0x${string}`>;\n /**\n * Optional: Gets the current transaction count (nonce) for an address.\n * Required for ERC-20 approval gas sponsoring.\n */\n getTransactionCount?(args: { address: `0x${string}` }): Promise<number>;\n /**\n * Optional: Estimates current gas fees per gas.\n * Required for ERC-20 approval gas sponsoring.\n */\n estimateFeesPerGas?(): Promise<{ maxFeePerGas: bigint; maxPriorityFeePerGas: bigint }>;\n};\n\n/**\n * FacilitatorEvmSigner - Used by x402 facilitators to verify and settle payments\n * This is typically a viem PublicClient + WalletClient combination that can\n * read contract state, verify signatures, write transactions, and wait for receipts\n *\n * Supports multiple addresses for load balancing, key rotation, and high availability\n */\nexport type FacilitatorEvmSigner = {\n /**\n * Get all addresses this facilitator can use for signing\n * Enables dynamic address selection for load balancing and key rotation\n */\n getAddresses(): readonly `0x${string}`[];\n\n readContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\n verifyTypedData(args: {\n address: `0x${string}`;\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n primaryType: string;\n message: Record<string, unknown>;\n signature: `0x${string}`;\n }): Promise<boolean>;\n writeContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args: readonly unknown[];\n gas?: bigint;\n dataSuffix?: `0x${string}`;\n }): Promise<`0x${string}`>;\n sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>;\n waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{\n status: string;\n logs?: readonly Log[];\n }>;\n getCode(args: { address: `0x${string}` }): Promise<`0x${string}` | undefined>;\n};\n\n/**\n * Composes a ClientEvmSigner from a local account and a public client.\n *\n * Use this when your signer (e.g., `privateKeyToAccount`) doesn't have\n * `readContract`. The `publicClient` provides the on-chain read capability.\n *\n * Alternatively, use a WalletClient extended with publicActions directly:\n * ```typescript\n * const signer = createWalletClient({\n * account: privateKeyToAccount('0x...'),\n * chain: baseSepolia,\n * transport: http(),\n * }).extend(publicActions);\n * ```\n *\n * @param signer - A signer with `address` and `signTypedData` (and optionally `readContract`)\n * @param publicClient - A client with optional read/nonce/fee helpers\n * @param publicClient.readContract - The readContract method from the public client\n * @param publicClient.getTransactionCount - Optional getTransactionCount for ERC-20 approval\n * @param publicClient.estimateFeesPerGas - Optional estimateFeesPerGas for ERC-20 approval\n * @returns A ClientEvmSigner with any available optional capabilities\n *\n * @example\n * ```typescript\n * const account = privateKeyToAccount(\"0x...\");\n * const publicClient = createPublicClient({ chain: baseSepolia, transport: http() });\n * const signer = toClientEvmSigner(account, publicClient);\n * ```\n */\nexport function toClientEvmSigner(\n signer: Omit<ClientEvmSigner, \"readContract\"> & {\n readContract?: ClientEvmSigner[\"readContract\"];\n },\n publicClient?: {\n readContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\n getTransactionCount?(args: { address: `0x${string}` }): Promise<number>;\n estimateFeesPerGas?(): Promise<{ maxFeePerGas: bigint; maxPriorityFeePerGas: bigint }>;\n },\n): ClientEvmSigner {\n const readContract = signer.readContract ?? publicClient?.readContract.bind(publicClient);\n\n const result: ClientEvmSigner = {\n address: signer.address,\n signTypedData: msg => signer.signTypedData(msg),\n };\n\n if (readContract) {\n result.readContract = readContract;\n }\n\n // Forward optional capabilities from signer or publicClient\n const signTransaction = signer.signTransaction;\n if (signTransaction) {\n result.signTransaction = args => signTransaction(args);\n }\n\n const getTransactionCount =\n signer.getTransactionCount ?? publicClient?.getTransactionCount?.bind(publicClient);\n if (getTransactionCount) {\n result.getTransactionCount = args => getTransactionCount(args);\n }\n\n const estimateFeesPerGas =\n signer.estimateFeesPerGas ?? publicClient?.estimateFeesPerGas?.bind(publicClient);\n if (estimateFeesPerGas) {\n result.estimateFeesPerGas = () => estimateFeesPerGas();\n }\n\n return result;\n}\n\n/**\n * Converts a viem client with single address to a FacilitatorEvmSigner\n * Wraps the single address in a getAddresses() function for compatibility\n *\n * @param client - The client to convert (must have 'address' property)\n * @returns FacilitatorEvmSigner with getAddresses() support\n */\nexport function toFacilitatorEvmSigner(\n client: Omit<FacilitatorEvmSigner, \"getAddresses\"> & { address: `0x${string}` },\n): FacilitatorEvmSigner {\n return {\n ...client,\n getAddresses: () => [client.address],\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAkBA,kBAA0E;;;ACwKnE,SAAS,uBACd,QACsB;AACtB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,cAAc,MAAM,CAAC,OAAO,OAAO;AAAA,EACrC;AACF;;;ADhDA,SAAS,iBAAiB,MAAqB,QAAuC;AACpF,MAAI,CAAC,UAAU,WAAW,MAAM;AAC9B,WAAO;AAAA,EACT;AACA,SAAO,GAAG,IAAI,GAAG,OAAO,MAAM,CAAC,CAAC;AAClC;AAqBO,SAAS,2BACd,cACA,QACA,UAAuC,CAAC,GACL;AAGnC,QAAM,SAAS;AAGf,iBAAe,mBACb,IACA,MACA,aACwB;AACxB,UAAM,QAAQ;AACd,UAAM,CAAC,SAAS,OAAO,IAAI,IAAI,MAAM,QAAQ,IAAI;AAAA,MAC/C,OAAO,WAAW;AAAA,MAClB,OAAO,oBAAoB,EAAE,SAAS,OAAO,QAAQ,CAAC;AAAA,MACtD,OAAO,mBAAmB;AAAA,IAC5B,CAAC;AACD,UAAM,MACJ,eACA,QAAQ,cACP,MAAM,OAAO,YAAY,EAAE,SAAS,OAAO,SAAS,IAAI,MAAM,MAAM,CAAC;AAExE,UAAM,SAAS,MAAM,OAAO,gBAAgB;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc,KAAK;AAAA,MACnB,sBAAsB,KAAK;AAAA,MAC3B;AAAA,IACF,CAAC;AAKD,UAAM,wBAAwB,KAAK,OAAO,QAAQ,OAAO,EAAE,CAAC;AAC5D,WAAO,OAAO,mBAAmB,EAAE,sBAAsB,CAAC;AAAA,EAC5D;AAEA,QAAM,OAAO,uBAAuB;AAAA,IAClC,SAAS,OAAO;AAAA,IAChB,cAAc,UAAQ,OAAO,aAAa,IAAI;AAAA,IAC9C,iBAAiB,UAAQ,OAAO,gBAAgB,IAAI;AAAA,IACpD,SAAS,UAAQ,OAAO,QAAQ,IAAI;AAAA,IACpC,2BAA2B,UAAQ,OAAO,0BAA0B,IAAI;AAAA,IACxE,eAAe,UAAQ;AACrB,YAAM,OAAO;AAAA,YACX,gCAAmB;AAAA,UACjB,KAAK,KAAK;AAAA,UACV,cAAc,KAAK;AAAA,UACnB,MAAM,KAAK;AAAA,QACb,CAAC;AAAA,QACD,KAAK;AAAA,MACP;AACA,aAAO,mBAAmB,KAAK,SAAS,MAAM,KAAK,GAAG;AAAA,IACxD;AAAA,IACA,iBAAiB,UAAQ,mBAAmB,KAAK,IAAI,KAAK,IAAI;AAAA,EAChE,CAAC;AAMD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,iBAAiB,cAAc;AACnC,YAAM,SAA0B,CAAC;AACjC,iBAAW,MAAM,cAAc;AAC7B,YAAI,OAAO,OAAO,UAAU;AAC1B,gBAAM,wBAAwB,KAAK,GAAG,QAAQ,OAAO,EAAE,CAAC;AACxD,iBAAO,KAAK,MAAM,OAAO,mBAAmB,EAAE,sBAAsB,CAAC,CAAC;AAAA,QACxE,OAAO;AACL,iBAAO,KAAK,MAAM,mBAAmB,GAAG,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC;AAAA,QAC9D;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
|