New:Socket for Asana Is Now Available.Learn more
Get Started

@x402/evm

Package Overview
Dependencies
Maintainers
2
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@x402/evm - npm Package Compare versions

Comparing version
2.20.0
to
2.21.0
+162
dist/esm/chunk-3QTA5JH4.mjs
import {
ExactEvmSchemeV12 as ExactEvmSchemeV1,
NETWORKS
} from "./chunk-NVFLWXGP.mjs";
import {
createPermit2Payload
} from "./chunk-UBBS476I.mjs";
import {
trySignEip2612PermitExtension,
trySignErc20ApprovalExtension
} from "./chunk-27MWX225.mjs";
import {
authorizationTypes
} from "./chunk-MACPBXCT.mjs";
import {
createNonce,
getEvmChainId
} from "./chunk-TW7Z65AO.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: "0",
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 = 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 signer.signTypedData({
domain,
types: authorizationTypes,
primaryType: "TransferWithAuthorization",
message
});
}
// src/exact/client/scheme.ts
var ExactEvmScheme = class {
/**
* Creates a new ExactEvmClient instance.
*
* @param signer - The EVM signer for client operations.
* Base flow only requires `address` + `signTypedData`.
* Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally
* requires optional capabilities like `readContract` and tx signing helpers.
* @param options - Optional RPC configuration used to backfill extension capabilities.
*/
constructor(signer, options) {
this.signer = signer;
this.options = options;
this.scheme = "exact";
}
/**
* Creates a payment payload for the Exact scheme.
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
*
* For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the
* signer supports `readContract`, automatically signs an EIP-2612 permit
* when Permit2 allowance is insufficient.
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - The payment requirements
* @param context - Optional context with server-declared extensions
* @returns Promise resolving to a payment payload result (with optional extensions)
*/
async createPaymentPayload(x402Version, paymentRequirements, context) {
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
if (assetTransferMethod === "permit2") {
const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);
const eip2612Extensions = await trySignEip2612PermitExtension(
this.signer,
this.options,
paymentRequirements,
result,
context
);
if (eip2612Extensions) {
return {
...result,
extensions: eip2612Extensions
};
}
const erc20Extensions = await trySignErc20ApprovalExtension(
this.signer,
this.options,
paymentRequirements,
context
);
if (erc20Extensions) {
return {
...result,
extensions: erc20Extensions
};
}
return result;
}
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
}
};
// src/exact/client/register.ts
function registerExactEvmScheme(client, config) {
const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions);
if (config.networks && config.networks.length > 0) {
config.networks.forEach((network) => {
client.register(network, evmScheme);
});
} else {
client.register("eip155:*", evmScheme);
}
NETWORKS.forEach((network) => {
client.registerV1(network, new ExactEvmSchemeV1(config.signer));
});
if (config.policies) {
config.policies.forEach((policy) => {
client.registerPolicy(policy);
});
}
return client;
}
export {
ExactEvmScheme,
registerExactEvmScheme
};
//# sourceMappingURL=chunk-3QTA5JH4.mjs.map
{"version":3,"sources":["../../src/exact/client/eip3009.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, getEvmChainId } 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: \"0\",\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 = 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 signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n}\n","import {\n SchemeNetworkClient,\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@x402/core/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { AssetTransferMethod } from \"../../types\";\nimport { createEIP3009Payload } from \"./eip3009\";\nimport { createPermit2Payload } from \"./permit2\";\nimport {\n trySignEip2612PermitExtension,\n trySignErc20ApprovalExtension,\n} from \"../../shared/extensions\";\nimport { ExactEvmSchemeOptions } from \"./rpc\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows.\n *\n * Routes to the appropriate authorization method based on\n * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009\n * for backward compatibility with older facilitators.\n *\n * When the server advertises `eip2612GasSponsoring` and the asset transfer\n * method is `permit2`, the scheme automatically signs an EIP-2612 permit\n * if the user lacks Permit2 approval. This requires `readContract` on the signer.\n */\nexport class ExactEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClient instance.\n *\n * @param signer - The EVM signer for client operations.\n * Base flow only requires `address` + `signTypedData`.\n * Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally\n * requires optional capabilities like `readContract` and tx signing helpers.\n * @param options - Optional RPC configuration used to backfill extension capabilities.\n */\n constructor(\n private readonly signer: ClientEvmSigner,\n private readonly options?: ExactEvmSchemeOptions,\n ) {}\n\n /**\n * Creates a payment payload for the Exact scheme.\n * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.\n *\n * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the\n * signer supports `readContract`, automatically signs an EIP-2612 permit\n * when Permit2 allowance is insufficient.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @param context - Optional context with server-declared extensions\n * @returns Promise resolving to a payment payload result (with optional extensions)\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const assetTransferMethod =\n (paymentRequirements.extra?.assetTransferMethod as AssetTransferMethod) ?? \"eip3009\";\n\n if (assetTransferMethod === \"permit2\") {\n const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);\n\n const eip2612Extensions = await trySignEip2612PermitExtension(\n this.signer,\n this.options,\n paymentRequirements,\n result,\n context,\n );\n\n if (eip2612Extensions) {\n return {\n ...result,\n extensions: eip2612Extensions,\n };\n }\n\n const erc20Extensions = await trySignErc20ApprovalExtension(\n this.signer,\n this.options,\n paymentRequirements,\n context,\n );\n if (erc20Extensions) {\n return {\n ...result,\n extensions: erc20Extensions,\n };\n }\n\n return result;\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 { ExactEvmSchemeOptions } from \"./rpc\";\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 Exact EVM client scheme options.\n * Supports either a single config ({ rpcUrl }) or per-chain configs\n * keyed by EVM chain ID ({ 8453: { rpcUrl: \"...\" } }).\n */\n schemeOptions?: ExactEvmSchemeOptions;\n\n /**\n * Optional specific networks to register.\n * If not provided, registers wildcard support (eip155:*).\n */\n networks?: Network[];\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Client instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param client - The x402Client instance to register schemes to\n * @param config - Configuration for EVM client registration\n * @returns The client instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/client/register\";\n * import { x402Client } from \"@x402/core/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const client = new x402Client();\n * registerExactEvmScheme(client, { signer: account });\n * ```\n */\nexport function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client {\n const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions);\n\n // Register V2 scheme\n // EIP-2612 gas sponsoring is handled internally by the scheme when the\n // server advertises support - no separate extension registration needed.\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n client.register(network, evmScheme);\n });\n } else {\n // Register wildcard for all EVM chains\n client.register(\"eip155:*\", evmScheme);\n }\n\n // Register all V1 networks\n NETWORKS.forEach(network => {\n client.registerV1(network as Network, new ExactEvmSchemeV1(config.signer));\n });\n\n // Apply policies if provided\n if (config.policies) {\n config.policies.forEach(policy => {\n client.registerPolicy(policy);\n });\n }\n\n return client;\n}\n"],"mappings":"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","names":[]}
// src/exact/facilitator/errors.ts
var ErrAssetNotDeployedContract = "asset_not_deployed_contract";
var ErrInvalidScheme = "invalid_exact_evm_scheme";
var ErrNetworkMismatch = "invalid_exact_evm_network_mismatch";
var ErrMissingEip712Domain = "invalid_exact_evm_missing_eip712_domain";
var ErrRecipientMismatch = "invalid_exact_evm_recipient_mismatch";
var ErrInvalidSignature = "invalid_exact_evm_signature";
var ErrValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before";
var ErrValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after";
var ErrInvalidAuthorizationValue = "invalid_exact_evm_authorization_value";
var ErrAuthorizationValueMismatch = "invalid_exact_evm_payload_authorization_value_mismatch";
var ErrTransactionFailed = "invalid_exact_evm_transaction_failed";
var ErrTransferEventMismatch = "invalid_exact_evm_transfer_event_mismatch";
var ErrEip3009TokenNameMismatch = "invalid_exact_evm_token_name_mismatch";
var ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch";
var ErrEip3009NotSupported = "invalid_exact_evm_eip3009_not_supported";
var ErrEip3009NonceAlreadyUsed = "invalid_exact_evm_nonce_already_used";
var ErrEip3009InsufficientBalance = "invalid_exact_evm_insufficient_balance";
var ErrEip3009SimulationFailed = "invalid_exact_evm_transaction_simulation_failed";
var ErrPermit2InvalidSpender = "invalid_permit2_spender";
var ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch";
var ErrPermit2DeadlineExpired = "permit2_deadline_expired";
var ErrPermit2NotYetValid = "permit2_not_yet_valid";
var ErrPermit2AmountMismatch = "permit2_amount_mismatch";
var ErrPermit2TokenMismatch = "permit2_token_mismatch";
var ErrPermit2InvalidSignature = "invalid_permit2_signature";
var ErrPermit2AllowanceRequired = "permit2_allowance_required";
var ErrPermit2SimulationFailed = "permit2_simulation_failed";
var ErrPermit2InsufficientBalance = "permit2_insufficient_balance";
var ErrPermit2ProxyNotDeployed = "permit2_proxy_not_deployed";
var ErrPermit2InvalidAmount = "permit2_invalid_amount";
var ErrPermit2InvalidDestination = "permit2_invalid_destination";
var ErrPermit2InvalidOwner = "permit2_invalid_owner";
var ErrPermit2PaymentTooEarly = "permit2_payment_too_early";
var ErrPermit2InvalidNonce = "permit2_invalid_nonce";
var ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch";
var ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format";
var ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch";
var ErrErc20ApprovalAssetMismatch = "erc20_approval_asset_mismatch";
var ErrErc20ApprovalSpenderNotPermit2 = "erc20_approval_spender_not_permit2";
var ErrErc20ApprovalTxWrongTarget = "erc20_approval_tx_wrong_target";
var ErrErc20ApprovalTxWrongSelector = "erc20_approval_tx_wrong_selector";
var ErrErc20ApprovalTxWrongSpender = "erc20_approval_tx_wrong_spender";
var ErrErc20ApprovalTxInvalidCalldata = "erc20_approval_tx_invalid_calldata";
var ErrErc20ApprovalTxSignerMismatch = "erc20_approval_tx_signer_mismatch";
var ErrErc20ApprovalTxInvalidSignature = "erc20_approval_tx_invalid_signature";
var ErrErc20ApprovalTxParseFailed = "erc20_approval_tx_parse_failed";
var ErrErc20ApprovalTxFailed = "erc20_approval_tx_failed";
var ErrInvalidEip2612ExtensionFormat = "invalid_eip2612_extension_format";
var ErrEip2612FromMismatch = "eip2612_from_mismatch";
var ErrEip2612AssetMismatch = "eip2612_asset_mismatch";
var ErrEip2612SpenderNotPermit2 = "eip2612_spender_not_permit2";
var ErrEip2612DeadlineExpired = "eip2612_deadline_expired";
var ErrUnsupportedPayloadType = "unsupported_payload_type";
var ErrInvalidTransactionState = "invalid_transaction_state";
var ErrFactoryNotAllowed = "eip6492_factory_not_allowed";
var ErrSmartWalletDeploymentFailed = "smart_wallet_deployment_failed";
export {
ErrAssetNotDeployedContract,
ErrInvalidScheme,
ErrNetworkMismatch,
ErrMissingEip712Domain,
ErrRecipientMismatch,
ErrInvalidSignature,
ErrValidBeforeExpired,
ErrValidAfterInFuture,
ErrInvalidAuthorizationValue,
ErrAuthorizationValueMismatch,
ErrTransactionFailed,
ErrTransferEventMismatch,
ErrEip3009TokenNameMismatch,
ErrEip3009TokenVersionMismatch,
ErrEip3009NotSupported,
ErrEip3009NonceAlreadyUsed,
ErrEip3009InsufficientBalance,
ErrEip3009SimulationFailed,
ErrPermit2InvalidSpender,
ErrPermit2RecipientMismatch,
ErrPermit2DeadlineExpired,
ErrPermit2NotYetValid,
ErrPermit2AmountMismatch,
ErrPermit2TokenMismatch,
ErrPermit2InvalidSignature,
ErrPermit2AllowanceRequired,
ErrPermit2SimulationFailed,
ErrPermit2InsufficientBalance,
ErrPermit2ProxyNotDeployed,
ErrPermit2InvalidAmount,
ErrPermit2InvalidDestination,
ErrPermit2InvalidOwner,
ErrPermit2PaymentTooEarly,
ErrPermit2InvalidNonce,
ErrPermit2612AmountMismatch,
ErrErc20ApprovalInvalidFormat,
ErrErc20ApprovalFromMismatch,
ErrErc20ApprovalAssetMismatch,
ErrErc20ApprovalSpenderNotPermit2,
ErrErc20ApprovalTxWrongTarget,
ErrErc20ApprovalTxWrongSelector,
ErrErc20ApprovalTxWrongSpender,
ErrErc20ApprovalTxInvalidCalldata,
ErrErc20ApprovalTxSignerMismatch,
ErrErc20ApprovalTxInvalidSignature,
ErrErc20ApprovalTxParseFailed,
ErrErc20ApprovalTxFailed,
ErrInvalidEip2612ExtensionFormat,
ErrEip2612FromMismatch,
ErrEip2612AssetMismatch,
ErrEip2612SpenderNotPermit2,
ErrEip2612DeadlineExpired,
ErrUnsupportedPayloadType,
ErrInvalidTransactionState,
ErrFactoryNotAllowed,
ErrSmartWalletDeploymentFailed
};
//# sourceMappingURL=chunk-7ER7IIEN.mjs.map
{"version":3,"sources":["../../src/exact/facilitator/errors.ts"],"sourcesContent":["/**\n * Named error reason constants for the exact EVM facilitator.\n *\n * These strings must be character-for-character identical to the Go constants in\n * go/mechanisms/evm/exact/facilitator/errors.go to maintain cross-SDK parity.\n */\n\nexport const ErrAssetNotDeployedContract = \"asset_not_deployed_contract\";\n\nexport const ErrInvalidScheme = \"invalid_exact_evm_scheme\";\nexport const ErrNetworkMismatch = \"invalid_exact_evm_network_mismatch\";\nexport const ErrMissingEip712Domain = \"invalid_exact_evm_missing_eip712_domain\";\nexport const ErrRecipientMismatch = \"invalid_exact_evm_recipient_mismatch\";\nexport const ErrInvalidSignature = \"invalid_exact_evm_signature\";\nexport const ErrValidBeforeExpired = \"invalid_exact_evm_payload_authorization_valid_before\";\nexport const ErrValidAfterInFuture = \"invalid_exact_evm_payload_authorization_valid_after\";\nexport const ErrInvalidAuthorizationValue = \"invalid_exact_evm_authorization_value\";\nexport const ErrAuthorizationValueMismatch =\n \"invalid_exact_evm_payload_authorization_value_mismatch\";\nexport const ErrUndeployedSmartWallet = \"invalid_exact_evm_payload_undeployed_smart_wallet\";\nexport const ErrTransactionFailed = \"invalid_exact_evm_transaction_failed\";\nexport const ErrTransferEventMismatch = \"invalid_exact_evm_transfer_event_mismatch\";\n\n// EIP-3009 verify errors\nexport const ErrEip3009TokenNameMismatch = \"invalid_exact_evm_token_name_mismatch\";\nexport const ErrEip3009TokenVersionMismatch = \"invalid_exact_evm_token_version_mismatch\";\nexport const ErrEip3009NotSupported = \"invalid_exact_evm_eip3009_not_supported\";\nexport const ErrEip3009NonceAlreadyUsed = \"invalid_exact_evm_nonce_already_used\";\nexport const ErrEip3009InsufficientBalance = \"invalid_exact_evm_insufficient_balance\";\nexport const ErrEip3009SimulationFailed = \"invalid_exact_evm_transaction_simulation_failed\";\n\n// Permit2 verify errors\nexport const ErrPermit2InvalidSpender = \"invalid_permit2_spender\";\nexport const ErrPermit2RecipientMismatch = \"invalid_permit2_recipient_mismatch\";\nexport const ErrPermit2DeadlineExpired = \"permit2_deadline_expired\";\nexport const ErrPermit2NotYetValid = \"permit2_not_yet_valid\";\nexport const ErrPermit2AmountMismatch = \"permit2_amount_mismatch\";\nexport const ErrPermit2TokenMismatch = \"permit2_token_mismatch\";\nexport const ErrPermit2InvalidSignature = \"invalid_permit2_signature\";\nexport const ErrPermit2AllowanceRequired = \"permit2_allowance_required\";\nexport const ErrPermit2SimulationFailed = \"permit2_simulation_failed\";\nexport const ErrPermit2InsufficientBalance = \"permit2_insufficient_balance\";\nexport const ErrPermit2ProxyNotDeployed = \"permit2_proxy_not_deployed\";\n\n// Permit2 settle errors (from contract reverts)\nexport const ErrPermit2InvalidAmount = \"permit2_invalid_amount\";\nexport const ErrPermit2InvalidDestination = \"permit2_invalid_destination\";\nexport const ErrPermit2InvalidOwner = \"permit2_invalid_owner\";\nexport const ErrPermit2PaymentTooEarly = \"permit2_payment_too_early\";\nexport const ErrPermit2InvalidNonce = \"permit2_invalid_nonce\";\nexport const ErrPermit2612AmountMismatch = \"permit2_2612_amount_mismatch\";\n\n// ERC-20 approval gas sponsoring verify errors\nexport const ErrErc20ApprovalInvalidFormat = \"invalid_erc20_approval_extension_format\";\nexport const ErrErc20ApprovalFromMismatch = \"erc20_approval_from_mismatch\";\nexport const ErrErc20ApprovalAssetMismatch = \"erc20_approval_asset_mismatch\";\nexport const ErrErc20ApprovalSpenderNotPermit2 = \"erc20_approval_spender_not_permit2\";\nexport const ErrErc20ApprovalTxWrongTarget = \"erc20_approval_tx_wrong_target\";\nexport const ErrErc20ApprovalTxWrongSelector = \"erc20_approval_tx_wrong_selector\";\nexport const ErrErc20ApprovalTxWrongSpender = \"erc20_approval_tx_wrong_spender\";\nexport const ErrErc20ApprovalTxInvalidCalldata = \"erc20_approval_tx_invalid_calldata\";\nexport const ErrErc20ApprovalTxSignerMismatch = \"erc20_approval_tx_signer_mismatch\";\nexport const ErrErc20ApprovalTxInvalidSignature = \"erc20_approval_tx_invalid_signature\";\nexport const ErrErc20ApprovalTxParseFailed = \"erc20_approval_tx_parse_failed\";\nexport const ErrErc20ApprovalTxFailed = \"erc20_approval_tx_failed\";\n\n// EIP-2612 gas sponsoring verify errors\nexport const ErrInvalidEip2612ExtensionFormat = \"invalid_eip2612_extension_format\";\nexport const ErrEip2612FromMismatch = \"eip2612_from_mismatch\";\nexport const ErrEip2612AssetMismatch = \"eip2612_asset_mismatch\";\nexport const ErrEip2612SpenderNotPermit2 = \"eip2612_spender_not_permit2\";\nexport const ErrEip2612DeadlineExpired = \"eip2612_deadline_expired\";\n\n// Shared settle errors\nexport const ErrUnsupportedPayloadType = \"unsupported_payload_type\";\nexport const ErrInvalidTransactionState = \"invalid_transaction_state\";\nexport const ErrFactoryNotAllowed = \"eip6492_factory_not_allowed\";\nexport const ErrSmartWalletDeploymentFailed = \"smart_wallet_deployment_failed\";\n"],"mappings":";AAOO,IAAM,8BAA8B;AAEpC,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,wBAAwB;AAC9B,IAAM,+BAA+B;AACrC,IAAM,gCACX;AAEK,IAAM,uBAAuB;AAC7B,IAAM,2BAA2B;AAGjC,IAAM,8BAA8B;AACpC,IAAM,iCAAiC;AACvC,IAAM,yBAAyB;AAC/B,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,6BAA6B;AAGnC,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AACpC,IAAM,4BAA4B;AAClC,IAAM,wBAAwB;AAC9B,IAAM,2BAA2B;AACjC,IAAM,0BAA0B;AAChC,IAAM,6BAA6B;AACnC,IAAM,8BAA8B;AACpC,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,6BAA6B;AAGnC,IAAM,0BAA0B;AAChC,IAAM,+BAA+B;AACrC,IAAM,yBAAyB;AAC/B,IAAM,4BAA4B;AAClC,IAAM,yBAAyB;AAC/B,IAAM,8BAA8B;AAGpC,IAAM,gCAAgC;AACtC,IAAM,+BAA+B;AACrC,IAAM,gCAAgC;AACtC,IAAM,oCAAoC;AAC1C,IAAM,gCAAgC;AACtC,IAAM,kCAAkC;AACxC,IAAM,iCAAiC;AACvC,IAAM,oCAAoC;AAC1C,IAAM,mCAAmC;AACzC,IAAM,qCAAqC;AAC3C,IAAM,gCAAgC;AACtC,IAAM,2BAA2B;AAGjC,IAAM,mCAAmC;AACzC,IAAM,yBAAyB;AAC/B,IAAM,0BAA0B;AAChC,IAAM,8BAA8B;AACpC,IAAM,4BAA4B;AAGlC,IAAM,4BAA4B;AAClC,IAAM,6BAA6B;AACnC,IAAM,uBAAuB;AAC7B,IAAM,iCAAiC;","names":[]}
import {
ErrEip2612AssetMismatch,
ErrEip2612DeadlineExpired,
ErrEip2612FromMismatch,
ErrEip2612SpenderNotPermit2,
ErrErc20ApprovalAssetMismatch,
ErrErc20ApprovalFromMismatch,
ErrErc20ApprovalInvalidFormat,
ErrErc20ApprovalSpenderNotPermit2,
ErrErc20ApprovalTxFailed,
ErrErc20ApprovalTxInvalidCalldata,
ErrErc20ApprovalTxInvalidSignature,
ErrErc20ApprovalTxParseFailed,
ErrErc20ApprovalTxSignerMismatch,
ErrErc20ApprovalTxWrongSelector,
ErrErc20ApprovalTxWrongSpender,
ErrErc20ApprovalTxWrongTarget,
ErrInvalidEip2612ExtensionFormat,
ErrInvalidTransactionState,
ErrPermit2612AmountMismatch,
ErrPermit2AllowanceRequired,
ErrPermit2InsufficientBalance,
ErrPermit2InvalidAmount,
ErrPermit2InvalidDestination,
ErrPermit2InvalidNonce,
ErrPermit2InvalidOwner,
ErrPermit2InvalidSignature,
ErrPermit2PaymentTooEarly,
ErrPermit2ProxyNotDeployed,
ErrPermit2SimulationFailed,
ErrTransactionFailed
} from "./chunk-7ER7IIEN.mjs";
import {
validateEip2612GasSponsoringInfo,
validateErc20ApprovalGasSponsoringInfo
} from "./chunk-27MWX225.mjs";
import {
PERMIT2_ADDRESS,
eip3009ABI,
erc20AllowanceAbi,
erc20ApproveAbi,
permit2WitnessTypes
} from "./chunk-MACPBXCT.mjs";
import {
multicall
} from "./chunk-VS3RYAYE.mjs";
import {
createPermit2Nonce,
getEvmChainId
} from "./chunk-TW7Z65AO.mjs";
// src/shared/permit2.ts
import { getAddress as getAddress2, encodeFunctionData, parseErc6492Signature } from "viem";
// src/shared/erc20approval.ts
import {
getAddress,
parseTransaction,
decodeFunctionData,
recoverTransactionAddress
} from "viem";
var APPROVE_SELECTOR = "0x095ea7b3";
async function validateErc20ApprovalForPayment(info, payer, tokenAddress) {
if (!validateErc20ApprovalGasSponsoringInfo(info)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalInvalidFormat,
invalidMessage: "ERC-20 approval extension info failed schema validation"
};
}
if (getAddress(info.from) !== getAddress(payer)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalFromMismatch,
invalidMessage: `Expected from=${payer}, got ${info.from}`
};
}
if (getAddress(info.asset) !== tokenAddress) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalAssetMismatch,
invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`
};
}
if (getAddress(info.spender) !== getAddress(PERMIT2_ADDRESS)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalSpenderNotPermit2,
invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`
};
}
try {
const serializedTx = info.signedTransaction;
const tx = parseTransaction(serializedTx);
if (!tx.to || getAddress(tx.to) !== tokenAddress) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxWrongTarget,
invalidMessage: `Transaction targets ${tx.to ?? "null"}, expected ${tokenAddress}`
};
}
const data = tx.data ?? "0x";
if (!data.startsWith(APPROVE_SELECTOR)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxWrongSelector,
invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`
};
}
try {
const decoded = decodeFunctionData({
abi: erc20ApproveAbi,
data
});
const calldataSpender = getAddress(decoded.args[0]);
if (calldataSpender !== getAddress(PERMIT2_ADDRESS)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxWrongSpender,
invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`
};
}
} catch {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxInvalidCalldata,
invalidMessage: "Failed to decode approve() calldata from the signed transaction"
};
}
try {
const recoveredAddress = await recoverTransactionAddress({
serializedTransaction: serializedTx
});
if (getAddress(recoveredAddress) !== getAddress(payer)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxSignerMismatch,
invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`
};
}
} catch {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxInvalidSignature,
invalidMessage: "Failed to recover signer from the signed transaction"
};
}
} catch {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxParseFailed,
invalidMessage: "Failed to parse the signed transaction"
};
}
return { isValid: true };
}
// src/upto/facilitator/errors.ts
var ErrUptoInvalidScheme = "invalid_upto_evm_scheme";
var ErrUptoNetworkMismatch = "invalid_upto_evm_network_mismatch";
var ErrUptoSettlementExceedsAmount = "invalid_upto_evm_payload_settlement_exceeds_amount";
var ErrUptoAmountExceedsPermitted = "upto_amount_exceeds_permitted";
var ErrUptoUnauthorizedFacilitator = "upto_unauthorized_facilitator";
var ErrUptoFacilitatorMismatch = "upto_facilitator_mismatch";
// src/shared/permit2.ts
async function waitAndReturnSettleResponse(signer, tx, payload, payer) {
const receipt = await signer.waitForTransactionReceipt({ hash: tx });
if (receipt.status !== "success") {
return {
success: false,
errorReason: ErrInvalidTransactionState,
transaction: tx,
network: payload.accepted.network,
payer
};
}
return {
success: true,
transaction: tx,
network: payload.accepted.network,
payer
};
}
function mapSettleError(error, payload, payer) {
let errorReason = ErrTransactionFailed;
if (error instanceof Error) {
const message = error.message;
if (message.includes("Permit2612AmountMismatch")) {
errorReason = ErrPermit2612AmountMismatch;
} else if (message.includes("InvalidAmount")) {
errorReason = ErrPermit2InvalidAmount;
} else if (message.includes("InvalidDestination")) {
errorReason = ErrPermit2InvalidDestination;
} else if (message.includes("InvalidOwner")) {
errorReason = ErrPermit2InvalidOwner;
} else if (message.includes("PaymentTooEarly")) {
errorReason = ErrPermit2PaymentTooEarly;
} else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) {
errorReason = ErrPermit2InvalidSignature;
} else if (message.includes("InvalidNonce")) {
errorReason = ErrPermit2InvalidNonce;
} else if (message.includes("erc20_approval_tx_failed")) {
errorReason = ErrErc20ApprovalTxFailed;
} else if (message.includes("AmountExceedsPermitted")) {
errorReason = ErrUptoAmountExceedsPermitted;
} else if (message.includes("UnauthorizedFacilitator")) {
errorReason = ErrUptoUnauthorizedFacilitator;
} else {
errorReason = `${ErrTransactionFailed}: ${message.slice(0, 500)}`;
}
}
return {
success: false,
errorReason,
transaction: "",
network: payload.accepted.network,
payer
};
}
function validateEip2612PermitForPayment(info, payer, tokenAddress) {
if (!validateEip2612GasSponsoringInfo(info)) {
return { isValid: false, invalidReason: ErrInvalidEip2612ExtensionFormat };
}
if (getAddress2(info.from) !== getAddress2(payer)) {
return { isValid: false, invalidReason: ErrEip2612FromMismatch };
}
if (getAddress2(info.asset) !== tokenAddress) {
return { isValid: false, invalidReason: ErrEip2612AssetMismatch };
}
if (getAddress2(info.spender) !== getAddress2(PERMIT2_ADDRESS)) {
return { isValid: false, invalidReason: ErrEip2612SpenderNotPermit2 };
}
const now = Math.floor(Date.now() / 1e3);
if (BigInt(info.deadline) < BigInt(now + 6)) {
return { isValid: false, invalidReason: ErrEip2612DeadlineExpired };
}
return { isValid: true };
}
async function simulatePermit2Settle(config, signer, settleArgs) {
try {
await signer.readContract({
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "settle",
args: settleArgs
});
return true;
} catch {
return false;
}
}
async function simulatePermit2SettleWithPermit(config, signer, settleArgs, eip2612Info) {
try {
const { v, r, s } = splitEip2612Signature(eip2612Info.signature);
await signer.readContract({
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "settleWithPermit",
args: [
{
value: BigInt(eip2612Info.amount),
deadline: BigInt(eip2612Info.deadline),
r,
s,
v
},
...settleArgs
]
});
return true;
} catch {
return false;
}
}
async function simulatePermit2SettleWithErc20Approval(config, extensionSigner, settleArgs, erc20Info) {
if (!extensionSigner.simulateTransactions) {
return false;
}
try {
const settleData = encodeFunctionData({
abi: config.proxyABI,
functionName: "settle",
args: settleArgs
});
return await extensionSigner.simulateTransactions([
erc20Info.signedTransaction,
{ to: config.proxyAddress, data: settleData, gas: BigInt(3e5) }
]);
} catch {
return false;
}
}
async function diagnosePermit2SimulationFailure(config, signer, tokenAddress, permit2Payload, amountRequired) {
const payer = permit2Payload.permit2Authorization.from;
const diagnosticCalls = [
{
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "PERMIT2"
},
{
address: tokenAddress,
abi: eip3009ABI,
functionName: "balanceOf",
args: [payer]
},
{
address: tokenAddress,
abi: erc20AllowanceAbi,
functionName: "allowance",
args: [payer, PERMIT2_ADDRESS]
}
];
try {
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
const [proxyResult, balanceResult, allowanceResult] = results;
if (proxyResult.status === "failure") {
return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };
}
if (balanceResult.status === "success") {
const balance = balanceResult.result;
if (balance < BigInt(amountRequired)) {
return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };
}
}
if (allowanceResult.status === "success") {
const allowance = allowanceResult.result;
if (allowance < BigInt(amountRequired)) {
return { isValid: false, invalidReason: ErrPermit2AllowanceRequired, payer };
}
}
} catch {
}
return { isValid: false, invalidReason: ErrPermit2SimulationFailed, payer };
}
async function checkPermit2Prerequisites(config, signer, tokenAddress, payer, amountRequired) {
const diagnosticCalls = [
{
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "PERMIT2"
},
{
address: tokenAddress,
abi: eip3009ABI,
functionName: "balanceOf",
args: [payer]
}
];
try {
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
const [proxyResult, balanceResult] = results;
if (proxyResult.status === "failure") {
return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };
}
if (balanceResult.status === "success") {
const balance = balanceResult.result;
if (balance < BigInt(amountRequired)) {
return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };
}
}
} catch {
}
return { isValid: true, invalidReason: void 0, payer };
}
function buildExactPermit2SettleArgs(permit2Payload) {
const { signature } = parseErc6492Signature(permit2Payload.signature);
return [
{
permitted: {
token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
},
nonce: BigInt(permit2Payload.permit2Authorization.nonce),
deadline: BigInt(permit2Payload.permit2Authorization.deadline)
},
getAddress2(permit2Payload.permit2Authorization.from),
{
to: getAddress2(permit2Payload.permit2Authorization.witness.to),
validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
},
signature
];
}
function buildUptoPermit2SettleArgs(permit2Payload, settlementAmount, facilitatorAddress) {
const { signature } = parseErc6492Signature(permit2Payload.signature);
return [
{
permitted: {
token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
},
nonce: BigInt(permit2Payload.permit2Authorization.nonce),
deadline: BigInt(permit2Payload.permit2Authorization.deadline)
},
settlementAmount,
getAddress2(permit2Payload.permit2Authorization.from),
{
to: getAddress2(permit2Payload.permit2Authorization.witness.to),
facilitator: getAddress2(facilitatorAddress),
validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
},
signature
];
}
function splitEip2612Signature(signature) {
const sig = signature.startsWith("0x") ? signature.slice(2) : signature;
if (sig.length !== 130) {
throw new Error(
`invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`
);
}
const r = `0x${sig.slice(0, 64)}`;
const s = `0x${sig.slice(64, 128)}`;
const v = parseInt(sig.slice(128, 130), 16);
return { v, r, s };
}
async function createPermit2PayloadForProxy(proxyAddress, signer, x402Version, paymentRequirements) {
const now = Math.floor(Date.now() / 1e3);
const nonce = createPermit2Nonce();
const validAfter = "0";
const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();
const permit2Authorization = {
from: signer.address,
permitted: {
token: getAddress2(paymentRequirements.asset),
amount: paymentRequirements.amount
},
spender: proxyAddress,
nonce,
deadline,
witness: {
to: getAddress2(paymentRequirements.payTo),
validAfter
}
};
const signature = await signPermit2Authorization(
signer,
permit2Authorization,
paymentRequirements
);
return {
x402Version,
payload: { signature, permit2Authorization }
};
}
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
const chainId = getEvmChainId(requirements.network);
return await signer.signTypedData({
domain: { name: "Permit2", chainId, verifyingContract: PERMIT2_ADDRESS },
types: permit2WitnessTypes,
primaryType: "PermitWitnessTransferFrom",
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)
}
}
});
}
export {
validateErc20ApprovalForPayment,
ErrUptoInvalidScheme,
ErrUptoNetworkMismatch,
ErrUptoSettlementExceedsAmount,
ErrUptoFacilitatorMismatch,
waitAndReturnSettleResponse,
mapSettleError,
validateEip2612PermitForPayment,
simulatePermit2Settle,
simulatePermit2SettleWithPermit,
simulatePermit2SettleWithErc20Approval,
diagnosePermit2SimulationFailure,
checkPermit2Prerequisites,
buildExactPermit2SettleArgs,
buildUptoPermit2SettleArgs,
splitEip2612Signature,
createPermit2PayloadForProxy
};
//# sourceMappingURL=chunk-JFVEMVMS.mjs.map
{"version":3,"sources":["../../src/shared/permit2.ts","../../src/shared/erc20approval.ts","../../src/upto/facilitator/errors.ts"],"sourcesContent":["import {\n PaymentPayload,\n PaymentPayloadResult,\n PaymentRequirements,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport {\n extractEip2612GasSponsoringInfo,\n validateEip2612GasSponsoringInfo,\n extractErc20ApprovalGasSponsoringInfo,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n type Eip2612GasSponsoringInfo,\n type Erc20ApprovalGasSponsoringFacilitatorExtension,\n type Erc20ApprovalGasSponsoringSigner,\n} from \"../exact/extensions\";\nimport { getAddress, encodeFunctionData, parseErc6492Signature } from \"viem\";\nimport { PERMIT2_ADDRESS, eip3009ABI, erc20AllowanceAbi, permit2WitnessTypes } from \"../constants\";\nimport { multicall, ContractCall } from \"../multicall\";\nimport { createPermit2Nonce, getEvmChainId } from \"../utils\";\nimport {\n ErrPermit2612AmountMismatch,\n ErrPermit2InvalidAmount,\n ErrPermit2InvalidDestination,\n ErrPermit2InvalidNonce,\n ErrPermit2InvalidOwner,\n ErrPermit2InvalidSignature,\n ErrPermit2PaymentTooEarly,\n ErrPermit2AllowanceRequired,\n ErrPermit2SimulationFailed,\n ErrPermit2InsufficientBalance,\n ErrPermit2ProxyNotDeployed,\n ErrInvalidTransactionState,\n ErrTransactionFailed,\n ErrInvalidEip2612ExtensionFormat,\n ErrEip2612FromMismatch,\n ErrEip2612AssetMismatch,\n ErrEip2612SpenderNotPermit2,\n ErrEip2612DeadlineExpired,\n ErrErc20ApprovalTxFailed,\n} from \"../exact/facilitator/errors\";\nimport { ClientEvmSigner, FacilitatorEvmSigner } from \"../signer\";\nimport { ExactPermit2Payload, Permit2Authorization, UptoPermit2Payload } from \"../types\";\nimport { validateErc20ApprovalForPayment } from \"./erc20approval\";\nimport {\n ErrUptoAmountExceedsPermitted,\n ErrUptoUnauthorizedFacilitator,\n} from \"../upto/facilitator/errors\";\n\n/**\n * Base type for Permit2 payloads shared between exact and upto schemes.\n * Both {@link ExactPermit2Payload} and {@link UptoPermit2Payload} satisfy this type.\n */\nexport type Permit2PayloadBase = ExactPermit2Payload | UptoPermit2Payload;\n\n/**\n * Configuration for the Permit2 proxy contract used during settlement.\n * The exact and upto schemes use different proxy addresses and ABIs.\n */\nexport type Permit2ProxyConfig = {\n /** The deployed proxy contract address. */\n proxyAddress: `0x${string}`;\n /** The proxy contract ABI (must include settle and settleWithPermit functions). */\n proxyABI: readonly Record<string, unknown>[];\n};\n\n/**\n * Checks Permit2 allowance and validates gas sponsoring extensions if allowance is insufficient.\n *\n * When the on-chain ERC-20 allowance to the Permit2 contract is below the required amount,\n * this function falls back to validating EIP-2612 or ERC-20 approval gas sponsoring extensions\n * attached to the payment payload.\n *\n * @param signer - The facilitator signer for on-chain reads\n * @param payload - The payment payload\n * @param requirements - The payment requirements\n * @param payer - The payer address\n * @param tokenAddress - The token contract address\n * @param context - Optional facilitator context for extension lookup\n * @returns A VerifyResponse if verification should stop (failure), or null to continue\n */\nexport async function verifyPermit2Allowance(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n context?: FacilitatorContext,\n): Promise<VerifyResponse | null> {\n try {\n const allowance = (await signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return null; // Sufficient allowance, continue verification\n }\n\n // Allowance insufficient — try EIP-2612 gas sponsoring first\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null; // EIP-2612 is valid, allowance will be set atomically during settlement\n }\n\n // Try ERC-20 approval gas sponsoring as fallback\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null; // ERC-20 approval is valid, will be broadcast before settlement\n }\n }\n\n return { isValid: false, invalidReason: \"permit2_allowance_required\", payer };\n } catch {\n // Allowance check failed — validate extensions if present; fail closed if none valid\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null;\n }\n\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null;\n }\n }\n\n return { isValid: false, invalidReason: \"permit2_allowance_required\", payer };\n }\n}\n\n/**\n * Waits for a transaction receipt and returns the appropriate SettleResponse.\n *\n * @param signer - Signer with waitForTransactionReceipt capability\n * @param tx - The transaction hash to wait for\n * @param payload - The payment payload (for network info)\n * @param payer - The payer address\n * @returns Promise resolving to a settlement response indicating success or failure\n */\nexport async function waitAndReturnSettleResponse(\n signer: Pick<FacilitatorEvmSigner, \"waitForTransactionReceipt\">,\n tx: `0x${string}`,\n payload: PaymentPayload,\n payer: `0x${string}`,\n): Promise<SettleResponse> {\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: ErrInvalidTransactionState,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n}\n\n/**\n * Maps contract revert errors to structured SettleResponse error reasons.\n *\n * Inspects the error message for known contract revert strings and maps them\n * to the corresponding error reason constants. Falls back to a generic\n * \"transaction_failed\" reason with truncated message for unrecognized errors.\n *\n * @param error - The caught error (typically from a contract write)\n * @param payload - The payment payload (for network info)\n * @param payer - The payer address\n * @returns A failed SettleResponse with the mapped error reason\n */\nexport function mapSettleError(\n error: unknown,\n payload: PaymentPayload,\n payer: `0x${string}`,\n): SettleResponse {\n let errorReason: string = ErrTransactionFailed;\n if (error instanceof Error) {\n const message = error.message;\n if (message.includes(\"Permit2612AmountMismatch\")) {\n errorReason = ErrPermit2612AmountMismatch;\n } else if (message.includes(\"InvalidAmount\")) {\n errorReason = ErrPermit2InvalidAmount;\n } else if (message.includes(\"InvalidDestination\")) {\n errorReason = ErrPermit2InvalidDestination;\n } else if (message.includes(\"InvalidOwner\")) {\n errorReason = ErrPermit2InvalidOwner;\n } else if (message.includes(\"PaymentTooEarly\")) {\n errorReason = ErrPermit2PaymentTooEarly;\n } else if (message.includes(\"InvalidSignature\") || message.includes(\"SignatureExpired\")) {\n errorReason = ErrPermit2InvalidSignature;\n } else if (message.includes(\"InvalidNonce\")) {\n errorReason = ErrPermit2InvalidNonce;\n } else if (message.includes(\"erc20_approval_tx_failed\")) {\n errorReason = ErrErc20ApprovalTxFailed;\n } else if (message.includes(\"AmountExceedsPermitted\")) {\n errorReason = ErrUptoAmountExceedsPermitted;\n } else if (message.includes(\"UnauthorizedFacilitator\")) {\n errorReason = ErrUptoUnauthorizedFacilitator;\n } else {\n errorReason = `${ErrTransactionFailed}: ${message.slice(0, 500)}`;\n }\n }\n return {\n success: false,\n errorReason,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n}\n\n/**\n * Validates EIP-2612 permit extension data for a Permit2 payment.\n *\n * Checks that the permit extension has a valid format and that the from address,\n * asset address, spender address, and deadline all match expectations.\n *\n * @param info - The EIP-2612 gas sponsoring info extracted from the payment payload\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result with isValid flag and optional invalidReason string\n */\nexport function validateEip2612PermitForPayment(\n info: Eip2612GasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): { isValid: boolean; invalidReason?: string } {\n if (!validateEip2612GasSponsoringInfo(info)) {\n return { isValid: false, invalidReason: ErrInvalidEip2612ExtensionFormat };\n }\n\n if (getAddress(info.from as `0x${string}`) !== getAddress(payer)) {\n return { isValid: false, invalidReason: ErrEip2612FromMismatch };\n }\n\n if (getAddress(info.asset as `0x${string}`) !== tokenAddress) {\n return { isValid: false, invalidReason: ErrEip2612AssetMismatch };\n }\n\n if (getAddress(info.spender as `0x${string}`) !== getAddress(PERMIT2_ADDRESS)) {\n return { isValid: false, invalidReason: ErrEip2612SpenderNotPermit2 };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(info.deadline) < BigInt(now + 6)) {\n return { isValid: false, invalidReason: ErrEip2612DeadlineExpired };\n }\n\n return { isValid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Simulation helpers (shared across exact and upto)\n// ---------------------------------------------------------------------------\n\n/**\n * Simulates settle() via eth_call (readContract).\n * Returns true if simulation succeeded, false if it failed.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulatePermit2Settle(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n settleArgs: readonly unknown[],\n): Promise<boolean> {\n try {\n await signer.readContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settle\",\n args: settleArgs,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Simulates settleWithPermit() via eth_call (readContract).\n * The contract atomically calls token.permit() then PERMIT2.permitTransferFrom(),\n * so simulation covers allowance + balance + nonces.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @param eip2612Info - EIP-2612 gas sponsoring info from the payload extension\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulatePermit2SettleWithPermit(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n settleArgs: readonly unknown[],\n eip2612Info: Eip2612GasSponsoringInfo,\n): Promise<boolean> {\n try {\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n\n await signer.readContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settleWithPermit\",\n args: [\n {\n value: BigInt(eip2612Info.amount),\n deadline: BigInt(eip2612Info.deadline),\n r,\n s,\n v,\n },\n ...settleArgs,\n ],\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Delegates the full approve+settle simulation flow to the extension signer via simulateTransactions.\n * The signer owns execution strategy.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param extensionSigner - The extension signer with simulateTransactions capability\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @param erc20Info - Object containing the signed approval transaction\n * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction hex string\n * @returns true if the bundle simulation succeeded, false otherwise\n */\nexport async function simulatePermit2SettleWithErc20Approval(\n config: Permit2ProxyConfig,\n extensionSigner: Erc20ApprovalGasSponsoringSigner,\n settleArgs: readonly unknown[],\n erc20Info: { signedTransaction: string },\n): Promise<boolean> {\n if (!extensionSigner.simulateTransactions) {\n return false;\n }\n\n try {\n const settleData = encodeFunctionData({\n abi: config.proxyABI,\n functionName: \"settle\",\n args: settleArgs,\n });\n\n return await extensionSigner.simulateTransactions([\n erc20Info.signedTransaction as `0x${string}`,\n { to: config.proxyAddress, data: settleData, gas: BigInt(300_000) },\n ]);\n } catch {\n return false;\n }\n}\n\n/**\n * Diagnoses a Permit2 simulation failure by performing a multicall to check the proxy deployment, balance and allowance.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param tokenAddress - ERC-20 token contract address\n * @param permit2Payload - The Permit2 authorization payload\n * @param amountRequired - Required payment amount (as string)\n * @returns VerifyResponse with the most specific failure reason\n */\nexport async function diagnosePermit2SimulationFailure(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n tokenAddress: `0x${string}`,\n permit2Payload: Permit2PayloadBase,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n const diagnosticCalls: ContractCall[] = [\n {\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"PERMIT2\",\n },\n {\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n },\n {\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [proxyResult, balanceResult, allowanceResult] = results;\n\n if (proxyResult.status === \"failure\") {\n return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };\n }\n }\n\n if (allowanceResult.status === \"success\") {\n const allowance = allowanceResult.result as bigint;\n if (allowance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2AllowanceRequired, payer };\n }\n }\n } catch {\n // Diagnostic multicall itself failed — fall through to generic error\n }\n\n return { isValid: false, invalidReason: ErrPermit2SimulationFailed, payer };\n}\n\n/**\n * Targeted multicall for the ERC-20 approval path where simulation cannot be used\n * (the approval hasn't been broadcast yet, so settle() would fail for expected reasons).\n * Checks proxy deployment, payer token balance and payer ETH balance for gas.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param tokenAddress - ERC-20 token contract address\n * @param payer - The payer address\n * @param amountRequired - Required payment amount (as string)\n * @returns VerifyResponse — valid if checks pass, otherwise the most specific failure\n */\nexport async function checkPermit2Prerequisites(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n tokenAddress: `0x${string}`,\n payer: `0x${string}`,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const diagnosticCalls: ContractCall[] = [\n {\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"PERMIT2\",\n },\n {\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [proxyResult, balanceResult] = results;\n\n if (proxyResult.status === \"failure\") {\n return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };\n }\n }\n } catch {\n // Multicall failed — fall through to valid (fail open for prerequisites-only check)\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n}\n\n/**\n * Builds args for exact settle(permit, owner, witness, signature).\n *\n * @param permit2Payload - The Permit2 payload containing authorization and signature data\n * @returns Tuple of contract call arguments for the exact settle function\n */\nexport function buildExactPermit2SettleArgs(permit2Payload: Permit2PayloadBase) {\n const { signature } = parseErc6492Signature(permit2Payload.signature);\n\n return [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n signature,\n ] as const;\n}\n\n/**\n * Builds args for upto settle(permit, amount, owner, witness, signature).\n * The upto contract's settle() takes an additional `amount` parameter and the witness\n * includes a `facilitator` field.\n *\n * @param permit2Payload - The upto Permit2 payload containing authorization and signature data\n * @param settlementAmount - The amount to settle on-chain\n * @param facilitatorAddress - The facilitator address authorized in the witness\n * @returns Tuple of contract call arguments for the upto settle function\n */\nexport function buildUptoPermit2SettleArgs(\n permit2Payload: UptoPermit2Payload,\n settlementAmount: bigint,\n facilitatorAddress: `0x${string}`,\n) {\n const { signature } = parseErc6492Signature(permit2Payload.signature);\n\n return [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n settlementAmount,\n getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n facilitator: getAddress(facilitatorAddress),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n signature,\n ] as const;\n}\n\n/**\n * Splits a 65-byte EIP-2612 signature into v, r, s components.\n *\n * @param signature - The hex-encoded 65-byte signature (with or without 0x prefix)\n * @returns Object with v (uint8), r (bytes32 hex), s (bytes32 hex)\n * @throws Error if the signature is not exactly 65 bytes (130 hex chars)\n */\nexport function splitEip2612Signature(signature: string): {\n v: number;\n r: `0x${string}`;\n s: `0x${string}`;\n} {\n const sig = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n\n if (sig.length !== 130) {\n throw new Error(\n `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`,\n );\n }\n\n const r = `0x${sig.slice(0, 64)}` as `0x${string}`;\n const s = `0x${sig.slice(64, 128)}` as `0x${string}`;\n const v = parseInt(sig.slice(128, 130), 16);\n\n return { v, r, s };\n}\n\n// ---------------------------------------------------------------------------\n// Client-side helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a Permit2 payload for any scheme (exact or upto).\n * The only scheme-specific input is the proxy address used as the spender.\n *\n * @param proxyAddress - The x402 proxy contract address to set as spender\n * @param signer - The EVM client signer\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2PayloadForProxy(\n proxyAddress: `0x${string}`,\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n\n // Lower time bound - allow some clock skew\n const validAfter = \"0\";\n // Upper time bound is enforced by Permit2's deadline field\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n const permit2Authorization: Permit2Authorization & { from: `0x${string}` } = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: proxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n validAfter,\n },\n };\n\n const signature = await signPermit2Authorization(\n signer,\n permit2Authorization,\n paymentRequirements,\n );\n\n return {\n x402Version,\n payload: { signature, permit2Authorization },\n };\n}\n\n/**\n * Signs a Permit2 authorization using EIP-712 with witness data.\n * The signature authorizes the proxy contract to transfer tokens on behalf of the signer.\n *\n * @param signer - The EVM client signer\n * @param permit2Authorization - The Permit2 authorization parameters\n * @param requirements - The payment requirements\n * @returns Promise resolving to the hex-encoded signature\n */\nasync function signPermit2Authorization(\n signer: ClientEvmSigner,\n permit2Authorization: Permit2Authorization & { from: `0x${string}` },\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(requirements.network);\n\n return await signer.signTypedData({\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message: {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n },\n },\n });\n}\n","import {\n getAddress,\n parseTransaction,\n decodeFunctionData,\n recoverTransactionAddress,\n type TransactionSerialized,\n} from \"viem\";\nimport type { VerifyResponse } from \"@x402/core/types\";\nimport {\n validateErc20ApprovalGasSponsoringInfo,\n type Erc20ApprovalGasSponsoringInfo,\n} from \"../exact/extensions\";\nimport { PERMIT2_ADDRESS, erc20ApproveAbi } from \"../constants\";\nimport {\n ErrErc20ApprovalInvalidFormat,\n ErrErc20ApprovalFromMismatch,\n ErrErc20ApprovalAssetMismatch,\n ErrErc20ApprovalSpenderNotPermit2,\n ErrErc20ApprovalTxWrongTarget,\n ErrErc20ApprovalTxWrongSelector,\n ErrErc20ApprovalTxWrongSpender,\n ErrErc20ApprovalTxInvalidCalldata,\n ErrErc20ApprovalTxSignerMismatch,\n ErrErc20ApprovalTxInvalidSignature,\n ErrErc20ApprovalTxParseFailed,\n} from \"../exact/facilitator/errors\";\n\n/** The approve(address,uint256) function selector */\nconst APPROVE_SELECTOR = \"0x095ea7b3\";\n\n/**\n * Validates ERC-20 approval extension data for a Permit2 payment.\n *\n * Performs comprehensive validation:\n * - Format validation via validateErc20ApprovalGasSponsoringInfo (JSON Schema)\n * - `from` matches payer\n * - `asset` matches token\n * - `spender` is PERMIT2_ADDRESS\n * - Transaction `to` matches token address\n * - Transaction calldata is a valid approve(PERMIT2_ADDRESS, ...) call\n * - Recovered transaction signer matches `from`\n *\n * @param info - The ERC-20 approval gas sponsoring info\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result with invalidReason and invalidMessage on failure\n */\nexport async function validateErc20ApprovalForPayment(\n info: Erc20ApprovalGasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): Promise<Pick<VerifyResponse, \"isValid\" | \"invalidReason\" | \"invalidMessage\">> {\n if (!validateErc20ApprovalGasSponsoringInfo(info)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalInvalidFormat,\n invalidMessage: \"ERC-20 approval extension info failed schema validation\",\n };\n }\n\n if (getAddress(info.from) !== getAddress(payer)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalFromMismatch,\n invalidMessage: `Expected from=${payer}, got ${info.from}`,\n };\n }\n\n if (getAddress(info.asset) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalAssetMismatch,\n invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`,\n };\n }\n\n if (getAddress(info.spender) !== getAddress(PERMIT2_ADDRESS)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalSpenderNotPermit2,\n invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`,\n };\n }\n\n try {\n const serializedTx = info.signedTransaction as TransactionSerialized;\n const tx = parseTransaction(serializedTx);\n\n if (!tx.to || getAddress(tx.to) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongTarget,\n invalidMessage: `Transaction targets ${tx.to ?? \"null\"}, expected ${tokenAddress}`,\n };\n }\n\n const data = tx.data ?? \"0x\";\n if (!data.startsWith(APPROVE_SELECTOR)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongSelector,\n invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`,\n };\n }\n\n try {\n const decoded = decodeFunctionData({\n abi: erc20ApproveAbi,\n data: data as `0x${string}`,\n });\n const calldataSpender = getAddress(decoded.args[0] as `0x${string}`);\n if (calldataSpender !== getAddress(PERMIT2_ADDRESS)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongSpender,\n invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxInvalidCalldata,\n invalidMessage: \"Failed to decode approve() calldata from the signed transaction\",\n };\n }\n\n try {\n const recoveredAddress = await recoverTransactionAddress({\n serializedTransaction: serializedTx,\n });\n if (getAddress(recoveredAddress) !== getAddress(payer)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxSignerMismatch,\n invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxInvalidSignature,\n invalidMessage: \"Failed to recover signer from the signed transaction\",\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxParseFailed,\n invalidMessage: \"Failed to parse the signed transaction\",\n };\n }\n\n return { isValid: true };\n}\n","/**\n * Named error reason constants for the upto EVM facilitator.\n *\n * Shared Permit2 errors are re-exported from exact/facilitator/errors.ts.\n * Upto-specific errors are defined here.\n *\n * These strings must be character-for-character identical to the Go constants\n * to maintain cross-SDK parity.\n */\n\n// Re-export shared EVM errors\nexport { ErrAssetNotDeployedContract } from \"../../exact/facilitator/errors\";\n\n// Re-export shared Permit2 errors\nexport {\n ErrPermit2InvalidSpender,\n ErrPermit2RecipientMismatch,\n ErrPermit2DeadlineExpired,\n ErrPermit2NotYetValid,\n ErrPermit2AmountMismatch,\n ErrPermit2TokenMismatch,\n ErrPermit2InvalidSignature,\n ErrPermit2AllowanceRequired,\n ErrPermit2InvalidAmount,\n ErrPermit2InvalidDestination,\n ErrPermit2InvalidOwner,\n ErrPermit2PaymentTooEarly,\n ErrPermit2InvalidNonce,\n ErrPermit2612AmountMismatch,\n ErrErc20ApprovalInvalidFormat,\n ErrErc20ApprovalFromMismatch,\n ErrErc20ApprovalAssetMismatch,\n ErrErc20ApprovalSpenderNotPermit2,\n ErrErc20ApprovalTxWrongTarget,\n ErrErc20ApprovalTxWrongSelector,\n ErrErc20ApprovalTxWrongSpender,\n ErrErc20ApprovalTxInvalidCalldata,\n ErrErc20ApprovalTxSignerMismatch,\n ErrErc20ApprovalTxInvalidSignature,\n ErrErc20ApprovalTxParseFailed,\n} from \"../../exact/facilitator/errors\";\n\n// Upto-specific errors\nexport const ErrUptoInvalidScheme = \"invalid_upto_evm_scheme\";\nexport const ErrUptoNetworkMismatch = \"invalid_upto_evm_network_mismatch\";\nexport const ErrUptoSettlementExceedsAmount = \"invalid_upto_evm_payload_settlement_exceeds_amount\";\nexport const ErrUptoAmountExceedsPermitted = \"upto_amount_exceeds_permitted\";\nexport const ErrUptoUnauthorizedFacilitator = \"upto_unauthorized_facilitator\";\nexport const ErrUptoFacilitatorMismatch = \"upto_facilitator_mismatch\";\n"],"mappings":"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","names":["getAddress","getAddress"]}
// src/shared/defaultAssets.ts
var DEFAULT_STABLECOINS = {
"eip155:8453": {
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
name: "USD Coin",
version: "2",
decimals: 6
},
// Base mainnet USDC
"eip155:84532": {
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
name: "USDC",
version: "2",
decimals: 6
},
// Base Sepolia USDC
"eip155:4326": {
address: "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7",
name: "MegaUSD",
version: "1",
decimals: 18,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)
"eip155:143": {
address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
name: "USD Coin",
version: "2",
decimals: 6
},
// Monad mainnet USDC
"eip155:988": {
address: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
name: "USDT0",
version: "1",
decimals: 6
},
// Stable mainnet USDT0
"eip155:2201": {
address: "0x78Cf24370174180738C5B8E352B6D14c83a6c9A9",
name: "USDT0",
version: "1",
decimals: 6
},
// Stable testnet USDT0
"eip155:137": {
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
name: "USD Coin",
version: "2",
decimals: 6
},
// Polygon mainnet USDC
"eip155:42161": {
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
name: "USD Coin",
version: "2",
decimals: 6
},
// Arbitrum One USDC
"eip155:421614": {
address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
name: "USD Coin",
version: "2",
decimals: 6
},
// Arbitrum Sepolia USDC
"eip155:31612": {
address: "0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186",
name: "Mezo USD",
version: "1",
decimals: 18,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)
"eip155:31611": {
address: "0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503",
name: "Mezo USD",
version: "1",
decimals: 18,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)
"eip155:723487": {
address: "0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb",
name: "Stable Coin",
version: "1",
decimals: 6,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Radius Network SBC (no EIP-3009, supports EIP-2612)
"eip155:72344": {
address: "0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb",
name: "Stable Coin",
version: "1",
decimals: 6,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Radius Testnet SBC (no EIP-3009, supports EIP-2612)
"eip155:36900": {
address: "0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2",
name: "USDC.e",
version: "2",
decimals: 6
},
// ADI Chain USDC.e (EIP-3009 supported)
"eip155:190415": {
address: "0x401eCb1D350407f13ba348573E5630B83638E30D",
name: "Bridged USDC",
version: "2",
decimals: 6
},
// HPP mainnet USDC.e
"eip155:181228": {
address: "0x401eCb1D350407f13ba348573E5630B83638E30D",
name: "Bridged USDC",
version: "2",
decimals: 6
},
// HPP Sepolia USDC.e
"eip155:50": {
address: "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1",
name: "USDC",
version: "2",
decimals: 6
},
// XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)
"eip155:51": {
address: "0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4",
name: "USDC",
version: "2",
decimals: 6
},
// XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)
"eip155:38833": {
address: "0xA5b8BF902b2844dA17d4506cc827F7F1681735E7",
name: "USDC",
version: "1",
decimals: 6,
assetTransferMethod: "permit2"
},
// Igra mainnet USDC (no EIP-3009, no EIP-2612)
"eip155:14": {
address: "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
name: "USD\u20AE0",
version: "1",
decimals: 6
},
// Flare mainnet USD₮0 (EIP-3009 supported)
"eip155:42220": {
address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
name: "USDC",
version: "2",
decimals: 6
},
// Celo mainnet USDC (EIP-3009 supported)
"eip155:11142220": {
address: "0x01C5C0122039549AD1493B8220cABEdD739BC44E",
name: "USDC",
version: "2",
decimals: 6
}
// Celo Sepolia testnet USDC (EIP-3009 supported)
};
function getDefaultAsset(network) {
const info = DEFAULT_STABLECOINS[network];
if (!info) {
throw new Error(`No default asset configured for network ${network}`);
}
return info;
}
export {
DEFAULT_STABLECOINS,
getDefaultAsset
};
//# sourceMappingURL=chunk-KTVL22S4.mjs.map
{"version":3,"sources":["../../src/shared/defaultAssets.ts"],"sourcesContent":["import type { Network } from \"@x402/core/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSETS.md at the\n * repository root for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31612\": {\n address: \"0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:723487\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Network SBC (no EIP-3009, supports EIP-2612)\n \"eip155:72344\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Testnet SBC (no EIP-3009, supports EIP-2612)\n \"eip155:36900\": {\n address: \"0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2\",\n name: \"USDC.e\",\n version: \"2\",\n decimals: 6,\n }, // ADI Chain USDC.e (EIP-3009 supported)\n \"eip155:190415\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP mainnet USDC.e\n \"eip155:181228\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP Sepolia USDC.e\n \"eip155:50\": {\n address: \"0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:51\": {\n address: \"0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:38833\": {\n address: \"0xA5b8BF902b2844dA17d4506cc827F7F1681735E7\",\n name: \"USDC\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n }, // Igra mainnet USDC (no EIP-3009, no EIP-2612)\n \"eip155:14\": {\n address: \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\",\n name: \"USD\\u20AE0\",\n version: \"1\",\n decimals: 6,\n }, // Flare mainnet USD₮0 (EIP-3009 supported)\n \"eip155:42220\": {\n address: \"0xcebA9300f2b948710d2653dD7B07f33A8B32118C\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Celo mainnet USDC (EIP-3009 supported)\n \"eip155:11142220\": {\n address: \"0x01C5C0122039549AD1493B8220cABEdD739BC44E\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Celo Sepolia testnet USDC (EIP-3009 supported)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n"],"mappings":"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","names":[]}
import {
classifyErc6492Payer,
verifyTypedDataSignature
} from "./chunk-BEMCJZKA.mjs";
import {
ErrEip3009InsufficientBalance,
ErrEip3009NonceAlreadyUsed,
ErrEip3009NotSupported,
ErrEip3009SimulationFailed,
ErrEip3009TokenNameMismatch,
ErrEip3009TokenVersionMismatch,
ErrFactoryNotAllowed,
ErrInvalidAuthorizationValue,
ErrInvalidScheme,
ErrInvalidSignature,
ErrMissingEip712Domain,
ErrNetworkMismatch,
ErrRecipientMismatch,
ErrSmartWalletDeploymentFailed,
ErrTransactionFailed,
ErrTransferEventMismatch,
ErrValidAfterInFuture,
ErrValidBeforeExpired
} from "./chunk-7ER7IIEN.mjs";
import {
resolveDataSuffix
} from "./chunk-27MWX225.mjs";
import {
authorizationTypes,
eip3009ABI
} from "./chunk-MACPBXCT.mjs";
import {
multicall
} from "./chunk-VS3RYAYE.mjs";
import {
createNonce
} from "./chunk-TW7Z65AO.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 = getEvmChainIdV1(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 getAddress3, isAddressEqual as isAddressEqual2, parseErc6492Signature as parseErc6492Signature2 } from "viem";
// src/exact/facilitator/eip3009-utils.ts
import {
encodeFunctionData,
getAddress as getAddress2,
isAddressEqual,
parseErc6492Signature,
parseEventLogs,
parseSignature
} from "viem";
var erc20TransferEventAbi = [
{
type: "event",
name: "Transfer",
anonymous: false,
inputs: [
{ name: "from", type: "address", indexed: true },
{ name: "to", type: "address", indexed: true },
{ name: "value", type: "uint256", indexed: false }
]
}
];
async function simulateEip3009Transfer(signer, erc20Address, payload, eip6492Deployment) {
return (await simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment)).ok;
}
async function simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment) {
const auth = payload.authorization;
const transferArgs = [
getAddress2(auth.from),
getAddress2(auth.to),
BigInt(auth.value),
BigInt(auth.validAfter),
BigInt(auth.validBefore),
auth.nonce
];
if (eip6492Deployment) {
const { signature: innerSignature } = parseErc6492Signature(payload.signature);
const transferCalldata = encodeFunctionData({
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [...transferArgs, innerSignature]
});
try {
const results = await multicall(signer.readContract.bind(signer), [
{
address: getAddress2(eip6492Deployment.factoryAddress),
callData: eip6492Deployment.factoryCalldata
},
{
address: erc20Address,
callData: transferCalldata
}
]);
return { ok: results[1]?.status === "success" };
} catch (error) {
return { ok: false, error };
}
}
const sig = payload.signature;
const sigLength = sig.startsWith("0x") ? sig.length - 2 : sig.length;
const isECDSA = sigLength === 130;
try {
if (isECDSA) {
const parsedSig = parseSignature(sig);
await signer.readContract({
address: erc20Address,
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [
...transferArgs,
parsedSig.v ?? parsedSig.yParity,
parsedSig.r,
parsedSig.s
]
});
} else {
await signer.readContract({
address: erc20Address,
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [...transferArgs, sig]
});
}
return { ok: true };
} catch (error) {
return { ok: false, error };
}
}
async function diagnoseEip3009SimulationFailure(signer, erc20Address, payload, requirements, amountRequired) {
const payer = payload.authorization.from;
const diagnosticCalls = [
{
address: erc20Address,
abi: eip3009ABI,
functionName: "balanceOf",
args: [payload.authorization.from]
},
{
address: erc20Address,
abi: eip3009ABI,
functionName: "name"
},
{
address: erc20Address,
abi: eip3009ABI,
functionName: "version"
},
{
address: erc20Address,
abi: eip3009ABI,
functionName: "authorizationState",
args: [payload.authorization.from, payload.authorization.nonce]
}
];
try {
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
const [balanceResult, nameResult, versionResult, authStateResult] = results;
if (authStateResult.status === "failure") {
return { isValid: false, invalidReason: ErrEip3009NotSupported, payer };
}
if (authStateResult.status === "success" && authStateResult.result === true) {
return { isValid: false, invalidReason: ErrEip3009NonceAlreadyUsed, payer };
}
if (nameResult.status === "success" && requirements.extra?.name && nameResult.result !== requirements.extra.name) {
return { isValid: false, invalidReason: ErrEip3009TokenNameMismatch, payer };
}
if (versionResult.status === "success" && requirements.extra?.version && versionResult.result !== requirements.extra.version) {
return { isValid: false, invalidReason: ErrEip3009TokenVersionMismatch, payer };
}
if (balanceResult.status === "success") {
const balance = balanceResult.result;
if (balance < BigInt(amountRequired)) {
return {
isValid: false,
invalidReason: ErrEip3009InsufficientBalance,
payer
};
}
}
} catch {
}
return { isValid: false, invalidReason: ErrEip3009SimulationFailed, payer };
}
function verifyEip3009TransferEvent(logs, erc20Address, expected) {
const transferLogs = parseEventLogs({
abi: erc20TransferEventAbi,
eventName: "Transfer",
logs: logs.filter((log) => isAddressEqual(log.address, erc20Address))
});
return transferLogs.some(
(log) => isAddressEqual(log.args.from, expected.from) && isAddressEqual(log.args.to, expected.to) && log.args.value === expected.value
);
}
function parseEip3009TransferError(error) {
const msg = error instanceof Error ? error.message : String(error);
if (/authorization.*(expired|valid before)/i.test(msg) || /AuthorizationExpired/i.test(msg)) {
return ErrValidBeforeExpired;
}
if (/authorization.*not.*valid|AuthorizationNotYetValid/i.test(msg)) {
return ErrValidAfterInFuture;
}
if (/authorization.*used|AuthorizationAlreadyUsed|AuthorizationUsedOrCanceled/i.test(msg)) {
return ErrEip3009NonceAlreadyUsed;
}
if (/transfer.*exceeds.*balance|insufficient.*balance|ERC20InsufficientBalance/i.test(msg)) {
return ErrEip3009InsufficientBalance;
}
if (/invalid.*signature|SignerMismatch|InvalidSignatureV|InvalidSignatureS/i.test(msg)) {
return ErrInvalidSignature;
}
return ErrTransactionFailed;
}
async function executeTransferWithAuthorization(signer, erc20Address, payload, dataSuffix) {
const { signature } = parseErc6492Signature(payload.signature);
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
const isECDSA = signatureLength === 130;
const auth = payload.authorization;
const baseArgs = [
getAddress2(auth.from),
getAddress2(auth.to),
BigInt(auth.value),
BigInt(auth.validAfter),
BigInt(auth.validBefore),
auth.nonce
];
let signatureArgs;
if (isECDSA) {
const parsedSig = parseSignature(signature);
signatureArgs = [
parsedSig.v || parsedSig.yParity,
parsedSig.r,
parsedSig.s
];
} else {
signatureArgs = [signature];
}
return signer.writeContract({
address: erc20Address,
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [...baseArgs, ...signatureArgs],
dataSuffix
});
}
// src/exact/v1/facilitator/scheme.ts
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 = {
eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],
simulateInSettle: config?.simulateInSettle ?? 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) {
return this._verify(payload, requirements);
}
/**
* Settles a payment by executing the transfer (V1).
*
* @param payload - The payment payload to settle
* @param requirements - The payment requirements
* @param context - Optional facilitator context for extension capabilities
* @returns Promise resolving to settlement response
*/
async settle(payload, requirements, context) {
const payloadV1 = payload;
const exactEvmPayload = payload.payload;
const valid = await this._verify(payload, requirements, {
simulate: this.config.simulateInSettle ?? false
});
if (!valid.isValid) {
return {
success: false,
network: payloadV1.network,
transaction: "",
errorReason: valid.invalidReason ?? ErrInvalidScheme,
payer: exactEvmPayload.authorization.from
};
}
try {
const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature2(
exactEvmPayload.signature
);
if (factoryAddress && factoryCalldata && !isAddressEqual2(factoryAddress, "0x0000000000000000000000000000000000000000")) {
const payerAddress = exactEvmPayload.authorization.from;
const bytecode = await this.signer.getCode({ address: payerAddress });
if (!bytecode || bytecode === "0x") {
const normalizedFactory = factoryAddress.toLowerCase();
const isAllowed = (this.config.eip6492AllowedFactories ?? []).some(
(allowed) => allowed.toLowerCase() === normalizedFactory
);
if (!isAllowed) {
return {
success: false,
errorReason: ErrFactoryNotAllowed,
transaction: "",
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
const deployTx = await this.signer.sendTransaction({
to: factoryAddress,
data: factoryCalldata
});
const deployReceipt = await this.signer.waitForTransactionReceipt({ hash: deployTx });
if (deployReceipt.status !== "success") {
return {
success: false,
errorReason: ErrSmartWalletDeploymentFailed,
transaction: "",
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
}
}
const dataSuffix = await resolveDataSuffix(context, {
paymentPayload: payload,
paymentRequirements: requirements
});
const tx = await executeTransferWithAuthorization(
this.signer,
getAddress3(requirements.asset),
exactEvmPayload,
dataSuffix
);
const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
if (receipt.status !== "success") {
return {
success: false,
errorReason: ErrTransactionFailed,
transaction: tx,
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
const auth = exactEvmPayload.authorization;
if (receipt.logs != null && !verifyEip3009TransferEvent(receipt.logs, getAddress3(requirements.asset), {
from: getAddress3(auth.from),
to: getAddress3(auth.to),
value: BigInt(auth.value)
})) {
return {
success: false,
errorReason: ErrTransferEventMismatch,
transaction: tx,
network: payloadV1.network,
payer: auth.from
};
}
return {
success: true,
transaction: tx,
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
} catch (error) {
return {
success: false,
errorReason: error instanceof Error ? error.message : ErrTransactionFailed,
transaction: "",
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
}
/**
* Internal verify with optional simulation control.
*
* @param payload - The payment payload to verify
* @param requirements - The payment requirements
* @param options - Verification options (e.g. simulate)
* @returns Promise resolving to verification response
*/
async _verify(payload, requirements, options) {
const requirementsV1 = requirements;
const payloadV1 = payload;
const exactEvmPayload = payload.payload;
const payer = exactEvmPayload.authorization.from;
let eip6492Deployment;
if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") {
return {
isValid: false,
invalidReason: ErrInvalidScheme,
payer
};
}
let chainId;
try {
chainId = getEvmChainIdV1(payloadV1.network);
} catch {
return {
isValid: false,
invalidReason: ErrNetworkMismatch,
payer
};
}
if (!requirements.extra?.name || !requirements.extra?.version) {
return {
isValid: false,
invalidReason: ErrMissingEip712Domain,
payer
};
}
const { name, version } = requirements.extra;
const erc20Address = getAddress3(requirements.asset);
if (payloadV1.network !== requirements.network) {
return {
isValid: false,
invalidReason: ErrNetworkMismatch,
payer
};
}
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
}
};
const signature = exactEvmPayload.signature;
const {
isCounterfactual,
innerSignature,
eip6492Deployment: classification6492
} = await classifyErc6492Payer(this.signer, signature, payer);
if (classification6492) {
eip6492Deployment = classification6492;
}
if (isCounterfactual) {
const factory = classification6492?.factoryAddress;
const factoryAllowed = !!factory && this.config.eip6492AllowedFactories.some(
(a) => a.trim().toLowerCase() === factory.toLowerCase()
);
if (!factoryAllowed) {
return {
isValid: false,
invalidReason: ErrFactoryNotAllowed,
payer
};
}
}
if (!isCounterfactual) {
const isValid = await verifyTypedDataSignature(this.signer, {
address: payer,
...permitTypedData,
signature: innerSignature
});
if (!isValid) {
return {
isValid: false,
invalidReason: ErrInvalidSignature,
payer
};
}
}
if (getAddress3(exactEvmPayload.authorization.to) !== getAddress3(requirements.payTo)) {
return {
isValid: false,
invalidReason: ErrRecipientMismatch,
payer
};
}
const now = Math.floor(Date.now() / 1e3);
if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
return {
isValid: false,
invalidReason: ErrValidBeforeExpired,
payer
};
}
if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
return {
isValid: false,
invalidReason: ErrValidAfterInFuture,
payer
};
}
if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {
return {
isValid: false,
invalidReason: ErrInvalidAuthorizationValue,
payer
};
}
if (options?.simulate !== false) {
const simulationSucceeded = await simulateEip3009Transfer(
this.signer,
erc20Address,
exactEvmPayload,
eip6492Deployment
);
if (!simulationSucceeded) {
return diagnoseEip3009SimulationFailure(
this.signer,
erc20Address,
exactEvmPayload,
requirements,
requirementsV1.maxAmountRequired
);
}
}
return {
isValid: true,
invalidReason: void 0,
payer
};
}
};
// src/v1/index.ts
var EVM_NETWORK_CHAIN_ID_MAP = {
ethereum: 1,
sepolia: 11155111,
abstract: 2741,
"abstract-testnet": 11124,
"base-sepolia": 84532,
base: 8453,
"avalanche-fuji": 43113,
avalanche: 43114,
iotex: 4689,
sei: 1329,
"sei-testnet": 1328,
polygon: 137,
"polygon-amoy": 80002,
peaq: 3338,
story: 1514,
educhain: 41923,
"skale-base-sepolia": 324705682,
megaeth: 4326,
monad: 143,
stable: 988,
"stable-testnet": 2201,
celo: 42220,
flare: 14
};
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
function getEvmChainIdV1(network) {
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
if (!chainId) {
throw new Error(`Unsupported v1 network: ${network}`);
}
return chainId;
}
export {
simulateEip3009TransferResult,
diagnoseEip3009SimulationFailure,
verifyEip3009TransferEvent,
parseEip3009TransferError,
executeTransferWithAuthorization,
ExactEvmSchemeV12 as ExactEvmSchemeV1,
EVM_NETWORK_CHAIN_ID_MAP,
NETWORKS,
getEvmChainIdV1,
ExactEvmSchemeV1 as ExactEvmSchemeV12
};
//# sourceMappingURL=chunk-NVFLWXGP.mjs.map
{"version":3,"sources":["../../src/exact/v1/client/scheme.ts","../../src/exact/v1/facilitator/scheme.ts","../../src/exact/facilitator/eip3009-utils.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 } from \"../../../utils\";\nimport { EvmNetworkV1, getEvmChainIdV1 } from \"../../../v1\";\n\n/**\n * EVM client implementation for the Exact payment scheme (V1).\n */\nexport class ExactEvmSchemeV1 implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClientV1 instance.\n *\n * @param signer - The EVM signer for client operations\n */\n constructor(private readonly signer: ClientEvmSigner) {}\n\n /**\n * Creates a payment payload for the Exact scheme (V1).\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n ): Promise<\n Pick<PaymentPayload, \"x402Version\" | \"payload\"> & { scheme: string; network: Network }\n > {\n const selectedV1 = paymentRequirements as unknown as PaymentRequirementsV1;\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEvmPayloadV1[\"authorization\"] = {\n from: this.signer.address,\n to: getAddress(selectedV1.payTo),\n value: selectedV1.maxAmountRequired,\n validAfter: (now - 600).toString(), // 10 minutes before\n validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n // Sign the authorization\n const signature = await this.signAuthorization(authorization, selectedV1);\n\n const payload: ExactEvmPayloadV1 = {\n authorization,\n signature,\n };\n\n return {\n x402Version,\n scheme: selectedV1.scheme,\n network: selectedV1.network,\n payload,\n };\n }\n\n /**\n * Sign the EIP-3009 authorization using EIP-712\n *\n * @param authorization - The authorization to sign\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\n private async signAuthorization(\n authorization: ExactEvmPayloadV1[\"authorization\"],\n requirements: PaymentRequirementsV1,\n ): Promise<`0x${string}`> {\n const chainId = getEvmChainIdV1(requirements.network as EvmNetworkV1);\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n throw new Error(\n `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n );\n }\n\n const { name, version } = requirements.extra;\n\n const domain = {\n name,\n version,\n chainId,\n verifyingContract: getAddress(requirements.asset),\n };\n\n const message = {\n from: getAddress(authorization.from),\n to: getAddress(authorization.to),\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce,\n };\n\n return await this.signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n }\n}\n","import {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { resolveDataSuffix } from \"../../../shared/extensions\";\nimport { verifyTypedDataSignature, classifyErc6492Payer } from \"../../../shared/verifySignature\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { EvmNetworkV1, getEvmChainIdV1 } from \"../../../v1\";\nimport * as Errors from \"../../facilitator/errors\";\nimport {\n diagnoseEip3009SimulationFailure,\n executeTransferWithAuthorization,\n simulateEip3009Transfer,\n verifyEip3009TransferEvent,\n} from \"../../facilitator/eip3009-utils\";\n\nexport interface VerifyV1Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. Facilitators must\n * explicitly list every factory they trust to prevent arbitrary transaction injection via\n * attacker-controlled ERC-6492 signature wrappers. An empty or omitted list denies all factory\n * deployment calls.\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme (V1).\n */\nexport class ExactEvmSchemeV1 implements SchemeNetworkFacilitator {\n readonly scheme = \"exact\";\n readonly caipFamily = \"eip155:*\";\n private readonly config: Required<ExactEvmSchemeV1Config>;\n\n /**\n * Creates a new ExactEvmFacilitatorV1 instance.\n *\n * @param signer - The EVM signer for facilitator operations\n * @param config - Optional configuration for the facilitator\n */\n constructor(\n private readonly signer: FacilitatorEvmSigner,\n config?: ExactEvmSchemeV1Config,\n ) {\n this.config = {\n eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],\n simulateInSettle: config?.simulateInSettle ?? false,\n };\n }\n\n /**\n * Get mechanism-specific extra data for the supported kinds endpoint.\n * For EVM, no extra data is needed.\n *\n * @param _ - The network identifier (unused for EVM)\n * @returns undefined (EVM has no extra data)\n */\n getExtra(_: string): Record<string, unknown> | undefined {\n return undefined;\n }\n\n /**\n * Get signer addresses used by this facilitator.\n * Returns all addresses this facilitator can use for signing/settling transactions.\n *\n * @param _ - The network identifier (unused for EVM, addresses are network-agnostic)\n * @returns Array of facilitator wallet addresses\n */\n getSigners(_: string): string[] {\n return [...this.signer.getAddresses()];\n }\n\n /**\n * Verifies a payment payload (V1).\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n return this._verify(payload, requirements);\n }\n\n /**\n * Settles a payment by executing the transfer (V1).\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<SettleResponse> {\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Re-verify before settling\n const valid = await this._verify(payload, requirements, {\n simulate: this.config.simulateInSettle ?? false,\n });\n if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable (for optional deployment)\n const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature(\n exactEvmPayload.signature!,\n );\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if factory is in the allowlist\n if (\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n const normalizedFactory = factoryAddress.toLowerCase();\n const isAllowed = (this.config.eip6492AllowedFactories ?? []).some(\n allowed => allowed.toLowerCase() === normalizedFactory,\n );\n if (!isAllowed) {\n return {\n success: false,\n errorReason: Errors.ErrFactoryNotAllowed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Send the factory calldata directly as a transaction\n // The factoryCalldata already contains the complete encoded function call\n const deployTx = await this.signer.sendTransaction({\n to: factoryAddress as Hex,\n data: factoryCalldata as Hex,\n });\n\n // Wait for deployment and verify it actually succeeded.\n const deployReceipt = await this.signer.waitForTransactionReceipt({ hash: deployTx });\n if (deployReceipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrSmartWalletDeploymentFailed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Do NOT re-simulate the transfer here. The authoritative pre-check is the atomic\n // deploy+transfer simulation in verify; a second standalone eth_call after the real\n // deploy tx races the deploy's state propagation across load-balanced RPC nodes and\n // false-rejected valid wallets. The on-chain transferWithAuthorization below is the\n // definitive signature check; a genuinely unsupported inner signature reverts there\n // and is classified by parseEip3009TransferError.\n }\n }\n\n // V1 payloads carry no extensions, so the builder-code suffix can only contain the\n // facilitator's own wallet code (`w`); client app (`a`) and service (`s`) codes are\n // always absent.\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n const tx = await executeTransferWithAuthorization(\n this.signer,\n getAddress(requirements.asset),\n exactEvmPayload,\n dataSuffix,\n );\n\n // Wait for transaction confirmation\n const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrTransactionFailed,\n transaction: tx,\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Receipt status only proves the tx did not revert.\n // When logs are present, require the expected ERC-20 Transfer event.\n const auth = exactEvmPayload.authorization;\n if (\n receipt.logs != null &&\n !verifyEip3009TransferEvent(receipt.logs, getAddress(requirements.asset), {\n from: getAddress(auth.from),\n to: getAddress(auth.to),\n value: BigInt(auth.value),\n })\n ) {\n return {\n success: false,\n errorReason: Errors.ErrTransferEventMismatch,\n transaction: tx,\n network: payloadV1.network,\n payer: auth.from,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n } catch (error) {\n return {\n success: false,\n errorReason: error instanceof Error ? error.message : Errors.ErrTransactionFailed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n }\n\n /**\n * Internal verify with optional simulation control.\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param options - Verification options (e.g. simulate)\n * @returns Promise resolving to verification response\n */\n private async _verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n options?: VerifyV1Options,\n ): Promise<VerifyResponse> {\n const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n const payer = exactEvmPayload.authorization.from;\n let eip6492Deployment:\n | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` }\n | undefined;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainIdV1(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: Errors.ErrMissingEip712Domain,\n payer,\n };\n }\n\n const { name, version } = requirements.extra as { name: string; version: string };\n const erc20Address = getAddress(requirements.asset);\n\n // Verify network matches\n if (payloadV1.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n // Build typed data for signature verification\n const permitTypedData = {\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\" as const,\n domain: {\n name,\n version,\n chainId,\n verifyingContract: erc20Address,\n },\n message: {\n from: exactEvmPayload.authorization.from,\n to: exactEvmPayload.authorization.to,\n value: BigInt(exactEvmPayload.authorization.value),\n validAfter: BigInt(exactEvmPayload.authorization.validAfter),\n validBefore: BigInt(exactEvmPayload.authorization.validBefore),\n nonce: exactEvmPayload.authorization.nonce,\n },\n };\n\n const signature = exactEvmPayload.signature!;\n\n // Classify the payer (counterfactual vs deployed) and extract inner sig in one shot.\n const {\n isCounterfactual,\n innerSignature,\n eip6492Deployment: classification6492,\n } = await classifyErc6492Payer(this.signer, signature, payer);\n\n if (classification6492) {\n eip6492Deployment = classification6492;\n }\n\n if (isCounterfactual) {\n // Mirror settle's allowlist gate so verify predicts settle: a counterfactual payment whose\n // factory is not allowlisted is rejected at settle, so reject it here too.\n const factory = classification6492?.factoryAddress;\n const factoryAllowed =\n !!factory &&\n this.config.eip6492AllowedFactories.some(\n a => a.trim().toLowerCase() === factory.toLowerCase(),\n );\n if (!factoryAllowed) {\n return {\n isValid: false,\n invalidReason: Errors.ErrFactoryNotAllowed,\n payer,\n };\n }\n }\n\n if (!isCounterfactual) {\n // Non-counterfactual path: verify using the strict primitive that mirrors\n // on-chain SignatureChecker semantics (ecrecover for EOAs, strict EIP-1271\n // for any address with code). No ECDSA fallback for code addresses.\n const isValid = await verifyTypedDataSignature(this.signer, {\n address: payer,\n ...permitTypedData,\n signature: innerSignature,\n });\n if (!isValid) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidSignature,\n payer,\n };\n }\n }\n // Counterfactual path: defer to on-chain simulation which deploys + verifies atomically.\n\n // Verify payment recipient matches\n if (getAddress(exactEvmPayload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrRecipientMismatch,\n payer,\n };\n }\n\n // Verify validBefore is in the future (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidBeforeExpired,\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidAfterInFuture,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidAuthorizationValue,\n payer,\n };\n }\n\n // Transaction simulation\n if (options?.simulate !== false) {\n const simulationSucceeded = await simulateEip3009Transfer(\n this.signer,\n erc20Address,\n exactEvmPayload,\n eip6492Deployment,\n );\n if (!simulationSucceeded) {\n return diagnoseEip3009SimulationFailure(\n this.signer,\n erc20Address,\n exactEvmPayload,\n requirements,\n requirementsV1.maxAmountRequired,\n );\n }\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n }\n}\n","import { PaymentRequirements, VerifyResponse } from \"@x402/core/types\";\nimport {\n encodeFunctionData,\n getAddress,\n Hex,\n isAddressEqual,\n parseErc6492Signature,\n parseEventLogs,\n parseSignature,\n type Log,\n} from \"viem\";\nimport { eip3009ABI } from \"../../constants\";\nimport { multicall, ContractCall, RawContractCall } from \"../../multicall\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport * as Errors from \"./errors\";\n\nconst erc20TransferEventAbi = [\n {\n type: \"event\",\n name: \"Transfer\",\n anonymous: false,\n inputs: [\n { name: \"from\", type: \"address\", indexed: true },\n { name: \"to\", type: \"address\", indexed: true },\n { name: \"value\", type: \"uint256\", indexed: false },\n ],\n },\n] as const;\n\nexport interface Eip6492Deployment {\n factoryAddress: `0x${string}`;\n factoryCalldata: `0x${string}`;\n}\n\n/**\n * Outcome of a transfer simulation. `error` is populated only when the underlying `eth_call`\n * threw (revert or transport), letting callers distinguish a contract revert from an RPC failure.\n */\nexport interface SimulateEip3009Result {\n ok: boolean;\n error?: unknown;\n}\n\n/**\n * Simulates transferWithAuthorization via eth_call.\n * Returns true if simulation succeeded, false if it failed.\n *\n * @param signer - EVM signer for contract reads\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param eip6492Deployment - Optional EIP-6492 factory info for undeployed smart wallets\n *\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulateEip3009Transfer(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n eip6492Deployment?: Eip6492Deployment,\n): Promise<boolean> {\n return (await simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment)).ok;\n}\n\n/**\n * Like {@link simulateEip3009Transfer} but returns the thrown error (if any) alongside the\n * boolean outcome, so callers can tell a contract revert apart from a transport/RPC failure.\n *\n * @param signer - EVM signer for contract reads\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param eip6492Deployment - Optional EIP-6492 factory info for undeployed smart wallets\n * @returns The simulation outcome and, on failure via a thrown error, that error.\n */\nexport async function simulateEip3009TransferResult(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n eip6492Deployment?: Eip6492Deployment,\n): Promise<SimulateEip3009Result> {\n const auth = payload.authorization;\n const transferArgs = [\n getAddress(auth.from),\n getAddress(auth.to),\n BigInt(auth.value),\n BigInt(auth.validAfter),\n BigInt(auth.validBefore),\n auth.nonce,\n ] as const;\n\n if (eip6492Deployment) {\n const { signature: innerSignature } = parseErc6492Signature(payload.signature!);\n const transferCalldata = encodeFunctionData({\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...transferArgs, innerSignature],\n });\n\n try {\n const results = await multicall(signer.readContract.bind(signer), [\n {\n address: getAddress(eip6492Deployment.factoryAddress),\n callData: eip6492Deployment.factoryCalldata,\n } satisfies RawContractCall,\n {\n address: erc20Address,\n callData: transferCalldata,\n } satisfies RawContractCall,\n ]);\n\n return { ok: results[1]?.status === \"success\" };\n } catch (error) {\n return { ok: false, error };\n }\n }\n\n const sig = payload.signature!;\n const sigLength = sig.startsWith(\"0x\") ? sig.length - 2 : sig.length;\n const isECDSA = sigLength === 130;\n\n try {\n if (isECDSA) {\n const parsedSig = parseSignature(sig);\n await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n ...transferArgs,\n (parsedSig.v as number | undefined) ?? parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...transferArgs, sig],\n });\n }\n return { ok: true };\n } catch (error) {\n return { ok: false, error };\n }\n}\n\n/**\n * After simulation fails, runs a single diagnostic multicall to determine the most specific error reason.\n * Checks balanceOf, name, version and authorizationState in one RPC round-trip.\n *\n * @param signer - EVM signer used for the payment\n * @param erc20Address - Address of the ERC-20 token contract\n * @param payload - The EIP-3009 transfer authorization payload\n * @param requirements - Payment requirements to validate against\n * @param amountRequired - Required amount for the payment (balance check)\n *\n * @returns Promise resolving to the verification result with validity and optional invalid reason\n */\nexport async function diagnoseEip3009SimulationFailure(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n requirements: PaymentRequirements,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const payer = payload.authorization.from;\n\n const diagnosticCalls: ContractCall[] = [\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payload.authorization.from],\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"name\",\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"version\",\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"authorizationState\",\n args: [payload.authorization.from, payload.authorization.nonce],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [balanceResult, nameResult, versionResult, authStateResult] = results;\n\n if (authStateResult.status === \"failure\") {\n return { isValid: false, invalidReason: Errors.ErrEip3009NotSupported, payer };\n }\n\n if (authStateResult.status === \"success\" && authStateResult.result === true) {\n return { isValid: false, invalidReason: Errors.ErrEip3009NonceAlreadyUsed, payer };\n }\n\n if (\n nameResult.status === \"success\" &&\n requirements.extra?.name &&\n nameResult.result !== requirements.extra.name\n ) {\n return { isValid: false, invalidReason: Errors.ErrEip3009TokenNameMismatch, payer };\n }\n\n if (\n versionResult.status === \"success\" &&\n requirements.extra?.version &&\n versionResult.result !== requirements.extra.version\n ) {\n return { isValid: false, invalidReason: Errors.ErrEip3009TokenVersionMismatch, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrEip3009InsufficientBalance,\n payer,\n };\n }\n }\n } catch {\n // Diagnostic multicall failed — fall through to generic error\n }\n\n return { isValid: false, invalidReason: Errors.ErrEip3009SimulationFailed, payer };\n}\n\n/**\n * Verifies that the post-settle receipt contains an ERC-20 Transfer event\n * emitted by the expected token contract whose (from, to, value) matches the\n * authorization.\n *\n * @param logs - Receipt logs to search for a matching Transfer\n * @param erc20Address - The ERC-20 token contract that should have emitted the Transfer\n * @param expected - The expected Transfer arguments from the authorization\n * @param expected.from - Expected `from` of the Transfer event\n * @param expected.to - Expected `to` of the Transfer event\n * @param expected.value - Expected `value` of the Transfer event\n * @returns true when a matching Transfer log is present, false otherwise\n */\nexport function verifyEip3009TransferEvent(\n logs: readonly Log[],\n erc20Address: `0x${string}`,\n expected: { from: `0x${string}`; to: `0x${string}`; value: bigint },\n): boolean {\n const transferLogs = parseEventLogs({\n abi: erc20TransferEventAbi,\n eventName: \"Transfer\",\n logs: logs.filter(log => isAddressEqual(log.address, erc20Address)),\n });\n return transferLogs.some(\n log =>\n isAddressEqual(log.args.from, expected.from) &&\n isAddressEqual(log.args.to, expected.to) &&\n log.args.value === expected.value,\n );\n}\n\n/**\n * Maps an EIP-3009 contract revert error to a specific error code.\n * Falls back to ErrTransactionFailed when the revert reason is unknown.\n *\n * @param error - The error thrown during transfer execution\n * @returns A specific error reason string\n */\nexport function parseEip3009TransferError(error: unknown): string {\n const msg = error instanceof Error ? error.message : String(error);\n if (/authorization.*(expired|valid before)/i.test(msg) || /AuthorizationExpired/i.test(msg)) {\n return Errors.ErrValidBeforeExpired;\n }\n if (/authorization.*not.*valid|AuthorizationNotYetValid/i.test(msg)) {\n return Errors.ErrValidAfterInFuture;\n }\n if (/authorization.*used|AuthorizationAlreadyUsed|AuthorizationUsedOrCanceled/i.test(msg)) {\n return Errors.ErrEip3009NonceAlreadyUsed;\n }\n if (/transfer.*exceeds.*balance|insufficient.*balance|ERC20InsufficientBalance/i.test(msg)) {\n return Errors.ErrEip3009InsufficientBalance;\n }\n if (/invalid.*signature|SignerMismatch|InvalidSignatureV|InvalidSignatureS/i.test(msg)) {\n return Errors.ErrInvalidSignature;\n }\n return Errors.ErrTransactionFailed;\n}\n\n/**\n * Executes transferWithAuthorization onchain.\n *\n * @param signer - EVM signer for contract writes\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param dataSuffix - Optional hex bytes to append after the ABI-encoded calldata\n *\n * @returns Transaction hash\n */\nexport async function executeTransferWithAuthorization(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n dataSuffix?: Hex,\n): Promise<Hex> {\n const { signature } = parseErc6492Signature(payload.signature!);\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n const auth = payload.authorization;\n const baseArgs = [\n getAddress(auth.from),\n getAddress(auth.to),\n BigInt(auth.value),\n BigInt(auth.validAfter),\n BigInt(auth.validBefore),\n auth.nonce,\n ] as const;\n\n let signatureArgs: readonly unknown[];\n if (isECDSA) {\n const parsedSig = parseSignature(signature);\n signatureArgs = [\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ];\n } else {\n signatureArgs = [signature];\n }\n\n return signer.writeContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...baseArgs, ...signatureArgs],\n dataSuffix,\n });\n}\n","export { ExactEvmSchemeV1 } from \"../exact/v1\";\n\nexport const EVM_NETWORK_CHAIN_ID_MAP = {\n ethereum: 1,\n sepolia: 11155111,\n abstract: 2741,\n \"abstract-testnet\": 11124,\n \"base-sepolia\": 84532,\n base: 8453,\n \"avalanche-fuji\": 43113,\n avalanche: 43114,\n iotex: 4689,\n sei: 1329,\n \"sei-testnet\": 1328,\n polygon: 137,\n \"polygon-amoy\": 80002,\n peaq: 3338,\n story: 1514,\n educhain: 41923,\n \"skale-base-sepolia\": 324705682,\n megaeth: 4326,\n monad: 143,\n stable: 988,\n \"stable-testnet\": 2201,\n celo: 42220,\n flare: 14,\n} as const;\n\nexport type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP;\n\nexport const NETWORKS: string[] = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);\n\n/**\n * Extract chain ID from a v1 legacy network name.\n *\n * @param network - The v1 network name (e.g., \"base-sepolia\", \"polygon\")\n * @returns The numeric chain ID\n * @throws Error if the network name is not a known v1 network\n */\nexport function getEvmChainIdV1(network: string): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network as EvmNetworkV1];\n if (!chainId) {\n throw new Error(`Unsupported v1 network: ${network}`);\n }\n return chainId;\n}\n"],"mappings":"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","names":["getAddress","isAddressEqual","parseErc6492Signature","getAddress","getAddress","ExactEvmSchemeV1","parseErc6492Signature","isAddressEqual","getAddress"]}
import {
createPermit2PayloadForProxy
} from "./chunk-JFVEMVMS.mjs";
import {
PERMIT2_ADDRESS,
erc20AllowanceAbi,
erc20ApproveAbi,
x402ExactPermit2ProxyAddress
} from "./chunk-MACPBXCT.mjs";
// src/exact/client/permit2.ts
import { encodeFunctionData, getAddress } from "viem";
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
return createPermit2PayloadForProxy(
x402ExactPermit2ProxyAddress,
signer,
x402Version,
paymentRequirements
);
}
function createPermit2ApprovalTx(tokenAddress) {
const data = encodeFunctionData({
abi: erc20ApproveAbi,
functionName: "approve",
args: [PERMIT2_ADDRESS, MAX_UINT256]
});
return {
to: getAddress(tokenAddress),
data
};
}
function getPermit2AllowanceReadParams(params) {
return {
address: getAddress(params.tokenAddress),
abi: erc20AllowanceAbi,
functionName: "allowance",
args: [getAddress(params.ownerAddress), PERMIT2_ADDRESS]
};
}
export {
createPermit2Payload,
createPermit2ApprovalTx,
getPermit2AllowanceReadParams
};
//# sourceMappingURL=chunk-UBBS476I.mjs.map
{"version":3,"sources":["../../src/exact/client/permit2.ts"],"sourcesContent":["import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport {\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n erc20ApproveAbi,\n erc20AllowanceAbi,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { createPermit2PayloadForProxy } from \"../../shared/permit2\";\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 return createPermit2PayloadForProxy(\n x402ExactPermit2ProxyAddress,\n signer,\n x402Version,\n paymentRequirements,\n );\n}\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"],"mappings":";;;;;;;;;;;AACA,SAAS,oBAAoB,kBAAkB;AAW/C,IAAM,cAAc,OAAO,oEAAoE;AAY/F,eAAsB,qBACpB,QACA,aACA,qBAC+B;AAC/B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAkBO,SAAS,wBAAwB,cAGtC;AACA,QAAM,OAAO,mBAAmB;AAAA,IAC9B,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,iBAAiB,WAAW;AAAA,EACrC,CAAC;AAED,SAAO;AAAA,IACL,IAAI,WAAW,YAAY;AAAA,IAC3B;AAAA,EACF;AACF;AA6BO,SAAS,8BAA8B,QAK5C;AACA,SAAO;AAAA,IACL,SAAS,WAAW,OAAO,YAAY;AAAA,IACvC,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,WAAW,OAAO,YAAY,GAAG,eAAe;AAAA,EACzD;AACF;","names":[]}
+3
-1

@@ -622,3 +622,5 @@ "use strict";

stable: 988,
"stable-testnet": 2201
"stable-testnet": 2201,
celo: 42220,
flare: 14
};

@@ -625,0 +627,0 @@ var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);

@@ -175,4 +175,25 @@ "use strict";

assetTransferMethod: "permit2"
},
// Igra mainnet USDC (no EIP-3009, no EIP-2612)
"eip155:14": {
address: "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
name: "USD\u20AE0",
version: "1",
decimals: 6
},
// Flare mainnet USD₮0 (EIP-3009 supported)
"eip155:42220": {
address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
name: "USDC",
version: "2",
decimals: 6
},
// Celo mainnet USDC (EIP-3009 supported)
"eip155:11142220": {
address: "0x01C5C0122039549AD1493B8220cABEdD739BC44E",
name: "USDC",
version: "2",
decimals: 6
}
// Igra mainnet USDC (no EIP-3009, no EIP-2612)
// Celo Sepolia testnet USDC (EIP-3009 supported)
};

@@ -179,0 +200,0 @@ function getDefaultAsset(network) {

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../../src/exact/server/index.ts","../../../../src/exact/server/scheme.ts","../../../../src/shared/defaultAssets.ts","../../../../src/exact/server/register.ts"],"sourcesContent":["export { ExactEvmScheme } from \"./scheme\";\nexport { registerExactEvmScheme } from \"./register\";\nexport type { EvmResourceServerConfig } from \"./register\";\n","import {\n AssetAmount,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n MoneyParser,\n} from \"@x402/core/types\";\nimport { convertToTokenAmount, numberToDecimalString, parseMoneyString } from \"@x402/core/utils\";\nimport { getDefaultAsset, type ExactDefaultAssetInfo } from \"../../shared/defaultAssets\";\n\n/**\n * EVM server implementation for the Exact payment scheme.\n */\nexport class ExactEvmScheme implements SchemeNetworkServer {\n readonly scheme = \"exact\";\n private moneyParsers: MoneyParser[] = [];\n\n /**\n * Register a custom money parser in the parser chain.\n * Multiple parsers can be registered - they will be tried in registration order.\n * Each parser receives a decimal amount (e.g., 1.50 for $1.50).\n * If a parser returns null, the next parser in the chain will be tried.\n * The default parser is always the final fallback.\n *\n * @param parser - Custom function to convert amount to AssetAmount (or null to skip)\n * @returns The server instance for chaining\n *\n * @example\n * evmServer.registerMoneyParser(async (amount, network) => {\n * // Custom conversion logic\n * if (amount > 100) {\n * // Use different token for large amounts\n * return { amount: (amount * 1e18).toString(), asset: \"0xCustomToken\" };\n * }\n * return null; // Use next parser\n * });\n */\n registerMoneyParser(parser: MoneyParser): ExactEvmScheme {\n this.moneyParsers.push(parser);\n return this;\n }\n\n /**\n * Returns the decimal precision of the default stablecoin for the given network.\n * Implements the optional AssetDecimalsProvider interface used by resolveSettlementOverrideAmount.\n *\n * @param _asset - The asset symbol (unused; defaults to the network's default stablecoin)\n * @param network - The network to look up the default asset for\n * @returns The number of decimal places for the asset\n */\n getAssetDecimals(_asset: string, network: Network): number {\n try {\n return getDefaultAsset(network).decimals;\n } catch {\n return 6;\n }\n }\n\n /**\n * Parses a price into an asset amount.\n * If price is already an AssetAmount, returns it directly.\n * If price is Money (string | number), parses to decimal and tries custom parsers.\n * Falls back to default conversion if all custom parsers return null.\n *\n * @param price - The price to parse\n * @param network - The network to use\n * @returns Promise that resolves to the parsed asset amount\n */\n async parsePrice(price: Price, network: Network): Promise<AssetAmount> {\n // If already an AssetAmount, return it directly\n if (typeof price === \"object\" && price !== null && \"amount\" in price) {\n if (!price.asset) {\n throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);\n }\n return {\n amount: price.amount,\n asset: price.asset,\n extra: price.extra || {},\n };\n }\n\n // Parse Money to decimal number\n const amount = this.parseMoneyToDecimal(price);\n\n // Try each custom money parser in order\n for (const parser of this.moneyParsers) {\n const result = await parser(amount, network);\n if (result !== null) {\n return result;\n }\n }\n\n // All custom parsers returned null, use default conversion\n return this.defaultMoneyConversion(amount, network);\n }\n\n /**\n * Build payment requirements for this scheme/network combination\n *\n * @param paymentRequirements - The base payment requirements\n * @param supportedKind - The supported kind from facilitator (unused)\n * @param supportedKind.x402Version - The x402 version\n * @param supportedKind.scheme - The logical payment scheme\n * @param supportedKind.network - The network identifier in CAIP-2 format\n * @param supportedKind.extra - Optional extra metadata regarding scheme/network implementation details\n * @param extensionKeys - Extension keys supported by the facilitator (unused)\n * @returns Payment requirements ready to be sent to clients\n */\n enhancePaymentRequirements(\n paymentRequirements: PaymentRequirements,\n supportedKind: {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n },\n extensionKeys: string[],\n ): Promise<PaymentRequirements> {\n // Mark unused parameters to satisfy linter\n void supportedKind;\n void extensionKeys;\n return Promise.resolve(paymentRequirements);\n }\n\n /**\n * Parse Money (string | number) to a decimal number.\n * Handles formats like \"$1.50\", \"1.50\", 1.50, etc.\n *\n * @param money - The money value to parse\n * @returns Decimal number\n */\n private parseMoneyToDecimal(money: string | number): number {\n if (typeof money === \"number\") {\n return money;\n }\n\n return parseMoneyString(money);\n }\n\n /**\n * Converts a numeric dollar amount to an AssetAmount using the default token for the network.\n *\n * @param amount - The dollar amount as a number\n * @param network - The target network\n * @returns The converted asset amount with token metadata\n */\n private defaultMoneyConversion(amount: number, network: Network): AssetAmount {\n const assetInfo: ExactDefaultAssetInfo = getDefaultAsset(network);\n const tokenAmount = convertToTokenAmount(numberToDecimalString(amount), assetInfo.decimals);\n\n // EIP-3009 tokens always need name/version for their transferWithAuthorization domain.\n // Permit2 tokens only need them if the token supports EIP-2612 (for gasless permit signing).\n // Omitting name/version for permit2 tokens signals the client to skip EIP-2612 and use\n // ERC-20 approval gas sponsoring instead.\n const includeEip712Domain = !assetInfo.assetTransferMethod || assetInfo.supportsEip2612;\n\n return {\n amount: tokenAmount,\n asset: assetInfo.address,\n extra: {\n ...(includeEip712Domain && {\n name: assetInfo.name,\n version: assetInfo.version,\n }),\n ...(assetInfo.assetTransferMethod && {\n assetTransferMethod: assetInfo.assetTransferMethod,\n }),\n },\n };\n }\n}\n","import type { Network } from \"@x402/core/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSET.md in\n * exact/server/ for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31612\": {\n address: \"0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:723487\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Network SBC (no EIP-3009, supports EIP-2612)\n \"eip155:72344\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Testnet SBC (no EIP-3009, supports EIP-2612)\n \"eip155:36900\": {\n address: \"0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2\",\n name: \"USDC.e\",\n version: \"2\",\n decimals: 6,\n }, // ADI Chain USDC.e (EIP-3009 supported)\n \"eip155:190415\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP mainnet USDC.e\n \"eip155:181228\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP Sepolia USDC.e\n \"eip155:50\": {\n address: \"0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:51\": {\n address: \"0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:38833\": {\n address: \"0xA5b8BF902b2844dA17d4506cc827F7F1681735E7\",\n name: \"USDC\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n }, // Igra mainnet USDC (no EIP-3009, no EIP-2612)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n","import { x402ResourceServer } from \"@x402/core/server\";\nimport { Network } from \"@x402/core/types\";\nimport { ExactEvmScheme } from \"./scheme\";\n\n/**\n * Configuration options for registering EVM schemes to an x402ResourceServer\n */\nexport interface EvmResourceServerConfig {\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 x402ResourceServer instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n *\n * @param server - The x402ResourceServer instance to register schemes to\n * @param config - Configuration for EVM resource server registration\n * @returns The server instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/server/register\";\n * import { x402ResourceServer } from \"@x402/core/server\";\n *\n * const server = new x402ResourceServer(facilitatorClient);\n * registerExactEvmScheme(server, {});\n * ```\n */\nexport function registerExactEvmScheme(\n server: x402ResourceServer,\n config: EvmResourceServerConfig = {},\n): x402ResourceServer {\n // Register V2 scheme\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n server.register(network, new ExactEvmScheme());\n });\n } else {\n // Register wildcard for all EVM chains\n server.register(\"eip155:*\", new ExactEvmScheme());\n }\n\n return server;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQA,mBAA8E;;;ACkCvE,IAAM,sBAA6D;AAAA,EACxE,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,EACvB;AAAA;AACF;AASO,SAAS,gBAAgB,SAAyC;AACvE,QAAM,OAAO,oBAAoB,OAAO;AACxC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,2CAA2C,OAAO,EAAE;AAAA,EACtE;AACA,SAAO;AACT;;;ADzKO,IAAM,iBAAN,MAAoD;AAAA,EAApD;AACL,SAAS,SAAS;AAClB,SAAQ,eAA8B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBvC,oBAAoB,QAAqC;AACvD,SAAK,aAAa,KAAK,MAAM;AAC7B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,iBAAiB,QAAgB,SAA0B;AACzD,QAAI;AACF,aAAO,gBAAgB,OAAO,EAAE;AAAA,IAClC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,WAAW,OAAc,SAAwC;AAErE,QAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY,OAAO;AACpE,UAAI,CAAC,MAAM,OAAO;AAChB,cAAM,IAAI,MAAM,8DAA8D,OAAO,EAAE;AAAA,MACzF;AACA,aAAO;AAAA,QACL,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM;AAAA,QACb,OAAO,MAAM,SAAS,CAAC;AAAA,MACzB;AAAA,IACF;AAGA,UAAM,SAAS,KAAK,oBAAoB,KAAK;AAG7C,eAAW,UAAU,KAAK,cAAc;AACtC,YAAM,SAAS,MAAM,OAAO,QAAQ,OAAO;AAC3C,UAAI,WAAW,MAAM;AACnB,eAAO;AAAA,MACT;AAAA,IACF;AAGA,WAAO,KAAK,uBAAuB,QAAQ,OAAO;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,2BACE,qBACA,eAMA,eAC8B;AAE9B,SAAK;AACL,SAAK;AACL,WAAO,QAAQ,QAAQ,mBAAmB;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,oBAAoB,OAAgC;AAC1D,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO;AAAA,IACT;AAEA,eAAO,+BAAiB,KAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,uBAAuB,QAAgB,SAA+B;AAC5E,UAAM,YAAmC,gBAAgB,OAAO;AAChE,UAAM,kBAAc,uCAAqB,oCAAsB,MAAM,GAAG,UAAU,QAAQ;AAM1F,UAAM,sBAAsB,CAAC,UAAU,uBAAuB,UAAU;AAExE,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,UAAU;AAAA,MACjB,OAAO;AAAA,QACL,GAAI,uBAAuB;AAAA,UACzB,MAAM,UAAU;AAAA,UAChB,SAAS,UAAU;AAAA,QACrB;AAAA,QACA,GAAI,UAAU,uBAAuB;AAAA,UACnC,qBAAqB,UAAU;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AEzIO,SAAS,uBACd,QACA,SAAkC,CAAC,GACf;AAEpB,MAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AAEjD,WAAO,SAAS,QAAQ,aAAW;AACjC,aAAO,SAAS,SAAS,IAAI,eAAe,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH,OAAO;AAEL,WAAO,SAAS,YAAY,IAAI,eAAe,CAAC;AAAA,EAClD;AAEA,SAAO;AACT;","names":[]}
{"version":3,"sources":["../../../../src/exact/server/index.ts","../../../../src/exact/server/scheme.ts","../../../../src/shared/defaultAssets.ts","../../../../src/exact/server/register.ts"],"sourcesContent":["export { ExactEvmScheme } from \"./scheme\";\nexport { registerExactEvmScheme } from \"./register\";\nexport type { EvmResourceServerConfig } from \"./register\";\n","import {\n AssetAmount,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n MoneyParser,\n} from \"@x402/core/types\";\nimport { convertToTokenAmount, numberToDecimalString, parseMoneyString } from \"@x402/core/utils\";\nimport { getDefaultAsset, type ExactDefaultAssetInfo } from \"../../shared/defaultAssets\";\n\n/**\n * EVM server implementation for the Exact payment scheme.\n */\nexport class ExactEvmScheme implements SchemeNetworkServer {\n readonly scheme = \"exact\";\n private moneyParsers: MoneyParser[] = [];\n\n /**\n * Register a custom money parser in the parser chain.\n * Multiple parsers can be registered - they will be tried in registration order.\n * Each parser receives a decimal amount (e.g., 1.50 for $1.50).\n * If a parser returns null, the next parser in the chain will be tried.\n * The default parser is always the final fallback.\n *\n * @param parser - Custom function to convert amount to AssetAmount (or null to skip)\n * @returns The server instance for chaining\n *\n * @example\n * evmServer.registerMoneyParser(async (amount, network) => {\n * // Custom conversion logic\n * if (amount > 100) {\n * // Use different token for large amounts\n * return { amount: (amount * 1e18).toString(), asset: \"0xCustomToken\" };\n * }\n * return null; // Use next parser\n * });\n */\n registerMoneyParser(parser: MoneyParser): ExactEvmScheme {\n this.moneyParsers.push(parser);\n return this;\n }\n\n /**\n * Returns the decimal precision of the default stablecoin for the given network.\n * Implements the optional AssetDecimalsProvider interface used by resolveSettlementOverrideAmount.\n *\n * @param _asset - The asset symbol (unused; defaults to the network's default stablecoin)\n * @param network - The network to look up the default asset for\n * @returns The number of decimal places for the asset\n */\n getAssetDecimals(_asset: string, network: Network): number {\n try {\n return getDefaultAsset(network).decimals;\n } catch {\n return 6;\n }\n }\n\n /**\n * Parses a price into an asset amount.\n * If price is already an AssetAmount, returns it directly.\n * If price is Money (string | number), parses to decimal and tries custom parsers.\n * Falls back to default conversion if all custom parsers return null.\n *\n * @param price - The price to parse\n * @param network - The network to use\n * @returns Promise that resolves to the parsed asset amount\n */\n async parsePrice(price: Price, network: Network): Promise<AssetAmount> {\n // If already an AssetAmount, return it directly\n if (typeof price === \"object\" && price !== null && \"amount\" in price) {\n if (!price.asset) {\n throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);\n }\n return {\n amount: price.amount,\n asset: price.asset,\n extra: price.extra || {},\n };\n }\n\n // Parse Money to decimal number\n const amount = this.parseMoneyToDecimal(price);\n\n // Try each custom money parser in order\n for (const parser of this.moneyParsers) {\n const result = await parser(amount, network);\n if (result !== null) {\n return result;\n }\n }\n\n // All custom parsers returned null, use default conversion\n return this.defaultMoneyConversion(amount, network);\n }\n\n /**\n * Build payment requirements for this scheme/network combination\n *\n * @param paymentRequirements - The base payment requirements\n * @param supportedKind - The supported kind from facilitator (unused)\n * @param supportedKind.x402Version - The x402 version\n * @param supportedKind.scheme - The logical payment scheme\n * @param supportedKind.network - The network identifier in CAIP-2 format\n * @param supportedKind.extra - Optional extra metadata regarding scheme/network implementation details\n * @param extensionKeys - Extension keys supported by the facilitator (unused)\n * @returns Payment requirements ready to be sent to clients\n */\n enhancePaymentRequirements(\n paymentRequirements: PaymentRequirements,\n supportedKind: {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n },\n extensionKeys: string[],\n ): Promise<PaymentRequirements> {\n // Mark unused parameters to satisfy linter\n void supportedKind;\n void extensionKeys;\n return Promise.resolve(paymentRequirements);\n }\n\n /**\n * Parse Money (string | number) to a decimal number.\n * Handles formats like \"$1.50\", \"1.50\", 1.50, etc.\n *\n * @param money - The money value to parse\n * @returns Decimal number\n */\n private parseMoneyToDecimal(money: string | number): number {\n if (typeof money === \"number\") {\n return money;\n }\n\n return parseMoneyString(money);\n }\n\n /**\n * Converts a numeric dollar amount to an AssetAmount using the default token for the network.\n *\n * @param amount - The dollar amount as a number\n * @param network - The target network\n * @returns The converted asset amount with token metadata\n */\n private defaultMoneyConversion(amount: number, network: Network): AssetAmount {\n const assetInfo: ExactDefaultAssetInfo = getDefaultAsset(network);\n const tokenAmount = convertToTokenAmount(numberToDecimalString(amount), assetInfo.decimals);\n\n // EIP-3009 tokens always need name/version for their transferWithAuthorization domain.\n // Permit2 tokens only need them if the token supports EIP-2612 (for gasless permit signing).\n // Omitting name/version for permit2 tokens signals the client to skip EIP-2612 and use\n // ERC-20 approval gas sponsoring instead.\n const includeEip712Domain = !assetInfo.assetTransferMethod || assetInfo.supportsEip2612;\n\n return {\n amount: tokenAmount,\n asset: assetInfo.address,\n extra: {\n ...(includeEip712Domain && {\n name: assetInfo.name,\n version: assetInfo.version,\n }),\n ...(assetInfo.assetTransferMethod && {\n assetTransferMethod: assetInfo.assetTransferMethod,\n }),\n },\n };\n }\n}\n","import type { Network } from \"@x402/core/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSETS.md at the\n * repository root for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31612\": {\n address: \"0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:723487\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Network SBC (no EIP-3009, supports EIP-2612)\n \"eip155:72344\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Testnet SBC (no EIP-3009, supports EIP-2612)\n \"eip155:36900\": {\n address: \"0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2\",\n name: \"USDC.e\",\n version: \"2\",\n decimals: 6,\n }, // ADI Chain USDC.e (EIP-3009 supported)\n \"eip155:190415\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP mainnet USDC.e\n \"eip155:181228\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP Sepolia USDC.e\n \"eip155:50\": {\n address: \"0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:51\": {\n address: \"0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:38833\": {\n address: \"0xA5b8BF902b2844dA17d4506cc827F7F1681735E7\",\n name: \"USDC\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n }, // Igra mainnet USDC (no EIP-3009, no EIP-2612)\n \"eip155:14\": {\n address: \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\",\n name: \"USD\\u20AE0\",\n version: \"1\",\n decimals: 6,\n }, // Flare mainnet USD₮0 (EIP-3009 supported)\n \"eip155:42220\": {\n address: \"0xcebA9300f2b948710d2653dD7B07f33A8B32118C\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Celo mainnet USDC (EIP-3009 supported)\n \"eip155:11142220\": {\n address: \"0x01C5C0122039549AD1493B8220cABEdD739BC44E\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Celo Sepolia testnet USDC (EIP-3009 supported)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n","import { x402ResourceServer } from \"@x402/core/server\";\nimport { Network } from \"@x402/core/types\";\nimport { ExactEvmScheme } from \"./scheme\";\n\n/**\n * Configuration options for registering EVM schemes to an x402ResourceServer\n */\nexport interface EvmResourceServerConfig {\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 x402ResourceServer instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n *\n * @param server - The x402ResourceServer instance to register schemes to\n * @param config - Configuration for EVM resource server registration\n * @returns The server instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/server/register\";\n * import { x402ResourceServer } from \"@x402/core/server\";\n *\n * const server = new x402ResourceServer(facilitatorClient);\n * registerExactEvmScheme(server, {});\n * ```\n */\nexport function registerExactEvmScheme(\n server: x402ResourceServer,\n config: EvmResourceServerConfig = {},\n): x402ResourceServer {\n // Register V2 scheme\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n server.register(network, new ExactEvmScheme());\n });\n } else {\n // Register wildcard for all EVM chains\n server.register(\"eip155:*\", new ExactEvmScheme());\n }\n\n return server;\n}\n"],"mappings":"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","names":[]}

@@ -101,3 +101,5 @@ "use strict";

stable: 988,
"stable-testnet": 2201
"stable-testnet": 2201,
celo: 42220,
flare: 14
};

@@ -104,0 +106,0 @@ var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);

@@ -274,3 +274,5 @@ "use strict";

stable: 988,
"stable-testnet": 2201
"stable-testnet": 2201,
celo: 42220,
flare: 14
};

@@ -296,2 +298,3 @@ var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);

var ErrTransactionFailed = "invalid_exact_evm_transaction_failed";
var ErrTransferEventMismatch = "invalid_exact_evm_transfer_event_mismatch";
var ErrEip3009TokenNameMismatch = "invalid_exact_evm_token_name_mismatch";

@@ -386,2 +389,14 @@ var ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch";

// src/exact/facilitator/eip3009-utils.ts
var erc20TransferEventAbi = [
{
type: "event",
name: "Transfer",
anonymous: false,
inputs: [
{ name: "from", type: "address", indexed: true },
{ name: "to", type: "address", indexed: true },
{ name: "value", type: "uint256", indexed: false }
]
}
];
async function simulateEip3009Transfer(signer, erc20Address, payload, eip6492Deployment) {

@@ -508,2 +523,12 @@ return (await simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment)).ok;

}
function verifyEip3009TransferEvent(logs, erc20Address, expected) {
const transferLogs = (0, import_viem9.parseEventLogs)({
abi: erc20TransferEventAbi,
eventName: "Transfer",
logs: logs.filter((log) => (0, import_viem9.isAddressEqual)(log.address, erc20Address))
});
return transferLogs.some(
(log) => (0, import_viem9.isAddressEqual)(log.args.from, expected.from) && (0, import_viem9.isAddressEqual)(log.args.to, expected.to) && log.args.value === expected.value
);
}
async function executeTransferWithAuthorization(signer, erc20Address, payload, dataSuffix) {

@@ -669,2 +694,16 @@ const { signature } = (0, import_viem9.parseErc6492Signature)(payload.signature);

}
const auth = exactEvmPayload.authorization;
if (receipt.logs != null && !verifyEip3009TransferEvent(receipt.logs, (0, import_viem10.getAddress)(requirements.asset), {
from: (0, import_viem10.getAddress)(auth.from),
to: (0, import_viem10.getAddress)(auth.to),
value: BigInt(auth.value)
})) {
return {
success: false,
errorReason: ErrTransferEventMismatch,
transaction: tx,
network: payloadV1.network,
payer: auth.from
};
}
return {

@@ -671,0 +710,0 @@ success: true,

@@ -207,4 +207,4 @@ export { E as ExactEvmScheme } from './scheme-DbvdjMb_.js';

* Each network has the right to determine its own default stablecoin that can
* be expressed as a USD string by calling servers. See DEFAULT_ASSET.md in
* exact/server/ for how to add new chains.
* be expressed as a USD string by calling servers. See DEFAULT_ASSETS.md at the
* repository root for how to add new chains.
*/

@@ -211,0 +211,0 @@ declare const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo>;

@@ -175,4 +175,25 @@ "use strict";

assetTransferMethod: "permit2"
},
// Igra mainnet USDC (no EIP-3009, no EIP-2612)
"eip155:14": {
address: "0xe7cd86e13AC4309349F30B3435a9d337750fC82D",
name: "USD\u20AE0",
version: "1",
decimals: 6
},
// Flare mainnet USD₮0 (EIP-3009 supported)
"eip155:42220": {
address: "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
name: "USDC",
version: "2",
decimals: 6
},
// Celo mainnet USDC (EIP-3009 supported)
"eip155:11142220": {
address: "0x01C5C0122039549AD1493B8220cABEdD739BC44E",
name: "USDC",
version: "2",
decimals: 6
}
// Igra mainnet USDC (no EIP-3009, no EIP-2612)
// Celo Sepolia testnet USDC (EIP-3009 supported)
};

@@ -179,0 +200,0 @@ function getDefaultAsset(network) {

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../../src/upto/server/index.ts","../../../../src/upto/server/scheme.ts","../../../../src/shared/defaultAssets.ts"],"sourcesContent":["// Note: No register.ts helper — V1 backward compatibility is not needed for upto.\n// Use direct class instantiation: server.register(\"eip155:*\", new UptoEvmScheme())\nexport { UptoEvmScheme } from \"./scheme\";\n","import {\n AssetAmount,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n MoneyParser,\n} from \"@x402/core/types\";\nimport { convertToTokenAmount, numberToDecimalString, parseMoneyString } from \"@x402/core/utils\";\nimport { getAddress } from \"viem\";\nimport { getDefaultAsset } from \"../../shared/defaultAssets\";\n\n/**\n * EVM server implementation for the Upto payment scheme.\n * Handles price parsing, payment requirements enhancement, and default asset resolution.\n */\nexport class UptoEvmScheme implements SchemeNetworkServer {\n readonly scheme = \"upto\";\n private moneyParsers: MoneyParser[] = [];\n\n /**\n * Registers a custom money parser for converting prices to asset amounts.\n *\n * @param parser - The money parser function to register\n * @returns This instance for chaining\n */\n registerMoneyParser(parser: MoneyParser): UptoEvmScheme {\n this.moneyParsers.push(parser);\n return this;\n }\n\n /**\n * Returns the decimal precision of the default stablecoin for the given network.\n * Implements the optional AssetDecimalsProvider interface used by resolveSettlementOverrideAmount.\n *\n * @param _asset - The asset symbol (unused; defaults to the network's default stablecoin)\n * @param network - The network to look up the default asset for\n * @returns The number of decimal places for the asset\n */\n getAssetDecimals(_asset: string, network: Network): number {\n try {\n return getDefaultAsset(network).decimals;\n } catch {\n return 6;\n }\n }\n\n /**\n * Parses a price into an asset amount for the given network.\n *\n * @param price - The price to parse (string, number, or AssetAmount)\n * @param network - The target network\n * @returns Promise resolving to an asset amount\n */\n async parsePrice(price: Price, network: Network): Promise<AssetAmount> {\n if (typeof price === \"object\" && price !== null && \"amount\" in price) {\n if (!price.asset) {\n throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);\n }\n return {\n amount: price.amount,\n asset: price.asset,\n extra: price.extra || {},\n };\n }\n\n const amount = this.parseMoneyToDecimal(price);\n\n for (const parser of this.moneyParsers) {\n const result = await parser(amount, network);\n if (result !== null) {\n return result;\n }\n }\n\n return this.defaultMoneyConversion(amount, network);\n }\n\n /**\n * Enhances payment requirements with upto-specific metadata.\n *\n * @param paymentRequirements - The base payment requirements\n * @param supportedKind - The supported scheme/network kind\n * @param supportedKind.x402Version - The x402 protocol version\n * @param supportedKind.scheme - The payment scheme name\n * @param supportedKind.network - The target network\n * @param supportedKind.extra - Optional extra metadata\n * @param extensionKeys - Extension keys to include\n * @returns Promise resolving to enhanced payment requirements\n */\n enhancePaymentRequirements(\n paymentRequirements: PaymentRequirements,\n supportedKind: {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n },\n extensionKeys: string[],\n ): Promise<PaymentRequirements> {\n void extensionKeys;\n return Promise.resolve({\n ...paymentRequirements,\n extra: {\n ...paymentRequirements.extra,\n assetTransferMethod: \"permit2\",\n ...(supportedKind.extra?.facilitatorAddress\n ? { facilitatorAddress: getAddress(supportedKind.extra.facilitatorAddress as string) }\n : {}),\n },\n });\n }\n\n /**\n * Parses a money string or number into a decimal value.\n *\n * @param money - The money value to parse\n * @returns The parsed decimal amount\n */\n private parseMoneyToDecimal(money: string | number): number {\n if (typeof money === \"number\") {\n return money;\n }\n\n return parseMoneyString(money);\n }\n\n /**\n * Converts a numeric dollar amount to an AssetAmount using the default token for the network.\n *\n * @param amount - The dollar amount as a number\n * @param network - The target network\n * @returns The converted asset amount with token metadata\n */\n private defaultMoneyConversion(amount: number, network: Network): AssetAmount {\n const assetInfo = getDefaultAsset(network);\n const tokenAmount = convertToTokenAmount(numberToDecimalString(amount), assetInfo.decimals);\n\n return {\n amount: tokenAmount,\n asset: assetInfo.address,\n extra: {\n name: assetInfo.name,\n version: assetInfo.version,\n assetTransferMethod: \"permit2\",\n },\n };\n }\n}\n","import type { Network } from \"@x402/core/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSET.md in\n * exact/server/ for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31612\": {\n address: \"0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:723487\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Network SBC (no EIP-3009, supports EIP-2612)\n \"eip155:72344\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Testnet SBC (no EIP-3009, supports EIP-2612)\n \"eip155:36900\": {\n address: \"0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2\",\n name: \"USDC.e\",\n version: \"2\",\n decimals: 6,\n }, // ADI Chain USDC.e (EIP-3009 supported)\n \"eip155:190415\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP mainnet USDC.e\n \"eip155:181228\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP Sepolia USDC.e\n \"eip155:50\": {\n address: \"0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:51\": {\n address: \"0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:38833\": {\n address: \"0xA5b8BF902b2844dA17d4506cc827F7F1681735E7\",\n name: \"USDC\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n }, // Igra mainnet USDC (no EIP-3009, no EIP-2612)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQA,mBAA8E;AAC9E,kBAA2B;;;ACiCpB,IAAM,sBAA6D;AAAA,EACxE,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,EACvB;AAAA;AACF;AASO,SAAS,gBAAgB,SAAyC;AACvE,QAAM,OAAO,oBAAoB,OAAO;AACxC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,2CAA2C,OAAO,EAAE;AAAA,EACtE;AACA,SAAO;AACT;;;ADvKO,IAAM,gBAAN,MAAmD;AAAA,EAAnD;AACL,SAAS,SAAS;AAClB,SAAQ,eAA8B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvC,oBAAoB,QAAoC;AACtD,SAAK,aAAa,KAAK,MAAM;AAC7B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,iBAAiB,QAAgB,SAA0B;AACzD,QAAI;AACF,aAAO,gBAAgB,OAAO,EAAE;AAAA,IAClC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,WAAW,OAAc,SAAwC;AACrE,QAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,YAAY,OAAO;AACpE,UAAI,CAAC,MAAM,OAAO;AAChB,cAAM,IAAI,MAAM,8DAA8D,OAAO,EAAE;AAAA,MACzF;AACA,aAAO;AAAA,QACL,QAAQ,MAAM;AAAA,QACd,OAAO,MAAM;AAAA,QACb,OAAO,MAAM,SAAS,CAAC;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,SAAS,KAAK,oBAAoB,KAAK;AAE7C,eAAW,UAAU,KAAK,cAAc;AACtC,YAAM,SAAS,MAAM,OAAO,QAAQ,OAAO;AAC3C,UAAI,WAAW,MAAM;AACnB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO,KAAK,uBAAuB,QAAQ,OAAO;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,2BACE,qBACA,eAMA,eAC8B;AAC9B,SAAK;AACL,WAAO,QAAQ,QAAQ;AAAA,MACrB,GAAG;AAAA,MACH,OAAO;AAAA,QACL,GAAG,oBAAoB;AAAA,QACvB,qBAAqB;AAAA,QACrB,GAAI,cAAc,OAAO,qBACrB,EAAE,wBAAoB,wBAAW,cAAc,MAAM,kBAA4B,EAAE,IACnF,CAAC;AAAA,MACP;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,oBAAoB,OAAgC;AAC1D,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO;AAAA,IACT;AAEA,eAAO,+BAAiB,KAAK;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,uBAAuB,QAAgB,SAA+B;AAC5E,UAAM,YAAY,gBAAgB,OAAO;AACzC,UAAM,kBAAc,uCAAqB,oCAAsB,MAAM,GAAG,UAAU,QAAQ;AAE1F,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,OAAO,UAAU;AAAA,MACjB,OAAO;AAAA,QACL,MAAM,UAAU;AAAA,QAChB,SAAS,UAAU;AAAA,QACnB,qBAAqB;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
{"version":3,"sources":["../../../../src/upto/server/index.ts","../../../../src/upto/server/scheme.ts","../../../../src/shared/defaultAssets.ts"],"sourcesContent":["// Note: No register.ts helper — V1 backward compatibility is not needed for upto.\n// Use direct class instantiation: server.register(\"eip155:*\", new UptoEvmScheme())\nexport { UptoEvmScheme } from \"./scheme\";\n","import {\n AssetAmount,\n Network,\n PaymentRequirements,\n Price,\n SchemeNetworkServer,\n MoneyParser,\n} from \"@x402/core/types\";\nimport { convertToTokenAmount, numberToDecimalString, parseMoneyString } from \"@x402/core/utils\";\nimport { getAddress } from \"viem\";\nimport { getDefaultAsset } from \"../../shared/defaultAssets\";\n\n/**\n * EVM server implementation for the Upto payment scheme.\n * Handles price parsing, payment requirements enhancement, and default asset resolution.\n */\nexport class UptoEvmScheme implements SchemeNetworkServer {\n readonly scheme = \"upto\";\n private moneyParsers: MoneyParser[] = [];\n\n /**\n * Registers a custom money parser for converting prices to asset amounts.\n *\n * @param parser - The money parser function to register\n * @returns This instance for chaining\n */\n registerMoneyParser(parser: MoneyParser): UptoEvmScheme {\n this.moneyParsers.push(parser);\n return this;\n }\n\n /**\n * Returns the decimal precision of the default stablecoin for the given network.\n * Implements the optional AssetDecimalsProvider interface used by resolveSettlementOverrideAmount.\n *\n * @param _asset - The asset symbol (unused; defaults to the network's default stablecoin)\n * @param network - The network to look up the default asset for\n * @returns The number of decimal places for the asset\n */\n getAssetDecimals(_asset: string, network: Network): number {\n try {\n return getDefaultAsset(network).decimals;\n } catch {\n return 6;\n }\n }\n\n /**\n * Parses a price into an asset amount for the given network.\n *\n * @param price - The price to parse (string, number, or AssetAmount)\n * @param network - The target network\n * @returns Promise resolving to an asset amount\n */\n async parsePrice(price: Price, network: Network): Promise<AssetAmount> {\n if (typeof price === \"object\" && price !== null && \"amount\" in price) {\n if (!price.asset) {\n throw new Error(`Asset address must be specified for AssetAmount on network ${network}`);\n }\n return {\n amount: price.amount,\n asset: price.asset,\n extra: price.extra || {},\n };\n }\n\n const amount = this.parseMoneyToDecimal(price);\n\n for (const parser of this.moneyParsers) {\n const result = await parser(amount, network);\n if (result !== null) {\n return result;\n }\n }\n\n return this.defaultMoneyConversion(amount, network);\n }\n\n /**\n * Enhances payment requirements with upto-specific metadata.\n *\n * @param paymentRequirements - The base payment requirements\n * @param supportedKind - The supported scheme/network kind\n * @param supportedKind.x402Version - The x402 protocol version\n * @param supportedKind.scheme - The payment scheme name\n * @param supportedKind.network - The target network\n * @param supportedKind.extra - Optional extra metadata\n * @param extensionKeys - Extension keys to include\n * @returns Promise resolving to enhanced payment requirements\n */\n enhancePaymentRequirements(\n paymentRequirements: PaymentRequirements,\n supportedKind: {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n },\n extensionKeys: string[],\n ): Promise<PaymentRequirements> {\n void extensionKeys;\n return Promise.resolve({\n ...paymentRequirements,\n extra: {\n ...paymentRequirements.extra,\n assetTransferMethod: \"permit2\",\n ...(supportedKind.extra?.facilitatorAddress\n ? { facilitatorAddress: getAddress(supportedKind.extra.facilitatorAddress as string) }\n : {}),\n },\n });\n }\n\n /**\n * Parses a money string or number into a decimal value.\n *\n * @param money - The money value to parse\n * @returns The parsed decimal amount\n */\n private parseMoneyToDecimal(money: string | number): number {\n if (typeof money === \"number\") {\n return money;\n }\n\n return parseMoneyString(money);\n }\n\n /**\n * Converts a numeric dollar amount to an AssetAmount using the default token for the network.\n *\n * @param amount - The dollar amount as a number\n * @param network - The target network\n * @returns The converted asset amount with token metadata\n */\n private defaultMoneyConversion(amount: number, network: Network): AssetAmount {\n const assetInfo = getDefaultAsset(network);\n const tokenAmount = convertToTokenAmount(numberToDecimalString(amount), assetInfo.decimals);\n\n return {\n amount: tokenAmount,\n asset: assetInfo.address,\n extra: {\n name: assetInfo.name,\n version: assetInfo.version,\n assetTransferMethod: \"permit2\",\n },\n };\n }\n}\n","import type { Network } from \"@x402/core/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSETS.md at the\n * repository root for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31612\": {\n address: \"0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:723487\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Network SBC (no EIP-3009, supports EIP-2612)\n \"eip155:72344\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Testnet SBC (no EIP-3009, supports EIP-2612)\n \"eip155:36900\": {\n address: \"0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2\",\n name: \"USDC.e\",\n version: \"2\",\n decimals: 6,\n }, // ADI Chain USDC.e (EIP-3009 supported)\n \"eip155:190415\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP mainnet USDC.e\n \"eip155:181228\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP Sepolia USDC.e\n \"eip155:50\": {\n address: \"0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:51\": {\n address: \"0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:38833\": {\n address: \"0xA5b8BF902b2844dA17d4506cc827F7F1681735E7\",\n name: \"USDC\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n }, // Igra mainnet USDC (no EIP-3009, no EIP-2612)\n \"eip155:14\": {\n address: \"0xe7cd86e13AC4309349F30B3435a9d337750fC82D\",\n name: \"USD\\u20AE0\",\n version: \"1\",\n decimals: 6,\n }, // Flare mainnet USD₮0 (EIP-3009 supported)\n \"eip155:42220\": {\n address: \"0xcebA9300f2b948710d2653dD7B07f33A8B32118C\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Celo mainnet USDC (EIP-3009 supported)\n \"eip155:11142220\": {\n address: \"0x01C5C0122039549AD1493B8220cABEdD739BC44E\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Celo Sepolia testnet USDC (EIP-3009 supported)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n"],"mappings":"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","names":[]}

@@ -28,2 +28,4 @@ export { ExactEvmSchemeV1 } from '../exact/v1/client/index.js';

readonly "stable-testnet": 2201;
readonly celo: 42220;
readonly flare: 14;
};

@@ -30,0 +32,0 @@ type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP;

@@ -185,3 +185,5 @@ "use strict";

stable: 988,
"stable-testnet": 2201
"stable-testnet": 2201,
celo: 42220,
flare: 14
};

@@ -188,0 +190,0 @@ var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);

@@ -80,4 +80,4 @@ import {

validateErc20ApprovalForPayment
} from "../../chunk-HAEDTF25.mjs";
import "../../chunk-23HX7MHV.mjs";
} from "../../chunk-JFVEMVMS.mjs";
import "../../chunk-7ER7IIEN.mjs";
import {

@@ -84,0 +84,0 @@ ERC20_APPROVAL_GAS_SPONSORING_KEY,

@@ -30,3 +30,3 @@ import {

getDefaultAsset
} from "../../chunk-DQI2DTA4.mjs";
} from "../../chunk-KTVL22S4.mjs";
import {

@@ -33,0 +33,0 @@ isBatchSettlementDepositPayload,

import {
ExactEvmScheme,
registerExactEvmScheme
} from "../../chunk-GSVPWDXO.mjs";
import "../../chunk-ZWPJEMS5.mjs";
} from "../../chunk-3QTA5JH4.mjs";
import "../../chunk-NVFLWXGP.mjs";
import "../../chunk-BEMCJZKA.mjs";

@@ -10,5 +10,5 @@ import {

getPermit2AllowanceReadParams
} from "../../chunk-63YBFPIQ.mjs";
import "../../chunk-HAEDTF25.mjs";
import "../../chunk-23HX7MHV.mjs";
} from "../../chunk-UBBS476I.mjs";
import "../../chunk-JFVEMVMS.mjs";
import "../../chunk-7ER7IIEN.mjs";
import "../../chunk-27MWX225.mjs";

@@ -15,0 +15,0 @@ import {

@@ -11,4 +11,5 @@ import {

parseEip3009TransferError,
simulateEip3009TransferResult
} from "../../chunk-ZWPJEMS5.mjs";
simulateEip3009TransferResult,
verifyEip3009TransferEvent
} from "../../chunk-NVFLWXGP.mjs";
import {

@@ -30,3 +31,3 @@ classifyErc6492Payer,

waitAndReturnSettleResponse
} from "../../chunk-HAEDTF25.mjs";
} from "../../chunk-JFVEMVMS.mjs";
import {

@@ -50,6 +51,7 @@ ErrAssetNotDeployedContract,

ErrTransactionFailed,
ErrTransferEventMismatch,
ErrUnsupportedPayloadType,
ErrValidAfterInFuture,
ErrValidBeforeExpired
} from "../../chunk-23HX7MHV.mjs";
} from "../../chunk-7ER7IIEN.mjs";
import {

@@ -292,2 +294,16 @@ ERC20_APPROVAL_GAS_SPONSORING_KEY,

}
const auth = eip3009Payload.authorization;
if (receipt.logs != null && !verifyEip3009TransferEvent(receipt.logs, getAddress(requirements.asset), {
from: getAddress(auth.from),
to: getAddress(auth.to),
value: BigInt(auth.value)
})) {
return {
success: false,
errorReason: ErrTransferEventMismatch,
transaction: tx,
network: payload.accepted.network,
payer
};
}
return {

@@ -294,0 +310,0 @@ success: true,

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../../src/exact/facilitator/eip3009.ts","../../../../src/exact/facilitator/permit2.ts","../../../../src/exact/facilitator/scheme.ts","../../../../src/exact/facilitator/register.ts"],"sourcesContent":["import {\n PaymentPayload,\n PaymentRequirements,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { getEvmChainId } from \"../../utils\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport * as Errors from \"./errors\";\nimport { resolveDataSuffix } from \"../../shared/extensions\";\nimport { verifyTypedDataSignature, classifyErc6492Payer } from \"../../shared/verifySignature\";\nimport {\n diagnoseEip3009SimulationFailure,\n executeTransferWithAuthorization,\n parseEip3009TransferError,\n simulateEip3009TransferResult,\n} from \"./eip3009-utils\";\n\nexport interface VerifyEIP3009Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface EIP3009FacilitatorConfig {\n /**\n * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. Facilitators must\n * explicitly list every factory they trust to prevent arbitrary transaction injection via\n * attacker-controlled ERC-6492 signature wrappers. An empty or omitted list denies all factory\n * deployment calls.\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * 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 * @param options - Optional verification options\n * @param allowedFactories - Allowlisted ERC-6492 factory addresses; a counterfactual payment whose\n * factory is not in this list is rejected here so verify mirrors settle's policy gate.\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 options?: VerifyEIP3009Options,\n allowedFactories: string[] = [],\n): Promise<VerifyResponse> {\n const payer = eip3009Payload.authorization.from;\n let eip6492Deployment:\n | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` }\n | undefined;\n\n // Verify scheme matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n // Get chain configuration\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: Errors.ErrMissingEip712Domain,\n payer,\n };\n }\n\n const { name, version } = requirements.extra as { name: string; version: string };\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: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n // Build typed data for signature verification\n const permitTypedData = {\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\" as const,\n domain: {\n name,\n version,\n chainId: getEvmChainId(requirements.network),\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 const signature = eip3009Payload.signature!;\n\n // Classify the payer: fetch code once, parse ERC-6492 wrapper, determine counterfactual.\n // Using classifyErc6492Payer avoids duplicating this block across eip3009.ts / v1/scheme.ts.\n const {\n isCounterfactual,\n innerSignature,\n eip6492Deployment: classification6492,\n } = await classifyErc6492Payer(signer, signature, payer);\n\n if (classification6492) {\n eip6492Deployment = classification6492;\n }\n\n if (isCounterfactual) {\n // Counterfactual deposits are deployed by settle via the factory, which is gated by the\n // allowlist. Enforce the same gate here so verify does not return isValid:true for a payment\n // that settle will reject with ErrFactoryNotAllowed (verify must predict settle).\n const factory = classification6492?.factoryAddress;\n const factoryAllowed =\n !!factory && allowedFactories.some(a => a.trim().toLowerCase() === factory.toLowerCase());\n if (!factoryAllowed) {\n return {\n isValid: false,\n invalidReason: Errors.ErrFactoryNotAllowed,\n payer,\n };\n }\n }\n\n if (!isCounterfactual) {\n // For deployed addresses (plain EOA, smart contract, 7702 EOA): verify the\n // signature using a strict primitive that mirrors on-chain SignatureChecker\n // semantics — ecrecover when no code, strict EIP-1271 when code is present.\n // No ECDSA fallback for code addresses; that fallback causes pre-verify to\n // accept sigs the on-chain token rejects (empirically confirmed on Base Sepolia).\n const isValid = await verifyTypedDataSignature(signer, {\n address: eip3009Payload.authorization.from,\n ...permitTypedData,\n signature: innerSignature,\n });\n if (!isValid) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidSignature,\n payer,\n };\n }\n }\n // Counterfactual: skip pre-verify and defer to on-chain simulation/settle which\n // deploys the factory first then atomically validates the signature.\n\n // Verify payment recipient matches\n if (getAddress(eip3009Payload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrRecipientMismatch,\n payer,\n };\n }\n\n // Verify validBefore is in the future (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidBeforeExpired,\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidAfterInFuture,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (BigInt(eip3009Payload.authorization.value) !== BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrAuthorizationValueMismatch,\n payer,\n };\n }\n\n // Reject payments whose asset is an EOA — eth_call on an EOA silently returns\n // empty data without reverting, so simulation would pass but no Transfer event\n // would be emitted, producing a silent no-op settlement.\n const assetBytecode = await signer.getCode({ address: erc20Address });\n if (!assetBytecode || assetBytecode === \"0x\") {\n return { isValid: false, invalidReason: Errors.ErrAssetNotDeployedContract, payer };\n }\n\n // Transaction simulation\n if (options?.simulate !== false) {\n const { ok, error: simError } = await simulateEip3009TransferResult(\n signer,\n erc20Address,\n eip3009Payload,\n eip6492Deployment,\n );\n if (!ok) {\n const diagnosis = await diagnoseEip3009SimulationFailure(\n signer,\n erc20Address,\n eip3009Payload,\n requirements,\n requirements.amount,\n );\n // Carry the raw revert text so the concrete reason survives the mapping to a code.\n const rawMessage =\n simError instanceof Error ? simError.message : simError ? String(simError) : undefined;\n return rawMessage ? { ...diagnosis, invalidMessage: rawMessage } : diagnosis;\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 * @param context - Optional facilitator context for extension capabilities\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 context?: FacilitatorContext,\n): Promise<SettleResponse> {\n const payer = eip3009Payload.authorization.from;\n\n // Re-verify before settling\n const valid = await verifyEIP3009(\n signer,\n payload,\n requirements,\n eip3009Payload,\n { simulate: config.simulateInSettle ?? false },\n config.eip6492AllowedFactories ?? [],\n );\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable (for optional deployment).\n // Keep the full result so we can access the inner signature later for\n // the post-deploy transfer simulation.\n const settleErc6492Data = parseErc6492Signature(eip3009Payload.signature!);\n const {\n address: factoryAddress,\n data: factoryCalldata,\n signature: erc6492InnerSig,\n } = settleErc6492Data;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if factory is in the allowlist\n if (\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const bytecode = await signer.getCode({ address: payer });\n\n if (!bytecode || bytecode === \"0x\") {\n const normalizedFactory = factoryAddress.toLowerCase();\n const isAllowed = (config.eip6492AllowedFactories ?? []).some(\n allowed => allowed.toLowerCase() === normalizedFactory,\n );\n if (!isAllowed) {\n return {\n success: false,\n errorReason: Errors.ErrFactoryNotAllowed,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n\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 and check whether it actually succeeded.\n // A reverted factory tx would silently proceed without this check, misclassifying\n // the downstream transfer failure as an invalid-signature error.\n const deployReceipt = await signer.waitForTransactionReceipt({ hash: deployTx });\n if (deployReceipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrSmartWalletDeploymentFailed,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n\n // Do NOT re-simulate the transfer here. The single authoritative pre-check is the\n // atomic Multicall3 deploy+transfer simulation that runs in verify (one eth_call,\n // state carried across both sub-calls). A second standalone eth_call after the real\n // deploy tx is unreliable — the read can race the deploy's state propagation across\n // load-balanced RPC nodes — and was producing false `eip6492_deployed_inner_wallet_\n // signature_unsupported` rejections for valid wallets (e.g. Coinbase Smart Wallet).\n // The on-chain transferWithAuthorization below is itself the definitive signature\n // check (the token routes to the wallet's isValidSignature); a genuinely\n // unsupported inner signature reverts there and is classified by the catch block.\n }\n }\n\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n // When the original signature was ERC-6492 wrapped (deployed wallet), use the\n // extracted inner signature for the on-chain transferWithAuthorization call.\n // FiatTokenV2_2's isValidSignature on the deployed contract expects the compact inner signature\n const settlePayload =\n erc6492InnerSig && erc6492InnerSig !== eip3009Payload.signature\n ? { ...eip3009Payload, signature: erc6492InnerSig }\n : eip3009Payload;\n\n const tx = await executeTransferWithAuthorization(\n signer,\n getAddress(requirements.asset),\n settlePayload,\n dataSuffix,\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: Errors.ErrTransactionFailed,\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 // Preserve the raw revert text alongside the mapped code. The mapper collapses many\n // distinct on-chain reverts into a single reason (e.g. ErrInvalidSignature), so without\n // the original message the true cause is invisible to callers/operators.\n return {\n success: false,\n errorReason: parseEip3009TransferError(error),\n errorMessage: error instanceof Error ? error.message : String(error),\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport {\n extractEip2612GasSponsoringInfo,\n extractErc20ApprovalGasSponsoringInfo,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n resolveErc20ApprovalExtensionSigner,\n type Eip2612GasSponsoringInfo,\n type Erc20ApprovalGasSponsoringFacilitatorExtension,\n type Erc20ApprovalGasSponsoringSigner,\n} from \"../extensions\";\nimport { getAddress, encodeFunctionData } from \"viem\";\nimport { appendDataSuffix, resolveDataSuffix } from \"../../shared/extensions\";\nimport {\n PERMIT2_ADDRESS,\n permit2WitnessTypes,\n x402ExactPermit2ProxyABI,\n x402ExactPermit2ProxyAddress,\n} from \"../../constants\";\nimport * as Errors from \"./errors\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\nimport { getEvmChainId } from \"../../utils\";\nimport { validateErc20ApprovalForPayment } from \"./erc20approval\";\nimport { verifyTypedDataSignature } from \"../../shared/verifySignature\";\nimport {\n simulatePermit2Settle,\n simulatePermit2SettleWithPermit,\n simulatePermit2SettleWithErc20Approval,\n diagnosePermit2SimulationFailure,\n checkPermit2Prerequisites,\n validateEip2612PermitForPayment,\n buildExactPermit2SettleArgs,\n splitEip2612Signature,\n waitAndReturnSettleResponse,\n mapSettleError,\n type Permit2ProxyConfig,\n} from \"../../shared/permit2\";\n\nconst exactProxyConfig: Permit2ProxyConfig = {\n proxyAddress: x402ExactPermit2ProxyAddress,\n proxyABI: x402ExactPermit2ProxyABI,\n};\n\nexport interface VerifyPermit2Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface Permit2FacilitatorConfig {\n /**\n * If enabled, simulates transaction before settling. Defaults to false,\n * i.e. only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * Verifies a Permit2 payment payload.\n *\n * Handles all Permit2 verification paths:\n * - Standard: checks on-chain Permit2 allowance\n * - EIP-2612: validates the EIP-2612 permit extension when allowance is insufficient\n * - ERC-20 approval: validates the pre-signed approve tx extension when allowance is insufficient\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 * @param context - Optional facilitator context for extension-provided capabilities\n * @param options - Optional verification options (e.g. simulate)\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 context?: FacilitatorContext,\n options?: VerifyPermit2Options,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrUnsupportedPayloadType,\n payer,\n };\n }\n\n if (payload.accepted.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset);\n\n const assetBytecode = await signer.getCode({ address: tokenAddress });\n if (!assetBytecode || assetBytecode === \"0x\") {\n return { isValid: false, invalidReason: Errors.ErrAssetNotDeployedContract, payer };\n }\n\n if (\n getAddress(permit2Payload.permit2Authorization.spender) !==\n getAddress(x402ExactPermit2ProxyAddress)\n ) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2InvalidSpender,\n payer,\n };\n }\n\n if (\n getAddress(permit2Payload.permit2Authorization.witness.to) !== getAddress(requirements.payTo)\n ) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2RecipientMismatch,\n payer,\n };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2DeadlineExpired,\n payer,\n };\n }\n\n if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2NotYetValid,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (\n BigInt(permit2Payload.permit2Authorization.permitted.amount) !== BigInt(requirements.amount)\n ) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2AmountMismatch,\n payer,\n };\n }\n\n if (getAddress(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2TokenMismatch,\n payer,\n };\n }\n\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 },\n },\n };\n\n // Verify signature using a strict primitive that mirrors Permit2's\n // on-chain SignatureVerification (libraries/SignatureVerification.sol):\n // ecrecover when the address has no code, strict EIP-1271 isValidSignature\n // when it does. No ECDSA fallback for addresses with code — that fallback\n // would accept signatures Permit2 rejects on-chain (notably for ERC-7702\n // EOAs whose delegate doesn't accept raw owner ECDSA).\n const signatureValid = await verifyTypedDataSignature(signer, {\n address: payer,\n ...permit2TypedData,\n signature: permit2Payload.signature,\n });\n if (!signatureValid) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2InvalidSignature,\n payer,\n };\n }\n\n // If simulation is disabled, return early\n if (options?.simulate === false) {\n return { isValid: true, invalidReason: undefined, payer };\n }\n\n // Branch: EIP-2612 gas sponsoring (atomic settleWithPermit via contract)\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const fieldResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!fieldResult.isValid) {\n return { isValid: false, invalidReason: fieldResult.invalidReason!, payer };\n }\n\n const exactSettleArgs = buildExactPermit2SettleArgs(permit2Payload);\n const simOk = await simulatePermit2SettleWithPermit(\n exactProxyConfig,\n signer,\n exactSettleArgs,\n eip2612Info,\n );\n if (!simOk) {\n return diagnosePermit2SimulationFailure(\n exactProxyConfig,\n signer,\n tokenAddress,\n permit2Payload,\n requirements.amount,\n );\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n }\n\n // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer)\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const fieldResult = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!fieldResult.isValid) {\n return { isValid: false, invalidReason: fieldResult.invalidReason!, payer };\n }\n\n const extensionSigner = resolveErc20ApprovalExtensionSigner(\n erc20GasSponsorshipExtension,\n requirements.network,\n );\n\n if (extensionSigner?.simulateTransactions) {\n const simOk = await simulatePermit2SettleWithErc20Approval(\n exactProxyConfig,\n extensionSigner,\n buildExactPermit2SettleArgs(permit2Payload),\n erc20Info,\n );\n if (!simOk) {\n return diagnosePermit2SimulationFailure(\n exactProxyConfig,\n signer,\n tokenAddress,\n permit2Payload,\n requirements.amount,\n );\n }\n return { isValid: true, invalidReason: undefined, payer };\n }\n\n // Fallback to prerequisite-only check if simulateTransactions is not available\n return checkPermit2Prerequisites(\n exactProxyConfig,\n signer,\n tokenAddress,\n payer,\n requirements.amount,\n );\n }\n }\n\n // Branch: standard settle (allowance already on-chain)\n const simOk = await simulatePermit2Settle(\n exactProxyConfig,\n signer,\n buildExactPermit2SettleArgs(permit2Payload),\n );\n if (!simOk) {\n return diagnosePermit2SimulationFailure(\n exactProxyConfig,\n signer,\n tokenAddress,\n permit2Payload,\n requirements.amount,\n );\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n}\n\n/**\n * Settles a Permit2 payment. Single entry point for all Permit2 settlement paths:\n *\n * 1. EIP-2612 extension present -> settleWithPermit (atomic single tx via contract)\n * 2. ERC-20 approval extension present + extension signer -> broadcast approval + settle (via extension signer)\n * 3. Standard -> settle directly (allowance already on-chain)\n *\n * @param signer - The base 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 * @param context - Optional facilitator context for extension-provided capabilities\n * @param config - Optional facilitator config (simulateInSettle)\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 context?: FacilitatorContext,\n config?: Permit2FacilitatorConfig,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n const valid = await verifyPermit2(signer, payload, requirements, permit2Payload, context, {\n simulate: config?.simulateInSettle ?? false,\n });\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n // Branch: EIP-2612 gas sponsoring (atomic settleWithPermit via contract)\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n return settlePermit2WithEIP2612(\n exactProxyConfig,\n signer,\n payload,\n permit2Payload,\n eip2612Info,\n dataSuffix,\n );\n }\n\n // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer)\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n const extensionSigner = resolveErc20ApprovalExtensionSigner(\n erc20GasSponsorshipExtension,\n payload.accepted.network,\n );\n if (extensionSigner) {\n return settlePermit2WithERC20Approval(\n exactProxyConfig,\n extensionSigner,\n payload,\n permit2Payload,\n erc20Info,\n dataSuffix,\n );\n }\n }\n\n // Branch: standard settle (allowance already on-chain)\n return settlePermit2Direct(exactProxyConfig, signer, payload, permit2Payload, dataSuffix);\n}\n\n// ---------------------------------------------------------------------------\n// Exact-only settle helpers (not shared — upto has its own implementations)\n// ---------------------------------------------------------------------------\n\n/**\n * Settles a Permit2 payment via settleWithPermit, including the EIP-2612 permit atomically.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload for network info\n * @param permit2Payload - The Permit2 payload with authorization and signature\n * @param eip2612Info - The EIP-2612 gas sponsoring info from the payload extension\n * @param dataSuffix - Optional hex suffix appended to the settlement transaction\n * @returns Promise resolving to a settlement response\n */\nasync function settlePermit2WithEIP2612(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n permit2Payload: ExactPermit2Payload,\n eip2612Info: Eip2612GasSponsoringInfo,\n dataSuffix?: `0x${string}`,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n try {\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n\n const tx = await signer.writeContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settleWithPermit\",\n args: [\n {\n value: BigInt(eip2612Info.amount),\n deadline: BigInt(eip2612Info.deadline),\n r,\n s,\n v,\n },\n ...buildExactPermit2SettleArgs(permit2Payload),\n ],\n dataSuffix,\n });\n\n return waitAndReturnSettleResponse(signer, tx, payload, payer);\n } catch (error) {\n return mapSettleError(error, payload, payer);\n }\n}\n\n/**\n * Settles a Permit2 payment using an ERC-20 approval gas sponsoring extension.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param extensionSigner - The extension signer with sendTransactions capability\n * @param payload - The payment payload for network info\n * @param permit2Payload - The Permit2 payload with authorization and signature\n * @param erc20Info - Object containing the signed approval transaction\n * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction\n * @param dataSuffix - Optional hex suffix appended to the settlement transaction\n * @returns Promise resolving to a settlement response\n */\nasync function settlePermit2WithERC20Approval(\n config: Permit2ProxyConfig,\n extensionSigner: Erc20ApprovalGasSponsoringSigner,\n payload: PaymentPayload,\n permit2Payload: ExactPermit2Payload,\n erc20Info: { signedTransaction: string },\n dataSuffix?: `0x${string}`,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n try {\n const settleData = appendDataSuffix(\n encodeFunctionData({\n abi: config.proxyABI,\n functionName: \"settle\",\n args: buildExactPermit2SettleArgs(permit2Payload),\n }),\n dataSuffix,\n );\n\n const txHashes = await extensionSigner.sendTransactions([\n erc20Info.signedTransaction as `0x${string}`,\n { to: config.proxyAddress, data: settleData, gas: BigInt(300_000) },\n ]);\n\n const settleTxHash = txHashes[txHashes.length - 1];\n return waitAndReturnSettleResponse(extensionSigner, settleTxHash, payload, payer);\n } catch (error) {\n return mapSettleError(error, payload, payer);\n }\n}\n\n/**\n * Settles a Permit2 payment directly when Permit2 allowance is already on-chain.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload for network info\n * @param permit2Payload - The Permit2 payload with authorization and signature\n * @param dataSuffix - Optional hex suffix appended to the settlement transaction\n * @returns Promise resolving to a settlement response\n */\nasync function settlePermit2Direct(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n permit2Payload: ExactPermit2Payload,\n dataSuffix?: `0x${string}`,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n try {\n const tx = await signer.writeContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settle\",\n args: buildExactPermit2SettleArgs(permit2Payload),\n dataSuffix,\n });\n\n return waitAndReturnSettleResponse(signer, tx, payload, payer);\n } catch (error) {\n return mapSettleError(error, payload, payer);\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n FacilitatorContext,\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 * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. An empty or omitted\n * list denies all factory deployment calls (feature disabled by default).\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, run on-chain simulation during settle's re-verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme.\n * Thin router that delegates to EIP-3009 or Permit2 based on payload type.\n * All extension handling (EIP-2612, ERC-20 approval gas sponsoring) is owned\n * by the Permit2 functions via FacilitatorContext.\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 ExactEvmScheme facilitator instance.\n *\n * @param signer - The EVM signer for facilitator operations\n * @param config - Optional configuration\n */\n constructor(\n private readonly signer: FacilitatorEvmSigner,\n config?: ExactEvmSchemeConfig,\n ) {\n this.config = {\n eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],\n simulateInSettle: config?.simulateInSettle ?? false,\n };\n }\n\n /**\n * Returns undefined — EVM has no mechanism-specific extra data.\n *\n * @param _ - The network identifier (unused)\n * @returns undefined\n */\n getExtra(_: string): Record<string, unknown> | undefined {\n return undefined;\n }\n\n /**\n * Returns facilitator wallet addresses for the supported response.\n *\n * @param _ - The network identifier (unused, 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. Routes to Permit2 or EIP-3009 based on payload type.\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @param _ - Payment required extensions (unused; reserved for interface parity)\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n _?: Record<string, unknown>,\n ): Promise<VerifyResponse> {\n const rawPayload = payload.payload as ExactEvmPayloadV2;\n const isPermit2 = isPermit2Payload(rawPayload);\n\n if (isPermit2) {\n return verifyPermit2(this.signer, payload, requirements, rawPayload, context);\n }\n\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return verifyEIP3009(\n this.signer,\n payload,\n requirements,\n eip3009Payload,\n undefined,\n this.config.eip6492AllowedFactories,\n );\n }\n\n /**\n * Settles a payment. Routes to Permit2 or EIP-3009 based on payload type.\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<SettleResponse> {\n const rawPayload = payload.payload as ExactEvmPayloadV2;\n const isPermit2 = isPermit2Payload(rawPayload);\n\n if (isPermit2) {\n return settlePermit2(this.signer, payload, requirements, rawPayload, context, {\n simulateInSettle: this.config.simulateInSettle,\n });\n }\n\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config, context);\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 * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. An empty or omitted\n * list denies all factory deployment calls (feature disabled by default).\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n\n /**\n * If enabled, reruns on-chain simulation during settle's re-verify.\n *\n * @default false\n */\n simulateInSettle?: 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 eip6492AllowedFactories: config.eip6492AllowedFactories,\n simulateInSettle: config.simulateInSettle,\n }),\n );\n\n // Register all V1 networks\n facilitator.registerV1(\n NETWORKS as Network[],\n new ExactEvmSchemeV1(config.signer, {\n eip6492AllowedFactories: config.eip6492AllowedFactories,\n simulateInSettle: config.simulateInSettle,\n }),\n );\n\n return facilitator;\n}\n"],"mappings":"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","names":["getAddress","getAddress","simOk"]}
{"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 FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature } from \"viem\";\nimport { authorizationTypes } from \"../../constants\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { getEvmChainId } from \"../../utils\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport * as Errors from \"./errors\";\nimport { resolveDataSuffix } from \"../../shared/extensions\";\nimport { verifyTypedDataSignature, classifyErc6492Payer } from \"../../shared/verifySignature\";\nimport {\n diagnoseEip3009SimulationFailure,\n executeTransferWithAuthorization,\n parseEip3009TransferError,\n simulateEip3009TransferResult,\n verifyEip3009TransferEvent,\n} from \"./eip3009-utils\";\n\nexport interface VerifyEIP3009Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface EIP3009FacilitatorConfig {\n /**\n * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. Facilitators must\n * explicitly list every factory they trust to prevent arbitrary transaction injection via\n * attacker-controlled ERC-6492 signature wrappers. An empty or omitted list denies all factory\n * deployment calls.\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * 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 * @param options - Optional verification options\n * @param allowedFactories - Allowlisted ERC-6492 factory addresses; a counterfactual payment whose\n * factory is not in this list is rejected here so verify mirrors settle's policy gate.\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 options?: VerifyEIP3009Options,\n allowedFactories: string[] = [],\n): Promise<VerifyResponse> {\n const payer = eip3009Payload.authorization.from;\n let eip6492Deployment:\n | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` }\n | undefined;\n\n // Verify scheme matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n // Get chain configuration\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: Errors.ErrMissingEip712Domain,\n payer,\n };\n }\n\n const { name, version } = requirements.extra as { name: string; version: string };\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: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n // Build typed data for signature verification\n const permitTypedData = {\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\" as const,\n domain: {\n name,\n version,\n chainId: getEvmChainId(requirements.network),\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 const signature = eip3009Payload.signature!;\n\n // Classify the payer: fetch code once, parse ERC-6492 wrapper, determine counterfactual.\n // Using classifyErc6492Payer avoids duplicating this block across eip3009.ts / v1/scheme.ts.\n const {\n isCounterfactual,\n innerSignature,\n eip6492Deployment: classification6492,\n } = await classifyErc6492Payer(signer, signature, payer);\n\n if (classification6492) {\n eip6492Deployment = classification6492;\n }\n\n if (isCounterfactual) {\n // Counterfactual deposits are deployed by settle via the factory, which is gated by the\n // allowlist. Enforce the same gate here so verify does not return isValid:true for a payment\n // that settle will reject with ErrFactoryNotAllowed (verify must predict settle).\n const factory = classification6492?.factoryAddress;\n const factoryAllowed =\n !!factory && allowedFactories.some(a => a.trim().toLowerCase() === factory.toLowerCase());\n if (!factoryAllowed) {\n return {\n isValid: false,\n invalidReason: Errors.ErrFactoryNotAllowed,\n payer,\n };\n }\n }\n\n if (!isCounterfactual) {\n // For deployed addresses (plain EOA, smart contract, 7702 EOA): verify the\n // signature using a strict primitive that mirrors on-chain SignatureChecker\n // semantics — ecrecover when no code, strict EIP-1271 when code is present.\n // No ECDSA fallback for code addresses; that fallback causes pre-verify to\n // accept sigs the on-chain token rejects (empirically confirmed on Base Sepolia).\n const isValid = await verifyTypedDataSignature(signer, {\n address: eip3009Payload.authorization.from,\n ...permitTypedData,\n signature: innerSignature,\n });\n if (!isValid) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidSignature,\n payer,\n };\n }\n }\n // Counterfactual: skip pre-verify and defer to on-chain simulation/settle which\n // deploys the factory first then atomically validates the signature.\n\n // Verify payment recipient matches\n if (getAddress(eip3009Payload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrRecipientMismatch,\n payer,\n };\n }\n\n // Verify validBefore is in the future (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(eip3009Payload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidBeforeExpired,\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(eip3009Payload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidAfterInFuture,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (BigInt(eip3009Payload.authorization.value) !== BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrAuthorizationValueMismatch,\n payer,\n };\n }\n\n // Reject payments whose asset is an EOA — eth_call on an EOA silently returns\n // empty data without reverting, so simulation would pass but no Transfer event\n // would be emitted, producing a silent no-op settlement.\n const assetBytecode = await signer.getCode({ address: erc20Address });\n if (!assetBytecode || assetBytecode === \"0x\") {\n return { isValid: false, invalidReason: Errors.ErrAssetNotDeployedContract, payer };\n }\n\n // Transaction simulation\n if (options?.simulate !== false) {\n const { ok, error: simError } = await simulateEip3009TransferResult(\n signer,\n erc20Address,\n eip3009Payload,\n eip6492Deployment,\n );\n if (!ok) {\n const diagnosis = await diagnoseEip3009SimulationFailure(\n signer,\n erc20Address,\n eip3009Payload,\n requirements,\n requirements.amount,\n );\n // Carry the raw revert text so the concrete reason survives the mapping to a code.\n const rawMessage =\n simError instanceof Error ? simError.message : simError ? String(simError) : undefined;\n return rawMessage ? { ...diagnosis, invalidMessage: rawMessage } : diagnosis;\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 * @param context - Optional facilitator context for extension capabilities\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 context?: FacilitatorContext,\n): Promise<SettleResponse> {\n const payer = eip3009Payload.authorization.from;\n\n // Re-verify before settling\n const valid = await verifyEIP3009(\n signer,\n payload,\n requirements,\n eip3009Payload,\n { simulate: config.simulateInSettle ?? false },\n config.eip6492AllowedFactories ?? [],\n );\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable (for optional deployment).\n // Keep the full result so we can access the inner signature later for\n // the post-deploy transfer simulation.\n const settleErc6492Data = parseErc6492Signature(eip3009Payload.signature!);\n const {\n address: factoryAddress,\n data: factoryCalldata,\n signature: erc6492InnerSig,\n } = settleErc6492Data;\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if factory is in the allowlist\n if (\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const bytecode = await signer.getCode({ address: payer });\n\n if (!bytecode || bytecode === \"0x\") {\n const normalizedFactory = factoryAddress.toLowerCase();\n const isAllowed = (config.eip6492AllowedFactories ?? []).some(\n allowed => allowed.toLowerCase() === normalizedFactory,\n );\n if (!isAllowed) {\n return {\n success: false,\n errorReason: Errors.ErrFactoryNotAllowed,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n\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 and check whether it actually succeeded.\n // A reverted factory tx would silently proceed without this check, misclassifying\n // the downstream transfer failure as an invalid-signature error.\n const deployReceipt = await signer.waitForTransactionReceipt({ hash: deployTx });\n if (deployReceipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrSmartWalletDeploymentFailed,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n\n // Do NOT re-simulate the transfer here. The single authoritative pre-check is the\n // atomic Multicall3 deploy+transfer simulation that runs in verify (one eth_call,\n // state carried across both sub-calls). A second standalone eth_call after the real\n // deploy tx is unreliable — the read can race the deploy's state propagation across\n // load-balanced RPC nodes — and was producing false `eip6492_deployed_inner_wallet_\n // signature_unsupported` rejections for valid wallets (e.g. Coinbase Smart Wallet).\n // The on-chain transferWithAuthorization below is itself the definitive signature\n // check (the token routes to the wallet's isValidSignature); a genuinely\n // unsupported inner signature reverts there and is classified by the catch block.\n }\n }\n\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n // When the original signature was ERC-6492 wrapped (deployed wallet), use the\n // extracted inner signature for the on-chain transferWithAuthorization call.\n // FiatTokenV2_2's isValidSignature on the deployed contract expects the compact inner signature\n const settlePayload =\n erc6492InnerSig && erc6492InnerSig !== eip3009Payload.signature\n ? { ...eip3009Payload, signature: erc6492InnerSig }\n : eip3009Payload;\n\n const tx = await executeTransferWithAuthorization(\n signer,\n getAddress(requirements.asset),\n settlePayload,\n dataSuffix,\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: Errors.ErrTransactionFailed,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n // Receipt status only proves the tx did not revert.\n // When logs are present, require the expected ERC-20 Transfer event.\n const auth = eip3009Payload.authorization;\n if (\n receipt.logs != null &&\n !verifyEip3009TransferEvent(receipt.logs, getAddress(requirements.asset), {\n from: getAddress(auth.from),\n to: getAddress(auth.to),\n value: BigInt(auth.value),\n })\n ) {\n return {\n success: false,\n errorReason: Errors.ErrTransferEventMismatch,\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 // Preserve the raw revert text alongside the mapped code. The mapper collapses many\n // distinct on-chain reverts into a single reason (e.g. ErrInvalidSignature), so without\n // the original message the true cause is invisible to callers/operators.\n return {\n success: false,\n errorReason: parseEip3009TransferError(error),\n errorMessage: error instanceof Error ? error.message : String(error),\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport {\n extractEip2612GasSponsoringInfo,\n extractErc20ApprovalGasSponsoringInfo,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n resolveErc20ApprovalExtensionSigner,\n type Eip2612GasSponsoringInfo,\n type Erc20ApprovalGasSponsoringFacilitatorExtension,\n type Erc20ApprovalGasSponsoringSigner,\n} from \"../extensions\";\nimport { getAddress, encodeFunctionData } from \"viem\";\nimport { appendDataSuffix, resolveDataSuffix } from \"../../shared/extensions\";\nimport {\n PERMIT2_ADDRESS,\n permit2WitnessTypes,\n x402ExactPermit2ProxyABI,\n x402ExactPermit2ProxyAddress,\n} from \"../../constants\";\nimport * as Errors from \"./errors\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactPermit2Payload } from \"../../types\";\nimport { getEvmChainId } from \"../../utils\";\nimport { validateErc20ApprovalForPayment } from \"./erc20approval\";\nimport { verifyTypedDataSignature } from \"../../shared/verifySignature\";\nimport {\n simulatePermit2Settle,\n simulatePermit2SettleWithPermit,\n simulatePermit2SettleWithErc20Approval,\n diagnosePermit2SimulationFailure,\n checkPermit2Prerequisites,\n validateEip2612PermitForPayment,\n buildExactPermit2SettleArgs,\n splitEip2612Signature,\n waitAndReturnSettleResponse,\n mapSettleError,\n type Permit2ProxyConfig,\n} from \"../../shared/permit2\";\n\nconst exactProxyConfig: Permit2ProxyConfig = {\n proxyAddress: x402ExactPermit2ProxyAddress,\n proxyABI: x402ExactPermit2ProxyABI,\n};\n\nexport interface VerifyPermit2Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface Permit2FacilitatorConfig {\n /**\n * If enabled, simulates transaction before settling. Defaults to false,\n * i.e. only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * Verifies a Permit2 payment payload.\n *\n * Handles all Permit2 verification paths:\n * - Standard: checks on-chain Permit2 allowance\n * - EIP-2612: validates the EIP-2612 permit extension when allowance is insufficient\n * - ERC-20 approval: validates the pre-signed approve tx extension when allowance is insufficient\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 * @param context - Optional facilitator context for extension-provided capabilities\n * @param options - Optional verification options (e.g. simulate)\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 context?: FacilitatorContext,\n options?: VerifyPermit2Options,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrUnsupportedPayloadType,\n payer,\n };\n }\n\n if (payload.accepted.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n const chainId = getEvmChainId(requirements.network);\n const tokenAddress = getAddress(requirements.asset);\n\n const assetBytecode = await signer.getCode({ address: tokenAddress });\n if (!assetBytecode || assetBytecode === \"0x\") {\n return { isValid: false, invalidReason: Errors.ErrAssetNotDeployedContract, payer };\n }\n\n if (\n getAddress(permit2Payload.permit2Authorization.spender) !==\n getAddress(x402ExactPermit2ProxyAddress)\n ) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2InvalidSpender,\n payer,\n };\n }\n\n if (\n getAddress(permit2Payload.permit2Authorization.witness.to) !== getAddress(requirements.payTo)\n ) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2RecipientMismatch,\n payer,\n };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(permit2Payload.permit2Authorization.deadline) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2DeadlineExpired,\n payer,\n };\n }\n\n if (BigInt(permit2Payload.permit2Authorization.witness.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2NotYetValid,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (\n BigInt(permit2Payload.permit2Authorization.permitted.amount) !== BigInt(requirements.amount)\n ) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2AmountMismatch,\n payer,\n };\n }\n\n if (getAddress(permit2Payload.permit2Authorization.permitted.token) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2TokenMismatch,\n payer,\n };\n }\n\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 },\n },\n };\n\n // Verify signature using a strict primitive that mirrors Permit2's\n // on-chain SignatureVerification (libraries/SignatureVerification.sol):\n // ecrecover when the address has no code, strict EIP-1271 isValidSignature\n // when it does. No ECDSA fallback for addresses with code — that fallback\n // would accept signatures Permit2 rejects on-chain (notably for ERC-7702\n // EOAs whose delegate doesn't accept raw owner ECDSA).\n const signatureValid = await verifyTypedDataSignature(signer, {\n address: payer,\n ...permit2TypedData,\n signature: permit2Payload.signature,\n });\n if (!signatureValid) {\n return {\n isValid: false,\n invalidReason: Errors.ErrPermit2InvalidSignature,\n payer,\n };\n }\n\n // If simulation is disabled, return early\n if (options?.simulate === false) {\n return { isValid: true, invalidReason: undefined, payer };\n }\n\n // Branch: EIP-2612 gas sponsoring (atomic settleWithPermit via contract)\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const fieldResult = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!fieldResult.isValid) {\n return { isValid: false, invalidReason: fieldResult.invalidReason!, payer };\n }\n\n const exactSettleArgs = buildExactPermit2SettleArgs(permit2Payload);\n const simOk = await simulatePermit2SettleWithPermit(\n exactProxyConfig,\n signer,\n exactSettleArgs,\n eip2612Info,\n );\n if (!simOk) {\n return diagnosePermit2SimulationFailure(\n exactProxyConfig,\n signer,\n tokenAddress,\n permit2Payload,\n requirements.amount,\n );\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n }\n\n // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer)\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const fieldResult = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!fieldResult.isValid) {\n return { isValid: false, invalidReason: fieldResult.invalidReason!, payer };\n }\n\n const extensionSigner = resolveErc20ApprovalExtensionSigner(\n erc20GasSponsorshipExtension,\n requirements.network,\n );\n\n if (extensionSigner?.simulateTransactions) {\n const simOk = await simulatePermit2SettleWithErc20Approval(\n exactProxyConfig,\n extensionSigner,\n buildExactPermit2SettleArgs(permit2Payload),\n erc20Info,\n );\n if (!simOk) {\n return diagnosePermit2SimulationFailure(\n exactProxyConfig,\n signer,\n tokenAddress,\n permit2Payload,\n requirements.amount,\n );\n }\n return { isValid: true, invalidReason: undefined, payer };\n }\n\n // Fallback to prerequisite-only check if simulateTransactions is not available\n return checkPermit2Prerequisites(\n exactProxyConfig,\n signer,\n tokenAddress,\n payer,\n requirements.amount,\n );\n }\n }\n\n // Branch: standard settle (allowance already on-chain)\n const simOk = await simulatePermit2Settle(\n exactProxyConfig,\n signer,\n buildExactPermit2SettleArgs(permit2Payload),\n );\n if (!simOk) {\n return diagnosePermit2SimulationFailure(\n exactProxyConfig,\n signer,\n tokenAddress,\n permit2Payload,\n requirements.amount,\n );\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n}\n\n/**\n * Settles a Permit2 payment. Single entry point for all Permit2 settlement paths:\n *\n * 1. EIP-2612 extension present -> settleWithPermit (atomic single tx via contract)\n * 2. ERC-20 approval extension present + extension signer -> broadcast approval + settle (via extension signer)\n * 3. Standard -> settle directly (allowance already on-chain)\n *\n * @param signer - The base 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 * @param context - Optional facilitator context for extension-provided capabilities\n * @param config - Optional facilitator config (simulateInSettle)\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 context?: FacilitatorContext,\n config?: Permit2FacilitatorConfig,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n const valid = await verifyPermit2(signer, payload, requirements, permit2Payload, context, {\n simulate: config?.simulateInSettle ?? false,\n });\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n // Branch: EIP-2612 gas sponsoring (atomic settleWithPermit via contract)\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n return settlePermit2WithEIP2612(\n exactProxyConfig,\n signer,\n payload,\n permit2Payload,\n eip2612Info,\n dataSuffix,\n );\n }\n\n // Branch: ERC-20 approval gas sponsoring (broadcast approval + settle via extension signer)\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n const extensionSigner = resolveErc20ApprovalExtensionSigner(\n erc20GasSponsorshipExtension,\n payload.accepted.network,\n );\n if (extensionSigner) {\n return settlePermit2WithERC20Approval(\n exactProxyConfig,\n extensionSigner,\n payload,\n permit2Payload,\n erc20Info,\n dataSuffix,\n );\n }\n }\n\n // Branch: standard settle (allowance already on-chain)\n return settlePermit2Direct(exactProxyConfig, signer, payload, permit2Payload, dataSuffix);\n}\n\n// ---------------------------------------------------------------------------\n// Exact-only settle helpers (not shared — upto has its own implementations)\n// ---------------------------------------------------------------------------\n\n/**\n * Settles a Permit2 payment via settleWithPermit, including the EIP-2612 permit atomically.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload for network info\n * @param permit2Payload - The Permit2 payload with authorization and signature\n * @param eip2612Info - The EIP-2612 gas sponsoring info from the payload extension\n * @param dataSuffix - Optional hex suffix appended to the settlement transaction\n * @returns Promise resolving to a settlement response\n */\nasync function settlePermit2WithEIP2612(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n permit2Payload: ExactPermit2Payload,\n eip2612Info: Eip2612GasSponsoringInfo,\n dataSuffix?: `0x${string}`,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n try {\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n\n const tx = await signer.writeContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settleWithPermit\",\n args: [\n {\n value: BigInt(eip2612Info.amount),\n deadline: BigInt(eip2612Info.deadline),\n r,\n s,\n v,\n },\n ...buildExactPermit2SettleArgs(permit2Payload),\n ],\n dataSuffix,\n });\n\n return waitAndReturnSettleResponse(signer, tx, payload, payer);\n } catch (error) {\n return mapSettleError(error, payload, payer);\n }\n}\n\n/**\n * Settles a Permit2 payment using an ERC-20 approval gas sponsoring extension.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param extensionSigner - The extension signer with sendTransactions capability\n * @param payload - The payment payload for network info\n * @param permit2Payload - The Permit2 payload with authorization and signature\n * @param erc20Info - Object containing the signed approval transaction\n * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction\n * @param dataSuffix - Optional hex suffix appended to the settlement transaction\n * @returns Promise resolving to a settlement response\n */\nasync function settlePermit2WithERC20Approval(\n config: Permit2ProxyConfig,\n extensionSigner: Erc20ApprovalGasSponsoringSigner,\n payload: PaymentPayload,\n permit2Payload: ExactPermit2Payload,\n erc20Info: { signedTransaction: string },\n dataSuffix?: `0x${string}`,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n try {\n const settleData = appendDataSuffix(\n encodeFunctionData({\n abi: config.proxyABI,\n functionName: \"settle\",\n args: buildExactPermit2SettleArgs(permit2Payload),\n }),\n dataSuffix,\n );\n\n const txHashes = await extensionSigner.sendTransactions([\n erc20Info.signedTransaction as `0x${string}`,\n { to: config.proxyAddress, data: settleData, gas: BigInt(300_000) },\n ]);\n\n const settleTxHash = txHashes[txHashes.length - 1];\n return waitAndReturnSettleResponse(extensionSigner, settleTxHash, payload, payer);\n } catch (error) {\n return mapSettleError(error, payload, payer);\n }\n}\n\n/**\n * Settles a Permit2 payment directly when Permit2 allowance is already on-chain.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - The facilitator signer for contract writes\n * @param payload - The payment payload for network info\n * @param permit2Payload - The Permit2 payload with authorization and signature\n * @param dataSuffix - Optional hex suffix appended to the settlement transaction\n * @returns Promise resolving to a settlement response\n */\nasync function settlePermit2Direct(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n permit2Payload: ExactPermit2Payload,\n dataSuffix?: `0x${string}`,\n): Promise<SettleResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n try {\n const tx = await signer.writeContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settle\",\n args: buildExactPermit2SettleArgs(permit2Payload),\n dataSuffix,\n });\n\n return waitAndReturnSettleResponse(signer, tx, payload, payer);\n } catch (error) {\n return mapSettleError(error, payload, payer);\n }\n}\n","import {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n FacilitatorContext,\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 * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. An empty or omitted\n * list denies all factory deployment calls (feature disabled by default).\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, run on-chain simulation during settle's re-verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme.\n * Thin router that delegates to EIP-3009 or Permit2 based on payload type.\n * All extension handling (EIP-2612, ERC-20 approval gas sponsoring) is owned\n * by the Permit2 functions via FacilitatorContext.\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 ExactEvmScheme facilitator instance.\n *\n * @param signer - The EVM signer for facilitator operations\n * @param config - Optional configuration\n */\n constructor(\n private readonly signer: FacilitatorEvmSigner,\n config?: ExactEvmSchemeConfig,\n ) {\n this.config = {\n eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],\n simulateInSettle: config?.simulateInSettle ?? false,\n };\n }\n\n /**\n * Returns undefined — EVM has no mechanism-specific extra data.\n *\n * @param _ - The network identifier (unused)\n * @returns undefined\n */\n getExtra(_: string): Record<string, unknown> | undefined {\n return undefined;\n }\n\n /**\n * Returns facilitator wallet addresses for the supported response.\n *\n * @param _ - The network identifier (unused, 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. Routes to Permit2 or EIP-3009 based on payload type.\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @param _ - Payment required extensions (unused; reserved for interface parity)\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n _?: Record<string, unknown>,\n ): Promise<VerifyResponse> {\n const rawPayload = payload.payload as ExactEvmPayloadV2;\n const isPermit2 = isPermit2Payload(rawPayload);\n\n if (isPermit2) {\n return verifyPermit2(this.signer, payload, requirements, rawPayload, context);\n }\n\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return verifyEIP3009(\n this.signer,\n payload,\n requirements,\n eip3009Payload,\n undefined,\n this.config.eip6492AllowedFactories,\n );\n }\n\n /**\n * Settles a payment. Routes to Permit2 or EIP-3009 based on payload type.\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<SettleResponse> {\n const rawPayload = payload.payload as ExactEvmPayloadV2;\n const isPermit2 = isPermit2Payload(rawPayload);\n\n if (isPermit2) {\n return settlePermit2(this.signer, payload, requirements, rawPayload, context, {\n simulateInSettle: this.config.simulateInSettle,\n });\n }\n\n const eip3009Payload: ExactEIP3009Payload = rawPayload;\n return settleEIP3009(this.signer, payload, requirements, eip3009Payload, this.config, context);\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 * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. An empty or omitted\n * list denies all factory deployment calls (feature disabled by default).\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n\n /**\n * If enabled, reruns on-chain simulation during settle's re-verify.\n *\n * @default false\n */\n simulateInSettle?: 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 eip6492AllowedFactories: config.eip6492AllowedFactories,\n simulateInSettle: config.simulateInSettle,\n }),\n );\n\n // Register all V1 networks\n facilitator.registerV1(\n NETWORKS as Network[],\n new ExactEvmSchemeV1(config.signer, {\n eip6492AllowedFactories: config.eip6492AllowedFactories,\n simulateInSettle: config.simulateInSettle,\n }),\n );\n\n return facilitator;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,SAAS,YAAiB,gBAAgB,6BAA6B;AAsDvE,eAAsB,cACpB,QACA,SACA,cACA,gBACA,SACA,mBAA6B,CAAC,GACL;AACzB,QAAM,QAAQ,eAAe,cAAc;AAC3C,MAAI;AAKJ,MAAI,QAAQ,SAAS,WAAW,WAAW,aAAa,WAAW,SAAS;AAC1E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,aAAa,OAAO,QAAQ,CAAC,aAAa,OAAO,SAAS;AAC7D,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,MAAM,QAAQ,IAAI,aAAa;AACvC,QAAM,eAAe,WAAW,aAAa,KAAK;AAGlD,MAAI,QAAQ,SAAS,YAAY,aAAa,SAAS;AACrD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB;AAAA,IACtB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA,SAAS,cAAc,aAAa,OAAO;AAAA,MAC3C,mBAAmB;AAAA,IACrB;AAAA,IACA,SAAS;AAAA,MACP,MAAM,eAAe,cAAc;AAAA,MACnC,IAAI,eAAe,cAAc;AAAA,MACjC,OAAO,OAAO,eAAe,cAAc,KAAK;AAAA,MAChD,YAAY,OAAO,eAAe,cAAc,UAAU;AAAA,MAC1D,aAAa,OAAO,eAAe,cAAc,WAAW;AAAA,MAC5D,OAAO,eAAe,cAAc;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,YAAY,eAAe;AAIjC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,mBAAmB;AAAA,EACrB,IAAI,MAAM,qBAAqB,QAAQ,WAAW,KAAK;AAEvD,MAAI,oBAAoB;AACtB,wBAAoB;AAAA,EACtB;AAEA,MAAI,kBAAkB;AAIpB,UAAM,UAAU,oBAAoB;AACpC,UAAM,iBACJ,CAAC,CAAC,WAAW,iBAAiB,KAAK,OAAK,EAAE,KAAK,EAAE,YAAY,MAAM,QAAQ,YAAY,CAAC;AAC1F,QAAI,CAAC,gBAAgB;AACnB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAsB;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,kBAAkB;AAMrB,UAAM,UAAU,MAAM,yBAAyB,QAAQ;AAAA,MACrD,SAAS,eAAe,cAAc;AAAA,MACtC,GAAG;AAAA,MACH,WAAW;AAAA,IACb,CAAC;AACD,QAAI,CAAC,SAAS;AACZ,aAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAsB;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAKA,MAAI,WAAW,eAAe,cAAc,EAAE,MAAM,WAAW,aAAa,KAAK,GAAG;AAClF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,MAAI,OAAO,eAAe,cAAc,WAAW,IAAI,OAAO,MAAM,CAAC,GAAG;AACtE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,eAAe,cAAc,UAAU,IAAI,OAAO,GAAG,GAAG;AACjE,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,eAAe,cAAc,KAAK,MAAM,OAAO,aAAa,MAAM,GAAG;AAC9E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAKA,QAAM,gBAAgB,MAAM,OAAO,QAAQ,EAAE,SAAS,aAAa,CAAC;AACpE,MAAI,CAAC,iBAAiB,kBAAkB,MAAM;AAC5C,WAAO,EAAE,SAAS,OAAO,eAAsB,6BAA6B,MAAM;AAAA,EACpF;AAGA,MAAI,SAAS,aAAa,OAAO;AAC/B,UAAM,EAAE,IAAI,OAAO,SAAS,IAAI,MAAM;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,IAAI;AACP,YAAM,YAAY,MAAM;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa;AAAA,MACf;AAEA,YAAM,aACJ,oBAAoB,QAAQ,SAAS,UAAU,WAAW,OAAO,QAAQ,IAAI;AAC/E,aAAO,aAAa,EAAE,GAAG,WAAW,gBAAgB,WAAW,IAAI;AAAA,IACrE;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,eAAe;AAAA,IACf;AAAA,EACF;AACF;AAaA,eAAsB,cACpB,QACA,SACA,cACA,gBACA,QACA,SACyB;AACzB,QAAM,QAAQ,eAAe,cAAc;AAG3C,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,UAAU,OAAO,oBAAoB,MAAM;AAAA,IAC7C,OAAO,2BAA2B,CAAC;AAAA,EACrC;AACA,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,QAAQ,SAAS;AAAA,MAC1B,aAAa;AAAA,MACb,aAAa,MAAM,iBAAwB;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AAIF,UAAM,oBAAoB,sBAAsB,eAAe,SAAU;AACzE,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,MAAM;AAAA,MACN,WAAW;AAAA,IACb,IAAI;AAGJ,QACE,kBACA,mBACA,CAAC,eAAe,gBAAgB,4CAA4C,GAC5E;AAEA,YAAM,WAAW,MAAM,OAAO,QAAQ,EAAE,SAAS,MAAM,CAAC;AAExD,UAAI,CAAC,YAAY,aAAa,MAAM;AAClC,cAAM,oBAAoB,eAAe,YAAY;AACrD,cAAM,aAAa,OAAO,2BAA2B,CAAC,GAAG;AAAA,UACvD,aAAW,QAAQ,YAAY,MAAM;AAAA,QACvC;AACA,YAAI,CAAC,WAAW;AACd,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,aAAoB;AAAA,YACpB,aAAa;AAAA,YACb,SAAS,QAAQ,SAAS;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAGA,cAAM,WAAW,MAAM,OAAO,gBAAgB;AAAA,UAC5C,IAAI;AAAA,UACJ,MAAM;AAAA,QACR,CAAC;AAKD,cAAM,gBAAgB,MAAM,OAAO,0BAA0B,EAAE,MAAM,SAAS,CAAC;AAC/E,YAAI,cAAc,WAAW,WAAW;AACtC,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,aAAoB;AAAA,YACpB,aAAa;AAAA,YACb,SAAS,QAAQ,SAAS;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAAA,MAWF;AAAA,IACF;AAEA,UAAM,aAAa,MAAM,kBAAkB,SAAS;AAAA,MAClD,gBAAgB;AAAA,MAChB,qBAAqB;AAAA,IACvB,CAAC;AAKD,UAAM,gBACJ,mBAAmB,oBAAoB,eAAe,YAClD,EAAE,GAAG,gBAAgB,WAAW,gBAAgB,IAChD;AAEN,UAAM,KAAK,MAAM;AAAA,MACf;AAAA,MACA,WAAW,aAAa,KAAK;AAAA,MAC7B;AAAA,MACA;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,OAAO,0BAA0B,EAAE,MAAM,GAAG,CAAC;AAEnE,QAAI,QAAQ,WAAW,WAAW;AAChC,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAoB;AAAA,QACpB,aAAa;AAAA,QACb,SAAS,QAAQ,SAAS;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAIA,UAAM,OAAO,eAAe;AAC5B,QACE,QAAQ,QAAQ,QAChB,CAAC,2BAA2B,QAAQ,MAAM,WAAW,aAAa,KAAK,GAAG;AAAA,MACxE,MAAM,WAAW,KAAK,IAAI;AAAA,MAC1B,IAAI,WAAW,KAAK,EAAE;AAAA,MACtB,OAAO,OAAO,KAAK,KAAK;AAAA,IAC1B,CAAC,GACD;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,aAAoB;AAAA,QACpB,aAAa;AAAA,QACb,SAAS,QAAQ,SAAS;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa;AAAA,MACb,SAAS,QAAQ,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAId,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,0BAA0B,KAAK;AAAA,MAC5C,cAAc,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACnE,aAAa;AAAA,MACb,SAAS,QAAQ,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;;;AC9ZA,SAAS,cAAAA,aAAY,0BAA0B;AA4B/C,IAAM,mBAAuC;AAAA,EAC3C,cAAc;AAAA,EACd,UAAU;AACZ;AAiCA,eAAsB,cACpB,QACA,SACA,cACA,gBACA,SACA,SACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAElD,MAAI,QAAQ,SAAS,WAAW,WAAW,aAAa,WAAW,SAAS;AAC1E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,YAAY,aAAa,SAAS;AACrD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,cAAc,aAAa,OAAO;AAClD,QAAM,eAAeC,YAAW,aAAa,KAAK;AAElD,QAAM,gBAAgB,MAAM,OAAO,QAAQ,EAAE,SAAS,aAAa,CAAC;AACpE,MAAI,CAAC,iBAAiB,kBAAkB,MAAM;AAC5C,WAAO,EAAE,SAAS,OAAO,eAAsB,6BAA6B,MAAM;AAAA,EACpF;AAEA,MACEA,YAAW,eAAe,qBAAqB,OAAO,MACtDA,YAAW,4BAA4B,GACvC;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,MACEA,YAAW,eAAe,qBAAqB,QAAQ,EAAE,MAAMA,YAAW,aAAa,KAAK,GAC5F;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,MAAI,OAAO,eAAe,qBAAqB,QAAQ,IAAI,OAAO,MAAM,CAAC,GAAG;AAC1E,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,eAAe,qBAAqB,QAAQ,UAAU,IAAI,OAAO,GAAG,GAAG;AAChF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,MACE,OAAO,eAAe,qBAAqB,UAAU,MAAM,MAAM,OAAO,aAAa,MAAM,GAC3F;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,MAAIA,YAAW,eAAe,qBAAqB,UAAU,KAAK,MAAM,cAAc;AACpF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB;AAAA,IACvB,OAAO;AAAA,IACP,aAAa;AAAA,IACb,QAAQ;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA,mBAAmB;AAAA,IACrB;AAAA,IACA,SAAS;AAAA,MACP,WAAW;AAAA,QACT,OAAOA,YAAW,eAAe,qBAAqB,UAAU,KAAK;AAAA,QACrE,QAAQ,OAAO,eAAe,qBAAqB,UAAU,MAAM;AAAA,MACrE;AAAA,MACA,SAASA,YAAW,eAAe,qBAAqB,OAAO;AAAA,MAC/D,OAAO,OAAO,eAAe,qBAAqB,KAAK;AAAA,MACvD,UAAU,OAAO,eAAe,qBAAqB,QAAQ;AAAA,MAC7D,SAAS;AAAA,QACP,IAAIA,YAAW,eAAe,qBAAqB,QAAQ,EAAE;AAAA,QAC7D,YAAY,OAAO,eAAe,qBAAqB,QAAQ,UAAU;AAAA,MAC3E;AAAA,IACF;AAAA,EACF;AAQA,QAAM,iBAAiB,MAAM,yBAAyB,QAAQ;AAAA,IAC5D,SAAS;AAAA,IACT,GAAG;AAAA,IACH,WAAW,eAAe;AAAA,EAC5B,CAAC;AACD,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAsB;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,aAAa,OAAO;AAC/B,WAAO,EAAE,SAAS,MAAM,eAAe,QAAW,MAAM;AAAA,EAC1D;AAGA,QAAM,cAAc,gCAAgC,OAAO;AAC3D,MAAI,aAAa;AACf,UAAM,cAAc,gCAAgC,aAAa,OAAO,YAAY;AACpF,QAAI,CAAC,YAAY,SAAS;AACxB,aAAO,EAAE,SAAS,OAAO,eAAe,YAAY,eAAgB,MAAM;AAAA,IAC5E;AAEA,UAAM,kBAAkB,4BAA4B,cAAc;AAClE,UAAMC,SAAQ,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAACA,QAAO;AACV,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAEA,WAAO,EAAE,SAAS,MAAM,eAAe,QAAW,MAAM;AAAA,EAC1D;AAGA,QAAM,+BACJ,SAAS;AAAA,IACP;AAAA,EACF;AACF,MAAI,8BAA8B;AAChC,UAAM,YAAY,sCAAsC,OAAO;AAC/D,QAAI,WAAW;AACb,YAAM,cAAc,MAAM,gCAAgC,WAAW,OAAO,YAAY;AACxF,UAAI,CAAC,YAAY,SAAS;AACxB,eAAO,EAAE,SAAS,OAAO,eAAe,YAAY,eAAgB,MAAM;AAAA,MAC5E;AAEA,YAAM,kBAAkB;AAAA,QACtB;AAAA,QACA,aAAa;AAAA,MACf;AAEA,UAAI,iBAAiB,sBAAsB;AACzC,cAAMA,SAAQ,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,UACA,4BAA4B,cAAc;AAAA,UAC1C;AAAA,QACF;AACA,YAAI,CAACA,QAAO;AACV,iBAAO;AAAA,YACL;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,aAAa;AAAA,UACf;AAAA,QACF;AACA,eAAO,EAAE,SAAS,MAAM,eAAe,QAAW,MAAM;AAAA,MAC1D;AAGA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA,4BAA4B,cAAc;AAAA,EAC5C;AACA,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa;AAAA,IACf;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,MAAM,eAAe,QAAW,MAAM;AAC1D;AAiBA,eAAsB,cACpB,QACA,SACA,cACA,gBACA,SACA,QACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAElD,QAAM,QAAQ,MAAM,cAAc,QAAQ,SAAS,cAAc,gBAAgB,SAAS;AAAA,IACxF,UAAU,QAAQ,oBAAoB;AAAA,EACxC,CAAC;AACD,MAAI,CAAC,MAAM,SAAS;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,QAAQ,SAAS;AAAA,MAC1B,aAAa;AAAA,MACb,aAAa,MAAM,iBAAwB;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,kBAAkB,SAAS;AAAA,IAClD,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,EACvB,CAAC;AAGD,QAAM,cAAc,gCAAgC,OAAO;AAC3D,MAAI,aAAa;AACf,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,sCAAsC,OAAO;AAC/D,MAAI,WAAW;AACb,UAAM,+BACJ,SAAS;AAAA,MACP;AAAA,IACF;AACF,UAAM,kBAAkB;AAAA,MACtB;AAAA,MACA,QAAQ,SAAS;AAAA,IACnB;AACA,QAAI,iBAAiB;AACnB,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO,oBAAoB,kBAAkB,QAAQ,SAAS,gBAAgB,UAAU;AAC1F;AAiBA,eAAe,yBACb,QACA,QACA,SACA,gBACA,aACA,YACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAClD,MAAI;AACF,UAAM,EAAE,GAAG,GAAG,EAAE,IAAI,sBAAsB,YAAY,SAAS;AAE/D,UAAM,KAAK,MAAM,OAAO,cAAc;AAAA,MACpC,SAAS,OAAO;AAAA,MAChB,KAAK,OAAO;AAAA,MACZ,cAAc;AAAA,MACd,MAAM;AAAA,QACJ;AAAA,UACE,OAAO,OAAO,YAAY,MAAM;AAAA,UAChC,UAAU,OAAO,YAAY,QAAQ;AAAA,UACrC;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,GAAG,4BAA4B,cAAc;AAAA,MAC/C;AAAA,MACA;AAAA,IACF,CAAC;AAED,WAAO,4BAA4B,QAAQ,IAAI,SAAS,KAAK;AAAA,EAC/D,SAAS,OAAO;AACd,WAAO,eAAe,OAAO,SAAS,KAAK;AAAA,EAC7C;AACF;AAcA,eAAe,+BACb,QACA,iBACA,SACA,gBACA,WACA,YACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAElD,MAAI;AACF,UAAM,aAAa;AAAA,MACjB,mBAAmB;AAAA,QACjB,KAAK,OAAO;AAAA,QACZ,cAAc;AAAA,QACd,MAAM,4BAA4B,cAAc;AAAA,MAClD,CAAC;AAAA,MACD;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,gBAAgB,iBAAiB;AAAA,MACtD,UAAU;AAAA,MACV,EAAE,IAAI,OAAO,cAAc,MAAM,YAAY,KAAK,OAAO,GAAO,EAAE;AAAA,IACpE,CAAC;AAED,UAAM,eAAe,SAAS,SAAS,SAAS,CAAC;AACjD,WAAO,4BAA4B,iBAAiB,cAAc,SAAS,KAAK;AAAA,EAClF,SAAS,OAAO;AACd,WAAO,eAAe,OAAO,SAAS,KAAK;AAAA,EAC7C;AACF;AAYA,eAAe,oBACb,QACA,QACA,SACA,gBACA,YACyB;AACzB,QAAM,QAAQ,eAAe,qBAAqB;AAClD,MAAI;AACF,UAAM,KAAK,MAAM,OAAO,cAAc;AAAA,MACpC,SAAS,OAAO;AAAA,MAChB,KAAK,OAAO;AAAA,MACZ,cAAc;AAAA,MACd,MAAM,4BAA4B,cAAc;AAAA,MAChD;AAAA,IACF,CAAC;AAED,WAAO,4BAA4B,QAAQ,IAAI,SAAS,KAAK;AAAA,EAC/D,SAAS,OAAO;AACd,WAAO,eAAe,OAAO,SAAS,KAAK;AAAA,EAC7C;AACF;;;ACneO,IAAM,iBAAN,MAAyD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW9D,YACmB,QACjB,QACA;AAFiB;AAXnB,SAAS,SAAS;AAClB,SAAS,aAAa;AAapB,SAAK,SAAS;AAAA,MACZ,yBAAyB,QAAQ,2BAA2B,CAAC;AAAA,MAC7D,kBAAkB,QAAQ,oBAAoB;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,GAAgD;AACvD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,GAAqB;AAC9B,WAAO,CAAC,GAAG,KAAK,OAAO,aAAa,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,OACJ,SACA,cACA,SACA,GACyB;AACzB,UAAM,aAAa,QAAQ;AAC3B,UAAM,YAAY,iBAAiB,UAAU;AAE7C,QAAI,WAAW;AACb,aAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,YAAY,OAAO;AAAA,IAC9E;AAEA,UAAM,iBAAsC;AAC5C,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,OACJ,SACA,cACA,SACyB;AACzB,UAAM,aAAa,QAAQ;AAC3B,UAAM,YAAY,iBAAiB,UAAU;AAE7C,QAAI,WAAW;AACb,aAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,YAAY,SAAS;AAAA,QAC5E,kBAAkB,KAAK,OAAO;AAAA,MAChC,CAAC;AAAA,IACH;AAEA,UAAM,iBAAsC;AAC5C,WAAO,cAAc,KAAK,QAAQ,SAAS,cAAc,gBAAgB,KAAK,QAAQ,OAAO;AAAA,EAC/F;AACF;;;AChEO,SAAS,uBACd,aACA,QACiB;AAEjB,cAAY;AAAA,IACV,OAAO;AAAA,IACP,IAAI,eAAe,OAAO,QAAQ;AAAA,MAChC,yBAAyB,OAAO;AAAA,MAChC,kBAAkB,OAAO;AAAA,IAC3B,CAAC;AAAA,EACH;AAGA,cAAY;AAAA,IACV;AAAA,IACA,IAAI,iBAAiB,OAAO,QAAQ;AAAA,MAClC,yBAAyB,OAAO;AAAA,MAChC,kBAAkB,OAAO;AAAA,IAC3B,CAAC;AAAA,EACH;AAEA,SAAO;AACT;","names":["getAddress","getAddress","simOk"]}
import {
getDefaultAsset
} from "../../chunk-DQI2DTA4.mjs";
} from "../../chunk-KTVL22S4.mjs";

@@ -5,0 +5,0 @@ // src/exact/server/scheme.ts

import {
ExactEvmSchemeV12 as ExactEvmSchemeV1
} from "../../../chunk-ZWPJEMS5.mjs";
} from "../../../chunk-NVFLWXGP.mjs";
import "../../../chunk-BEMCJZKA.mjs";
import "../../../chunk-23HX7MHV.mjs";
import "../../../chunk-7ER7IIEN.mjs";
import "../../../chunk-27MWX225.mjs";

@@ -7,0 +7,0 @@ import "../../../chunk-MACPBXCT.mjs";

import {
ExactEvmSchemeV1
} from "../../../chunk-ZWPJEMS5.mjs";
} from "../../../chunk-NVFLWXGP.mjs";
import "../../../chunk-BEMCJZKA.mjs";
import "../../../chunk-23HX7MHV.mjs";
import "../../../chunk-7ER7IIEN.mjs";
import "../../../chunk-27MWX225.mjs";

@@ -7,0 +7,0 @@ import "../../../chunk-MACPBXCT.mjs";

@@ -207,4 +207,4 @@ export { E as ExactEvmScheme } from './scheme-B1OAu4_v.mjs';

* Each network has the right to determine its own default stablecoin that can
* be expressed as a USD string by calling servers. See DEFAULT_ASSET.md in
* exact/server/ for how to add new chains.
* be expressed as a USD string by calling servers. See DEFAULT_ASSETS.md at the
* repository root for how to add new chains.
*/

@@ -211,0 +211,0 @@ declare const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo>;

@@ -24,7 +24,7 @@ import {

ExactEvmScheme
} from "./chunk-GSVPWDXO.mjs";
} from "./chunk-3QTA5JH4.mjs";
import {
DEFAULT_STABLECOINS,
getDefaultAsset
} from "./chunk-DQI2DTA4.mjs";
} from "./chunk-KTVL22S4.mjs";
import {

@@ -43,3 +43,3 @@ isEIP3009Payload,

} from "./chunk-U4HCGTLU.mjs";
import "./chunk-ZWPJEMS5.mjs";
import "./chunk-NVFLWXGP.mjs";
import {

@@ -57,5 +57,5 @@ classifyErc6492Payer,

getPermit2AllowanceReadParams
} from "./chunk-63YBFPIQ.mjs";
import "./chunk-HAEDTF25.mjs";
import "./chunk-23HX7MHV.mjs";
} from "./chunk-UBBS476I.mjs";
import "./chunk-JFVEMVMS.mjs";
import "./chunk-7ER7IIEN.mjs";
import {

@@ -62,0 +62,0 @@ BUILDER_CODE_KEY,

@@ -7,5 +7,5 @@ import {

getPermit2AllowanceReadParams
} from "../../chunk-63YBFPIQ.mjs";
import "../../chunk-HAEDTF25.mjs";
import "../../chunk-23HX7MHV.mjs";
} from "../../chunk-UBBS476I.mjs";
import "../../chunk-JFVEMVMS.mjs";
import "../../chunk-7ER7IIEN.mjs";
import "../../chunk-27MWX225.mjs";

@@ -12,0 +12,0 @@ import {

@@ -24,7 +24,7 @@ import {

waitAndReturnSettleResponse
} from "../../chunk-HAEDTF25.mjs";
} from "../../chunk-JFVEMVMS.mjs";
import {
ErrAssetNotDeployedContract,
ErrPermit2AmountMismatch
} from "../../chunk-23HX7MHV.mjs";
} from "../../chunk-7ER7IIEN.mjs";
import {

@@ -31,0 +31,0 @@ ERC20_APPROVAL_GAS_SPONSORING_KEY,

import {
getDefaultAsset
} from "../../chunk-DQI2DTA4.mjs";
} from "../../chunk-KTVL22S4.mjs";

@@ -5,0 +5,0 @@ // src/upto/server/scheme.ts

@@ -28,2 +28,4 @@ export { ExactEvmSchemeV1 } from '../exact/v1/client/index.mjs';

readonly "stable-testnet": 2201;
readonly celo: 42220;
readonly flare: 14;
};

@@ -30,0 +32,0 @@ type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP;

@@ -6,5 +6,5 @@ import {

getEvmChainIdV1
} from "../chunk-ZWPJEMS5.mjs";
} from "../chunk-NVFLWXGP.mjs";
import "../chunk-BEMCJZKA.mjs";
import "../chunk-23HX7MHV.mjs";
import "../chunk-7ER7IIEN.mjs";
import "../chunk-27MWX225.mjs";

@@ -11,0 +11,0 @@ import "../chunk-MACPBXCT.mjs";

{
"name": "@x402/evm",
"version": "2.20.0",
"version": "2.21.0",
"main": "./dist/cjs/index.js",

@@ -38,3 +38,3 @@ "module": "./dist/esm/index.js",

"zod": "^3.24.2",
"@x402/core": "~2.20.0"
"@x402/core": "~2.21.0"
},

@@ -41,0 +41,0 @@ "exports": {

// src/exact/facilitator/errors.ts
var ErrAssetNotDeployedContract = "asset_not_deployed_contract";
var ErrInvalidScheme = "invalid_exact_evm_scheme";
var ErrNetworkMismatch = "invalid_exact_evm_network_mismatch";
var ErrMissingEip712Domain = "invalid_exact_evm_missing_eip712_domain";
var ErrRecipientMismatch = "invalid_exact_evm_recipient_mismatch";
var ErrInvalidSignature = "invalid_exact_evm_signature";
var ErrValidBeforeExpired = "invalid_exact_evm_payload_authorization_valid_before";
var ErrValidAfterInFuture = "invalid_exact_evm_payload_authorization_valid_after";
var ErrInvalidAuthorizationValue = "invalid_exact_evm_authorization_value";
var ErrAuthorizationValueMismatch = "invalid_exact_evm_payload_authorization_value_mismatch";
var ErrTransactionFailed = "invalid_exact_evm_transaction_failed";
var ErrEip3009TokenNameMismatch = "invalid_exact_evm_token_name_mismatch";
var ErrEip3009TokenVersionMismatch = "invalid_exact_evm_token_version_mismatch";
var ErrEip3009NotSupported = "invalid_exact_evm_eip3009_not_supported";
var ErrEip3009NonceAlreadyUsed = "invalid_exact_evm_nonce_already_used";
var ErrEip3009InsufficientBalance = "invalid_exact_evm_insufficient_balance";
var ErrEip3009SimulationFailed = "invalid_exact_evm_transaction_simulation_failed";
var ErrPermit2InvalidSpender = "invalid_permit2_spender";
var ErrPermit2RecipientMismatch = "invalid_permit2_recipient_mismatch";
var ErrPermit2DeadlineExpired = "permit2_deadline_expired";
var ErrPermit2NotYetValid = "permit2_not_yet_valid";
var ErrPermit2AmountMismatch = "permit2_amount_mismatch";
var ErrPermit2TokenMismatch = "permit2_token_mismatch";
var ErrPermit2InvalidSignature = "invalid_permit2_signature";
var ErrPermit2AllowanceRequired = "permit2_allowance_required";
var ErrPermit2SimulationFailed = "permit2_simulation_failed";
var ErrPermit2InsufficientBalance = "permit2_insufficient_balance";
var ErrPermit2ProxyNotDeployed = "permit2_proxy_not_deployed";
var ErrPermit2InvalidAmount = "permit2_invalid_amount";
var ErrPermit2InvalidDestination = "permit2_invalid_destination";
var ErrPermit2InvalidOwner = "permit2_invalid_owner";
var ErrPermit2PaymentTooEarly = "permit2_payment_too_early";
var ErrPermit2InvalidNonce = "permit2_invalid_nonce";
var ErrPermit2612AmountMismatch = "permit2_2612_amount_mismatch";
var ErrErc20ApprovalInvalidFormat = "invalid_erc20_approval_extension_format";
var ErrErc20ApprovalFromMismatch = "erc20_approval_from_mismatch";
var ErrErc20ApprovalAssetMismatch = "erc20_approval_asset_mismatch";
var ErrErc20ApprovalSpenderNotPermit2 = "erc20_approval_spender_not_permit2";
var ErrErc20ApprovalTxWrongTarget = "erc20_approval_tx_wrong_target";
var ErrErc20ApprovalTxWrongSelector = "erc20_approval_tx_wrong_selector";
var ErrErc20ApprovalTxWrongSpender = "erc20_approval_tx_wrong_spender";
var ErrErc20ApprovalTxInvalidCalldata = "erc20_approval_tx_invalid_calldata";
var ErrErc20ApprovalTxSignerMismatch = "erc20_approval_tx_signer_mismatch";
var ErrErc20ApprovalTxInvalidSignature = "erc20_approval_tx_invalid_signature";
var ErrErc20ApprovalTxParseFailed = "erc20_approval_tx_parse_failed";
var ErrErc20ApprovalTxFailed = "erc20_approval_tx_failed";
var ErrInvalidEip2612ExtensionFormat = "invalid_eip2612_extension_format";
var ErrEip2612FromMismatch = "eip2612_from_mismatch";
var ErrEip2612AssetMismatch = "eip2612_asset_mismatch";
var ErrEip2612SpenderNotPermit2 = "eip2612_spender_not_permit2";
var ErrEip2612DeadlineExpired = "eip2612_deadline_expired";
var ErrUnsupportedPayloadType = "unsupported_payload_type";
var ErrInvalidTransactionState = "invalid_transaction_state";
var ErrFactoryNotAllowed = "eip6492_factory_not_allowed";
var ErrSmartWalletDeploymentFailed = "smart_wallet_deployment_failed";
export {
ErrAssetNotDeployedContract,
ErrInvalidScheme,
ErrNetworkMismatch,
ErrMissingEip712Domain,
ErrRecipientMismatch,
ErrInvalidSignature,
ErrValidBeforeExpired,
ErrValidAfterInFuture,
ErrInvalidAuthorizationValue,
ErrAuthorizationValueMismatch,
ErrTransactionFailed,
ErrEip3009TokenNameMismatch,
ErrEip3009TokenVersionMismatch,
ErrEip3009NotSupported,
ErrEip3009NonceAlreadyUsed,
ErrEip3009InsufficientBalance,
ErrEip3009SimulationFailed,
ErrPermit2InvalidSpender,
ErrPermit2RecipientMismatch,
ErrPermit2DeadlineExpired,
ErrPermit2NotYetValid,
ErrPermit2AmountMismatch,
ErrPermit2TokenMismatch,
ErrPermit2InvalidSignature,
ErrPermit2AllowanceRequired,
ErrPermit2SimulationFailed,
ErrPermit2InsufficientBalance,
ErrPermit2ProxyNotDeployed,
ErrPermit2InvalidAmount,
ErrPermit2InvalidDestination,
ErrPermit2InvalidOwner,
ErrPermit2PaymentTooEarly,
ErrPermit2InvalidNonce,
ErrPermit2612AmountMismatch,
ErrErc20ApprovalInvalidFormat,
ErrErc20ApprovalFromMismatch,
ErrErc20ApprovalAssetMismatch,
ErrErc20ApprovalSpenderNotPermit2,
ErrErc20ApprovalTxWrongTarget,
ErrErc20ApprovalTxWrongSelector,
ErrErc20ApprovalTxWrongSpender,
ErrErc20ApprovalTxInvalidCalldata,
ErrErc20ApprovalTxSignerMismatch,
ErrErc20ApprovalTxInvalidSignature,
ErrErc20ApprovalTxParseFailed,
ErrErc20ApprovalTxFailed,
ErrInvalidEip2612ExtensionFormat,
ErrEip2612FromMismatch,
ErrEip2612AssetMismatch,
ErrEip2612SpenderNotPermit2,
ErrEip2612DeadlineExpired,
ErrUnsupportedPayloadType,
ErrInvalidTransactionState,
ErrFactoryNotAllowed,
ErrSmartWalletDeploymentFailed
};
//# sourceMappingURL=chunk-23HX7MHV.mjs.map
{"version":3,"sources":["../../src/exact/facilitator/errors.ts"],"sourcesContent":["/**\n * Named error reason constants for the exact EVM facilitator.\n *\n * These strings must be character-for-character identical to the Go constants in\n * go/mechanisms/evm/exact/facilitator/errors.go to maintain cross-SDK parity.\n */\n\nexport const ErrAssetNotDeployedContract = \"asset_not_deployed_contract\";\n\nexport const ErrInvalidScheme = \"invalid_exact_evm_scheme\";\nexport const ErrNetworkMismatch = \"invalid_exact_evm_network_mismatch\";\nexport const ErrMissingEip712Domain = \"invalid_exact_evm_missing_eip712_domain\";\nexport const ErrRecipientMismatch = \"invalid_exact_evm_recipient_mismatch\";\nexport const ErrInvalidSignature = \"invalid_exact_evm_signature\";\nexport const ErrValidBeforeExpired = \"invalid_exact_evm_payload_authorization_valid_before\";\nexport const ErrValidAfterInFuture = \"invalid_exact_evm_payload_authorization_valid_after\";\nexport const ErrInvalidAuthorizationValue = \"invalid_exact_evm_authorization_value\";\nexport const ErrAuthorizationValueMismatch =\n \"invalid_exact_evm_payload_authorization_value_mismatch\";\nexport const ErrUndeployedSmartWallet = \"invalid_exact_evm_payload_undeployed_smart_wallet\";\nexport const ErrTransactionFailed = \"invalid_exact_evm_transaction_failed\";\n\n// EIP-3009 verify errors\nexport const ErrEip3009TokenNameMismatch = \"invalid_exact_evm_token_name_mismatch\";\nexport const ErrEip3009TokenVersionMismatch = \"invalid_exact_evm_token_version_mismatch\";\nexport const ErrEip3009NotSupported = \"invalid_exact_evm_eip3009_not_supported\";\nexport const ErrEip3009NonceAlreadyUsed = \"invalid_exact_evm_nonce_already_used\";\nexport const ErrEip3009InsufficientBalance = \"invalid_exact_evm_insufficient_balance\";\nexport const ErrEip3009SimulationFailed = \"invalid_exact_evm_transaction_simulation_failed\";\n\n// Permit2 verify errors\nexport const ErrPermit2InvalidSpender = \"invalid_permit2_spender\";\nexport const ErrPermit2RecipientMismatch = \"invalid_permit2_recipient_mismatch\";\nexport const ErrPermit2DeadlineExpired = \"permit2_deadline_expired\";\nexport const ErrPermit2NotYetValid = \"permit2_not_yet_valid\";\nexport const ErrPermit2AmountMismatch = \"permit2_amount_mismatch\";\nexport const ErrPermit2TokenMismatch = \"permit2_token_mismatch\";\nexport const ErrPermit2InvalidSignature = \"invalid_permit2_signature\";\nexport const ErrPermit2AllowanceRequired = \"permit2_allowance_required\";\nexport const ErrPermit2SimulationFailed = \"permit2_simulation_failed\";\nexport const ErrPermit2InsufficientBalance = \"permit2_insufficient_balance\";\nexport const ErrPermit2ProxyNotDeployed = \"permit2_proxy_not_deployed\";\n\n// Permit2 settle errors (from contract reverts)\nexport const ErrPermit2InvalidAmount = \"permit2_invalid_amount\";\nexport const ErrPermit2InvalidDestination = \"permit2_invalid_destination\";\nexport const ErrPermit2InvalidOwner = \"permit2_invalid_owner\";\nexport const ErrPermit2PaymentTooEarly = \"permit2_payment_too_early\";\nexport const ErrPermit2InvalidNonce = \"permit2_invalid_nonce\";\nexport const ErrPermit2612AmountMismatch = \"permit2_2612_amount_mismatch\";\n\n// ERC-20 approval gas sponsoring verify errors\nexport const ErrErc20ApprovalInvalidFormat = \"invalid_erc20_approval_extension_format\";\nexport const ErrErc20ApprovalFromMismatch = \"erc20_approval_from_mismatch\";\nexport const ErrErc20ApprovalAssetMismatch = \"erc20_approval_asset_mismatch\";\nexport const ErrErc20ApprovalSpenderNotPermit2 = \"erc20_approval_spender_not_permit2\";\nexport const ErrErc20ApprovalTxWrongTarget = \"erc20_approval_tx_wrong_target\";\nexport const ErrErc20ApprovalTxWrongSelector = \"erc20_approval_tx_wrong_selector\";\nexport const ErrErc20ApprovalTxWrongSpender = \"erc20_approval_tx_wrong_spender\";\nexport const ErrErc20ApprovalTxInvalidCalldata = \"erc20_approval_tx_invalid_calldata\";\nexport const ErrErc20ApprovalTxSignerMismatch = \"erc20_approval_tx_signer_mismatch\";\nexport const ErrErc20ApprovalTxInvalidSignature = \"erc20_approval_tx_invalid_signature\";\nexport const ErrErc20ApprovalTxParseFailed = \"erc20_approval_tx_parse_failed\";\nexport const ErrErc20ApprovalTxFailed = \"erc20_approval_tx_failed\";\n\n// EIP-2612 gas sponsoring verify errors\nexport const ErrInvalidEip2612ExtensionFormat = \"invalid_eip2612_extension_format\";\nexport const ErrEip2612FromMismatch = \"eip2612_from_mismatch\";\nexport const ErrEip2612AssetMismatch = \"eip2612_asset_mismatch\";\nexport const ErrEip2612SpenderNotPermit2 = \"eip2612_spender_not_permit2\";\nexport const ErrEip2612DeadlineExpired = \"eip2612_deadline_expired\";\n\n// Shared settle errors\nexport const ErrUnsupportedPayloadType = \"unsupported_payload_type\";\nexport const ErrInvalidTransactionState = \"invalid_transaction_state\";\nexport const ErrFactoryNotAllowed = \"eip6492_factory_not_allowed\";\nexport const ErrSmartWalletDeploymentFailed = \"smart_wallet_deployment_failed\";\n"],"mappings":";AAOO,IAAM,8BAA8B;AAEpC,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAC5B,IAAM,wBAAwB;AAC9B,IAAM,wBAAwB;AAC9B,IAAM,+BAA+B;AACrC,IAAM,gCACX;AAEK,IAAM,uBAAuB;AAG7B,IAAM,8BAA8B;AACpC,IAAM,iCAAiC;AACvC,IAAM,yBAAyB;AAC/B,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,6BAA6B;AAGnC,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AACpC,IAAM,4BAA4B;AAClC,IAAM,wBAAwB;AAC9B,IAAM,2BAA2B;AACjC,IAAM,0BAA0B;AAChC,IAAM,6BAA6B;AACnC,IAAM,8BAA8B;AACpC,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,6BAA6B;AAGnC,IAAM,0BAA0B;AAChC,IAAM,+BAA+B;AACrC,IAAM,yBAAyB;AAC/B,IAAM,4BAA4B;AAClC,IAAM,yBAAyB;AAC/B,IAAM,8BAA8B;AAGpC,IAAM,gCAAgC;AACtC,IAAM,+BAA+B;AACrC,IAAM,gCAAgC;AACtC,IAAM,oCAAoC;AAC1C,IAAM,gCAAgC;AACtC,IAAM,kCAAkC;AACxC,IAAM,iCAAiC;AACvC,IAAM,oCAAoC;AAC1C,IAAM,mCAAmC;AACzC,IAAM,qCAAqC;AAC3C,IAAM,gCAAgC;AACtC,IAAM,2BAA2B;AAGjC,IAAM,mCAAmC;AACzC,IAAM,yBAAyB;AAC/B,IAAM,0BAA0B;AAChC,IAAM,8BAA8B;AACpC,IAAM,4BAA4B;AAGlC,IAAM,4BAA4B;AAClC,IAAM,6BAA6B;AACnC,IAAM,uBAAuB;AAC7B,IAAM,iCAAiC;","names":[]}
import {
createPermit2PayloadForProxy
} from "./chunk-HAEDTF25.mjs";
import {
PERMIT2_ADDRESS,
erc20AllowanceAbi,
erc20ApproveAbi,
x402ExactPermit2ProxyAddress
} from "./chunk-MACPBXCT.mjs";
// src/exact/client/permit2.ts
import { encodeFunctionData, getAddress } from "viem";
var MAX_UINT256 = BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
async function createPermit2Payload(signer, x402Version, paymentRequirements) {
return createPermit2PayloadForProxy(
x402ExactPermit2ProxyAddress,
signer,
x402Version,
paymentRequirements
);
}
function createPermit2ApprovalTx(tokenAddress) {
const data = encodeFunctionData({
abi: erc20ApproveAbi,
functionName: "approve",
args: [PERMIT2_ADDRESS, MAX_UINT256]
});
return {
to: getAddress(tokenAddress),
data
};
}
function getPermit2AllowanceReadParams(params) {
return {
address: getAddress(params.tokenAddress),
abi: erc20AllowanceAbi,
functionName: "allowance",
args: [getAddress(params.ownerAddress), PERMIT2_ADDRESS]
};
}
export {
createPermit2Payload,
createPermit2ApprovalTx,
getPermit2AllowanceReadParams
};
//# sourceMappingURL=chunk-63YBFPIQ.mjs.map
{"version":3,"sources":["../../src/exact/client/permit2.ts"],"sourcesContent":["import { PaymentRequirements, PaymentPayloadResult } from \"@x402/core/types\";\nimport { encodeFunctionData, getAddress } from \"viem\";\nimport {\n PERMIT2_ADDRESS,\n x402ExactPermit2ProxyAddress,\n erc20ApproveAbi,\n erc20AllowanceAbi,\n} from \"../../constants\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { createPermit2PayloadForProxy } from \"../../shared/permit2\";\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 return createPermit2PayloadForProxy(\n x402ExactPermit2ProxyAddress,\n signer,\n x402Version,\n paymentRequirements,\n );\n}\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"],"mappings":";;;;;;;;;;;AACA,SAAS,oBAAoB,kBAAkB;AAW/C,IAAM,cAAc,OAAO,oEAAoE;AAY/F,eAAsB,qBACpB,QACA,aACA,qBAC+B;AAC/B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAkBO,SAAS,wBAAwB,cAGtC;AACA,QAAM,OAAO,mBAAmB;AAAA,IAC9B,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,iBAAiB,WAAW;AAAA,EACrC,CAAC;AAED,SAAO;AAAA,IACL,IAAI,WAAW,YAAY;AAAA,IAC3B;AAAA,EACF;AACF;AA6BO,SAAS,8BAA8B,QAK5C;AACA,SAAO;AAAA,IACL,SAAS,WAAW,OAAO,YAAY;AAAA,IACvC,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,WAAW,OAAO,YAAY,GAAG,eAAe;AAAA,EACzD;AACF;","names":[]}
// src/shared/defaultAssets.ts
var DEFAULT_STABLECOINS = {
"eip155:8453": {
address: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
name: "USD Coin",
version: "2",
decimals: 6
},
// Base mainnet USDC
"eip155:84532": {
address: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
name: "USDC",
version: "2",
decimals: 6
},
// Base Sepolia USDC
"eip155:4326": {
address: "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7",
name: "MegaUSD",
version: "1",
decimals: 18,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)
"eip155:143": {
address: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603",
name: "USD Coin",
version: "2",
decimals: 6
},
// Monad mainnet USDC
"eip155:988": {
address: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736",
name: "USDT0",
version: "1",
decimals: 6
},
// Stable mainnet USDT0
"eip155:2201": {
address: "0x78Cf24370174180738C5B8E352B6D14c83a6c9A9",
name: "USDT0",
version: "1",
decimals: 6
},
// Stable testnet USDT0
"eip155:137": {
address: "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
name: "USD Coin",
version: "2",
decimals: 6
},
// Polygon mainnet USDC
"eip155:42161": {
address: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
name: "USD Coin",
version: "2",
decimals: 6
},
// Arbitrum One USDC
"eip155:421614": {
address: "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d",
name: "USD Coin",
version: "2",
decimals: 6
},
// Arbitrum Sepolia USDC
"eip155:31612": {
address: "0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186",
name: "Mezo USD",
version: "1",
decimals: 18,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)
"eip155:31611": {
address: "0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503",
name: "Mezo USD",
version: "1",
decimals: 18,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)
"eip155:723487": {
address: "0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb",
name: "Stable Coin",
version: "1",
decimals: 6,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Radius Network SBC (no EIP-3009, supports EIP-2612)
"eip155:72344": {
address: "0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb",
name: "Stable Coin",
version: "1",
decimals: 6,
assetTransferMethod: "permit2",
supportsEip2612: true
},
// Radius Testnet SBC (no EIP-3009, supports EIP-2612)
"eip155:36900": {
address: "0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2",
name: "USDC.e",
version: "2",
decimals: 6
},
// ADI Chain USDC.e (EIP-3009 supported)
"eip155:190415": {
address: "0x401eCb1D350407f13ba348573E5630B83638E30D",
name: "Bridged USDC",
version: "2",
decimals: 6
},
// HPP mainnet USDC.e
"eip155:181228": {
address: "0x401eCb1D350407f13ba348573E5630B83638E30D",
name: "Bridged USDC",
version: "2",
decimals: 6
},
// HPP Sepolia USDC.e
"eip155:50": {
address: "0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1",
name: "USDC",
version: "2",
decimals: 6
},
// XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)
"eip155:51": {
address: "0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4",
name: "USDC",
version: "2",
decimals: 6
},
// XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)
"eip155:38833": {
address: "0xA5b8BF902b2844dA17d4506cc827F7F1681735E7",
name: "USDC",
version: "1",
decimals: 6,
assetTransferMethod: "permit2"
}
// Igra mainnet USDC (no EIP-3009, no EIP-2612)
};
function getDefaultAsset(network) {
const info = DEFAULT_STABLECOINS[network];
if (!info) {
throw new Error(`No default asset configured for network ${network}`);
}
return info;
}
export {
DEFAULT_STABLECOINS,
getDefaultAsset
};
//# sourceMappingURL=chunk-DQI2DTA4.mjs.map
{"version":3,"sources":["../../src/shared/defaultAssets.ts"],"sourcesContent":["import type { Network } from \"@x402/core/types\";\n\n/**\n * Base stablecoin asset configuration shared across all EVM payment schemes.\n * Contains the core fields needed to identify and convert tokens.\n */\nexport type DefaultAssetInfo = {\n /** Token contract address */\n address: string;\n /** EIP-712 domain name (must match the token's domain separator) */\n name: string;\n /** EIP-712 domain version (must match the token's domain separator) */\n version: string;\n /** Token decimal places (typically 6 for USDC) */\n decimals: number;\n};\n\n/**\n * Extended asset configuration for the exact scheme.\n * Includes transfer method hints that control client-side behaviour.\n */\nexport type ExactDefaultAssetInfo = DefaultAssetInfo & {\n /**\n * Transfer method override: `\"permit2\"` for tokens that don't support EIP-3009.\n * Omit for EIP-3009 tokens (default behaviour).\n */\n assetTransferMethod?: string;\n /**\n * Set to `true` for permit2 tokens that implement EIP-2612 `permit()`.\n * Controls whether name/version are included in `extra` so the client can\n * sign a gasless EIP-2612 permit for Permit2 approval.\n */\n supportsEip2612?: boolean;\n};\n\n/**\n * Default stablecoins indexed by CAIP-2 network identifier.\n *\n * Each network has the right to determine its own default stablecoin that can\n * be expressed as a USD string by calling servers. See DEFAULT_ASSET.md in\n * exact/server/ for how to add new chains.\n */\nexport const DEFAULT_STABLECOINS: Record<string, ExactDefaultAssetInfo> = {\n \"eip155:8453\": {\n address: \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Base mainnet USDC\n \"eip155:84532\": {\n address: \"0x036CbD53842c5426634e7929541eC2318f3dCF7e\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // Base Sepolia USDC\n \"eip155:4326\": {\n address: \"0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7\",\n name: \"MegaUSD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // MegaETH mainnet MegaUSD (no EIP-3009, supports EIP-2612)\n \"eip155:143\": {\n address: \"0x754704Bc059F8C67012fEd69BC8A327a5aafb603\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Monad mainnet USDC\n \"eip155:988\": {\n address: \"0x779Ded0c9e1022225f8E0630b35a9b54bE713736\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable mainnet USDT0\n \"eip155:2201\": {\n address: \"0x78Cf24370174180738C5B8E352B6D14c83a6c9A9\",\n name: \"USDT0\",\n version: \"1\",\n decimals: 6,\n }, // Stable testnet USDT0\n \"eip155:137\": {\n address: \"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Polygon mainnet USDC\n \"eip155:42161\": {\n address: \"0xaf88d065e77c8cC2239327C5EDb3A432268e5831\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum One USDC\n \"eip155:421614\": {\n address: \"0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d\",\n name: \"USD Coin\",\n version: \"2\",\n decimals: 6,\n }, // Arbitrum Sepolia USDC\n \"eip155:31612\": {\n address: \"0xdD468A1DDc392dcdbEf6db6e34E89AA338F9F186\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo mainnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:31611\": {\n address: \"0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503\",\n name: \"Mezo USD\",\n version: \"1\",\n decimals: 18,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Mezo Testnet mUSD (no EIP-3009, supports EIP-2612)\n \"eip155:723487\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Network SBC (no EIP-3009, supports EIP-2612)\n \"eip155:72344\": {\n address: \"0x33ad9e4BD16B69B5BFdED37D8B5D9fF9aba014Fb\",\n name: \"Stable Coin\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n supportsEip2612: true,\n }, // Radius Testnet SBC (no EIP-3009, supports EIP-2612)\n \"eip155:36900\": {\n address: \"0x9cb8142aEBBcdc60AF7c97Af897A67A8f3CA71C2\",\n name: \"USDC.e\",\n version: \"2\",\n decimals: 6,\n }, // ADI Chain USDC.e (EIP-3009 supported)\n \"eip155:190415\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP mainnet USDC.e\n \"eip155:181228\": {\n address: \"0x401eCb1D350407f13ba348573E5630B83638E30D\",\n name: \"Bridged USDC\",\n version: \"2\",\n decimals: 6,\n }, // HPP Sepolia USDC.e\n \"eip155:50\": {\n address: \"0xfA2958CB79b0491CC627c1557F441eF849Ca8eb1\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Network mainnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:51\": {\n address: \"0xb5AB69F7bBada22B28e79C8FFAECe55eF1c771D4\",\n name: \"USDC\",\n version: \"2\",\n decimals: 6,\n }, // XDC Apothem testnet USDC (Bridged USDC Standard, EIP-3009 supported)\n \"eip155:38833\": {\n address: \"0xA5b8BF902b2844dA17d4506cc827F7F1681735E7\",\n name: \"USDC\",\n version: \"1\",\n decimals: 6,\n assetTransferMethod: \"permit2\",\n }, // Igra mainnet USDC (no EIP-3009, no EIP-2612)\n};\n\n/**\n * Look up the default stablecoin for a network.\n *\n * @param network - CAIP-2 network identifier (e.g. \"eip155:8453\")\n * @returns The default asset info\n * @throws If no default asset is configured for the network\n */\nexport function getDefaultAsset(network: Network): ExactDefaultAssetInfo {\n const info = DEFAULT_STABLECOINS[network];\n if (!info) {\n throw new Error(`No default asset configured for network ${network}`);\n }\n return info;\n}\n"],"mappings":";AA0CO,IAAM,sBAA6D;AAAA,EACxE,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACnB;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,EACZ;AAAA;AAAA,EACA,gBAAgB;AAAA,IACd,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,UAAU;AAAA,IACV,qBAAqB;AAAA,EACvB;AAAA;AACF;AASO,SAAS,gBAAgB,SAAyC;AACvE,QAAM,OAAO,oBAAoB,OAAO;AACxC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,2CAA2C,OAAO,EAAE;AAAA,EACtE;AACA,SAAO;AACT;","names":[]}
import {
ExactEvmSchemeV12 as ExactEvmSchemeV1,
NETWORKS
} from "./chunk-ZWPJEMS5.mjs";
import {
createPermit2Payload
} from "./chunk-63YBFPIQ.mjs";
import {
trySignEip2612PermitExtension,
trySignErc20ApprovalExtension
} from "./chunk-27MWX225.mjs";
import {
authorizationTypes
} from "./chunk-MACPBXCT.mjs";
import {
createNonce,
getEvmChainId
} from "./chunk-TW7Z65AO.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: "0",
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 = 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 signer.signTypedData({
domain,
types: authorizationTypes,
primaryType: "TransferWithAuthorization",
message
});
}
// src/exact/client/scheme.ts
var ExactEvmScheme = class {
/**
* Creates a new ExactEvmClient instance.
*
* @param signer - The EVM signer for client operations.
* Base flow only requires `address` + `signTypedData`.
* Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally
* requires optional capabilities like `readContract` and tx signing helpers.
* @param options - Optional RPC configuration used to backfill extension capabilities.
*/
constructor(signer, options) {
this.signer = signer;
this.options = options;
this.scheme = "exact";
}
/**
* Creates a payment payload for the Exact scheme.
* Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.
*
* For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the
* signer supports `readContract`, automatically signs an EIP-2612 permit
* when Permit2 allowance is insufficient.
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - The payment requirements
* @param context - Optional context with server-declared extensions
* @returns Promise resolving to a payment payload result (with optional extensions)
*/
async createPaymentPayload(x402Version, paymentRequirements, context) {
const assetTransferMethod = paymentRequirements.extra?.assetTransferMethod ?? "eip3009";
if (assetTransferMethod === "permit2") {
const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);
const eip2612Extensions = await trySignEip2612PermitExtension(
this.signer,
this.options,
paymentRequirements,
result,
context
);
if (eip2612Extensions) {
return {
...result,
extensions: eip2612Extensions
};
}
const erc20Extensions = await trySignErc20ApprovalExtension(
this.signer,
this.options,
paymentRequirements,
context
);
if (erc20Extensions) {
return {
...result,
extensions: erc20Extensions
};
}
return result;
}
return createEIP3009Payload(this.signer, x402Version, paymentRequirements);
}
};
// src/exact/client/register.ts
function registerExactEvmScheme(client, config) {
const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions);
if (config.networks && config.networks.length > 0) {
config.networks.forEach((network) => {
client.register(network, evmScheme);
});
} else {
client.register("eip155:*", evmScheme);
}
NETWORKS.forEach((network) => {
client.registerV1(network, new ExactEvmSchemeV1(config.signer));
});
if (config.policies) {
config.policies.forEach((policy) => {
client.registerPolicy(policy);
});
}
return client;
}
export {
ExactEvmScheme,
registerExactEvmScheme
};
//# sourceMappingURL=chunk-GSVPWDXO.mjs.map
{"version":3,"sources":["../../src/exact/client/eip3009.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, getEvmChainId } 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: \"0\",\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 = 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 signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n}\n","import {\n SchemeNetworkClient,\n PaymentRequirements,\n PaymentPayloadResult,\n PaymentPayloadContext,\n} from \"@x402/core/types\";\nimport { ClientEvmSigner } from \"../../signer\";\nimport { AssetTransferMethod } from \"../../types\";\nimport { createEIP3009Payload } from \"./eip3009\";\nimport { createPermit2Payload } from \"./permit2\";\nimport {\n trySignEip2612PermitExtension,\n trySignErc20ApprovalExtension,\n} from \"../../shared/extensions\";\nimport { ExactEvmSchemeOptions } from \"./rpc\";\n\n/**\n * EVM client implementation for the Exact payment scheme.\n * Supports both EIP-3009 (transferWithAuthorization) and Permit2 flows.\n *\n * Routes to the appropriate authorization method based on\n * `requirements.extra.assetTransferMethod`. Defaults to EIP-3009\n * for backward compatibility with older facilitators.\n *\n * When the server advertises `eip2612GasSponsoring` and the asset transfer\n * method is `permit2`, the scheme automatically signs an EIP-2612 permit\n * if the user lacks Permit2 approval. This requires `readContract` on the signer.\n */\nexport class ExactEvmScheme implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClient instance.\n *\n * @param signer - The EVM signer for client operations.\n * Base flow only requires `address` + `signTypedData`.\n * Extension enrichment (EIP-2612 / ERC-20 approval sponsoring) additionally\n * requires optional capabilities like `readContract` and tx signing helpers.\n * @param options - Optional RPC configuration used to backfill extension capabilities.\n */\n constructor(\n private readonly signer: ClientEvmSigner,\n private readonly options?: ExactEvmSchemeOptions,\n ) {}\n\n /**\n * Creates a payment payload for the Exact scheme.\n * Routes to EIP-3009 or Permit2 based on requirements.extra.assetTransferMethod.\n *\n * For Permit2 flows, if the server advertises `eip2612GasSponsoring` and the\n * signer supports `readContract`, automatically signs an EIP-2612 permit\n * when Permit2 allowance is insufficient.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @param context - Optional context with server-declared extensions\n * @returns Promise resolving to a payment payload result (with optional extensions)\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n context?: PaymentPayloadContext,\n ): Promise<PaymentPayloadResult> {\n const assetTransferMethod =\n (paymentRequirements.extra?.assetTransferMethod as AssetTransferMethod) ?? \"eip3009\";\n\n if (assetTransferMethod === \"permit2\") {\n const result = await createPermit2Payload(this.signer, x402Version, paymentRequirements);\n\n const eip2612Extensions = await trySignEip2612PermitExtension(\n this.signer,\n this.options,\n paymentRequirements,\n result,\n context,\n );\n\n if (eip2612Extensions) {\n return {\n ...result,\n extensions: eip2612Extensions,\n };\n }\n\n const erc20Extensions = await trySignErc20ApprovalExtension(\n this.signer,\n this.options,\n paymentRequirements,\n context,\n );\n if (erc20Extensions) {\n return {\n ...result,\n extensions: erc20Extensions,\n };\n }\n\n return result;\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 { ExactEvmSchemeOptions } from \"./rpc\";\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 Exact EVM client scheme options.\n * Supports either a single config ({ rpcUrl }) or per-chain configs\n * keyed by EVM chain ID ({ 8453: { rpcUrl: \"...\" } }).\n */\n schemeOptions?: ExactEvmSchemeOptions;\n\n /**\n * Optional specific networks to register.\n * If not provided, registers wildcard support (eip155:*).\n */\n networks?: Network[];\n}\n\n/**\n * Registers EVM exact payment schemes to an x402Client instance.\n *\n * This function registers:\n * - V2: eip155:* wildcard scheme with ExactEvmScheme (or specific networks if provided)\n * - V1: All supported EVM networks with ExactEvmSchemeV1\n *\n * @param client - The x402Client instance to register schemes to\n * @param config - Configuration for EVM client registration\n * @returns The client instance for chaining\n *\n * @example\n * ```typescript\n * import { registerExactEvmScheme } from \"@x402/evm/exact/client/register\";\n * import { x402Client } from \"@x402/core/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const account = privateKeyToAccount(\"0x...\");\n * const client = new x402Client();\n * registerExactEvmScheme(client, { signer: account });\n * ```\n */\nexport function registerExactEvmScheme(client: x402Client, config: EvmClientConfig): x402Client {\n const evmScheme = new ExactEvmScheme(config.signer, config.schemeOptions);\n\n // Register V2 scheme\n // EIP-2612 gas sponsoring is handled internally by the scheme when the\n // server advertises support - no separate extension registration needed.\n if (config.networks && config.networks.length > 0) {\n // Register specific networks\n config.networks.forEach(network => {\n client.register(network, evmScheme);\n });\n } else {\n // Register wildcard for all EVM chains\n client.register(\"eip155:*\", evmScheme);\n }\n\n // Register all V1 networks\n NETWORKS.forEach(network => {\n client.registerV1(network as Network, new ExactEvmSchemeV1(config.signer));\n });\n\n // Apply policies if provided\n if (config.policies) {\n config.policies.forEach(policy => {\n client.registerPolicy(policy);\n });\n }\n\n return client;\n}\n"],"mappings":"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","names":[]}
import {
ErrEip2612AssetMismatch,
ErrEip2612DeadlineExpired,
ErrEip2612FromMismatch,
ErrEip2612SpenderNotPermit2,
ErrErc20ApprovalAssetMismatch,
ErrErc20ApprovalFromMismatch,
ErrErc20ApprovalInvalidFormat,
ErrErc20ApprovalSpenderNotPermit2,
ErrErc20ApprovalTxFailed,
ErrErc20ApprovalTxInvalidCalldata,
ErrErc20ApprovalTxInvalidSignature,
ErrErc20ApprovalTxParseFailed,
ErrErc20ApprovalTxSignerMismatch,
ErrErc20ApprovalTxWrongSelector,
ErrErc20ApprovalTxWrongSpender,
ErrErc20ApprovalTxWrongTarget,
ErrInvalidEip2612ExtensionFormat,
ErrInvalidTransactionState,
ErrPermit2612AmountMismatch,
ErrPermit2AllowanceRequired,
ErrPermit2InsufficientBalance,
ErrPermit2InvalidAmount,
ErrPermit2InvalidDestination,
ErrPermit2InvalidNonce,
ErrPermit2InvalidOwner,
ErrPermit2InvalidSignature,
ErrPermit2PaymentTooEarly,
ErrPermit2ProxyNotDeployed,
ErrPermit2SimulationFailed,
ErrTransactionFailed
} from "./chunk-23HX7MHV.mjs";
import {
validateEip2612GasSponsoringInfo,
validateErc20ApprovalGasSponsoringInfo
} from "./chunk-27MWX225.mjs";
import {
PERMIT2_ADDRESS,
eip3009ABI,
erc20AllowanceAbi,
erc20ApproveAbi,
permit2WitnessTypes
} from "./chunk-MACPBXCT.mjs";
import {
multicall
} from "./chunk-VS3RYAYE.mjs";
import {
createPermit2Nonce,
getEvmChainId
} from "./chunk-TW7Z65AO.mjs";
// src/shared/permit2.ts
import { getAddress as getAddress2, encodeFunctionData, parseErc6492Signature } from "viem";
// src/shared/erc20approval.ts
import {
getAddress,
parseTransaction,
decodeFunctionData,
recoverTransactionAddress
} from "viem";
var APPROVE_SELECTOR = "0x095ea7b3";
async function validateErc20ApprovalForPayment(info, payer, tokenAddress) {
if (!validateErc20ApprovalGasSponsoringInfo(info)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalInvalidFormat,
invalidMessage: "ERC-20 approval extension info failed schema validation"
};
}
if (getAddress(info.from) !== getAddress(payer)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalFromMismatch,
invalidMessage: `Expected from=${payer}, got ${info.from}`
};
}
if (getAddress(info.asset) !== tokenAddress) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalAssetMismatch,
invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`
};
}
if (getAddress(info.spender) !== getAddress(PERMIT2_ADDRESS)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalSpenderNotPermit2,
invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`
};
}
try {
const serializedTx = info.signedTransaction;
const tx = parseTransaction(serializedTx);
if (!tx.to || getAddress(tx.to) !== tokenAddress) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxWrongTarget,
invalidMessage: `Transaction targets ${tx.to ?? "null"}, expected ${tokenAddress}`
};
}
const data = tx.data ?? "0x";
if (!data.startsWith(APPROVE_SELECTOR)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxWrongSelector,
invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`
};
}
try {
const decoded = decodeFunctionData({
abi: erc20ApproveAbi,
data
});
const calldataSpender = getAddress(decoded.args[0]);
if (calldataSpender !== getAddress(PERMIT2_ADDRESS)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxWrongSpender,
invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`
};
}
} catch {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxInvalidCalldata,
invalidMessage: "Failed to decode approve() calldata from the signed transaction"
};
}
try {
const recoveredAddress = await recoverTransactionAddress({
serializedTransaction: serializedTx
});
if (getAddress(recoveredAddress) !== getAddress(payer)) {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxSignerMismatch,
invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`
};
}
} catch {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxInvalidSignature,
invalidMessage: "Failed to recover signer from the signed transaction"
};
}
} catch {
return {
isValid: false,
invalidReason: ErrErc20ApprovalTxParseFailed,
invalidMessage: "Failed to parse the signed transaction"
};
}
return { isValid: true };
}
// src/upto/facilitator/errors.ts
var ErrUptoInvalidScheme = "invalid_upto_evm_scheme";
var ErrUptoNetworkMismatch = "invalid_upto_evm_network_mismatch";
var ErrUptoSettlementExceedsAmount = "invalid_upto_evm_payload_settlement_exceeds_amount";
var ErrUptoAmountExceedsPermitted = "upto_amount_exceeds_permitted";
var ErrUptoUnauthorizedFacilitator = "upto_unauthorized_facilitator";
var ErrUptoFacilitatorMismatch = "upto_facilitator_mismatch";
// src/shared/permit2.ts
async function waitAndReturnSettleResponse(signer, tx, payload, payer) {
const receipt = await signer.waitForTransactionReceipt({ hash: tx });
if (receipt.status !== "success") {
return {
success: false,
errorReason: ErrInvalidTransactionState,
transaction: tx,
network: payload.accepted.network,
payer
};
}
return {
success: true,
transaction: tx,
network: payload.accepted.network,
payer
};
}
function mapSettleError(error, payload, payer) {
let errorReason = ErrTransactionFailed;
if (error instanceof Error) {
const message = error.message;
if (message.includes("Permit2612AmountMismatch")) {
errorReason = ErrPermit2612AmountMismatch;
} else if (message.includes("InvalidAmount")) {
errorReason = ErrPermit2InvalidAmount;
} else if (message.includes("InvalidDestination")) {
errorReason = ErrPermit2InvalidDestination;
} else if (message.includes("InvalidOwner")) {
errorReason = ErrPermit2InvalidOwner;
} else if (message.includes("PaymentTooEarly")) {
errorReason = ErrPermit2PaymentTooEarly;
} else if (message.includes("InvalidSignature") || message.includes("SignatureExpired")) {
errorReason = ErrPermit2InvalidSignature;
} else if (message.includes("InvalidNonce")) {
errorReason = ErrPermit2InvalidNonce;
} else if (message.includes("erc20_approval_tx_failed")) {
errorReason = ErrErc20ApprovalTxFailed;
} else if (message.includes("AmountExceedsPermitted")) {
errorReason = ErrUptoAmountExceedsPermitted;
} else if (message.includes("UnauthorizedFacilitator")) {
errorReason = ErrUptoUnauthorizedFacilitator;
} else {
errorReason = `${ErrTransactionFailed}: ${message.slice(0, 500)}`;
}
}
return {
success: false,
errorReason,
transaction: "",
network: payload.accepted.network,
payer
};
}
function validateEip2612PermitForPayment(info, payer, tokenAddress) {
if (!validateEip2612GasSponsoringInfo(info)) {
return { isValid: false, invalidReason: ErrInvalidEip2612ExtensionFormat };
}
if (getAddress2(info.from) !== getAddress2(payer)) {
return { isValid: false, invalidReason: ErrEip2612FromMismatch };
}
if (getAddress2(info.asset) !== tokenAddress) {
return { isValid: false, invalidReason: ErrEip2612AssetMismatch };
}
if (getAddress2(info.spender) !== getAddress2(PERMIT2_ADDRESS)) {
return { isValid: false, invalidReason: ErrEip2612SpenderNotPermit2 };
}
const now = Math.floor(Date.now() / 1e3);
if (BigInt(info.deadline) < BigInt(now + 6)) {
return { isValid: false, invalidReason: ErrEip2612DeadlineExpired };
}
return { isValid: true };
}
async function simulatePermit2Settle(config, signer, settleArgs) {
try {
await signer.readContract({
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "settle",
args: settleArgs
});
return true;
} catch {
return false;
}
}
async function simulatePermit2SettleWithPermit(config, signer, settleArgs, eip2612Info) {
try {
const { v, r, s } = splitEip2612Signature(eip2612Info.signature);
await signer.readContract({
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "settleWithPermit",
args: [
{
value: BigInt(eip2612Info.amount),
deadline: BigInt(eip2612Info.deadline),
r,
s,
v
},
...settleArgs
]
});
return true;
} catch {
return false;
}
}
async function simulatePermit2SettleWithErc20Approval(config, extensionSigner, settleArgs, erc20Info) {
if (!extensionSigner.simulateTransactions) {
return false;
}
try {
const settleData = encodeFunctionData({
abi: config.proxyABI,
functionName: "settle",
args: settleArgs
});
return await extensionSigner.simulateTransactions([
erc20Info.signedTransaction,
{ to: config.proxyAddress, data: settleData, gas: BigInt(3e5) }
]);
} catch {
return false;
}
}
async function diagnosePermit2SimulationFailure(config, signer, tokenAddress, permit2Payload, amountRequired) {
const payer = permit2Payload.permit2Authorization.from;
const diagnosticCalls = [
{
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "PERMIT2"
},
{
address: tokenAddress,
abi: eip3009ABI,
functionName: "balanceOf",
args: [payer]
},
{
address: tokenAddress,
abi: erc20AllowanceAbi,
functionName: "allowance",
args: [payer, PERMIT2_ADDRESS]
}
];
try {
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
const [proxyResult, balanceResult, allowanceResult] = results;
if (proxyResult.status === "failure") {
return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };
}
if (balanceResult.status === "success") {
const balance = balanceResult.result;
if (balance < BigInt(amountRequired)) {
return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };
}
}
if (allowanceResult.status === "success") {
const allowance = allowanceResult.result;
if (allowance < BigInt(amountRequired)) {
return { isValid: false, invalidReason: ErrPermit2AllowanceRequired, payer };
}
}
} catch {
}
return { isValid: false, invalidReason: ErrPermit2SimulationFailed, payer };
}
async function checkPermit2Prerequisites(config, signer, tokenAddress, payer, amountRequired) {
const diagnosticCalls = [
{
address: config.proxyAddress,
abi: config.proxyABI,
functionName: "PERMIT2"
},
{
address: tokenAddress,
abi: eip3009ABI,
functionName: "balanceOf",
args: [payer]
}
];
try {
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
const [proxyResult, balanceResult] = results;
if (proxyResult.status === "failure") {
return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };
}
if (balanceResult.status === "success") {
const balance = balanceResult.result;
if (balance < BigInt(amountRequired)) {
return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };
}
}
} catch {
}
return { isValid: true, invalidReason: void 0, payer };
}
function buildExactPermit2SettleArgs(permit2Payload) {
const { signature } = parseErc6492Signature(permit2Payload.signature);
return [
{
permitted: {
token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
},
nonce: BigInt(permit2Payload.permit2Authorization.nonce),
deadline: BigInt(permit2Payload.permit2Authorization.deadline)
},
getAddress2(permit2Payload.permit2Authorization.from),
{
to: getAddress2(permit2Payload.permit2Authorization.witness.to),
validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
},
signature
];
}
function buildUptoPermit2SettleArgs(permit2Payload, settlementAmount, facilitatorAddress) {
const { signature } = parseErc6492Signature(permit2Payload.signature);
return [
{
permitted: {
token: getAddress2(permit2Payload.permit2Authorization.permitted.token),
amount: BigInt(permit2Payload.permit2Authorization.permitted.amount)
},
nonce: BigInt(permit2Payload.permit2Authorization.nonce),
deadline: BigInt(permit2Payload.permit2Authorization.deadline)
},
settlementAmount,
getAddress2(permit2Payload.permit2Authorization.from),
{
to: getAddress2(permit2Payload.permit2Authorization.witness.to),
facilitator: getAddress2(facilitatorAddress),
validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter)
},
signature
];
}
function splitEip2612Signature(signature) {
const sig = signature.startsWith("0x") ? signature.slice(2) : signature;
if (sig.length !== 130) {
throw new Error(
`invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`
);
}
const r = `0x${sig.slice(0, 64)}`;
const s = `0x${sig.slice(64, 128)}`;
const v = parseInt(sig.slice(128, 130), 16);
return { v, r, s };
}
async function createPermit2PayloadForProxy(proxyAddress, signer, x402Version, paymentRequirements) {
const now = Math.floor(Date.now() / 1e3);
const nonce = createPermit2Nonce();
const validAfter = "0";
const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();
const permit2Authorization = {
from: signer.address,
permitted: {
token: getAddress2(paymentRequirements.asset),
amount: paymentRequirements.amount
},
spender: proxyAddress,
nonce,
deadline,
witness: {
to: getAddress2(paymentRequirements.payTo),
validAfter
}
};
const signature = await signPermit2Authorization(
signer,
permit2Authorization,
paymentRequirements
);
return {
x402Version,
payload: { signature, permit2Authorization }
};
}
async function signPermit2Authorization(signer, permit2Authorization, requirements) {
const chainId = getEvmChainId(requirements.network);
return await signer.signTypedData({
domain: { name: "Permit2", chainId, verifyingContract: PERMIT2_ADDRESS },
types: permit2WitnessTypes,
primaryType: "PermitWitnessTransferFrom",
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)
}
}
});
}
export {
validateErc20ApprovalForPayment,
ErrUptoInvalidScheme,
ErrUptoNetworkMismatch,
ErrUptoSettlementExceedsAmount,
ErrUptoFacilitatorMismatch,
waitAndReturnSettleResponse,
mapSettleError,
validateEip2612PermitForPayment,
simulatePermit2Settle,
simulatePermit2SettleWithPermit,
simulatePermit2SettleWithErc20Approval,
diagnosePermit2SimulationFailure,
checkPermit2Prerequisites,
buildExactPermit2SettleArgs,
buildUptoPermit2SettleArgs,
splitEip2612Signature,
createPermit2PayloadForProxy
};
//# sourceMappingURL=chunk-HAEDTF25.mjs.map
{"version":3,"sources":["../../src/shared/permit2.ts","../../src/shared/erc20approval.ts","../../src/upto/facilitator/errors.ts"],"sourcesContent":["import {\n PaymentPayload,\n PaymentPayloadResult,\n PaymentRequirements,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport {\n extractEip2612GasSponsoringInfo,\n validateEip2612GasSponsoringInfo,\n extractErc20ApprovalGasSponsoringInfo,\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n type Eip2612GasSponsoringInfo,\n type Erc20ApprovalGasSponsoringFacilitatorExtension,\n type Erc20ApprovalGasSponsoringSigner,\n} from \"../exact/extensions\";\nimport { getAddress, encodeFunctionData, parseErc6492Signature } from \"viem\";\nimport { PERMIT2_ADDRESS, eip3009ABI, erc20AllowanceAbi, permit2WitnessTypes } from \"../constants\";\nimport { multicall, ContractCall } from \"../multicall\";\nimport { createPermit2Nonce, getEvmChainId } from \"../utils\";\nimport {\n ErrPermit2612AmountMismatch,\n ErrPermit2InvalidAmount,\n ErrPermit2InvalidDestination,\n ErrPermit2InvalidNonce,\n ErrPermit2InvalidOwner,\n ErrPermit2InvalidSignature,\n ErrPermit2PaymentTooEarly,\n ErrPermit2AllowanceRequired,\n ErrPermit2SimulationFailed,\n ErrPermit2InsufficientBalance,\n ErrPermit2ProxyNotDeployed,\n ErrInvalidTransactionState,\n ErrTransactionFailed,\n ErrInvalidEip2612ExtensionFormat,\n ErrEip2612FromMismatch,\n ErrEip2612AssetMismatch,\n ErrEip2612SpenderNotPermit2,\n ErrEip2612DeadlineExpired,\n ErrErc20ApprovalTxFailed,\n} from \"../exact/facilitator/errors\";\nimport { ClientEvmSigner, FacilitatorEvmSigner } from \"../signer\";\nimport { ExactPermit2Payload, Permit2Authorization, UptoPermit2Payload } from \"../types\";\nimport { validateErc20ApprovalForPayment } from \"./erc20approval\";\nimport {\n ErrUptoAmountExceedsPermitted,\n ErrUptoUnauthorizedFacilitator,\n} from \"../upto/facilitator/errors\";\n\n/**\n * Base type for Permit2 payloads shared between exact and upto schemes.\n * Both {@link ExactPermit2Payload} and {@link UptoPermit2Payload} satisfy this type.\n */\nexport type Permit2PayloadBase = ExactPermit2Payload | UptoPermit2Payload;\n\n/**\n * Configuration for the Permit2 proxy contract used during settlement.\n * The exact and upto schemes use different proxy addresses and ABIs.\n */\nexport type Permit2ProxyConfig = {\n /** The deployed proxy contract address. */\n proxyAddress: `0x${string}`;\n /** The proxy contract ABI (must include settle and settleWithPermit functions). */\n proxyABI: readonly Record<string, unknown>[];\n};\n\n/**\n * Checks Permit2 allowance and validates gas sponsoring extensions if allowance is insufficient.\n *\n * When the on-chain ERC-20 allowance to the Permit2 contract is below the required amount,\n * this function falls back to validating EIP-2612 or ERC-20 approval gas sponsoring extensions\n * attached to the payment payload.\n *\n * @param signer - The facilitator signer for on-chain reads\n * @param payload - The payment payload\n * @param requirements - The payment requirements\n * @param payer - The payer address\n * @param tokenAddress - The token contract address\n * @param context - Optional facilitator context for extension lookup\n * @returns A VerifyResponse if verification should stop (failure), or null to continue\n */\nexport async function verifyPermit2Allowance(\n signer: FacilitatorEvmSigner,\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n context?: FacilitatorContext,\n): Promise<VerifyResponse | null> {\n try {\n const allowance = (await signer.readContract({\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n })) as bigint;\n\n if (allowance >= BigInt(requirements.amount)) {\n return null; // Sufficient allowance, continue verification\n }\n\n // Allowance insufficient — try EIP-2612 gas sponsoring first\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null; // EIP-2612 is valid, allowance will be set atomically during settlement\n }\n\n // Try ERC-20 approval gas sponsoring as fallback\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null; // ERC-20 approval is valid, will be broadcast before settlement\n }\n }\n\n return { isValid: false, invalidReason: \"permit2_allowance_required\", payer };\n } catch {\n // Allowance check failed — validate extensions if present; fail closed if none valid\n const eip2612Info = extractEip2612GasSponsoringInfo(payload);\n if (eip2612Info) {\n const result = validateEip2612PermitForPayment(eip2612Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null;\n }\n\n const erc20GasSponsorshipExtension =\n context?.getExtension<Erc20ApprovalGasSponsoringFacilitatorExtension>(\n ERC20_APPROVAL_GAS_SPONSORING_KEY,\n );\n if (erc20GasSponsorshipExtension) {\n const erc20Info = extractErc20ApprovalGasSponsoringInfo(payload);\n if (erc20Info) {\n const result = await validateErc20ApprovalForPayment(erc20Info, payer, tokenAddress);\n if (!result.isValid) {\n return { isValid: false, invalidReason: result.invalidReason!, payer };\n }\n return null;\n }\n }\n\n return { isValid: false, invalidReason: \"permit2_allowance_required\", payer };\n }\n}\n\n/**\n * Waits for a transaction receipt and returns the appropriate SettleResponse.\n *\n * @param signer - Signer with waitForTransactionReceipt capability\n * @param tx - The transaction hash to wait for\n * @param payload - The payment payload (for network info)\n * @param payer - The payer address\n * @returns Promise resolving to a settlement response indicating success or failure\n */\nexport async function waitAndReturnSettleResponse(\n signer: Pick<FacilitatorEvmSigner, \"waitForTransactionReceipt\">,\n tx: `0x${string}`,\n payload: PaymentPayload,\n payer: `0x${string}`,\n): Promise<SettleResponse> {\n const receipt = await signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: ErrInvalidTransactionState,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payload.accepted.network,\n payer,\n };\n}\n\n/**\n * Maps contract revert errors to structured SettleResponse error reasons.\n *\n * Inspects the error message for known contract revert strings and maps them\n * to the corresponding error reason constants. Falls back to a generic\n * \"transaction_failed\" reason with truncated message for unrecognized errors.\n *\n * @param error - The caught error (typically from a contract write)\n * @param payload - The payment payload (for network info)\n * @param payer - The payer address\n * @returns A failed SettleResponse with the mapped error reason\n */\nexport function mapSettleError(\n error: unknown,\n payload: PaymentPayload,\n payer: `0x${string}`,\n): SettleResponse {\n let errorReason: string = ErrTransactionFailed;\n if (error instanceof Error) {\n const message = error.message;\n if (message.includes(\"Permit2612AmountMismatch\")) {\n errorReason = ErrPermit2612AmountMismatch;\n } else if (message.includes(\"InvalidAmount\")) {\n errorReason = ErrPermit2InvalidAmount;\n } else if (message.includes(\"InvalidDestination\")) {\n errorReason = ErrPermit2InvalidDestination;\n } else if (message.includes(\"InvalidOwner\")) {\n errorReason = ErrPermit2InvalidOwner;\n } else if (message.includes(\"PaymentTooEarly\")) {\n errorReason = ErrPermit2PaymentTooEarly;\n } else if (message.includes(\"InvalidSignature\") || message.includes(\"SignatureExpired\")) {\n errorReason = ErrPermit2InvalidSignature;\n } else if (message.includes(\"InvalidNonce\")) {\n errorReason = ErrPermit2InvalidNonce;\n } else if (message.includes(\"erc20_approval_tx_failed\")) {\n errorReason = ErrErc20ApprovalTxFailed;\n } else if (message.includes(\"AmountExceedsPermitted\")) {\n errorReason = ErrUptoAmountExceedsPermitted;\n } else if (message.includes(\"UnauthorizedFacilitator\")) {\n errorReason = ErrUptoUnauthorizedFacilitator;\n } else {\n errorReason = `${ErrTransactionFailed}: ${message.slice(0, 500)}`;\n }\n }\n return {\n success: false,\n errorReason,\n transaction: \"\",\n network: payload.accepted.network,\n payer,\n };\n}\n\n/**\n * Validates EIP-2612 permit extension data for a Permit2 payment.\n *\n * Checks that the permit extension has a valid format and that the from address,\n * asset address, spender address, and deadline all match expectations.\n *\n * @param info - The EIP-2612 gas sponsoring info extracted from the payment payload\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result with isValid flag and optional invalidReason string\n */\nexport function validateEip2612PermitForPayment(\n info: Eip2612GasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): { isValid: boolean; invalidReason?: string } {\n if (!validateEip2612GasSponsoringInfo(info)) {\n return { isValid: false, invalidReason: ErrInvalidEip2612ExtensionFormat };\n }\n\n if (getAddress(info.from as `0x${string}`) !== getAddress(payer)) {\n return { isValid: false, invalidReason: ErrEip2612FromMismatch };\n }\n\n if (getAddress(info.asset as `0x${string}`) !== tokenAddress) {\n return { isValid: false, invalidReason: ErrEip2612AssetMismatch };\n }\n\n if (getAddress(info.spender as `0x${string}`) !== getAddress(PERMIT2_ADDRESS)) {\n return { isValid: false, invalidReason: ErrEip2612SpenderNotPermit2 };\n }\n\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(info.deadline) < BigInt(now + 6)) {\n return { isValid: false, invalidReason: ErrEip2612DeadlineExpired };\n }\n\n return { isValid: true };\n}\n\n// ---------------------------------------------------------------------------\n// Simulation helpers (shared across exact and upto)\n// ---------------------------------------------------------------------------\n\n/**\n * Simulates settle() via eth_call (readContract).\n * Returns true if simulation succeeded, false if it failed.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulatePermit2Settle(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n settleArgs: readonly unknown[],\n): Promise<boolean> {\n try {\n await signer.readContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settle\",\n args: settleArgs,\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Simulates settleWithPermit() via eth_call (readContract).\n * The contract atomically calls token.permit() then PERMIT2.permitTransferFrom(),\n * so simulation covers allowance + balance + nonces.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @param eip2612Info - EIP-2612 gas sponsoring info from the payload extension\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulatePermit2SettleWithPermit(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n settleArgs: readonly unknown[],\n eip2612Info: Eip2612GasSponsoringInfo,\n): Promise<boolean> {\n try {\n const { v, r, s } = splitEip2612Signature(eip2612Info.signature);\n\n await signer.readContract({\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"settleWithPermit\",\n args: [\n {\n value: BigInt(eip2612Info.amount),\n deadline: BigInt(eip2612Info.deadline),\n r,\n s,\n v,\n },\n ...settleArgs,\n ],\n });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Delegates the full approve+settle simulation flow to the extension signer via simulateTransactions.\n * The signer owns execution strategy.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param extensionSigner - The extension signer with simulateTransactions capability\n * @param settleArgs - Pre-built settle function arguments (scheme-specific)\n * @param erc20Info - Object containing the signed approval transaction\n * @param erc20Info.signedTransaction - The RLP-encoded signed ERC-20 approve transaction hex string\n * @returns true if the bundle simulation succeeded, false otherwise\n */\nexport async function simulatePermit2SettleWithErc20Approval(\n config: Permit2ProxyConfig,\n extensionSigner: Erc20ApprovalGasSponsoringSigner,\n settleArgs: readonly unknown[],\n erc20Info: { signedTransaction: string },\n): Promise<boolean> {\n if (!extensionSigner.simulateTransactions) {\n return false;\n }\n\n try {\n const settleData = encodeFunctionData({\n abi: config.proxyABI,\n functionName: \"settle\",\n args: settleArgs,\n });\n\n return await extensionSigner.simulateTransactions([\n erc20Info.signedTransaction as `0x${string}`,\n { to: config.proxyAddress, data: settleData, gas: BigInt(300_000) },\n ]);\n } catch {\n return false;\n }\n}\n\n/**\n * Diagnoses a Permit2 simulation failure by performing a multicall to check the proxy deployment, balance and allowance.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param tokenAddress - ERC-20 token contract address\n * @param permit2Payload - The Permit2 authorization payload\n * @param amountRequired - Required payment amount (as string)\n * @returns VerifyResponse with the most specific failure reason\n */\nexport async function diagnosePermit2SimulationFailure(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n tokenAddress: `0x${string}`,\n permit2Payload: Permit2PayloadBase,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const payer = permit2Payload.permit2Authorization.from;\n\n const diagnosticCalls: ContractCall[] = [\n {\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"PERMIT2\",\n },\n {\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n },\n {\n address: tokenAddress,\n abi: erc20AllowanceAbi,\n functionName: \"allowance\",\n args: [payer, PERMIT2_ADDRESS],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [proxyResult, balanceResult, allowanceResult] = results;\n\n if (proxyResult.status === \"failure\") {\n return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };\n }\n }\n\n if (allowanceResult.status === \"success\") {\n const allowance = allowanceResult.result as bigint;\n if (allowance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2AllowanceRequired, payer };\n }\n }\n } catch {\n // Diagnostic multicall itself failed — fall through to generic error\n }\n\n return { isValid: false, invalidReason: ErrPermit2SimulationFailed, payer };\n}\n\n/**\n * Targeted multicall for the ERC-20 approval path where simulation cannot be used\n * (the approval hasn't been broadcast yet, so settle() would fail for expected reasons).\n * Checks proxy deployment, payer token balance and payer ETH balance for gas.\n *\n * @param config - The proxy contract configuration (address and ABI)\n * @param signer - EVM signer for contract reads\n * @param tokenAddress - ERC-20 token contract address\n * @param payer - The payer address\n * @param amountRequired - Required payment amount (as string)\n * @returns VerifyResponse — valid if checks pass, otherwise the most specific failure\n */\nexport async function checkPermit2Prerequisites(\n config: Permit2ProxyConfig,\n signer: FacilitatorEvmSigner,\n tokenAddress: `0x${string}`,\n payer: `0x${string}`,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const diagnosticCalls: ContractCall[] = [\n {\n address: config.proxyAddress,\n abi: config.proxyABI,\n functionName: \"PERMIT2\",\n },\n {\n address: tokenAddress,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payer],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [proxyResult, balanceResult] = results;\n\n if (proxyResult.status === \"failure\") {\n return { isValid: false, invalidReason: ErrPermit2ProxyNotDeployed, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return { isValid: false, invalidReason: ErrPermit2InsufficientBalance, payer };\n }\n }\n } catch {\n // Multicall failed — fall through to valid (fail open for prerequisites-only check)\n }\n\n return { isValid: true, invalidReason: undefined, payer };\n}\n\n/**\n * Builds args for exact settle(permit, owner, witness, signature).\n *\n * @param permit2Payload - The Permit2 payload containing authorization and signature data\n * @returns Tuple of contract call arguments for the exact settle function\n */\nexport function buildExactPermit2SettleArgs(permit2Payload: Permit2PayloadBase) {\n const { signature } = parseErc6492Signature(permit2Payload.signature);\n\n return [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n signature,\n ] as const;\n}\n\n/**\n * Builds args for upto settle(permit, amount, owner, witness, signature).\n * The upto contract's settle() takes an additional `amount` parameter and the witness\n * includes a `facilitator` field.\n *\n * @param permit2Payload - The upto Permit2 payload containing authorization and signature data\n * @param settlementAmount - The amount to settle on-chain\n * @param facilitatorAddress - The facilitator address authorized in the witness\n * @returns Tuple of contract call arguments for the upto settle function\n */\nexport function buildUptoPermit2SettleArgs(\n permit2Payload: UptoPermit2Payload,\n settlementAmount: bigint,\n facilitatorAddress: `0x${string}`,\n) {\n const { signature } = parseErc6492Signature(permit2Payload.signature);\n\n return [\n {\n permitted: {\n token: getAddress(permit2Payload.permit2Authorization.permitted.token),\n amount: BigInt(permit2Payload.permit2Authorization.permitted.amount),\n },\n nonce: BigInt(permit2Payload.permit2Authorization.nonce),\n deadline: BigInt(permit2Payload.permit2Authorization.deadline),\n },\n settlementAmount,\n getAddress(permit2Payload.permit2Authorization.from),\n {\n to: getAddress(permit2Payload.permit2Authorization.witness.to),\n facilitator: getAddress(facilitatorAddress),\n validAfter: BigInt(permit2Payload.permit2Authorization.witness.validAfter),\n },\n signature,\n ] as const;\n}\n\n/**\n * Splits a 65-byte EIP-2612 signature into v, r, s components.\n *\n * @param signature - The hex-encoded 65-byte signature (with or without 0x prefix)\n * @returns Object with v (uint8), r (bytes32 hex), s (bytes32 hex)\n * @throws Error if the signature is not exactly 65 bytes (130 hex chars)\n */\nexport function splitEip2612Signature(signature: string): {\n v: number;\n r: `0x${string}`;\n s: `0x${string}`;\n} {\n const sig = signature.startsWith(\"0x\") ? signature.slice(2) : signature;\n\n if (sig.length !== 130) {\n throw new Error(\n `invalid EIP-2612 signature length: expected 65 bytes (130 hex chars), got ${sig.length / 2} bytes`,\n );\n }\n\n const r = `0x${sig.slice(0, 64)}` as `0x${string}`;\n const s = `0x${sig.slice(64, 128)}` as `0x${string}`;\n const v = parseInt(sig.slice(128, 130), 16);\n\n return { v, r, s };\n}\n\n// ---------------------------------------------------------------------------\n// Client-side helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a Permit2 payload for any scheme (exact or upto).\n * The only scheme-specific input is the proxy address used as the spender.\n *\n * @param proxyAddress - The x402 proxy contract address to set as spender\n * @param signer - The EVM client signer\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload result\n */\nexport async function createPermit2PayloadForProxy(\n proxyAddress: `0x${string}`,\n signer: ClientEvmSigner,\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n): Promise<PaymentPayloadResult> {\n const now = Math.floor(Date.now() / 1000);\n const nonce = createPermit2Nonce();\n\n // Lower time bound - allow some clock skew\n const validAfter = \"0\";\n // Upper time bound is enforced by Permit2's deadline field\n const deadline = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n const permit2Authorization: Permit2Authorization & { from: `0x${string}` } = {\n from: signer.address,\n permitted: {\n token: getAddress(paymentRequirements.asset),\n amount: paymentRequirements.amount,\n },\n spender: proxyAddress,\n nonce,\n deadline,\n witness: {\n to: getAddress(paymentRequirements.payTo),\n validAfter,\n },\n };\n\n const signature = await signPermit2Authorization(\n signer,\n permit2Authorization,\n paymentRequirements,\n );\n\n return {\n x402Version,\n payload: { signature, permit2Authorization },\n };\n}\n\n/**\n * Signs a Permit2 authorization using EIP-712 with witness data.\n * The signature authorizes the proxy contract to transfer tokens on behalf of the signer.\n *\n * @param signer - The EVM client signer\n * @param permit2Authorization - The Permit2 authorization parameters\n * @param requirements - The payment requirements\n * @returns Promise resolving to the hex-encoded signature\n */\nasync function signPermit2Authorization(\n signer: ClientEvmSigner,\n permit2Authorization: Permit2Authorization & { from: `0x${string}` },\n requirements: PaymentRequirements,\n): Promise<`0x${string}`> {\n const chainId = getEvmChainId(requirements.network);\n\n return await signer.signTypedData({\n domain: { name: \"Permit2\", chainId, verifyingContract: PERMIT2_ADDRESS },\n types: permit2WitnessTypes,\n primaryType: \"PermitWitnessTransferFrom\",\n message: {\n permitted: {\n token: getAddress(permit2Authorization.permitted.token),\n amount: BigInt(permit2Authorization.permitted.amount),\n },\n spender: getAddress(permit2Authorization.spender),\n nonce: BigInt(permit2Authorization.nonce),\n deadline: BigInt(permit2Authorization.deadline),\n witness: {\n to: getAddress(permit2Authorization.witness.to),\n validAfter: BigInt(permit2Authorization.witness.validAfter),\n },\n },\n });\n}\n","import {\n getAddress,\n parseTransaction,\n decodeFunctionData,\n recoverTransactionAddress,\n type TransactionSerialized,\n} from \"viem\";\nimport type { VerifyResponse } from \"@x402/core/types\";\nimport {\n validateErc20ApprovalGasSponsoringInfo,\n type Erc20ApprovalGasSponsoringInfo,\n} from \"../exact/extensions\";\nimport { PERMIT2_ADDRESS, erc20ApproveAbi } from \"../constants\";\nimport {\n ErrErc20ApprovalInvalidFormat,\n ErrErc20ApprovalFromMismatch,\n ErrErc20ApprovalAssetMismatch,\n ErrErc20ApprovalSpenderNotPermit2,\n ErrErc20ApprovalTxWrongTarget,\n ErrErc20ApprovalTxWrongSelector,\n ErrErc20ApprovalTxWrongSpender,\n ErrErc20ApprovalTxInvalidCalldata,\n ErrErc20ApprovalTxSignerMismatch,\n ErrErc20ApprovalTxInvalidSignature,\n ErrErc20ApprovalTxParseFailed,\n} from \"../exact/facilitator/errors\";\n\n/** The approve(address,uint256) function selector */\nconst APPROVE_SELECTOR = \"0x095ea7b3\";\n\n/**\n * Validates ERC-20 approval extension data for a Permit2 payment.\n *\n * Performs comprehensive validation:\n * - Format validation via validateErc20ApprovalGasSponsoringInfo (JSON Schema)\n * - `from` matches payer\n * - `asset` matches token\n * - `spender` is PERMIT2_ADDRESS\n * - Transaction `to` matches token address\n * - Transaction calldata is a valid approve(PERMIT2_ADDRESS, ...) call\n * - Recovered transaction signer matches `from`\n *\n * @param info - The ERC-20 approval gas sponsoring info\n * @param payer - The expected payer address\n * @param tokenAddress - The expected token address\n * @returns Validation result with invalidReason and invalidMessage on failure\n */\nexport async function validateErc20ApprovalForPayment(\n info: Erc20ApprovalGasSponsoringInfo,\n payer: `0x${string}`,\n tokenAddress: `0x${string}`,\n): Promise<Pick<VerifyResponse, \"isValid\" | \"invalidReason\" | \"invalidMessage\">> {\n if (!validateErc20ApprovalGasSponsoringInfo(info)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalInvalidFormat,\n invalidMessage: \"ERC-20 approval extension info failed schema validation\",\n };\n }\n\n if (getAddress(info.from) !== getAddress(payer)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalFromMismatch,\n invalidMessage: `Expected from=${payer}, got ${info.from}`,\n };\n }\n\n if (getAddress(info.asset) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalAssetMismatch,\n invalidMessage: `Expected asset=${tokenAddress}, got ${info.asset}`,\n };\n }\n\n if (getAddress(info.spender) !== getAddress(PERMIT2_ADDRESS)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalSpenderNotPermit2,\n invalidMessage: `Expected spender=${PERMIT2_ADDRESS}, got ${info.spender}`,\n };\n }\n\n try {\n const serializedTx = info.signedTransaction as TransactionSerialized;\n const tx = parseTransaction(serializedTx);\n\n if (!tx.to || getAddress(tx.to) !== tokenAddress) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongTarget,\n invalidMessage: `Transaction targets ${tx.to ?? \"null\"}, expected ${tokenAddress}`,\n };\n }\n\n const data = tx.data ?? \"0x\";\n if (!data.startsWith(APPROVE_SELECTOR)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongSelector,\n invalidMessage: `Transaction calldata does not start with approve() selector ${APPROVE_SELECTOR}`,\n };\n }\n\n try {\n const decoded = decodeFunctionData({\n abi: erc20ApproveAbi,\n data: data as `0x${string}`,\n });\n const calldataSpender = getAddress(decoded.args[0] as `0x${string}`);\n if (calldataSpender !== getAddress(PERMIT2_ADDRESS)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxWrongSpender,\n invalidMessage: `approve() spender is ${calldataSpender}, expected Permit2 ${PERMIT2_ADDRESS}`,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxInvalidCalldata,\n invalidMessage: \"Failed to decode approve() calldata from the signed transaction\",\n };\n }\n\n try {\n const recoveredAddress = await recoverTransactionAddress({\n serializedTransaction: serializedTx,\n });\n if (getAddress(recoveredAddress) !== getAddress(payer)) {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxSignerMismatch,\n invalidMessage: `Transaction signed by ${recoveredAddress}, expected payer ${payer}`,\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxInvalidSignature,\n invalidMessage: \"Failed to recover signer from the signed transaction\",\n };\n }\n } catch {\n return {\n isValid: false,\n invalidReason: ErrErc20ApprovalTxParseFailed,\n invalidMessage: \"Failed to parse the signed transaction\",\n };\n }\n\n return { isValid: true };\n}\n","/**\n * Named error reason constants for the upto EVM facilitator.\n *\n * Shared Permit2 errors are re-exported from exact/facilitator/errors.ts.\n * Upto-specific errors are defined here.\n *\n * These strings must be character-for-character identical to the Go constants\n * to maintain cross-SDK parity.\n */\n\n// Re-export shared EVM errors\nexport { ErrAssetNotDeployedContract } from \"../../exact/facilitator/errors\";\n\n// Re-export shared Permit2 errors\nexport {\n ErrPermit2InvalidSpender,\n ErrPermit2RecipientMismatch,\n ErrPermit2DeadlineExpired,\n ErrPermit2NotYetValid,\n ErrPermit2AmountMismatch,\n ErrPermit2TokenMismatch,\n ErrPermit2InvalidSignature,\n ErrPermit2AllowanceRequired,\n ErrPermit2InvalidAmount,\n ErrPermit2InvalidDestination,\n ErrPermit2InvalidOwner,\n ErrPermit2PaymentTooEarly,\n ErrPermit2InvalidNonce,\n ErrPermit2612AmountMismatch,\n ErrErc20ApprovalInvalidFormat,\n ErrErc20ApprovalFromMismatch,\n ErrErc20ApprovalAssetMismatch,\n ErrErc20ApprovalSpenderNotPermit2,\n ErrErc20ApprovalTxWrongTarget,\n ErrErc20ApprovalTxWrongSelector,\n ErrErc20ApprovalTxWrongSpender,\n ErrErc20ApprovalTxInvalidCalldata,\n ErrErc20ApprovalTxSignerMismatch,\n ErrErc20ApprovalTxInvalidSignature,\n ErrErc20ApprovalTxParseFailed,\n} from \"../../exact/facilitator/errors\";\n\n// Upto-specific errors\nexport const ErrUptoInvalidScheme = \"invalid_upto_evm_scheme\";\nexport const ErrUptoNetworkMismatch = \"invalid_upto_evm_network_mismatch\";\nexport const ErrUptoSettlementExceedsAmount = \"invalid_upto_evm_payload_settlement_exceeds_amount\";\nexport const ErrUptoAmountExceedsPermitted = \"upto_amount_exceeds_permitted\";\nexport const ErrUptoUnauthorizedFacilitator = \"upto_unauthorized_facilitator\";\nexport const ErrUptoFacilitatorMismatch = \"upto_facilitator_mismatch\";\n"],"mappings":"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","names":["getAddress","getAddress"]}
import {
classifyErc6492Payer,
verifyTypedDataSignature
} from "./chunk-BEMCJZKA.mjs";
import {
ErrEip3009InsufficientBalance,
ErrEip3009NonceAlreadyUsed,
ErrEip3009NotSupported,
ErrEip3009SimulationFailed,
ErrEip3009TokenNameMismatch,
ErrEip3009TokenVersionMismatch,
ErrFactoryNotAllowed,
ErrInvalidAuthorizationValue,
ErrInvalidScheme,
ErrInvalidSignature,
ErrMissingEip712Domain,
ErrNetworkMismatch,
ErrRecipientMismatch,
ErrSmartWalletDeploymentFailed,
ErrTransactionFailed,
ErrValidAfterInFuture,
ErrValidBeforeExpired
} from "./chunk-23HX7MHV.mjs";
import {
resolveDataSuffix
} from "./chunk-27MWX225.mjs";
import {
authorizationTypes,
eip3009ABI
} from "./chunk-MACPBXCT.mjs";
import {
multicall
} from "./chunk-VS3RYAYE.mjs";
import {
createNonce
} from "./chunk-TW7Z65AO.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 = getEvmChainIdV1(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 getAddress3, isAddressEqual, parseErc6492Signature as parseErc6492Signature2 } from "viem";
// src/exact/facilitator/eip3009-utils.ts
import { encodeFunctionData, getAddress as getAddress2, parseErc6492Signature, parseSignature } from "viem";
async function simulateEip3009Transfer(signer, erc20Address, payload, eip6492Deployment) {
return (await simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment)).ok;
}
async function simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment) {
const auth = payload.authorization;
const transferArgs = [
getAddress2(auth.from),
getAddress2(auth.to),
BigInt(auth.value),
BigInt(auth.validAfter),
BigInt(auth.validBefore),
auth.nonce
];
if (eip6492Deployment) {
const { signature: innerSignature } = parseErc6492Signature(payload.signature);
const transferCalldata = encodeFunctionData({
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [...transferArgs, innerSignature]
});
try {
const results = await multicall(signer.readContract.bind(signer), [
{
address: getAddress2(eip6492Deployment.factoryAddress),
callData: eip6492Deployment.factoryCalldata
},
{
address: erc20Address,
callData: transferCalldata
}
]);
return { ok: results[1]?.status === "success" };
} catch (error) {
return { ok: false, error };
}
}
const sig = payload.signature;
const sigLength = sig.startsWith("0x") ? sig.length - 2 : sig.length;
const isECDSA = sigLength === 130;
try {
if (isECDSA) {
const parsedSig = parseSignature(sig);
await signer.readContract({
address: erc20Address,
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [
...transferArgs,
parsedSig.v ?? parsedSig.yParity,
parsedSig.r,
parsedSig.s
]
});
} else {
await signer.readContract({
address: erc20Address,
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [...transferArgs, sig]
});
}
return { ok: true };
} catch (error) {
return { ok: false, error };
}
}
async function diagnoseEip3009SimulationFailure(signer, erc20Address, payload, requirements, amountRequired) {
const payer = payload.authorization.from;
const diagnosticCalls = [
{
address: erc20Address,
abi: eip3009ABI,
functionName: "balanceOf",
args: [payload.authorization.from]
},
{
address: erc20Address,
abi: eip3009ABI,
functionName: "name"
},
{
address: erc20Address,
abi: eip3009ABI,
functionName: "version"
},
{
address: erc20Address,
abi: eip3009ABI,
functionName: "authorizationState",
args: [payload.authorization.from, payload.authorization.nonce]
}
];
try {
const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);
const [balanceResult, nameResult, versionResult, authStateResult] = results;
if (authStateResult.status === "failure") {
return { isValid: false, invalidReason: ErrEip3009NotSupported, payer };
}
if (authStateResult.status === "success" && authStateResult.result === true) {
return { isValid: false, invalidReason: ErrEip3009NonceAlreadyUsed, payer };
}
if (nameResult.status === "success" && requirements.extra?.name && nameResult.result !== requirements.extra.name) {
return { isValid: false, invalidReason: ErrEip3009TokenNameMismatch, payer };
}
if (versionResult.status === "success" && requirements.extra?.version && versionResult.result !== requirements.extra.version) {
return { isValid: false, invalidReason: ErrEip3009TokenVersionMismatch, payer };
}
if (balanceResult.status === "success") {
const balance = balanceResult.result;
if (balance < BigInt(amountRequired)) {
return {
isValid: false,
invalidReason: ErrEip3009InsufficientBalance,
payer
};
}
}
} catch {
}
return { isValid: false, invalidReason: ErrEip3009SimulationFailed, payer };
}
function parseEip3009TransferError(error) {
const msg = error instanceof Error ? error.message : String(error);
if (/authorization.*(expired|valid before)/i.test(msg) || /AuthorizationExpired/i.test(msg)) {
return ErrValidBeforeExpired;
}
if (/authorization.*not.*valid|AuthorizationNotYetValid/i.test(msg)) {
return ErrValidAfterInFuture;
}
if (/authorization.*used|AuthorizationAlreadyUsed|AuthorizationUsedOrCanceled/i.test(msg)) {
return ErrEip3009NonceAlreadyUsed;
}
if (/transfer.*exceeds.*balance|insufficient.*balance|ERC20InsufficientBalance/i.test(msg)) {
return ErrEip3009InsufficientBalance;
}
if (/invalid.*signature|SignerMismatch|InvalidSignatureV|InvalidSignatureS/i.test(msg)) {
return ErrInvalidSignature;
}
return ErrTransactionFailed;
}
async function executeTransferWithAuthorization(signer, erc20Address, payload, dataSuffix) {
const { signature } = parseErc6492Signature(payload.signature);
const signatureLength = signature.startsWith("0x") ? signature.length - 2 : signature.length;
const isECDSA = signatureLength === 130;
const auth = payload.authorization;
const baseArgs = [
getAddress2(auth.from),
getAddress2(auth.to),
BigInt(auth.value),
BigInt(auth.validAfter),
BigInt(auth.validBefore),
auth.nonce
];
let signatureArgs;
if (isECDSA) {
const parsedSig = parseSignature(signature);
signatureArgs = [
parsedSig.v || parsedSig.yParity,
parsedSig.r,
parsedSig.s
];
} else {
signatureArgs = [signature];
}
return signer.writeContract({
address: erc20Address,
abi: eip3009ABI,
functionName: "transferWithAuthorization",
args: [...baseArgs, ...signatureArgs],
dataSuffix
});
}
// src/exact/v1/facilitator/scheme.ts
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 = {
eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],
simulateInSettle: config?.simulateInSettle ?? 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) {
return this._verify(payload, requirements);
}
/**
* Settles a payment by executing the transfer (V1).
*
* @param payload - The payment payload to settle
* @param requirements - The payment requirements
* @param context - Optional facilitator context for extension capabilities
* @returns Promise resolving to settlement response
*/
async settle(payload, requirements, context) {
const payloadV1 = payload;
const exactEvmPayload = payload.payload;
const valid = await this._verify(payload, requirements, {
simulate: this.config.simulateInSettle ?? false
});
if (!valid.isValid) {
return {
success: false,
network: payloadV1.network,
transaction: "",
errorReason: valid.invalidReason ?? ErrInvalidScheme,
payer: exactEvmPayload.authorization.from
};
}
try {
const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature2(
exactEvmPayload.signature
);
if (factoryAddress && factoryCalldata && !isAddressEqual(factoryAddress, "0x0000000000000000000000000000000000000000")) {
const payerAddress = exactEvmPayload.authorization.from;
const bytecode = await this.signer.getCode({ address: payerAddress });
if (!bytecode || bytecode === "0x") {
const normalizedFactory = factoryAddress.toLowerCase();
const isAllowed = (this.config.eip6492AllowedFactories ?? []).some(
(allowed) => allowed.toLowerCase() === normalizedFactory
);
if (!isAllowed) {
return {
success: false,
errorReason: ErrFactoryNotAllowed,
transaction: "",
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
const deployTx = await this.signer.sendTransaction({
to: factoryAddress,
data: factoryCalldata
});
const deployReceipt = await this.signer.waitForTransactionReceipt({ hash: deployTx });
if (deployReceipt.status !== "success") {
return {
success: false,
errorReason: ErrSmartWalletDeploymentFailed,
transaction: "",
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
}
}
const dataSuffix = await resolveDataSuffix(context, {
paymentPayload: payload,
paymentRequirements: requirements
});
const tx = await executeTransferWithAuthorization(
this.signer,
getAddress3(requirements.asset),
exactEvmPayload,
dataSuffix
);
const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });
if (receipt.status !== "success") {
return {
success: false,
errorReason: ErrTransactionFailed,
transaction: tx,
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
return {
success: true,
transaction: tx,
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
} catch (error) {
return {
success: false,
errorReason: error instanceof Error ? error.message : ErrTransactionFailed,
transaction: "",
network: payloadV1.network,
payer: exactEvmPayload.authorization.from
};
}
}
/**
* Internal verify with optional simulation control.
*
* @param payload - The payment payload to verify
* @param requirements - The payment requirements
* @param options - Verification options (e.g. simulate)
* @returns Promise resolving to verification response
*/
async _verify(payload, requirements, options) {
const requirementsV1 = requirements;
const payloadV1 = payload;
const exactEvmPayload = payload.payload;
const payer = exactEvmPayload.authorization.from;
let eip6492Deployment;
if (payloadV1.scheme !== "exact" || requirements.scheme !== "exact") {
return {
isValid: false,
invalidReason: ErrInvalidScheme,
payer
};
}
let chainId;
try {
chainId = getEvmChainIdV1(payloadV1.network);
} catch {
return {
isValid: false,
invalidReason: ErrNetworkMismatch,
payer
};
}
if (!requirements.extra?.name || !requirements.extra?.version) {
return {
isValid: false,
invalidReason: ErrMissingEip712Domain,
payer
};
}
const { name, version } = requirements.extra;
const erc20Address = getAddress3(requirements.asset);
if (payloadV1.network !== requirements.network) {
return {
isValid: false,
invalidReason: ErrNetworkMismatch,
payer
};
}
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
}
};
const signature = exactEvmPayload.signature;
const {
isCounterfactual,
innerSignature,
eip6492Deployment: classification6492
} = await classifyErc6492Payer(this.signer, signature, payer);
if (classification6492) {
eip6492Deployment = classification6492;
}
if (isCounterfactual) {
const factory = classification6492?.factoryAddress;
const factoryAllowed = !!factory && this.config.eip6492AllowedFactories.some(
(a) => a.trim().toLowerCase() === factory.toLowerCase()
);
if (!factoryAllowed) {
return {
isValid: false,
invalidReason: ErrFactoryNotAllowed,
payer
};
}
}
if (!isCounterfactual) {
const isValid = await verifyTypedDataSignature(this.signer, {
address: payer,
...permitTypedData,
signature: innerSignature
});
if (!isValid) {
return {
isValid: false,
invalidReason: ErrInvalidSignature,
payer
};
}
}
if (getAddress3(exactEvmPayload.authorization.to) !== getAddress3(requirements.payTo)) {
return {
isValid: false,
invalidReason: ErrRecipientMismatch,
payer
};
}
const now = Math.floor(Date.now() / 1e3);
if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {
return {
isValid: false,
invalidReason: ErrValidBeforeExpired,
payer
};
}
if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {
return {
isValid: false,
invalidReason: ErrValidAfterInFuture,
payer
};
}
if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {
return {
isValid: false,
invalidReason: ErrInvalidAuthorizationValue,
payer
};
}
if (options?.simulate !== false) {
const simulationSucceeded = await simulateEip3009Transfer(
this.signer,
erc20Address,
exactEvmPayload,
eip6492Deployment
);
if (!simulationSucceeded) {
return diagnoseEip3009SimulationFailure(
this.signer,
erc20Address,
exactEvmPayload,
requirements,
requirementsV1.maxAmountRequired
);
}
}
return {
isValid: true,
invalidReason: void 0,
payer
};
}
};
// src/v1/index.ts
var EVM_NETWORK_CHAIN_ID_MAP = {
ethereum: 1,
sepolia: 11155111,
abstract: 2741,
"abstract-testnet": 11124,
"base-sepolia": 84532,
base: 8453,
"avalanche-fuji": 43113,
avalanche: 43114,
iotex: 4689,
sei: 1329,
"sei-testnet": 1328,
polygon: 137,
"polygon-amoy": 80002,
peaq: 3338,
story: 1514,
educhain: 41923,
"skale-base-sepolia": 324705682,
megaeth: 4326,
monad: 143,
stable: 988,
"stable-testnet": 2201
};
var NETWORKS = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);
function getEvmChainIdV1(network) {
const chainId = EVM_NETWORK_CHAIN_ID_MAP[network];
if (!chainId) {
throw new Error(`Unsupported v1 network: ${network}`);
}
return chainId;
}
export {
simulateEip3009TransferResult,
diagnoseEip3009SimulationFailure,
parseEip3009TransferError,
executeTransferWithAuthorization,
ExactEvmSchemeV12 as ExactEvmSchemeV1,
EVM_NETWORK_CHAIN_ID_MAP,
NETWORKS,
getEvmChainIdV1,
ExactEvmSchemeV1 as ExactEvmSchemeV12
};
//# sourceMappingURL=chunk-ZWPJEMS5.mjs.map
{"version":3,"sources":["../../src/exact/v1/client/scheme.ts","../../src/exact/v1/facilitator/scheme.ts","../../src/exact/facilitator/eip3009-utils.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 } from \"../../../utils\";\nimport { EvmNetworkV1, getEvmChainIdV1 } from \"../../../v1\";\n\n/**\n * EVM client implementation for the Exact payment scheme (V1).\n */\nexport class ExactEvmSchemeV1 implements SchemeNetworkClient {\n readonly scheme = \"exact\";\n\n /**\n * Creates a new ExactEvmClientV1 instance.\n *\n * @param signer - The EVM signer for client operations\n */\n constructor(private readonly signer: ClientEvmSigner) {}\n\n /**\n * Creates a payment payload for the Exact scheme (V1).\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - The payment requirements\n * @returns Promise resolving to a payment payload\n */\n async createPaymentPayload(\n x402Version: number,\n paymentRequirements: PaymentRequirements,\n ): Promise<\n Pick<PaymentPayload, \"x402Version\" | \"payload\"> & { scheme: string; network: Network }\n > {\n const selectedV1 = paymentRequirements as unknown as PaymentRequirementsV1;\n const nonce = createNonce();\n const now = Math.floor(Date.now() / 1000);\n\n const authorization: ExactEvmPayloadV1[\"authorization\"] = {\n from: this.signer.address,\n to: getAddress(selectedV1.payTo),\n value: selectedV1.maxAmountRequired,\n validAfter: (now - 600).toString(), // 10 minutes before\n validBefore: (now + selectedV1.maxTimeoutSeconds).toString(),\n nonce,\n };\n\n // Sign the authorization\n const signature = await this.signAuthorization(authorization, selectedV1);\n\n const payload: ExactEvmPayloadV1 = {\n authorization,\n signature,\n };\n\n return {\n x402Version,\n scheme: selectedV1.scheme,\n network: selectedV1.network,\n payload,\n };\n }\n\n /**\n * Sign the EIP-3009 authorization using EIP-712\n *\n * @param authorization - The authorization to sign\n * @param requirements - The payment requirements\n * @returns Promise resolving to the signature\n */\n private async signAuthorization(\n authorization: ExactEvmPayloadV1[\"authorization\"],\n requirements: PaymentRequirementsV1,\n ): Promise<`0x${string}`> {\n const chainId = getEvmChainIdV1(requirements.network as EvmNetworkV1);\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n throw new Error(\n `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n );\n }\n\n const { name, version } = requirements.extra;\n\n const domain = {\n name,\n version,\n chainId,\n verifyingContract: getAddress(requirements.asset),\n };\n\n const message = {\n from: getAddress(authorization.from),\n to: getAddress(authorization.to),\n value: BigInt(authorization.value),\n validAfter: BigInt(authorization.validAfter),\n validBefore: BigInt(authorization.validBefore),\n nonce: authorization.nonce,\n };\n\n return await this.signer.signTypedData({\n domain,\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\",\n message,\n });\n }\n}\n","import {\n PaymentPayload,\n PaymentPayloadV1,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n FacilitatorContext,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport { resolveDataSuffix } from \"../../../shared/extensions\";\nimport { verifyTypedDataSignature, classifyErc6492Payer } from \"../../../shared/verifySignature\";\nimport { PaymentRequirementsV1 } from \"@x402/core/types/v1\";\nimport { getAddress, Hex, isAddressEqual, parseErc6492Signature } from \"viem\";\nimport { authorizationTypes } from \"../../../constants\";\nimport { FacilitatorEvmSigner } from \"../../../signer\";\nimport { ExactEvmPayloadV1 } from \"../../../types\";\nimport { EvmNetworkV1, getEvmChainIdV1 } from \"../../../v1\";\nimport * as Errors from \"../../facilitator/errors\";\nimport {\n diagnoseEip3009SimulationFailure,\n executeTransferWithAuthorization,\n simulateEip3009Transfer,\n} from \"../../facilitator/eip3009-utils\";\n\nexport interface VerifyV1Options {\n /** Run onchain simulation. Defaults to true. */\n simulate?: boolean;\n}\n\nexport interface ExactEvmSchemeV1Config {\n /**\n * Allowlist of factory contract addresses (hex strings, case-insensitive) that the facilitator\n * will call when deploying an undeployed smart wallet via ERC-6492.\n *\n * A non-empty list enables ERC-4337 smart wallet deployment via EIP-6492. Facilitators must\n * explicitly list every factory they trust to prevent arbitrary transaction injection via\n * attacker-controlled ERC-6492 signature wrappers. An empty or omitted list denies all factory\n * deployment calls.\n *\n * @default []\n */\n eip6492AllowedFactories?: string[];\n /**\n * If enabled, simulates transaction before settling. Defaults to false, ie only simulate during verify.\n *\n * @default false\n */\n simulateInSettle?: boolean;\n}\n\n/**\n * EVM facilitator implementation for the Exact payment scheme (V1).\n */\nexport class ExactEvmSchemeV1 implements SchemeNetworkFacilitator {\n readonly scheme = \"exact\";\n readonly caipFamily = \"eip155:*\";\n private readonly config: Required<ExactEvmSchemeV1Config>;\n\n /**\n * Creates a new ExactEvmFacilitatorV1 instance.\n *\n * @param signer - The EVM signer for facilitator operations\n * @param config - Optional configuration for the facilitator\n */\n constructor(\n private readonly signer: FacilitatorEvmSigner,\n config?: ExactEvmSchemeV1Config,\n ) {\n this.config = {\n eip6492AllowedFactories: config?.eip6492AllowedFactories ?? [],\n simulateInSettle: config?.simulateInSettle ?? false,\n };\n }\n\n /**\n * Get mechanism-specific extra data for the supported kinds endpoint.\n * For EVM, no extra data is needed.\n *\n * @param _ - The network identifier (unused for EVM)\n * @returns undefined (EVM has no extra data)\n */\n getExtra(_: string): Record<string, unknown> | undefined {\n return undefined;\n }\n\n /**\n * Get signer addresses used by this facilitator.\n * Returns all addresses this facilitator can use for signing/settling transactions.\n *\n * @param _ - The network identifier (unused for EVM, addresses are network-agnostic)\n * @returns Array of facilitator wallet addresses\n */\n getSigners(_: string): string[] {\n return [...this.signer.getAddresses()];\n }\n\n /**\n * Verifies a payment payload (V1).\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n return this._verify(payload, requirements);\n }\n\n /**\n * Settles a payment by executing the transfer (V1).\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @param context - Optional facilitator context for extension capabilities\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n context?: FacilitatorContext,\n ): Promise<SettleResponse> {\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n\n // Re-verify before settling\n const valid = await this._verify(payload, requirements, {\n simulate: this.config.simulateInSettle ?? false,\n });\n if (!valid.isValid) {\n return {\n success: false,\n network: payloadV1.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? Errors.ErrInvalidScheme,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n try {\n // Parse ERC-6492 signature if applicable (for optional deployment)\n const { address: factoryAddress, data: factoryCalldata } = parseErc6492Signature(\n exactEvmPayload.signature!,\n );\n\n // Deploy ERC-4337 smart wallet via EIP-6492 if factory is in the allowlist\n if (\n factoryAddress &&\n factoryCalldata &&\n !isAddressEqual(factoryAddress, \"0x0000000000000000000000000000000000000000\")\n ) {\n // Check if smart wallet is already deployed\n const payerAddress = exactEvmPayload.authorization.from;\n const bytecode = await this.signer.getCode({ address: payerAddress });\n\n if (!bytecode || bytecode === \"0x\") {\n const normalizedFactory = factoryAddress.toLowerCase();\n const isAllowed = (this.config.eip6492AllowedFactories ?? []).some(\n allowed => allowed.toLowerCase() === normalizedFactory,\n );\n if (!isAllowed) {\n return {\n success: false,\n errorReason: Errors.ErrFactoryNotAllowed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Send the factory calldata directly as a transaction\n // The factoryCalldata already contains the complete encoded function call\n const deployTx = await this.signer.sendTransaction({\n to: factoryAddress as Hex,\n data: factoryCalldata as Hex,\n });\n\n // Wait for deployment and verify it actually succeeded.\n const deployReceipt = await this.signer.waitForTransactionReceipt({ hash: deployTx });\n if (deployReceipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrSmartWalletDeploymentFailed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n // Do NOT re-simulate the transfer here. The authoritative pre-check is the atomic\n // deploy+transfer simulation in verify; a second standalone eth_call after the real\n // deploy tx races the deploy's state propagation across load-balanced RPC nodes and\n // false-rejected valid wallets. The on-chain transferWithAuthorization below is the\n // definitive signature check; a genuinely unsupported inner signature reverts there\n // and is classified by parseEip3009TransferError.\n }\n }\n\n // V1 payloads carry no extensions, so the builder-code suffix can only contain the\n // facilitator's own wallet code (`w`); client app (`a`) and service (`s`) codes are\n // always absent.\n const dataSuffix = await resolveDataSuffix(context, {\n paymentPayload: payload,\n paymentRequirements: requirements,\n });\n\n const tx = await executeTransferWithAuthorization(\n this.signer,\n getAddress(requirements.asset),\n exactEvmPayload,\n dataSuffix,\n );\n\n // Wait for transaction confirmation\n const receipt = await this.signer.waitForTransactionReceipt({ hash: tx });\n\n if (receipt.status !== \"success\") {\n return {\n success: false,\n errorReason: Errors.ErrTransactionFailed,\n transaction: tx,\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n\n return {\n success: true,\n transaction: tx,\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n } catch (error) {\n return {\n success: false,\n errorReason: error instanceof Error ? error.message : Errors.ErrTransactionFailed,\n transaction: \"\",\n network: payloadV1.network,\n payer: exactEvmPayload.authorization.from,\n };\n }\n }\n\n /**\n * Internal verify with optional simulation control.\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @param options - Verification options (e.g. simulate)\n * @returns Promise resolving to verification response\n */\n private async _verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n options?: VerifyV1Options,\n ): Promise<VerifyResponse> {\n const requirementsV1 = requirements as unknown as PaymentRequirementsV1;\n const payloadV1 = payload as unknown as PaymentPayloadV1;\n const exactEvmPayload = payload.payload as ExactEvmPayloadV1;\n const payer = exactEvmPayload.authorization.from;\n let eip6492Deployment:\n | { factoryAddress: `0x${string}`; factoryCalldata: `0x${string}` }\n | undefined;\n\n // Verify scheme matches\n if (payloadV1.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidScheme,\n payer,\n };\n }\n\n // Get chain configuration\n let chainId: number;\n try {\n chainId = getEvmChainIdV1(payloadV1.network as EvmNetworkV1);\n } catch {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n if (!requirements.extra?.name || !requirements.extra?.version) {\n return {\n isValid: false,\n invalidReason: Errors.ErrMissingEip712Domain,\n payer,\n };\n }\n\n const { name, version } = requirements.extra as { name: string; version: string };\n const erc20Address = getAddress(requirements.asset);\n\n // Verify network matches\n if (payloadV1.network !== requirements.network) {\n return {\n isValid: false,\n invalidReason: Errors.ErrNetworkMismatch,\n payer,\n };\n }\n\n // Build typed data for signature verification\n const permitTypedData = {\n types: authorizationTypes,\n primaryType: \"TransferWithAuthorization\" as const,\n domain: {\n name,\n version,\n chainId,\n verifyingContract: erc20Address,\n },\n message: {\n from: exactEvmPayload.authorization.from,\n to: exactEvmPayload.authorization.to,\n value: BigInt(exactEvmPayload.authorization.value),\n validAfter: BigInt(exactEvmPayload.authorization.validAfter),\n validBefore: BigInt(exactEvmPayload.authorization.validBefore),\n nonce: exactEvmPayload.authorization.nonce,\n },\n };\n\n const signature = exactEvmPayload.signature!;\n\n // Classify the payer (counterfactual vs deployed) and extract inner sig in one shot.\n const {\n isCounterfactual,\n innerSignature,\n eip6492Deployment: classification6492,\n } = await classifyErc6492Payer(this.signer, signature, payer);\n\n if (classification6492) {\n eip6492Deployment = classification6492;\n }\n\n if (isCounterfactual) {\n // Mirror settle's allowlist gate so verify predicts settle: a counterfactual payment whose\n // factory is not allowlisted is rejected at settle, so reject it here too.\n const factory = classification6492?.factoryAddress;\n const factoryAllowed =\n !!factory &&\n this.config.eip6492AllowedFactories.some(\n a => a.trim().toLowerCase() === factory.toLowerCase(),\n );\n if (!factoryAllowed) {\n return {\n isValid: false,\n invalidReason: Errors.ErrFactoryNotAllowed,\n payer,\n };\n }\n }\n\n if (!isCounterfactual) {\n // Non-counterfactual path: verify using the strict primitive that mirrors\n // on-chain SignatureChecker semantics (ecrecover for EOAs, strict EIP-1271\n // for any address with code). No ECDSA fallback for code addresses.\n const isValid = await verifyTypedDataSignature(this.signer, {\n address: payer,\n ...permitTypedData,\n signature: innerSignature,\n });\n if (!isValid) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidSignature,\n payer,\n };\n }\n }\n // Counterfactual path: defer to on-chain simulation which deploys + verifies atomically.\n\n // Verify payment recipient matches\n if (getAddress(exactEvmPayload.authorization.to) !== getAddress(requirements.payTo)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrRecipientMismatch,\n payer,\n };\n }\n\n // Verify validBefore is in the future (with 6 second buffer for block time)\n const now = Math.floor(Date.now() / 1000);\n if (BigInt(exactEvmPayload.authorization.validBefore) < BigInt(now + 6)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidBeforeExpired,\n payer,\n };\n }\n\n // Verify validAfter is not in the future\n if (BigInt(exactEvmPayload.authorization.validAfter) > BigInt(now)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrValidAfterInFuture,\n payer,\n };\n }\n\n // Verify amount exactly matches requirements\n if (BigInt(exactEvmPayload.authorization.value) !== BigInt(requirementsV1.maxAmountRequired)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrInvalidAuthorizationValue,\n payer,\n };\n }\n\n // Transaction simulation\n if (options?.simulate !== false) {\n const simulationSucceeded = await simulateEip3009Transfer(\n this.signer,\n erc20Address,\n exactEvmPayload,\n eip6492Deployment,\n );\n if (!simulationSucceeded) {\n return diagnoseEip3009SimulationFailure(\n this.signer,\n erc20Address,\n exactEvmPayload,\n requirements,\n requirementsV1.maxAmountRequired,\n );\n }\n }\n\n return {\n isValid: true,\n invalidReason: undefined,\n payer,\n };\n }\n}\n","import { PaymentRequirements, VerifyResponse } from \"@x402/core/types\";\nimport { encodeFunctionData, getAddress, Hex, parseErc6492Signature, parseSignature } from \"viem\";\nimport { eip3009ABI } from \"../../constants\";\nimport { multicall, ContractCall, RawContractCall } from \"../../multicall\";\nimport { FacilitatorEvmSigner } from \"../../signer\";\nimport { ExactEIP3009Payload } from \"../../types\";\nimport * as Errors from \"./errors\";\n\nexport interface Eip6492Deployment {\n factoryAddress: `0x${string}`;\n factoryCalldata: `0x${string}`;\n}\n\n/**\n * Outcome of a transfer simulation. `error` is populated only when the underlying `eth_call`\n * threw (revert or transport), letting callers distinguish a contract revert from an RPC failure.\n */\nexport interface SimulateEip3009Result {\n ok: boolean;\n error?: unknown;\n}\n\n/**\n * Simulates transferWithAuthorization via eth_call.\n * Returns true if simulation succeeded, false if it failed.\n *\n * @param signer - EVM signer for contract reads\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param eip6492Deployment - Optional EIP-6492 factory info for undeployed smart wallets\n *\n * @returns true if simulation succeeded, false if it failed\n */\nexport async function simulateEip3009Transfer(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n eip6492Deployment?: Eip6492Deployment,\n): Promise<boolean> {\n return (await simulateEip3009TransferResult(signer, erc20Address, payload, eip6492Deployment)).ok;\n}\n\n/**\n * Like {@link simulateEip3009Transfer} but returns the thrown error (if any) alongside the\n * boolean outcome, so callers can tell a contract revert apart from a transport/RPC failure.\n *\n * @param signer - EVM signer for contract reads\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param eip6492Deployment - Optional EIP-6492 factory info for undeployed smart wallets\n * @returns The simulation outcome and, on failure via a thrown error, that error.\n */\nexport async function simulateEip3009TransferResult(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n eip6492Deployment?: Eip6492Deployment,\n): Promise<SimulateEip3009Result> {\n const auth = payload.authorization;\n const transferArgs = [\n getAddress(auth.from),\n getAddress(auth.to),\n BigInt(auth.value),\n BigInt(auth.validAfter),\n BigInt(auth.validBefore),\n auth.nonce,\n ] as const;\n\n if (eip6492Deployment) {\n const { signature: innerSignature } = parseErc6492Signature(payload.signature!);\n const transferCalldata = encodeFunctionData({\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...transferArgs, innerSignature],\n });\n\n try {\n const results = await multicall(signer.readContract.bind(signer), [\n {\n address: getAddress(eip6492Deployment.factoryAddress),\n callData: eip6492Deployment.factoryCalldata,\n } satisfies RawContractCall,\n {\n address: erc20Address,\n callData: transferCalldata,\n } satisfies RawContractCall,\n ]);\n\n return { ok: results[1]?.status === \"success\" };\n } catch (error) {\n return { ok: false, error };\n }\n }\n\n const sig = payload.signature!;\n const sigLength = sig.startsWith(\"0x\") ? sig.length - 2 : sig.length;\n const isECDSA = sigLength === 130;\n\n try {\n if (isECDSA) {\n const parsedSig = parseSignature(sig);\n await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [\n ...transferArgs,\n (parsedSig.v as number | undefined) ?? parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ],\n });\n } else {\n await signer.readContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...transferArgs, sig],\n });\n }\n return { ok: true };\n } catch (error) {\n return { ok: false, error };\n }\n}\n\n/**\n * After simulation fails, runs a single diagnostic multicall to determine the most specific error reason.\n * Checks balanceOf, name, version and authorizationState in one RPC round-trip.\n *\n * @param signer - EVM signer used for the payment\n * @param erc20Address - Address of the ERC-20 token contract\n * @param payload - The EIP-3009 transfer authorization payload\n * @param requirements - Payment requirements to validate against\n * @param amountRequired - Required amount for the payment (balance check)\n *\n * @returns Promise resolving to the verification result with validity and optional invalid reason\n */\nexport async function diagnoseEip3009SimulationFailure(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n requirements: PaymentRequirements,\n amountRequired: string,\n): Promise<VerifyResponse> {\n const payer = payload.authorization.from;\n\n const diagnosticCalls: ContractCall[] = [\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"balanceOf\",\n args: [payload.authorization.from],\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"name\",\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"version\",\n },\n {\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"authorizationState\",\n args: [payload.authorization.from, payload.authorization.nonce],\n },\n ];\n\n try {\n const results = await multicall(signer.readContract.bind(signer), diagnosticCalls);\n\n const [balanceResult, nameResult, versionResult, authStateResult] = results;\n\n if (authStateResult.status === \"failure\") {\n return { isValid: false, invalidReason: Errors.ErrEip3009NotSupported, payer };\n }\n\n if (authStateResult.status === \"success\" && authStateResult.result === true) {\n return { isValid: false, invalidReason: Errors.ErrEip3009NonceAlreadyUsed, payer };\n }\n\n if (\n nameResult.status === \"success\" &&\n requirements.extra?.name &&\n nameResult.result !== requirements.extra.name\n ) {\n return { isValid: false, invalidReason: Errors.ErrEip3009TokenNameMismatch, payer };\n }\n\n if (\n versionResult.status === \"success\" &&\n requirements.extra?.version &&\n versionResult.result !== requirements.extra.version\n ) {\n return { isValid: false, invalidReason: Errors.ErrEip3009TokenVersionMismatch, payer };\n }\n\n if (balanceResult.status === \"success\") {\n const balance = balanceResult.result as bigint;\n if (balance < BigInt(amountRequired)) {\n return {\n isValid: false,\n invalidReason: Errors.ErrEip3009InsufficientBalance,\n payer,\n };\n }\n }\n } catch {\n // Diagnostic multicall failed — fall through to generic error\n }\n\n return { isValid: false, invalidReason: Errors.ErrEip3009SimulationFailed, payer };\n}\n\n/**\n * Maps an EIP-3009 contract revert error to a specific error code.\n * Falls back to ErrTransactionFailed when the revert reason is unknown.\n *\n * @param error - The error thrown during transfer execution\n * @returns A specific error reason string\n */\nexport function parseEip3009TransferError(error: unknown): string {\n const msg = error instanceof Error ? error.message : String(error);\n if (/authorization.*(expired|valid before)/i.test(msg) || /AuthorizationExpired/i.test(msg)) {\n return Errors.ErrValidBeforeExpired;\n }\n if (/authorization.*not.*valid|AuthorizationNotYetValid/i.test(msg)) {\n return Errors.ErrValidAfterInFuture;\n }\n if (/authorization.*used|AuthorizationAlreadyUsed|AuthorizationUsedOrCanceled/i.test(msg)) {\n return Errors.ErrEip3009NonceAlreadyUsed;\n }\n if (/transfer.*exceeds.*balance|insufficient.*balance|ERC20InsufficientBalance/i.test(msg)) {\n return Errors.ErrEip3009InsufficientBalance;\n }\n if (/invalid.*signature|SignerMismatch|InvalidSignatureV|InvalidSignatureS/i.test(msg)) {\n return Errors.ErrInvalidSignature;\n }\n return Errors.ErrTransactionFailed;\n}\n\n/**\n * Executes transferWithAuthorization onchain.\n *\n * @param signer - EVM signer for contract writes\n * @param erc20Address - ERC-20 token contract address\n * @param payload - EIP-3009 transfer authorization payload\n * @param dataSuffix - Optional hex bytes to append after the ABI-encoded calldata\n *\n * @returns Transaction hash\n */\nexport async function executeTransferWithAuthorization(\n signer: FacilitatorEvmSigner,\n erc20Address: `0x${string}`,\n payload: ExactEIP3009Payload,\n dataSuffix?: Hex,\n): Promise<Hex> {\n const { signature } = parseErc6492Signature(payload.signature!);\n const signatureLength = signature.startsWith(\"0x\") ? signature.length - 2 : signature.length;\n const isECDSA = signatureLength === 130;\n\n const auth = payload.authorization;\n const baseArgs = [\n getAddress(auth.from),\n getAddress(auth.to),\n BigInt(auth.value),\n BigInt(auth.validAfter),\n BigInt(auth.validBefore),\n auth.nonce,\n ] as const;\n\n let signatureArgs: readonly unknown[];\n if (isECDSA) {\n const parsedSig = parseSignature(signature);\n signatureArgs = [\n (parsedSig.v as number | undefined) || parsedSig.yParity,\n parsedSig.r,\n parsedSig.s,\n ];\n } else {\n signatureArgs = [signature];\n }\n\n return signer.writeContract({\n address: erc20Address,\n abi: eip3009ABI,\n functionName: \"transferWithAuthorization\",\n args: [...baseArgs, ...signatureArgs],\n dataSuffix,\n });\n}\n","export { ExactEvmSchemeV1 } from \"../exact/v1\";\n\nexport const EVM_NETWORK_CHAIN_ID_MAP = {\n ethereum: 1,\n sepolia: 11155111,\n abstract: 2741,\n \"abstract-testnet\": 11124,\n \"base-sepolia\": 84532,\n base: 8453,\n \"avalanche-fuji\": 43113,\n avalanche: 43114,\n iotex: 4689,\n sei: 1329,\n \"sei-testnet\": 1328,\n polygon: 137,\n \"polygon-amoy\": 80002,\n peaq: 3338,\n story: 1514,\n educhain: 41923,\n \"skale-base-sepolia\": 324705682,\n megaeth: 4326,\n monad: 143,\n stable: 988,\n \"stable-testnet\": 2201,\n} as const;\n\nexport type EvmNetworkV1 = keyof typeof EVM_NETWORK_CHAIN_ID_MAP;\n\nexport const NETWORKS: string[] = Object.keys(EVM_NETWORK_CHAIN_ID_MAP);\n\n/**\n * Extract chain ID from a v1 legacy network name.\n *\n * @param network - The v1 network name (e.g., \"base-sepolia\", \"polygon\")\n * @returns The numeric chain ID\n * @throws Error if the network name is not a known v1 network\n */\nexport function getEvmChainIdV1(network: string): number {\n const chainId = EVM_NETWORK_CHAIN_ID_MAP[network as EvmNetworkV1];\n if (!chainId) {\n throw new Error(`Unsupported v1 network: ${network}`);\n }\n return chainId;\n}\n"],"mappings":"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","names":["getAddress","parseErc6492Signature","getAddress","getAddress","ExactEvmSchemeV1","parseErc6492Signature","getAddress"]}

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display