| 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 }; |
| // 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 | ||
| }; | ||
| 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-DSSJHWGT.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} 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"]} |
| // src/types.ts | ||
| function isPermit2Payload(payload) { | ||
| return "permit2Authorization" in payload; | ||
| } | ||
| function isEIP3009Payload(payload) { | ||
| return "authorization" in payload; | ||
| } | ||
| export { | ||
| isPermit2Payload, | ||
| isEIP3009Payload | ||
| }; | ||
| //# sourceMappingURL=chunk-PFULIQAE.mjs.map |
| {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["/**\n * Asset transfer methods for the exact EVM scheme.\n * - eip3009: Uses transferWithAuthorization (USDC, etc.) - recommended for compatible tokens\n * - permit2: Uses Permit2 + x402Permit2Proxy - universal fallback for any ERC-20\n */\nexport type AssetTransferMethod = \"eip3009\" | \"permit2\";\n\n/**\n * EIP-3009 payload for tokens with native transferWithAuthorization support.\n */\nexport type ExactEIP3009Payload = {\n signature?: `0x${string}`;\n authorization: {\n from: `0x${string}`;\n to: `0x${string}`;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: `0x${string}`;\n };\n};\n\n/**\n * Permit2 witness data structure.\n * Matches the Witness struct in x402Permit2Proxy contract.\n * Note: Upper time bound is enforced by Permit2's `deadline` field, not a witness field.\n */\nexport type Permit2Witness = {\n to: `0x${string}`;\n validAfter: string;\n extra: `0x${string}`;\n};\n\n/**\n * Permit2 authorization parameters.\n * Used to reconstruct the signed message for verification.\n */\nexport type Permit2Authorization = {\n permitted: {\n token: `0x${string}`;\n amount: string;\n };\n spender: `0x${string}`;\n nonce: string;\n deadline: string;\n witness: Permit2Witness;\n};\n\n/**\n * Permit2 payload for tokens using the Permit2 + x402Permit2Proxy flow.\n */\nexport type ExactPermit2Payload = {\n signature: `0x${string}`;\n permit2Authorization: Permit2Authorization & {\n from: `0x${string}`;\n };\n};\n\nexport type ExactEvmPayloadV1 = ExactEIP3009Payload;\n\nexport type ExactEvmPayloadV2 = ExactEIP3009Payload | ExactPermit2Payload;\n\n/**\n * Type guard to check if a payload is a Permit2 payload.\n * Permit2 payloads have a `permit2Authorization` field.\n *\n * @param payload - The payload to check.\n * @returns True if the payload is a Permit2 payload, false otherwise.\n */\nexport function isPermit2Payload(payload: ExactEvmPayloadV2): payload is ExactPermit2Payload {\n return \"permit2Authorization\" in payload;\n}\n\n/**\n * Type guard to check if a payload is an EIP-3009 payload.\n * EIP-3009 payloads have an `authorization` field.\n *\n * @param payload - The payload to check.\n * @returns True if the payload is an EIP-3009 payload, false otherwise.\n */\nexport function isEIP3009Payload(payload: ExactEvmPayloadV2): payload is ExactEIP3009Payload {\n return \"authorization\" in payload;\n}\n"],"mappings":";AAqEO,SAAS,iBAAiB,SAA4D;AAC3F,SAAO,0BAA0B;AACnC;AASO,SAAS,iBAAiB,SAA4D;AAC3F,SAAO,mBAAmB;AAC5B;","names":[]} |
| import { | ||
| ExactEvmSchemeV1, | ||
| NETWORKS, | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| createNonce, | ||
| createPermit2Nonce, | ||
| permit2WitnessTypes, | ||
| x402ExactPermit2ProxyAddress | ||
| } from "./chunk-DSSJHWGT.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-U4H6Q62Q.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"]} |
| 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 }; |
@@ -1,3 +0,3 @@ | ||
| export { ExactEvmScheme } from '../../index.js'; | ||
| import { x402Client, SelectPaymentRequirements, PaymentPolicy } from '@x402/core/client'; | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-BYv82va2.js'; | ||
| import { SelectPaymentRequirements, PaymentPolicy, x402Client } from '@x402/core/client'; | ||
| import { Network } from '@x402/core/types'; | ||
@@ -4,0 +4,0 @@ import { C as ClientEvmSigner } from '../../signer-5OVDxViv.js'; |
+264
-119
@@ -24,2 +24,5 @@ "use strict"; | ||
| ExactEvmScheme: () => ExactEvmScheme, | ||
| createPermit2ApprovalTx: () => createPermit2ApprovalTx, | ||
| erc20AllowanceAbi: () => erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams: () => getPermit2AllowanceReadParams, | ||
| registerExactEvmScheme: () => registerExactEvmScheme | ||
@@ -29,4 +32,4 @@ }); | ||
| // src/exact/client/scheme.ts | ||
| var import_viem2 = require("viem"); | ||
| // src/exact/client/eip3009.ts | ||
| var import_viem4 = require("viem"); | ||
@@ -44,28 +47,31 @@ // src/constants.ts | ||
| }; | ||
| 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 PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| // src/utils.ts | ||
| var import_viem3 = require("viem"); | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem = require("viem"); | ||
| function getEvmChainId(network) { | ||
| const networkMap = { | ||
| base: 8453, | ||
| "base-sepolia": 84532, | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002 | ||
| }; | ||
| return networkMap[network] || 1; | ||
| } | ||
| function createNonce() { | ||
| const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return (0, import_viem.toHex)(cryptoObj.getRandomValues(new Uint8Array(32))); | ||
| } | ||
| // src/exact/client/scheme.ts | ||
| var ExactEvmScheme = class { | ||
| var ExactEvmSchemeV1 = class { | ||
| /** | ||
| * Creates a new ExactEvmClient instance. | ||
| * Creates a new ExactEvmClientV1 instance. | ||
| * | ||
@@ -79,3 +85,3 @@ * @param signer - The EVM signer for client operations | ||
| /** | ||
| * Creates a payment payload for the Exact scheme. | ||
| * Creates a payment payload for the Exact scheme (V1). | ||
| * | ||
@@ -87,2 +93,3 @@ * @param x402Version - The x402 protocol version | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const selectedV1 = paymentRequirements; | ||
| const nonce = createNonce(); | ||
@@ -92,10 +99,10 @@ const now = Math.floor(Date.now() / 1e3); | ||
| from: this.signer.address, | ||
| to: (0, import_viem2.getAddress)(paymentRequirements.payTo), | ||
| value: paymentRequirements.amount, | ||
| to: (0, import_viem.getAddress)(selectedV1.payTo), | ||
| value: selectedV1.maxAmountRequired, | ||
| validAfter: (now - 600).toString(), | ||
| // 10 minutes before | ||
| validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(), | ||
| validBefore: (now + selectedV1.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await this.signAuthorization(authorization, paymentRequirements); | ||
| const signature = await this.signAuthorization(authorization, selectedV1); | ||
| const payload = { | ||
@@ -107,2 +114,4 @@ authorization, | ||
| x402Version, | ||
| scheme: selectedV1.scheme, | ||
| network: selectedV1.network, | ||
| payload | ||
@@ -119,3 +128,3 @@ }; | ||
| async signAuthorization(authorization, requirements) { | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const chainId = getEvmChainId(requirements.network); | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
@@ -131,7 +140,7 @@ throw new Error( | ||
| chainId, | ||
| verifyingContract: (0, import_viem2.getAddress)(requirements.asset) | ||
| verifyingContract: (0, import_viem.getAddress)(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: (0, import_viem2.getAddress)(authorization.from), | ||
| to: (0, import_viem2.getAddress)(authorization.to), | ||
| from: (0, import_viem.getAddress)(authorization.from), | ||
| to: (0, import_viem.getAddress)(authorization.to), | ||
| value: BigInt(authorization.value), | ||
@@ -151,7 +160,215 @@ validAfter: BigInt(authorization.validAfter), | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem3 = require("viem"); | ||
| var ExactEvmSchemeV1 = class { | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var import_viem2 = require("viem"); | ||
| // 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 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| // src/utils.ts | ||
| 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 (0, import_viem3.toHex)(getCrypto().getRandomValues(new Uint8Array(32))); | ||
| } | ||
| function createPermit2Nonce() { | ||
| const randomBytes = getCrypto().getRandomValues(new Uint8Array(32)); | ||
| return BigInt((0, import_viem3.toHex)(randomBytes)).toString(); | ||
| } | ||
| // src/exact/client/eip3009.ts | ||
| async function createEIP3009Payload(signer, x402Version, paymentRequirements) { | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: signer.address, | ||
| to: (0, import_viem4.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: (0, import_viem4.getAddress)(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: (0, import_viem4.getAddress)(authorization.from), | ||
| to: (0, import_viem4.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 | ||
| var import_viem5 = require("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: (0, import_viem5.getAddress)(paymentRequirements.asset), | ||
| amount: paymentRequirements.amount | ||
| }, | ||
| spender: x402ExactPermit2ProxyAddress, | ||
| nonce, | ||
| deadline, | ||
| witness: { | ||
| to: (0, import_viem5.getAddress)(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: (0, import_viem5.getAddress)(permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Authorization.permitted.amount) | ||
| }, | ||
| spender: (0, import_viem5.getAddress)(permit2Authorization.spender), | ||
| nonce: BigInt(permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Authorization.deadline), | ||
| witness: { | ||
| to: (0, import_viem5.getAddress)(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 = (0, import_viem5.encodeFunctionData)({ | ||
| abi: erc20ApproveAbi, | ||
| functionName: "approve", | ||
| args: [PERMIT2_ADDRESS, MAX_UINT256] | ||
| }); | ||
| return { | ||
| to: (0, import_viem5.getAddress)(tokenAddress), | ||
| data | ||
| }; | ||
| } | ||
| function getPermit2AllowanceReadParams(params) { | ||
| return { | ||
| address: (0, import_viem5.getAddress)(params.tokenAddress), | ||
| abi: erc20AllowanceAbi, | ||
| functionName: "allowance", | ||
| args: [(0, import_viem5.getAddress)(params.ownerAddress), PERMIT2_ADDRESS] | ||
| }; | ||
| } | ||
| // src/exact/client/scheme.ts | ||
| var ExactEvmScheme = class { | ||
| /** | ||
| * Creates a new ExactEvmClientV1 instance. | ||
| * Creates a new ExactEvmClient instance. | ||
| * | ||
@@ -165,93 +382,18 @@ * @param signer - The EVM signer for client operations | ||
| /** | ||
| * Creates a payment payload for the Exact scheme (V1). | ||
| * 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 | ||
| * @returns Promise resolving to a payment payload result | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const selectedV1 = paymentRequirements; | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: this.signer.address, | ||
| to: (0, import_viem3.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 assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009"; | ||
| if (assetTransferMethod === "permit2") { | ||
| return createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const domain = { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: (0, import_viem3.getAddress)(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: (0, import_viem3.getAddress)(authorization.from), | ||
| to: (0, import_viem3.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 | ||
| }); | ||
| return createEIP3009Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| }; | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/v1/index.ts | ||
| var NETWORKS = [ | ||
| "abstract", | ||
| "abstract-testnet", | ||
| "base-sepolia", | ||
| "base", | ||
| "avalanche-fuji", | ||
| "avalanche", | ||
| "iotex", | ||
| "sei", | ||
| "sei-testnet", | ||
| "polygon", | ||
| "polygon-amoy", | ||
| "peaq", | ||
| "story", | ||
| "educhain", | ||
| "skale-base-sepolia" | ||
| ]; | ||
| // src/exact/client/register.ts | ||
@@ -279,4 +421,7 @@ function registerExactEvmScheme(client, config) { | ||
| ExactEvmScheme, | ||
| createPermit2ApprovalTx, | ||
| erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams, | ||
| registerExactEvmScheme | ||
| }); | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../../src/exact/client/index.ts","../../../../src/exact/client/scheme.ts","../../../../src/constants.ts","../../../../src/utils.ts","../../../../src/exact/v1/client/scheme.ts","../../../../src/exact/v1/facilitator/scheme.ts","../../../../src/v1/index.ts","../../../../src/exact/client/register.ts"],"sourcesContent":["export { ExactEvmScheme } from \"./scheme\";\nexport { registerExactEvmScheme } from \"./register\";\nexport type { EvmClientConfig } from \"./register\";\n","import { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmPayloadV2 } from \"../../types\";\nimport { createNonce } from \"../../utils\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n *\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 *\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<Pick<PaymentPayload, \"x402Version\" | \"payload\">> {\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEvmPayloadV2[\"authorization\"] = {\n from: this.signer.address,\n to: getAddress(paymentRequirements.payTo),\n value: paymentRequirements.amount,\n validAfter: (now - 600).toString(), // 10 minutes before\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n // Sign the authorization\n const signature = await this.signAuthorization(authorization, paymentRequirements);\n\n const payload: ExactEvmPayloadV2 = {\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 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: ExactEvmPayloadV2[\"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 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// 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","import { toHex } from \"viem\";\nimport { Network } from \"@x402/core/types\";\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 */\nexport function getEvmChainId(network: Network): number {\n const networkMap: Record<string, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n ethereum: 1,\n sepolia: 11155111,\n polygon: 137,\n \"polygon-amoy\": 80002,\n };\n return networkMap[network] || 1;\n}\n\n/**\n * Create a random 32-byte nonce for authorization\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n // Use dynamic import to avoid require() in ESM context\n const cryptoObj =\n typeof globalThis.crypto !== \"undefined\"\n ? globalThis.crypto\n : (globalThis as { crypto?: Crypto }).crypto;\n\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n\n return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));\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\";\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);\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","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\";\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 const chainId = getEvmChainId(payloadV1.network);\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 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 NETWORKS: string[] = [\n \"abstract\",\n \"abstract-testnet\",\n \"base-sepolia\",\n \"base\",\n \"avalanche-fuji\",\n \"avalanche\",\n \"iotex\",\n \"sei\",\n \"sei-testnet\",\n \"polygon\",\n \"polygon-amoy\",\n \"peaq\",\n \"story\",\n \"educhain\",\n \"skale-base-sepolia\",\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":["import_viem","import_viem","import_viem"]} | ||
| {"version":3,"sources":["../../../../src/exact/client/index.ts","../../../../src/exact/client/eip3009.ts","../../../../src/constants.ts","../../../../src/utils.ts","../../../../src/exact/v1/client/scheme.ts","../../../../src/exact/v1/facilitator/scheme.ts","../../../../src/v1/index.ts","../../../../src/exact/client/permit2.ts","../../../../src/exact/client/scheme.ts","../../../../src/exact/client/register.ts"],"sourcesContent":["export { ExactEvmScheme } from \"./scheme\";\nexport { registerExactEvmScheme } from \"./register\";\nexport type { EvmClientConfig } from \"./register\";\nexport {\n createPermit2ApprovalTx,\n getPermit2AllowanceReadParams,\n erc20AllowanceAbi,\n type Permit2AllowanceParams,\n} from \"./permit2\";\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","// 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","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} 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 { 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":["import_viem","import_viem","import_viem","import_viem"]} |
@@ -16,2 +16,3 @@ import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse, Network } from '@x402/core/types'; | ||
| * EVM facilitator implementation for the Exact payment scheme. | ||
| * Routes between EIP-3009 and Permit2 based on payload type. | ||
| */ | ||
@@ -48,2 +49,3 @@ declare class ExactEvmScheme implements SchemeNetworkFacilitator { | ||
| * Verifies a payment payload. | ||
| * Routes to the appropriate verification logic based on payload type. | ||
| * | ||
@@ -57,2 +59,3 @@ * @param payload - The payment payload to verify | ||
| * Settles a payment by executing the transfer. | ||
| * Routes to the appropriate settlement logic based on payload type. | ||
| * | ||
@@ -59,0 +62,0 @@ * @param payload - The payment payload to settle |
@@ -28,3 +28,8 @@ "use strict"; | ||
| // src/exact/facilitator/scheme.ts | ||
| // src/types.ts | ||
| function isPermit2Payload(payload) { | ||
| return "permit2Authorization" in payload; | ||
| } | ||
| // src/exact/facilitator/eip3009.ts | ||
| var import_viem = require("viem"); | ||
@@ -43,2 +48,20 @@ | ||
| }; | ||
| 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 = [ | ||
@@ -92,3 +115,599 @@ { | ||
| ]; | ||
| var PERMIT2_ADDRESS = "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| var x402ExactPermit2ProxyAddress = "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| 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/exact/facilitator/eip3009.ts | ||
| async function verifyEIP3009(signer, payload, requirements, eip3009Payload) { | ||
| const payer = eip3009Payload.authorization.from; | ||
| if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "missing_eip712_domain", | ||
| payer | ||
| }; | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const erc20Address = (0, import_viem.getAddress)(requirements.asset); | ||
| if (payload.accepted.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const permitTypedData = { | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| domain: { | ||
| name, | ||
| version, | ||
| chainId: parseInt(requirements.network.split(":")[1]), | ||
| verifyingContract: erc20Address | ||
| }, | ||
| message: { | ||
| from: eip3009Payload.authorization.from, | ||
| to: eip3009Payload.authorization.to, | ||
| value: BigInt(eip3009Payload.authorization.value), | ||
| validAfter: BigInt(eip3009Payload.authorization.validAfter), | ||
| validBefore: BigInt(eip3009Payload.authorization.validBefore), | ||
| nonce: eip3009Payload.authorization.nonce | ||
| } | ||
| }; | ||
| try { | ||
| const recoveredAddress = await signer.verifyTypedData({ | ||
| address: eip3009Payload.authorization.from, | ||
| ...permitTypedData, | ||
| signature: eip3009Payload.signature | ||
| }); | ||
| if (!recoveredAddress) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| const signature = eip3009Payload.signature; | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isSmartWallet = signatureLength > 130; | ||
| if (isSmartWallet) { | ||
| const payerAddress = eip3009Payload.authorization.from; | ||
| const bytecode = await signer.getCode({ address: payerAddress }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| const erc6492Data = (0, import_viem.parseErc6492Signature)(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem.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 | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| if ((0, import_viem.getAddress)(eip3009Payload.authorization.to) !== (0, import_viem.getAddress)(requirements.payTo)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_recipient_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_before", | ||
| payer | ||
| }; | ||
| } | ||
| if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_after", | ||
| payer | ||
| }; | ||
| } | ||
| try { | ||
| const balance = await signer.readContract({ | ||
| address: erc20Address, | ||
| abi: eip3009ABI, | ||
| functionName: "balanceOf", | ||
| args: [eip3009Payload.authorization.from] | ||
| }); | ||
| if (BigInt(balance) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| 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.`, | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| if (BigInt(eip3009Payload.authorization.value) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_value", | ||
| payer | ||
| }; | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer | ||
| }; | ||
| } | ||
| async function settleEIP3009(signer, payload, requirements, eip3009Payload, config) { | ||
| const payer = eip3009Payload.authorization.from; | ||
| const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payload.accepted.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| try { | ||
| const parseResult = (0, import_viem.parseErc6492Signature)(eip3009Payload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| const bytecode = await signer.getCode({ address: payer }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| const deployTx = await signer.sendTransaction({ | ||
| to: factoryAddress, | ||
| data: factoryCalldata | ||
| }); | ||
| await signer.waitForTransactionReceipt({ hash: deployTx }); | ||
| } | ||
| } | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isECDSA = signatureLength === 130; | ||
| let tx; | ||
| if (isECDSA) { | ||
| const parsedSig = (0, import_viem.parseSignature)(signature); | ||
| tx = await signer.writeContract({ | ||
| address: (0, import_viem.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem.getAddress)(eip3009Payload.authorization.from), | ||
| (0, import_viem.getAddress)(eip3009Payload.authorization.to), | ||
| BigInt(eip3009Payload.authorization.value), | ||
| BigInt(eip3009Payload.authorization.validAfter), | ||
| BigInt(eip3009Payload.authorization.validBefore), | ||
| eip3009Payload.authorization.nonce, | ||
| parsedSig.v || parsedSig.yParity, | ||
| parsedSig.r, | ||
| parsedSig.s | ||
| ] | ||
| }); | ||
| } else { | ||
| tx = await signer.writeContract({ | ||
| address: (0, import_viem.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem.getAddress)(eip3009Payload.authorization.from), | ||
| (0, import_viem.getAddress)(eip3009Payload.authorization.to), | ||
| BigInt(eip3009Payload.authorization.value), | ||
| BigInt(eip3009Payload.authorization.validAfter), | ||
| BigInt(eip3009Payload.authorization.validBefore), | ||
| eip3009Payload.authorization.nonce, | ||
| signature | ||
| ] | ||
| }); | ||
| } | ||
| const receipt = await signer.waitForTransactionReceipt({ hash: tx }); | ||
| if (receipt.status !== "success") { | ||
| return { | ||
| success: false, | ||
| errorReason: "invalid_transaction_state", | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } catch { | ||
| return { | ||
| success: false, | ||
| errorReason: "transaction_failed", | ||
| transaction: "", | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| // src/exact/facilitator/permit2.ts | ||
| var import_viem2 = require("viem"); | ||
| var erc20AllowanceABI = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| async function verifyPermit2(signer, payload, requirements, permit2Payload) { | ||
| const payer = permit2Payload.permit2Authorization.from; | ||
| if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| if (payload.accepted.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const tokenAddress = (0, import_viem2.getAddress)(requirements.asset); | ||
| if ((0, import_viem2.getAddress)(permit2Payload.permit2Authorization.spender) !== (0, import_viem2.getAddress)(x402ExactPermit2ProxyAddress)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_spender", | ||
| payer | ||
| }; | ||
| } | ||
| if ((0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to) !== (0, import_viem2.getAddress)(requirements.payTo)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_recipient_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_deadline_expired", | ||
| payer | ||
| }; | ||
| } | ||
| if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_not_yet_valid", | ||
| payer | ||
| }; | ||
| } | ||
| if (BigInt(permit2Payload.permit2Authorization.permitted.amount) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_insufficient_amount", | ||
| payer | ||
| }; | ||
| } | ||
| if ((0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_token_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const permit2TypedData = { | ||
| types: permit2WitnessTypes, | ||
| primaryType: "PermitWitnessTransferFrom", | ||
| domain: { | ||
| name: "Permit2", | ||
| chainId, | ||
| verifyingContract: PERMIT2_ADDRESS | ||
| }, | ||
| message: { | ||
| permitted: { | ||
| token: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| }, | ||
| spender: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.spender), | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline), | ||
| witness: { | ||
| to: (0, import_viem2.getAddress)(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| } | ||
| } | ||
| }; | ||
| try { | ||
| const isValid = await signer.verifyTypedData({ | ||
| address: payer, | ||
| ...permit2TypedData, | ||
| signature: permit2Payload.signature | ||
| }); | ||
| if (!isValid) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_signature", | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_signature", | ||
| payer | ||
| }; | ||
| } | ||
| try { | ||
| const allowance = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: erc20AllowanceABI, | ||
| functionName: "allowance", | ||
| args: [payer, PERMIT2_ADDRESS] | ||
| }); | ||
| if (allowance < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_allowance_required", | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| try { | ||
| const balance = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: eip3009ABI, | ||
| functionName: "balanceOf", | ||
| args: [payer] | ||
| }); | ||
| if (balance < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| 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.`, | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer | ||
| }; | ||
| } | ||
| async function settlePermit2(signer, payload, requirements, permit2Payload) { | ||
| const payer = permit2Payload.permit2Authorization.from; | ||
| const valid = await verifyPermit2(signer, payload, requirements, permit2Payload); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payload.accepted.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| 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) | ||
| }, | ||
| 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 }); | ||
| if (receipt.status !== "success") { | ||
| return { | ||
| success: false, | ||
| errorReason: "invalid_transaction_state", | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } catch (error) { | ||
| let errorReason = "transaction_failed"; | ||
| if (error instanceof Error) { | ||
| const message = error.message; | ||
| if (message.includes("AmountExceedsPermitted")) { | ||
| errorReason = "permit2_amount_exceeds_permitted"; | ||
| } else if (message.includes("InvalidDestination")) { | ||
| errorReason = "permit2_invalid_destination"; | ||
| } else if (message.includes("InvalidOwner")) { | ||
| errorReason = "permit2_invalid_owner"; | ||
| } else if (message.includes("PaymentTooEarly")) { | ||
| errorReason = "permit2_payment_too_early"; | ||
| } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) { | ||
| errorReason = "permit2_invalid_signature"; | ||
| } else if (message.includes("InvalidNonce")) { | ||
| errorReason = "permit2_invalid_nonce"; | ||
| } else { | ||
| errorReason = `transaction_failed: ${message.slice(0, 500)}`; | ||
| } | ||
| } | ||
| return { | ||
| success: false, | ||
| errorReason, | ||
| transaction: "", | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| // src/exact/facilitator/scheme.ts | ||
@@ -132,2 +751,3 @@ var ExactEvmScheme = class { | ||
| * Verifies a payment payload. | ||
| * Routes to the appropriate verification logic based on payload type. | ||
| * | ||
@@ -139,142 +759,12 @@ * @param payload - The payment payload to verify | ||
| async verify(payload, requirements) { | ||
| const exactEvmPayload = payload.payload; | ||
| if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| const rawPayload = payload.payload; | ||
| if (isPermit2Payload(rawPayload)) { | ||
| return verifyPermit2(this.signer, payload, requirements, rawPayload); | ||
| } | ||
| 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 = (0, import_viem.getAddress)(requirements.asset); | ||
| if (payload.accepted.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const permitTypedData = { | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| domain: { | ||
| name, | ||
| version, | ||
| chainId: parseInt(requirements.network.split(":")[1]), | ||
| 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 = (0, import_viem.parseErc6492Signature)(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem.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 ((0, import_viem.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem.getAddress)(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(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_value", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| const eip3009Payload = rawPayload; | ||
| return verifyEIP3009(this.signer, payload, requirements, eip3009Payload); | ||
| } | ||
| /** | ||
| * Settles a payment by executing the transfer. | ||
| * Routes to the appropriate settlement logic based on payload type. | ||
| * | ||
@@ -286,99 +776,8 @@ * @param payload - The payment payload to settle | ||
| async settle(payload, requirements) { | ||
| const exactEvmPayload = payload.payload; | ||
| const valid = await this.verify(payload, requirements); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payload.accepted.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| const rawPayload = payload.payload; | ||
| if (isPermit2Payload(rawPayload)) { | ||
| return settlePermit2(this.signer, payload, requirements, rawPayload); | ||
| } | ||
| try { | ||
| const parseResult = (0, import_viem.parseErc6492Signature)(exactEvmPayload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem.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 = (0, import_viem.parseSignature)(signature); | ||
| tx = await this.signer.writeContract({ | ||
| address: (0, import_viem.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem.getAddress)(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: (0, import_viem.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem.getAddress)(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: payload.accepted.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } catch (error) { | ||
| console.error("Failed to settle transaction:", error); | ||
| return { | ||
| success: false, | ||
| errorReason: "transaction_failed", | ||
| transaction: "", | ||
| network: payload.accepted.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const eip3009Payload = rawPayload; | ||
| return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config); | ||
| } | ||
@@ -388,20 +787,43 @@ }; | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var import_viem5 = require("viem"); | ||
| // src/utils.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem3 = require("viem"); | ||
| // 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 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| // src/utils.ts | ||
| var import_viem2 = require("viem"); | ||
| function getEvmChainId(network) { | ||
| const networkMap = { | ||
| base: 8453, | ||
| "base-sepolia": 84532, | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002 | ||
| }; | ||
| return networkMap[network] || 1; | ||
| const chainId = EVM_NETWORK_CHAIN_ID_MAP[network]; | ||
| if (!chainId) { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
| return chainId; | ||
| } | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var ExactEvmSchemeV1 = class { | ||
| var ExactEvmSchemeV12 = class { | ||
| /** | ||
@@ -459,3 +881,12 @@ * Creates a new ExactEvmFacilitatorV1 instance. | ||
| } | ||
| const chainId = getEvmChainId(payloadV1.network); | ||
| 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) { | ||
@@ -469,3 +900,3 @@ return { | ||
| const { name, version } = requirements.extra; | ||
| const erc20Address = (0, import_viem3.getAddress)(requirements.asset); | ||
| const erc20Address = (0, import_viem5.getAddress)(requirements.asset); | ||
| if (payloadV1.network !== requirements.network) { | ||
@@ -517,4 +948,4 @@ return { | ||
| if (!bytecode || bytecode === "0x") { | ||
| const erc6492Data = (0, import_viem3.parseErc6492Signature)(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem3.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000"); | ||
| const erc6492Data = (0, import_viem5.parseErc6492Signature)(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem5.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000"); | ||
| if (!hasDeploymentInfo) { | ||
@@ -542,3 +973,3 @@ return { | ||
| } | ||
| if ((0, import_viem3.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem3.getAddress)(requirements.payTo)) { | ||
| if ((0, import_viem5.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem5.getAddress)(requirements.payTo)) { | ||
| return { | ||
@@ -576,2 +1007,3 @@ 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 | ||
@@ -616,5 +1048,5 @@ }; | ||
| try { | ||
| const parseResult = (0, import_viem3.parseErc6492Signature)(exactEvmPayload.signature); | ||
| const parseResult = (0, import_viem5.parseErc6492Signature)(exactEvmPayload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem3.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem5.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| const payerAddress = exactEvmPayload.authorization.from; | ||
@@ -643,10 +1075,10 @@ const bytecode = await this.signer.getCode({ address: payerAddress }); | ||
| if (isECDSA) { | ||
| const parsedSig = (0, import_viem3.parseSignature)(signature); | ||
| const parsedSig = (0, import_viem5.parseSignature)(signature); | ||
| tx = await this.signer.writeContract({ | ||
| address: (0, import_viem3.getAddress)(requirements.asset), | ||
| address: (0, import_viem5.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.to), | ||
| (0, import_viem5.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem5.getAddress)(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
@@ -663,8 +1095,8 @@ BigInt(exactEvmPayload.authorization.validAfter), | ||
| tx = await this.signer.writeContract({ | ||
| address: (0, import_viem3.getAddress)(requirements.asset), | ||
| address: (0, import_viem5.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.to), | ||
| (0, import_viem5.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem5.getAddress)(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
@@ -707,24 +1139,2 @@ BigInt(exactEvmPayload.authorization.validAfter), | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem4 = require("viem"); | ||
| // src/v1/index.ts | ||
| var NETWORKS = [ | ||
| "abstract", | ||
| "abstract-testnet", | ||
| "base-sepolia", | ||
| "base", | ||
| "avalanche-fuji", | ||
| "avalanche", | ||
| "iotex", | ||
| "sei", | ||
| "sei-testnet", | ||
| "polygon", | ||
| "polygon-amoy", | ||
| "peaq", | ||
| "story", | ||
| "educhain", | ||
| "skale-base-sepolia" | ||
| ]; | ||
| // src/exact/facilitator/register.ts | ||
@@ -740,3 +1150,3 @@ function registerExactEvmScheme(facilitator, config) { | ||
| NETWORKS, | ||
| new ExactEvmSchemeV1(config.signer, { | ||
| new ExactEvmSchemeV12(config.signer, { | ||
| deployERC4337WithEIP6492: config.deployERC4337WithEIP6492 | ||
@@ -743,0 +1153,0 @@ }) |
@@ -28,3 +28,3 @@ "use strict"; | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem2 = require("viem"); | ||
| var import_viem3 = require("viem"); | ||
@@ -44,21 +44,47 @@ // src/constants.ts | ||
| // src/utils.ts | ||
| var import_viem2 = require("viem"); | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var import_viem = require("viem"); | ||
| // 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 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| // src/utils.ts | ||
| function getEvmChainId(network) { | ||
| const networkMap = { | ||
| base: 8453, | ||
| "base-sepolia": 84532, | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002 | ||
| }; | ||
| return networkMap[network] || 1; | ||
| const chainId = EVM_NETWORK_CHAIN_ID_MAP[network]; | ||
| if (!chainId) { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
| return chainId; | ||
| } | ||
| function createNonce() { | ||
| const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto; | ||
| function getCrypto() { | ||
| const cryptoObj = globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return (0, import_viem.toHex)(cryptoObj.getRandomValues(new Uint8Array(32))); | ||
| return cryptoObj; | ||
| } | ||
| function createNonce() { | ||
| return (0, import_viem2.toHex)(getCrypto().getRandomValues(new Uint8Array(32))); | ||
| } | ||
@@ -89,3 +115,3 @@ // src/exact/v1/client/scheme.ts | ||
| from: this.signer.address, | ||
| to: (0, import_viem2.getAddress)(selectedV1.payTo), | ||
| to: (0, import_viem3.getAddress)(selectedV1.payTo), | ||
| value: selectedV1.maxAmountRequired, | ||
@@ -128,7 +154,7 @@ validAfter: (now - 600).toString(), | ||
| chainId, | ||
| verifyingContract: (0, import_viem2.getAddress)(requirements.asset) | ||
| verifyingContract: (0, import_viem3.getAddress)(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: (0, import_viem2.getAddress)(authorization.from), | ||
| to: (0, import_viem2.getAddress)(authorization.to), | ||
| from: (0, import_viem3.getAddress)(authorization.from), | ||
| to: (0, import_viem3.getAddress)(authorization.to), | ||
| value: BigInt(authorization.value), | ||
@@ -135,0 +161,0 @@ validAfter: BigInt(authorization.validAfter), |
@@ -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"],"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\";\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);\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// 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","import { toHex } from \"viem\";\nimport { Network } from \"@x402/core/types\";\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 */\nexport function getEvmChainId(network: Network): number {\n const networkMap: Record<string, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n ethereum: 1,\n sepolia: 11155111,\n polygon: 137,\n \"polygon-amoy\": 80002,\n };\n return networkMap[network] || 1;\n}\n\n/**\n * Create a random 32-byte nonce for authorization\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n // Use dynamic import to avoid require() in ESM context\n const cryptoObj =\n typeof globalThis.crypto !== \"undefined\"\n ? globalThis.crypto\n : (globalThis as { crypto?: Crypto }).crypto;\n\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n\n return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACOA,IAAAA,eAA2B;;;ACNpB,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;;;ACVA,kBAAsB;AAUf,SAAS,cAAc,SAA0B;AACtD,QAAM,aAAqC;AAAA,IACzC,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,gBAAgB;AAAA,EAClB;AACA,SAAO,WAAW,OAAO,KAAK;AAChC;AAOO,SAAS,cAA6B;AAE3C,QAAM,YACJ,OAAO,WAAW,WAAW,cACzB,WAAW,SACV,WAAmC;AAE1C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,aAAO,mBAAM,UAAU,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC;AAC5D;;;AFvBO,IAAM,mBAAN,MAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3D,YAA6B,QAAyB;AAAzB;AAP7B,SAAS,SAAS;AAAA,EAOqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvD,MAAM,qBACJ,aACA,qBAGA;AACA,UAAM,aAAa;AACnB,UAAM,QAAQ,YAAY;AAC1B,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAExC,UAAM,gBAAoD;AAAA,MACxD,MAAM,KAAK,OAAO;AAAA,MAClB,QAAI,yBAAW,WAAW,KAAK;AAAA,MAC/B,OAAO,WAAW;AAAA,MAClB,aAAa,MAAM,KAAK,SAAS;AAAA;AAAA,MACjC,cAAc,MAAM,WAAW,mBAAmB,SAAS;AAAA,MAC3D;AAAA,IACF;AAGA,UAAM,YAAY,MAAM,KAAK,kBAAkB,eAAe,UAAU;AAExE,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,SAAS,WAAW;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBACZ,eACA,cACwB;AACxB,UAAM,UAAU,cAAc,aAAa,OAAO;AAElD,QAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,YAAM,IAAI;AAAA,QACR,4FAA4F,aAAa,KAAK;AAAA,MAChH;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AAEvC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAmB,yBAAW,aAAa,KAAK;AAAA,IAClD;AAEA,UAAM,UAAU;AAAA,MACd,UAAM,yBAAW,cAAc,IAAI;AAAA,MACnC,QAAI,yBAAW,cAAc,EAAE;AAAA,MAC/B,OAAO,OAAO,cAAc,KAAK;AAAA,MACjC,YAAY,OAAO,cAAc,UAAU;AAAA,MAC3C,aAAa,OAAO,cAAc,WAAW;AAAA,MAC7C,OAAO,cAAc;AAAA,IACvB;AAEA,WAAO,MAAM,KAAK,OAAO,cAAc;AAAA,MACrC;AAAA,MACA,OAAO;AAAA,MACP,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":["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 * 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} 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"]} |
@@ -23,3 +23,3 @@ "use strict"; | ||
| __export(facilitator_exports, { | ||
| ExactEvmSchemeV1: () => ExactEvmSchemeV1 | ||
| ExactEvmSchemeV1: () => ExactEvmSchemeV12 | ||
| }); | ||
@@ -29,3 +29,3 @@ module.exports = __toCommonJS(facilitator_exports); | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var import_viem2 = require("viem"); | ||
| var import_viem3 = require("viem"); | ||
@@ -93,17 +93,40 @@ // src/constants.ts | ||
| // src/utils.ts | ||
| var import_viem2 = require("viem"); | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem = require("viem"); | ||
| // 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 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| // src/utils.ts | ||
| function getEvmChainId(network) { | ||
| const networkMap = { | ||
| base: 8453, | ||
| "base-sepolia": 84532, | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002 | ||
| }; | ||
| return networkMap[network] || 1; | ||
| const chainId = EVM_NETWORK_CHAIN_ID_MAP[network]; | ||
| if (!chainId) { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
| return chainId; | ||
| } | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var ExactEvmSchemeV1 = class { | ||
| var ExactEvmSchemeV12 = class { | ||
| /** | ||
@@ -161,3 +184,12 @@ * Creates a new ExactEvmFacilitatorV1 instance. | ||
| } | ||
| const chainId = getEvmChainId(payloadV1.network); | ||
| 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) { | ||
@@ -171,3 +203,3 @@ return { | ||
| const { name, version } = requirements.extra; | ||
| const erc20Address = (0, import_viem2.getAddress)(requirements.asset); | ||
| const erc20Address = (0, import_viem3.getAddress)(requirements.asset); | ||
| if (payloadV1.network !== requirements.network) { | ||
@@ -219,4 +251,4 @@ return { | ||
| if (!bytecode || bytecode === "0x") { | ||
| const erc6492Data = (0, import_viem2.parseErc6492Signature)(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem2.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000"); | ||
| const erc6492Data = (0, import_viem3.parseErc6492Signature)(signature); | ||
| const hasDeploymentInfo = erc6492Data.address && erc6492Data.data && !(0, import_viem3.isAddressEqual)(erc6492Data.address, "0x0000000000000000000000000000000000000000"); | ||
| if (!hasDeploymentInfo) { | ||
@@ -244,3 +276,3 @@ return { | ||
| } | ||
| if ((0, import_viem2.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem2.getAddress)(requirements.payTo)) { | ||
| if ((0, import_viem3.getAddress)(exactEvmPayload.authorization.to) !== (0, import_viem3.getAddress)(requirements.payTo)) { | ||
| return { | ||
@@ -278,2 +310,3 @@ 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 | ||
@@ -318,5 +351,5 @@ }; | ||
| try { | ||
| const parseResult = (0, import_viem2.parseErc6492Signature)(exactEvmPayload.signature); | ||
| const parseResult = (0, import_viem3.parseErc6492Signature)(exactEvmPayload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem2.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| if (this.config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !(0, import_viem3.isAddressEqual)(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| const payerAddress = exactEvmPayload.authorization.from; | ||
@@ -345,10 +378,10 @@ const bytecode = await this.signer.getCode({ address: payerAddress }); | ||
| if (isECDSA) { | ||
| const parsedSig = (0, import_viem2.parseSignature)(signature); | ||
| const parsedSig = (0, import_viem3.parseSignature)(signature); | ||
| tx = await this.signer.writeContract({ | ||
| address: (0, import_viem2.getAddress)(requirements.asset), | ||
| address: (0, import_viem3.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem2.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem2.getAddress)(exactEvmPayload.authorization.to), | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
@@ -365,8 +398,8 @@ BigInt(exactEvmPayload.authorization.validAfter), | ||
| tx = await this.signer.writeContract({ | ||
| address: (0, import_viem2.getAddress)(requirements.asset), | ||
| address: (0, import_viem3.getAddress)(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| (0, import_viem2.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem2.getAddress)(exactEvmPayload.authorization.to), | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.from), | ||
| (0, import_viem3.getAddress)(exactEvmPayload.authorization.to), | ||
| BigInt(exactEvmPayload.authorization.value), | ||
@@ -373,0 +406,0 @@ BigInt(exactEvmPayload.authorization.validAfter), |
@@ -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"],"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\";\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 const chainId = getEvmChainId(payloadV1.network);\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 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// 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","import { toHex } from \"viem\";\nimport { Network } from \"@x402/core/types\";\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 */\nexport function getEvmChainId(network: Network): number {\n const networkMap: Record<string, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n ethereum: 1,\n sepolia: 11155111,\n polygon: 137,\n \"polygon-amoy\": 80002,\n };\n return networkMap[network] || 1;\n}\n\n/**\n * Create a random 32-byte nonce for authorization\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n // Use dynamic import to avoid require() in ESM context\n const cryptoObj =\n typeof globalThis.crypto !== \"undefined\"\n ? globalThis.crypto\n : (globalThis as { crypto?: Crypto }).crypto;\n\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n\n return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));\n}\n"],"mappings":"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","names":["import_viem"]} | ||
| {"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} 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"]} |
+458
-31
@@ -1,36 +0,463 @@ | ||
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayload } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from './signer-5OVDxViv.js'; | ||
| export { 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-BYv82va2.js'; | ||
| export { C as ClientEvmSigner, F as FacilitatorEvmSigner, t as toClientEvmSigner, a as toFacilitatorEvmSigner } from './signer-5OVDxViv.js'; | ||
| import '@x402/core/types'; | ||
| /** | ||
| * EVM client implementation for the Exact payment scheme. | ||
| * Asset transfer methods for the exact EVM scheme. | ||
| * - eip3009: Uses transferWithAuthorization (USDC, etc.) - recommended for compatible tokens | ||
| * - permit2: Uses Permit2 + x402Permit2Proxy - universal fallback for any ERC-20 | ||
| */ | ||
| type AssetTransferMethod = "eip3009" | "permit2"; | ||
| /** | ||
| * EIP-3009 payload for tokens with native transferWithAuthorization support. | ||
| */ | ||
| type ExactEIP3009Payload = { | ||
| signature?: `0x${string}`; | ||
| authorization: { | ||
| from: `0x${string}`; | ||
| to: `0x${string}`; | ||
| value: string; | ||
| validAfter: string; | ||
| validBefore: string; | ||
| nonce: `0x${string}`; | ||
| }; | ||
| }; | ||
| /** | ||
| * Permit2 witness data structure. | ||
| * Matches the Witness struct in x402Permit2Proxy contract. | ||
| * Note: Upper time bound is enforced by Permit2's `deadline` field, not a witness field. | ||
| */ | ||
| type Permit2Witness = { | ||
| to: `0x${string}`; | ||
| validAfter: string; | ||
| extra: `0x${string}`; | ||
| }; | ||
| /** | ||
| * Permit2 authorization parameters. | ||
| * Used to reconstruct the signed message for verification. | ||
| */ | ||
| type Permit2Authorization = { | ||
| permitted: { | ||
| token: `0x${string}`; | ||
| amount: string; | ||
| }; | ||
| spender: `0x${string}`; | ||
| nonce: string; | ||
| deadline: string; | ||
| witness: Permit2Witness; | ||
| }; | ||
| /** | ||
| * Permit2 payload for tokens using the Permit2 + x402Permit2Proxy flow. | ||
| */ | ||
| type ExactPermit2Payload = { | ||
| signature: `0x${string}`; | ||
| permit2Authorization: Permit2Authorization & { | ||
| from: `0x${string}`; | ||
| }; | ||
| }; | ||
| type ExactEvmPayloadV1 = ExactEIP3009Payload; | ||
| type ExactEvmPayloadV2 = ExactEIP3009Payload | ExactPermit2Payload; | ||
| /** | ||
| * Type guard to check if a payload is a Permit2 payload. | ||
| * Permit2 payloads have a `permit2Authorization` field. | ||
| * | ||
| * @param payload - The payload to check. | ||
| * @returns True if the payload is a Permit2 payload, false otherwise. | ||
| */ | ||
| 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. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload | ||
| */ | ||
| createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements): Promise<Pick<PaymentPayload, "x402Version" | "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 | ||
| */ | ||
| private signAuthorization; | ||
| } | ||
| declare function isPermit2Payload(payload: ExactEvmPayloadV2): payload is ExactPermit2Payload; | ||
| /** | ||
| * Type guard to check if a payload is an EIP-3009 payload. | ||
| * EIP-3009 payloads have an `authorization` field. | ||
| * | ||
| * @param payload - The payload to check. | ||
| * @returns True if the payload is an EIP-3009 payload, false otherwise. | ||
| */ | ||
| declare function isEIP3009Payload(payload: ExactEvmPayloadV2): payload is ExactEIP3009Payload; | ||
| export { ClientEvmSigner, ExactEvmScheme }; | ||
| declare const authorizationTypes: { | ||
| readonly TransferWithAuthorization: readonly [{ | ||
| readonly name: "from"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validBefore"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "bytes32"; | ||
| }]; | ||
| }; | ||
| /** | ||
| * Permit2 EIP-712 types for signing PermitWitnessTransferFrom. | ||
| * Must match the exact format expected by the Permit2 contract. | ||
| * Note: Types must be in ALPHABETICAL order after the primary type (TokenPermissions < Witness). | ||
| */ | ||
| declare const permit2WitnessTypes: { | ||
| readonly PermitWitnessTransferFrom: readonly [{ | ||
| readonly name: "permitted"; | ||
| readonly type: "TokenPermissions"; | ||
| }, { | ||
| readonly name: "spender"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "witness"; | ||
| readonly type: "Witness"; | ||
| }]; | ||
| readonly TokenPermissions: readonly [{ | ||
| readonly name: "token"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "amount"; | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly Witness: readonly [{ | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "extra"; | ||
| readonly type: "bytes"; | ||
| }]; | ||
| }; | ||
| declare const eip3009ABI: readonly [{ | ||
| readonly inputs: readonly [{ | ||
| readonly name: "from"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validBefore"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "bytes32"; | ||
| }, { | ||
| readonly name: "v"; | ||
| readonly type: "uint8"; | ||
| }, { | ||
| readonly name: "r"; | ||
| readonly type: "bytes32"; | ||
| }, { | ||
| readonly name: "s"; | ||
| readonly type: "bytes32"; | ||
| }]; | ||
| readonly name: "transferWithAuthorization"; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| readonly type: "function"; | ||
| }, { | ||
| readonly inputs: readonly [{ | ||
| readonly name: "from"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validBefore"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "bytes32"; | ||
| }, { | ||
| readonly name: "signature"; | ||
| readonly type: "bytes"; | ||
| }]; | ||
| readonly name: "transferWithAuthorization"; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| readonly type: "function"; | ||
| }, { | ||
| readonly inputs: readonly [{ | ||
| readonly name: "account"; | ||
| readonly type: "address"; | ||
| }]; | ||
| readonly name: "balanceOf"; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| readonly type: "function"; | ||
| }, { | ||
| readonly inputs: readonly []; | ||
| readonly name: "version"; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "string"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| readonly type: "function"; | ||
| }]; | ||
| /** | ||
| * Canonical Permit2 contract address. | ||
| * Same address on all EVM chains via CREATE2 deployment. | ||
| * | ||
| * @see https://github.com/Uniswap/permit2 | ||
| */ | ||
| declare const PERMIT2_ADDRESS: "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| /** | ||
| * x402ExactPermit2Proxy contract address. | ||
| * Vanity address: 0x4020...0001 for easy recognition. | ||
| * This address is deterministic based on: | ||
| * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C) | ||
| * - Vanity-mined salt for prefix 0x4020 and suffix 0001 | ||
| * - Contract bytecode + constructor args (PERMIT2_ADDRESS) | ||
| */ | ||
| declare const x402ExactPermit2ProxyAddress: "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| /** | ||
| * x402UptoPermit2Proxy contract address. | ||
| * Vanity address: 0x4020...0002 for easy recognition. | ||
| * This address is deterministic based on: | ||
| * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C) | ||
| * - Vanity-mined salt for prefix 0x4020 and suffix 0002 | ||
| * - Contract bytecode + constructor args (PERMIT2_ADDRESS) | ||
| */ | ||
| declare const x402UptoPermit2ProxyAddress: "0x4020633461b2895a48930Ff97eE8fCdE8E520002"; | ||
| /** | ||
| * x402ExactPermit2Proxy ABI - settle function for exact payment scheme. | ||
| */ | ||
| declare const x402ExactPermit2ProxyABI: readonly [{ | ||
| readonly type: "function"; | ||
| readonly name: "PERMIT2"; | ||
| readonly inputs: readonly []; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "address"; | ||
| readonly internalType: "contract ISignatureTransfer"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "WITNESS_TYPEHASH"; | ||
| readonly inputs: readonly []; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "bytes32"; | ||
| readonly internalType: "bytes32"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "WITNESS_TYPE_STRING"; | ||
| readonly inputs: readonly []; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "string"; | ||
| readonly internalType: "string"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "initialize"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "_permit2"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }]; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "settle"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "permit"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.PermitTransferFrom"; | ||
| readonly components: readonly [{ | ||
| readonly name: "permitted"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.TokenPermissions"; | ||
| readonly components: readonly [{ | ||
| readonly name: "token"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "amount"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "witness"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct x402BasePermit2Proxy.Witness"; | ||
| readonly components: readonly [{ | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "extra"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| }, { | ||
| readonly name: "signature"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "settleWithPermit"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "permit2612"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct x402BasePermit2Proxy.EIP2612Permit"; | ||
| readonly components: readonly [{ | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "r"; | ||
| readonly type: "bytes32"; | ||
| readonly internalType: "bytes32"; | ||
| }, { | ||
| readonly name: "s"; | ||
| readonly type: "bytes32"; | ||
| readonly internalType: "bytes32"; | ||
| }, { | ||
| readonly name: "v"; | ||
| readonly type: "uint8"; | ||
| readonly internalType: "uint8"; | ||
| }]; | ||
| }, { | ||
| readonly name: "permit"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.PermitTransferFrom"; | ||
| readonly components: readonly [{ | ||
| readonly name: "permitted"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.TokenPermissions"; | ||
| readonly components: readonly [{ | ||
| readonly name: "token"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "amount"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "witness"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct x402BasePermit2Proxy.Witness"; | ||
| readonly components: readonly [{ | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "extra"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| }, { | ||
| readonly name: "signature"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| }, { | ||
| readonly type: "event"; | ||
| readonly name: "Settled"; | ||
| readonly inputs: readonly []; | ||
| readonly anonymous: false; | ||
| }, { | ||
| readonly type: "event"; | ||
| readonly name: "SettledWithPermit"; | ||
| readonly inputs: readonly []; | ||
| readonly anonymous: false; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "AlreadyInitialized"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "InvalidDestination"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "InvalidOwner"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "InvalidPermit2Address"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "PaymentTooEarly"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "ReentrancyGuardReentrantCall"; | ||
| readonly inputs: readonly []; | ||
| }]; | ||
| export { type AssetTransferMethod, type ExactEIP3009Payload, type ExactEvmPayloadV1, type ExactEvmPayloadV2, type ExactPermit2Payload, PERMIT2_ADDRESS, type Permit2Authorization, type Permit2Witness, authorizationTypes, eip3009ABI, isEIP3009Payload, isPermit2Payload, permit2WitnessTypes, x402ExactPermit2ProxyABI, x402ExactPermit2ProxyAddress, x402UptoPermit2ProxyAddress }; |
+438
-63
@@ -24,9 +24,21 @@ "use strict"; | ||
| ExactEvmScheme: () => ExactEvmScheme, | ||
| PERMIT2_ADDRESS: () => PERMIT2_ADDRESS, | ||
| authorizationTypes: () => authorizationTypes, | ||
| createPermit2ApprovalTx: () => createPermit2ApprovalTx, | ||
| eip3009ABI: () => eip3009ABI, | ||
| erc20AllowanceAbi: () => erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams: () => getPermit2AllowanceReadParams, | ||
| isEIP3009Payload: () => isEIP3009Payload, | ||
| isPermit2Payload: () => isPermit2Payload, | ||
| permit2WitnessTypes: () => permit2WitnessTypes, | ||
| toClientEvmSigner: () => toClientEvmSigner, | ||
| toFacilitatorEvmSigner: () => toFacilitatorEvmSigner | ||
| toFacilitatorEvmSigner: () => toFacilitatorEvmSigner, | ||
| x402ExactPermit2ProxyABI: () => x402ExactPermit2ProxyABI, | ||
| x402ExactPermit2ProxyAddress: () => x402ExactPermit2ProxyAddress, | ||
| x402UptoPermit2ProxyAddress: () => x402UptoPermit2ProxyAddress | ||
| }); | ||
| module.exports = __toCommonJS(src_exports); | ||
| // src/exact/client/scheme.ts | ||
| var import_viem2 = require("viem"); | ||
| // src/exact/client/eip3009.ts | ||
| var import_viem4 = require("viem"); | ||
@@ -44,13 +56,406 @@ // src/constants.ts | ||
| }; | ||
| 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 | ||
| var import_viem3 = require("viem"); | ||
| // src/exact/v1/client/scheme.ts | ||
| var import_viem = require("viem"); | ||
| function createNonce() { | ||
| const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto; | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| var import_viem2 = require("viem"); | ||
| // 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 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| // src/utils.ts | ||
| function getCrypto() { | ||
| const cryptoObj = globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return (0, import_viem.toHex)(cryptoObj.getRandomValues(new Uint8Array(32))); | ||
| return cryptoObj; | ||
| } | ||
| function createNonce() { | ||
| return (0, import_viem3.toHex)(getCrypto().getRandomValues(new Uint8Array(32))); | ||
| } | ||
| function createPermit2Nonce() { | ||
| const randomBytes = getCrypto().getRandomValues(new Uint8Array(32)); | ||
| return BigInt((0, import_viem3.toHex)(randomBytes)).toString(); | ||
| } | ||
| // src/exact/client/eip3009.ts | ||
| async function createEIP3009Payload(signer, x402Version, paymentRequirements) { | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: signer.address, | ||
| to: (0, import_viem4.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: (0, import_viem4.getAddress)(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: (0, import_viem4.getAddress)(authorization.from), | ||
| to: (0, import_viem4.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 | ||
| var import_viem5 = require("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: (0, import_viem5.getAddress)(paymentRequirements.asset), | ||
| amount: paymentRequirements.amount | ||
| }, | ||
| spender: x402ExactPermit2ProxyAddress, | ||
| nonce, | ||
| deadline, | ||
| witness: { | ||
| to: (0, import_viem5.getAddress)(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: (0, import_viem5.getAddress)(permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Authorization.permitted.amount) | ||
| }, | ||
| spender: (0, import_viem5.getAddress)(permit2Authorization.spender), | ||
| nonce: BigInt(permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Authorization.deadline), | ||
| witness: { | ||
| to: (0, import_viem5.getAddress)(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 = (0, import_viem5.encodeFunctionData)({ | ||
| abi: erc20ApproveAbi, | ||
| functionName: "approve", | ||
| args: [PERMIT2_ADDRESS, MAX_UINT256] | ||
| }); | ||
| return { | ||
| to: (0, import_viem5.getAddress)(tokenAddress), | ||
| data | ||
| }; | ||
| } | ||
| function getPermit2AllowanceReadParams(params) { | ||
| return { | ||
| address: (0, import_viem5.getAddress)(params.tokenAddress), | ||
| abi: erc20AllowanceAbi, | ||
| functionName: "allowance", | ||
| args: [(0, import_viem5.getAddress)(params.ownerAddress), PERMIT2_ADDRESS] | ||
| }; | ||
| } | ||
| // src/exact/client/scheme.ts | ||
@@ -69,64 +474,14 @@ var ExactEvmScheme = class { | ||
| * 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 | ||
| * @returns Promise resolving to a payment payload result | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: this.signer.address, | ||
| to: (0, import_viem2.getAddress)(paymentRequirements.payTo), | ||
| value: paymentRequirements.amount, | ||
| validAfter: (now - 600).toString(), | ||
| // 10 minutes before | ||
| validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await this.signAuthorization(authorization, paymentRequirements); | ||
| const payload = { | ||
| authorization, | ||
| signature | ||
| }; | ||
| return { | ||
| x402Version, | ||
| 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 = 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 assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009"; | ||
| if (assetTransferMethod === "permit2") { | ||
| return createPermit2Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const domain = { | ||
| name, | ||
| version, | ||
| chainId, | ||
| verifyingContract: (0, import_viem2.getAddress)(requirements.asset) | ||
| }; | ||
| const message = { | ||
| from: (0, import_viem2.getAddress)(authorization.from), | ||
| to: (0, import_viem2.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 | ||
| }); | ||
| return createEIP3009Payload(this.signer, x402Version, paymentRequirements); | ||
| } | ||
@@ -145,8 +500,28 @@ }; | ||
| } | ||
| // src/types.ts | ||
| function isPermit2Payload(payload) { | ||
| return "permit2Authorization" in payload; | ||
| } | ||
| function isEIP3009Payload(payload) { | ||
| return "authorization" in payload; | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| ExactEvmScheme, | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| createPermit2ApprovalTx, | ||
| eip3009ABI, | ||
| erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams, | ||
| isEIP3009Payload, | ||
| isPermit2Payload, | ||
| permit2WitnessTypes, | ||
| toClientEvmSigner, | ||
| toFacilitatorEvmSigner | ||
| toFacilitatorEvmSigner, | ||
| x402ExactPermit2ProxyABI, | ||
| x402ExactPermit2ProxyAddress, | ||
| x402UptoPermit2ProxyAddress | ||
| }); | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/index.ts","../../src/exact/client/scheme.ts","../../src/constants.ts","../../src/utils.ts","../../src/signer.ts"],"sourcesContent":["/**\n * @module @x402/evm - x402 Payment Protocol EVM Implementation\n *\n * This module provides the EVM-specific implementation of the x402 payment protocol.\n */\n\n// Export EVM implementation modules here\n// The actual implementation logic will be added by copying from the core/src/schemes/evm folder\n\nexport { ExactEvmScheme } from \"./exact\";\nexport { toClientEvmSigner, toFacilitatorEvmSigner } from \"./signer\";\nexport type { ClientEvmSigner, FacilitatorEvmSigner } from \"./signer\";\n","import { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmPayloadV2 } from \"../../types\";\nimport { createNonce } from \"../../utils\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n *\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 *\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<Pick<PaymentPayload, \"x402Version\" | \"payload\">> {\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEvmPayloadV2[\"authorization\"] = {\n from: this.signer.address,\n to: getAddress(paymentRequirements.payTo),\n value: paymentRequirements.amount,\n validAfter: (now - 600).toString(), // 10 minutes before\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n // Sign the authorization\n const signature = await this.signAuthorization(authorization, paymentRequirements);\n\n const payload: ExactEvmPayloadV2 = {\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 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: ExactEvmPayloadV2[\"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 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// 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","import { toHex } from \"viem\";\nimport { Network } from \"@x402/core/types\";\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 */\nexport function getEvmChainId(network: Network): number {\n const networkMap: Record<string, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n ethereum: 1,\n sepolia: 11155111,\n polygon: 137,\n \"polygon-amoy\": 80002,\n };\n return networkMap[network] || 1;\n}\n\n/**\n * Create a random 32-byte nonce for authorization\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n // Use dynamic import to avoid require() in ESM context\n const cryptoObj =\n typeof globalThis.crypto !== \"undefined\"\n ? globalThis.crypto\n : (globalThis as { crypto?: Crypto }).crypto;\n\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n\n return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));\n}\n","/**\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,IAAAA,eAA2B;;;ACApB,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;;;ACVA,kBAAsB;AA2Bf,SAAS,cAA6B;AAE3C,QAAM,YACJ,OAAO,WAAW,WAAW,cACzB,WAAW,SACV,WAAmC;AAE1C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,aAAO,mBAAM,UAAU,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC;AAC5D;;;AF5BO,IAAM,iBAAN,MAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzD,YAA6B,QAAyB;AAAzB;AAP7B,SAAS,SAAS;AAAA,EAOqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvD,MAAM,qBACJ,aACA,qBAC0D;AAC1D,UAAM,QAAQ,YAAY;AAC1B,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAExC,UAAM,gBAAoD;AAAA,MACxD,MAAM,KAAK,OAAO;AAAA,MAClB,QAAI,yBAAW,oBAAoB,KAAK;AAAA,MACxC,OAAO,oBAAoB;AAAA,MAC3B,aAAa,MAAM,KAAK,SAAS;AAAA;AAAA,MACjC,cAAc,MAAM,oBAAoB,mBAAmB,SAAS;AAAA,MACpE;AAAA,IACF;AAGA,UAAM,YAAY,MAAM,KAAK,kBAAkB,eAAe,mBAAmB;AAEjF,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBACZ,eACA,cACwB;AACxB,UAAM,UAAU,SAAS,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAE3D,QAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,YAAM,IAAI;AAAA,QACR,4FAA4F,aAAa,KAAK;AAAA,MAChH;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AAEvC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,uBAAmB,yBAAW,aAAa,KAAK;AAAA,IAClD;AAEA,UAAM,UAAU;AAAA,MACd,UAAM,yBAAW,cAAc,IAAI;AAAA,MACnC,QAAI,yBAAW,cAAc,EAAE;AAAA,MAC/B,OAAO,OAAO,cAAc,KAAK;AAAA,MACjC,YAAY,OAAO,cAAc,UAAU;AAAA,MAC3C,aAAa,OAAO,cAAc,WAAW;AAAA,MAC7C,OAAO,cAAc;AAAA,IACvB;AAEA,WAAO,MAAM,KAAK,OAAO,cAAc;AAAA,MACrC;AAAA,MACA,OAAO;AAAA,MACP,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AG1CO,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":["import_viem"]} | ||
| {"version":3,"sources":["../../src/index.ts","../../src/exact/client/eip3009.ts","../../src/constants.ts","../../src/utils.ts","../../src/exact/v1/client/scheme.ts","../../src/exact/v1/facilitator/scheme.ts","../../src/v1/index.ts","../../src/exact/client/permit2.ts","../../src/exact/client/scheme.ts","../../src/signer.ts","../../src/types.ts"],"sourcesContent":["/**\n * @module @x402/evm - x402 Payment Protocol EVM Implementation\n *\n * This module provides the EVM-specific implementation of the x402 payment protocol.\n */\n\n// Exact scheme client\nexport { ExactEvmScheme } from \"./exact\";\nexport {\n createPermit2ApprovalTx,\n getPermit2AllowanceReadParams,\n erc20AllowanceAbi,\n type Permit2AllowanceParams,\n} from \"./exact/client\";\n\n// Signers\nexport { toClientEvmSigner, toFacilitatorEvmSigner } from \"./signer\";\nexport type { ClientEvmSigner, FacilitatorEvmSigner } from \"./signer\";\n\n// Types\nexport type {\n AssetTransferMethod,\n ExactEIP3009Payload,\n ExactPermit2Payload,\n ExactEvmPayloadV1,\n ExactEvmPayloadV2,\n Permit2Witness,\n Permit2Authorization,\n} from \"./types\";\nexport { isPermit2Payload, isEIP3009Payload } from \"./types\";\n\n// Constants\nexport {\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n x402UptoPermit2ProxyAddress,\n permit2WitnessTypes,\n authorizationTypes,\n eip3009ABI,\n x402ExactPermit2ProxyABI,\n} from \"./constants\";\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","// 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","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} 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 { 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","/**\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","/**\n * Asset transfer methods for the exact EVM scheme.\n * - eip3009: Uses transferWithAuthorization (USDC, etc.) - recommended for compatible tokens\n * - permit2: Uses Permit2 + x402Permit2Proxy - universal fallback for any ERC-20\n */\nexport type AssetTransferMethod = \"eip3009\" | \"permit2\";\n\n/**\n * EIP-3009 payload for tokens with native transferWithAuthorization support.\n */\nexport type ExactEIP3009Payload = {\n signature?: `0x${string}`;\n authorization: {\n from: `0x${string}`;\n to: `0x${string}`;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: `0x${string}`;\n };\n};\n\n/**\n * Permit2 witness data structure.\n * Matches the Witness struct in x402Permit2Proxy contract.\n * Note: Upper time bound is enforced by Permit2's `deadline` field, not a witness field.\n */\nexport type Permit2Witness = {\n to: `0x${string}`;\n validAfter: string;\n extra: `0x${string}`;\n};\n\n/**\n * Permit2 authorization parameters.\n * Used to reconstruct the signed message for verification.\n */\nexport type Permit2Authorization = {\n permitted: {\n token: `0x${string}`;\n amount: string;\n };\n spender: `0x${string}`;\n nonce: string;\n deadline: string;\n witness: Permit2Witness;\n};\n\n/**\n * Permit2 payload for tokens using the Permit2 + x402Permit2Proxy flow.\n */\nexport type ExactPermit2Payload = {\n signature: `0x${string}`;\n permit2Authorization: Permit2Authorization & {\n from: `0x${string}`;\n };\n};\n\nexport type ExactEvmPayloadV1 = ExactEIP3009Payload;\n\nexport type ExactEvmPayloadV2 = ExactEIP3009Payload | ExactPermit2Payload;\n\n/**\n * Type guard to check if a payload is a Permit2 payload.\n * Permit2 payloads have a `permit2Authorization` field.\n *\n * @param payload - The payload to check.\n * @returns True if the payload is a Permit2 payload, false otherwise.\n */\nexport function isPermit2Payload(payload: ExactEvmPayloadV2): payload is ExactPermit2Payload {\n return \"permit2Authorization\" in payload;\n}\n\n/**\n * Type guard to check if a payload is an EIP-3009 payload.\n * EIP-3009 payloads have an `authorization` field.\n *\n * @param payload - The payload to check.\n * @returns True if the payload is an EIP-3009 payload, false otherwise.\n */\nexport function isEIP3009Payload(payload: ExactEvmPayloadV2): payload is ExactEIP3009Payload {\n return \"authorization\" in payload;\n}\n"],"mappings":"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","names":["import_viem","import_viem","import_viem","import_viem"]} |
@@ -5,4 +5,24 @@ export { ExactEvmSchemeV1 } from '../exact/v1/client/index.js'; | ||
| declare const EVM_NETWORK_CHAIN_ID_MAP: { | ||
| readonly ethereum: 1; | ||
| readonly sepolia: 11155111; | ||
| readonly abstract: 2741; | ||
| readonly "abstract-testnet": 11124; | ||
| readonly "base-sepolia": 84532; | ||
| readonly base: 8453; | ||
| readonly "avalanche-fuji": 43113; | ||
| readonly avalanche: 43114; | ||
| readonly iotex: 4689; | ||
| readonly sei: 1329; | ||
| readonly "sei-testnet": 1328; | ||
| readonly polygon: 137; | ||
| readonly "polygon-amoy": 80002; | ||
| readonly peaq: 3338; | ||
| readonly story: 1514; | ||
| readonly educhain: 41923; | ||
| readonly "skale-base-sepolia": 324705682; | ||
| }; | ||
| type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP; | ||
| declare const NETWORKS: string[]; | ||
| export { NETWORKS }; | ||
| export { EVM_NETWORK_CHAIN_ID_MAP, type EvmNetworkV1, NETWORKS }; |
+33
-29
@@ -23,2 +23,3 @@ "use strict"; | ||
| __export(v1_exports, { | ||
| EVM_NETWORK_CHAIN_ID_MAP: () => EVM_NETWORK_CHAIN_ID_MAP, | ||
| ExactEvmSchemeV1: () => ExactEvmSchemeV1, | ||
@@ -47,19 +48,18 @@ NETWORKS: () => NETWORKS | ||
| function getEvmChainId(network) { | ||
| const networkMap = { | ||
| base: 8453, | ||
| "base-sepolia": 84532, | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002 | ||
| }; | ||
| return networkMap[network] || 1; | ||
| const chainId = EVM_NETWORK_CHAIN_ID_MAP[network]; | ||
| if (!chainId) { | ||
| throw new Error(`Unsupported network: ${network}`); | ||
| } | ||
| return chainId; | ||
| } | ||
| function createNonce() { | ||
| const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto; | ||
| function getCrypto() { | ||
| const cryptoObj = globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return (0, import_viem.toHex)(cryptoObj.getRandomValues(new Uint8Array(32))); | ||
| return cryptoObj; | ||
| } | ||
| function createNonce() { | ||
| return (0, import_viem.toHex)(getCrypto().getRandomValues(new Uint8Array(32))); | ||
| } | ||
@@ -151,21 +151,25 @@ // src/exact/v1/client/scheme.ts | ||
| // src/v1/index.ts | ||
| var NETWORKS = [ | ||
| "abstract", | ||
| "abstract-testnet", | ||
| "base-sepolia", | ||
| "base", | ||
| "avalanche-fuji", | ||
| "avalanche", | ||
| "iotex", | ||
| "sei", | ||
| "sei-testnet", | ||
| "polygon", | ||
| "polygon-amoy", | ||
| "peaq", | ||
| "story", | ||
| "educhain", | ||
| "skale-base-sepolia" | ||
| ]; | ||
| 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 | ||
| }; | ||
| var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| EVM_NETWORK_CHAIN_ID_MAP, | ||
| ExactEvmSchemeV1, | ||
@@ -172,0 +176,0 @@ NETWORKS |
@@ -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 NETWORKS: string[] = [\n \"abstract\",\n \"abstract-testnet\",\n \"base-sepolia\",\n \"base\",\n \"avalanche-fuji\",\n \"avalanche\",\n \"iotex\",\n \"sei\",\n \"sei-testnet\",\n \"polygon\",\n \"polygon-amoy\",\n \"peaq\",\n \"story\",\n \"educhain\",\n \"skale-base-sepolia\",\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\";\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);\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// 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","import { toHex } from \"viem\";\nimport { Network } from \"@x402/core/types\";\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 */\nexport function getEvmChainId(network: Network): number {\n const networkMap: Record<string, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n ethereum: 1,\n sepolia: 11155111,\n polygon: 137,\n \"polygon-amoy\": 80002,\n };\n return networkMap[network] || 1;\n}\n\n/**\n * Create a random 32-byte nonce for authorization\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n // Use dynamic import to avoid require() in ESM context\n const cryptoObj =\n typeof globalThis.crypto !== \"undefined\"\n ? globalThis.crypto\n : (globalThis as { crypto?: Crypto }).crypto;\n\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n\n return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));\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\";\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 const chainId = getEvmChainId(payloadV1.network);\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 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} 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"]} |
@@ -1,3 +0,3 @@ | ||
| export { ExactEvmScheme } from '../../index.mjs'; | ||
| import { x402Client, SelectPaymentRequirements, PaymentPolicy } from '@x402/core/client'; | ||
| export { E as ExactEvmScheme, P as Permit2AllowanceParams, c as createPermit2ApprovalTx, e as erc20AllowanceAbi, g as getPermit2AllowanceReadParams } from '../../permit2-BsAoJiWD.mjs'; | ||
| import { SelectPaymentRequirements, PaymentPolicy, x402Client } from '@x402/core/client'; | ||
| import { Network } from '@x402/core/types'; | ||
@@ -4,0 +4,0 @@ import { C as ClientEvmSigner } from '../../signer-5OVDxViv.mjs'; |
| import { | ||
| ExactEvmScheme | ||
| } from "../../chunk-FOUXRQAV.mjs"; | ||
| import { | ||
| NETWORKS | ||
| } from "../../chunk-QLXM7BIB.mjs"; | ||
| import { | ||
| ExactEvmSchemeV1 | ||
| } from "../../chunk-PSA4YVU2.mjs"; | ||
| import "../../chunk-JYZWCLMP.mjs"; | ||
| import "../../chunk-ZYXTTU74.mjs"; | ||
| // 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; | ||
| } | ||
| ExactEvmScheme, | ||
| createPermit2ApprovalTx, | ||
| erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams, | ||
| registerExactEvmScheme | ||
| } from "../../chunk-U4H6Q62Q.mjs"; | ||
| import "../../chunk-DSSJHWGT.mjs"; | ||
| export { | ||
| ExactEvmScheme, | ||
| createPermit2ApprovalTx, | ||
| erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams, | ||
| registerExactEvmScheme | ||
| }; | ||
| //# sourceMappingURL=index.mjs.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../../src/exact/client/register.ts"],"sourcesContent":["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":";;;;;;;;;;;;;AAwDO,SAAS,uBAAuB,QAAoB,QAAqC;AAE9F,MAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AAEjD,WAAO,SAAS,QAAQ,aAAW;AACjC,aAAO,SAAS,SAAS,IAAI,eAAe,OAAO,MAAM,CAAC;AAAA,IAC5D,CAAC;AAAA,EACH,OAAO;AAEL,WAAO,SAAS,YAAY,IAAI,eAAe,OAAO,MAAM,CAAC;AAAA,EAC/D;AAGA,WAAS,QAAQ,aAAW;AAC1B,WAAO,WAAW,SAAoB,IAAI,iBAAiB,OAAO,MAAM,CAAC;AAAA,EAC3E,CAAC;AAGD,MAAI,OAAO,UAAU;AACnB,WAAO,SAAS,QAAQ,YAAU;AAChC,aAAO,eAAe,MAAM;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":[]} | ||
| {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]} |
@@ -16,2 +16,3 @@ import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse, Network } from '@x402/core/types'; | ||
| * EVM facilitator implementation for the Exact payment scheme. | ||
| * Routes between EIP-3009 and Permit2 based on payload type. | ||
| */ | ||
@@ -48,2 +49,3 @@ declare class ExactEvmScheme implements SchemeNetworkFacilitator { | ||
| * Verifies a payment payload. | ||
| * Routes to the appropriate verification logic based on payload type. | ||
| * | ||
@@ -57,2 +59,3 @@ * @param payload - The payment payload to verify | ||
| * Settles a payment by executing the transfer. | ||
| * Routes to the appropriate settlement logic based on payload type. | ||
| * | ||
@@ -59,0 +62,0 @@ * @param payload - The payment payload to settle |
| import { | ||
| NETWORKS | ||
| } from "../../chunk-QLXM7BIB.mjs"; | ||
| import "../../chunk-PSA4YVU2.mjs"; | ||
| isPermit2Payload | ||
| } from "../../chunk-PFULIQAE.mjs"; | ||
| import { | ||
| ExactEvmSchemeV1 | ||
| } from "../../chunk-JYZWCLMP.mjs"; | ||
| import { | ||
| ExactEvmSchemeV12 as ExactEvmSchemeV1, | ||
| NETWORKS, | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| eip3009ABI | ||
| } from "../../chunk-ZYXTTU74.mjs"; | ||
| eip3009ABI, | ||
| permit2WitnessTypes, | ||
| x402ExactPermit2ProxyABI, | ||
| x402ExactPermit2ProxyAddress | ||
| } from "../../chunk-DSSJHWGT.mjs"; | ||
| // src/exact/facilitator/eip3009.ts | ||
| import { getAddress, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; | ||
| async function verifyEIP3009(signer, payload, requirements, eip3009Payload) { | ||
| const payer = eip3009Payload.authorization.from; | ||
| if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| if (!requirements.extra?.name || !requirements.extra?.version) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "missing_eip712_domain", | ||
| payer | ||
| }; | ||
| } | ||
| const { name, version } = requirements.extra; | ||
| const erc20Address = getAddress(requirements.asset); | ||
| if (payload.accepted.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const permitTypedData = { | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| domain: { | ||
| name, | ||
| version, | ||
| chainId: parseInt(requirements.network.split(":")[1]), | ||
| verifyingContract: erc20Address | ||
| }, | ||
| message: { | ||
| from: eip3009Payload.authorization.from, | ||
| to: eip3009Payload.authorization.to, | ||
| value: BigInt(eip3009Payload.authorization.value), | ||
| validAfter: BigInt(eip3009Payload.authorization.validAfter), | ||
| validBefore: BigInt(eip3009Payload.authorization.validBefore), | ||
| nonce: eip3009Payload.authorization.nonce | ||
| } | ||
| }; | ||
| try { | ||
| const recoveredAddress = await signer.verifyTypedData({ | ||
| address: eip3009Payload.authorization.from, | ||
| ...permitTypedData, | ||
| signature: eip3009Payload.signature | ||
| }); | ||
| if (!recoveredAddress) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| const signature = eip3009Payload.signature; | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isSmartWallet = signatureLength > 130; | ||
| if (isSmartWallet) { | ||
| const payerAddress = eip3009Payload.authorization.from; | ||
| const bytecode = await 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 | ||
| }; | ||
| } | ||
| } else { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_signature", | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| if (getAddress(eip3009Payload.authorization.to) !== getAddress(requirements.payTo)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_recipient_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_before", | ||
| payer | ||
| }; | ||
| } | ||
| if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_valid_after", | ||
| payer | ||
| }; | ||
| } | ||
| try { | ||
| const balance = await signer.readContract({ | ||
| address: erc20Address, | ||
| abi: eip3009ABI, | ||
| functionName: "balanceOf", | ||
| args: [eip3009Payload.authorization.from] | ||
| }); | ||
| if (BigInt(balance) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| 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.`, | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| if (BigInt(eip3009Payload.authorization.value) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_value", | ||
| payer | ||
| }; | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer | ||
| }; | ||
| } | ||
| async function settleEIP3009(signer, payload, requirements, eip3009Payload, config) { | ||
| const payer = eip3009Payload.authorization.from; | ||
| const valid = await verifyEIP3009(signer, payload, requirements, eip3009Payload); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payload.accepted.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| try { | ||
| const parseResult = parseErc6492Signature(eip3009Payload.signature); | ||
| const { signature, address: factoryAddress, data: factoryCalldata } = parseResult; | ||
| if (config.deployERC4337WithEIP6492 && factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) { | ||
| const bytecode = await signer.getCode({ address: payer }); | ||
| if (!bytecode || bytecode === "0x") { | ||
| const deployTx = await signer.sendTransaction({ | ||
| to: factoryAddress, | ||
| data: factoryCalldata | ||
| }); | ||
| await signer.waitForTransactionReceipt({ hash: deployTx }); | ||
| } | ||
| } | ||
| const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length; | ||
| const isECDSA = signatureLength === 130; | ||
| let tx; | ||
| if (isECDSA) { | ||
| const parsedSig = parseSignature(signature); | ||
| tx = await signer.writeContract({ | ||
| address: getAddress(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress(eip3009Payload.authorization.from), | ||
| getAddress(eip3009Payload.authorization.to), | ||
| BigInt(eip3009Payload.authorization.value), | ||
| BigInt(eip3009Payload.authorization.validAfter), | ||
| BigInt(eip3009Payload.authorization.validBefore), | ||
| eip3009Payload.authorization.nonce, | ||
| parsedSig.v || parsedSig.yParity, | ||
| parsedSig.r, | ||
| parsedSig.s | ||
| ] | ||
| }); | ||
| } else { | ||
| tx = await signer.writeContract({ | ||
| address: getAddress(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress(eip3009Payload.authorization.from), | ||
| getAddress(eip3009Payload.authorization.to), | ||
| BigInt(eip3009Payload.authorization.value), | ||
| BigInt(eip3009Payload.authorization.validAfter), | ||
| BigInt(eip3009Payload.authorization.validBefore), | ||
| eip3009Payload.authorization.nonce, | ||
| signature | ||
| ] | ||
| }); | ||
| } | ||
| const receipt = await signer.waitForTransactionReceipt({ hash: tx }); | ||
| if (receipt.status !== "success") { | ||
| return { | ||
| success: false, | ||
| errorReason: "invalid_transaction_state", | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } catch { | ||
| return { | ||
| success: false, | ||
| errorReason: "transaction_failed", | ||
| transaction: "", | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| // src/exact/facilitator/permit2.ts | ||
| import { getAddress as getAddress2 } from "viem"; | ||
| var erc20AllowanceABI = [ | ||
| { | ||
| type: "function", | ||
| name: "allowance", | ||
| inputs: [ | ||
| { name: "owner", type: "address" }, | ||
| { name: "spender", type: "address" } | ||
| ], | ||
| outputs: [{ type: "uint256" }], | ||
| stateMutability: "view" | ||
| } | ||
| ]; | ||
| async function verifyPermit2(signer, payload, requirements, permit2Payload) { | ||
| const payer = permit2Payload.permit2Authorization.from; | ||
| if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| if (payload.accepted.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const chainId = parseInt(requirements.network.split(":")[1]); | ||
| const tokenAddress = getAddress2(requirements.asset); | ||
| if (getAddress2(permit2Payload.permit2Authorization.spender) !== getAddress2(x402ExactPermit2ProxyAddress)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_spender", | ||
| payer | ||
| }; | ||
| } | ||
| if (getAddress2(permit2Payload.permit2Authorization.witness.to) !== getAddress2(requirements.payTo)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_recipient_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_deadline_expired", | ||
| payer | ||
| }; | ||
| } | ||
| if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_not_yet_valid", | ||
| payer | ||
| }; | ||
| } | ||
| if (BigInt(permit2Payload.permit2Authorization.permitted.amount) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_insufficient_amount", | ||
| payer | ||
| }; | ||
| } | ||
| if (getAddress2(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_token_mismatch", | ||
| payer | ||
| }; | ||
| } | ||
| const permit2TypedData = { | ||
| types: permit2WitnessTypes, | ||
| primaryType: "PermitWitnessTransferFrom", | ||
| domain: { | ||
| name: "Permit2", | ||
| chainId, | ||
| verifyingContract: PERMIT2_ADDRESS | ||
| }, | ||
| message: { | ||
| permitted: { | ||
| token: getAddress2(permit2Payload.permit2Authorization.permitted.token), | ||
| amount: BigInt(permit2Payload.permit2Authorization.permitted.amount) | ||
| }, | ||
| spender: getAddress2(permit2Payload.permit2Authorization.spender), | ||
| nonce: BigInt(permit2Payload.permit2Authorization.nonce), | ||
| deadline: BigInt(permit2Payload.permit2Authorization.deadline), | ||
| witness: { | ||
| to: getAddress2(permit2Payload.permit2Authorization.witness.to), | ||
| validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter), | ||
| extra: permit2Payload.permit2Authorization.witness.extra | ||
| } | ||
| } | ||
| }; | ||
| try { | ||
| const isValid = await signer.verifyTypedData({ | ||
| address: payer, | ||
| ...permit2TypedData, | ||
| signature: permit2Payload.signature | ||
| }); | ||
| if (!isValid) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_signature", | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_permit2_signature", | ||
| payer | ||
| }; | ||
| } | ||
| try { | ||
| const allowance = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: erc20AllowanceABI, | ||
| functionName: "allowance", | ||
| args: [payer, PERMIT2_ADDRESS] | ||
| }); | ||
| if (allowance < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "permit2_allowance_required", | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| try { | ||
| const balance = await signer.readContract({ | ||
| address: tokenAddress, | ||
| abi: eip3009ABI, | ||
| functionName: "balanceOf", | ||
| args: [payer] | ||
| }); | ||
| if (balance < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| 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.`, | ||
| payer | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer | ||
| }; | ||
| } | ||
| async function settlePermit2(signer, payload, requirements, permit2Payload) { | ||
| const payer = permit2Payload.permit2Authorization.from; | ||
| const valid = await verifyPermit2(signer, payload, requirements, permit2Payload); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payload.accepted.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer | ||
| }; | ||
| } | ||
| 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) | ||
| }, | ||
| 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 }); | ||
| if (receipt.status !== "success") { | ||
| return { | ||
| success: false, | ||
| errorReason: "invalid_transaction_state", | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } catch (error) { | ||
| let errorReason = "transaction_failed"; | ||
| if (error instanceof Error) { | ||
| const message = error.message; | ||
| if (message.includes("AmountExceedsPermitted")) { | ||
| errorReason = "permit2_amount_exceeds_permitted"; | ||
| } else if (message.includes("InvalidDestination")) { | ||
| errorReason = "permit2_invalid_destination"; | ||
| } else if (message.includes("InvalidOwner")) { | ||
| errorReason = "permit2_invalid_owner"; | ||
| } else if (message.includes("PaymentTooEarly")) { | ||
| errorReason = "permit2_payment_too_early"; | ||
| } else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) { | ||
| errorReason = "permit2_invalid_signature"; | ||
| } else if (message.includes("InvalidNonce")) { | ||
| errorReason = "permit2_invalid_nonce"; | ||
| } else { | ||
| errorReason = `transaction_failed: ${message.slice(0, 500)}`; | ||
| } | ||
| } | ||
| return { | ||
| success: false, | ||
| errorReason, | ||
| transaction: "", | ||
| network: payload.accepted.network, | ||
| payer | ||
| }; | ||
| } | ||
| } | ||
| // src/exact/facilitator/scheme.ts | ||
| import { getAddress, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; | ||
| var ExactEvmScheme = class { | ||
@@ -52,2 +522,3 @@ /** | ||
| * Verifies a payment payload. | ||
| * Routes to the appropriate verification logic based on payload type. | ||
| * | ||
@@ -59,142 +530,12 @@ * @param payload - The payment payload to verify | ||
| async verify(payload, requirements) { | ||
| const exactEvmPayload = payload.payload; | ||
| if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "unsupported_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| const rawPayload = payload.payload; | ||
| if (isPermit2Payload(rawPayload)) { | ||
| return verifyPermit2(this.signer, payload, requirements, rawPayload); | ||
| } | ||
| 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 = getAddress(requirements.asset); | ||
| if (payload.accepted.network !== requirements.network) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "network_mismatch", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const permitTypedData = { | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| domain: { | ||
| name, | ||
| version, | ||
| chainId: parseInt(requirements.network.split(":")[1]), | ||
| 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 (getAddress(exactEvmPayload.authorization.to) !== getAddress(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(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "insufficient_funds", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| } catch { | ||
| } | ||
| if (BigInt(exactEvmPayload.authorization.value) < BigInt(requirements.amount)) { | ||
| return { | ||
| isValid: false, | ||
| invalidReason: "invalid_exact_evm_payload_authorization_value", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| isValid: true, | ||
| invalidReason: void 0, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| const eip3009Payload = rawPayload; | ||
| return verifyEIP3009(this.signer, payload, requirements, eip3009Payload); | ||
| } | ||
| /** | ||
| * Settles a payment by executing the transfer. | ||
| * Routes to the appropriate settlement logic based on payload type. | ||
| * | ||
@@ -206,99 +547,8 @@ * @param payload - The payment payload to settle | ||
| async settle(payload, requirements) { | ||
| const exactEvmPayload = payload.payload; | ||
| const valid = await this.verify(payload, requirements); | ||
| if (!valid.isValid) { | ||
| return { | ||
| success: false, | ||
| network: payload.accepted.network, | ||
| transaction: "", | ||
| errorReason: valid.invalidReason ?? "invalid_scheme", | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| const rawPayload = payload.payload; | ||
| if (isPermit2Payload(rawPayload)) { | ||
| return settlePermit2(this.signer, payload, requirements, rawPayload); | ||
| } | ||
| 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: getAddress(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress(exactEvmPayload.authorization.from), | ||
| getAddress(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: getAddress(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress(exactEvmPayload.authorization.from), | ||
| getAddress(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: payload.accepted.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| return { | ||
| success: true, | ||
| transaction: tx, | ||
| network: payload.accepted.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } catch (error) { | ||
| console.error("Failed to settle transaction:", error); | ||
| return { | ||
| success: false, | ||
| errorReason: "transaction_failed", | ||
| transaction: "", | ||
| network: payload.accepted.network, | ||
| payer: exactEvmPayload.authorization.from | ||
| }; | ||
| } | ||
| const eip3009Payload = rawPayload; | ||
| return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config); | ||
| } | ||
@@ -305,0 +555,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../../../src/exact/facilitator/scheme.ts","../../../../src/exact/facilitator/register.ts"],"sourcesContent":["import {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\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 { ExactEvmPayloadV2 } from \"../../types\";\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 */\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 *\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 exactEvmPayload = payload.payload as ExactEvmPayloadV2;\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: exactEvmPayload.authorization.from,\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: 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 (payload.accepted.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: parseInt(requirements.network.split(\":\")[1]),\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(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"insufficient_funds\",\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(requirements.amount)) {\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.\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 exactEvmPayload = payload.payload as ExactEvmPayloadV2;\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: payload.accepted.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: payload.accepted.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.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: payload.accepted.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\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":[]} | ||
| {"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":"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","names":["getAddress","getAddress"]} |
| import { | ||
| ExactEvmSchemeV1 | ||
| } from "../../../chunk-PSA4YVU2.mjs"; | ||
| import "../../../chunk-ZYXTTU74.mjs"; | ||
| } from "../../../chunk-DSSJHWGT.mjs"; | ||
| export { | ||
@@ -6,0 +5,0 @@ ExactEvmSchemeV1 |
| import { | ||
| ExactEvmSchemeV1 | ||
| } from "../../../chunk-JYZWCLMP.mjs"; | ||
| import "../../../chunk-ZYXTTU74.mjs"; | ||
| ExactEvmSchemeV12 as ExactEvmSchemeV1 | ||
| } from "../../../chunk-DSSJHWGT.mjs"; | ||
| export { | ||
@@ -6,0 +5,0 @@ ExactEvmSchemeV1 |
+458
-31
@@ -1,36 +0,463 @@ | ||
| import { SchemeNetworkClient, PaymentRequirements, PaymentPayload } from '@x402/core/types'; | ||
| import { C as ClientEvmSigner } from './signer-5OVDxViv.mjs'; | ||
| export { 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-BsAoJiWD.mjs'; | ||
| export { C as ClientEvmSigner, F as FacilitatorEvmSigner, t as toClientEvmSigner, a as toFacilitatorEvmSigner } from './signer-5OVDxViv.mjs'; | ||
| import '@x402/core/types'; | ||
| /** | ||
| * EVM client implementation for the Exact payment scheme. | ||
| * Asset transfer methods for the exact EVM scheme. | ||
| * - eip3009: Uses transferWithAuthorization (USDC, etc.) - recommended for compatible tokens | ||
| * - permit2: Uses Permit2 + x402Permit2Proxy - universal fallback for any ERC-20 | ||
| */ | ||
| type AssetTransferMethod = "eip3009" | "permit2"; | ||
| /** | ||
| * EIP-3009 payload for tokens with native transferWithAuthorization support. | ||
| */ | ||
| type ExactEIP3009Payload = { | ||
| signature?: `0x${string}`; | ||
| authorization: { | ||
| from: `0x${string}`; | ||
| to: `0x${string}`; | ||
| value: string; | ||
| validAfter: string; | ||
| validBefore: string; | ||
| nonce: `0x${string}`; | ||
| }; | ||
| }; | ||
| /** | ||
| * Permit2 witness data structure. | ||
| * Matches the Witness struct in x402Permit2Proxy contract. | ||
| * Note: Upper time bound is enforced by Permit2's `deadline` field, not a witness field. | ||
| */ | ||
| type Permit2Witness = { | ||
| to: `0x${string}`; | ||
| validAfter: string; | ||
| extra: `0x${string}`; | ||
| }; | ||
| /** | ||
| * Permit2 authorization parameters. | ||
| * Used to reconstruct the signed message for verification. | ||
| */ | ||
| type Permit2Authorization = { | ||
| permitted: { | ||
| token: `0x${string}`; | ||
| amount: string; | ||
| }; | ||
| spender: `0x${string}`; | ||
| nonce: string; | ||
| deadline: string; | ||
| witness: Permit2Witness; | ||
| }; | ||
| /** | ||
| * Permit2 payload for tokens using the Permit2 + x402Permit2Proxy flow. | ||
| */ | ||
| type ExactPermit2Payload = { | ||
| signature: `0x${string}`; | ||
| permit2Authorization: Permit2Authorization & { | ||
| from: `0x${string}`; | ||
| }; | ||
| }; | ||
| type ExactEvmPayloadV1 = ExactEIP3009Payload; | ||
| type ExactEvmPayloadV2 = ExactEIP3009Payload | ExactPermit2Payload; | ||
| /** | ||
| * Type guard to check if a payload is a Permit2 payload. | ||
| * Permit2 payloads have a `permit2Authorization` field. | ||
| * | ||
| * @param payload - The payload to check. | ||
| * @returns True if the payload is a Permit2 payload, false otherwise. | ||
| */ | ||
| 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. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload | ||
| */ | ||
| createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements): Promise<Pick<PaymentPayload, "x402Version" | "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 | ||
| */ | ||
| private signAuthorization; | ||
| } | ||
| declare function isPermit2Payload(payload: ExactEvmPayloadV2): payload is ExactPermit2Payload; | ||
| /** | ||
| * Type guard to check if a payload is an EIP-3009 payload. | ||
| * EIP-3009 payloads have an `authorization` field. | ||
| * | ||
| * @param payload - The payload to check. | ||
| * @returns True if the payload is an EIP-3009 payload, false otherwise. | ||
| */ | ||
| declare function isEIP3009Payload(payload: ExactEvmPayloadV2): payload is ExactEIP3009Payload; | ||
| export { ClientEvmSigner, ExactEvmScheme }; | ||
| declare const authorizationTypes: { | ||
| readonly TransferWithAuthorization: readonly [{ | ||
| readonly name: "from"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validBefore"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "bytes32"; | ||
| }]; | ||
| }; | ||
| /** | ||
| * Permit2 EIP-712 types for signing PermitWitnessTransferFrom. | ||
| * Must match the exact format expected by the Permit2 contract. | ||
| * Note: Types must be in ALPHABETICAL order after the primary type (TokenPermissions < Witness). | ||
| */ | ||
| declare const permit2WitnessTypes: { | ||
| readonly PermitWitnessTransferFrom: readonly [{ | ||
| readonly name: "permitted"; | ||
| readonly type: "TokenPermissions"; | ||
| }, { | ||
| readonly name: "spender"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "witness"; | ||
| readonly type: "Witness"; | ||
| }]; | ||
| readonly TokenPermissions: readonly [{ | ||
| readonly name: "token"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "amount"; | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly Witness: readonly [{ | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "extra"; | ||
| readonly type: "bytes"; | ||
| }]; | ||
| }; | ||
| declare const eip3009ABI: readonly [{ | ||
| readonly inputs: readonly [{ | ||
| readonly name: "from"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validBefore"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "bytes32"; | ||
| }, { | ||
| readonly name: "v"; | ||
| readonly type: "uint8"; | ||
| }, { | ||
| readonly name: "r"; | ||
| readonly type: "bytes32"; | ||
| }, { | ||
| readonly name: "s"; | ||
| readonly type: "bytes32"; | ||
| }]; | ||
| readonly name: "transferWithAuthorization"; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| readonly type: "function"; | ||
| }, { | ||
| readonly inputs: readonly [{ | ||
| readonly name: "from"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| }, { | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "validBefore"; | ||
| readonly type: "uint256"; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "bytes32"; | ||
| }, { | ||
| readonly name: "signature"; | ||
| readonly type: "bytes"; | ||
| }]; | ||
| readonly name: "transferWithAuthorization"; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| readonly type: "function"; | ||
| }, { | ||
| readonly inputs: readonly [{ | ||
| readonly name: "account"; | ||
| readonly type: "address"; | ||
| }]; | ||
| readonly name: "balanceOf"; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "uint256"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| readonly type: "function"; | ||
| }, { | ||
| readonly inputs: readonly []; | ||
| readonly name: "version"; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "string"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| readonly type: "function"; | ||
| }]; | ||
| /** | ||
| * Canonical Permit2 contract address. | ||
| * Same address on all EVM chains via CREATE2 deployment. | ||
| * | ||
| * @see https://github.com/Uniswap/permit2 | ||
| */ | ||
| declare const PERMIT2_ADDRESS: "0x000000000022D473030F116dDEE9F6B43aC78BA3"; | ||
| /** | ||
| * x402ExactPermit2Proxy contract address. | ||
| * Vanity address: 0x4020...0001 for easy recognition. | ||
| * This address is deterministic based on: | ||
| * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C) | ||
| * - Vanity-mined salt for prefix 0x4020 and suffix 0001 | ||
| * - Contract bytecode + constructor args (PERMIT2_ADDRESS) | ||
| */ | ||
| declare const x402ExactPermit2ProxyAddress: "0x4020615294c913F045dc10f0a5cdEbd86c280001"; | ||
| /** | ||
| * x402UptoPermit2Proxy contract address. | ||
| * Vanity address: 0x4020...0002 for easy recognition. | ||
| * This address is deterministic based on: | ||
| * - Arachnid's deterministic deployer (0x4e59b44847b379578588920cA78FbF26c0B4956C) | ||
| * - Vanity-mined salt for prefix 0x4020 and suffix 0002 | ||
| * - Contract bytecode + constructor args (PERMIT2_ADDRESS) | ||
| */ | ||
| declare const x402UptoPermit2ProxyAddress: "0x4020633461b2895a48930Ff97eE8fCdE8E520002"; | ||
| /** | ||
| * x402ExactPermit2Proxy ABI - settle function for exact payment scheme. | ||
| */ | ||
| declare const x402ExactPermit2ProxyABI: readonly [{ | ||
| readonly type: "function"; | ||
| readonly name: "PERMIT2"; | ||
| readonly inputs: readonly []; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "address"; | ||
| readonly internalType: "contract ISignatureTransfer"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "WITNESS_TYPEHASH"; | ||
| readonly inputs: readonly []; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "bytes32"; | ||
| readonly internalType: "bytes32"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "WITNESS_TYPE_STRING"; | ||
| readonly inputs: readonly []; | ||
| readonly outputs: readonly [{ | ||
| readonly name: ""; | ||
| readonly type: "string"; | ||
| readonly internalType: "string"; | ||
| }]; | ||
| readonly stateMutability: "view"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "initialize"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "_permit2"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }]; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "settle"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "permit"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.PermitTransferFrom"; | ||
| readonly components: readonly [{ | ||
| readonly name: "permitted"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.TokenPermissions"; | ||
| readonly components: readonly [{ | ||
| readonly name: "token"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "amount"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "witness"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct x402BasePermit2Proxy.Witness"; | ||
| readonly components: readonly [{ | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "extra"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| }, { | ||
| readonly name: "signature"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| }, { | ||
| readonly type: "function"; | ||
| readonly name: "settleWithPermit"; | ||
| readonly inputs: readonly [{ | ||
| readonly name: "permit2612"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct x402BasePermit2Proxy.EIP2612Permit"; | ||
| readonly components: readonly [{ | ||
| readonly name: "value"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "r"; | ||
| readonly type: "bytes32"; | ||
| readonly internalType: "bytes32"; | ||
| }, { | ||
| readonly name: "s"; | ||
| readonly type: "bytes32"; | ||
| readonly internalType: "bytes32"; | ||
| }, { | ||
| readonly name: "v"; | ||
| readonly type: "uint8"; | ||
| readonly internalType: "uint8"; | ||
| }]; | ||
| }, { | ||
| readonly name: "permit"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.PermitTransferFrom"; | ||
| readonly components: readonly [{ | ||
| readonly name: "permitted"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct ISignatureTransfer.TokenPermissions"; | ||
| readonly components: readonly [{ | ||
| readonly name: "token"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "amount"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "nonce"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "deadline"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }]; | ||
| }, { | ||
| readonly name: "owner"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "witness"; | ||
| readonly type: "tuple"; | ||
| readonly internalType: "struct x402BasePermit2Proxy.Witness"; | ||
| readonly components: readonly [{ | ||
| readonly name: "to"; | ||
| readonly type: "address"; | ||
| readonly internalType: "address"; | ||
| }, { | ||
| readonly name: "validAfter"; | ||
| readonly type: "uint256"; | ||
| readonly internalType: "uint256"; | ||
| }, { | ||
| readonly name: "extra"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| }, { | ||
| readonly name: "signature"; | ||
| readonly type: "bytes"; | ||
| readonly internalType: "bytes"; | ||
| }]; | ||
| readonly outputs: readonly []; | ||
| readonly stateMutability: "nonpayable"; | ||
| }, { | ||
| readonly type: "event"; | ||
| readonly name: "Settled"; | ||
| readonly inputs: readonly []; | ||
| readonly anonymous: false; | ||
| }, { | ||
| readonly type: "event"; | ||
| readonly name: "SettledWithPermit"; | ||
| readonly inputs: readonly []; | ||
| readonly anonymous: false; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "AlreadyInitialized"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "InvalidDestination"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "InvalidOwner"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "InvalidPermit2Address"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "PaymentTooEarly"; | ||
| readonly inputs: readonly []; | ||
| }, { | ||
| readonly type: "error"; | ||
| readonly name: "ReentrancyGuardReentrantCall"; | ||
| readonly inputs: readonly []; | ||
| }]; | ||
| export { type AssetTransferMethod, type ExactEIP3009Payload, type ExactEvmPayloadV1, type ExactEvmPayloadV2, type ExactPermit2Payload, PERMIT2_ADDRESS, type Permit2Authorization, type Permit2Witness, authorizationTypes, eip3009ABI, isEIP3009Payload, isPermit2Payload, permit2WitnessTypes, x402ExactPermit2ProxyABI, x402ExactPermit2ProxyAddress, x402UptoPermit2ProxyAddress }; |
+31
-4
| import { | ||
| ExactEvmScheme | ||
| } from "./chunk-FOUXRQAV.mjs"; | ||
| import "./chunk-ZYXTTU74.mjs"; | ||
| ExactEvmScheme, | ||
| createPermit2ApprovalTx, | ||
| erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams | ||
| } from "./chunk-U4H6Q62Q.mjs"; | ||
| import { | ||
| isEIP3009Payload, | ||
| isPermit2Payload | ||
| } from "./chunk-PFULIQAE.mjs"; | ||
| import { | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| eip3009ABI, | ||
| permit2WitnessTypes, | ||
| x402ExactPermit2ProxyABI, | ||
| x402ExactPermit2ProxyAddress, | ||
| x402UptoPermit2ProxyAddress | ||
| } from "./chunk-DSSJHWGT.mjs"; | ||
@@ -18,5 +33,17 @@ // src/signer.ts | ||
| ExactEvmScheme, | ||
| PERMIT2_ADDRESS, | ||
| authorizationTypes, | ||
| createPermit2ApprovalTx, | ||
| eip3009ABI, | ||
| erc20AllowanceAbi, | ||
| getPermit2AllowanceReadParams, | ||
| isEIP3009Payload, | ||
| isPermit2Payload, | ||
| permit2WitnessTypes, | ||
| toClientEvmSigner, | ||
| toFacilitatorEvmSigner | ||
| toFacilitatorEvmSigner, | ||
| x402ExactPermit2ProxyABI, | ||
| x402ExactPermit2ProxyAddress, | ||
| x402UptoPermit2ProxyAddress | ||
| }; | ||
| //# sourceMappingURL=index.mjs.map |
@@ -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 * 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":[]} |
@@ -5,4 +5,24 @@ export { ExactEvmSchemeV1 } from '../exact/v1/client/index.mjs'; | ||
| declare const EVM_NETWORK_CHAIN_ID_MAP: { | ||
| readonly ethereum: 1; | ||
| readonly sepolia: 11155111; | ||
| readonly abstract: 2741; | ||
| readonly "abstract-testnet": 11124; | ||
| readonly "base-sepolia": 84532; | ||
| readonly base: 8453; | ||
| readonly "avalanche-fuji": 43113; | ||
| readonly avalanche: 43114; | ||
| readonly iotex: 4689; | ||
| readonly sei: 1329; | ||
| readonly "sei-testnet": 1328; | ||
| readonly polygon: 137; | ||
| readonly "polygon-amoy": 80002; | ||
| readonly peaq: 3338; | ||
| readonly story: 1514; | ||
| readonly educhain: 41923; | ||
| readonly "skale-base-sepolia": 324705682; | ||
| }; | ||
| type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP; | ||
| declare const NETWORKS: string[]; | ||
| export { NETWORKS }; | ||
| export { EVM_NETWORK_CHAIN_ID_MAP, type EvmNetworkV1, NETWORKS }; |
| import { | ||
| EVM_NETWORK_CHAIN_ID_MAP, | ||
| ExactEvmSchemeV1, | ||
| NETWORKS | ||
| } from "../chunk-QLXM7BIB.mjs"; | ||
| import { | ||
| ExactEvmSchemeV1 | ||
| } from "../chunk-PSA4YVU2.mjs"; | ||
| import "../chunk-JYZWCLMP.mjs"; | ||
| import "../chunk-ZYXTTU74.mjs"; | ||
| } from "../chunk-DSSJHWGT.mjs"; | ||
| export { | ||
| EVM_NETWORK_CHAIN_ID_MAP, | ||
| ExactEvmSchemeV1, | ||
@@ -11,0 +9,0 @@ NETWORKS |
+2
-2
| { | ||
| "name": "@x402/evm", | ||
| "version": "2.2.0", | ||
| "version": "2.3.0", | ||
| "main": "./dist/cjs/index.js", | ||
@@ -38,3 +38,3 @@ "module": "./dist/esm/index.js", | ||
| "zod": "^3.24.2", | ||
| "@x402/core": "^2.2.0" | ||
| "@x402/core": "~2.3.0" | ||
| }, | ||
@@ -41,0 +41,0 @@ "exports": { |
| import { | ||
| authorizationTypes, | ||
| createNonce | ||
| } from "./chunk-ZYXTTU74.mjs"; | ||
| // src/exact/client/scheme.ts | ||
| import { getAddress } from "viem"; | ||
| 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. | ||
| * | ||
| * @param x402Version - The x402 protocol version | ||
| * @param paymentRequirements - The payment requirements | ||
| * @returns Promise resolving to a payment payload | ||
| */ | ||
| async createPaymentPayload(x402Version, paymentRequirements) { | ||
| const nonce = createNonce(); | ||
| const now = Math.floor(Date.now() / 1e3); | ||
| const authorization = { | ||
| from: this.signer.address, | ||
| to: getAddress(paymentRequirements.payTo), | ||
| value: paymentRequirements.amount, | ||
| validAfter: (now - 600).toString(), | ||
| // 10 minutes before | ||
| validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(), | ||
| nonce | ||
| }; | ||
| const signature = await this.signAuthorization(authorization, paymentRequirements); | ||
| const payload = { | ||
| authorization, | ||
| signature | ||
| }; | ||
| return { | ||
| x402Version, | ||
| 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 = 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 this.signer.signTypedData({ | ||
| domain, | ||
| types: authorizationTypes, | ||
| primaryType: "TransferWithAuthorization", | ||
| message | ||
| }); | ||
| } | ||
| }; | ||
| export { | ||
| ExactEvmScheme | ||
| }; | ||
| //# sourceMappingURL=chunk-FOUXRQAV.mjs.map |
| {"version":3,"sources":["../../src/exact/client/scheme.ts"],"sourcesContent":["import { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from \"@x402/core/types\";\nimport { getAddress } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { ExactEvmPayloadV2 } from \"../../types\";\nimport { createNonce } from \"../../utils\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n *\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 *\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<Pick<PaymentPayload, \"x402Version\" | \"payload\">> {\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEvmPayloadV2[\"authorization\"] = {\n from: this.signer.address,\n to: getAddress(paymentRequirements.payTo),\n value: paymentRequirements.amount,\n validAfter: (now - 600).toString(), // 10 minutes before\n validBefore: (now + paymentRequirements.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n // Sign the authorization\n const signature = await this.signAuthorization(authorization, paymentRequirements);\n\n const payload: ExactEvmPayloadV2 = {\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 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: ExactEvmPayloadV2[\"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 this.signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n }\n}\n"],"mappings":";;;;;;AACA,SAAS,kBAAkB;AAUpB,IAAM,iBAAN,MAAoD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQzD,YAA6B,QAAyB;AAAzB;AAP7B,SAAS,SAAS;AAAA,EAOqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvD,MAAM,qBACJ,aACA,qBAC0D;AAC1D,UAAM,QAAQ,YAAY;AAC1B,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAExC,UAAM,gBAAoD;AAAA,MACxD,MAAM,KAAK,OAAO;AAAA,MAClB,IAAI,WAAW,oBAAoB,KAAK;AAAA,MACxC,OAAO,oBAAoB;AAAA,MAC3B,aAAa,MAAM,KAAK,SAAS;AAAA;AAAA,MACjC,cAAc,MAAM,oBAAoB,mBAAmB,SAAS;AAAA,MACpE;AAAA,IACF;AAGA,UAAM,YAAY,MAAM,KAAK,kBAAkB,eAAe,mBAAmB;AAEjF,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBACZ,eACA,cACwB;AACxB,UAAM,UAAU,SAAS,aAAa,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;AAE3D,QAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,YAAM,IAAI;AAAA,QACR,4FAA4F,aAAa,KAAK;AAAA,MAChH;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AAEvC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,WAAW,aAAa,KAAK;AAAA,IAClD;AAEA,UAAM,UAAU;AAAA,MACd,MAAM,WAAW,cAAc,IAAI;AAAA,MACnC,IAAI,WAAW,cAAc,EAAE;AAAA,MAC/B,OAAO,OAAO,cAAc,KAAK;AAAA,MACjC,YAAY,OAAO,cAAc,UAAU;AAAA,MAC3C,aAAa,OAAO,cAAc,WAAW;AAAA,MAC7C,OAAO,cAAc;AAAA,IACvB;AAEA,WAAO,MAAM,KAAK,OAAO,cAAc;AAAA,MACrC;AAAA,MACA,OAAO;AAAA,MACP,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]} |
| import { | ||
| authorizationTypes, | ||
| eip3009ABI, | ||
| getEvmChainId | ||
| } from "./chunk-ZYXTTU74.mjs"; | ||
| // src/exact/v1/facilitator/scheme.ts | ||
| import { getAddress, isAddressEqual, parseErc6492Signature, parseSignature } from "viem"; | ||
| var ExactEvmSchemeV1 = 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 | ||
| }; | ||
| } | ||
| const chainId = getEvmChainId(payloadV1.network); | ||
| 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 = getAddress(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 (getAddress(exactEvmPayload.authorization.to) !== getAddress(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", | ||
| 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: getAddress(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress(exactEvmPayload.authorization.from), | ||
| getAddress(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: getAddress(requirements.asset), | ||
| abi: eip3009ABI, | ||
| functionName: "transferWithAuthorization", | ||
| args: [ | ||
| getAddress(exactEvmPayload.authorization.from), | ||
| getAddress(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 | ||
| }; | ||
| } | ||
| } | ||
| }; | ||
| export { | ||
| ExactEvmSchemeV1 | ||
| }; | ||
| //# sourceMappingURL=chunk-JYZWCLMP.mjs.map |
| {"version":3,"sources":["../../src/exact/v1/facilitator/scheme.ts"],"sourcesContent":["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\";\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 const chainId = getEvmChainId(payloadV1.network);\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 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 { | ||
| authorizationTypes, | ||
| createNonce, | ||
| getEvmChainId | ||
| } from "./chunk-ZYXTTU74.mjs"; | ||
| // src/exact/v1/client/scheme.ts | ||
| import { getAddress } from "viem"; | ||
| 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 | ||
| }); | ||
| } | ||
| }; | ||
| export { | ||
| ExactEvmSchemeV1 | ||
| }; | ||
| //# sourceMappingURL=chunk-PSA4YVU2.mjs.map |
| {"version":3,"sources":["../../src/exact/v1/client/scheme.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\";\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);\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"],"mappings":";;;;;;;AAOA,SAAS,kBAAkB;AASpB,IAAM,mBAAN,MAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3D,YAA6B,QAAyB;AAAzB;AAP7B,SAAS,SAAS;AAAA,EAOqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvD,MAAM,qBACJ,aACA,qBAGA;AACA,UAAM,aAAa;AACnB,UAAM,QAAQ,YAAY;AAC1B,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAExC,UAAM,gBAAoD;AAAA,MACxD,MAAM,KAAK,OAAO;AAAA,MAClB,IAAI,WAAW,WAAW,KAAK;AAAA,MAC/B,OAAO,WAAW;AAAA,MAClB,aAAa,MAAM,KAAK,SAAS;AAAA;AAAA,MACjC,cAAc,MAAM,WAAW,mBAAmB,SAAS;AAAA,MAC3D;AAAA,IACF;AAGA,UAAM,YAAY,MAAM,KAAK,kBAAkB,eAAe,UAAU;AAExE,UAAM,UAA6B;AAAA,MACjC;AAAA,MACA;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,WAAW;AAAA,MACnB,SAAS,WAAW;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,kBACZ,eACA,cACwB;AACxB,UAAM,UAAU,cAAc,aAAa,OAAO;AAElD,QAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,YAAM,IAAI;AAAA,QACR,4FAA4F,aAAa,KAAK;AAAA,MAChH;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AAEvC,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA,mBAAmB,WAAW,aAAa,KAAK;AAAA,IAClD;AAEA,UAAM,UAAU;AAAA,MACd,MAAM,WAAW,cAAc,IAAI;AAAA,MACnC,IAAI,WAAW,cAAc,EAAE;AAAA,MAC/B,OAAO,OAAO,cAAc,KAAK;AAAA,MACjC,YAAY,OAAO,cAAc,UAAU;AAAA,MAC3C,aAAa,OAAO,cAAc,WAAW;AAAA,MAC7C,OAAO,cAAc;AAAA,IACvB;AAEA,WAAO,MAAM,KAAK,OAAO,cAAc;AAAA,MACrC;AAAA,MACA,OAAO;AAAA,MACP,aAAa;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":[]} |
| // src/v1/index.ts | ||
| var NETWORKS = [ | ||
| "abstract", | ||
| "abstract-testnet", | ||
| "base-sepolia", | ||
| "base", | ||
| "avalanche-fuji", | ||
| "avalanche", | ||
| "iotex", | ||
| "sei", | ||
| "sei-testnet", | ||
| "polygon", | ||
| "polygon-amoy", | ||
| "peaq", | ||
| "story", | ||
| "educhain", | ||
| "skale-base-sepolia" | ||
| ]; | ||
| export { | ||
| NETWORKS | ||
| }; | ||
| //# sourceMappingURL=chunk-QLXM7BIB.mjs.map |
| {"version":3,"sources":["../../src/v1/index.ts"],"sourcesContent":["export { ExactEvmSchemeV1 } from \"../exact/v1\";\n\nexport const NETWORKS: string[] = [\n \"abstract\",\n \"abstract-testnet\",\n \"base-sepolia\",\n \"base\",\n \"avalanche-fuji\",\n \"avalanche\",\n \"iotex\",\n \"sei\",\n \"sei-testnet\",\n \"polygon\",\n \"polygon-amoy\",\n \"peaq\",\n \"story\",\n \"educhain\",\n \"skale-base-sepolia\",\n];\n"],"mappings":";AAEO,IAAM,WAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]} |
| // 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 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" | ||
| } | ||
| ]; | ||
| // src/utils.ts | ||
| import { toHex } from "viem"; | ||
| function getEvmChainId(network) { | ||
| const networkMap = { | ||
| base: 8453, | ||
| "base-sepolia": 84532, | ||
| ethereum: 1, | ||
| sepolia: 11155111, | ||
| polygon: 137, | ||
| "polygon-amoy": 80002 | ||
| }; | ||
| return networkMap[network] || 1; | ||
| } | ||
| function createNonce() { | ||
| const cryptoObj = typeof globalThis.crypto !== "undefined" ? globalThis.crypto : globalThis.crypto; | ||
| if (!cryptoObj) { | ||
| throw new Error("Crypto API not available"); | ||
| } | ||
| return toHex(cryptoObj.getRandomValues(new Uint8Array(32))); | ||
| } | ||
| export { | ||
| authorizationTypes, | ||
| eip3009ABI, | ||
| getEvmChainId, | ||
| createNonce | ||
| }; | ||
| //# sourceMappingURL=chunk-ZYXTTU74.mjs.map |
| {"version":3,"sources":["../../src/constants.ts","../../src/utils.ts"],"sourcesContent":["// 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// 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","import { toHex } from \"viem\";\nimport { Network } from \"@x402/core/types\";\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 */\nexport function getEvmChainId(network: Network): number {\n const networkMap: Record<string, number> = {\n base: 8453,\n \"base-sepolia\": 84532,\n ethereum: 1,\n sepolia: 11155111,\n polygon: 137,\n \"polygon-amoy\": 80002,\n };\n return networkMap[network] || 1;\n}\n\n/**\n * Create a random 32-byte nonce for authorization\n *\n * @returns A hex-encoded 32-byte nonce\n */\nexport function createNonce(): `0x${string}` {\n // Use dynamic import to avoid require() in ESM context\n const cryptoObj =\n typeof globalThis.crypto !== \"undefined\"\n ? globalThis.crypto\n : (globalThis as { crypto?: Crypto }).crypto;\n\n if (!cryptoObj) {\n throw new Error(\"Crypto API not available\");\n }\n\n return toHex(cryptoObj.getRandomValues(new Uint8Array(32)));\n}\n"],"mappings":";AACO,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;AAGO,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;;;AC5DA,SAAS,aAAa;AAUf,SAAS,cAAc,SAA0B;AACtD,QAAM,aAAqC;AAAA,IACzC,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,gBAAgB;AAAA,EAClB;AACA,SAAO,WAAW,OAAO,KAAK;AAChC;AAOO,SAAS,cAA6B;AAE3C,QAAM,YACJ,OAAO,WAAW,WAAW,cACzB,WAAW,SACV,WAAmC;AAE1C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,MAAM,0BAA0B;AAAA,EAC5C;AAEA,SAAO,MAAM,UAAU,gBAAgB,IAAI,WAAW,EAAE,CAAC,CAAC;AAC5D;","names":[]} |
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
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
694542
74.59%5764
56.38%54
-3.57%4
300%+ Added
- Removed
Updated