| import { SchemeNetworkClient, PaymentRequirements, PaymentPayloadContext, PaymentPayloadResult } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from './signer-3KGwtdNT.js'; | ||
| /** | ||
| * EVM client implementation for the Exact payment scheme. | ||
| * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows. | ||
| * | ||
| * Routes to the appropriate authorization method based on | ||
| * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009 | ||
| * for backward compatibility with older facilitators. | ||
| * | ||
| * When the server advertises `eip2612GasSponsoring` and the asset transfer | ||
| * method is `permit2`, the scheme automatically signs an EIP-2612 permit | ||
| * if the user lacks Permit2 approval. This requires `readContract` on the signer. | ||
| */ | ||
| declare class ExactEvmScheme implements SchemeNetworkClient { | ||
| private readonly signer; | ||
| readonly scheme = "exact"; | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations. | ||
| * Must support `readContract` for EIP-2612 gas sponsoring. | ||
| * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
| constructor(signer: ClientEvmSigner); | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod. | ||
| * | ||
| * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the | ||
| * signer supports `readContract`, automatically signs an EIP-2612 permit | ||
| * when Permit2 allowance is insufficient. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @param context - Optional context with server-declared extensions | ||
| * @returns Promise resolving to a payment payload result (with optional extensions) | ||
| */ | ||
| createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>; | ||
| /** | ||
| * Attempts to sign an EIP-2612 permit for gasless Permit2 approval. | ||
| * | ||
| * Returns extension data if: | ||
| * 1. Server advertises eip2612GasSponsoring | ||
| * 2. Signer has readContract capability | ||
| * 3. Current Permit2 allowance is insufficient | ||
| * | ||
| * Returns undefined if the extension should not be used. | ||
| * | ||
| * @param requirements - The payment requirements from the server | ||
| * @param result - The payment payload result from the scheme | ||
| * @param context - Optional context containing server extensions and metadata | ||
| * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable | ||
| */ | ||
| private trySignEip2612Permit; | ||
| } | ||
| /** | ||
| * ERC20 allowance ABI for checking approval status. | ||
| */ | ||
| declare const erc20AllowanceAbi: readonly [{ | ||
| readonly type: "function"; | ||
| readonly name: "allowance"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "spender"; | ||
| readonly type: "address"; | ||
| }]; | ||
| readonly outputs: readonly [{ | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }]; | ||
| /** | ||
| * Creates transaction data to approve Permit2 to spend tokens. | ||
| * The user sends this transaction (paying gas) before using Permit2 flow. | ||
| * | ||
| * @param tokenAddress - The ERC20 token contract address | ||
| * @returns Transaction data to send for approval | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const tx = createPermit2ApprovalTx("0x..."); | ||
| * await walletClient.sendTransaction({ | ||
| * to: tx.to, | ||
| * data: tx.data, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createPermit2ApprovalTx(tokenAddress: `0x${string}`): { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }; | ||
| /** | ||
| * Parameters for checking Permit2 allowance. | ||
| * Application provides these to check if approval is needed. | ||
| */ | ||
| interface Permit2AllowanceParams { | ||
| tokenAddress: `0x${string}`; | ||
| ownerAddress: `0x${string}`; | ||
| } | ||
| /** | ||
| * Returns contract read parameters for checking Permit2 allowance. | ||
| * Use with a public client to check if the user has approved Permit2. | ||
| * | ||
| * @param params - The allowance check parameters | ||
| * @returns Contract read parameters for checking allowance | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const readParams = getPermit2AllowanceReadParams({ | ||
| * tokenAddress: "0x...", | ||
| * ownerAddress: "0x...", | ||
| * }); | ||
| * | ||
| * const allowance = await publicClient.readContract(readParams); | ||
| * const needsApproval = allowance < requiredAmount; | ||
| * ``` | ||
| */ | ||
| declare function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): { | ||
| address: `0x${string}`; | ||
| abi: typeof erc20AllowanceAbi; | ||
| functionName: "allowance"; | ||
| args: [`0x${string}`, `0x${string}`]; | ||
| }; | ||
| export { ExactEvmScheme as E, type Permit2AllowanceParams as P, createPermit2ApprovalTx as c, erc20AllowanceAbi as e, getPermit2AllowanceReadParams as g }; |
| /** | ||
| * ClientEvmSigner - Used by x402 clients to sign payment authorizations. | ||
| * | ||
| * Typically a viem WalletClient extended with publicActions: | ||
| * ```typescript | ||
| * const client = createWalletClient({ | ||
| * account: privateKeyToAccount('0x...'), | ||
| * chain: baseSepolia, | ||
| * transport: http(), | ||
| * }).extend(publicActions); | ||
| * ``` | ||
| * | ||
| * Or composed via `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
| type ClientEvmSigner = { | ||
| readonly address: `0x${string}`; | ||
| signTypedData(message: { | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| }): Promise<`0x${string}`>; | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| }; | ||
| /** | ||
| * FacilitatorEvmSigner - Used by x402 facilitators to verify and settle payments | ||
| * This is typically a viem PublicClient + WalletClient combination that can | ||
| * read contract state, verify signatures, write transactions, and wait for receipts | ||
| * | ||
| * Supports multiple addresses for load balancing, key rotation, and high availability | ||
| */ | ||
| type FacilitatorEvmSigner = { | ||
| /** | ||
| * Get all addresses this facilitator can use for signing | ||
| * Enables dynamic address selection for load balancing and key rotation | ||
| */ | ||
| getAddresses(): readonly `0x${string}`[]; | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| verifyTypedData(args: { | ||
| address: `0x${string}`; | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| signature: `0x${string}`; | ||
| }): Promise<boolean>; | ||
| writeContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args: readonly unknown[]; | ||
| }): Promise<`0x${string}`>; | ||
| sendTransaction(args: { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }): Promise<`0x${string}`>; | ||
| waitForTransactionReceipt(args: { | ||
| hash: `0x${string}`; | ||
| }): Promise<{ | ||
| status: string; | ||
| }>; | ||
| getCode(args: { | ||
| address: `0x${string}`; | ||
| }): Promise<`0x${string}` | undefined>; | ||
| }; | ||
| /** | ||
| * Composes a ClientEvmSigner from a local account and a public client. | ||
| * | ||
| * Use this when your signer (e.g., `privateKeyToAccount`) doesn't have | ||
| * `readContract`. The `publicClient` provides the on-chain read capability. | ||
| * | ||
| * Alternatively, use a WalletClient extended with publicActions directly: | ||
| * ```typescript | ||
| * const signer = createWalletClient({ | ||
| * account: privateKeyToAccount('0x...'), | ||
| * chain: baseSepolia, | ||
| * transport: http(), | ||
| * }).extend(publicActions); | ||
| * ``` | ||
| * | ||
| * @param signer - A signer with `address` and `signTypedData` (and optionally `readContract`) | ||
| * @param publicClient - A client with `readContract` (required if signer lacks it) | ||
| * @param publicClient.readContract - The readContract method from the public client | ||
| * @returns A complete ClientEvmSigner | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const account = privateKeyToAccount("0x..."); | ||
| * const publicClient = createPublicClient({ chain: baseSepolia, transport: http() }); | ||
| * const signer = toClientEvmSigner(account, publicClient); | ||
| * ``` | ||
| */ | ||
| declare function toClientEvmSigner(signer: Omit<ClientEvmSigner, "readContract"> & { | ||
| readContract?: ClientEvmSigner["readContract"]; | ||
| }, publicClient?: { | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| }): ClientEvmSigner; | ||
| /** | ||
| * Converts a viem client with single address to a FacilitatorEvmSigner | ||
| * Wraps the single address in a getAddresses() function for compatibility | ||
| * | ||
| * @param client - The client to convert (must have 'address' property) | ||
| * @returns FacilitatorEvmSigner with getAddresses() support | ||
| */ | ||
| declare function toFacilitatorEvmSigner(client: Omit<FacilitatorEvmSigner, "getAddresses"> & { | ||
| address: `0x${string}`; | ||
| }): FacilitatorEvmSigner; | ||
| export { type ClientEvmSigner as C, type FacilitatorEvmSigner as F, toFacilitatorEvmSigner as a, toClientEvmSigner as t }; |
| import { | ||
| ExactEvmSchemeV1, | ||
| NETWORKS, | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| createNonce, | ||
| createPermit2Nonce, | ||
| eip2612NoncesAbi, | ||
| eip2612PermitTypes, | ||
| permit2WitnessTypes, | ||
| x402ExactPermit2ProxyAddress | ||
| } from "./chunk-GSU4DHTC.mjs"; | ||
| // src/exact/client/scheme.ts | ||
| import { EIP2612_GAS_SPONSORING } from "@x402/extensions"; | ||
| import { getAddress as getAddress4 } from "viem"; | ||
| // src/exact/client/eip3009.ts | ||
| import { getAddress } from "viem"; | ||
| async function createEIP3009Payload(signer, x402Version, paymentRequirements) { | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: signer.address, | ||
| to: getAddress(paymentRequirements.payTo), | ||
| value: paymentRequirements.amount, | ||
| validAfter: (now - 600).toString(), | ||
| validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements); | ||
| const payload = { | ||
| authorization, | ||
| signature | ||
| }; | ||
| return { | ||
| x402Version, | ||
| payload | ||
| }; | ||
| } | ||
| async function signEIP3009Authorization(signer, authorization, requirements) { | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| throw new Error( | ||
| `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}` | ||
| ); | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const domain = { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: getAddress(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: getAddress(authorization.from), | ||
| to: getAddress(authorization.to), | ||
| value: BigInt(authorization.value), | ||
| validAfter: BigInt(authorization.validAfter), | ||
| validBefore: BigInt(authorization.validBefore), | ||
| nonce: authorization.nonce | ||
| }; | ||
| return await signer.signTypedData({ | ||
| domain, | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| message | ||
| }); | ||
| } | ||
| // src/exact/client/permit2.ts | ||
| import { encodeFunctionData, getAddress as getAddress2 } from "viem"; | ||
| var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); | ||
| async function createPermit2Payload(signer, x402Version, paymentRequirements) { | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const nonce = createPermit2Nonce(); | ||
| const validAfter = (now - 600).toString(); | ||
| const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString(); | ||
| const permit2Authorization = { | ||
| from: signer.address, | ||
| permitted: { | ||
| token: getAddress2(paymentRequirements.asset), | ||
| amount: paymentRequirements.amount | ||
| }, | ||
| spender: x402ExactPermit2ProxyAddress, | ||
| nonce, | ||
| deadline, | ||
| witness: { | ||
| to: getAddress2(paymentRequirements.payTo), | ||
| validAfter, | ||
| extra: "0x" | ||
| } | ||
| }; | ||
| const signature = await signPermit2Authorization( | ||
| signer, | ||
| permit2Authorization, | ||
| paymentRequirements | ||
| ); | ||
| const payload = { | ||
| signature, | ||
| permit2Authorization | ||
| }; | ||
| return { | ||
| x402Version, | ||
| payload | ||
| }; | ||
| } | ||
| async function signPermit2Authorization(signer, permit2Authorization, requirements) { | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const domain = { | ||
| name: "Permit2", | ||
| chainId, | ||
| verifyingContract: PERMIT2_ADDRESS | ||
| }; | ||
| const message = { | ||
| permitted: { | ||
| token: getAddress2(permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Authorization.permitted.amount) | ||
| }, | ||
| spender: getAddress2(permit2Authorization.spender), | ||
| nonce: BigInt(permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Authorization.deadline), | ||
| witness: { | ||
| to: getAddress2(permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Authorization.witness.validAfter), | ||
| extra: permit2Authorization.witness.extra | ||
| } | ||
| }; | ||
| return await signer.signTypedData({ | ||
| domain, | ||
| types: permit2WitnessTypes, | ||
| primaryType: "PermitWitnessTransferFrom", | ||
| message | ||
| }); | ||
| } | ||
| var erc20ApproveAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "approve", | ||
| inputs: [ | ||
| { name: "spender", type: "address" }, | ||
| { name: "amount", type: "uint256" } | ||
| ], | ||
| outputs: [{ type: "bool" }], | ||
| stateMutability: "nonpayable" | ||
| } | ||
| ]; | ||
| var erc20AllowanceAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| function createPermit2ApprovalTx(tokenAddress) { | ||
| const data = encodeFunctionData({ | ||
| abi: erc20ApproveAbi, | ||
| functionName: "approve", | ||
| args: [PERMIT2_ADDRESS, MAX_UINT256] | ||
| }); | ||
| return { | ||
| to: getAddress2(tokenAddress), | ||
| data | ||
| }; | ||
| } | ||
| function getPermit2AllowanceReadParams(params) { | ||
| return { | ||
| address: getAddress2(params.tokenAddress), | ||
| abi: erc20AllowanceAbi, | ||
| functionName: "allowance", | ||
| args: [getAddress2(params.ownerAddress), PERMIT2_ADDRESS] | ||
| }; | ||
| } | ||
| // src/exact/client/eip2612.ts | ||
| import { getAddress as getAddress3 } from "viem"; | ||
| var MAX_UINT2562 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); | ||
| async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion, chainId, deadline) { | ||
| const owner = signer.address; | ||
| const spender = getAddress3(PERMIT2_ADDRESS); | ||
| const nonce = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: eip2612NoncesAbi, | ||
| functionName: "nonces", | ||
| args: [owner] | ||
| }); | ||
| const domain = { | ||
| name: tokenName, | ||
| version: tokenVersion, | ||
| chainId, | ||
| verifyingContract: tokenAddress | ||
| }; | ||
| const message = { | ||
| owner, | ||
| spender, | ||
| value: MAX_UINT2562, | ||
| nonce, | ||
| deadline: BigInt(deadline) | ||
| }; | ||
| const signature = await signer.signTypedData({ | ||
| domain, | ||
| types: eip2612PermitTypes, | ||
| primaryType: "Permit", | ||
| message | ||
| }); | ||
| return { | ||
| from: owner, | ||
| asset: tokenAddress, | ||
| spender, | ||
| amount: MAX_UINT2562.toString(), | ||
| nonce: nonce.toString(), | ||
| deadline, | ||
| signature, | ||
| version: "1" | ||
| }; | ||
| } | ||
| // src/exact/client/scheme.ts | ||
| var erc20AllowanceAbi2 = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| var ExactEvmScheme = class { | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations. | ||
| * Must support `readContract` for EIP-2612 gas sponsoring. | ||
| * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
| constructor(signer) { | ||
| this.signer = signer; | ||
| this.scheme = "exact"; | ||
| } | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod. | ||
| * | ||
| * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the | ||
| * signer supports `readContract`, automatically signs an EIP-2612 permit | ||
| * when Permit2 allowance is insufficient. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @param context - Optional context with server-declared extensions | ||
| * @returns Promise resolving to a payment payload result (with optional extensions) | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements, context) { | ||
| const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009"; | ||
| if (assetTransferMethod === "permit2") { | ||
| const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| const eip2612Extensions = await this.trySignEip2612Permit( | ||
| paymentRequirements, | ||
| result, | ||
| context | ||
| ); | ||
| if (eip2612Extensions) { | ||
| return { | ||
| ...result, | ||
| extensions: eip2612Extensions | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| return createEIP3009Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| /** | ||
| * Attempts to sign an EIP-2612 permit for gasless Permit2 approval. | ||
| * | ||
| * Returns extension data if: | ||
| * 1. Server advertises eip2612GasSponsoring | ||
| * 2. Signer has readContract capability | ||
| * 3. Current Permit2 allowance is insufficient | ||
| * | ||
| * Returns undefined if the extension should not be used. | ||
| * | ||
| * @param requirements - The payment requirements from the server | ||
| * @param result - The payment payload result from the scheme | ||
| * @param context - Optional context containing server extensions and metadata | ||
| * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable | ||
| */ | ||
| async trySignEip2612Permit(requirements, result, context) { | ||
| if (!context?.extensions?.[EIP2612_GAS_SPONSORING.key]) { | ||
| return void 0; | ||
| } | ||
| const tokenName = requirements.extra?.name; | ||
| const tokenVersion = requirements.extra?.version; | ||
| if (!tokenName || !tokenVersion) { | ||
| return void 0; | ||
| } | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const tokenAddress = getAddress4(requirements.asset); | ||
| try { | ||
| const allowance = await this.signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: erc20AllowanceAbi2, | ||
| functionName: "allowance", | ||
| args: [this.signer.address, PERMIT2_ADDRESS] | ||
| }); | ||
| if (allowance >= BigInt(requirements.amount)) { | ||
| return void 0; | ||
| } | ||
| } catch { | ||
| } | ||
| const permit2Auth = result.payload?.permit2Authorization; | ||
| const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString(); | ||
| const info = await signEip2612Permit( | ||
| this.signer, | ||
| tokenAddress, | ||
| tokenName, | ||
| tokenVersion, | ||
| chainId, | ||
| deadline | ||
| ); | ||
| return { | ||
| [EIP2612_GAS_SPONSORING.key]: { info } | ||
| }; | ||
| } | ||
| }; | ||
| // src/exact/client/register.ts | ||
| function registerExactEvmScheme(client, config) { | ||
| const evmScheme = new ExactEvmScheme(config.signer); | ||
| if (config.networks && config.networks.length > 0) { | ||
| config.networks.forEach((network) => { | ||
| client.register(network, evmScheme); | ||
| }); | ||
| } else { | ||
| client.register("eip155:*", evmScheme); | ||
| } | ||
| NETWORKS.forEach((network) => { | ||
| client.registerV1(network, new ExactEvmSchemeV1(config.signer)); | ||
| }); | ||
| if (config.policies) { | ||
| config.policies.forEach((policy) => { | ||
| client.registerPolicy(policy); | ||
| }); | ||
| } | ||
| return client; | ||
| } | ||
| export { | ||
| erc20AllowanceAbi, | ||
| createPermit2ApprovalTx, | ||
| getPermit2AllowanceReadParams, | ||
| ExactEvmScheme, | ||
| registerExactEvmScheme | ||
| }; | ||
| //# sourceMappingURL=chunk-CJHYX7BQ.mjs.map |
| {"version":3,"sources":["../../src/exact/client/scheme.ts","../../src/exact/client/eip3009.ts","../../src/exact/client/permit2.ts","../../src/exact/client/eip2612.ts","../../src/exact/client/register.ts"],"sourcesContent":["import {\n PaymentRequirements,\n SchemeNetworkClient,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@x402/core/types\";\nimport { EIP2612_GAS_SPONSORING } from \"@x402/extensions\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { AssetTransferMethod } from \"../../types\";\nimport { PERMIT2_ADDRESS } from \"../../constants\";\nimport { getAddress } from \"viem\";\nimport { createEIP3009Payload } from \"./eip3009\";\nimport { createPermit2Payload } from \"./permit2\";\nimport { signEip2612Permit } from \"./eip2612\";\n\n/** ERC20 allowance ABI for checking Permit2 approval */\nconst 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/**\n * EVM client implementation for the Exact payment scheme.\n * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows.\n *\n * Routes to the appropriate authorization method based on\n * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009\n * for backward compatibility with older facilitators.\n *\n * When the server advertises `eip2612GasSponsoring` and the asset transfer\n * method is `permit2`, the scheme automatically signs an EIP-2612 permit\n * if the user lacks Permit2 approval. This requires `readContract` on the signer.\n */\nexport class ExactEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClient instance.\n *\n * @param signer - The EVM signer for client operations.\n * Must support `readContract` for EIP-2612 gas sponsoring.\n * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`.\n */\n constructor(private readonly signer: ClientEvmSigner) {}\n\n /**\n * Creates a payment payload for the Exact scheme.\n * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.\n *\n * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the\n * signer supports `readContract`, automatically signs an EIP-2612 permit\n * when Permit2 allowance is insufficient.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @param context - Optional context with server-declared extensions\n * @returns Promise resolving to a payment payload result (with optional extensions)\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const assetTransferMethod =\n (paymentRequirements.extra?.assetTransferMethod as AssetTransferMethod) ?? \"eip3009\";\n\n if (assetTransferMethod === \"permit2\") {\n const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);\n\n // Check if EIP-2612 gas sponsoring is advertised and we can handle it\n const eip2612Extensions = await this.trySignEip2612Permit(\n paymentRequirements,\n result,\n context,\n );\n\n if (eip2612Extensions) {\n return {\n ...result,\n extensions: eip2612Extensions,\n };\n }\n\n return result;\n }\n\n return createEIP3009Payload(this.signer, x402Version, paymentRequirements);\n }\n\n /**\n * Attempts to sign an EIP-2612 permit for gasless Permit2 approval.\n *\n * Returns extension data if:\n * 1. Server advertises eip2612GasSponsoring\n * 2. Signer has readContract capability\n * 3. Current Permit2 allowance is insufficient\n *\n * Returns undefined if the extension should not be used.\n *\n * @param requirements - The payment requirements from the server\n * @param result - The payment payload result from the scheme\n * @param context - Optional context containing server extensions and metadata\n * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable\n */\n private async trySignEip2612Permit(\n requirements: PaymentRequirements,\n result: PaymentPayloadResult,\n context?: PaymentPayloadContext,\n ): Promise<Record<string, unknown> | undefined> {\n // Check if server advertises eip2612GasSponsoring\n if (!context?.extensions?.[EIP2612_GAS_SPONSORING.key]) {\n return undefined;\n }\n\n // Check that required token metadata is available\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 = parseInt(requirements.network.split(\":\")[1]);\n const tokenAddress = getAddress(requirements.asset) as `0x${string}`;\n\n // Check if user already has sufficient Permit2 allowance\n try {\n const allowance = (await this.signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [this.signer.address, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return undefined; // Already approved, no need for EIP-2612\n }\n } catch {\n // If we can't check allowance, proceed with EIP-2612 signing\n }\n\n // Use the same deadline as the Permit2 authorization\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 // Sign the EIP-2612 permit\n const info = await signEip2612Permit(\n this.signer,\n tokenAddress,\n tokenName,\n tokenVersion,\n chainId,\n deadline,\n );\n\n return {\n [EIP2612_GAS_SPONSORING.key]: { info },\n };\n }\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport { createNonce } from \"../../utils\";\n\n/**\n * Creates an EIP-3009 (transferWithAuthorization) payload.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createEIP3009Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEIP3009Payload[\"authorization\"] = {\n from: signer.address,\n to: getAddress(paymentRequirements.payTo),\n value: paymentRequirements.amount,\n validAfter: (now - 600).toString(),\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements);\n\n const payload: ExactEIP3009Payload = {\n authorization,\n signature,\n };\n\n return {\n x402Version,\n payload,\n };\n}\n\n/**\n * Sign the EIP-3009 authorization using EIP-712.\n *\n * @param signer - The EVM signer\n * @param authorization - The authorization to sign\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\nasync function signEIP3009Authorization(\n signer: ClientEvmSigner,\n authorization: ExactEIP3009Payload[\"authorization\"],\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = parseInt(requirements.network.split(\":\")[1]);\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 signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport {\n permit2WitnessTypes,\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\nimport { createPermit2Nonce } from \"../../utils\";\n\n/** Maximum uint256 value for unlimited approval. */\nconst MAX_UINT256 = BigInt(\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\");\n\n/**\n * Creates a Permit2 payload using the x402Permit2Proxy witness pattern.\n * The spender is set to x402Permit2Proxy, which enforces that funds\n * can only be sent to the witness.to address.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n\n // Lower time bound - allow some clock skew\n const validAfter = (now - 600).toString();\n // Upper time bound is enforced by Permit2's deadline field\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n const permit2Authorization: ExactPermit2Payload[\"permit2Authorization\"] = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: x402ExactPermit2ProxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n validAfter,\n extra: \"0x\",\n },\n };\n\n const signature = await signPermit2Authorization(\n signer,\n permit2Authorization,\n paymentRequirements,\n );\n\n const payload: ExactPermit2Payload = {\n signature,\n permit2Authorization,\n };\n\n return {\n x402Version,\n payload,\n };\n}\n\n/**\n * Sign the Permit2 authorization using EIP-712 with witness data.\n * The signature authorizes the x402Permit2Proxy to transfer tokens on behalf of the signer.\n *\n * @param signer - The EVM signer\n * @param permit2Authorization - The Permit2 authorization parameters\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\nasync function signPermit2Authorization(\n signer: ClientEvmSigner,\n permit2Authorization: ExactPermit2Payload[\"permit2Authorization\"],\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = parseInt(requirements.network.split(\":\")[1]);\n\n const domain = {\n name: \"Permit2\",\n chainId,\n verifyingContract: PERMIT2_ADDRESS,\n };\n\n const message = {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n extra: permit2Authorization.witness.extra,\n },\n };\n\n return await signer.signTypedData({\n domain,\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message,\n });\n}\n\n/**\n * ERC20 approve ABI for encoding approval transactions.\n */\nconst 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/**\n * ERC20 allowance ABI for checking approval status.\n */\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/**\n * Creates transaction data to approve Permit2 to spend tokens.\n * The user sends this transaction (paying gas) before using Permit2 flow.\n *\n * @param tokenAddress - The ERC20 token contract address\n * @returns Transaction data to send for approval\n *\n * @example\n * ```typescript\n * const tx = createPermit2ApprovalTx(\"0x...\");\n * await walletClient.sendTransaction({\n * to: tx.to,\n * data: tx.data,\n * });\n * ```\n */\nexport function createPermit2ApprovalTx(tokenAddress: `0x${string}`): {\n to: `0x${string}`;\n data: `0x${string}`;\n} {\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [PERMIT2_ADDRESS, MAX_UINT256],\n });\n\n return {\n to: getAddress(tokenAddress),\n data,\n };\n}\n\n/**\n * Parameters for checking Permit2 allowance.\n * Application provides these to check if approval is needed.\n */\nexport interface Permit2AllowanceParams {\n tokenAddress: `0x${string}`;\n ownerAddress: `0x${string}`;\n}\n\n/**\n * Returns contract read parameters for checking Permit2 allowance.\n * Use with a public client to check if the user has approved Permit2.\n *\n * @param params - The allowance check parameters\n * @returns Contract read parameters for checking allowance\n *\n * @example\n * ```typescript\n * const readParams = getPermit2AllowanceReadParams({\n * tokenAddress: \"0x...\",\n * ownerAddress: \"0x...\",\n * });\n *\n * const allowance = await publicClient.readContract(readParams);\n * const needsApproval = allowance < requiredAmount;\n * ```\n */\nexport function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): {\n address: `0x${string}`;\n abi: typeof erc20AllowanceAbi;\n functionName: \"allowance\";\n args: [`0x${string}`, `0x${string}`];\n} {\n return {\n address: getAddress(params.tokenAddress),\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [getAddress(params.ownerAddress), PERMIT2_ADDRESS],\n };\n}\n","import { getAddress } from \"viem\";\nimport type { Eip2612GasSponsoringInfo } from \"@x402/extensions\";\nimport { eip2612PermitTypes, eip2612NoncesAbi, PERMIT2_ADDRESS } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\n\n/** Maximum uint256 value for unlimited approval. */\nconst MAX_UINT256 = BigInt(\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\");\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 * @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 * @returns The EIP-2612 gas sponsoring info object\n */\nexport async function signEip2612Permit(\n signer: ClientEvmSigner,\n tokenAddress: `0x${string}`,\n tokenName: string,\n tokenVersion: string,\n chainId: number,\n deadline: 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 message = {\n owner,\n spender,\n value: MAX_UINT256,\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: MAX_UINT256.toString(),\n nonce: nonce.toString(),\n deadline,\n signature,\n version: \"1\",\n };\n}\n","import { x402Client, SelectPaymentRequirements, PaymentPolicy } from \"@x402/core/client\";\nimport { Network } from \"@x402/core/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmScheme } from \"./scheme\";\nimport { ExactEvmSchemeV1 } from \"../v1/client/scheme\";\nimport { NETWORKS } from \"../../v1\";\n\n/**\n * Configuration options for registering EVM schemes to an x402Client\n */\nexport interface EvmClientConfig {\n /**\n * The EVM signer to use for creating payment payloads\n */\n signer: ClientEvmSigner;\n\n /**\n * Optional payment requirements selector function\n * If not provided, uses the default selector (first available option)\n */\n paymentRequirementsSelector?: SelectPaymentRequirements;\n\n /**\n * Optional policies to apply to the client\n */\n policies?: PaymentPolicy[];\n\n /**\n * Optional specific networks to register\n * If not provided, registers wildcard support (eip155:*)\n */\n networks?: Network[];\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Client instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param client - The x402Client instance to register schemes to\n * @param config - Configuration for EVM client registration\n * @returns The client instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/client/register\";\n * import { x402Client } from \"@x402/core/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const client = new x402Client();\n * registerExactEvmScheme(client, { signer: account });\n * ```\n */\nexport function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client {\n const evmScheme = new ExactEvmScheme(config.signer);\n\n // Register V2 scheme\n // EIP-2612 gas sponsoring is handled internally by the scheme when the\n // server advertises support - no separate extension registration needed.\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n client.register(network, evmScheme);\n });\n } else {\n // Register wildcard for all EVM chains\n client.register(\"eip155:*\", evmScheme);\n }\n\n // Register all V1 networks\n NETWORKS.forEach(network => {\n client.registerV1(network as Network, new ExactEvmSchemeV1(config.signer));\n });\n\n // Apply policies if provided\n if (config.policies) {\n config.policies.forEach(policy => {\n client.registerPolicy(policy);\n });\n }\n\n return client;\n}\n"],"mappings":"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","names":["getAddress","getAddress","getAddress","getAddress","MAX_UINT256","getAddress","erc20AllowanceAbi","getAddress"]} |
| // src/exact/v1/client/scheme.ts | ||
| import { getAddress } from "viem"; | ||
| // src/constants.ts | ||
| var authorizationTypes = { | ||
| TransferWithAuthorization: [ | ||
| { name: "from", type: "address" }, | ||
| { name: "to", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "validBefore", type: "uint256" }, | ||
| { name: "nonce", type: "bytes32" } | ||
| ] | ||
| }; | ||
| var permit2WitnessTypes = { | ||
| PermitWitnessTransferFrom: [ | ||
| { name: "permitted", type: "TokenPermissions" }, | ||
| { name: "spender", type: "address" }, | ||
| { name: "nonce", type: "uint256" }, | ||
| { name: "deadline", type: "uint256" }, | ||
| { name: "witness", type: "Witness" } | ||
| ], | ||
| TokenPermissions: [ | ||
| { name: "token", type: "address" }, | ||
| { name: "amount", type: "uint256" } | ||
| ], | ||
| Witness: [ | ||
| { name: "to", type: "address" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "extra", type: "bytes" } | ||
| ] | ||
| }; | ||
| var eip3009ABI = [ | ||
| { | ||
| inputs: [ | ||
| { name: "from", type: "address" }, | ||
| { name: "to", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "validBefore", type: "uint256" }, | ||
| { name: "nonce", type: "bytes32" }, | ||
| { name: "v", type: "uint8" }, | ||
| { name: "r", type: "bytes32" }, | ||
| { name: "s", type: "bytes32" } | ||
| ], | ||
| name: "transferWithAuthorization", | ||
| outputs: [], | ||
| stateMutability: "nonpayable", | ||
| type: "function" | ||
| }, | ||
| { | ||
| inputs: [ | ||
| { name: "from", type: "address" }, | ||
| { name: "to", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "validBefore", type: "uint256" }, | ||
| { name: "nonce", type: "bytes32" }, | ||
| { name: "signature", type: "bytes" } | ||
| ], | ||
| name: "transferWithAuthorization", | ||
| outputs: [], | ||
| stateMutability: "nonpayable", | ||
| type: "function" | ||
| }, | ||
| { | ||
| inputs: [{ name: "account", type: "address" }], | ||
| name: "balanceOf", | ||
| outputs: [{ name: "", type: "uint256" }], | ||
| stateMutability: "view", | ||
| type: "function" | ||
| }, | ||
| { | ||
| inputs: [], | ||
| name: "version", | ||
| outputs: [{ name: "", type: "string" }], | ||
| stateMutability: "view", | ||
| type: "function" | ||
| } | ||
| ]; | ||
| var eip2612PermitTypes = { | ||
| Permit: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "nonce", type: "uint256" }, | ||
| { name: "deadline", type: "uint256" } | ||
| ] | ||
| }; | ||
| var eip2612NoncesAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "nonces", | ||
| inputs: [{ name: "owner", type: "address" }], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| var x402UptoPermit2ProxyAddress = "0x4020633461b2895a48930Ff97eE8fCdE8E520002"; | ||
| var x402ExactPermit2ProxyABI = [ | ||
| { | ||
| type: "function", | ||
| name: "PERMIT2", | ||
| inputs: [], | ||
| outputs: [{ name: "", type: "address", internalType: "contract ISignatureTransfer" }], | ||
| stateMutability: "view" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "WITNESS_TYPEHASH", | ||
| inputs: [], | ||
| outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], | ||
| stateMutability: "view" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "WITNESS_TYPE_STRING", | ||
| inputs: [], | ||
| outputs: [{ name: "", type: "string", internalType: "string" }], | ||
| stateMutability: "view" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "initialize", | ||
| inputs: [{ name: "_permit2", type: "address", internalType: "address" }], | ||
| outputs: [], | ||
| stateMutability: "nonpayable" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "settle", | ||
| inputs: [ | ||
| { | ||
| name: "permit", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.PermitTransferFrom", | ||
| components: [ | ||
| { | ||
| name: "permitted", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.TokenPermissions", | ||
| components: [ | ||
| { name: "token", type: "address", internalType: "address" }, | ||
| { name: "amount", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "nonce", type: "uint256", internalType: "uint256" }, | ||
| { name: "deadline", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "owner", type: "address", internalType: "address" }, | ||
| { | ||
| name: "witness", | ||
| type: "tuple", | ||
| internalType: "struct x402BasePermit2Proxy.Witness", | ||
| components: [ | ||
| { name: "to", type: "address", internalType: "address" }, | ||
| { name: "validAfter", type: "uint256", internalType: "uint256" }, | ||
| { name: "extra", type: "bytes", internalType: "bytes" } | ||
| ] | ||
| }, | ||
| { name: "signature", type: "bytes", internalType: "bytes" } | ||
| ], | ||
| outputs: [], | ||
| stateMutability: "nonpayable" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "settleWithPermit", | ||
| inputs: [ | ||
| { | ||
| name: "permit2612", | ||
| type: "tuple", | ||
| internalType: "struct x402BasePermit2Proxy.EIP2612Permit", | ||
| components: [ | ||
| { name: "value", type: "uint256", internalType: "uint256" }, | ||
| { name: "deadline", type: "uint256", internalType: "uint256" }, | ||
| { name: "r", type: "bytes32", internalType: "bytes32" }, | ||
| { name: "s", type: "bytes32", internalType: "bytes32" }, | ||
| { name: "v", type: "uint8", internalType: "uint8" } | ||
| ] | ||
| }, | ||
| { | ||
| name: "permit", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.PermitTransferFrom", | ||
| components: [ | ||
| { | ||
| name: "permitted", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.TokenPermissions", | ||
| components: [ | ||
| { name: "token", type: "address", internalType: "address" }, | ||
| { name: "amount", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "nonce", type: "uint256", internalType: "uint256" }, | ||
| { name: "deadline", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "owner", type: "address", internalType: "address" }, | ||
| { | ||
| name: "witness", | ||
| type: "tuple", | ||
| internalType: "struct x402BasePermit2Proxy.Witness", | ||
| components: [ | ||
| { name: "to", type: "address", internalType: "address" }, | ||
| { name: "validAfter", type: "uint256", internalType: "uint256" }, | ||
| { name: "extra", type: "bytes", internalType: "bytes" } | ||
| ] | ||
| }, | ||
| { name: "signature", type: "bytes", internalType: "bytes" } | ||
| ], | ||
| outputs: [], | ||
| stateMutability: "nonpayable" | ||
| }, | ||
| { type: "event", name: "Settled", inputs: [], anonymous: false }, | ||
| { type: "event", name: "SettledWithPermit", inputs: [], anonymous: false }, | ||
| { type: "error", name: "AlreadyInitialized", inputs: [] }, | ||
| { type: "error", name: "InvalidDestination", inputs: [] }, | ||
| { type: "error", name: "InvalidOwner", inputs: [] }, | ||
| { type: "error", name: "InvalidPermit2Address", inputs: [] }, | ||
| { type: "error", name: "PaymentTooEarly", inputs: [] }, | ||
| { type: "error", name: "ReentrancyGuardReentrantCall", inputs: [] } | ||
| ]; | ||
| // src/utils.ts | ||
| import { toHex } from "viem"; | ||
| function getEvmChainId(network) { | ||
| const chainId = EVM_NETWORK_CHAIN_ID_MAP[network]; | ||
| if (!chainId) { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
| return chainId; | ||
| } | ||
| function getCrypto() { | ||
| const cryptoObj = globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return cryptoObj; | ||
| } | ||
| function createNonce() { | ||
| return toHex(getCrypto().getRandomValues(new Uint8Array(32))); | ||
| } | ||
| function createPermit2Nonce() { | ||
| const randomBytes = getCrypto().getRandomValues(new Uint8Array(32)); | ||
| return BigInt(toHex(randomBytes)).toString(); | ||
| } | ||
| // src/exact/v1/client/scheme.ts | ||
| var ExactEvmSchemeV1 = class { | ||
| /** | ||
| * Creates a new ExactEvmClientV1 instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| */ | ||
| constructor(signer) { | ||
| this.signer = signer; | ||
| this.scheme = "exact"; | ||
| } | ||
| /** | ||
| * Creates a payment payload for the Exact scheme (V1). | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const selectedV1 = paymentRequirements; | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: this.signer.address, | ||
| to: getAddress(selectedV1.payTo), | ||
| value: selectedV1.maxAmountRequired, | ||
| validAfter: (now - 600).toString(), | ||
| // 10 minutes before | ||
| validBefore: (now + selectedV1.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await this.signAuthorization(authorization, selectedV1); | ||
| const payload = { | ||
| authorization, | ||
| signature | ||
| }; | ||
| return { | ||
| x402Version, | ||
| scheme: selectedV1.scheme, | ||
| network: selectedV1.network, | ||
| payload | ||
| }; | ||
| } | ||
| /** | ||
| * Sign the EIP-3009 authorization using EIP-712 | ||
| * | ||
| * @param authorization - The authorization to sign | ||
| * @param requirements - The payment requirements | ||
| * @returns Promise resolving to the signature | ||
| */ | ||
| async signAuthorization(authorization, requirements) { | ||
| const chainId = getEvmChainId(requirements.network); | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| throw new Error( | ||
| `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}` | ||
| ); | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const domain = { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: getAddress(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: getAddress(authorization.from), | ||
| to: getAddress(authorization.to), | ||
| value: BigInt(authorization.value), | ||
| validAfter: BigInt(authorization.validAfter), | ||
| validBefore: BigInt(authorization.validBefore), | ||
| nonce: authorization.nonce | ||
| }; | ||
| return await this.signer.signTypedData({ | ||
| domain, | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| message | ||
| }); | ||
| } | ||
| }; | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| import { getAddress as getAddress2, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; | ||
| var ExactEvmSchemeV12 = class { | ||
| /** | ||
| * Creates a new ExactEvmFacilitatorV1 instance. | ||
| * | ||
| * @param signer - The EVM signer for facilitator operations | ||
| * @param config - Optional configuration for the facilitator | ||
| */ | ||
| constructor(signer, config) { | ||
| this.signer = signer; | ||
| this.scheme = "exact"; | ||
| this.caipFamily = "eip155:*"; | ||
| this.config = { | ||
| deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false | ||
| }; | ||
| } | ||
| /** | ||
| * Get mechanism-specific extra data for the supported kinds endpoint. | ||
| * For EVM, no extra data is needed. | ||
| * | ||
| * @param _ - The network identifier (unused for EVM) | ||
| * @returns undefined (EVM has no extra data) | ||
| */ | ||
| getExtra(_) { | ||
| return void 0; | ||
| } | ||
| /** | ||
| * Get signer addresses used by this facilitator. | ||
| * Returns all addresses this facilitator can use for signing/settling transactions. | ||
| * | ||
| * @param _ - The network identifier (unused for EVM, addresses are network-agnostic) | ||
| * @returns Array of facilitator wallet addresses | ||
| */ | ||
| getSigners(_) { | ||
| return [...this.signer.getAddresses()]; | ||
| } | ||
| /** | ||
| * Verifies a payment payload (V1). | ||
| * | ||
| * @param payload - The payment payload to verify | ||
| * @param requirements - The payment requirements | ||
| * @returns Promise resolving to verification response | ||
| */ | ||
| async verify(payload, requirements) { | ||
| const requirementsV1 = requirements; | ||
| const payloadV1 = payload; | ||
| const exactEvmPayload = payload.payload; | ||
| if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| let chainId; | ||
| try { | ||
| chainId = getEvmChainId(payloadV1.network); | ||
| } catch { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: `invalid_network`, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "missing_eip712_domain", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const erc20Address = getAddress2(requirements.asset); | ||
| if (payloadV1.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const permitTypedData = { | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| domain: { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: erc20Address | ||
| }, | ||
| message: { | ||
| from: exactEvmPayload.authorization.from, | ||
| to: exactEvmPayload.authorization.to, | ||
| value: BigInt(exactEvmPayload.authorization.value), | ||
| validAfter: BigInt(exactEvmPayload.authorization.validAfter), | ||
| validBefore: BigInt(exactEvmPayload.authorization.validBefore), | ||
| nonce: exactEvmPayload.authorization.nonce | ||
| } | ||
| }; | ||
| try { | ||
| const recoveredAddress = await this.signer.verifyTypedData({ | ||
| address: exactEvmPayload.authorization.from, | ||
| ...permitTypedData, | ||
| signature: exactEvmPayload.signature | ||
| }); | ||
| if (!recoveredAddress) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } catch { | ||
| const signature = exactEvmPayload.signature; | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isSmartWallet = signatureLength > 130; | ||
| if (isSmartWallet) { | ||
| const payerAddress = exactEvmPayload.authorization.from; | ||
| const bytecode = await this.signer.getCode({ address: payerAddress }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| const erc6492Data = parseErc6492Signature(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000"); | ||
| if (!hasDeploymentInfo) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet", | ||
| payer: payerAddress | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } | ||
| if (getAddress2(exactEvmPayload.authorization.to) !== getAddress2(requirements.payTo)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_recipient_mismatch", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_before", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_after", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| try { | ||
| const balance = await this.signer.readContract({ | ||
| address: erc20Address, | ||
| abi: eip3009ABI, | ||
| functionName: "balanceOf", | ||
| args: [exactEvmPayload.authorization.from] | ||
| }); | ||
| if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_value", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| /** | ||
| * Settles a payment by executing the transfer (V1). | ||
| * | ||
| * @param payload - The payment payload to settle | ||
| * @param requirements - The payment requirements | ||
| * @returns Promise resolving to settlement response | ||
| */ | ||
| async settle(payload, requirements) { | ||
| const payloadV1 = payload; | ||
| const exactEvmPayload = payload.payload; | ||
| const valid = await this.verify(payload, requirements); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payloadV1.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| try { | ||
| const parseResult = parseErc6492Signature(exactEvmPayload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| const payerAddress = exactEvmPayload.authorization.from; | ||
| const bytecode = await this.signer.getCode({ address: payerAddress }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| try { | ||
| console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`); | ||
| const deployTx = await this.signer.sendTransaction({ | ||
| to: factoryAddress, | ||
| data: factoryCalldata | ||
| }); | ||
| await this.signer.waitForTransactionReceipt({ hash: deployTx }); | ||
| console.log(`Successfully deployed smart wallet for ${payerAddress}`); | ||
| } catch (deployError) { | ||
| console.error("Smart wallet deployment failed:", deployError); | ||
| throw deployError; | ||
| } | ||
| } else { | ||
| console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`); | ||
| } | ||
| } | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isECDSA = signatureLength === 130; | ||
| let tx; | ||
| if (isECDSA) { | ||
| const parsedSig = parseSignature(signature); | ||
| tx = await this.signer.writeContract({ | ||
| address: getAddress2(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress2(exactEvmPayload.authorization.from), | ||
| getAddress2(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
| BigInt(exactEvmPayload.authorization.validAfter), | ||
| BigInt(exactEvmPayload.authorization.validBefore), | ||
| exactEvmPayload.authorization.nonce, | ||
| parsedSig.v || parsedSig.yParity, | ||
| parsedSig.r, | ||
| parsedSig.s | ||
| ] | ||
| }); | ||
| } else { | ||
| tx = await this.signer.writeContract({ | ||
| address: getAddress2(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress2(exactEvmPayload.authorization.from), | ||
| getAddress2(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
| BigInt(exactEvmPayload.authorization.validAfter), | ||
| BigInt(exactEvmPayload.authorization.validBefore), | ||
| exactEvmPayload.authorization.nonce, | ||
| signature | ||
| ] | ||
| }); | ||
| } | ||
| const receipt = await this.signer.waitForTransactionReceipt({ hash: tx }); | ||
| if (receipt.status !== "success") { | ||
| return { | ||
| success: false, | ||
| errorReason: "invalid_transaction_state", | ||
| transaction: tx, | ||
| network: payloadV1.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payloadV1.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } catch (error) { | ||
| console.error("Failed to settle transaction:", error); | ||
| return { | ||
| success: false, | ||
| errorReason: "transaction_failed", | ||
| transaction: "", | ||
| network: payloadV1.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } | ||
| }; | ||
| // src/v1/index.ts | ||
| var EVM_NETWORK_CHAIN_ID_MAP = { | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| abstract: 2741, | ||
| "abstract-testnet": 11124, | ||
| "base-sepolia": 84532, | ||
| base: 8453, | ||
| "avalanche-fuji": 43113, | ||
| avalanche: 43114, | ||
| iotex: 4689, | ||
| sei: 1329, | ||
| "sei-testnet": 1328, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002, | ||
| peaq: 3338, | ||
| story: 1514, | ||
| educhain: 41923, | ||
| "skale-base-sepolia": 324705682, | ||
| megaeth: 4326 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| export { | ||
| authorizationTypes, | ||
| permit2WitnessTypes, | ||
| eip3009ABI, | ||
| eip2612PermitTypes, | ||
| eip2612NoncesAbi, | ||
| PERMIT2_ADDRESS, | ||
| x402ExactPermit2ProxyAddress, | ||
| x402UptoPermit2ProxyAddress, | ||
| x402ExactPermit2ProxyABI, | ||
| ExactEvmSchemeV1, | ||
| ExactEvmSchemeV12, | ||
| EVM_NETWORK_CHAIN_ID_MAP, | ||
| NETWORKS, | ||
| createNonce, | ||
| createPermit2Nonce | ||
| }; | ||
| //# sourceMappingURL=chunk-GSU4DHTC.mjs.map |
| {"version":3,"sources":["../../src/exact/v1/client/scheme.ts","../../src/constants.ts","../../src/utils.ts","../../src/exact/v1/facilitator/scheme.ts","../../src/v1/index.ts"],"sourcesContent":["import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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","// 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.\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 { name: \"extra\", type: \"bytes\" },\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] 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/**\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\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} 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"],"mappings":"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","names":["getAddress","ExactEvmSchemeV1","getAddress"]} |
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayloadContext, PaymentPayloadResult } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from './signer-3KGwtdNT.mjs'; | ||
| /** | ||
| * EVM client implementation for the Exact payment scheme. | ||
| * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows. | ||
| * | ||
| * Routes to the appropriate authorization method based on | ||
| * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009 | ||
| * for backward compatibility with older facilitators. | ||
| * | ||
| * When the server advertises `eip2612GasSponsoring` and the asset transfer | ||
| * method is `permit2`, the scheme automatically signs an EIP-2612 permit | ||
| * if the user lacks Permit2 approval. This requires `readContract` on the signer. | ||
| */ | ||
| declare class ExactEvmScheme implements SchemeNetworkClient { | ||
| private readonly signer; | ||
| readonly scheme = "exact"; | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations. | ||
| * Must support `readContract` for EIP-2612 gas sponsoring. | ||
| * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
| constructor(signer: ClientEvmSigner); | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod. | ||
| * | ||
| * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the | ||
| * signer supports `readContract`, automatically signs an EIP-2612 permit | ||
| * when Permit2 allowance is insufficient. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @param context - Optional context with server-declared extensions | ||
| * @returns Promise resolving to a payment payload result (with optional extensions) | ||
| */ | ||
| createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>; | ||
| /** | ||
| * Attempts to sign an EIP-2612 permit for gasless Permit2 approval. | ||
| * | ||
| * Returns extension data if: | ||
| * 1. Server advertises eip2612GasSponsoring | ||
| * 2. Signer has readContract capability | ||
| * 3. Current Permit2 allowance is insufficient | ||
| * | ||
| * Returns undefined if the extension should not be used. | ||
| * | ||
| * @param requirements - The payment requirements from the server | ||
| * @param result - The payment payload result from the scheme | ||
| * @param context - Optional context containing server extensions and metadata | ||
| * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable | ||
| */ | ||
| private trySignEip2612Permit; | ||
| } | ||
| /** | ||
| * ERC20 allowance ABI for checking approval status. | ||
| */ | ||
| declare const erc20AllowanceAbi: readonly [{ | ||
| readonly type: "function"; | ||
| readonly name: "allowance"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "spender"; | ||
| readonly type: "address"; | ||
| }]; | ||
| readonly outputs: readonly [{ | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }]; | ||
| /** | ||
| * Creates transaction data to approve Permit2 to spend tokens. | ||
| * The user sends this transaction (paying gas) before using Permit2 flow. | ||
| * | ||
| * @param tokenAddress - The ERC20 token contract address | ||
| * @returns Transaction data to send for approval | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const tx = createPermit2ApprovalTx("0x..."); | ||
| * await walletClient.sendTransaction({ | ||
| * to: tx.to, | ||
| * data: tx.data, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createPermit2ApprovalTx(tokenAddress: `0x${string}`): { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }; | ||
| /** | ||
| * Parameters for checking Permit2 allowance. | ||
| * Application provides these to check if approval is needed. | ||
| */ | ||
| interface Permit2AllowanceParams { | ||
| tokenAddress: `0x${string}`; | ||
| ownerAddress: `0x${string}`; | ||
| } | ||
| /** | ||
| * Returns contract read parameters for checking Permit2 allowance. | ||
| * Use with a public client to check if the user has approved Permit2. | ||
| * | ||
| * @param params - The allowance check parameters | ||
| * @returns Contract read parameters for checking allowance | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const readParams = getPermit2AllowanceReadParams({ | ||
| * tokenAddress: "0x...", | ||
| * ownerAddress: "0x...", | ||
| * }); | ||
| * | ||
| * const allowance = await publicClient.readContract(readParams); | ||
| * const needsApproval = allowance < requiredAmount; | ||
| * ``` | ||
| */ | ||
| declare function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): { | ||
| address: `0x${string}`; | ||
| abi: typeof erc20AllowanceAbi; | ||
| functionName: "allowance"; | ||
| args: [`0x${string}`, `0x${string}`]; | ||
| }; | ||
| export { ExactEvmScheme as E, type Permit2AllowanceParams as P, createPermit2ApprovalTx as c, erc20AllowanceAbi as e, getPermit2AllowanceReadParams as g }; |
| /** | ||
| * ClientEvmSigner - Used by x402 clients to sign payment authorizations. | ||
| * | ||
| * Typically a viem WalletClient extended with publicActions: | ||
| * ```typescript | ||
| * const client = createWalletClient({ | ||
| * account: privateKeyToAccount('0x...'), | ||
| * chain: baseSepolia, | ||
| * transport: http(), | ||
| * }).extend(publicActions); | ||
| * ``` | ||
| * | ||
| * Or composed via `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
| type ClientEvmSigner = { | ||
| readonly address: `0x${string}`; | ||
| signTypedData(message: { | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| }): Promise<`0x${string}`>; | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| }; | ||
| /** | ||
| * FacilitatorEvmSigner - Used by x402 facilitators to verify and settle payments | ||
| * This is typically a viem PublicClient + WalletClient combination that can | ||
| * read contract state, verify signatures, write transactions, and wait for receipts | ||
| * | ||
| * Supports multiple addresses for load balancing, key rotation, and high availability | ||
| */ | ||
| type FacilitatorEvmSigner = { | ||
| /** | ||
| * Get all addresses this facilitator can use for signing | ||
| * Enables dynamic address selection for load balancing and key rotation | ||
| */ | ||
| getAddresses(): readonly `0x${string}`[]; | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| verifyTypedData(args: { | ||
| address: `0x${string}`; | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| signature: `0x${string}`; | ||
| }): Promise<boolean>; | ||
| writeContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args: readonly unknown[]; | ||
| }): Promise<`0x${string}`>; | ||
| sendTransaction(args: { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }): Promise<`0x${string}`>; | ||
| waitForTransactionReceipt(args: { | ||
| hash: `0x${string}`; | ||
| }): Promise<{ | ||
| status: string; | ||
| }>; | ||
| getCode(args: { | ||
| address: `0x${string}`; | ||
| }): Promise<`0x${string}` | undefined>; | ||
| }; | ||
| /** | ||
| * Composes a ClientEvmSigner from a local account and a public client. | ||
| * | ||
| * Use this when your signer (e.g., `privateKeyToAccount`) doesn't have | ||
| * `readContract`. The `publicClient` provides the on-chain read capability. | ||
| * | ||
| * Alternatively, use a WalletClient extended with publicActions directly: | ||
| * ```typescript | ||
| * const signer = createWalletClient({ | ||
| * account: privateKeyToAccount('0x...'), | ||
| * chain: baseSepolia, | ||
| * transport: http(), | ||
| * }).extend(publicActions); | ||
| * ``` | ||
| * | ||
| * @param signer - A signer with `address` and `signTypedData` (and optionally `readContract`) | ||
| * @param publicClient - A client with `readContract` (required if signer lacks it) | ||
| * @param publicClient.readContract - The readContract method from the public client | ||
| * @returns A complete ClientEvmSigner | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const account = privateKeyToAccount("0x..."); | ||
| * const publicClient = createPublicClient({ chain: baseSepolia, transport: http() }); | ||
| * const signer = toClientEvmSigner(account, publicClient); | ||
| * ``` | ||
| */ | ||
| declare function toClientEvmSigner(signer: Omit<ClientEvmSigner, "readContract"> & { | ||
| readContract?: ClientEvmSigner["readContract"]; | ||
| }, publicClient?: { | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| }): ClientEvmSigner; | ||
| /** | ||
| * Converts a viem client with single address to a FacilitatorEvmSigner | ||
| * Wraps the single address in a getAddresses() function for compatibility | ||
| * | ||
| * @param client - The client to convert (must have 'address' property) | ||
| * @returns FacilitatorEvmSigner with getAddresses() support | ||
| */ | ||
| declare function toFacilitatorEvmSigner(client: Omit<FacilitatorEvmSigner, "getAddresses"> & { | ||
| address: `0x${string}`; | ||
| }): FacilitatorEvmSigner; | ||
| export { type ClientEvmSigner as C, type FacilitatorEvmSigner as F, toFacilitatorEvmSigner as a, toClientEvmSigner as t }; |
@@ -1,5 +0,5 @@ | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-BYv82va2.js'; | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-CzKPU5By.js'; | ||
| import { SelectPaymentRequirements, PaymentPolicy, x402Client } from '@x402/core/client'; | ||
| import { Network } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from '../../signer-5OVDxViv.js'; | ||
| import { C as ClientEvmSigner } from '../../signer-3KGwtdNT.js'; | ||
@@ -6,0 +6,0 @@ /** |
@@ -31,4 +31,4 @@ "use strict"; | ||
| // src/exact/client/eip3009.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/exact/client/scheme.ts | ||
| var import_extensions = require("@x402/extensions"); | ||
@@ -64,5 +64,29 @@ // src/constants.ts | ||
| }; | ||
| var eip2612PermitTypes = { | ||
| Permit: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "nonce", type: "uint256" }, | ||
| { name: "deadline", type: "uint256" } | ||
| ] | ||
| }; | ||
| var eip2612NoncesAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "nonces", | ||
| inputs: [{ name: "owner", type: "address" }], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| // src/exact/client/scheme.ts | ||
| var import_viem7 = require("viem"); | ||
| // src/exact/client/eip3009.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/utils.ts | ||
@@ -363,3 +387,58 @@ var import_viem3 = require("viem"); | ||
| // src/exact/client/eip2612.ts | ||
| var import_viem6 = require("viem"); | ||
| var MAX_UINT2562 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); | ||
| async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion, chainId, deadline) { | ||
| const owner = signer.address; | ||
| const spender = (0, import_viem6.getAddress)(PERMIT2_ADDRESS); | ||
| const nonce = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: eip2612NoncesAbi, | ||
| functionName: "nonces", | ||
| args: [owner] | ||
| }); | ||
| const domain = { | ||
| name: tokenName, | ||
| version: tokenVersion, | ||
| chainId, | ||
| verifyingContract: tokenAddress | ||
| }; | ||
| const message = { | ||
| owner, | ||
| spender, | ||
| value: MAX_UINT2562, | ||
| nonce, | ||
| deadline: BigInt(deadline) | ||
| }; | ||
| const signature = await signer.signTypedData({ | ||
| domain, | ||
| types: eip2612PermitTypes, | ||
| primaryType: "Permit", | ||
| message | ||
| }); | ||
| return { | ||
| from: owner, | ||
| asset: tokenAddress, | ||
| spender, | ||
| amount: MAX_UINT2562.toString(), | ||
| nonce: nonce.toString(), | ||
| deadline, | ||
| signature, | ||
| version: "1" | ||
| }; | ||
| } | ||
| // src/exact/client/scheme.ts | ||
| var erc20AllowanceAbi2 = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| var ExactEvmScheme = class { | ||
@@ -369,3 +448,5 @@ /** | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| * @param signer - The EVM signer for client operations. | ||
| * Must support `readContract` for EIP-2612 gas sponsoring. | ||
| * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
@@ -380,13 +461,82 @@ constructor(signer) { | ||
| * | ||
| * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the | ||
| * signer supports `readContract`, automatically signs an EIP-2612 permit | ||
| * when Permit2 allowance is insufficient. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload result | ||
| * @param context - Optional context with server-declared extensions | ||
| * @returns Promise resolving to a payment payload result (with optional extensions) | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| async createPaymentPayload(x402Version, paymentRequirements, context) { | ||
| const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009"; | ||
| if (assetTransferMethod === "permit2") { | ||
| return createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| const eip2612Extensions = await this.trySignEip2612Permit( | ||
| paymentRequirements, | ||
| result, | ||
| context | ||
| ); | ||
| if (eip2612Extensions) { | ||
| return { | ||
| ...result, | ||
| extensions: eip2612Extensions | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| return createEIP3009Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| /** | ||
| * Attempts to sign an EIP-2612 permit for gasless Permit2 approval. | ||
| * | ||
| * Returns extension data if: | ||
| * 1. Server advertises eip2612GasSponsoring | ||
| * 2. Signer has readContract capability | ||
| * 3. Current Permit2 allowance is insufficient | ||
| * | ||
| * Returns undefined if the extension should not be used. | ||
| * | ||
| * @param requirements - The payment requirements from the server | ||
| * @param result - The payment payload result from the scheme | ||
| * @param context - Optional context containing server extensions and metadata | ||
| * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable | ||
| */ | ||
| async trySignEip2612Permit(requirements, result, context) { | ||
| if (!context?.extensions?.[import_extensions.EIP2612_GAS_SPONSORING.key]) { | ||
| return void 0; | ||
| } | ||
| const tokenName = requirements.extra?.name; | ||
| const tokenVersion = requirements.extra?.version; | ||
| if (!tokenName || !tokenVersion) { | ||
| return void 0; | ||
| } | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const tokenAddress = (0, import_viem7.getAddress)(requirements.asset); | ||
| try { | ||
| const allowance = await this.signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: erc20AllowanceAbi2, | ||
| functionName: "allowance", | ||
| args: [this.signer.address, PERMIT2_ADDRESS] | ||
| }); | ||
| if (allowance >= BigInt(requirements.amount)) { | ||
| return void 0; | ||
| } | ||
| } catch { | ||
| } | ||
| const permit2Auth = result.payload?.permit2Authorization; | ||
| const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString(); | ||
| const info = await signEip2612Permit( | ||
| this.signer, | ||
| tokenAddress, | ||
| tokenName, | ||
| tokenVersion, | ||
| chainId, | ||
| deadline | ||
| ); | ||
| return { | ||
| [import_extensions.EIP2612_GAS_SPONSORING.key]: { info } | ||
| }; | ||
| } | ||
| }; | ||
@@ -396,8 +546,9 @@ | ||
| function registerExactEvmScheme(client, config) { | ||
| const evmScheme = new ExactEvmScheme(config.signer); | ||
| if (config.networks && config.networks.length > 0) { | ||
| config.networks.forEach((network) => { | ||
| client.register(network, new ExactEvmScheme(config.signer)); | ||
| client.register(network, evmScheme); | ||
| }); | ||
| } else { | ||
| client.register("eip155:*", new ExactEvmScheme(config.signer)); | ||
| client.register("eip155:*", evmScheme); | ||
| } | ||
@@ -404,0 +555,0 @@ NETWORKS.forEach((network) => { |
| import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse, Network } from '@x402/core/types'; | ||
| import { F as FacilitatorEvmSigner } from '../../signer-5OVDxViv.js'; | ||
| import { F as FacilitatorEvmSigner } from '../../signer-3KGwtdNT.js'; | ||
| import { x402Facilitator } from '@x402/core/facilitator'; | ||
@@ -4,0 +4,0 @@ |
@@ -473,2 +473,3 @@ "use strict"; | ||
| // src/exact/facilitator/permit2.ts | ||
| var import_extensions = require("@x402/extensions"); | ||
| var import_viem2 = require("viem"); | ||
@@ -599,9 +600,32 @@ var erc20AllowanceABI = [ | ||
| if (allowance < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_allowance_required", | ||
| payer | ||
| }; | ||
| const eip2612Info = (0, import_extensions.extractEip2612GasSponsoringInfo)(payload); | ||
| if (eip2612Info) { | ||
| const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); | ||
| if (!validationResult.isValid) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: validationResult.invalidReason, | ||
| payer | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_allowance_required", | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| } catch { | ||
| const eip2612Info = (0, import_extensions.extractEip2612GasSponsoringInfo)(payload); | ||
| if (eip2612Info) { | ||
| const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); | ||
| if (!validationResult.isValid) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: validationResult.invalidReason, | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| } | ||
@@ -644,24 +668,59 @@ try { | ||
| try { | ||
| const tx = await signer.writeContract({ | ||
| address: x402ExactPermit2ProxyAddress, | ||
| abi: x402ExactPermit2ProxyABI, | ||
| functionName: "settle", | ||
| args: [ | ||
| { | ||
| permitted: { | ||
| token: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| const eip2612Info = (0, import_extensions.extractEip2612GasSponsoringInfo)(payload); | ||
| let tx; | ||
| if (eip2612Info) { | ||
| const { v, r, s } = splitEip2612Signature(eip2612Info.signature); | ||
| tx = await signer.writeContract({ | ||
| address: x402ExactPermit2ProxyAddress, | ||
| abi: x402ExactPermit2ProxyABI, | ||
| functionName: "settleWithPermit", | ||
| args: [ | ||
| { | ||
| value: BigInt(eip2612Info.amount), | ||
| deadline: BigInt(eip2612Info.deadline), | ||
| r, | ||
| s, | ||
| v | ||
| }, | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline) | ||
| }, | ||
| (0, import_viem2.getAddress)(payer), | ||
| { | ||
| to: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| }, | ||
| permit2Payload.signature | ||
| ] | ||
| }); | ||
| { | ||
| permitted: { | ||
| token: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| }, | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline) | ||
| }, | ||
| (0, import_viem2.getAddress)(payer), | ||
| { | ||
| to: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| }, | ||
| permit2Payload.signature | ||
| ] | ||
| }); | ||
| } else { | ||
| tx = await signer.writeContract({ | ||
| address: x402ExactPermit2ProxyAddress, | ||
| abi: x402ExactPermit2ProxyABI, | ||
| functionName: "settle", | ||
| args: [ | ||
| { | ||
| permitted: { | ||
| token: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| }, | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline) | ||
| }, | ||
| (0, import_viem2.getAddress)(payer), | ||
| { | ||
| to: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| }, | ||
| permit2Payload.signature | ||
| ] | ||
| }); | ||
| } | ||
| const receipt = await signer.waitForTransactionReceipt({ hash: tx }); | ||
@@ -712,2 +771,33 @@ if (receipt.status !== "success") { | ||
| } | ||
| function validateEip2612PermitForPayment(info, payer, tokenAddress) { | ||
| if (!(0, import_extensions.validateEip2612GasSponsoringInfo)(info)) { | ||
| return { isValid: false, invalidReason: "invalid_eip2612_extension_format" }; | ||
| } | ||
| if ((0, import_viem2.getAddress)(info.from) !== (0, import_viem2.getAddress)(payer)) { | ||
| return { isValid: false, invalidReason: "eip2612_from_mismatch" }; | ||
| } | ||
| if ((0, import_viem2.getAddress)(info.asset) !== tokenAddress) { | ||
| return { isValid: false, invalidReason: "eip2612_asset_mismatch" }; | ||
| } | ||
| if ((0, import_viem2.getAddress)(info.spender) !== (0, import_viem2.getAddress)(PERMIT2_ADDRESS)) { | ||
| return { isValid: false, invalidReason: "eip2612_spender_not_permit2" }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(info.deadline) < BigInt(now + 6)) { | ||
| return { isValid: false, invalidReason: "eip2612_deadline_expired" }; | ||
| } | ||
| return { isValid: true }; | ||
| } | ||
| function splitEip2612Signature(signature) { | ||
| const sig = signature.startsWith("0x") ? signature.slice(2) : signature; | ||
| if (sig.length !== 130) { | ||
| throw new Error( | ||
| `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes` | ||
| ); | ||
| } | ||
| const r = `0x${sig.slice(0, 64)}`; | ||
| const s = `0x${sig.slice(64, 128)}`; | ||
| const v = parseInt(sig.slice(128, 130), 16); | ||
| return { v, r, s }; | ||
| } | ||
@@ -714,0 +804,0 @@ // src/exact/facilitator/scheme.ts |
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayload, Network } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from '../../../signer-5OVDxViv.js'; | ||
| import { C as ClientEvmSigner } from '../../../signer-3KGwtdNT.js'; | ||
@@ -4,0 +4,0 @@ /** |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../../../src/exact/v1/client/index.ts","../../../../../src/exact/v1/client/scheme.ts","../../../../../src/constants.ts","../../../../../src/utils.ts","../../../../../src/exact/v1/facilitator/scheme.ts","../../../../../src/v1/index.ts"],"sourcesContent":["export { ExactEvmSchemeV1 } from \"./scheme\";\n","import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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","// 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.\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 { name: \"extra\", type: \"bytes\" },\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] as const;\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\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} 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"],"mappings":"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","names":["import_viem","import_viem"]} | ||
| {"version":3,"sources":["../../../../../src/exact/v1/client/index.ts","../../../../../src/exact/v1/client/scheme.ts","../../../../../src/constants.ts","../../../../../src/utils.ts","../../../../../src/exact/v1/facilitator/scheme.ts","../../../../../src/v1/index.ts"],"sourcesContent":["export { ExactEvmSchemeV1 } from \"./scheme\";\n","import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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","// 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.\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 { name: \"extra\", type: \"bytes\" },\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] 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/**\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\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} 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"],"mappings":"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","names":["import_viem","import_viem"]} |
| import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse } from '@x402/core/types'; | ||
| import { F as FacilitatorEvmSigner } from '../../../signer-5OVDxViv.js'; | ||
| import { F as FacilitatorEvmSigner } from '../../../signer-3KGwtdNT.js'; | ||
@@ -4,0 +4,0 @@ interface ExactEvmSchemeV1Config { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../../../src/exact/v1/facilitator/index.ts","../../../../../src/exact/v1/facilitator/scheme.ts","../../../../../src/constants.ts","../../../../../src/utils.ts","../../../../../src/exact/v1/client/scheme.ts","../../../../../src/v1/index.ts"],"sourcesContent":["export { ExactEvmSchemeV1 } from \"./scheme\";\nexport type { ExactEvmSchemeV1Config } from \"./scheme\";\n","import {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\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.\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 { name: \"extra\", type: \"bytes\" },\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] as const;\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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} 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"],"mappings":"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","names":["ExactEvmSchemeV1","import_viem","import_viem","ExactEvmSchemeV1"]} | ||
| {"version":3,"sources":["../../../../../src/exact/v1/facilitator/index.ts","../../../../../src/exact/v1/facilitator/scheme.ts","../../../../../src/constants.ts","../../../../../src/utils.ts","../../../../../src/exact/v1/client/scheme.ts","../../../../../src/v1/index.ts"],"sourcesContent":["export { ExactEvmSchemeV1 } from \"./scheme\";\nexport type { ExactEvmSchemeV1Config } from \"./scheme\";\n","import {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\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.\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 { name: \"extra\", type: \"bytes\" },\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] 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/**\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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} 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"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,0BAAAA;AAAA;AAAA;;;ACSA,IAAAC,eAAuF;;;ACRhF,IAAM,qBAAqB;AAAA,EAChC,2BAA2B;AAAA,IACzB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC,EAAE,MAAM,MAAM,MAAM,UAAU;AAAA,IAC9B,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,IACjC,EAAE,MAAM,cAAc,MAAM,UAAU;AAAA,IACtC,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,IACvC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,EACnC;AACF;AA2BO,IAAM,aAAa;AAAA,EACxB;AAAA,IACE,QAAQ;AAAA,MACN,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,MAChC,EAAE,MAAM,MAAM,MAAM,UAAU;AAAA,MAC9B,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,MACjC,EAAE,MAAM,cAAc,MAAM,UAAU;AAAA,MACtC,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,MACvC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,MACjC,EAAE,MAAM,KAAK,MAAM,QAAQ;AAAA,MAC3B,EAAE,MAAM,KAAK,MAAM,UAAU;AAAA,MAC7B,EAAE,MAAM,KAAK,MAAM,UAAU;AAAA,IAC/B;AAAA,IACA,MAAM;AAAA,IACN,SAAS,CAAC;AAAA,IACV,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,QAAQ;AAAA,MACN,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,MAChC,EAAE,MAAM,MAAM,MAAM,UAAU;AAAA,MAC9B,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,MACjC,EAAE,MAAM,cAAc,MAAM,UAAU;AAAA,MACtC,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,MACvC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,MACjC,EAAE,MAAM,aAAa,MAAM,QAAQ;AAAA,IACrC;AAAA,IACA,MAAM;AAAA,IACN,SAAS,CAAC;AAAA,IACV,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,QAAQ,CAAC,EAAE,MAAM,WAAW,MAAM,UAAU,CAAC;AAAA,IAC7C,MAAM;AAAA,IACN,SAAS,CAAC,EAAE,MAAM,IAAI,MAAM,UAAU,CAAC;AAAA,IACvC,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AAAA,EACA;AAAA,IACE,QAAQ,CAAC;AAAA,IACT,MAAM;AAAA,IACN,SAAS,CAAC,EAAE,MAAM,IAAI,MAAM,SAAS,CAAC;AAAA,IACtC,iBAAiB;AAAA,IACjB,MAAM;AAAA,EACR;AACF;;;ACpFA,IAAAC,eAAsB;;;ACOtB,kBAA2B;;;ACLpB,IAAM,2BAA2B;AAAA,EACtC,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,OAAO;AAAA,EACP,KAAK;AAAA,EACL,eAAe;AAAA,EACf,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,UAAU;AAAA,EACV,sBAAsB;AAAA,EACtB,SAAS;AACX;AAIO,IAAM,WAAqB,OAAO,KAAK,wBAAwB;;;AFd/D,SAAS,cAAc,SAA+B;AAC3D,QAAM,UAAU,yBAAyB,OAAO;AAChD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,wBAAwB,OAAO,EAAE;AAAA,EACnD;AACA,SAAO;AACT;;;AFYO,IAAMC,oBAAN,MAA2D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWhE,YACmB,QACjB,QACA;AAFiB;AAXnB,SAAS,SAAS;AAClB,SAAS,aAAa;AAapB,SAAK,SAAS;AAAA,MACZ,0BAA0B,QAAQ,4BAA4B;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS,GAAgD;AACvD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,GAAqB;AAC9B,WAAO,CAAC,GAAG,KAAK,OAAO,aAAa,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OACJ,SACA,cACyB;AACzB,UAAM,iBAAiB;AACvB,UAAM,YAAY;AAClB,UAAM,kBAAkB,QAAQ;AAGhC,QAAI,UAAU,WAAW,WAAW,aAAa,WAAW,SAAS;AACnE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAGA,QAAI;AACJ,QAAI;AACF,gBAAU,cAAc,UAAU,OAAuB;AAAA,IAC3D,QAAQ;AACN,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAEA,QAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AACvC,UAAM,mBAAe,yBAAW,aAAa,KAAK;AAGlD,QAAI,UAAU,YAAY,aAAa,SAAS;AAC9C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAGA,UAAM,kBAAkB;AAAA,MACtB,OAAO;AAAA,MACP,aAAa;AAAA,MACb,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,mBAAmB;AAAA,MACrB;AAAA,MACA,SAAS;AAAA,QACP,MAAM,gBAAgB,cAAc;AAAA,QACpC,IAAI,gBAAgB,cAAc;AAAA,QAClC,OAAO,OAAO,gBAAgB,cAAc,KAAK;AAAA,QACjD,YAAY,OAAO,gBAAgB,cAAc,UAAU;AAAA,QAC3D,aAAa,OAAO,gBAAgB,cAAc,WAAW;AAAA,QAC7D,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAGA,QAAI;AACF,YAAM,mBAAmB,MAAM,KAAK,OAAO,gBAAgB;AAAA,QACzD,SAAS,gBAAgB,cAAc;AAAA,QACvC,GAAG;AAAA,QACH,WAAW,gBAAgB;AAAA,MAC7B,CAAC;AAED,UAAI,CAAC,kBAAkB;AACrB,eAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe;AAAA,UACf,OAAO,gBAAgB,cAAc;AAAA,QACvC;AAAA,MACF;AAAA,IACF,QAAQ;AAGN,YAAM,YAAY,gBAAgB;AAClC,YAAM,kBAAkB,UAAU,WAAW,IAAI,IAAI,UAAU,SAAS,IAAI,UAAU;AACtF,YAAM,gBAAgB,kBAAkB;AAExC,UAAI,eAAe;AACjB,cAAM,eAAe,gBAAgB,cAAc;AACnD,cAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,EAAE,SAAS,aAAa,CAAC;AAEpE,YAAI,CAAC,YAAY,aAAa,MAAM;AAIlC,gBAAM,kBAAc,oCAAsB,SAAS;AACnD,gBAAM,oBACJ,YAAY,WACZ,YAAY,QACZ,KAAC,6BAAe,YAAY,SAAS,4CAA4C;AAEnF,cAAI,CAAC,mBAAmB;AAGtB,mBAAO;AAAA,cACL,SAAS;AAAA,cACT,eAAe;AAAA,cACf,OAAO;AAAA,YACT;AAAA,UACF;AAAA,QAGF,OAAO;AAEL,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,eAAe;AAAA,YACf,OAAO,gBAAgB,cAAc;AAAA,UACvC;AAAA,QACF;AAAA,MACF,OAAO;AAEL,eAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe;AAAA,UACf,OAAO,gBAAgB,cAAc;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAGA,YAAI,yBAAW,gBAAgB,cAAc,EAAE,UAAM,yBAAW,aAAa,KAAK,GAAG;AACnF,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAGA,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAI,OAAO,gBAAgB,cAAc,WAAW,IAAI,OAAO,MAAM,CAAC,GAAG;AACvE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAGA,QAAI,OAAO,gBAAgB,cAAc,UAAU,IAAI,OAAO,GAAG,GAAG;AAClE,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAGA,QAAI;AACF,YAAM,UAAW,MAAM,KAAK,OAAO,aAAa;AAAA,QAC9C,SAAS;AAAA,QACT,KAAK;AAAA,QACL,cAAc;AAAA,QACd,MAAM,CAAC,gBAAgB,cAAc,IAAI;AAAA,MAC3C,CAAC;AAED,UAAI,OAAO,OAAO,IAAI,OAAO,eAAe,iBAAiB,GAAG;AAC9D,eAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe;AAAA,UACf,gBAAgB,yDAAyD,eAAe,iBAAiB,IAAI,aAAa,KAAK,gBAAgB,QAAQ,SAAS,CAAC,IAAI,aAAa,KAAK;AAAA,UACvL,OAAO,gBAAgB,cAAc;AAAA,QACvC;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAGA,QAAI,OAAO,gBAAgB,cAAc,KAAK,IAAI,OAAO,eAAe,iBAAiB,GAAG;AAC1F,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf,OAAO,gBAAgB,cAAc;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,OACJ,SACA,cACyB;AACzB,UAAM,YAAY;AAClB,UAAM,kBAAkB,QAAQ;AAGhC,UAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,YAAY;AACrD,QAAI,CAAC,MAAM,SAAS;AAClB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,SAAS,UAAU;AAAA,QACnB,aAAa;AAAA,QACb,aAAa,MAAM,iBAAiB;AAAA,QACpC,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAEA,QAAI;AAEF,YAAM,kBAAc,oCAAsB,gBAAgB,SAAU;AACpE,YAAM,EAAE,WAAW,SAAS,gBAAgB,MAAM,gBAAgB,IAAI;AAGtE,UACE,KAAK,OAAO,4BACZ,kBACA,mBACA,KAAC,6BAAe,gBAAgB,4CAA4C,GAC5E;AAEA,cAAM,eAAe,gBAAgB,cAAc;AACnD,cAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,EAAE,SAAS,aAAa,CAAC;AAEpE,YAAI,CAAC,YAAY,aAAa,MAAM;AAElC,cAAI;AACF,oBAAQ,IAAI,uCAAuC,YAAY,eAAe;AAI9E,kBAAM,WAAW,MAAM,KAAK,OAAO,gBAAgB;AAAA,cACjD,IAAI;AAAA,cACJ,MAAM;AAAA,YACR,CAAC;AAGD,kBAAM,KAAK,OAAO,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAC9D,oBAAQ,IAAI,0CAA0C,YAAY,EAAE;AAAA,UACtE,SAAS,aAAa;AACpB,oBAAQ,MAAM,mCAAmC,WAAW;AAE5D,kBAAM;AAAA,UACR;AAAA,QACF,OAAO;AACL,kBAAQ,IAAI,oBAAoB,YAAY,wCAAwC;AAAA,QACtF;AAAA,MACF;AAIA,YAAM,kBAAkB,UAAU,WAAW,IAAI,IAAI,UAAU,SAAS,IAAI,UAAU;AACtF,YAAM,UAAU,oBAAoB;AAEpC,UAAI;AACJ,UAAI,SAAS;AAEX,cAAM,gBAAY,6BAAe,SAAS;AAE1C,aAAK,MAAM,KAAK,OAAO,cAAc;AAAA,UACnC,aAAS,yBAAW,aAAa,KAAK;AAAA,UACtC,KAAK;AAAA,UACL,cAAc;AAAA,UACd,MAAM;AAAA,gBACJ,yBAAW,gBAAgB,cAAc,IAAI;AAAA,gBAC7C,yBAAW,gBAAgB,cAAc,EAAE;AAAA,YAC3C,OAAO,gBAAgB,cAAc,KAAK;AAAA,YAC1C,OAAO,gBAAgB,cAAc,UAAU;AAAA,YAC/C,OAAO,gBAAgB,cAAc,WAAW;AAAA,YAChD,gBAAgB,cAAc;AAAA,YAC7B,UAAU,KAA4B,UAAU;AAAA,YACjD,UAAU;AAAA,YACV,UAAU;AAAA,UACZ;AAAA,QACF,CAAC;AAAA,MACH,OAAO;AAGL,aAAK,MAAM,KAAK,OAAO,cAAc;AAAA,UACnC,aAAS,yBAAW,aAAa,KAAK;AAAA,UACtC,KAAK;AAAA,UACL,cAAc;AAAA,UACd,MAAM;AAAA,gBACJ,yBAAW,gBAAgB,cAAc,IAAI;AAAA,gBAC7C,yBAAW,gBAAgB,cAAc,EAAE;AAAA,YAC3C,OAAO,gBAAgB,cAAc,KAAK;AAAA,YAC1C,OAAO,gBAAgB,cAAc,UAAU;AAAA,YAC/C,OAAO,gBAAgB,cAAc,WAAW;AAAA,YAChD,gBAAgB,cAAc;AAAA,YAC9B;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAGA,YAAM,UAAU,MAAM,KAAK,OAAO,0BAA0B,EAAE,MAAM,GAAG,CAAC;AAExE,UAAI,QAAQ,WAAW,WAAW;AAChC,eAAO;AAAA,UACL,SAAS;AAAA,UACT,aAAa;AAAA,UACb,aAAa;AAAA,UACb,SAAS,UAAU;AAAA,UACnB,OAAO,gBAAgB,cAAc;AAAA,QACvC;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS,UAAU;AAAA,QACnB,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,iCAAiC,KAAK;AACpD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,aAAa;AAAA,QACb,SAAS,UAAU;AAAA,QACnB,OAAO,gBAAgB,cAAc;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AACF;","names":["ExactEvmSchemeV1","import_viem","import_viem","ExactEvmSchemeV1"]} |
@@ -1,3 +0,3 @@ | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from './permit2-BYv82va2.js'; | ||
| export { C as ClientEvmSigner, F as FacilitatorEvmSigner, t as toClientEvmSigner, a as toFacilitatorEvmSigner } from './signer-5OVDxViv.js'; | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from './permit2-CzKPU5By.js'; | ||
| export { C as ClientEvmSigner, F as FacilitatorEvmSigner, t as toClientEvmSigner, a as toFacilitatorEvmSigner } from './signer-3KGwtdNT.js'; | ||
| import '@x402/core/types'; | ||
@@ -4,0 +4,0 @@ |
+168
-8
@@ -41,4 +41,4 @@ "use strict"; | ||
| // src/exact/client/eip3009.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/exact/client/scheme.ts | ||
| var import_extensions = require("@x402/extensions"); | ||
@@ -122,2 +122,20 @@ // src/constants.ts | ||
| ]; | ||
| var eip2612PermitTypes = { | ||
| Permit: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "nonce", type: "uint256" }, | ||
| { name: "deadline", type: "uint256" } | ||
| ] | ||
| }; | ||
| var eip2612NoncesAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "nonces", | ||
| inputs: [{ name: "owner", type: "address" }], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
@@ -253,2 +271,8 @@ var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| // src/exact/client/scheme.ts | ||
| var import_viem7 = require("viem"); | ||
| // src/exact/client/eip3009.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/utils.ts | ||
@@ -463,3 +487,58 @@ var import_viem3 = require("viem"); | ||
| // src/exact/client/eip2612.ts | ||
| var import_viem6 = require("viem"); | ||
| var MAX_UINT2562 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); | ||
| async function signEip2612Permit(signer, tokenAddress, tokenName, tokenVersion, chainId, deadline) { | ||
| const owner = signer.address; | ||
| const spender = (0, import_viem6.getAddress)(PERMIT2_ADDRESS); | ||
| const nonce = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: eip2612NoncesAbi, | ||
| functionName: "nonces", | ||
| args: [owner] | ||
| }); | ||
| const domain = { | ||
| name: tokenName, | ||
| version: tokenVersion, | ||
| chainId, | ||
| verifyingContract: tokenAddress | ||
| }; | ||
| const message = { | ||
| owner, | ||
| spender, | ||
| value: MAX_UINT2562, | ||
| nonce, | ||
| deadline: BigInt(deadline) | ||
| }; | ||
| const signature = await signer.signTypedData({ | ||
| domain, | ||
| types: eip2612PermitTypes, | ||
| primaryType: "Permit", | ||
| message | ||
| }); | ||
| return { | ||
| from: owner, | ||
| asset: tokenAddress, | ||
| spender, | ||
| amount: MAX_UINT2562.toString(), | ||
| nonce: nonce.toString(), | ||
| deadline, | ||
| signature, | ||
| version: "1" | ||
| }; | ||
| } | ||
| // src/exact/client/scheme.ts | ||
| var erc20AllowanceAbi2 = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| var ExactEvmScheme = class { | ||
@@ -469,3 +548,5 @@ /** | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| * @param signer - The EVM signer for client operations. | ||
| * Must support `readContract` for EIP-2612 gas sponsoring. | ||
| * Use `createWalletClient(...).extend(publicActions)` or `toClientEvmSigner(account, publicClient)`. | ||
| */ | ||
@@ -480,18 +561,97 @@ constructor(signer) { | ||
| * | ||
| * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the | ||
| * signer supports `readContract`, automatically signs an EIP-2612 permit | ||
| * when Permit2 allowance is insufficient. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload result | ||
| * @param context - Optional context with server-declared extensions | ||
| * @returns Promise resolving to a payment payload result (with optional extensions) | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| async createPaymentPayload(x402Version, paymentRequirements, context) { | ||
| const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009"; | ||
| if (assetTransferMethod === "permit2") { | ||
| return createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| const eip2612Extensions = await this.trySignEip2612Permit( | ||
| paymentRequirements, | ||
| result, | ||
| context | ||
| ); | ||
| if (eip2612Extensions) { | ||
| return { | ||
| ...result, | ||
| extensions: eip2612Extensions | ||
| }; | ||
| } | ||
| return result; | ||
| } | ||
| return createEIP3009Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| /** | ||
| * Attempts to sign an EIP-2612 permit for gasless Permit2 approval. | ||
| * | ||
| * Returns extension data if: | ||
| * 1. Server advertises eip2612GasSponsoring | ||
| * 2. Signer has readContract capability | ||
| * 3. Current Permit2 allowance is insufficient | ||
| * | ||
| * Returns undefined if the extension should not be used. | ||
| * | ||
| * @param requirements - The payment requirements from the server | ||
| * @param result - The payment payload result from the scheme | ||
| * @param context - Optional context containing server extensions and metadata | ||
| * @returns Extension data for EIP-2612 gas sponsoring, or undefined if not applicable | ||
| */ | ||
| async trySignEip2612Permit(requirements, result, context) { | ||
| if (!context?.extensions?.[import_extensions.EIP2612_GAS_SPONSORING.key]) { | ||
| return void 0; | ||
| } | ||
| const tokenName = requirements.extra?.name; | ||
| const tokenVersion = requirements.extra?.version; | ||
| if (!tokenName || !tokenVersion) { | ||
| return void 0; | ||
| } | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const tokenAddress = (0, import_viem7.getAddress)(requirements.asset); | ||
| try { | ||
| const allowance = await this.signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: erc20AllowanceAbi2, | ||
| functionName: "allowance", | ||
| args: [this.signer.address, PERMIT2_ADDRESS] | ||
| }); | ||
| if (allowance >= BigInt(requirements.amount)) { | ||
| return void 0; | ||
| } | ||
| } catch { | ||
| } | ||
| const permit2Auth = result.payload?.permit2Authorization; | ||
| const deadline = permit2Auth?.deadline ?? Math.floor(Date.now() / 1e3 + requirements.maxTimeoutSeconds).toString(); | ||
| const info = await signEip2612Permit( | ||
| this.signer, | ||
| tokenAddress, | ||
| tokenName, | ||
| tokenVersion, | ||
| chainId, | ||
| deadline | ||
| ); | ||
| return { | ||
| [import_extensions.EIP2612_GAS_SPONSORING.key]: { info } | ||
| }; | ||
| } | ||
| }; | ||
| // src/signer.ts | ||
| function toClientEvmSigner(signer) { | ||
| return signer; | ||
| function toClientEvmSigner(signer, publicClient) { | ||
| const readContract = signer.readContract ?? publicClient?.readContract.bind(publicClient); | ||
| if (!readContract) { | ||
| throw new Error( | ||
| "toClientEvmSigner requires either a signer with readContract or a publicClient. Use createWalletClient(...).extend(publicActions) or pass a publicClient." | ||
| ); | ||
| } | ||
| return { | ||
| address: signer.address, | ||
| signTypedData: (msg) => signer.signTypedData(msg), | ||
| readContract | ||
| }; | ||
| } | ||
@@ -498,0 +658,0 @@ function toFacilitatorEvmSigner(client) { |
| export { ExactEvmSchemeV1 } from '../exact/v1/client/index.js'; | ||
| import '@x402/core/types'; | ||
| import '../signer-5OVDxViv.js'; | ||
| import '../signer-3KGwtdNT.js'; | ||
@@ -5,0 +5,0 @@ declare const EVM_NETWORK_CHAIN_ID_MAP: { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../src/v1/index.ts","../../../src/exact/v1/client/scheme.ts","../../../src/constants.ts","../../../src/utils.ts","../../../src/exact/v1/facilitator/scheme.ts"],"sourcesContent":["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} 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","import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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","// 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.\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 { name: \"extra\", type: \"bytes\" },\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] as const;\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n }\n}\n"],"mappings":"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","names":["import_viem","import_viem"]} | ||
| {"version":3,"sources":["../../../src/v1/index.ts","../../../src/exact/v1/client/scheme.ts","../../../src/constants.ts","../../../src/utils.ts","../../../src/exact/v1/facilitator/scheme.ts"],"sourcesContent":["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} 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","import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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","// 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.\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 { name: \"extra\", type: \"bytes\" },\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] 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/**\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n }\n}\n"],"mappings":"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","names":["import_viem","import_viem"]} |
@@ -1,5 +0,5 @@ | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-BsAoJiWD.mjs'; | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-C2FkNEHT.mjs'; | ||
| import { SelectPaymentRequirements, PaymentPolicy, x402Client } from '@x402/core/client'; | ||
| import { Network } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from '../../signer-5OVDxViv.mjs'; | ||
| import { C as ClientEvmSigner } from '../../signer-3KGwtdNT.mjs'; | ||
@@ -6,0 +6,0 @@ /** |
@@ -7,4 +7,4 @@ import { | ||
| registerExactEvmScheme | ||
| } from "../../chunk-E2YMUI3X.mjs"; | ||
| import "../../chunk-RPL6OFJL.mjs"; | ||
| } from "../../chunk-CJHYX7BQ.mjs"; | ||
| import "../../chunk-GSU4DHTC.mjs"; | ||
| export { | ||
@@ -11,0 +11,0 @@ ExactEvmScheme, |
| import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse, Network } from '@x402/core/types'; | ||
| import { F as FacilitatorEvmSigner } from '../../signer-5OVDxViv.mjs'; | ||
| import { F as FacilitatorEvmSigner } from '../../signer-3KGwtdNT.mjs'; | ||
| import { x402Facilitator } from '@x402/core/facilitator'; | ||
@@ -4,0 +4,0 @@ |
@@ -13,3 +13,3 @@ import { | ||
| x402ExactPermit2ProxyAddress | ||
| } from "../../chunk-RPL6OFJL.mjs"; | ||
| } from "../../chunk-GSU4DHTC.mjs"; | ||
@@ -248,2 +248,6 @@ // src/exact/facilitator/eip3009.ts | ||
| // src/exact/facilitator/permit2.ts | ||
| import { | ||
| extractEip2612GasSponsoringInfo, | ||
| validateEip2612GasSponsoringInfo | ||
| } from "@x402/extensions"; | ||
| import { getAddress as getAddress2 } from "viem"; | ||
@@ -374,9 +378,32 @@ var erc20AllowanceABI = [ | ||
| if (allowance < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_allowance_required", | ||
| payer | ||
| }; | ||
| const eip2612Info = extractEip2612GasSponsoringInfo(payload); | ||
| if (eip2612Info) { | ||
| const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); | ||
| if (!validationResult.isValid) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: validationResult.invalidReason, | ||
| payer | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_allowance_required", | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| } catch { | ||
| const eip2612Info = extractEip2612GasSponsoringInfo(payload); | ||
| if (eip2612Info) { | ||
| const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress); | ||
| if (!validationResult.isValid) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: validationResult.invalidReason, | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| } | ||
@@ -419,24 +446,59 @@ try { | ||
| try { | ||
| const tx = await signer.writeContract({ | ||
| address: x402ExactPermit2ProxyAddress, | ||
| abi: x402ExactPermit2ProxyABI, | ||
| functionName: "settle", | ||
| args: [ | ||
| { | ||
| permitted: { | ||
| token: getAddress2(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| const eip2612Info = extractEip2612GasSponsoringInfo(payload); | ||
| let tx; | ||
| if (eip2612Info) { | ||
| const { v, r, s } = splitEip2612Signature(eip2612Info.signature); | ||
| tx = await signer.writeContract({ | ||
| address: x402ExactPermit2ProxyAddress, | ||
| abi: x402ExactPermit2ProxyABI, | ||
| functionName: "settleWithPermit", | ||
| args: [ | ||
| { | ||
| value: BigInt(eip2612Info.amount), | ||
| deadline: BigInt(eip2612Info.deadline), | ||
| r, | ||
| s, | ||
| v | ||
| }, | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline) | ||
| }, | ||
| getAddress2(payer), | ||
| { | ||
| to: getAddress2(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| }, | ||
| permit2Payload.signature | ||
| ] | ||
| }); | ||
| { | ||
| permitted: { | ||
| token: getAddress2(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| }, | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline) | ||
| }, | ||
| getAddress2(payer), | ||
| { | ||
| to: getAddress2(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| }, | ||
| permit2Payload.signature | ||
| ] | ||
| }); | ||
| } else { | ||
| tx = await signer.writeContract({ | ||
| address: x402ExactPermit2ProxyAddress, | ||
| abi: x402ExactPermit2ProxyABI, | ||
| functionName: "settle", | ||
| args: [ | ||
| { | ||
| permitted: { | ||
| token: getAddress2(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| }, | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline) | ||
| }, | ||
| getAddress2(payer), | ||
| { | ||
| to: getAddress2(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| }, | ||
| permit2Payload.signature | ||
| ] | ||
| }); | ||
| } | ||
| const receipt = await signer.waitForTransactionReceipt({ hash: tx }); | ||
@@ -487,2 +549,33 @@ if (receipt.status !== "success") { | ||
| } | ||
| function validateEip2612PermitForPayment(info, payer, tokenAddress) { | ||
| if (!validateEip2612GasSponsoringInfo(info)) { | ||
| return { isValid: false, invalidReason: "invalid_eip2612_extension_format" }; | ||
| } | ||
| if (getAddress2(info.from) !== getAddress2(payer)) { | ||
| return { isValid: false, invalidReason: "eip2612_from_mismatch" }; | ||
| } | ||
| if (getAddress2(info.asset) !== tokenAddress) { | ||
| return { isValid: false, invalidReason: "eip2612_asset_mismatch" }; | ||
| } | ||
| if (getAddress2(info.spender) !== getAddress2(PERMIT2_ADDRESS)) { | ||
| return { isValid: false, invalidReason: "eip2612_spender_not_permit2" }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(info.deadline) < BigInt(now + 6)) { | ||
| return { isValid: false, invalidReason: "eip2612_deadline_expired" }; | ||
| } | ||
| return { isValid: true }; | ||
| } | ||
| function splitEip2612Signature(signature) { | ||
| const sig = signature.startsWith("0x") ? signature.slice(2) : signature; | ||
| if (sig.length !== 130) { | ||
| throw new Error( | ||
| `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes` | ||
| ); | ||
| } | ||
| const r = `0x${sig.slice(0, 64)}`; | ||
| const s = `0x${sig.slice(64, 128)}`; | ||
| const v = parseInt(sig.slice(128, 130), 16); | ||
| return { v, r, s }; | ||
| } | ||
@@ -489,0 +582,0 @@ // src/exact/facilitator/scheme.ts |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../../src/exact/facilitator/eip3009.ts","../../../../src/exact/facilitator/permit2.ts","../../../../src/exact/facilitator/scheme.ts","../../../../src/exact/facilitator/register.ts"],"sourcesContent":["import {\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\n\nexport interface EIP3009FacilitatorConfig {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492: boolean;\n}\n\n/**\n * Verifies an EIP-3009 payment payload.\n *\n * @param signer - The facilitator signer for contract reads\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param eip3009Payload - The EIP-3009 specific payload\n * @returns Promise resolving to verification response\n */\nexport async function verifyEIP3009(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n eip3009Payload: ExactEIP3009Payload,\n): Promise<VerifyResponse> {\n const payer = eip3009Payload.authorization.from;\n\n // Verify scheme matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer,\n };\n }\n\n // Get chain configuration\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer,\n };\n }\n\n const { name, version } = requirements.extra;\n const erc20Address = getAddress(requirements.asset);\n\n // Verify network matches\n if (payload.accepted.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: \"network_mismatch\",\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: parseInt(requirements.network.split(\":\")[1]),\n verifyingContract: erc20Address,\n },\n message: {\n from: eip3009Payload.authorization.from,\n to: eip3009Payload.authorization.to,\n value: BigInt(eip3009Payload.authorization.value),\n validAfter: BigInt(eip3009Payload.authorization.validAfter),\n validBefore: BigInt(eip3009Payload.authorization.validBefore),\n nonce: eip3009Payload.authorization.nonce,\n },\n };\n\n // Verify signature\n try {\n const recoveredAddress = await signer.verifyTypedData({\n address: eip3009Payload.authorization.from,\n ...permitTypedData,\n signature: eip3009Payload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = eip3009Payload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = eip3009Payload.authorization.from;\n const bytecode = await signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer,\n };\n }\n }\n\n // Verify payment recipient matches\n if (getAddress(eip3009Payload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_recipient_mismatch\",\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(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer,\n };\n }\n\n // Check balance\n try {\n const balance = (await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [eip3009Payload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(eip3009Payload.authorization.value) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n}\n\n/**\n * Settles an EIP-3009 payment by executing transferWithAuthorization.\n *\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param eip3009Payload - The EIP-3009 specific payload\n * @param config - Facilitator configuration\n * @returns Promise resolving to settlement response\n */\nexport async function settleEIP3009(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n eip3009Payload: ExactEIP3009Payload,\n config: EIP3009FacilitatorConfig,\n): Promise<SettleResponse> {\n const payer = eip3009Payload.authorization.from;\n\n // Re-verify before settling\n const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload);\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(eip3009Payload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n config.deployERC4337WithEIP6492 &&\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const bytecode = await signer.getCode({ address: payer });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet not deployed - attempt deployment\n const deployTx = await signer.sendTransaction({\n to: factoryAddress as Hex,\n data: factoryCalldata as Hex,\n });\n\n // Wait for deployment transaction\n await signer.waitForTransactionReceipt({ hash: deployTx });\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(eip3009Payload.authorization.from),\n getAddress(eip3009Payload.authorization.to),\n BigInt(eip3009Payload.authorization.value),\n BigInt(eip3009Payload.authorization.validAfter),\n BigInt(eip3009Payload.authorization.validBefore),\n eip3009Payload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n tx = await signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(eip3009Payload.authorization.from),\n getAddress(eip3009Payload.authorization.to),\n BigInt(eip3009Payload.authorization.value),\n BigInt(eip3009Payload.authorization.validAfter),\n BigInt(eip3009Payload.authorization.validBefore),\n eip3009Payload.authorization.nonce,\n signature,\n ],\n });\n }\n\n // Wait for transaction confirmation\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: \"invalid_transaction_state\",\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n } catch {\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport {\n eip3009ABI,\n PERMIT2_ADDRESS,\n permit2WitnessTypes,\n x402ExactPermit2ProxyABI,\n x402ExactPermit2ProxyAddress,\n} from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\n\n// ERC20 allowance ABI for checking Permit2 approval\nconst 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/**\n * Verifies a Permit2 payment payload.\n *\n * @param signer - The facilitator signer for contract reads\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param permit2Payload - The Permit2 specific payload\n * @returns Promise resolving to verification response\n */\nexport async function verifyPermit2(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n permit2Payload: ExactPermit2Payload,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n // Verify scheme matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer,\n };\n }\n\n // Verify network matches\n if (payload.accepted.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: \"network_mismatch\",\n payer,\n };\n }\n\n const chainId = parseInt(requirements.network.split(\":\")[1]);\n const tokenAddress = getAddress(requirements.asset);\n\n // Verify spender is the x402ExactPermit2Proxy\n if (\n getAddress(permit2Payload.permit2Authorization.spender) !==\n getAddress(x402ExactPermit2ProxyAddress)\n ) {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_spender\",\n payer,\n };\n }\n\n // Verify witness.to matches payTo\n if (\n getAddress(permit2Payload.permit2Authorization.witness.to) !== getAddress(requirements.payTo)\n ) {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_recipient_mismatch\",\n payer,\n };\n }\n\n // Verify deadline not expired (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: \"permit2_deadline_expired\",\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: \"permit2_not_yet_valid\",\n payer,\n };\n }\n\n // Verify amount is sufficient\n if (BigInt(permit2Payload.permit2Authorization.permitted.amount) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"permit2_insufficient_amount\",\n payer,\n };\n }\n\n // Verify token matches\n if (getAddress(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: \"permit2_token_mismatch\",\n payer,\n };\n }\n\n // Build typed data for Permit2 signature verification\n const permit2TypedData = {\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\" as const,\n domain: {\n name: \"Permit2\",\n chainId,\n verifyingContract: PERMIT2_ADDRESS,\n },\n message: {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Payload.permit2Authorization.spender),\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n extra: permit2Payload.permit2Authorization.witness.extra,\n },\n },\n };\n\n // Verify signature\n try {\n const isValid = await signer.verifyTypedData({\n address: payer,\n ...permit2TypedData,\n signature: permit2Payload.signature,\n });\n\n if (!isValid) {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_signature\",\n payer,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_signature\",\n payer,\n };\n }\n\n // Check Permit2 allowance\n try {\n const allowance = (await signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceABI,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"permit2_allowance_required\",\n payer,\n };\n }\n } catch {\n // If we can't check allowance, continue - settlement will fail if insufficient\n }\n\n // Check balance\n try {\n const balance = (await signer.readContract({\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n })) as bigint;\n\n if (balance < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n}\n\n/**\n * Settles a Permit2 payment by calling the x402ExactPermit2Proxy.\n *\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param permit2Payload - The Permit2 specific payload\n * @returns Promise resolving to settlement response\n */\nexport async function settlePermit2(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n permit2Payload: ExactPermit2Payload,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n // Re-verify before settling\n const valid = await verifyPermit2(signer, payload, requirements, permit2Payload);\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer,\n };\n }\n\n try {\n // Call x402ExactPermit2Proxy.settle()\n const tx = await signer.writeContract({\n address: x402ExactPermit2ProxyAddress,\n abi: x402ExactPermit2ProxyABI,\n functionName: \"settle\",\n args: [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n getAddress(payer),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n extra: permit2Payload.permit2Authorization.witness.extra as `0x${string}`,\n },\n permit2Payload.signature,\n ],\n });\n\n // Wait for transaction confirmation\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: \"invalid_transaction_state\",\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n } catch (error) {\n // Extract meaningful error message from the contract revert\n let errorReason = \"transaction_failed\";\n if (error instanceof Error) {\n // Check for common contract revert patterns\n const message = error.message;\n if (message.includes(\"AmountExceedsPermitted\")) {\n errorReason = \"permit2_amount_exceeds_permitted\";\n } else if (message.includes(\"InvalidDestination\")) {\n errorReason = \"permit2_invalid_destination\";\n } else if (message.includes(\"InvalidOwner\")) {\n errorReason = \"permit2_invalid_owner\";\n } else if (message.includes(\"PaymentTooEarly\")) {\n errorReason = \"permit2_payment_too_early\";\n } else if (message.includes(\"InvalidSignature\") || message.includes(\"SignatureExpired\")) {\n errorReason = \"permit2_invalid_signature\";\n } else if (message.includes(\"InvalidNonce\")) {\n errorReason = \"permit2_invalid_nonce\";\n } else {\n // Include error message for debugging (longer for better visibility)\n errorReason = `transaction_failed: ${message.slice(0, 500)}`;\n }\n }\n return {\n success: false,\n errorReason,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEvmPayloadV2, ExactEIP3009Payload, isPermit2Payload } from \"../../types\";\nimport { verifyEIP3009, settleEIP3009 } from \"./eip3009\";\nimport { verifyPermit2, settlePermit2 } from \"./permit2\";\n\nexport interface ExactEvmSchemeConfig {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme.\n * Routes between EIP-3009 and Permit2 based on payload type.\n */\nexport class ExactEvmScheme implements SchemeNetworkFacilitator {\n readonly scheme = \"exact\";\n readonly caipFamily = \"eip155:*\";\n private readonly config: Required<ExactEvmSchemeConfig>;\n\n /**\n * Creates a new ExactEvmFacilitator 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?: ExactEvmSchemeConfig,\n ) {\n this.config = {\n deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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.\n * Routes to the appropriate verification logic based on payload type.\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 const rawPayload = payload.payload as ExactEvmPayloadV2;\n\n // Route based on payload type\n if (isPermit2Payload(rawPayload)) {\n return verifyPermit2(this.signer, payload, requirements, rawPayload);\n }\n\n // Type-narrowed to EIP-3009 payload\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return verifyEIP3009(this.signer, payload, requirements, eip3009Payload);\n }\n\n /**\n * Settles a payment by executing the transfer.\n * Routes to the appropriate settlement logic based on payload type.\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<SettleResponse> {\n const rawPayload = payload.payload as ExactEvmPayloadV2;\n\n // Route based on payload type\n if (isPermit2Payload(rawPayload)) {\n return settlePermit2(this.signer, payload, requirements, rawPayload);\n }\n\n // Type-narrowed to EIP-3009 payload\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config);\n }\n}\n","import { x402Facilitator } from \"@x402/core/facilitator\";\nimport { Network } from \"@x402/core/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEvmScheme } from \"./scheme\";\nimport { ExactEvmSchemeV1 } from \"../v1/facilitator/scheme\";\nimport { NETWORKS } from \"../../v1\";\n\n/**\n * Configuration options for registering EVM schemes to an x402Facilitator\n */\nexport interface EvmFacilitatorConfig {\n /**\n * The EVM signer for facilitator operations (verify and settle)\n */\n signer: FacilitatorEvmSigner;\n\n /**\n * Networks to register (single network or array of networks)\n * Examples: \"eip155:84532\", [\"eip155:84532\", \"eip155:1\"]\n */\n networks: Network | Network[];\n\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: boolean;\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Facilitator instance.\n *\n * This function registers:\n * - V2: Specified networks with ExactEvmScheme\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param facilitator - The x402Facilitator instance to register schemes to\n * @param config - Configuration for EVM facilitator registration\n * @returns The facilitator instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/facilitator/register\";\n * import { x402Facilitator } from \"@x402/core/facilitator\";\n * import { createPublicClient, createWalletClient } from \"viem\";\n *\n * const facilitator = new x402Facilitator();\n *\n * // Single network\n * registerExactEvmScheme(facilitator, {\n * signer: combinedClient,\n * networks: \"eip155:84532\" // Base Sepolia\n * });\n *\n * // Multiple networks (will auto-derive eip155:* pattern)\n * registerExactEvmScheme(facilitator, {\n * signer: combinedClient,\n * networks: [\"eip155:84532\", \"eip155:1\"] // Base Sepolia and Mainnet\n * });\n * ```\n */\nexport function registerExactEvmScheme(\n facilitator: x402Facilitator,\n config: EvmFacilitatorConfig,\n): x402Facilitator {\n // Register V2 scheme with specified networks\n facilitator.register(\n config.networks,\n new ExactEvmScheme(config.signer, {\n deployERC4337WithEIP6492: config.deployERC4337WithEIP6492,\n }),\n );\n\n // Register all V1 networks\n facilitator.registerV1(\n NETWORKS as Network[],\n new ExactEvmSchemeV1(config.signer, {\n deployERC4337WithEIP6492: config.deployERC4337WithEIP6492,\n }),\n );\n\n return facilitator;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAMA,SAAS,YAAiB,gBAAgB,uBAAuB,sBAAsB;AAwBvF,eAAsB,cACpB,QACA,SACA,cACA,gBACyB;AACzB,QAAM,QAAQ,eAAe,cAAc;AAG3C,MAAI,QAAQ,SAAS,WAAW,WAAW,aAAa,WAAW,SAAS;AAC1E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AACvC,QAAM,eAAe,WAAW,aAAa,KAAK;AAGlD,MAAI,QAAQ,SAAS,YAAY,aAAa,SAAS;AACrD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA,SAAS,SAAS,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAAA,MACpD,mBAAmB;AAAA,IACrB;AAAA,IACA,SAAS;AAAA,MACP,MAAM,eAAe,cAAc;AAAA,MACnC,IAAI,eAAe,cAAc;AAAA,MACjC,OAAO,OAAO,eAAe,cAAc,KAAK;AAAA,MAChD,YAAY,OAAO,eAAe,cAAc,UAAU;AAAA,MAC1D,aAAa,OAAO,eAAe,cAAc,WAAW;AAAA,MAC5D,OAAO,eAAe,cAAc;AAAA,IACtC;AAAA,EACF;AAGA,MAAI;AACF,UAAM,mBAAmB,MAAM,OAAO,gBAAgB;AAAA,MACpD,SAAS,eAAe,cAAc;AAAA,MACtC,GAAG;AAAA,MACH,WAAW,eAAe;AAAA,IAC5B,CAAC;AAED,QAAI,CAAC,kBAAkB;AACrB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAGN,UAAM,YAAY,eAAe;AACjC,UAAM,kBAAkB,UAAU,WAAW,IAAI,IAAI,UAAU,SAAS,IAAI,UAAU;AACtF,UAAM,gBAAgB,kBAAkB;AAExC,QAAI,eAAe;AACjB,YAAM,eAAe,eAAe,cAAc;AAClD,YAAM,WAAW,MAAM,OAAO,QAAQ,EAAE,SAAS,aAAa,CAAC;AAE/D,UAAI,CAAC,YAAY,aAAa,MAAM;AAElC,cAAM,cAAc,sBAAsB,SAAS;AACnD,cAAM,oBACJ,YAAY,WACZ,YAAY,QACZ,CAAC,eAAe,YAAY,SAAS,4CAA4C;AAEnF,YAAI,CAAC,mBAAmB;AAEtB,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,eAAe;AAAA,YACf,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MAEF,OAAO;AAEL,eAAO;AAAA,UACL,SAAS;AAAA,UACT,eAAe;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AAEL,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,WAAW,eAAe,cAAc,EAAE,MAAM,WAAW,aAAa,KAAK,GAAG;AAClF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,MAAI,OAAO,eAAe,cAAc,WAAW,IAAI,OAAO,MAAM,CAAC,GAAG;AACtE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,eAAe,cAAc,UAAU,IAAI,OAAO,GAAG,GAAG;AACjE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,UAAW,MAAM,OAAO,aAAa;AAAA,MACzC,SAAS;AAAA,MACT,KAAK;AAAA,MACL,cAAc;AAAA,MACd,MAAM,CAAC,eAAe,cAAc,IAAI;AAAA,IAC1C,CAAC;AAED,QAAI,OAAO,OAAO,IAAI,OAAO,aAAa,MAAM,GAAG;AACjD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,gBAAgB,yDAAyD,aAAa,MAAM,IAAI,aAAa,KAAK,gBAAgB,QAAQ,SAAS,CAAC,IAAI,aAAa,KAAK;AAAA,QAC1K;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI,OAAO,eAAe,cAAc,KAAK,IAAI,OAAO,aAAa,MAAM,GAAG;AAC5E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe;AAAA,IACf;AAAA,EACF;AACF;AAYA,eAAsB,cACpB,QACA,SACA,cACA,gBACA,QACyB;AACzB,QAAM,QAAQ,eAAe,cAAc;AAG3C,QAAM,QAAQ,MAAM,cAAc,QAAQ,SAAS,cAAc,cAAc;AAC/E,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,QAAQ,SAAS;AAAA,MAC1B,aAAa;AAAA,MACb,aAAa,MAAM,iBAAiB;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,cAAc,sBAAsB,eAAe,SAAU;AACnE,UAAM,EAAE,WAAW,SAAS,gBAAgB,MAAM,gBAAgB,IAAI;AAGtE,QACE,OAAO,4BACP,kBACA,mBACA,CAAC,eAAe,gBAAgB,4CAA4C,GAC5E;AAEA,YAAM,WAAW,MAAM,OAAO,QAAQ,EAAE,SAAS,MAAM,CAAC;AAExD,UAAI,CAAC,YAAY,aAAa,MAAM;AAElC,cAAM,WAAW,MAAM,OAAO,gBAAgB;AAAA,UAC5C,IAAI;AAAA,UACJ,MAAM;AAAA,QACR,CAAC;AAGD,cAAM,OAAO,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAAA,MAC3D;AAAA,IACF;AAGA,UAAM,kBAAkB,UAAU,WAAW,IAAI,IAAI,UAAU,SAAS,IAAI,UAAU;AACtF,UAAM,UAAU,oBAAoB;AAEpC,QAAI;AACJ,QAAI,SAAS;AAEX,YAAM,YAAY,eAAe,SAAS;AAE1C,WAAK,MAAM,OAAO,cAAc;AAAA,QAC9B,SAAS,WAAW,aAAa,KAAK;AAAA,QACtC,KAAK;AAAA,QACL,cAAc;AAAA,QACd,MAAM;AAAA,UACJ,WAAW,eAAe,cAAc,IAAI;AAAA,UAC5C,WAAW,eAAe,cAAc,EAAE;AAAA,UAC1C,OAAO,eAAe,cAAc,KAAK;AAAA,UACzC,OAAO,eAAe,cAAc,UAAU;AAAA,UAC9C,OAAO,eAAe,cAAc,WAAW;AAAA,UAC/C,eAAe,cAAc;AAAA,UAC5B,UAAU,KAA4B,UAAU;AAAA,UACjD,UAAU;AAAA,UACV,UAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AAEL,WAAK,MAAM,OAAO,cAAc;AAAA,QAC9B,SAAS,WAAW,aAAa,KAAK;AAAA,QACtC,KAAK;AAAA,QACL,cAAc;AAAA,QACd,MAAM;AAAA,UACJ,WAAW,eAAe,cAAc,IAAI;AAAA,UAC5C,WAAW,eAAe,cAAc,EAAE;AAAA,UAC1C,OAAO,eAAe,cAAc,KAAK;AAAA,UACzC,OAAO,eAAe,cAAc,UAAU;AAAA,UAC9C,OAAO,eAAe,cAAc,WAAW;AAAA,UAC/C,eAAe,cAAc;AAAA,UAC7B;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,UAAU,MAAM,OAAO,0BAA0B,EAAE,MAAM,GAAG,CAAC;AAEnE,QAAI,QAAQ,WAAW,WAAW;AAChC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,aAAa;AAAA,QACb,SAAS,QAAQ,SAAS;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,SAAS,QAAQ,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa;AAAA,MACb,SAAS,QAAQ,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;;;ACjVA,SAAS,cAAAA,mBAAkB;AAY3B,IAAM,oBAAoB;AAAA,EACxB;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,MACjC,EAAE,MAAM,WAAW,MAAM,UAAU;AAAA,IACrC;AAAA,IACA,SAAS,CAAC,EAAE,MAAM,UAAU,CAAC;AAAA,IAC7B,iBAAiB;AAAA,EACnB;AACF;AAWA,eAAsB,cACpB,QACA,SACA,cACA,gBACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAGlD,MAAI,QAAQ,SAAS,WAAW,WAAW,aAAa,WAAW,SAAS;AAC1E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,YAAY,aAAa,SAAS;AACrD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,SAAS,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAC3D,QAAM,eAAeC,YAAW,aAAa,KAAK;AAGlD,MACEA,YAAW,eAAe,qBAAqB,OAAO,MACtDA,YAAW,4BAA4B,GACvC;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MACEA,YAAW,eAAe,qBAAqB,QAAQ,EAAE,MAAMA,YAAW,aAAa,KAAK,GAC5F;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,MAAI,OAAO,eAAe,qBAAqB,QAAQ,IAAI,OAAO,MAAM,CAAC,GAAG;AAC1E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,eAAe,qBAAqB,QAAQ,UAAU,IAAI,OAAO,GAAG,GAAG;AAChF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,eAAe,qBAAqB,UAAU,MAAM,IAAI,OAAO,aAAa,MAAM,GAAG;AAC9F,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAIA,YAAW,eAAe,qBAAqB,UAAU,KAAK,MAAM,cAAc;AACpF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,mBAAmB;AAAA,IACvB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,mBAAmB;AAAA,IACrB;AAAA,IACA,SAAS;AAAA,MACP,WAAW;AAAA,QACT,OAAOA,YAAW,eAAe,qBAAqB,UAAU,KAAK;AAAA,QACrE,QAAQ,OAAO,eAAe,qBAAqB,UAAU,MAAM;AAAA,MACrE;AAAA,MACA,SAASA,YAAW,eAAe,qBAAqB,OAAO;AAAA,MAC/D,OAAO,OAAO,eAAe,qBAAqB,KAAK;AAAA,MACvD,UAAU,OAAO,eAAe,qBAAqB,QAAQ;AAAA,MAC7D,SAAS;AAAA,QACP,IAAIA,YAAW,eAAe,qBAAqB,QAAQ,EAAE;AAAA,QAC7D,YAAY,OAAO,eAAe,qBAAqB,QAAQ,UAAU;AAAA,QACzE,OAAO,eAAe,qBAAqB,QAAQ;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,UAAU,MAAM,OAAO,gBAAgB;AAAA,MAC3C,SAAS;AAAA,MACT,GAAG;AAAA,MACH,WAAW,eAAe;AAAA,IAC5B,CAAC;AAED,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,YAAa,MAAM,OAAO,aAAa;AAAA,MAC3C,SAAS;AAAA,MACT,KAAK;AAAA,MACL,cAAc;AAAA,MACd,MAAM,CAAC,OAAO,eAAe;AAAA,IAC/B,CAAC;AAED,QAAI,YAAY,OAAO,aAAa,MAAM,GAAG;AAC3C,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI;AACF,UAAM,UAAW,MAAM,OAAO,aAAa;AAAA,MACzC,SAAS;AAAA,MACT,KAAK;AAAA,MACL,cAAc;AAAA,MACd,MAAM,CAAC,KAAK;AAAA,IACd,CAAC;AAED,QAAI,UAAU,OAAO,aAAa,MAAM,GAAG;AACzC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,gBAAgB,yDAAyD,aAAa,MAAM,IAAI,aAAa,KAAK,gBAAgB,QAAQ,SAAS,CAAC,IAAI,aAAa,KAAK;AAAA,QAC1K;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe;AAAA,IACf;AAAA,EACF;AACF;AAWA,eAAsB,cACpB,QACA,SACA,cACA,gBACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAGlD,QAAM,QAAQ,MAAM,cAAc,QAAQ,SAAS,cAAc,cAAc;AAC/E,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,QAAQ,SAAS;AAAA,MAC1B,aAAa;AAAA,MACb,aAAa,MAAM,iBAAiB;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AAEF,UAAM,KAAK,MAAM,OAAO,cAAc;AAAA,MACpC,SAAS;AAAA,MACT,KAAK;AAAA,MACL,cAAc;AAAA,MACd,MAAM;AAAA,QACJ;AAAA,UACE,WAAW;AAAA,YACT,OAAOA,YAAW,eAAe,qBAAqB,UAAU,KAAK;AAAA,YACrE,QAAQ,OAAO,eAAe,qBAAqB,UAAU,MAAM;AAAA,UACrE;AAAA,UACA,OAAO,OAAO,eAAe,qBAAqB,KAAK;AAAA,UACvD,UAAU,OAAO,eAAe,qBAAqB,QAAQ;AAAA,QAC/D;AAAA,QACAA,YAAW,KAAK;AAAA,QAChB;AAAA,UACE,IAAIA,YAAW,eAAe,qBAAqB,QAAQ,EAAE;AAAA,UAC7D,YAAY,OAAO,eAAe,qBAAqB,QAAQ,UAAU;AAAA,UACzE,OAAO,eAAe,qBAAqB,QAAQ;AAAA,QACrD;AAAA,QACA,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AAGD,UAAM,UAAU,MAAM,OAAO,0BAA0B,EAAE,MAAM,GAAG,CAAC;AAEnE,QAAI,QAAQ,WAAW,WAAW;AAChC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAa;AAAA,QACb,aAAa;AAAA,QACb,SAAS,QAAQ,SAAS;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,SAAS,QAAQ,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,QAAI,cAAc;AAClB,QAAI,iBAAiB,OAAO;AAE1B,YAAM,UAAU,MAAM;AACtB,UAAI,QAAQ,SAAS,wBAAwB,GAAG;AAC9C,sBAAc;AAAA,MAChB,WAAW,QAAQ,SAAS,oBAAoB,GAAG;AACjD,sBAAc;AAAA,MAChB,WAAW,QAAQ,SAAS,cAAc,GAAG;AAC3C,sBAAc;AAAA,MAChB,WAAW,QAAQ,SAAS,iBAAiB,GAAG;AAC9C,sBAAc;AAAA,MAChB,WAAW,QAAQ,SAAS,kBAAkB,KAAK,QAAQ,SAAS,kBAAkB,GAAG;AACvF,sBAAc;AAAA,MAChB,WAAW,QAAQ,SAAS,cAAc,GAAG;AAC3C,sBAAc;AAAA,MAChB,OAAO;AAEL,sBAAc,uBAAuB,QAAQ,MAAM,GAAG,GAAG,CAAC;AAAA,MAC5D;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,aAAa;AAAA,MACb,SAAS,QAAQ,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;;;AC/SO,IAAM,iBAAN,MAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW9D,YACmB,QACjB,QACA;AAFiB;AAXnB,SAAS,SAAS;AAClB,SAAS,aAAa;AAapB,SAAK,SAAS;AAAA,MACZ,0BAA0B,QAAQ,4BAA4B;AAAA,IAChE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,SAAS,GAAgD;AACvD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,GAAqB;AAC9B,WAAO,CAAC,GAAG,KAAK,OAAO,aAAa,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OACJ,SACA,cACyB;AACzB,UAAM,aAAa,QAAQ;AAG3B,QAAI,iBAAiB,UAAU,GAAG;AAChC,aAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,UAAU;AAAA,IACrE;AAGA,UAAM,iBAAsC;AAC5C,WAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,cAAc;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OACJ,SACA,cACyB;AACzB,UAAM,aAAa,QAAQ;AAG3B,QAAI,iBAAiB,UAAU,GAAG;AAChC,aAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,UAAU;AAAA,IACrE;AAGA,UAAM,iBAAsC;AAC5C,WAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,gBAAgB,KAAK,MAAM;AAAA,EACtF;AACF;;;ACpDO,SAAS,uBACd,aACA,QACiB;AAEjB,cAAY;AAAA,IACV,OAAO;AAAA,IACP,IAAI,eAAe,OAAO,QAAQ;AAAA,MAChC,0BAA0B,OAAO;AAAA,IACnC,CAAC;AAAA,EACH;AAGA,cAAY;AAAA,IACV;AAAA,IACA,IAAI,iBAAiB,OAAO,QAAQ;AAAA,MAClC,0BAA0B,OAAO;AAAA,IACnC,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":["getAddress","getAddress"]} | ||
| {"version":3,"sources":["../../../../src/exact/facilitator/eip3009.ts","../../../../src/exact/facilitator/permit2.ts","../../../../src/exact/facilitator/scheme.ts","../../../../src/exact/facilitator/register.ts"],"sourcesContent":["import {\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\n\nexport interface EIP3009FacilitatorConfig {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492: boolean;\n}\n\n/**\n * Verifies an EIP-3009 payment payload.\n *\n * @param signer - The facilitator signer for contract reads\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param eip3009Payload - The EIP-3009 specific payload\n * @returns Promise resolving to verification response\n */\nexport async function verifyEIP3009(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n eip3009Payload: ExactEIP3009Payload,\n): Promise<VerifyResponse> {\n const payer = eip3009Payload.authorization.from;\n\n // Verify scheme matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer,\n };\n }\n\n // Get chain configuration\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer,\n };\n }\n\n const { name, version } = requirements.extra;\n const erc20Address = getAddress(requirements.asset);\n\n // Verify network matches\n if (payload.accepted.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: \"network_mismatch\",\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: parseInt(requirements.network.split(\":\")[1]),\n verifyingContract: erc20Address,\n },\n message: {\n from: eip3009Payload.authorization.from,\n to: eip3009Payload.authorization.to,\n value: BigInt(eip3009Payload.authorization.value),\n validAfter: BigInt(eip3009Payload.authorization.validAfter),\n validBefore: BigInt(eip3009Payload.authorization.validBefore),\n nonce: eip3009Payload.authorization.nonce,\n },\n };\n\n // Verify signature\n try {\n const recoveredAddress = await signer.verifyTypedData({\n address: eip3009Payload.authorization.from,\n ...permitTypedData,\n signature: eip3009Payload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = eip3009Payload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = eip3009Payload.authorization.from;\n const bytecode = await signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer,\n };\n }\n }\n\n // Verify payment recipient matches\n if (getAddress(eip3009Payload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_recipient_mismatch\",\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(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer,\n };\n }\n\n // Check balance\n try {\n const balance = (await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [eip3009Payload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(eip3009Payload.authorization.value) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n}\n\n/**\n * Settles an EIP-3009 payment by executing transferWithAuthorization.\n *\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param eip3009Payload - The EIP-3009 specific payload\n * @param config - Facilitator configuration\n * @returns Promise resolving to settlement response\n */\nexport async function settleEIP3009(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n eip3009Payload: ExactEIP3009Payload,\n config: EIP3009FacilitatorConfig,\n): Promise<SettleResponse> {\n const payer = eip3009Payload.authorization.from;\n\n // Re-verify before settling\n const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload);\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(eip3009Payload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n config.deployERC4337WithEIP6492 &&\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const bytecode = await signer.getCode({ address: payer });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet not deployed - attempt deployment\n const deployTx = await signer.sendTransaction({\n to: factoryAddress as Hex,\n data: factoryCalldata as Hex,\n });\n\n // Wait for deployment transaction\n await signer.waitForTransactionReceipt({ hash: deployTx });\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(eip3009Payload.authorization.from),\n getAddress(eip3009Payload.authorization.to),\n BigInt(eip3009Payload.authorization.value),\n BigInt(eip3009Payload.authorization.validAfter),\n BigInt(eip3009Payload.authorization.validBefore),\n eip3009Payload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n tx = await signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(eip3009Payload.authorization.from),\n getAddress(eip3009Payload.authorization.to),\n BigInt(eip3009Payload.authorization.value),\n BigInt(eip3009Payload.authorization.validAfter),\n BigInt(eip3009Payload.authorization.validBefore),\n eip3009Payload.authorization.nonce,\n signature,\n ],\n });\n }\n\n // Wait for transaction confirmation\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: \"invalid_transaction_state\",\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n } catch {\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport {\n extractEip2612GasSponsoringInfo,\n validateEip2612GasSponsoringInfo,\n} from \"@x402/extensions\";\nimport type { Eip2612GasSponsoringInfo } from \"@x402/extensions\";\nimport { getAddress } from \"viem\";\nimport {\n eip3009ABI,\n PERMIT2_ADDRESS,\n permit2WitnessTypes,\n x402ExactPermit2ProxyABI,\n x402ExactPermit2ProxyAddress,\n} from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\n\n// ERC20 allowance ABI for checking Permit2 approval\nconst 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/**\n * Verifies a Permit2 payment payload.\n *\n * @param signer - The facilitator signer for contract reads\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param permit2Payload - The Permit2 specific payload\n * @returns Promise resolving to verification response\n */\nexport async function verifyPermit2(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n permit2Payload: ExactPermit2Payload,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n // Verify scheme matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer,\n };\n }\n\n // Verify network matches\n if (payload.accepted.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: \"network_mismatch\",\n payer,\n };\n }\n\n const chainId = parseInt(requirements.network.split(\":\")[1]);\n const tokenAddress = getAddress(requirements.asset);\n\n // Verify spender is the x402ExactPermit2Proxy\n if (\n getAddress(permit2Payload.permit2Authorization.spender) !==\n getAddress(x402ExactPermit2ProxyAddress)\n ) {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_spender\",\n payer,\n };\n }\n\n // Verify witness.to matches payTo\n if (\n getAddress(permit2Payload.permit2Authorization.witness.to) !== getAddress(requirements.payTo)\n ) {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_recipient_mismatch\",\n payer,\n };\n }\n\n // Verify deadline not expired (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: \"permit2_deadline_expired\",\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: \"permit2_not_yet_valid\",\n payer,\n };\n }\n\n // Verify amount is sufficient\n if (BigInt(permit2Payload.permit2Authorization.permitted.amount) < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"permit2_insufficient_amount\",\n payer,\n };\n }\n\n // Verify token matches\n if (getAddress(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: \"permit2_token_mismatch\",\n payer,\n };\n }\n\n // Build typed data for Permit2 signature verification\n const permit2TypedData = {\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\" as const,\n domain: {\n name: \"Permit2\",\n chainId,\n verifyingContract: PERMIT2_ADDRESS,\n },\n message: {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Payload.permit2Authorization.spender),\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n extra: permit2Payload.permit2Authorization.witness.extra,\n },\n },\n };\n\n // Verify signature\n try {\n const isValid = await signer.verifyTypedData({\n address: payer,\n ...permit2TypedData,\n signature: permit2Payload.signature,\n });\n\n if (!isValid) {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_signature\",\n payer,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: \"invalid_permit2_signature\",\n payer,\n };\n }\n\n // Check Permit2 allowance\n try {\n const allowance = (await signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceABI,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance < BigInt(requirements.amount)) {\n // Allowance insufficient - check for EIP-2612 gas sponsoring extension\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n // Validate the EIP-2612 extension data\n const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!validationResult.isValid) {\n return {\n isValid: false,\n invalidReason: validationResult.invalidReason!,\n payer,\n };\n }\n // EIP-2612 extension is valid, allowance will be set during settlement\n } else {\n return {\n isValid: false,\n invalidReason: \"permit2_allowance_required\",\n payer,\n };\n }\n }\n } catch {\n // If we can't check allowance, check if EIP-2612 extension is present\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const validationResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!validationResult.isValid) {\n return {\n isValid: false,\n invalidReason: validationResult.invalidReason!,\n payer,\n };\n }\n // EIP-2612 extension is valid, allowance will be set during settlement\n }\n }\n\n // Check balance\n try {\n const balance = (await signer.readContract({\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n })) as bigint;\n\n if (balance < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirements.amount} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n}\n\n/**\n * Settles a Permit2 payment by calling the x402ExactPermit2Proxy.\n *\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param permit2Payload - The Permit2 specific payload\n * @returns Promise resolving to settlement response\n */\nexport async function settlePermit2(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n permit2Payload: ExactPermit2Payload,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n // Re-verify before settling\n const valid = await verifyPermit2(signer, payload, requirements, permit2Payload);\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer,\n };\n }\n\n try {\n // Check if EIP-2612 gas sponsoring extension is present\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n\n let tx: `0x${string}`;\n\n if (eip2612Info) {\n // Use settleWithPermit - includes the EIP-2612 permit\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n\n tx = await signer.writeContract({\n address: x402ExactPermit2ProxyAddress,\n abi: x402ExactPermit2ProxyABI,\n functionName: \"settleWithPermit\",\n args: [\n {\n value: BigInt(eip2612Info.amount),\n deadline: BigInt(eip2612Info.deadline),\n r,\n s,\n v,\n },\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n getAddress(payer),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n extra: permit2Payload.permit2Authorization.witness.extra as `0x${string}`,\n },\n permit2Payload.signature,\n ],\n });\n } else {\n // Standard settle - no EIP-2612 extension\n tx = await signer.writeContract({\n address: x402ExactPermit2ProxyAddress,\n abi: x402ExactPermit2ProxyABI,\n functionName: \"settle\",\n args: [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n getAddress(payer),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n extra: permit2Payload.permit2Authorization.witness.extra as `0x${string}`,\n },\n permit2Payload.signature,\n ],\n });\n }\n\n // Wait for transaction confirmation\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: \"invalid_transaction_state\",\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n } catch (error) {\n // Extract meaningful error message from the contract revert\n let errorReason = \"transaction_failed\";\n if (error instanceof Error) {\n // Check for common contract revert patterns\n const message = error.message;\n if (message.includes(\"AmountExceedsPermitted\")) {\n errorReason = \"permit2_amount_exceeds_permitted\";\n } else if (message.includes(\"InvalidDestination\")) {\n errorReason = \"permit2_invalid_destination\";\n } else if (message.includes(\"InvalidOwner\")) {\n errorReason = \"permit2_invalid_owner\";\n } else if (message.includes(\"PaymentTooEarly\")) {\n errorReason = \"permit2_payment_too_early\";\n } else if (message.includes(\"InvalidSignature\") || message.includes(\"SignatureExpired\")) {\n errorReason = \"permit2_invalid_signature\";\n } else if (message.includes(\"InvalidNonce\")) {\n errorReason = \"permit2_invalid_nonce\";\n } else {\n // Include error message for debugging (longer for better visibility)\n errorReason = `transaction_failed: ${message.slice(0, 500)}`;\n }\n }\n return {\n success: false,\n errorReason,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n}\n\n/**\n * Validates EIP-2612 permit extension data for a payment.\n *\n * @param info - The EIP-2612 gas sponsoring info\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result\n */\nfunction validateEip2612PermitForPayment(\n info: Eip2612GasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): { isValid: boolean; invalidReason?: string } {\n // Validate format\n if (!validateEip2612GasSponsoringInfo(info)) {\n return { isValid: false, invalidReason: \"invalid_eip2612_extension_format\" };\n }\n\n // Verify from matches payer\n if (getAddress(info.from as `0x${string}`) !== getAddress(payer)) {\n return { isValid: false, invalidReason: \"eip2612_from_mismatch\" };\n }\n\n // Verify asset matches token\n if (getAddress(info.asset as `0x${string}`) !== tokenAddress) {\n return { isValid: false, invalidReason: \"eip2612_asset_mismatch\" };\n }\n\n // Verify spender is Permit2\n if (getAddress(info.spender as `0x${string}`) !== getAddress(PERMIT2_ADDRESS)) {\n return { isValid: false, invalidReason: \"eip2612_spender_not_permit2\" };\n }\n\n // Verify deadline not expired (with 6 second buffer, consistent with Permit2 deadline check)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(info.deadline) < BigInt(now + 6)) {\n return { isValid: false, invalidReason: \"eip2612_deadline_expired\" };\n }\n\n return { isValid: true };\n}\n\n/**\n * Splits a 65-byte EIP-2612 signature into v, r, s components.\n *\n * @param signature - The hex-encoded 65-byte signature\n * @returns Object with v (uint8), r (bytes32), s (bytes32)\n */\nfunction splitEip2612Signature(signature: string): {\n v: number;\n r: `0x${string}`;\n s: `0x${string}`;\n} {\n const sig = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n\n if (sig.length !== 130) {\n throw new Error(\n `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`,\n );\n }\n\n const r = `0x${sig.slice(0, 64)}` as `0x${string}`;\n const s = `0x${sig.slice(64, 128)}` as `0x${string}`;\n const v = parseInt(sig.slice(128, 130), 16);\n\n return { v, r, s };\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEvmPayloadV2, ExactEIP3009Payload, isPermit2Payload } from \"../../types\";\nimport { verifyEIP3009, settleEIP3009 } from \"./eip3009\";\nimport { verifyPermit2, settlePermit2 } from \"./permit2\";\n\nexport interface ExactEvmSchemeConfig {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme.\n * Routes between EIP-3009 and Permit2 based on payload type.\n */\nexport class ExactEvmScheme implements SchemeNetworkFacilitator {\n readonly scheme = \"exact\";\n readonly caipFamily = \"eip155:*\";\n private readonly config: Required<ExactEvmSchemeConfig>;\n\n /**\n * Creates a new ExactEvmFacilitator 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?: ExactEvmSchemeConfig,\n ) {\n this.config = {\n deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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.\n * Routes to the appropriate verification logic based on payload type.\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 const rawPayload = payload.payload as ExactEvmPayloadV2;\n\n // Route based on payload type\n if (isPermit2Payload(rawPayload)) {\n return verifyPermit2(this.signer, payload, requirements, rawPayload);\n }\n\n // Type-narrowed to EIP-3009 payload\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return verifyEIP3009(this.signer, payload, requirements, eip3009Payload);\n }\n\n /**\n * Settles a payment by executing the transfer.\n * Routes to the appropriate settlement logic based on payload type.\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<SettleResponse> {\n const rawPayload = payload.payload as ExactEvmPayloadV2;\n\n // Route based on payload type\n if (isPermit2Payload(rawPayload)) {\n return settlePermit2(this.signer, payload, requirements, rawPayload);\n }\n\n // Type-narrowed to EIP-3009 payload\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config);\n }\n}\n","import { x402Facilitator } from \"@x402/core/facilitator\";\nimport { Network } from \"@x402/core/types\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEvmScheme } from \"./scheme\";\nimport { ExactEvmSchemeV1 } from \"../v1/facilitator/scheme\";\nimport { NETWORKS } from \"../../v1\";\n\n/**\n * Configuration options for registering EVM schemes to an x402Facilitator\n */\nexport interface EvmFacilitatorConfig {\n /**\n * The EVM signer for facilitator operations (verify and settle)\n */\n signer: FacilitatorEvmSigner;\n\n /**\n * Networks to register (single network or array of networks)\n * Examples: \"eip155:84532\", [\"eip155:84532\", \"eip155:1\"]\n */\n networks: Network | Network[];\n\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: boolean;\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Facilitator instance.\n *\n * This function registers:\n * - V2: Specified networks with ExactEvmScheme\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param facilitator - The x402Facilitator instance to register schemes to\n * @param config - Configuration for EVM facilitator registration\n * @returns The facilitator instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/facilitator/register\";\n * import { x402Facilitator } from \"@x402/core/facilitator\";\n * import { createPublicClient, createWalletClient } from \"viem\";\n *\n * const facilitator = new x402Facilitator();\n *\n * // Single network\n * registerExactEvmScheme(facilitator, {\n * signer: combinedClient,\n * networks: \"eip155:84532\" // Base Sepolia\n * });\n *\n * // Multiple networks (will auto-derive eip155:* pattern)\n * registerExactEvmScheme(facilitator, {\n * signer: combinedClient,\n * networks: [\"eip155:84532\", \"eip155:1\"] // Base Sepolia and Mainnet\n * });\n * ```\n */\nexport function registerExactEvmScheme(\n facilitator: x402Facilitator,\n config: EvmFacilitatorConfig,\n): x402Facilitator {\n // Register V2 scheme with specified networks\n facilitator.register(\n config.networks,\n new ExactEvmScheme(config.signer, {\n deployERC4337WithEIP6492: config.deployERC4337WithEIP6492,\n }),\n );\n\n // Register all V1 networks\n facilitator.registerV1(\n NETWORKS as Network[],\n new ExactEvmSchemeV1(config.signer, {\n deployERC4337WithEIP6492: config.deployERC4337WithEIP6492,\n }),\n );\n\n return facilitator;\n}\n"],"mappings":"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","names":["getAddress","getAddress"]} |
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayload, Network } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from '../../../signer-5OVDxViv.mjs'; | ||
| import { C as ClientEvmSigner } from '../../../signer-3KGwtdNT.mjs'; | ||
@@ -4,0 +4,0 @@ /** |
| import { | ||
| ExactEvmSchemeV1 | ||
| } from "../../../chunk-RPL6OFJL.mjs"; | ||
| } from "../../../chunk-GSU4DHTC.mjs"; | ||
| export { | ||
@@ -5,0 +5,0 @@ ExactEvmSchemeV1 |
| import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse } from '@x402/core/types'; | ||
| import { F as FacilitatorEvmSigner } from '../../../signer-5OVDxViv.mjs'; | ||
| import { F as FacilitatorEvmSigner } from '../../../signer-3KGwtdNT.mjs'; | ||
@@ -4,0 +4,0 @@ interface ExactEvmSchemeV1Config { |
| import { | ||
| ExactEvmSchemeV12 as ExactEvmSchemeV1 | ||
| } from "../../../chunk-RPL6OFJL.mjs"; | ||
| } from "../../../chunk-GSU4DHTC.mjs"; | ||
| export { | ||
@@ -5,0 +5,0 @@ ExactEvmSchemeV1 |
@@ -1,3 +0,3 @@ | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from './permit2-BsAoJiWD.mjs'; | ||
| export { C as ClientEvmSigner, F as FacilitatorEvmSigner, t as toClientEvmSigner, a as toFacilitatorEvmSigner } from './signer-5OVDxViv.mjs'; | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from './permit2-C2FkNEHT.mjs'; | ||
| export { C as ClientEvmSigner, F as FacilitatorEvmSigner, t as toClientEvmSigner, a as toFacilitatorEvmSigner } from './signer-3KGwtdNT.mjs'; | ||
| import '@x402/core/types'; | ||
@@ -4,0 +4,0 @@ |
+14
-4
@@ -6,3 +6,3 @@ import { | ||
| getPermit2AllowanceReadParams | ||
| } from "./chunk-E2YMUI3X.mjs"; | ||
| } from "./chunk-CJHYX7BQ.mjs"; | ||
| import { | ||
@@ -20,7 +20,17 @@ isEIP3009Payload, | ||
| x402UptoPermit2ProxyAddress | ||
| } from "./chunk-RPL6OFJL.mjs"; | ||
| } from "./chunk-GSU4DHTC.mjs"; | ||
| // src/signer.ts | ||
| function toClientEvmSigner(signer) { | ||
| return signer; | ||
| function toClientEvmSigner(signer, publicClient) { | ||
| const readContract = signer.readContract ?? publicClient?.readContract.bind(publicClient); | ||
| if (!readContract) { | ||
| throw new Error( | ||
| "toClientEvmSigner requires either a signer with readContract or a publicClient. Use createWalletClient(...).extend(publicActions) or pass a publicClient." | ||
| ); | ||
| } | ||
| return { | ||
| address: signer.address, | ||
| signTypedData: (msg) => signer.signTypedData(msg), | ||
| readContract | ||
| }; | ||
| } | ||
@@ -27,0 +37,0 @@ function toFacilitatorEvmSigner(client) { |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/signer.ts"],"sourcesContent":["/**\n * ClientEvmSigner - Used by x402 clients to sign payment authorizations\n * This is typically a LocalAccount or wallet that holds private keys\n * and can sign EIP-712 typed data for payment authorizations\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\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 }): Promise<`0x${string}`>;\n sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>;\n waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{ status: string }>;\n getCode(args: { address: `0x${string}` }): Promise<`0x${string}` | undefined>;\n};\n\n/**\n * Converts a signer to a ClientEvmSigner\n *\n * @param signer - The signer to convert to a ClientEvmSigner\n * @returns The converted signer\n */\nexport function toClientEvmSigner(signer: ClientEvmSigner): ClientEvmSigner {\n return signer;\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":";;;;;;;;;;;;;;;;;;;;;AA4DO,SAAS,kBAAkB,QAA0C;AAC1E,SAAO;AACT;AASO,SAAS,uBACd,QACsB;AACtB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,cAAc,MAAM,CAAC,OAAO,OAAO;AAAA,EACrC;AACF;","names":[]} | ||
| {"version":3,"sources":["../../src/signer.ts"],"sourcesContent":["/**\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 readContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\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 }): Promise<`0x${string}`>;\n sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>;\n waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{ status: string }>;\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 `readContract` (required if signer lacks it)\n * @param publicClient.readContract - The readContract method from the public client\n * @returns A complete ClientEvmSigner\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 },\n): ClientEvmSigner {\n const readContract = signer.readContract ?? publicClient?.readContract.bind(publicClient);\n\n if (!readContract) {\n throw new Error(\n \"toClientEvmSigner requires either a signer with readContract or a publicClient. \" +\n \"Use createWalletClient(...).extend(publicActions) or pass a publicClient.\",\n );\n }\n\n return {\n address: signer.address,\n signTypedData: msg => signer.signTypedData(msg),\n readContract,\n };\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":";;;;;;;;;;;;;;;;;;;;;AAgGO,SAAS,kBACd,QAGA,cAQiB;AACjB,QAAM,eAAe,OAAO,gBAAgB,cAAc,aAAa,KAAK,YAAY;AAExF,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,OAAO;AAAA,IAChB,eAAe,SAAO,OAAO,cAAc,GAAG;AAAA,IAC9C;AAAA,EACF;AACF;AASO,SAAS,uBACd,QACsB;AACtB,SAAO;AAAA,IACL,GAAG;AAAA,IACH,cAAc,MAAM,CAAC,OAAO,OAAO;AAAA,EACrC;AACF;","names":[]} |
| export { ExactEvmSchemeV1 } from '../exact/v1/client/index.mjs'; | ||
| import '@x402/core/types'; | ||
| import '../signer-5OVDxViv.mjs'; | ||
| import '../signer-3KGwtdNT.mjs'; | ||
@@ -5,0 +5,0 @@ declare const EVM_NETWORK_CHAIN_ID_MAP: { |
@@ -5,3 +5,3 @@ import { | ||
| NETWORKS | ||
| } from "../chunk-RPL6OFJL.mjs"; | ||
| } from "../chunk-GSU4DHTC.mjs"; | ||
| export { | ||
@@ -8,0 +8,0 @@ EVM_NETWORK_CHAIN_ID_MAP, |
+3
-2
| { | ||
| "name": "@x402/evm", | ||
| "version": "2.3.1", | ||
| "version": "2.4.0", | ||
| "main": "./dist/cjs/index.js", | ||
@@ -38,3 +38,4 @@ "module": "./dist/esm/index.js", | ||
| "zod": "^3.24.2", | ||
| "@x402/core": "~2.3.1" | ||
| "@x402/extensions": "~2.4.0", | ||
| "@x402/core": "~2.4.0" | ||
| }, | ||
@@ -41,0 +42,0 @@ "exports": { |
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayloadResult } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from './signer-5OVDxViv.js'; | ||
| /** | ||
| * EVM client implementation for the Exact payment scheme. | ||
| * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows. | ||
| * | ||
| * Routes to the appropriate authorization method based on | ||
| * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009 | ||
| * for backward compatibility with older facilitators. | ||
| */ | ||
| declare class ExactEvmScheme implements SchemeNetworkClient { | ||
| private readonly signer; | ||
| readonly scheme = "exact"; | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| */ | ||
| constructor(signer: ClientEvmSigner); | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload result | ||
| */ | ||
| createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements): Promise<PaymentPayloadResult>; | ||
| } | ||
| /** | ||
| * ERC20 allowance ABI for checking approval status. | ||
| */ | ||
| declare const erc20AllowanceAbi: readonly [{ | ||
| readonly type: "function"; | ||
| readonly name: "allowance"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "spender"; | ||
| readonly type: "address"; | ||
| }]; | ||
| readonly outputs: readonly [{ | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }]; | ||
| /** | ||
| * Creates transaction data to approve Permit2 to spend tokens. | ||
| * The user sends this transaction (paying gas) before using Permit2 flow. | ||
| * | ||
| * @param tokenAddress - The ERC20 token contract address | ||
| * @returns Transaction data to send for approval | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const tx = createPermit2ApprovalTx("0x..."); | ||
| * await walletClient.sendTransaction({ | ||
| * to: tx.to, | ||
| * data: tx.data, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createPermit2ApprovalTx(tokenAddress: `0x${string}`): { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }; | ||
| /** | ||
| * Parameters for checking Permit2 allowance. | ||
| * Application provides these to check if approval is needed. | ||
| */ | ||
| interface Permit2AllowanceParams { | ||
| tokenAddress: `0x${string}`; | ||
| ownerAddress: `0x${string}`; | ||
| } | ||
| /** | ||
| * Returns contract read parameters for checking Permit2 allowance. | ||
| * Use with a public client to check if the user has approved Permit2. | ||
| * | ||
| * @param params - The allowance check parameters | ||
| * @returns Contract read parameters for checking allowance | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const readParams = getPermit2AllowanceReadParams({ | ||
| * tokenAddress: "0x...", | ||
| * ownerAddress: "0x...", | ||
| * }); | ||
| * | ||
| * const allowance = await publicClient.readContract(readParams); | ||
| * const needsApproval = allowance < requiredAmount; | ||
| * ``` | ||
| */ | ||
| declare function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): { | ||
| address: `0x${string}`; | ||
| abi: typeof erc20AllowanceAbi; | ||
| functionName: "allowance"; | ||
| args: [`0x${string}`, `0x${string}`]; | ||
| }; | ||
| export { ExactEvmScheme as E, type Permit2AllowanceParams as P, createPermit2ApprovalTx as c, erc20AllowanceAbi as e, getPermit2AllowanceReadParams as g }; |
| /** | ||
| * ClientEvmSigner - Used by x402 clients to sign payment authorizations | ||
| * This is typically a LocalAccount or wallet that holds private keys | ||
| * and can sign EIP-712 typed data for payment authorizations | ||
| */ | ||
| type ClientEvmSigner = { | ||
| readonly address: `0x${string}`; | ||
| signTypedData(message: { | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| }): Promise<`0x${string}`>; | ||
| }; | ||
| /** | ||
| * FacilitatorEvmSigner - Used by x402 facilitators to verify and settle payments | ||
| * This is typically a viem PublicClient + WalletClient combination that can | ||
| * read contract state, verify signatures, write transactions, and wait for receipts | ||
| * | ||
| * Supports multiple addresses for load balancing, key rotation, and high availability | ||
| */ | ||
| type FacilitatorEvmSigner = { | ||
| /** | ||
| * Get all addresses this facilitator can use for signing | ||
| * Enables dynamic address selection for load balancing and key rotation | ||
| */ | ||
| getAddresses(): readonly `0x${string}`[]; | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| verifyTypedData(args: { | ||
| address: `0x${string}`; | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| signature: `0x${string}`; | ||
| }): Promise<boolean>; | ||
| writeContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args: readonly unknown[]; | ||
| }): Promise<`0x${string}`>; | ||
| sendTransaction(args: { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }): Promise<`0x${string}`>; | ||
| waitForTransactionReceipt(args: { | ||
| hash: `0x${string}`; | ||
| }): Promise<{ | ||
| status: string; | ||
| }>; | ||
| getCode(args: { | ||
| address: `0x${string}`; | ||
| }): Promise<`0x${string}` | undefined>; | ||
| }; | ||
| /** | ||
| * Converts a signer to a ClientEvmSigner | ||
| * | ||
| * @param signer - The signer to convert to a ClientEvmSigner | ||
| * @returns The converted signer | ||
| */ | ||
| declare function toClientEvmSigner(signer: ClientEvmSigner): ClientEvmSigner; | ||
| /** | ||
| * Converts a viem client with single address to a FacilitatorEvmSigner | ||
| * Wraps the single address in a getAddresses() function for compatibility | ||
| * | ||
| * @param client - The client to convert (must have 'address' property) | ||
| * @returns FacilitatorEvmSigner with getAddresses() support | ||
| */ | ||
| declare function toFacilitatorEvmSigner(client: Omit<FacilitatorEvmSigner, "getAddresses"> & { | ||
| address: `0x${string}`; | ||
| }): FacilitatorEvmSigner; | ||
| export { type ClientEvmSigner as C, type FacilitatorEvmSigner as F, toFacilitatorEvmSigner as a, toClientEvmSigner as t }; |
| import { | ||
| ExactEvmSchemeV1, | ||
| NETWORKS, | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| createNonce, | ||
| createPermit2Nonce, | ||
| permit2WitnessTypes, | ||
| x402ExactPermit2ProxyAddress | ||
| } from "./chunk-RPL6OFJL.mjs"; | ||
| // src/exact/client/eip3009.ts | ||
| import { getAddress } from "viem"; | ||
| async function createEIP3009Payload(signer, x402Version, paymentRequirements) { | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: signer.address, | ||
| to: getAddress(paymentRequirements.payTo), | ||
| value: paymentRequirements.amount, | ||
| validAfter: (now - 600).toString(), | ||
| validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements); | ||
| const payload = { | ||
| authorization, | ||
| signature | ||
| }; | ||
| return { | ||
| x402Version, | ||
| payload | ||
| }; | ||
| } | ||
| async function signEIP3009Authorization(signer, authorization, requirements) { | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| throw new Error( | ||
| `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}` | ||
| ); | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const domain = { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: getAddress(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: getAddress(authorization.from), | ||
| to: getAddress(authorization.to), | ||
| value: BigInt(authorization.value), | ||
| validAfter: BigInt(authorization.validAfter), | ||
| validBefore: BigInt(authorization.validBefore), | ||
| nonce: authorization.nonce | ||
| }; | ||
| return await signer.signTypedData({ | ||
| domain, | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| message | ||
| }); | ||
| } | ||
| // src/exact/client/permit2.ts | ||
| import { encodeFunctionData, getAddress as getAddress2 } from "viem"; | ||
| var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); | ||
| async function createPermit2Payload(signer, x402Version, paymentRequirements) { | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const nonce = createPermit2Nonce(); | ||
| const validAfter = (now - 600).toString(); | ||
| const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString(); | ||
| const permit2Authorization = { | ||
| from: signer.address, | ||
| permitted: { | ||
| token: getAddress2(paymentRequirements.asset), | ||
| amount: paymentRequirements.amount | ||
| }, | ||
| spender: x402ExactPermit2ProxyAddress, | ||
| nonce, | ||
| deadline, | ||
| witness: { | ||
| to: getAddress2(paymentRequirements.payTo), | ||
| validAfter, | ||
| extra: "0x" | ||
| } | ||
| }; | ||
| const signature = await signPermit2Authorization( | ||
| signer, | ||
| permit2Authorization, | ||
| paymentRequirements | ||
| ); | ||
| const payload = { | ||
| signature, | ||
| permit2Authorization | ||
| }; | ||
| return { | ||
| x402Version, | ||
| payload | ||
| }; | ||
| } | ||
| async function signPermit2Authorization(signer, permit2Authorization, requirements) { | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const domain = { | ||
| name: "Permit2", | ||
| chainId, | ||
| verifyingContract: PERMIT2_ADDRESS | ||
| }; | ||
| const message = { | ||
| permitted: { | ||
| token: getAddress2(permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Authorization.permitted.amount) | ||
| }, | ||
| spender: getAddress2(permit2Authorization.spender), | ||
| nonce: BigInt(permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Authorization.deadline), | ||
| witness: { | ||
| to: getAddress2(permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Authorization.witness.validAfter), | ||
| extra: permit2Authorization.witness.extra | ||
| } | ||
| }; | ||
| return await signer.signTypedData({ | ||
| domain, | ||
| types: permit2WitnessTypes, | ||
| primaryType: "PermitWitnessTransferFrom", | ||
| message | ||
| }); | ||
| } | ||
| var erc20ApproveAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "approve", | ||
| inputs: [ | ||
| { name: "spender", type: "address" }, | ||
| { name: "amount", type: "uint256" } | ||
| ], | ||
| outputs: [{ type: "bool" }], | ||
| stateMutability: "nonpayable" | ||
| } | ||
| ]; | ||
| var erc20AllowanceAbi = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| function createPermit2ApprovalTx(tokenAddress) { | ||
| const data = encodeFunctionData({ | ||
| abi: erc20ApproveAbi, | ||
| functionName: "approve", | ||
| args: [PERMIT2_ADDRESS, MAX_UINT256] | ||
| }); | ||
| return { | ||
| to: getAddress2(tokenAddress), | ||
| data | ||
| }; | ||
| } | ||
| function getPermit2AllowanceReadParams(params) { | ||
| return { | ||
| address: getAddress2(params.tokenAddress), | ||
| abi: erc20AllowanceAbi, | ||
| functionName: "allowance", | ||
| args: [getAddress2(params.ownerAddress), PERMIT2_ADDRESS] | ||
| }; | ||
| } | ||
| // src/exact/client/scheme.ts | ||
| var ExactEvmScheme = class { | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| */ | ||
| constructor(signer) { | ||
| this.signer = signer; | ||
| this.scheme = "exact"; | ||
| } | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload result | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009"; | ||
| if (assetTransferMethod === "permit2") { | ||
| return createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| return createEIP3009Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| }; | ||
| // src/exact/client/register.ts | ||
| function registerExactEvmScheme(client, config) { | ||
| if (config.networks && config.networks.length > 0) { | ||
| config.networks.forEach((network) => { | ||
| client.register(network, new ExactEvmScheme(config.signer)); | ||
| }); | ||
| } else { | ||
| client.register("eip155:*", new ExactEvmScheme(config.signer)); | ||
| } | ||
| NETWORKS.forEach((network) => { | ||
| client.registerV1(network, new ExactEvmSchemeV1(config.signer)); | ||
| }); | ||
| if (config.policies) { | ||
| config.policies.forEach((policy) => { | ||
| client.registerPolicy(policy); | ||
| }); | ||
| } | ||
| return client; | ||
| } | ||
| export { | ||
| erc20AllowanceAbi, | ||
| createPermit2ApprovalTx, | ||
| getPermit2AllowanceReadParams, | ||
| ExactEvmScheme, | ||
| registerExactEvmScheme | ||
| }; | ||
| //# sourceMappingURL=chunk-E2YMUI3X.mjs.map |
| {"version":3,"sources":["../../src/exact/client/eip3009.ts","../../src/exact/client/permit2.ts","../../src/exact/client/scheme.ts","../../src/exact/client/register.ts"],"sourcesContent":["import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport { createNonce } from \"../../utils\";\n\n/**\n * Creates an EIP-3009 (transferWithAuthorization) payload.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createEIP3009Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEIP3009Payload[\"authorization\"] = {\n from: signer.address,\n to: getAddress(paymentRequirements.payTo),\n value: paymentRequirements.amount,\n validAfter: (now - 600).toString(),\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n const signature = await signEIP3009Authorization(signer, authorization, paymentRequirements);\n\n const payload: ExactEIP3009Payload = {\n authorization,\n signature,\n };\n\n return {\n x402Version,\n payload,\n };\n}\n\n/**\n * Sign the EIP-3009 authorization using EIP-712.\n *\n * @param signer - The EVM signer\n * @param authorization - The authorization to sign\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\nasync function signEIP3009Authorization(\n signer: ClientEvmSigner,\n authorization: ExactEIP3009Payload[\"authorization\"],\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = parseInt(requirements.network.split(\":\")[1]);\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 signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n}\n","import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport {\n permit2WitnessTypes,\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\nimport { createPermit2Nonce } from \"../../utils\";\n\n/** Maximum uint256 value for unlimited approval. */\nconst MAX_UINT256 = BigInt(\"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\");\n\n/**\n * Creates a Permit2 payload using the x402Permit2Proxy witness pattern.\n * The spender is set to x402Permit2Proxy, which enforces that funds\n * can only be sent to the witness.to address.\n *\n * @param signer - The EVM signer for client operations\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2Payload(\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n\n // Lower time bound - allow some clock skew\n const validAfter = (now - 600).toString();\n // Upper time bound is enforced by Permit2's deadline field\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n const permit2Authorization: ExactPermit2Payload[\"permit2Authorization\"] = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: x402ExactPermit2ProxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n validAfter,\n extra: \"0x\",\n },\n };\n\n const signature = await signPermit2Authorization(\n signer,\n permit2Authorization,\n paymentRequirements,\n );\n\n const payload: ExactPermit2Payload = {\n signature,\n permit2Authorization,\n };\n\n return {\n x402Version,\n payload,\n };\n}\n\n/**\n * Sign the Permit2 authorization using EIP-712 with witness data.\n * The signature authorizes the x402Permit2Proxy to transfer tokens on behalf of the signer.\n *\n * @param signer - The EVM signer\n * @param permit2Authorization - The Permit2 authorization parameters\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\nasync function signPermit2Authorization(\n signer: ClientEvmSigner,\n permit2Authorization: ExactPermit2Payload[\"permit2Authorization\"],\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = parseInt(requirements.network.split(\":\")[1]);\n\n const domain = {\n name: \"Permit2\",\n chainId,\n verifyingContract: PERMIT2_ADDRESS,\n };\n\n const message = {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n extra: permit2Authorization.witness.extra,\n },\n };\n\n return await signer.signTypedData({\n domain,\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message,\n });\n}\n\n/**\n * ERC20 approve ABI for encoding approval transactions.\n */\nconst 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/**\n * ERC20 allowance ABI for checking approval status.\n */\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/**\n * Creates transaction data to approve Permit2 to spend tokens.\n * The user sends this transaction (paying gas) before using Permit2 flow.\n *\n * @param tokenAddress - The ERC20 token contract address\n * @returns Transaction data to send for approval\n *\n * @example\n * ```typescript\n * const tx = createPermit2ApprovalTx(\"0x...\");\n * await walletClient.sendTransaction({\n * to: tx.to,\n * data: tx.data,\n * });\n * ```\n */\nexport function createPermit2ApprovalTx(tokenAddress: `0x${string}`): {\n to: `0x${string}`;\n data: `0x${string}`;\n} {\n const data = encodeFunctionData({\n abi: erc20ApproveAbi,\n functionName: \"approve\",\n args: [PERMIT2_ADDRESS, MAX_UINT256],\n });\n\n return {\n to: getAddress(tokenAddress),\n data,\n };\n}\n\n/**\n * Parameters for checking Permit2 allowance.\n * Application provides these to check if approval is needed.\n */\nexport interface Permit2AllowanceParams {\n tokenAddress: `0x${string}`;\n ownerAddress: `0x${string}`;\n}\n\n/**\n * Returns contract read parameters for checking Permit2 allowance.\n * Use with a public client to check if the user has approved Permit2.\n *\n * @param params - The allowance check parameters\n * @returns Contract read parameters for checking allowance\n *\n * @example\n * ```typescript\n * const readParams = getPermit2AllowanceReadParams({\n * tokenAddress: \"0x...\",\n * ownerAddress: \"0x...\",\n * });\n *\n * const allowance = await publicClient.readContract(readParams);\n * const needsApproval = allowance < requiredAmount;\n * ```\n */\nexport function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): {\n address: `0x${string}`;\n abi: typeof erc20AllowanceAbi;\n functionName: \"allowance\";\n args: [`0x${string}`, `0x${string}`];\n} {\n return {\n address: getAddress(params.tokenAddress),\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [getAddress(params.ownerAddress), PERMIT2_ADDRESS],\n };\n}\n","import { PaymentRequirements, SchemeNetworkClient, PaymentPayloadResult } from \"@x402/core/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { AssetTransferMethod } from \"../../types\";\nimport { createEIP3009Payload } from \"./eip3009\";\nimport { createPermit2Payload } from \"./permit2\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows.\n *\n * Routes to the appropriate authorization method based on\n * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009\n * for backward compatibility with older facilitators.\n */\nexport class ExactEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClient 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.\n * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n ): Promise<PaymentPayloadResult> {\n const assetTransferMethod =\n (paymentRequirements.extra?.assetTransferMethod as AssetTransferMethod) ?? \"eip3009\";\n\n if (assetTransferMethod === \"permit2\") {\n return createPermit2Payload(this.signer, x402Version, paymentRequirements);\n }\n\n return createEIP3009Payload(this.signer, x402Version, paymentRequirements);\n }\n}\n","import { x402Client, SelectPaymentRequirements, PaymentPolicy } from \"@x402/core/client\";\nimport { Network } from \"@x402/core/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmScheme } from \"./scheme\";\nimport { ExactEvmSchemeV1 } from \"../v1/client/scheme\";\nimport { NETWORKS } from \"../../v1\";\n\n/**\n * Configuration options for registering EVM schemes to an x402Client\n */\nexport interface EvmClientConfig {\n /**\n * The EVM signer to use for creating payment payloads\n */\n signer: ClientEvmSigner;\n\n /**\n * Optional payment requirements selector function\n * If not provided, uses the default selector (first available option)\n */\n paymentRequirementsSelector?: SelectPaymentRequirements;\n\n /**\n * Optional policies to apply to the client\n */\n policies?: PaymentPolicy[];\n\n /**\n * Optional specific networks to register\n * If not provided, registers wildcard support (eip155:*)\n */\n networks?: Network[];\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Client instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param client - The x402Client instance to register schemes to\n * @param config - Configuration for EVM client registration\n * @returns The client instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/client/register\";\n * import { x402Client } from \"@x402/core/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const client = new x402Client();\n * registerExactEvmScheme(client, { signer: account });\n * ```\n */\nexport function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client {\n // Register V2 scheme\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n client.register(network, new ExactEvmScheme(config.signer));\n });\n } else {\n // Register wildcard for all EVM chains\n client.register(\"eip155:*\", new ExactEvmScheme(config.signer));\n }\n\n // Register all V1 networks\n NETWORKS.forEach(network => {\n client.registerV1(network as Network, new ExactEvmSchemeV1(config.signer));\n });\n\n // Apply policies if provided\n if (config.policies) {\n config.policies.forEach(policy => {\n client.registerPolicy(policy);\n });\n }\n\n return client;\n}\n"],"mappings":"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","names":["getAddress","getAddress"]} |
| // src/exact/v1/client/scheme.ts | ||
| import { getAddress } from "viem"; | ||
| // src/constants.ts | ||
| var authorizationTypes = { | ||
| TransferWithAuthorization: [ | ||
| { name: "from", type: "address" }, | ||
| { name: "to", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "validBefore", type: "uint256" }, | ||
| { name: "nonce", type: "bytes32" } | ||
| ] | ||
| }; | ||
| var permit2WitnessTypes = { | ||
| PermitWitnessTransferFrom: [ | ||
| { name: "permitted", type: "TokenPermissions" }, | ||
| { name: "spender", type: "address" }, | ||
| { name: "nonce", type: "uint256" }, | ||
| { name: "deadline", type: "uint256" }, | ||
| { name: "witness", type: "Witness" } | ||
| ], | ||
| TokenPermissions: [ | ||
| { name: "token", type: "address" }, | ||
| { name: "amount", type: "uint256" } | ||
| ], | ||
| Witness: [ | ||
| { name: "to", type: "address" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "extra", type: "bytes" } | ||
| ] | ||
| }; | ||
| var eip3009ABI = [ | ||
| { | ||
| inputs: [ | ||
| { name: "from", type: "address" }, | ||
| { name: "to", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "validBefore", type: "uint256" }, | ||
| { name: "nonce", type: "bytes32" }, | ||
| { name: "v", type: "uint8" }, | ||
| { name: "r", type: "bytes32" }, | ||
| { name: "s", type: "bytes32" } | ||
| ], | ||
| name: "transferWithAuthorization", | ||
| outputs: [], | ||
| stateMutability: "nonpayable", | ||
| type: "function" | ||
| }, | ||
| { | ||
| inputs: [ | ||
| { name: "from", type: "address" }, | ||
| { name: "to", type: "address" }, | ||
| { name: "value", type: "uint256" }, | ||
| { name: "validAfter", type: "uint256" }, | ||
| { name: "validBefore", type: "uint256" }, | ||
| { name: "nonce", type: "bytes32" }, | ||
| { name: "signature", type: "bytes" } | ||
| ], | ||
| name: "transferWithAuthorization", | ||
| outputs: [], | ||
| stateMutability: "nonpayable", | ||
| type: "function" | ||
| }, | ||
| { | ||
| inputs: [{ name: "account", type: "address" }], | ||
| name: "balanceOf", | ||
| outputs: [{ name: "", type: "uint256" }], | ||
| stateMutability: "view", | ||
| type: "function" | ||
| }, | ||
| { | ||
| inputs: [], | ||
| name: "version", | ||
| outputs: [{ name: "", type: "string" }], | ||
| stateMutability: "view", | ||
| type: "function" | ||
| } | ||
| ]; | ||
| var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| var x402UptoPermit2ProxyAddress = "0x4020633461b2895a48930Ff97eE8fCdE8E520002"; | ||
| var x402ExactPermit2ProxyABI = [ | ||
| { | ||
| type: "function", | ||
| name: "PERMIT2", | ||
| inputs: [], | ||
| outputs: [{ name: "", type: "address", internalType: "contract ISignatureTransfer" }], | ||
| stateMutability: "view" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "WITNESS_TYPEHASH", | ||
| inputs: [], | ||
| outputs: [{ name: "", type: "bytes32", internalType: "bytes32" }], | ||
| stateMutability: "view" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "WITNESS_TYPE_STRING", | ||
| inputs: [], | ||
| outputs: [{ name: "", type: "string", internalType: "string" }], | ||
| stateMutability: "view" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "initialize", | ||
| inputs: [{ name: "_permit2", type: "address", internalType: "address" }], | ||
| outputs: [], | ||
| stateMutability: "nonpayable" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "settle", | ||
| inputs: [ | ||
| { | ||
| name: "permit", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.PermitTransferFrom", | ||
| components: [ | ||
| { | ||
| name: "permitted", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.TokenPermissions", | ||
| components: [ | ||
| { name: "token", type: "address", internalType: "address" }, | ||
| { name: "amount", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "nonce", type: "uint256", internalType: "uint256" }, | ||
| { name: "deadline", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "owner", type: "address", internalType: "address" }, | ||
| { | ||
| name: "witness", | ||
| type: "tuple", | ||
| internalType: "struct x402BasePermit2Proxy.Witness", | ||
| components: [ | ||
| { name: "to", type: "address", internalType: "address" }, | ||
| { name: "validAfter", type: "uint256", internalType: "uint256" }, | ||
| { name: "extra", type: "bytes", internalType: "bytes" } | ||
| ] | ||
| }, | ||
| { name: "signature", type: "bytes", internalType: "bytes" } | ||
| ], | ||
| outputs: [], | ||
| stateMutability: "nonpayable" | ||
| }, | ||
| { | ||
| type: "function", | ||
| name: "settleWithPermit", | ||
| inputs: [ | ||
| { | ||
| name: "permit2612", | ||
| type: "tuple", | ||
| internalType: "struct x402BasePermit2Proxy.EIP2612Permit", | ||
| components: [ | ||
| { name: "value", type: "uint256", internalType: "uint256" }, | ||
| { name: "deadline", type: "uint256", internalType: "uint256" }, | ||
| { name: "r", type: "bytes32", internalType: "bytes32" }, | ||
| { name: "s", type: "bytes32", internalType: "bytes32" }, | ||
| { name: "v", type: "uint8", internalType: "uint8" } | ||
| ] | ||
| }, | ||
| { | ||
| name: "permit", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.PermitTransferFrom", | ||
| components: [ | ||
| { | ||
| name: "permitted", | ||
| type: "tuple", | ||
| internalType: "struct ISignatureTransfer.TokenPermissions", | ||
| components: [ | ||
| { name: "token", type: "address", internalType: "address" }, | ||
| { name: "amount", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "nonce", type: "uint256", internalType: "uint256" }, | ||
| { name: "deadline", type: "uint256", internalType: "uint256" } | ||
| ] | ||
| }, | ||
| { name: "owner", type: "address", internalType: "address" }, | ||
| { | ||
| name: "witness", | ||
| type: "tuple", | ||
| internalType: "struct x402BasePermit2Proxy.Witness", | ||
| components: [ | ||
| { name: "to", type: "address", internalType: "address" }, | ||
| { name: "validAfter", type: "uint256", internalType: "uint256" }, | ||
| { name: "extra", type: "bytes", internalType: "bytes" } | ||
| ] | ||
| }, | ||
| { name: "signature", type: "bytes", internalType: "bytes" } | ||
| ], | ||
| outputs: [], | ||
| stateMutability: "nonpayable" | ||
| }, | ||
| { type: "event", name: "Settled", inputs: [], anonymous: false }, | ||
| { type: "event", name: "SettledWithPermit", inputs: [], anonymous: false }, | ||
| { type: "error", name: "AlreadyInitialized", inputs: [] }, | ||
| { type: "error", name: "InvalidDestination", inputs: [] }, | ||
| { type: "error", name: "InvalidOwner", inputs: [] }, | ||
| { type: "error", name: "InvalidPermit2Address", inputs: [] }, | ||
| { type: "error", name: "PaymentTooEarly", inputs: [] }, | ||
| { type: "error", name: "ReentrancyGuardReentrantCall", inputs: [] } | ||
| ]; | ||
| // src/utils.ts | ||
| import { toHex } from "viem"; | ||
| function getEvmChainId(network) { | ||
| const chainId = EVM_NETWORK_CHAIN_ID_MAP[network]; | ||
| if (!chainId) { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
| return chainId; | ||
| } | ||
| function getCrypto() { | ||
| const cryptoObj = globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return cryptoObj; | ||
| } | ||
| function createNonce() { | ||
| return toHex(getCrypto().getRandomValues(new Uint8Array(32))); | ||
| } | ||
| function createPermit2Nonce() { | ||
| const randomBytes = getCrypto().getRandomValues(new Uint8Array(32)); | ||
| return BigInt(toHex(randomBytes)).toString(); | ||
| } | ||
| // src/exact/v1/client/scheme.ts | ||
| var ExactEvmSchemeV1 = class { | ||
| /** | ||
| * Creates a new ExactEvmClientV1 instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| */ | ||
| constructor(signer) { | ||
| this.signer = signer; | ||
| this.scheme = "exact"; | ||
| } | ||
| /** | ||
| * Creates a payment payload for the Exact scheme (V1). | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const selectedV1 = paymentRequirements; | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: this.signer.address, | ||
| to: getAddress(selectedV1.payTo), | ||
| value: selectedV1.maxAmountRequired, | ||
| validAfter: (now - 600).toString(), | ||
| // 10 minutes before | ||
| validBefore: (now + selectedV1.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await this.signAuthorization(authorization, selectedV1); | ||
| const payload = { | ||
| authorization, | ||
| signature | ||
| }; | ||
| return { | ||
| x402Version, | ||
| scheme: selectedV1.scheme, | ||
| network: selectedV1.network, | ||
| payload | ||
| }; | ||
| } | ||
| /** | ||
| * Sign the EIP-3009 authorization using EIP-712 | ||
| * | ||
| * @param authorization - The authorization to sign | ||
| * @param requirements - The payment requirements | ||
| * @returns Promise resolving to the signature | ||
| */ | ||
| async signAuthorization(authorization, requirements) { | ||
| const chainId = getEvmChainId(requirements.network); | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| throw new Error( | ||
| `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}` | ||
| ); | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const domain = { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: getAddress(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: getAddress(authorization.from), | ||
| to: getAddress(authorization.to), | ||
| value: BigInt(authorization.value), | ||
| validAfter: BigInt(authorization.validAfter), | ||
| validBefore: BigInt(authorization.validBefore), | ||
| nonce: authorization.nonce | ||
| }; | ||
| return await this.signer.signTypedData({ | ||
| domain, | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| message | ||
| }); | ||
| } | ||
| }; | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| import { getAddress as getAddress2, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; | ||
| var ExactEvmSchemeV12 = class { | ||
| /** | ||
| * Creates a new ExactEvmFacilitatorV1 instance. | ||
| * | ||
| * @param signer - The EVM signer for facilitator operations | ||
| * @param config - Optional configuration for the facilitator | ||
| */ | ||
| constructor(signer, config) { | ||
| this.signer = signer; | ||
| this.scheme = "exact"; | ||
| this.caipFamily = "eip155:*"; | ||
| this.config = { | ||
| deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? false | ||
| }; | ||
| } | ||
| /** | ||
| * Get mechanism-specific extra data for the supported kinds endpoint. | ||
| * For EVM, no extra data is needed. | ||
| * | ||
| * @param _ - The network identifier (unused for EVM) | ||
| * @returns undefined (EVM has no extra data) | ||
| */ | ||
| getExtra(_) { | ||
| return void 0; | ||
| } | ||
| /** | ||
| * Get signer addresses used by this facilitator. | ||
| * Returns all addresses this facilitator can use for signing/settling transactions. | ||
| * | ||
| * @param _ - The network identifier (unused for EVM, addresses are network-agnostic) | ||
| * @returns Array of facilitator wallet addresses | ||
| */ | ||
| getSigners(_) { | ||
| return [...this.signer.getAddresses()]; | ||
| } | ||
| /** | ||
| * Verifies a payment payload (V1). | ||
| * | ||
| * @param payload - The payment payload to verify | ||
| * @param requirements - The payment requirements | ||
| * @returns Promise resolving to verification response | ||
| */ | ||
| async verify(payload, requirements) { | ||
| const requirementsV1 = requirements; | ||
| const payloadV1 = payload; | ||
| const exactEvmPayload = payload.payload; | ||
| if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| let chainId; | ||
| try { | ||
| chainId = getEvmChainId(payloadV1.network); | ||
| } catch { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: `invalid_network`, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "missing_eip712_domain", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const erc20Address = getAddress2(requirements.asset); | ||
| if (payloadV1.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const permitTypedData = { | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| domain: { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: erc20Address | ||
| }, | ||
| message: { | ||
| from: exactEvmPayload.authorization.from, | ||
| to: exactEvmPayload.authorization.to, | ||
| value: BigInt(exactEvmPayload.authorization.value), | ||
| validAfter: BigInt(exactEvmPayload.authorization.validAfter), | ||
| validBefore: BigInt(exactEvmPayload.authorization.validBefore), | ||
| nonce: exactEvmPayload.authorization.nonce | ||
| } | ||
| }; | ||
| try { | ||
| const recoveredAddress = await this.signer.verifyTypedData({ | ||
| address: exactEvmPayload.authorization.from, | ||
| ...permitTypedData, | ||
| signature: exactEvmPayload.signature | ||
| }); | ||
| if (!recoveredAddress) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } catch { | ||
| const signature = exactEvmPayload.signature; | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isSmartWallet = signatureLength > 130; | ||
| if (isSmartWallet) { | ||
| const payerAddress = exactEvmPayload.authorization.from; | ||
| const bytecode = await this.signer.getCode({ address: payerAddress }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| const erc6492Data = parseErc6492Signature(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !isAddressEqual(erc6492Data.address, "0x0000000000000000000000000000000000000000"); | ||
| if (!hasDeploymentInfo) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_undeployed_smart_wallet", | ||
| payer: payerAddress | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } | ||
| if (getAddress2(exactEvmPayload.authorization.to) !== getAddress2(requirements.payTo)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_recipient_mismatch", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_before", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_after", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| try { | ||
| const balance = await this.signer.readContract({ | ||
| address: erc20Address, | ||
| abi: eip3009ABI, | ||
| functionName: "balanceOf", | ||
| args: [exactEvmPayload.authorization.from] | ||
| }); | ||
| if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_value", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| /** | ||
| * Settles a payment by executing the transfer (V1). | ||
| * | ||
| * @param payload - The payment payload to settle | ||
| * @param requirements - The payment requirements | ||
| * @returns Promise resolving to settlement response | ||
| */ | ||
| async settle(payload, requirements) { | ||
| const payloadV1 = payload; | ||
| const exactEvmPayload = payload.payload; | ||
| const valid = await this.verify(payload, requirements); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payloadV1.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| try { | ||
| const parseResult = parseErc6492Signature(exactEvmPayload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| const payerAddress = exactEvmPayload.authorization.from; | ||
| const bytecode = await this.signer.getCode({ address: payerAddress }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| try { | ||
| console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`); | ||
| const deployTx = await this.signer.sendTransaction({ | ||
| to: factoryAddress, | ||
| data: factoryCalldata | ||
| }); | ||
| await this.signer.waitForTransactionReceipt({ hash: deployTx }); | ||
| console.log(`Successfully deployed smart wallet for ${payerAddress}`); | ||
| } catch (deployError) { | ||
| console.error("Smart wallet deployment failed:", deployError); | ||
| throw deployError; | ||
| } | ||
| } else { | ||
| console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`); | ||
| } | ||
| } | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isECDSA = signatureLength === 130; | ||
| let tx; | ||
| if (isECDSA) { | ||
| const parsedSig = parseSignature(signature); | ||
| tx = await this.signer.writeContract({ | ||
| address: getAddress2(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress2(exactEvmPayload.authorization.from), | ||
| getAddress2(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
| BigInt(exactEvmPayload.authorization.validAfter), | ||
| BigInt(exactEvmPayload.authorization.validBefore), | ||
| exactEvmPayload.authorization.nonce, | ||
| parsedSig.v || parsedSig.yParity, | ||
| parsedSig.r, | ||
| parsedSig.s | ||
| ] | ||
| }); | ||
| } else { | ||
| tx = await this.signer.writeContract({ | ||
| address: getAddress2(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress2(exactEvmPayload.authorization.from), | ||
| getAddress2(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
| BigInt(exactEvmPayload.authorization.validAfter), | ||
| BigInt(exactEvmPayload.authorization.validBefore), | ||
| exactEvmPayload.authorization.nonce, | ||
| signature | ||
| ] | ||
| }); | ||
| } | ||
| const receipt = await this.signer.waitForTransactionReceipt({ hash: tx }); | ||
| if (receipt.status !== "success") { | ||
| return { | ||
| success: false, | ||
| errorReason: "invalid_transaction_state", | ||
| transaction: tx, | ||
| network: payloadV1.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payloadV1.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } catch (error) { | ||
| console.error("Failed to settle transaction:", error); | ||
| return { | ||
| success: false, | ||
| errorReason: "transaction_failed", | ||
| transaction: "", | ||
| network: payloadV1.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } | ||
| }; | ||
| // src/v1/index.ts | ||
| var EVM_NETWORK_CHAIN_ID_MAP = { | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| abstract: 2741, | ||
| "abstract-testnet": 11124, | ||
| "base-sepolia": 84532, | ||
| base: 8453, | ||
| "avalanche-fuji": 43113, | ||
| avalanche: 43114, | ||
| iotex: 4689, | ||
| sei: 1329, | ||
| "sei-testnet": 1328, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002, | ||
| peaq: 3338, | ||
| story: 1514, | ||
| educhain: 41923, | ||
| "skale-base-sepolia": 324705682, | ||
| megaeth: 4326 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| export { | ||
| authorizationTypes, | ||
| permit2WitnessTypes, | ||
| eip3009ABI, | ||
| PERMIT2_ADDRESS, | ||
| x402ExactPermit2ProxyAddress, | ||
| x402UptoPermit2ProxyAddress, | ||
| x402ExactPermit2ProxyABI, | ||
| ExactEvmSchemeV1, | ||
| ExactEvmSchemeV12, | ||
| EVM_NETWORK_CHAIN_ID_MAP, | ||
| NETWORKS, | ||
| createNonce, | ||
| createPermit2Nonce | ||
| }; | ||
| //# sourceMappingURL=chunk-RPL6OFJL.mjs.map |
| {"version":3,"sources":["../../src/exact/v1/client/scheme.ts","../../src/constants.ts","../../src/utils.ts","../../src/exact/v1/facilitator/scheme.ts","../../src/v1/index.ts"],"sourcesContent":["import {\n Network,\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { ClientEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { createNonce, getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } 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 = getEvmChainId(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","// 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.\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 { name: \"extra\", type: \"bytes\" },\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] as const;\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 = \"0x4020615294c913F045dc10f0a5cdEbd86c280001\" 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 = \"0x4020633461b2895a48930Ff97eE8fCdE8E520002\" as const;\n\n/**\n * x402UptoPermit2Proxy ABI - settle function for upto payment scheme (variable amounts).\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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", inputs: [] },\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: \"ReentrancyGuardReentrantCall\", 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: \"initialize\",\n inputs: [{ name: \"_permit2\", type: \"address\", internalType: \"address\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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 x402BasePermit2Proxy.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 x402BasePermit2Proxy.Witness\",\n components: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"validAfter\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"extra\", type: \"bytes\", internalType: \"bytes\" },\n ],\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: \"AlreadyInitialized\", 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: \"ReentrancyGuardReentrantCall\", inputs: [] },\n] as const;\n","import { toHex } from \"viem\";\nimport { EVM_NETWORK_CHAIN_ID_MAP, EvmNetworkV1 } from \"./v1\";\n\n/**\n * Extract chain ID from network string (e.g., \"base-sepolia\" -> 84532)\n * Used by v1 implementations\n *\n * @param network - The network identifier\n * @returns The numeric chain ID\n * @throws Error if the network is not supported\n */\nexport function getEvmChainId(network: EvmNetworkV1): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];\n if (!chainId) {\n throw new Error(`Unsupported network: ${network}`);\n }\n return chainId;\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 {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature, parseSignature } from \"viem\";\nimport { authorizationTypes, eip3009ABI } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { getEvmChainId } from \"../../../utils\";\nimport { EvmNetworkV1 } from \"../../../v1\";\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * If enabled, the facilitator will deploy ERC-4337 smart wallets\n * via EIP-6492 when encountering undeployed contract signatures.\n *\n * @default false\n */\n deployERC4337WithEIP6492?: 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 deployERC4337WithEIP6492: config?.deployERC4337WithEIP6492 ?? 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 const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: \"unsupported_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainId(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: `invalid_network`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: \"missing_eip712_domain\",\n payer: exactEvmPayload.authorization.from,\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: \"network_mismatch\",\n payer: exactEvmPayload.authorization.from,\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\n try {\n const recoveredAddress = await this.signer.verifyTypedData({\n address: exactEvmPayload.authorization.from,\n ...permitTypedData,\n signature: exactEvmPayload.signature!,\n });\n\n if (!recoveredAddress) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // Signature verification failed - could be an undeployed smart wallet\n // Check if smart wallet is deployed\n const signature = exactEvmPayload.signature!;\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isSmartWallet = signatureLength > 130; // 65 bytes = 130 hex chars for EOA\n\n if (isSmartWallet) {\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n // Wallet is not deployed. Check if it's EIP-6492 with deployment info.\n // EIP-6492 signatures contain factory address and calldata needed for deployment.\n // Non-EIP-6492 undeployed wallets cannot succeed (no way to deploy them).\n const erc6492Data = parseErc6492Signature(signature);\n const hasDeploymentInfo =\n erc6492Data.address &&\n erc6492Data.data &&\n !isAddressEqual(erc6492Data.address, \"0x0000000000000000000000000000000000000000\");\n\n if (!hasDeploymentInfo) {\n // Non-EIP-6492 undeployed smart wallet - will always fail at settlement\n // since EIP-3009 requires on-chain EIP-1271 validation\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_undeployed_smart_wallet\",\n payer: payerAddress,\n };\n }\n // EIP-6492 signature with deployment info - allow through\n // Facilitators with sponsored deployment support can handle this in settle()\n } else {\n // Wallet is deployed but signature still failed - invalid signature\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n } else {\n // EOA signature failed\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_signature\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_recipient_mismatch\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_before\",\n payer: exactEvmPayload.authorization.from,\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: \"invalid_exact_evm_payload_authorization_valid_after\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Check balance\n try {\n const balance = (await this.signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [exactEvmPayload.authorization.from],\n })) as bigint;\n\n if (BigInt(balance) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\n invalidMessage: `Insufficient funds to complete the payment. Required: ${requirementsV1.maxAmountRequired} ${requirements.asset}, Available: ${balance.toString()} ${requirements.asset}. Please add funds to your wallet and try again.`,\n payer: exactEvmPayload.authorization.from,\n };\n }\n } catch {\n // If we can't check balance, continue with other validations\n }\n\n // Verify amount is sufficient\n if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_evm_payload_authorization_value\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer: exactEvmPayload.authorization.from,\n };\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 * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\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 if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"invalid_scheme\",\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable\n const parseResult = parseErc6492Signature(exactEvmPayload.signature!);\n const { signature, address: factoryAddress, data: factoryCalldata } = parseResult;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if configured and needed\n if (\n this.config.deployERC4337WithEIP6492 &&\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 // Wallet not deployed - attempt deployment\n try {\n console.log(`Deploying ERC-4337 smart wallet for ${payerAddress} via EIP-6492`);\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 console.log(`Successfully deployed smart wallet for ${payerAddress}`);\n } catch (deployError) {\n console.error(\"Smart wallet deployment failed:\", deployError);\n // Deployment failed - cannot proceed\n throw deployError;\n }\n } else {\n console.log(`Smart wallet for ${payerAddress} already deployed, skipping deployment`);\n }\n }\n\n // Determine if this is an ECDSA signature (EOA) or smart wallet signature\n // ECDSA signatures are exactly 65 bytes (130 hex chars without 0x)\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n let tx: Hex;\n if (isECDSA) {\n // For EOA wallets, parse signature into v, r, s and use that overload\n const parsedSig = parseSignature(signature);\n\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n // For smart wallets, use the bytes signature overload\n // The signature contains WebAuthn/P256 or other ERC-1271 compatible signature data\n tx = await this.signer.writeContract({\n address: getAddress(requirements.asset),\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n getAddress(exactEvmPayload.authorization.from),\n getAddress(exactEvmPayload.authorization.to),\n BigInt(exactEvmPayload.authorization.value),\n BigInt(exactEvmPayload.authorization.validAfter),\n BigInt(exactEvmPayload.authorization.validBefore),\n exactEvmPayload.authorization.nonce,\n signature,\n ],\n });\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: \"invalid_transaction_state\",\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 console.error(\"Failed to settle transaction:\", error);\n return {\n success: false,\n errorReason: \"transaction_failed\",\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\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} 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"],"mappings":"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","names":["getAddress","ExactEvmSchemeV1","getAddress"]} |
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayloadResult } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from './signer-5OVDxViv.mjs'; | ||
| /** | ||
| * EVM client implementation for the Exact payment scheme. | ||
| * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows. | ||
| * | ||
| * Routes to the appropriate authorization method based on | ||
| * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009 | ||
| * for backward compatibility with older facilitators. | ||
| */ | ||
| declare class ExactEvmScheme implements SchemeNetworkClient { | ||
| private readonly signer; | ||
| readonly scheme = "exact"; | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
| * @param signer - The EVM signer for client operations | ||
| */ | ||
| constructor(signer: ClientEvmSigner); | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload result | ||
| */ | ||
| createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements): Promise<PaymentPayloadResult>; | ||
| } | ||
| /** | ||
| * ERC20 allowance ABI for checking approval status. | ||
| */ | ||
| declare const erc20AllowanceAbi: readonly [{ | ||
| readonly type: "function"; | ||
| readonly name: "allowance"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "spender"; | ||
| readonly type: "address"; | ||
| }]; | ||
| readonly outputs: readonly [{ | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }]; | ||
| /** | ||
| * Creates transaction data to approve Permit2 to spend tokens. | ||
| * The user sends this transaction (paying gas) before using Permit2 flow. | ||
| * | ||
| * @param tokenAddress - The ERC20 token contract address | ||
| * @returns Transaction data to send for approval | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const tx = createPermit2ApprovalTx("0x..."); | ||
| * await walletClient.sendTransaction({ | ||
| * to: tx.to, | ||
| * data: tx.data, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| declare function createPermit2ApprovalTx(tokenAddress: `0x${string}`): { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }; | ||
| /** | ||
| * Parameters for checking Permit2 allowance. | ||
| * Application provides these to check if approval is needed. | ||
| */ | ||
| interface Permit2AllowanceParams { | ||
| tokenAddress: `0x${string}`; | ||
| ownerAddress: `0x${string}`; | ||
| } | ||
| /** | ||
| * Returns contract read parameters for checking Permit2 allowance. | ||
| * Use with a public client to check if the user has approved Permit2. | ||
| * | ||
| * @param params - The allowance check parameters | ||
| * @returns Contract read parameters for checking allowance | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * const readParams = getPermit2AllowanceReadParams({ | ||
| * tokenAddress: "0x...", | ||
| * ownerAddress: "0x...", | ||
| * }); | ||
| * | ||
| * const allowance = await publicClient.readContract(readParams); | ||
| * const needsApproval = allowance < requiredAmount; | ||
| * ``` | ||
| */ | ||
| declare function getPermit2AllowanceReadParams(params: Permit2AllowanceParams): { | ||
| address: `0x${string}`; | ||
| abi: typeof erc20AllowanceAbi; | ||
| functionName: "allowance"; | ||
| args: [`0x${string}`, `0x${string}`]; | ||
| }; | ||
| export { ExactEvmScheme as E, type Permit2AllowanceParams as P, createPermit2ApprovalTx as c, erc20AllowanceAbi as e, getPermit2AllowanceReadParams as g }; |
| /** | ||
| * ClientEvmSigner - Used by x402 clients to sign payment authorizations | ||
| * This is typically a LocalAccount or wallet that holds private keys | ||
| * and can sign EIP-712 typed data for payment authorizations | ||
| */ | ||
| type ClientEvmSigner = { | ||
| readonly address: `0x${string}`; | ||
| signTypedData(message: { | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| }): Promise<`0x${string}`>; | ||
| }; | ||
| /** | ||
| * FacilitatorEvmSigner - Used by x402 facilitators to verify and settle payments | ||
| * This is typically a viem PublicClient + WalletClient combination that can | ||
| * read contract state, verify signatures, write transactions, and wait for receipts | ||
| * | ||
| * Supports multiple addresses for load balancing, key rotation, and high availability | ||
| */ | ||
| type FacilitatorEvmSigner = { | ||
| /** | ||
| * Get all addresses this facilitator can use for signing | ||
| * Enables dynamic address selection for load balancing and key rotation | ||
| */ | ||
| getAddresses(): readonly `0x${string}`[]; | ||
| readContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args?: readonly unknown[]; | ||
| }): Promise<unknown>; | ||
| verifyTypedData(args: { | ||
| address: `0x${string}`; | ||
| domain: Record<string, unknown>; | ||
| types: Record<string, unknown>; | ||
| primaryType: string; | ||
| message: Record<string, unknown>; | ||
| signature: `0x${string}`; | ||
| }): Promise<boolean>; | ||
| writeContract(args: { | ||
| address: `0x${string}`; | ||
| abi: readonly unknown[]; | ||
| functionName: string; | ||
| args: readonly unknown[]; | ||
| }): Promise<`0x${string}`>; | ||
| sendTransaction(args: { | ||
| to: `0x${string}`; | ||
| data: `0x${string}`; | ||
| }): Promise<`0x${string}`>; | ||
| waitForTransactionReceipt(args: { | ||
| hash: `0x${string}`; | ||
| }): Promise<{ | ||
| status: string; | ||
| }>; | ||
| getCode(args: { | ||
| address: `0x${string}`; | ||
| }): Promise<`0x${string}` | undefined>; | ||
| }; | ||
| /** | ||
| * Converts a signer to a ClientEvmSigner | ||
| * | ||
| * @param signer - The signer to convert to a ClientEvmSigner | ||
| * @returns The converted signer | ||
| */ | ||
| declare function toClientEvmSigner(signer: ClientEvmSigner): ClientEvmSigner; | ||
| /** | ||
| * Converts a viem client with single address to a FacilitatorEvmSigner | ||
| * Wraps the single address in a getAddresses() function for compatibility | ||
| * | ||
| * @param client - The client to convert (must have 'address' property) | ||
| * @returns FacilitatorEvmSigner with getAddresses() support | ||
| */ | ||
| declare function toFacilitatorEvmSigner(client: Omit<FacilitatorEvmSigner, "getAddresses"> & { | ||
| address: `0x${string}`; | ||
| }): FacilitatorEvmSigner; | ||
| export { type ClientEvmSigner as C, type FacilitatorEvmSigner as F, toFacilitatorEvmSigner as a, toClientEvmSigner as t }; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
774953
11.36%6507
12.46%4
33.33%6
50%+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
Updated