@x402/extensions 2.6.0 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/offer-receipt/types.ts","../../src/offer-receipt/signing.ts","../../src/offer-receipt/did.ts","../../src/offer-receipt/server.ts","../../src/offer-receipt/client.ts"],"sourcesContent":["/**\n * Type definitions for the x402 Offer/Receipt Extension\n *\n * Based on: x402/specs/extensions/extension-offer-and-receipt.md (v1.0)\n *\n * Offers prove payment requirements originated from a resource server.\n * Receipts prove service was delivered after payment.\n */\n\n/**\n * Extension identifier constant\n */\nexport const OFFER_RECEIPT = \"offer-receipt\";\n\n/**\n * Supported signature formats (§3.1)\n */\nexport type SignatureFormat = \"jws\" | \"eip712\";\n\n// ============================================================================\n// Low-Level Signer Interfaces\n// ============================================================================\n\n/**\n * Base signer interface for pluggable signing backends\n */\nexport interface Signer {\n /** Key identifier DID (e.g., did:web:api.example.com#key-1) */\n kid: string;\n /** Sign payload and return signature string */\n sign: (payload: Uint8Array) => Promise<string>;\n /** Signature format */\n format: SignatureFormat;\n}\n\n/**\n * JWS-specific signer with algorithm info\n */\nexport interface JWSSigner extends Signer {\n format: \"jws\";\n /** JWS algorithm (e.g., ES256K, EdDSA) */\n algorithm: string;\n}\n\n/**\n * EIP-712 specific signer\n */\nexport interface EIP712Signer extends Signer {\n format: \"eip712\";\n /** Chain ID for EIP-712 domain */\n chainId: number;\n}\n\n// ============================================================================\n// Offer Types (§4)\n// ============================================================================\n\n/**\n * Offer payload fields (§4.2)\n *\n * Required: version, resourceUrl, scheme, network, asset, payTo, amount\n * Optional: validUntil\n */\nexport interface OfferPayload {\n /** Offer payload schema version (currently 1) */\n version: number;\n /** The paid resource URL */\n resourceUrl: string;\n /** Payment scheme identifier (e.g., \"exact\") */\n scheme: string;\n /** Blockchain network identifier (CAIP-2 format, e.g., \"eip155:8453\") */\n network: string;\n /** Token contract address or \"native\" */\n asset: string;\n /** Recipient wallet address */\n payTo: string;\n /** Required payment amount */\n amount: string;\n /** Unix timestamp (seconds) when the offer expires (optional) */\n validUntil: number;\n}\n\n/**\n * Signed offer in JWS format (§3.1.1)\n *\n * \"When format = 'jws': payload MUST be omitted\"\n */\nexport interface JWSSignedOffer {\n format: \"jws\";\n /** Index into accepts[] array (unsigned envelope field, §4.1.1) */\n acceptIndex?: number;\n /** JWS Compact Serialization string (header.payload.signature) */\n signature: string;\n}\n\n/**\n * Signed offer in EIP-712 format (§3.1.1)\n *\n * \"When format = 'eip712': payload is REQUIRED\"\n */\nexport interface EIP712SignedOffer {\n format: \"eip712\";\n /** Index into accepts[] array (unsigned envelope field, §4.1.1) */\n acceptIndex?: number;\n /** The canonical payload fields */\n payload: OfferPayload;\n /** Hex-encoded ECDSA signature (0x-prefixed, 65 bytes: r+s+v) */\n signature: string;\n}\n\n/**\n * Union type for signed offers\n */\nexport type SignedOffer = JWSSignedOffer | EIP712SignedOffer;\n\n// ============================================================================\n// Receipt Types (§5)\n// ============================================================================\n\n/**\n * Receipt payload fields (§5.2)\n *\n * Required: version, network, resourceUrl, payer, issuedAt\n * Optional: transaction (for verifiability over privacy)\n */\nexport interface ReceiptPayload {\n /** Receipt payload schema version (currently 1) */\n version: number;\n /** Blockchain network identifier (CAIP-2 format, e.g., \"eip155:8453\") */\n network: string;\n /** The paid resource URL */\n resourceUrl: string;\n /** Payer identifier (commonly a wallet address) */\n payer: string;\n /** Unix timestamp (seconds) when receipt was issued */\n issuedAt: number;\n /** Blockchain transaction hash (optional - for verifiability over privacy) */\n transaction: string;\n}\n\n/**\n * Signed receipt in JWS format (§3.1.1)\n */\nexport interface JWSSignedReceipt {\n format: \"jws\";\n /** JWS Compact Serialization string */\n signature: string;\n}\n\n/**\n * Signed receipt in EIP-712 format (§3.1.1)\n */\nexport interface EIP712SignedReceipt {\n format: \"eip712\";\n /** The receipt payload */\n payload: ReceiptPayload;\n /** Hex-encoded ECDSA signature */\n signature: string;\n}\n\n/**\n * Union type for signed receipts\n */\nexport type SignedReceipt = JWSSignedReceipt | EIP712SignedReceipt;\n\n// ============================================================================\n// Extension Configuration Types\n// ============================================================================\n\n/**\n * Declaration for the offer-receipt extension in route config\n * Used by servers to declare that a route uses offer-receipt\n */\nexport interface OfferReceiptDeclaration {\n /** Include transaction hash in receipt (default: false for privacy). Set to true for verifiability. */\n includeTxHash?: boolean;\n /** Offer validity duration in seconds. Default: 300 (see x402ResourceServer.ts) */\n offerValiditySeconds?: number;\n}\n\n/**\n * Input for creating an offer (derived from PaymentRequirements)\n */\nexport interface OfferInput {\n /** Index into accepts[] array this offer corresponds to (0-based) */\n acceptIndex: number;\n /** Payment scheme identifier */\n scheme: string;\n /** Blockchain network identifier (CAIP-2 format) */\n network: string;\n /** Token contract address or \"native\" */\n asset: string;\n /** Recipient wallet address */\n payTo: string;\n /** Required payment amount */\n amount: string;\n /** Offer validity duration in seconds. Default: 300 (see x402ResourceServer.ts) */\n offerValiditySeconds?: number;\n}\n\n/**\n * High-level issuer interface for the offer-receipt extension.\n * Creates and signs offers and receipts.\n * Used by createOfferReceiptExtension()\n */\nexport interface OfferReceiptIssuer {\n /** Key identifier DID */\n kid: string;\n /** Signature format */\n format: SignatureFormat;\n /** Create and sign an offer for a resource */\n issueOffer(resourceUrl: string, input: OfferInput): Promise<SignedOffer>;\n /** Create and sign a receipt for a completed payment */\n issueReceipt(\n resourceUrl: string,\n payer: string,\n network: string,\n transaction?: string,\n ): Promise<SignedReceipt>;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if an offer is JWS format\n *\n * @param offer - The signed offer to check\n * @returns True if the offer uses JWS format\n */\nexport function isJWSSignedOffer(offer: SignedOffer): offer is JWSSignedOffer {\n return offer.format === \"jws\";\n}\n\n/**\n * Check if an offer is EIP-712 format\n *\n * @param offer - The signed offer to check\n * @returns True if the offer uses EIP-712 format\n */\nexport function isEIP712SignedOffer(offer: SignedOffer): offer is EIP712SignedOffer {\n return offer.format === \"eip712\";\n}\n\n/**\n * Check if a receipt is JWS format\n *\n * @param receipt - The signed receipt to check\n * @returns True if the receipt uses JWS format\n */\nexport function isJWSSignedReceipt(receipt: SignedReceipt): receipt is JWSSignedReceipt {\n return receipt.format === \"jws\";\n}\n\n/**\n * Check if a receipt is EIP-712 format\n *\n * @param receipt - The signed receipt to check\n * @returns True if the receipt uses EIP-712 format\n */\nexport function isEIP712SignedReceipt(receipt: SignedReceipt): receipt is EIP712SignedReceipt {\n return receipt.format === \"eip712\";\n}\n\n/**\n * Check if a signer is JWS format\n *\n * @param signer - The signer to check\n * @returns True if the signer uses JWS format\n */\nexport function isJWSSigner(signer: Signer): signer is JWSSigner {\n return signer.format === \"jws\";\n}\n\n/**\n * Check if a signer is EIP-712 format\n *\n * @param signer - The signer to check\n * @returns True if the signer uses EIP-712 format\n */\nexport function isEIP712Signer(signer: Signer): signer is EIP712Signer {\n return signer.format === \"eip712\";\n}\n\n// ============================================================================\n// Receipt Input Type\n// ============================================================================\n\n/**\n * Input for creating a receipt\n */\nexport interface ReceiptInput {\n /** The resource URL that was paid for */\n resourceUrl: string;\n /** The payer identifier (wallet address) */\n payer: string;\n /** The blockchain network (CAIP-2 format) */\n network: string;\n /** The transaction hash (optional, for verifiability) */\n transaction?: string;\n}\n","/**\n * Signing utilities for x402 Offer/Receipt Extension\n *\n * This module provides:\n * - JCS (JSON Canonicalization Scheme) per RFC 8785\n * - JWS (JSON Web Signature) signing and extraction\n * - EIP-712 typed data signing\n * - Offer/Receipt creation utilities\n * - Signature verification utilities\n *\n * Based on: x402/specs/extensions/extension-offer-and-receipt.md (v1.0) §3\n */\n\nimport * as jose from \"jose\";\nimport { hashTypedData, recoverTypedDataAddress, type Hex, type TypedDataDomain } from \"viem\";\nimport type {\n JWSSigner,\n OfferPayload,\n ReceiptPayload,\n SignedOffer,\n SignedReceipt,\n OfferInput,\n ReceiptInput,\n} from \"./types\";\nimport {\n isJWSSignedOffer,\n isEIP712SignedOffer,\n isJWSSignedReceipt,\n isEIP712SignedReceipt,\n type JWSSignedOffer,\n type EIP712SignedOffer,\n type JWSSignedReceipt,\n type EIP712SignedReceipt,\n} from \"./types\";\nimport { extractPublicKeyFromKid } from \"./did\";\n\n// ============================================================================\n// JCS Canonicalization (RFC 8785)\n// ============================================================================\n\n/**\n * Canonicalize a JSON object using JCS (RFC 8785)\n *\n * Rules:\n * 1. Object keys are sorted lexicographically by UTF-16 code units\n * 2. No whitespace between tokens\n * 3. Numbers use shortest representation (no trailing zeros)\n * 4. Strings use minimal escaping\n * 5. null, true, false are lowercase literals\n *\n * @param value - The object to canonicalize\n * @returns The canonicalized JSON string\n */\nexport function canonicalize(value: unknown): string {\n return serializeValue(value);\n}\n\n/**\n * Serialize a value to canonical JSON\n *\n * @param value - The value to serialize\n * @returns The serialized string\n */\nfunction serializeValue(value: unknown): string {\n if (value === null) return \"null\";\n if (value === undefined) return \"null\";\n\n const type = typeof value;\n if (type === \"boolean\") return value ? \"true\" : \"false\";\n if (type === \"number\") return serializeNumber(value as number);\n if (type === \"string\") return serializeString(value as string);\n if (Array.isArray(value)) return serializeArray(value);\n if (type === \"object\") return serializeObject(value as Record<string, unknown>);\n\n throw new Error(`Cannot canonicalize value of type ${type}`);\n}\n\n/**\n * Serialize a number to canonical JSON\n *\n * @param num - The number to serialize\n * @returns The serialized string\n */\nfunction serializeNumber(num: number): string {\n if (!Number.isFinite(num)) throw new Error(\"Cannot canonicalize Infinity or NaN\");\n if (Object.is(num, -0)) return \"0\";\n return String(num);\n}\n\n/**\n * Serialize a string to canonical JSON\n *\n * @param str - The string to serialize\n * @returns The serialized string with proper escaping\n */\nfunction serializeString(str: string): string {\n let result = '\"';\n for (let i = 0; i < str.length; i++) {\n const char = str[i];\n const code = str.charCodeAt(i);\n if (code < 0x20) {\n result += \"\\\\u\" + code.toString(16).padStart(4, \"0\");\n } else if (char === '\"') {\n result += '\\\\\"';\n } else if (char === \"\\\\\") {\n result += \"\\\\\\\\\";\n } else {\n result += char;\n }\n }\n return result + '\"';\n}\n\n/**\n * Serialize an array to canonical JSON\n *\n * @param arr - The array to serialize\n * @returns The serialized string\n */\nfunction serializeArray(arr: unknown[]): string {\n return \"[\" + arr.map(serializeValue).join(\",\") + \"]\";\n}\n\n/**\n * Serialize an object to canonical JSON with sorted keys\n *\n * @param obj - The object to serialize\n * @returns The serialized string with sorted keys\n */\nfunction serializeObject(obj: Record<string, unknown>): string {\n const keys = Object.keys(obj).sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));\n const pairs: string[] = [];\n for (const key of keys) {\n const value = obj[key];\n if (value !== undefined) {\n pairs.push(serializeString(key) + \":\" + serializeValue(value));\n }\n }\n return \"{\" + pairs.join(\",\") + \"}\";\n}\n\n/**\n * Hash a canonicalized object using SHA-256\n *\n * @param obj - The object to hash\n * @returns The SHA-256 hash as Uint8Array\n */\nexport async function hashCanonical(obj: unknown): Promise<Uint8Array> {\n const canonical = canonicalize(obj);\n const data = new TextEncoder().encode(canonical);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n return new Uint8Array(hashBuffer);\n}\n\n/**\n * Get canonical bytes of an object (UTF-8 encoded)\n *\n * @param obj - The object to encode\n * @returns The UTF-8 encoded canonical JSON\n */\nexport function getCanonicalBytes(obj: unknown): Uint8Array {\n return new TextEncoder().encode(canonicalize(obj));\n}\n\n// ============================================================================\n// JWS Signing (§3.3)\n// ============================================================================\n\n/**\n * Create a JWS Compact Serialization from a payload\n *\n * Assembles the full JWS structure (header.payload.signature) using the\n * signer's algorithm and kid. The signer only needs to sign bytes and\n * return the base64url-encoded signature.\n *\n * @param payload - The payload object to sign\n * @param signer - The JWS signer\n * @returns The JWS compact serialization string\n */\nexport async function createJWS<T extends object>(payload: T, signer: JWSSigner): Promise<string> {\n const headerObj = { alg: signer.algorithm, kid: signer.kid };\n const headerB64 = jose.base64url.encode(new TextEncoder().encode(JSON.stringify(headerObj)));\n const canonical = canonicalize(payload);\n const payloadB64 = jose.base64url.encode(new TextEncoder().encode(canonical));\n const signingInput = new TextEncoder().encode(`${headerB64}.${payloadB64}`);\n const signatureB64 = await signer.sign(signingInput);\n return `${headerB64}.${payloadB64}.${signatureB64}`;\n}\n\n/**\n * Extract JWS header without verification\n *\n * @param jws - The JWS compact serialization string\n * @returns The decoded header object\n */\nexport function extractJWSHeader(jws: string): { alg: string; kid?: string } {\n const parts = jws.split(\".\");\n if (parts.length !== 3) throw new Error(\"Invalid JWS format\");\n const headerJson = jose.base64url.decode(parts[0]);\n return JSON.parse(new TextDecoder().decode(headerJson));\n}\n\n/**\n * Extract JWS payload\n *\n * Note: This extracts the payload without verifying the signature or\n * checking signer authorization. Signature verification requires resolving\n * key bindings (did:web documents, attestations, etc.) which is outside\n * the scope of x402 client utilities.\n *\n * @param jws - The JWS compact serialization string\n * @returns The decoded payload\n */\nexport function extractJWSPayload<T>(jws: string): T {\n const parts = jws.split(\".\");\n if (parts.length !== 3) throw new Error(\"Invalid JWS format\");\n const payloadJson = jose.base64url.decode(parts[1]);\n return JSON.parse(new TextDecoder().decode(payloadJson));\n}\n\n// ============================================================================\n// EIP-712 Domain Configuration (§3.2)\n// ============================================================================\n\n/**\n * Create EIP-712 domain for offer signing\n *\n * @returns The EIP-712 domain object\n */\nexport function createOfferDomain(): TypedDataDomain {\n return { name: \"x402 offer\", version: \"1\", chainId: 1 };\n}\n\n/**\n * Create EIP-712 domain for receipt signing\n *\n * @returns The EIP-712 domain object\n */\nexport function createReceiptDomain(): TypedDataDomain {\n return { name: \"x402 receipt\", version: \"1\", chainId: 1 };\n}\n\n/**\n * EIP-712 types for Offer (§4.3)\n */\nexport const OFFER_TYPES = {\n Offer: [\n { name: \"version\", type: \"uint256\" },\n { name: \"resourceUrl\", type: \"string\" },\n { name: \"scheme\", type: \"string\" },\n { name: \"network\", type: \"string\" },\n { name: \"asset\", type: \"string\" },\n { name: \"payTo\", type: \"string\" },\n { name: \"amount\", type: \"string\" },\n { name: \"validUntil\", type: \"uint256\" },\n ],\n};\n\n/**\n * EIP-712 types for Receipt (§5.3)\n */\nexport const RECEIPT_TYPES = {\n Receipt: [\n { name: \"version\", type: \"uint256\" },\n { name: \"network\", type: \"string\" },\n { name: \"resourceUrl\", type: \"string\" },\n { name: \"payer\", type: \"string\" },\n { name: \"issuedAt\", type: \"uint256\" },\n { name: \"transaction\", type: \"string\" },\n ],\n};\n\n// ============================================================================\n// EIP-712 Payload Preparation\n// ============================================================================\n\n/**\n * Prepare offer payload for EIP-712 signing\n *\n * @param payload - The offer payload\n * @returns The prepared message object for EIP-712\n */\nexport function prepareOfferForEIP712(payload: OfferPayload): {\n version: bigint;\n resourceUrl: string;\n scheme: string;\n network: string;\n asset: string;\n payTo: string;\n amount: string;\n validUntil: bigint;\n} {\n return {\n version: BigInt(payload.version),\n resourceUrl: payload.resourceUrl,\n scheme: payload.scheme,\n network: payload.network,\n asset: payload.asset,\n payTo: payload.payTo,\n amount: payload.amount,\n validUntil: BigInt(payload.validUntil),\n };\n}\n\n/**\n * Prepare receipt payload for EIP-712 signing\n *\n * @param payload - The receipt payload\n * @returns The prepared message object for EIP-712\n */\nexport function prepareReceiptForEIP712(payload: ReceiptPayload): {\n version: bigint;\n network: string;\n resourceUrl: string;\n payer: string;\n issuedAt: bigint;\n transaction: string;\n} {\n return {\n version: BigInt(payload.version),\n network: payload.network,\n resourceUrl: payload.resourceUrl,\n payer: payload.payer,\n issuedAt: BigInt(payload.issuedAt),\n transaction: payload.transaction,\n };\n}\n\n// ============================================================================\n// EIP-712 Hashing\n// ============================================================================\n\n/**\n * Hash offer typed data for EIP-712\n *\n * @param payload - The offer payload\n * @returns The EIP-712 hash\n */\nexport function hashOfferTypedData(payload: OfferPayload): Hex {\n return hashTypedData({\n domain: createOfferDomain(),\n types: OFFER_TYPES,\n primaryType: \"Offer\",\n message: prepareOfferForEIP712(payload),\n });\n}\n\n/**\n * Hash receipt typed data for EIP-712\n *\n * @param payload - The receipt payload\n * @returns The EIP-712 hash\n */\nexport function hashReceiptTypedData(payload: ReceiptPayload): Hex {\n return hashTypedData({\n domain: createReceiptDomain(),\n types: RECEIPT_TYPES,\n primaryType: \"Receipt\",\n message: prepareReceiptForEIP712(payload),\n });\n}\n\n// ============================================================================\n// EIP-712 Signing\n// ============================================================================\n\n/**\n * Function type for signing EIP-712 typed data\n */\nexport type SignTypedDataFn = (params: {\n domain: TypedDataDomain;\n types: Record<string, Array<{ name: string; type: string }>>;\n primaryType: string;\n message: Record<string, unknown>;\n}) => Promise<Hex>;\n\n/**\n * Sign an offer using EIP-712\n *\n * @param payload - The offer payload\n * @param signTypedData - The signing function\n * @returns The signature hex string\n */\nexport async function signOfferEIP712(\n payload: OfferPayload,\n signTypedData: SignTypedDataFn,\n): Promise<Hex> {\n return signTypedData({\n domain: createOfferDomain(),\n types: OFFER_TYPES,\n primaryType: \"Offer\",\n message: prepareOfferForEIP712(payload) as unknown as Record<string, unknown>,\n });\n}\n\n/**\n * Sign a receipt using EIP-712\n *\n * @param payload - The receipt payload\n * @param signTypedData - The signing function\n * @returns The signature hex string\n */\nexport async function signReceiptEIP712(\n payload: ReceiptPayload,\n signTypedData: SignTypedDataFn,\n): Promise<Hex> {\n return signTypedData({\n domain: createReceiptDomain(),\n types: RECEIPT_TYPES,\n primaryType: \"Receipt\",\n message: prepareReceiptForEIP712(payload) as unknown as Record<string, unknown>,\n });\n}\n\n// ============================================================================\n// Network Utilities\n// ============================================================================\n\n/**\n * Extract chain ID from an EIP-155 network string (strict format)\n *\n * @param network - The network string in \"eip155:<chainId>\" format\n * @returns The chain ID number\n * @throws Error if network is not in \"eip155:<chainId>\" format\n */\nexport function extractEIP155ChainId(network: string): number {\n const match = network.match(/^eip155:(\\d+)$/);\n if (!match) {\n throw new Error(`Invalid network format: ${network}. Expected \"eip155:<chainId>\"`);\n }\n return parseInt(match[1], 10);\n}\n\n/**\n * V1 EVM network name to chain ID mapping\n * Based on x402 v1 protocol network identifiers\n */\nconst V1_EVM_NETWORK_CHAIN_IDS: Record<string, number> = {\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};\n\n/**\n * V1 Solana network name to CAIP-2 mapping\n */\nconst V1_SOLANA_NETWORKS: Record<string, string> = {\n solana: \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\",\n \"solana-devnet\": \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\",\n \"solana-testnet\": \"solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z\",\n};\n\n/**\n * Convert a network string to CAIP-2 format\n *\n * Handles both CAIP-2 format and legacy x402 v1 network strings:\n * - CAIP-2: \"eip155:8453\" → \"eip155:8453\" (passed through)\n * - V1 EVM: \"base\" → \"eip155:8453\", \"base-sepolia\" → \"eip155:84532\"\n * - V1 Solana: \"solana\" → \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\"\n *\n * @param network - The network string to convert\n * @returns The CAIP-2 formatted network string\n * @throws Error if network is not a recognized v1 identifier or CAIP-2 format\n */\nexport function convertNetworkStringToCAIP2(network: string): string {\n // Already CAIP-2 format\n if (network.includes(\":\")) return network;\n\n // Check V1 EVM networks\n const chainId = V1_EVM_NETWORK_CHAIN_IDS[network.toLowerCase()];\n if (chainId !== undefined) {\n return `eip155:${chainId}`;\n }\n\n // Check V1 Solana networks\n const solanaNetwork = V1_SOLANA_NETWORKS[network.toLowerCase()];\n if (solanaNetwork) {\n return solanaNetwork;\n }\n\n throw new Error(\n `Unknown network identifier: \"${network}\". Expected CAIP-2 format (e.g., \"eip155:8453\") or v1 name (e.g., \"base\", \"solana\").`,\n );\n}\n\n/**\n * Extract chain ID from a CAIP-2 network string (EVM only)\n *\n * @param network - The CAIP-2 network string\n * @returns Chain ID number, or undefined for non-EVM networks\n */\nexport function extractChainIdFromCAIP2(network: string): number | undefined {\n const [namespace, reference] = network.split(\":\");\n if (namespace === \"eip155\" && reference) {\n const chainId = parseInt(reference, 10);\n return isNaN(chainId) ? undefined : chainId;\n }\n return undefined;\n}\n\n// ============================================================================\n// Offer Creation (§4)\n// ============================================================================\n\n/** Default offer validity in seconds (matches x402ResourceServer.ts) */\nconst DEFAULT_MAX_TIMEOUT_SECONDS = 300;\n\n/** Current extension version */\nconst EXTENSION_VERSION = 1;\n\n/**\n * Create an offer payload from input\n *\n * @param resourceUrl - The resource URL being paid for\n * @param input - The offer input parameters\n * @returns The offer payload\n */\nfunction createOfferPayload(resourceUrl: string, input: OfferInput): OfferPayload {\n const now = Math.floor(Date.now() / 1000);\n const offerValiditySeconds = input.offerValiditySeconds ?? DEFAULT_MAX_TIMEOUT_SECONDS;\n\n return {\n version: EXTENSION_VERSION,\n resourceUrl,\n scheme: input.scheme,\n network: input.network,\n asset: input.asset,\n payTo: input.payTo,\n amount: input.amount,\n validUntil: now + offerValiditySeconds,\n };\n}\n\n/**\n * Create a signed offer using JWS\n *\n * @param resourceUrl - The resource URL being paid for\n * @param input - The offer input parameters\n * @param signer - The JWS signer\n * @returns The signed offer with JWS format\n */\nexport async function createOfferJWS(\n resourceUrl: string,\n input: OfferInput,\n signer: JWSSigner,\n): Promise<JWSSignedOffer> {\n const payload = createOfferPayload(resourceUrl, input);\n const jws = await createJWS(payload, signer);\n return {\n format: \"jws\",\n acceptIndex: input.acceptIndex,\n signature: jws,\n };\n}\n\n/**\n * Create a signed offer using EIP-712\n *\n * @param resourceUrl - The resource URL being paid for\n * @param input - The offer input parameters\n * @param signTypedData - The signing function\n * @returns The signed offer with EIP-712 format\n */\nexport async function createOfferEIP712(\n resourceUrl: string,\n input: OfferInput,\n signTypedData: SignTypedDataFn,\n): Promise<EIP712SignedOffer> {\n const payload = createOfferPayload(resourceUrl, input);\n const signature = await signOfferEIP712(payload, signTypedData);\n return {\n format: \"eip712\",\n acceptIndex: input.acceptIndex,\n payload,\n signature,\n };\n}\n\n/**\n * Extract offer payload\n *\n * Note: This extracts the payload without verifying the signature or\n * checking signer authorization. Signer authorization requires resolving\n * key bindings (did:web documents, attestations, etc.) which is outside\n * the scope of x402 client utilities. See spec §4.5.1.\n *\n * @param offer - The signed offer\n * @returns The offer payload\n */\nexport function extractOfferPayload(offer: SignedOffer): OfferPayload {\n if (isJWSSignedOffer(offer)) {\n return extractJWSPayload<OfferPayload>(offer.signature);\n } else if (isEIP712SignedOffer(offer)) {\n return offer.payload;\n }\n throw new Error(`Unknown offer format: ${(offer as SignedOffer).format}`);\n}\n\n// ============================================================================\n// Receipt Creation (§5)\n// ============================================================================\n\n/**\n * Create a receipt payload for EIP-712 (requires all fields per spec §5.3)\n *\n * Per spec: \"implementations MUST set unused fields to empty string\"\n * for EIP-712 signing where fixed schemas require all fields.\n *\n * @param input - The receipt input parameters\n * @returns The receipt payload with all fields\n */\nfunction createReceiptPayloadForEIP712(input: ReceiptInput): ReceiptPayload {\n return {\n version: EXTENSION_VERSION,\n network: input.network,\n resourceUrl: input.resourceUrl,\n payer: input.payer,\n issuedAt: Math.floor(Date.now() / 1000),\n transaction: input.transaction ?? \"\",\n };\n}\n\n/**\n * Create a receipt payload for JWS (omits optional fields when not provided)\n *\n * Per spec §5.2: transaction is optional and should be omitted in JWS\n * when not provided (privacy-minimal by default).\n *\n * @param input - The receipt input parameters\n * @returns The receipt payload with optional fields omitted if not provided\n */\nfunction createReceiptPayloadForJWS(\n input: ReceiptInput,\n): Omit<ReceiptPayload, \"transaction\"> & { transaction?: string } {\n const payload: Omit<ReceiptPayload, \"transaction\"> & { transaction?: string } = {\n version: EXTENSION_VERSION,\n network: input.network,\n resourceUrl: input.resourceUrl,\n payer: input.payer,\n issuedAt: Math.floor(Date.now() / 1000),\n };\n if (input.transaction) {\n payload.transaction = input.transaction;\n }\n return payload;\n}\n\n/**\n * Create a signed receipt using JWS\n *\n * @param input - The receipt input parameters\n * @param signer - The JWS signer\n * @returns The signed receipt with JWS format\n */\nexport async function createReceiptJWS(\n input: ReceiptInput,\n signer: JWSSigner,\n): Promise<JWSSignedReceipt> {\n const payload = createReceiptPayloadForJWS(input);\n const jws = await createJWS(payload, signer);\n return { format: \"jws\", signature: jws };\n}\n\n/**\n * Create a signed receipt using EIP-712\n *\n * @param input - The receipt input parameters\n * @param signTypedData - The signing function\n * @returns The signed receipt with EIP-712 format\n */\nexport async function createReceiptEIP712(\n input: ReceiptInput,\n signTypedData: SignTypedDataFn,\n): Promise<EIP712SignedReceipt> {\n const payload = createReceiptPayloadForEIP712(input);\n const signature = await signReceiptEIP712(payload, signTypedData);\n return { format: \"eip712\", payload, signature };\n}\n\n/**\n * Extract receipt payload\n *\n * Note: This extracts the payload without verifying the signature or\n * checking signer authorization. Signer authorization requires resolving\n * key bindings (did:web documents, attestations, etc.) which is outside\n * the scope of x402 client utilities. See spec §5.5.\n *\n * @param receipt - The signed receipt\n * @returns The receipt payload\n */\nexport function extractReceiptPayload(receipt: SignedReceipt): ReceiptPayload {\n if (isJWSSignedReceipt(receipt)) {\n return extractJWSPayload<ReceiptPayload>(receipt.signature);\n } else if (isEIP712SignedReceipt(receipt)) {\n return receipt.payload;\n }\n throw new Error(`Unknown receipt format: ${(receipt as SignedReceipt).format}`);\n}\n\n// ============================================================================\n// Signature Verification\n// ============================================================================\n\n/**\n * Result of EIP-712 signature verification\n */\nexport interface EIP712VerificationResult<T> {\n signer: Hex;\n payload: T;\n}\n\n/**\n * Verify an EIP-712 signed offer and recover the signer address.\n * Does NOT verify signer authorization for the resourceUrl - see spec §4.5.1.\n *\n * @param offer - The EIP-712 signed offer\n * @returns The recovered signer address and payload\n */\nexport async function verifyOfferSignatureEIP712(\n offer: EIP712SignedOffer,\n): Promise<EIP712VerificationResult<OfferPayload>> {\n if (offer.format !== \"eip712\") {\n throw new Error(`Expected eip712 format, got ${offer.format}`);\n }\n if (!offer.payload || !(\"scheme\" in offer.payload)) {\n throw new Error(\"Invalid offer: missing or malformed payload\");\n }\n\n const signer = await recoverTypedDataAddress({\n domain: createOfferDomain(),\n types: OFFER_TYPES,\n primaryType: \"Offer\",\n message: prepareOfferForEIP712(offer.payload),\n signature: offer.signature as Hex,\n });\n\n return { signer, payload: offer.payload };\n}\n\n/**\n * Verify an EIP-712 signed receipt and recover the signer address.\n * Does NOT verify signer authorization for the resourceUrl - see spec §4.5.1.\n *\n * @param receipt - The EIP-712 signed receipt\n * @returns The recovered signer address and payload\n */\nexport async function verifyReceiptSignatureEIP712(\n receipt: EIP712SignedReceipt,\n): Promise<EIP712VerificationResult<ReceiptPayload>> {\n if (receipt.format !== \"eip712\") {\n throw new Error(`Expected eip712 format, got ${receipt.format}`);\n }\n if (!receipt.payload || !(\"payer\" in receipt.payload)) {\n throw new Error(\"Invalid receipt: missing or malformed payload\");\n }\n\n const signer = await recoverTypedDataAddress({\n domain: createReceiptDomain(),\n types: RECEIPT_TYPES,\n primaryType: \"Receipt\",\n message: prepareReceiptForEIP712(receipt.payload),\n signature: receipt.signature as Hex,\n });\n\n return { signer, payload: receipt.payload };\n}\n\n/**\n * Verify a JWS signed offer.\n * Does NOT verify signer authorization for the resourceUrl - see spec §4.5.1.\n * If no publicKey provided, extracts from kid (supports did:key, did:jwk, did:web).\n *\n * @param offer - The JWS signed offer\n * @param publicKey - Optional public key (JWK or KeyLike). If not provided, extracted from kid.\n * @returns The verified payload\n */\nexport async function verifyOfferSignatureJWS(\n offer: JWSSignedOffer,\n publicKey?: jose.KeyLike | jose.JWK,\n): Promise<OfferPayload> {\n if (offer.format !== \"jws\") {\n throw new Error(`Expected jws format, got ${offer.format}`);\n }\n const key = await resolveVerificationKey(offer.signature, publicKey);\n const { payload } = await jose.compactVerify(offer.signature, key);\n return JSON.parse(new TextDecoder().decode(payload)) as OfferPayload;\n}\n\n/**\n * Verify a JWS signed receipt.\n * Does NOT verify signer authorization for the resourceUrl - see spec §4.5.1.\n * If no publicKey provided, extracts from kid (supports did:key, did:jwk, did:web).\n *\n * @param receipt - The JWS signed receipt\n * @param publicKey - Optional public key (JWK or KeyLike). If not provided, extracted from kid.\n * @returns The verified payload\n */\nexport async function verifyReceiptSignatureJWS(\n receipt: JWSSignedReceipt,\n publicKey?: jose.KeyLike | jose.JWK,\n): Promise<ReceiptPayload> {\n if (receipt.format !== \"jws\") {\n throw new Error(`Expected jws format, got ${receipt.format}`);\n }\n const key = await resolveVerificationKey(receipt.signature, publicKey);\n const { payload } = await jose.compactVerify(receipt.signature, key);\n return JSON.parse(new TextDecoder().decode(payload)) as ReceiptPayload;\n}\n\n/**\n * Resolve the verification key for JWS verification\n *\n * @param jws - The JWS compact serialization string\n * @param providedKey - Optional explicit public key\n * @returns The resolved public key\n */\nasync function resolveVerificationKey(\n jws: string,\n providedKey?: jose.KeyLike | jose.JWK,\n): Promise<jose.KeyLike> {\n if (providedKey) {\n if (\"kty\" in providedKey) {\n const key = await jose.importJWK(providedKey);\n if (key instanceof Uint8Array) {\n throw new Error(\"Symmetric keys are not supported for JWS verification\");\n }\n return key;\n }\n return providedKey;\n }\n\n const header = extractJWSHeader(jws);\n if (!header.kid) {\n throw new Error(\"No public key provided and JWS header missing kid\");\n }\n\n return extractPublicKeyFromKid(header.kid);\n}\n","/**\n * DID Resolution Utilities\n *\n * Extracts public keys from DID key identifiers. Supports did:key, did:jwk, did:web.\n * Uses @noble/curves and @scure/base for cryptographic operations.\n */\n\nimport * as jose from \"jose\";\nimport { base58 } from \"@scure/base\";\nimport { secp256k1 } from \"@noble/curves/secp256k1\";\nimport { p256 } from \"@noble/curves/nist\";\n\n// Multicodec prefixes for supported key types\nconst MULTICODEC_ED25519_PUB = 0xed;\nconst MULTICODEC_SECP256K1_PUB = 0xe7;\nconst MULTICODEC_P256_PUB = 0x1200;\n\n/**\n * Extract a public key from a DID key identifier (kid).\n * Supports did:key, did:jwk, did:web.\n *\n * @param kid - The key identifier (DID URL, e.g., did:key:z6Mk..., did:web:example.com#key-1)\n * @returns The extracted public key\n */\nexport async function extractPublicKeyFromKid(kid: string): Promise<jose.KeyLike> {\n const [didPart, fragment] = kid.split(\"#\");\n const parts = didPart.split(\":\");\n\n if (parts.length < 3 || parts[0] !== \"did\") {\n throw new Error(`Invalid DID format: ${kid}`);\n }\n\n const method = parts[1];\n const identifier = parts.slice(2).join(\":\");\n\n switch (method) {\n case \"key\":\n return extractKeyFromDidKey(identifier);\n case \"jwk\":\n return extractKeyFromDidJwk(identifier);\n case \"web\":\n return resolveDidWeb(identifier, fragment);\n default:\n throw new Error(\n `Unsupported DID method \"${method}\". Supported: did:key, did:jwk, did:web. ` +\n `Provide the public key directly for other methods.`,\n );\n }\n}\n\n/**\n * Extract public key from did:key identifier (multibase-encoded)\n *\n * @param identifier - The did:key identifier (without the \"did:key:\" prefix)\n * @returns The extracted public key\n */\nasync function extractKeyFromDidKey(identifier: string): Promise<jose.KeyLike> {\n if (!identifier.startsWith(\"z\")) {\n throw new Error(`Unsupported multibase encoding. Expected 'z' (base58-btc).`);\n }\n\n const decoded = base58.decode(identifier.slice(1));\n const { codec, keyBytes } = readMulticodec(decoded);\n\n switch (codec) {\n case MULTICODEC_ED25519_PUB:\n return importAsymmetricJWK({\n kty: \"OKP\",\n crv: \"Ed25519\",\n x: jose.base64url.encode(keyBytes),\n });\n\n case MULTICODEC_SECP256K1_PUB: {\n const point = secp256k1.Point.fromHex(keyBytes);\n const uncompressed = point.toBytes(false);\n return importAsymmetricJWK({\n kty: \"EC\",\n crv: \"secp256k1\",\n x: jose.base64url.encode(uncompressed.slice(1, 33)),\n y: jose.base64url.encode(uncompressed.slice(33, 65)),\n });\n }\n\n case MULTICODEC_P256_PUB: {\n const point = p256.Point.fromHex(keyBytes);\n const uncompressed = point.toBytes(false);\n return importAsymmetricJWK({\n kty: \"EC\",\n crv: \"P-256\",\n x: jose.base64url.encode(uncompressed.slice(1, 33)),\n y: jose.base64url.encode(uncompressed.slice(33, 65)),\n });\n }\n\n default:\n throw new Error(\n `Unsupported key type in did:key (multicodec: 0x${codec.toString(16)}). ` +\n `Supported: Ed25519, secp256k1, P-256.`,\n );\n }\n}\n\n/**\n * Extract public key from did:jwk identifier (base64url-encoded JWK)\n *\n * @param identifier - The did:jwk identifier (without the \"did:jwk:\" prefix)\n * @returns The extracted public key\n */\nasync function extractKeyFromDidJwk(identifier: string): Promise<jose.KeyLike> {\n const jwkJson = new TextDecoder().decode(jose.base64url.decode(identifier));\n const jwk = JSON.parse(jwkJson) as jose.JWK;\n return importAsymmetricJWK(jwk);\n}\n\n/**\n * Resolve did:web by fetching DID document from .well-known/did.json\n *\n * @param identifier - The did:web identifier (without the \"did:web:\" prefix)\n * @param fragment - Optional fragment to identify specific key\n * @returns The extracted public key\n */\nasync function resolveDidWeb(identifier: string, fragment?: string): Promise<jose.KeyLike> {\n const parts = identifier.split(\":\");\n const domain = decodeURIComponent(parts[0]);\n const path = parts.slice(1).map(decodeURIComponent).join(\"/\");\n\n // did:web spec allows HTTP for localhost (https://w3c-ccg.github.io/did-method-web/#read-resolve)\n const host = domain.split(\":\")[0];\n const scheme = host === \"localhost\" || host === \"127.0.0.1\" ? \"http\" : \"https\";\n\n const url = path\n ? `${scheme}://${domain}/${path}/did.json`\n : `${scheme}://${domain}/.well-known/did.json`;\n\n let didDocument: DIDDocument;\n try {\n const response = await fetch(url, {\n headers: { Accept: \"application/did+json, application/json\" },\n });\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}`);\n }\n didDocument = (await response.json()) as DIDDocument;\n } catch (error) {\n throw new Error(\n `Failed to resolve did:web:${identifier}: ${error instanceof Error ? error.message : error}`,\n );\n }\n\n const fullDid = `did:web:${identifier}`;\n const keyId = fragment ? `${fullDid}#${fragment}` : undefined;\n const method = findVerificationMethod(didDocument, keyId);\n\n if (!method) {\n throw new Error(`No verification method found for ${keyId || fullDid}`);\n }\n\n if (method.publicKeyJwk) {\n return importAsymmetricJWK(method.publicKeyJwk);\n }\n if (method.publicKeyMultibase) {\n return extractKeyFromDidKey(method.publicKeyMultibase);\n }\n\n throw new Error(`Verification method ${method.id} has no supported key format`);\n}\n\n/**\n * Read multicodec varint prefix from bytes\n *\n * @param bytes - The encoded bytes\n * @returns The codec identifier and remaining key bytes\n */\nfunction readMulticodec(bytes: Uint8Array): { codec: number; keyBytes: Uint8Array } {\n let codec = 0;\n let shift = 0;\n let offset = 0;\n\n for (const byte of bytes) {\n codec |= (byte & 0x7f) << shift;\n offset++;\n if ((byte & 0x80) === 0) break;\n shift += 7;\n }\n\n return { codec, keyBytes: bytes.slice(offset) };\n}\n\n/**\n * Import an asymmetric JWK as a KeyLike\n *\n * @param jwk - The JWK to import\n * @returns The imported key\n */\nasync function importAsymmetricJWK(jwk: jose.JWK): Promise<jose.KeyLike> {\n const key = await jose.importJWK(jwk);\n if (key instanceof Uint8Array) {\n throw new Error(\"Symmetric keys are not supported\");\n }\n return key;\n}\n\ninterface DIDDocument {\n id: string;\n verificationMethod?: VerificationMethod[];\n assertionMethod?: (string | VerificationMethod)[];\n authentication?: (string | VerificationMethod)[];\n}\n\ninterface VerificationMethod {\n id: string;\n type: string;\n controller: string;\n publicKeyJwk?: jose.JWK;\n publicKeyMultibase?: string;\n}\n\n/**\n * Find a verification method in a DID document\n *\n * @param doc - The DID document\n * @param keyId - Optional specific key ID to find\n * @returns The verification method or undefined\n */\nfunction findVerificationMethod(doc: DIDDocument, keyId?: string): VerificationMethod | undefined {\n const methods = doc.verificationMethod || [];\n\n if (keyId) {\n return methods.find(m => m.id === keyId);\n }\n\n // Prefer assertionMethod, then authentication, then any\n for (const ref of doc.assertionMethod || []) {\n if (typeof ref === \"string\") {\n const m = methods.find(m => m.id === ref);\n if (m) return m;\n } else {\n return ref;\n }\n }\n\n for (const ref of doc.authentication || []) {\n if (typeof ref === \"string\") {\n const m = methods.find(m => m.id === ref);\n if (m) return m;\n } else {\n return ref;\n }\n }\n\n return methods[0];\n}\n","/**\n * Offer-Receipt Extension for x402ResourceServer\n *\n * This module provides the ResourceServerExtension implementation that uses\n * the extension hooks (enrichPaymentRequiredResponse, enrichSettlementResponse)\n * to add signed offers and receipts to x402 payment flows.\n *\n * Based on: x402/specs/extensions/extension-offer-and-receipt.md (v1.0)\n */\n\nimport type {\n ResourceServerExtension,\n PaymentRequiredContext,\n SettleResultContext,\n} from \"@x402/core/types\";\nimport type { PaymentRequirements } from \"@x402/core/types\";\nimport type { HTTPTransportContext } from \"@x402/core/http\";\nimport {\n OFFER_RECEIPT,\n type OfferReceiptIssuer,\n type OfferReceiptDeclaration,\n type OfferInput,\n type SignedOffer,\n type SignedReceipt,\n type JWSSigner,\n} from \"./types\";\nimport {\n createOfferJWS,\n createOfferEIP712,\n createReceiptJWS,\n createReceiptEIP712,\n type SignTypedDataFn,\n} from \"./signing\";\n\n// ============================================================================\n// JSON Schemas for Extension Responses\n// ============================================================================\n\n/**\n * JSON Schema for offer extension data (§6.1)\n */\nconst OFFER_SCHEMA = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n offers: {\n type: \"array\",\n items: {\n type: \"object\",\n properties: {\n format: { type: \"string\" },\n acceptIndex: { type: \"integer\" },\n payload: {\n type: \"object\",\n properties: {\n version: { type: \"integer\" },\n resourceUrl: { type: \"string\" },\n scheme: { type: \"string\" },\n network: { type: \"string\" },\n asset: { type: \"string\" },\n payTo: { type: \"string\" },\n amount: { type: \"string\" },\n validUntil: { type: \"integer\" },\n },\n required: [\"version\", \"resourceUrl\", \"scheme\", \"network\", \"asset\", \"payTo\", \"amount\"],\n },\n signature: { type: \"string\" },\n },\n required: [\"format\", \"signature\"],\n },\n },\n },\n required: [\"offers\"],\n};\n\n/**\n * JSON Schema for receipt extension data (§6.5)\n */\nconst RECEIPT_SCHEMA = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n receipt: {\n type: \"object\",\n properties: {\n format: { type: \"string\" },\n payload: {\n type: \"object\",\n properties: {\n version: { type: \"integer\" },\n network: { type: \"string\" },\n resourceUrl: { type: \"string\" },\n payer: { type: \"string\" },\n issuedAt: { type: \"integer\" },\n transaction: { type: \"string\" },\n },\n required: [\"version\", \"network\", \"resourceUrl\", \"payer\", \"issuedAt\"],\n },\n signature: { type: \"string\" },\n },\n required: [\"format\", \"signature\"],\n },\n },\n required: [\"receipt\"],\n};\n\n// ============================================================================\n// Extension Factory\n// ============================================================================\n\n/**\n * Convert PaymentRequirements to OfferInput\n *\n * @param requirements - The payment requirements\n * @param acceptIndex - Index into accepts[] array\n * @param offerValiditySeconds - Optional validity duration override\n * @returns The offer input object\n */\nfunction requirementsToOfferInput(\n requirements: PaymentRequirements,\n acceptIndex: number,\n offerValiditySeconds?: number,\n): OfferInput {\n return {\n acceptIndex,\n scheme: requirements.scheme,\n network: requirements.network,\n asset: requirements.asset,\n payTo: requirements.payTo,\n amount: requirements.amount,\n offerValiditySeconds: offerValiditySeconds ?? requirements.maxTimeoutSeconds,\n };\n}\n\n/**\n * Creates an offer-receipt extension for use with x402ResourceServer.\n *\n * The extension uses the hook system to:\n * 1. Add signed offers to each PaymentRequirements in 402 responses\n * 2. Add signed receipts to settlement responses after successful payment\n *\n * @param issuer - The issuer to use for creating and signing offers and receipts\n * @returns ResourceServerExtension that can be registered with x402ResourceServer\n */\nexport function createOfferReceiptExtension(issuer: OfferReceiptIssuer): ResourceServerExtension {\n return {\n key: OFFER_RECEIPT,\n\n // Add signed offers to 402 PaymentRequired response\n enrichPaymentRequiredResponse: async (\n declaration: unknown,\n context: PaymentRequiredContext,\n ): Promise<unknown> => {\n const config = declaration as OfferReceiptDeclaration | undefined;\n\n // Get resource URL from transport context or payment required response\n const resourceUrl =\n context.paymentRequiredResponse.resource?.url ||\n (context.transportContext as HTTPTransportContext)?.request?.adapter?.getUrl?.();\n\n if (!resourceUrl) {\n console.warn(\"[offer-receipt] No resource URL available for signing offers\");\n return undefined;\n }\n\n // Sign offers for each payment requirement\n const offers: SignedOffer[] = [];\n\n for (let i = 0; i < context.requirements.length; i++) {\n const requirement = context.requirements[i];\n try {\n const offerInput = requirementsToOfferInput(requirement, i, config?.offerValiditySeconds);\n const signedOffer = await issuer.issueOffer(resourceUrl, offerInput);\n offers.push(signedOffer);\n } catch (error) {\n console.error(`[offer-receipt] Failed to sign offer for requirement ${i}:`, error);\n }\n }\n\n if (offers.length === 0) {\n return undefined;\n }\n\n // Return extension data per spec structure\n return {\n info: {\n offers,\n },\n schema: OFFER_SCHEMA,\n };\n },\n\n // Add signed receipt to settlement response\n enrichSettlementResponse: async (\n declaration: unknown,\n context: SettleResultContext,\n ): Promise<unknown> => {\n const config = declaration as OfferReceiptDeclaration | undefined;\n\n // Skip if settlement failed\n if (!context.result.success) {\n return undefined;\n }\n\n // Get payer from settlement result\n const payer = context.result.payer;\n if (!payer) {\n console.warn(\"[offer-receipt] No payer available for signing receipt\");\n return undefined;\n }\n\n // Get network and transaction from settlement result\n const network = context.result.network;\n if (!network) {\n console.warn(\"[offer-receipt] No network available for signing receipt\");\n return undefined;\n }\n const transaction = context.result.transaction;\n\n // Get resource URL from transport context\n const resourceUrl = (\n context.transportContext as HTTPTransportContext\n )?.request?.adapter?.getUrl?.();\n\n if (!resourceUrl) {\n console.warn(\"[offer-receipt] No resource URL available for signing receipt\");\n return undefined;\n }\n\n // Determine whether to include transaction hash (default: false for privacy)\n const includeTxHash = config?.includeTxHash === true;\n\n try {\n const signedReceipt: SignedReceipt = await issuer.issueReceipt(\n resourceUrl,\n payer,\n network,\n includeTxHash ? transaction || undefined : undefined,\n );\n // Return extension data per spec structure\n return {\n info: {\n receipt: signedReceipt,\n },\n schema: RECEIPT_SCHEMA,\n };\n } catch (error) {\n console.error(\"[offer-receipt] Failed to sign receipt:\", error);\n return undefined;\n }\n },\n };\n}\n\n/**\n * Declare offer-receipt extension for a route\n *\n * Use this in route configuration to enable offer-receipt for a specific endpoint.\n *\n * @param config - Optional configuration for the extension\n * @returns Extension declaration object to spread into route config\n */\nexport function declareOfferReceiptExtension(\n config?: OfferReceiptDeclaration,\n): Record<string, OfferReceiptDeclaration> {\n return {\n [OFFER_RECEIPT]: {\n includeTxHash: config?.includeTxHash,\n offerValiditySeconds: config?.offerValiditySeconds,\n },\n };\n}\n\n// ============================================================================\n// Issuer Factory Functions\n// ============================================================================\n\n/**\n * Create an OfferReceiptIssuer that uses JWS format\n *\n * @param kid - Key identifier DID (e.g., did:web:api.example.com#key-1)\n * @param jwsSigner - JWS signer with sign() function and algorithm\n * @returns OfferReceiptIssuer for use with createOfferReceiptExtension\n */\nexport function createJWSOfferReceiptIssuer(kid: string, jwsSigner: JWSSigner): OfferReceiptIssuer {\n return {\n kid,\n format: \"jws\",\n\n async issueOffer(resourceUrl: string, input: OfferInput) {\n return createOfferJWS(resourceUrl, input, jwsSigner);\n },\n\n async issueReceipt(resourceUrl: string, payer: string, network: string, transaction?: string) {\n return createReceiptJWS({ resourceUrl, payer, network, transaction }, jwsSigner);\n },\n };\n}\n\n/**\n * Create an OfferReceiptIssuer that uses EIP-712 format\n *\n * @param kid - Key identifier DID (e.g., did:pkh:eip155:1:0x...)\n * @param signTypedData - Function to sign EIP-712 typed data\n * @returns OfferReceiptIssuer for use with createOfferReceiptExtension\n */\nexport function createEIP712OfferReceiptIssuer(\n kid: string,\n signTypedData: SignTypedDataFn,\n): OfferReceiptIssuer {\n return {\n kid,\n format: \"eip712\",\n\n async issueOffer(resourceUrl: string, input: OfferInput) {\n return createOfferEIP712(resourceUrl, input, signTypedData);\n },\n\n async issueReceipt(resourceUrl: string, payer: string, network: string, transaction?: string) {\n return createReceiptEIP712({ resourceUrl, payer, network, transaction }, signTypedData);\n },\n };\n}\n","/**\n * Client-side utilities for extracting offers and receipts from x402 responses\n *\n * Provides utilities for clients who want to access signed offers and receipts\n * from x402 payment flows. Useful for verified reviews, audit trails, and dispute resolution.\n *\n * @see README.md for usage examples (raw and wrapper flows)\n * @see examples/typescript/clients/offer-receipt/ for complete example\n */\n\nimport { decodePaymentResponseHeader } from \"@x402/core/http\";\nimport type { PaymentRequired, PaymentRequirements, SettleResponse } from \"@x402/core/types\";\nimport { OFFER_RECEIPT, type OfferPayload, type SignedOffer, type SignedReceipt } from \"./types\";\nimport { extractOfferPayload, extractReceiptPayload } from \"./signing\";\n\n/**\n * A signed offer with its decoded payload fields at the top level.\n * Combines the signed offer metadata with the decoded payload for easy access.\n */\nexport interface DecodedOffer extends OfferPayload {\n /** The original signed offer (for passing to other functions or downstream systems) */\n signedOffer: SignedOffer;\n /** The signature format used */\n format: \"jws\" | \"eip712\";\n /** Index into accepts[] array (hint for matching), may be undefined */\n acceptIndex?: number;\n}\n\n/**\n * Structure of offer-receipt extension data in PaymentRequired.extensions\n */\ninterface OfferReceiptExtensionInfo {\n info?: {\n offers?: SignedOffer[];\n receipt?: SignedReceipt;\n };\n}\n\n// ============================================================================\n// Exported Functions\n// ============================================================================\n\n/**\n * Verify that a receipt's payload matches the offer and payer.\n *\n * This performs basic payload field verification:\n * - resourceUrl matches the offer\n * - network matches the offer\n * - payer matches one of the client's wallet addresses\n * - issuedAt is recent (within maxAgeSeconds)\n *\n * NOTE: This does NOT verify the signature or key binding. See the comment\n * in the offer-receipt example for guidance on full verification.\n *\n * @param receipt - The signed receipt from the server\n * @param offer - The decoded offer that was accepted\n * @param payerAddresses - Array of the client's wallet addresses (EVM, SVM, etc.)\n * @param maxAgeSeconds - Maximum age of receipt in seconds (default: 3600 = 1 hour)\n * @returns true if all checks pass, false otherwise\n */\nexport function verifyReceiptMatchesOffer(\n receipt: SignedReceipt,\n offer: DecodedOffer,\n payerAddresses: string[],\n maxAgeSeconds: number = 3600,\n): boolean {\n const payload = extractReceiptPayload(receipt);\n\n const resourceUrlMatch = payload.resourceUrl === offer.resourceUrl;\n const networkMatch = payload.network === offer.network;\n const payerMatch = payerAddresses.some(\n addr => payload.payer.toLowerCase() === addr.toLowerCase(),\n );\n const issuedRecently = Math.floor(Date.now() / 1000) - payload.issuedAt < maxAgeSeconds;\n\n return resourceUrlMatch && networkMatch && payerMatch && issuedRecently;\n}\n\n/**\n * Extract signed offers from a PaymentRequired response.\n *\n * Call this immediately after receiving a 402 response to save the offers.\n * If the settlement response doesn't include a receipt, you'll still have\n * the offers for attestation purposes.\n *\n * @param paymentRequired - The PaymentRequired object from the 402 response\n * @returns Array of signed offers, or empty array if none present\n */\nexport function extractOffersFromPaymentRequired(paymentRequired: PaymentRequired): SignedOffer[] {\n const extData = paymentRequired.extensions?.[OFFER_RECEIPT] as\n | OfferReceiptExtensionInfo\n | undefined;\n return extData?.info?.offers ?? [];\n}\n\n/**\n * Decode all signed offers and return them with payload fields at the top level.\n *\n * Use this to inspect offer details (network, amount, etc.) for selection.\n * JWS decoding is cheap (base64 decode, no crypto), so decoding all offers\n * upfront is fine even with multiple offers.\n *\n * @param offers - Array of signed offers from extractOffersFromPaymentRequired\n * @returns Array of decoded offers with payload fields at top level\n */\nexport function decodeSignedOffers(offers: SignedOffer[]): DecodedOffer[] {\n return offers.map(offer => {\n const payload = extractOfferPayload(offer);\n return {\n // Spread payload fields at top level\n ...payload,\n // Include metadata\n signedOffer: offer,\n format: offer.format,\n acceptIndex: offer.acceptIndex,\n };\n });\n}\n\n/**\n * Find the accepts[] entry that matches a signed or decoded offer.\n *\n * Use this after selecting an offer to get the PaymentRequirements\n * object needed for createPaymentPayload.\n *\n * Uses the offer's acceptIndex as a hint for faster lookup, but verifies\n * the payload matches in case indices got out of sync.\n *\n * @param offer - A DecodedOffer (from decodeSignedOffers) or SignedOffer\n * @param accepts - Array of payment requirements from paymentRequired.accepts\n * @returns The matching PaymentRequirements, or undefined if not found\n */\nexport function findAcceptsObjectFromSignedOffer(\n offer: DecodedOffer | SignedOffer,\n accepts: PaymentRequirements[],\n): PaymentRequirements | undefined {\n // Check if it's a DecodedOffer (has signedOffer property) or SignedOffer\n const isDecoded = \"signedOffer\" in offer;\n const payload = isDecoded ? offer : extractOfferPayload(offer);\n const acceptIndex = isDecoded ? offer.acceptIndex : offer.acceptIndex;\n\n // Use acceptIndex as a hint - check that index first\n if (acceptIndex !== undefined && acceptIndex < accepts.length) {\n const hinted = accepts[acceptIndex];\n if (\n hinted.network === payload.network &&\n hinted.scheme === payload.scheme &&\n hinted.asset === payload.asset &&\n hinted.payTo === payload.payTo &&\n hinted.amount === payload.amount\n ) {\n return hinted;\n }\n }\n\n // Fall back to searching all accepts\n return accepts.find(\n req =>\n req.network === payload.network &&\n req.scheme === payload.scheme &&\n req.asset === payload.asset &&\n req.payTo === payload.payTo &&\n req.amount === payload.amount,\n );\n}\n\n/**\n * Extract signed receipt from a successful payment response.\n *\n * Call this after a successful payment to get the server's signed receipt.\n * The receipt proves the service was delivered after payment.\n *\n * @param response - The Response object from the successful request\n * @returns The signed receipt, or undefined if not present\n */\nexport function extractReceiptFromResponse(response: Response): SignedReceipt | undefined {\n const paymentResponseHeader =\n response.headers.get(\"PAYMENT-RESPONSE\") || response.headers.get(\"X-PAYMENT-RESPONSE\");\n\n if (!paymentResponseHeader) {\n return undefined;\n }\n\n try {\n const settlementResponse = decodePaymentResponseHeader(paymentResponseHeader) as SettleResponse;\n const receiptExtData = settlementResponse.extensions?.[OFFER_RECEIPT] as\n | OfferReceiptExtensionInfo\n | undefined;\n return receiptExtData?.info?.receipt;\n } catch {\n return undefined;\n }\n}\n"],"mappings":"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","names":["jose","m"]}
@@ -1,9 +1,12 @@
1
1
  export { k as BAZAAR, A as BazaarClientExtension, c as BodyDiscoveryExtension, B as BodyDiscoveryInfo, g as DeclareBodyDiscoveryExtensionConfig, i as DeclareDiscoveryExtensionConfig, j as DeclareDiscoveryExtensionInput, h as DeclareMcpDiscoveryExtensionConfig, f as DeclareQueryDiscoveryExtensionConfig, s as DiscoveredHTTPResource, t as DiscoveredMCPResource, u as DiscoveredResource, e as DiscoveryExtension, D as DiscoveryInfo, C as DiscoveryResource, E as DiscoveryResourcesResponse, L as ListDiscoveryResourcesParams, d as McpDiscoveryExtension, M as McpDiscoveryInfo, a as QueryDiscoveryExtension, Q as QueryDiscoveryInfo, V as ValidationResult, W as WithExtensions, b as bazaarResourceServerExtension, o as declareDiscoveryExtension, p as extractDiscoveryInfo, q as extractDiscoveryInfoFromExtension, w as extractDiscoveryInfoV1, y as extractResourceMetadataV1, n as isBodyExtensionConfig, x as isDiscoverableV1, l as isMcpExtensionConfig, m as isQueryExtensionConfig, r as validateAndExtract, v as validateDiscoveryExtension, z as withBazaar } from './index-CtOzXcjN.mjs';
2
2
  export { CompleteSIWxInfo, CreateSIWxHookOptions, DeclareSIWxOptions, EVMMessageVerifier, EVMSigner, InMemorySIWxStorage, SIGN_IN_WITH_X, SIWxExtension, SIWxExtensionInfo, SIWxExtensionSchema, SIWxHookEvent, SIWxPayload, SIWxPayloadSchema, SIWxSigner, SIWxStorage, SIWxValidationOptions, SIWxValidationResult, SIWxVerifyOptions, SIWxVerifyResult, SOLANA_DEVNET, SOLANA_MAINNET, SOLANA_TESTNET, SignatureScheme, SignatureType, SolanaSigner, SupportedChain, buildSIWxSchema, createSIWxClientHook, createSIWxMessage, createSIWxPayload, createSIWxRequestHook, createSIWxSettleHook, declareSIWxExtension, decodeBase58, encodeBase58, encodeSIWxHeader, extractEVMChainId, extractSolanaChainReference, formatSIWEMessage, formatSIWSMessage, getEVMAddress, getSolanaAddress, isEVMSigner, isSolanaSigner, parseSIWxHeader, signEVMMessage, signSolanaMessage, siwxResourceServerExtension, validateSIWxMessage, verifyEVMSignature, verifySIWxSignature, verifySolanaSignature, wrapFetchWithSIWx } from './sign-in-with-x/index.mjs';
3
+ export { DecodedOffer, EIP712SignedOffer, EIP712SignedReceipt, EIP712Signer, EIP712VerificationResult, JWSSignedOffer, JWSSignedReceipt, JWSSigner, OFFER_RECEIPT, OFFER_TYPES, OfferInput, OfferPayload, OfferReceiptDeclaration, OfferReceiptIssuer, RECEIPT_TYPES, ReceiptInput, ReceiptPayload, SignTypedDataFn, SignatureFormat, SignedOffer, SignedReceipt, Signer, canonicalize, convertNetworkStringToCAIP2, createEIP712OfferReceiptIssuer, createJWS, createJWSOfferReceiptIssuer, createOfferDomain, createOfferEIP712, createOfferJWS, createOfferReceiptExtension, createReceiptDomain, createReceiptEIP712, createReceiptJWS, declareOfferReceiptExtension, decodeSignedOffers, extractChainIdFromCAIP2, extractEIP155ChainId, extractJWSHeader, extractJWSPayload, extractOfferPayload, extractOffersFromPaymentRequired, extractPublicKeyFromKid, extractReceiptFromResponse, extractReceiptPayload, findAcceptsObjectFromSignedOffer, getCanonicalBytes, hashCanonical, hashOfferTypedData, hashReceiptTypedData, isEIP712SignedOffer, isEIP712SignedReceipt, isEIP712Signer, isJWSSignedOffer, isJWSSignedReceipt, isJWSSigner, prepareOfferForEIP712, prepareReceiptForEIP712, signOfferEIP712, signReceiptEIP712, verifyOfferSignatureEIP712, verifyOfferSignatureJWS, verifyReceiptMatchesOffer, verifyReceiptSignatureEIP712, verifyReceiptSignatureJWS } from './offer-receipt/index.mjs';
3
4
  export { PAYMENT_IDENTIFIER, PAYMENT_ID_MAX_LENGTH, PAYMENT_ID_MIN_LENGTH, PAYMENT_ID_PATTERN, PaymentIdentifierExtension, PaymentIdentifierInfo, PaymentIdentifierSchema, PaymentIdentifierValidationResult, appendPaymentIdentifierToExtensions, declarePaymentIdentifierExtension, extractAndValidatePaymentIdentifier, extractPaymentIdentifier, generatePaymentId, hasPaymentIdentifier, isPaymentIdentifierExtension, isPaymentIdentifierRequired, isValidPaymentId, paymentIdentifierResourceServerExtension, paymentIdentifierSchema, validatePaymentIdentifier, validatePaymentIdentifierRequirement } from './payment-identifier/index.mjs';
4
5
  import { FacilitatorExtension, PaymentPayload } from '@x402/core/types';
5
6
  import '@x402/core/http';
6
7
  import 'zod';
8
+ import 'jose';
9
+ import 'viem';
7
10
 
8
11
  /**
9
12
  * Type definitions for the EIP-2612 Gas Sponsoring Extension
@@ -140,13 +143,23 @@ declare function validateEip2612GasSponsoringInfo(info: Eip2612GasSponsoringInfo
140
143
  * it atomically before settling the Permit2 payment.
141
144
  */
142
145
 
146
+ /**
147
+ * A single transaction to be executed by the signer.
148
+ * - `0x${string}`: a pre-signed serialized transaction (broadcast as-is via sendRawTransaction)
149
+ * - `{ to, data, gas? }`: an unsigned call intent (signer signs and broadcasts)
150
+ */
151
+ type TransactionRequest = `0x${string}` | {
152
+ to: `0x${string}`;
153
+ data: `0x${string}`;
154
+ gas?: bigint;
155
+ };
143
156
  /**
144
157
  * Signer capability carried by the ERC-20 approval extension when registered in a facilitator.
145
158
  *
146
- * Mirrors FacilitatorEvmSigner (from @x402/evm) plus `sendRawTransaction`.
147
- * The extension signer owns the full approve+settle flow: it broadcasts the
148
- * pre-signed approval transaction AND executes the Permit2 settle call, enabling
149
- * production implementations to bundle both atomically (e.g., Flashbots, multicall).
159
+ * Mirrors FacilitatorEvmSigner (from @x402/evm) plus `sendTransactions`.
160
+ * The signer owns execution of multiple transactions, enabling production implementations
161
+ * to bundle them atomically (e.g., Flashbots, multicall, smart account batching)
162
+ * while simpler implementations can execute them sequentially.
150
163
  *
151
164
  * The method signatures are duplicated here (rather than extending FacilitatorEvmSigner)
152
165
  * to avoid a circular dependency between @x402/extensions and @x402/evm.
@@ -172,6 +185,7 @@ interface Erc20ApprovalGasSponsoringSigner {
172
185
  abi: readonly unknown[];
173
186
  functionName: string;
174
187
  args: readonly unknown[];
188
+ gas?: bigint;
175
189
  }): Promise<`0x${string}`>;
176
190
  sendTransaction(args: {
177
191
  to: `0x${string}`;
@@ -185,9 +199,7 @@ interface Erc20ApprovalGasSponsoringSigner {
185
199
  getCode(args: {
186
200
  address: `0x${string}`;
187
201
  }): Promise<`0x${string}` | undefined>;
188
- sendRawTransaction(args: {
189
- serializedTransaction: `0x${string}`;
190
- }): Promise<`0x${string}`>;
202
+ sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>;
191
203
  }
192
204
  /**
193
205
  * Extension identifier for the ERC-20 approval gas sponsoring extension.
@@ -200,41 +212,39 @@ declare const ERC20_APPROVAL_GAS_SPONSORING_VERSION = "1";
200
212
  /**
201
213
  * Extended extension object registered in a facilitator via registerExtension().
202
214
  * Carries the signer that owns the full approve+settle flow for ERC-20 tokens
203
- * that lack EIP-2612. The signer must have all FacilitatorEvmSigner capabilities
204
- * plus `sendRawTransaction` for broadcasting the pre-signed approval tx.
215
+ * that lack EIP-2612.
205
216
  *
206
217
  * @example
207
218
  * ```typescript
208
219
  * import { createErc20ApprovalGasSponsoringExtension } from '@x402/extensions';
209
220
  *
210
221
  * facilitator.registerExtension(
211
- * createErc20ApprovalGasSponsoringExtension(evmSigner, viemClient),
222
+ * createErc20ApprovalGasSponsoringExtension(signer),
212
223
  * );
213
224
  * ```
214
225
  */
215
226
  interface Erc20ApprovalGasSponsoringFacilitatorExtension extends FacilitatorExtension {
216
227
  key: "erc20ApprovalGasSponsoring";
217
- /** Signer with broadcast + settle capability. Optional — settlement fails gracefully if absent. */
228
+ /** Default signer with approve+settle capability. Optional — settlement fails gracefully if absent. */
218
229
  signer?: Erc20ApprovalGasSponsoringSigner;
230
+ /** Network-specific signer resolver. Takes precedence over `signer` when provided. */
231
+ signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined;
219
232
  }
220
233
  /**
221
- * Signer input for {@link createErc20ApprovalGasSponsoringExtension}.
234
+ * Base signer shape without `sendTransactions`.
222
235
  * Matches the FacilitatorEvmSigner shape from @x402/evm (duplicated to avoid circular dep).
223
236
  */
224
- type Erc20ApprovalGasSponsoringBaseSigner = Omit<Erc20ApprovalGasSponsoringSigner, "sendRawTransaction">;
237
+ type Erc20ApprovalGasSponsoringBaseSigner = Omit<Erc20ApprovalGasSponsoringSigner, "sendTransactions">;
225
238
  /**
226
239
  * Create an ERC-20 approval gas sponsoring extension ready to register in a facilitator.
227
240
  *
228
- * @param signer - The EVM facilitator signer (e.g. from `toFacilitatorEvmSigner()`)
229
- * @param client - Object providing `sendRawTransaction` (e.g. a viem WalletClient)
230
- * @param client.sendRawTransaction - Broadcasts a signed transaction to the network
241
+ * @param signer - A complete signer with `sendTransactions` already implemented.
242
+ * The signer decides how to execute the transactions (sequentially, batched, or atomically).
243
+ * @param signerForNetwork - Optional network-specific signer resolver. When provided,
244
+ * takes precedence over `signer` and allows different settlement signers per network.
231
245
  * @returns A fully configured extension to pass to `facilitator.registerExtension()`
232
246
  */
233
- declare function createErc20ApprovalGasSponsoringExtension(signer: Erc20ApprovalGasSponsoringBaseSigner, client: {
234
- sendRawTransaction: (args: {
235
- serializedTransaction: `0x${string}`;
236
- }) => Promise<`0x${string}`>;
237
- }): Erc20ApprovalGasSponsoringFacilitatorExtension;
247
+ declare function createErc20ApprovalGasSponsoringExtension(signer: Erc20ApprovalGasSponsoringSigner, signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined): Erc20ApprovalGasSponsoringFacilitatorExtension;
238
248
  /**
239
249
  * ERC-20 approval gas sponsoring info populated by the client.
240
250
  *
@@ -357,4 +367,4 @@ declare function extractErc20ApprovalGasSponsoringInfo(paymentPayload: PaymentPa
357
367
  */
358
368
  declare function validateErc20ApprovalGasSponsoringInfo(info: Erc20ApprovalGasSponsoringInfo): boolean;
359
369
 
360
- export { EIP2612_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING_VERSION, type Eip2612GasSponsoringExtension, type Eip2612GasSponsoringInfo, type Eip2612GasSponsoringServerInfo, type Erc20ApprovalGasSponsoringBaseSigner, type Erc20ApprovalGasSponsoringExtension, type Erc20ApprovalGasSponsoringFacilitatorExtension, type Erc20ApprovalGasSponsoringInfo, type Erc20ApprovalGasSponsoringServerInfo, type Erc20ApprovalGasSponsoringSigner, createErc20ApprovalGasSponsoringExtension, declareEip2612GasSponsoringExtension, declareErc20ApprovalGasSponsoringExtension, erc20ApprovalGasSponsoringSchema, extractEip2612GasSponsoringInfo, extractErc20ApprovalGasSponsoringInfo, validateEip2612GasSponsoringInfo, validateErc20ApprovalGasSponsoringInfo };
370
+ export { EIP2612_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING, ERC20_APPROVAL_GAS_SPONSORING_VERSION, type Eip2612GasSponsoringExtension, type Eip2612GasSponsoringInfo, type Eip2612GasSponsoringServerInfo, type Erc20ApprovalGasSponsoringBaseSigner, type Erc20ApprovalGasSponsoringExtension, type Erc20ApprovalGasSponsoringFacilitatorExtension, type Erc20ApprovalGasSponsoringInfo, type Erc20ApprovalGasSponsoringServerInfo, type Erc20ApprovalGasSponsoringSigner, type TransactionRequest, createErc20ApprovalGasSponsoringExtension, declareEip2612GasSponsoringExtension, declareErc20ApprovalGasSponsoringExtension, erc20ApprovalGasSponsoringSchema, extractEip2612GasSponsoringInfo, extractErc20ApprovalGasSponsoringInfo, validateEip2612GasSponsoringInfo, validateErc20ApprovalGasSponsoringInfo };
@@ -48,7 +48,55 @@ import {
48
48
  verifySIWxSignature,
49
49
  verifySolanaSignature,
50
50
  wrapFetchWithSIWx
51
- } from "./chunk-O34SGKEP.mjs";
51
+ } from "./chunk-QVNCC7CH.mjs";
52
+ import {
53
+ OFFER_RECEIPT,
54
+ OFFER_TYPES,
55
+ RECEIPT_TYPES,
56
+ canonicalize,
57
+ convertNetworkStringToCAIP2,
58
+ createEIP712OfferReceiptIssuer,
59
+ createJWS,
60
+ createJWSOfferReceiptIssuer,
61
+ createOfferDomain,
62
+ createOfferEIP712,
63
+ createOfferJWS,
64
+ createOfferReceiptExtension,
65
+ createReceiptDomain,
66
+ createReceiptEIP712,
67
+ createReceiptJWS,
68
+ declareOfferReceiptExtension,
69
+ decodeSignedOffers,
70
+ extractChainIdFromCAIP2,
71
+ extractEIP155ChainId,
72
+ extractJWSHeader,
73
+ extractJWSPayload,
74
+ extractOfferPayload,
75
+ extractOffersFromPaymentRequired,
76
+ extractPublicKeyFromKid,
77
+ extractReceiptFromResponse,
78
+ extractReceiptPayload,
79
+ findAcceptsObjectFromSignedOffer,
80
+ getCanonicalBytes,
81
+ hashCanonical,
82
+ hashOfferTypedData,
83
+ hashReceiptTypedData,
84
+ isEIP712SignedOffer,
85
+ isEIP712SignedReceipt,
86
+ isEIP712Signer,
87
+ isJWSSignedOffer,
88
+ isJWSSignedReceipt,
89
+ isJWSSigner,
90
+ prepareOfferForEIP712,
91
+ prepareReceiptForEIP712,
92
+ signOfferEIP712,
93
+ signReceiptEIP712,
94
+ verifyOfferSignatureEIP712,
95
+ verifyOfferSignatureJWS,
96
+ verifyReceiptMatchesOffer,
97
+ verifyReceiptSignatureEIP712,
98
+ verifyReceiptSignatureJWS
99
+ } from "./chunk-TYR4QHVX.mjs";
52
100
  import {
53
101
  PAYMENT_IDENTIFIER,
54
102
  PAYMENT_ID_MAX_LENGTH,
@@ -161,14 +209,8 @@ var ERC20_APPROVAL_GAS_SPONSORING = {
161
209
  key: "erc20ApprovalGasSponsoring"
162
210
  };
163
211
  var ERC20_APPROVAL_GAS_SPONSORING_VERSION = "1";
164
- function createErc20ApprovalGasSponsoringExtension(signer, client) {
165
- return {
166
- ...ERC20_APPROVAL_GAS_SPONSORING,
167
- signer: {
168
- ...signer,
169
- sendRawTransaction: client.sendRawTransaction.bind(client)
170
- }
171
- };
212
+ function createErc20ApprovalGasSponsoringExtension(signer, signerForNetwork) {
213
+ return { ...ERC20_APPROVAL_GAS_SPONSORING, signer, signerForNetwork };
172
214
  }
173
215
 
174
216
  // src/erc20-approval-gas-sponsoring/resourceService.ts
@@ -249,10 +291,13 @@ export {
249
291
  ERC20_APPROVAL_GAS_SPONSORING,
250
292
  ERC20_APPROVAL_GAS_SPONSORING_VERSION,
251
293
  InMemorySIWxStorage,
294
+ OFFER_RECEIPT,
295
+ OFFER_TYPES,
252
296
  PAYMENT_IDENTIFIER,
253
297
  PAYMENT_ID_MAX_LENGTH,
254
298
  PAYMENT_ID_MIN_LENGTH,
255
299
  PAYMENT_ID_PATTERN,
300
+ RECEIPT_TYPES,
256
301
  SIGN_IN_WITH_X,
257
302
  SIWxPayloadSchema,
258
303
  SOLANA_DEVNET,
@@ -261,7 +306,19 @@ export {
261
306
  appendPaymentIdentifierToExtensions,
262
307
  bazaarResourceServerExtension,
263
308
  buildSIWxSchema,
309
+ canonicalize,
310
+ convertNetworkStringToCAIP2,
311
+ createEIP712OfferReceiptIssuer,
264
312
  createErc20ApprovalGasSponsoringExtension,
313
+ createJWS,
314
+ createJWSOfferReceiptIssuer,
315
+ createOfferDomain,
316
+ createOfferEIP712,
317
+ createOfferJWS,
318
+ createOfferReceiptExtension,
319
+ createReceiptDomain,
320
+ createReceiptEIP712,
321
+ createReceiptJWS,
265
322
  createSIWxClientHook,
266
323
  createSIWxMessage,
267
324
  createSIWxPayload,
@@ -270,31 +327,53 @@ export {
270
327
  declareDiscoveryExtension,
271
328
  declareEip2612GasSponsoringExtension,
272
329
  declareErc20ApprovalGasSponsoringExtension,
330
+ declareOfferReceiptExtension,
273
331
  declarePaymentIdentifierExtension,
274
332
  declareSIWxExtension,
275
333
  decodeBase58,
334
+ decodeSignedOffers,
276
335
  encodeBase58,
277
336
  encodeSIWxHeader,
278
337
  erc20ApprovalGasSponsoringSchema,
279
338
  extractAndValidatePaymentIdentifier,
339
+ extractChainIdFromCAIP2,
280
340
  extractDiscoveryInfo,
281
341
  extractDiscoveryInfoFromExtension,
282
342
  extractDiscoveryInfoV1,
343
+ extractEIP155ChainId,
283
344
  extractEVMChainId,
284
345
  extractEip2612GasSponsoringInfo,
285
346
  extractErc20ApprovalGasSponsoringInfo,
347
+ extractJWSHeader,
348
+ extractJWSPayload,
349
+ extractOfferPayload,
350
+ extractOffersFromPaymentRequired,
286
351
  extractPaymentIdentifier,
352
+ extractPublicKeyFromKid,
353
+ extractReceiptFromResponse,
354
+ extractReceiptPayload,
287
355
  extractResourceMetadataV1,
288
356
  extractSolanaChainReference,
357
+ findAcceptsObjectFromSignedOffer,
289
358
  formatSIWEMessage,
290
359
  formatSIWSMessage,
291
360
  generatePaymentId,
361
+ getCanonicalBytes,
292
362
  getEVMAddress,
293
363
  getSolanaAddress,
294
364
  hasPaymentIdentifier,
365
+ hashCanonical,
366
+ hashOfferTypedData,
367
+ hashReceiptTypedData,
295
368
  isBodyExtensionConfig,
296
369
  isDiscoverableV1,
370
+ isEIP712SignedOffer,
371
+ isEIP712SignedReceipt,
372
+ isEIP712Signer,
297
373
  isEVMSigner,
374
+ isJWSSignedOffer,
375
+ isJWSSignedReceipt,
376
+ isJWSSigner,
298
377
  isMcpExtensionConfig,
299
378
  isPaymentIdentifierExtension,
300
379
  isPaymentIdentifierRequired,
@@ -304,7 +383,11 @@ export {
304
383
  parseSIWxHeader,
305
384
  paymentIdentifierResourceServerExtension,
306
385
  paymentIdentifierSchema,
386
+ prepareOfferForEIP712,
387
+ prepareReceiptForEIP712,
307
388
  signEVMMessage,
389
+ signOfferEIP712,
390
+ signReceiptEIP712,
308
391
  signSolanaMessage,
309
392
  siwxResourceServerExtension,
310
393
  validateAndExtract,
@@ -315,6 +398,11 @@ export {
315
398
  validatePaymentIdentifierRequirement,
316
399
  validateSIWxMessage,
317
400
  verifyEVMSignature,
401
+ verifyOfferSignatureEIP712,
402
+ verifyOfferSignatureJWS,
403
+ verifyReceiptMatchesOffer,
404
+ verifyReceiptSignatureEIP712,
405
+ verifyReceiptSignatureJWS,
318
406
  verifySIWxSignature,
319
407
  verifySolanaSignature,
320
408
  withBazaar,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/eip2612-gas-sponsoring/types.ts","../../src/eip2612-gas-sponsoring/resourceService.ts","../../src/eip2612-gas-sponsoring/facilitator.ts","../../src/erc20-approval-gas-sponsoring/types.ts","../../src/erc20-approval-gas-sponsoring/resourceService.ts","../../src/erc20-approval-gas-sponsoring/facilitator.ts"],"sourcesContent":["/**\n * Type definitions for the EIP-2612 Gas Sponsoring Extension\n *\n * This extension enables gasless approval of the Permit2 contract for tokens\n * that implement EIP-2612. The client signs an off-chain permit, and the\n * facilitator submits it on-chain via `x402Permit2Proxy.settleWithPermit`.\n */\n\nimport type { FacilitatorExtension } from \"@x402/core/types\";\n\n/**\n * Extension identifier for the EIP-2612 gas sponsoring extension.\n */\nexport const EIP2612_GAS_SPONSORING: FacilitatorExtension = { key: \"eip2612GasSponsoring\" };\n\n/**\n * EIP-2612 gas sponsoring info populated by the client.\n *\n * Contains the EIP-2612 permit signature and parameters that the facilitator\n * needs to call `x402Permit2Proxy.settleWithPermit`.\n */\nexport interface Eip2612GasSponsoringInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** The address of the sender (token owner). */\n from: string;\n /** The address of the ERC-20 token contract. */\n asset: string;\n /** The address of the spender (Canonical Permit2). */\n spender: string;\n /** The amount to approve (uint256 as decimal string). Typically MaxUint256. */\n amount: string;\n /** The current EIP-2612 nonce of the sender (decimal string). */\n nonce: string;\n /** The timestamp at which the permit signature expires (decimal string). */\n deadline: string;\n /** The 65-byte concatenated EIP-2612 permit signature (r, s, v) as a hex string. */\n signature: string;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * Server-side EIP-2612 gas sponsoring info included in PaymentRequired.\n * Contains a description and version; the client populates the rest.\n */\nexport interface Eip2612GasSponsoringServerInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** Human-readable description of the extension. */\n description: string;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * The full extension object as it appears in PaymentRequired.extensions\n * and PaymentPayload.extensions.\n */\nexport interface Eip2612GasSponsoringExtension {\n /** Extension info - server-provided or client-enriched. */\n info: Eip2612GasSponsoringServerInfo | Eip2612GasSponsoringInfo;\n /** JSON Schema describing the expected structure of info. */\n schema: Record<string, unknown>;\n}\n","/**\n * Resource Service functions for declaring the EIP-2612 Gas Sponsoring extension.\n *\n * These functions help servers declare support for EIP-2612 gasless Permit2 approvals\n * in the PaymentRequired response extensions.\n */\n\nimport { EIP2612_GAS_SPONSORING, type Eip2612GasSponsoringExtension } from \"./types\";\n\n/**\n * The JSON Schema for the EIP-2612 gas sponsoring extension info.\n * Matches the schema defined in the spec.\n */\nconst eip2612GasSponsoringSchema: Record<string, unknown> = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n from: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the sender.\",\n },\n asset: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the ERC-20 token contract.\",\n },\n spender: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the spender (Canonical Permit2).\",\n },\n amount: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The amount to approve (uint256). Typically MaxUint.\",\n },\n nonce: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The current nonce of the sender.\",\n },\n deadline: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The timestamp at which the signature expires.\",\n },\n signature: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]+$\",\n description: \"The 65-byte concatenated signature (r, s, v) as a hex string.\",\n },\n version: {\n type: \"string\",\n pattern: \"^[0-9]+(\\\\.[0-9]+)*$\",\n description: \"Schema version identifier.\",\n },\n },\n required: [\"from\", \"asset\", \"spender\", \"amount\", \"nonce\", \"deadline\", \"signature\", \"version\"],\n};\n\n/**\n * Declares the EIP-2612 gas sponsoring extension for inclusion in\n * PaymentRequired.extensions.\n *\n * The server advertises that it (or its facilitator) supports EIP-2612\n * gasless Permit2 approval. The client will populate the info with the\n * actual permit signature data.\n *\n * @returns An object keyed by the extension identifier containing the extension declaration\n *\n * @example\n * ```typescript\n * import { declareEip2612GasSponsoringExtension } from '@x402/extensions';\n *\n * const routes = [\n * {\n * path: \"/api/data\",\n * price: \"$0.01\",\n * extensions: {\n * ...declareEip2612GasSponsoringExtension(),\n * },\n * },\n * ];\n * ```\n */\nexport function declareEip2612GasSponsoringExtension(): Record<\n string,\n Eip2612GasSponsoringExtension\n> {\n const key = EIP2612_GAS_SPONSORING.key;\n return {\n [key]: {\n info: {\n description:\n \"The facilitator accepts EIP-2612 gasless Permit to `Permit2` canonical contract.\",\n version: \"1\",\n },\n schema: eip2612GasSponsoringSchema,\n },\n };\n}\n","/**\n * Facilitator functions for extracting and validating EIP-2612 Gas Sponsoring extension data.\n *\n * These functions help facilitators extract the EIP-2612 permit data from payment\n * payloads and validate it before calling settleWithPermit.\n */\n\nimport type { PaymentPayload } from \"@x402/core/types\";\nimport {\n EIP2612_GAS_SPONSORING,\n type Eip2612GasSponsoringInfo,\n type Eip2612GasSponsoringExtension,\n} from \"./types\";\n\n/**\n * Extracts the EIP-2612 gas sponsoring info from a payment payload's extensions.\n *\n * Returns the info if the extension is present and contains the required client-populated\n * fields (from, asset, spender, amount, nonce, deadline, signature, version).\n *\n * @param paymentPayload - The payment payload to extract from\n * @returns The EIP-2612 gas sponsoring info, or null if not present\n */\nexport function extractEip2612GasSponsoringInfo(\n paymentPayload: PaymentPayload,\n): Eip2612GasSponsoringInfo | null {\n if (!paymentPayload.extensions) {\n return null;\n }\n\n const extension = paymentPayload.extensions[EIP2612_GAS_SPONSORING.key] as\n | Eip2612GasSponsoringExtension\n | undefined;\n\n if (!extension?.info) {\n return null;\n }\n\n const info = extension.info as Record<string, unknown>;\n\n // Check that the client has populated the required fields\n if (\n !info.from ||\n !info.asset ||\n !info.spender ||\n !info.amount ||\n !info.nonce ||\n !info.deadline ||\n !info.signature ||\n !info.version\n ) {\n return null;\n }\n\n return info as unknown as Eip2612GasSponsoringInfo;\n}\n\n/**\n * Validates that the EIP-2612 gas sponsoring info has valid format.\n *\n * Performs basic validation on the info fields:\n * - Addresses are valid hex (0x + 40 hex chars)\n * - Amount, nonce, deadline are numeric strings\n * - Signature is a hex string\n * - Version is a numeric version string\n *\n * @param info - The EIP-2612 gas sponsoring info to validate\n * @returns True if the info is valid, false otherwise\n */\nexport function validateEip2612GasSponsoringInfo(info: Eip2612GasSponsoringInfo): boolean {\n const addressPattern = /^0x[a-fA-F0-9]{40}$/;\n const numericPattern = /^[0-9]+$/;\n const hexPattern = /^0x[a-fA-F0-9]+$/;\n const versionPattern = /^[0-9]+(\\.[0-9]+)*$/;\n\n return (\n addressPattern.test(info.from) &&\n addressPattern.test(info.asset) &&\n addressPattern.test(info.spender) &&\n numericPattern.test(info.amount) &&\n numericPattern.test(info.nonce) &&\n numericPattern.test(info.deadline) &&\n hexPattern.test(info.signature) &&\n versionPattern.test(info.version)\n );\n}\n","/**\n * Type definitions for the ERC-20 Approval Gas Sponsoring Extension\n *\n * This extension enables gasless Permit2 approval for generic ERC-20 tokens\n * that do NOT implement EIP-2612. The client signs (but does not broadcast) a\n * raw `approve(Permit2, MaxUint256)` transaction, and the facilitator broadcasts\n * it atomically before settling the Permit2 payment.\n */\n\nimport type { FacilitatorExtension } from \"@x402/core/types\";\n\n/**\n * Signer capability carried by the ERC-20 approval extension when registered in a facilitator.\n *\n * Mirrors FacilitatorEvmSigner (from @x402/evm) plus `sendRawTransaction`.\n * The extension signer owns the full approve+settle flow: it broadcasts the\n * pre-signed approval transaction AND executes the Permit2 settle call, enabling\n * production implementations to bundle both atomically (e.g., Flashbots, multicall).\n *\n * The method signatures are duplicated here (rather than extending FacilitatorEvmSigner)\n * to avoid a circular dependency between @x402/extensions and @x402/evm.\n */\nexport interface Erc20ApprovalGasSponsoringSigner {\n getAddresses(): readonly `0x${string}`[];\n readContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\n verifyTypedData(args: {\n address: `0x${string}`;\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n primaryType: string;\n message: Record<string, unknown>;\n signature: `0x${string}`;\n }): Promise<boolean>;\n writeContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args: readonly unknown[];\n }): Promise<`0x${string}`>;\n sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>;\n waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{ status: string }>;\n getCode(args: { address: `0x${string}` }): Promise<`0x${string}` | undefined>;\n sendRawTransaction(args: { serializedTransaction: `0x${string}` }): Promise<`0x${string}`>;\n}\n\n/**\n * Extension identifier for the ERC-20 approval gas sponsoring extension.\n */\nexport const ERC20_APPROVAL_GAS_SPONSORING = {\n key: \"erc20ApprovalGasSponsoring\",\n} as const satisfies FacilitatorExtension;\n\n/** Current schema version for the ERC-20 approval gas sponsoring extension info. */\nexport const ERC20_APPROVAL_GAS_SPONSORING_VERSION = \"1\";\n\n/**\n * Extended extension object registered in a facilitator via registerExtension().\n * Carries the signer that owns the full approve+settle flow for ERC-20 tokens\n * that lack EIP-2612. The signer must have all FacilitatorEvmSigner capabilities\n * plus `sendRawTransaction` for broadcasting the pre-signed approval tx.\n *\n * @example\n * ```typescript\n * import { createErc20ApprovalGasSponsoringExtension } from '@x402/extensions';\n *\n * facilitator.registerExtension(\n * createErc20ApprovalGasSponsoringExtension(evmSigner, viemClient),\n * );\n * ```\n */\nexport interface Erc20ApprovalGasSponsoringFacilitatorExtension extends FacilitatorExtension {\n key: \"erc20ApprovalGasSponsoring\";\n /** Signer with broadcast + settle capability. Optional — settlement fails gracefully if absent. */\n signer?: Erc20ApprovalGasSponsoringSigner;\n}\n\n/**\n * Signer input for {@link createErc20ApprovalGasSponsoringExtension}.\n * Matches the FacilitatorEvmSigner shape from @x402/evm (duplicated to avoid circular dep).\n */\nexport type Erc20ApprovalGasSponsoringBaseSigner = Omit<\n Erc20ApprovalGasSponsoringSigner,\n \"sendRawTransaction\"\n>;\n\n/**\n * Create an ERC-20 approval gas sponsoring extension ready to register in a facilitator.\n *\n * @param signer - The EVM facilitator signer (e.g. from `toFacilitatorEvmSigner()`)\n * @param client - Object providing `sendRawTransaction` (e.g. a viem WalletClient)\n * @param client.sendRawTransaction - Broadcasts a signed transaction to the network\n * @returns A fully configured extension to pass to `facilitator.registerExtension()`\n */\nexport function createErc20ApprovalGasSponsoringExtension(\n signer: Erc20ApprovalGasSponsoringBaseSigner,\n client: {\n sendRawTransaction: (args: { serializedTransaction: `0x${string}` }) => Promise<`0x${string}`>;\n },\n): Erc20ApprovalGasSponsoringFacilitatorExtension {\n return {\n ...ERC20_APPROVAL_GAS_SPONSORING,\n signer: {\n ...signer,\n sendRawTransaction: client.sendRawTransaction.bind(client),\n },\n };\n}\n\n/**\n * ERC-20 approval gas sponsoring info populated by the client.\n *\n * Contains the RLP-encoded signed `approve(Permit2, MaxUint256)` transaction\n * that the facilitator broadcasts before settling the Permit2 payment.\n *\n * Note: Unlike EIP-2612, there is no nonce/deadline/signature — instead the\n * entire signed transaction is included as `signedTransaction`.\n */\nexport interface Erc20ApprovalGasSponsoringInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** The address of the sender (token owner who signed the tx). */\n from: `0x${string}`;\n /** The address of the ERC-20 token contract. */\n asset: `0x${string}`;\n /** The address of the spender (Canonical Permit2). */\n spender: `0x${string}`;\n /** The amount approved (uint256 as decimal string). Always MaxUint256. */\n amount: string;\n /** The RLP-encoded signed EIP-1559 transaction as a hex string. */\n signedTransaction: `0x${string}`;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * Server-side ERC-20 approval gas sponsoring info included in PaymentRequired.\n * Contains a description and version; the client populates the rest.\n */\nexport interface Erc20ApprovalGasSponsoringServerInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** Human-readable description of the extension. */\n description: string;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * The full extension object as it appears in PaymentRequired.extensions\n * and PaymentPayload.extensions.\n */\nexport interface Erc20ApprovalGasSponsoringExtension {\n /** Extension info - server-provided or client-enriched. */\n info: Erc20ApprovalGasSponsoringServerInfo | Erc20ApprovalGasSponsoringInfo;\n /** JSON Schema describing the expected structure of info. */\n schema: Record<string, unknown>;\n}\n","/**\n * Resource Service functions for declaring the ERC-20 Approval Gas Sponsoring extension.\n *\n * These functions help servers declare support for ERC-20 approval gas sponsoring\n * in the PaymentRequired response extensions. Use this for tokens that do NOT\n * implement EIP-2612 (generic ERC-20 tokens).\n */\n\nimport {\n ERC20_APPROVAL_GAS_SPONSORING,\n ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n type Erc20ApprovalGasSponsoringExtension,\n} from \"./types\";\n\n/**\n * The JSON Schema for the ERC-20 approval gas sponsoring extension info.\n * Matches the schema defined in the spec.\n */\nexport const erc20ApprovalGasSponsoringSchema: Record<string, unknown> = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n from: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the sender (token owner).\",\n },\n asset: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the ERC-20 token contract.\",\n },\n spender: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the spender (Canonical Permit2).\",\n },\n amount: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The amount approved (uint256). Always MaxUint256.\",\n },\n signedTransaction: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]+$\",\n description: \"The RLP-encoded signed EIP-1559 transaction as a hex string.\",\n },\n version: {\n type: \"string\",\n pattern: \"^[0-9]+(\\\\.[0-9]+)*$\",\n description: \"Schema version identifier.\",\n },\n },\n required: [\"from\", \"asset\", \"spender\", \"amount\", \"signedTransaction\", \"version\"],\n};\n\n/**\n * Declares the ERC-20 approval gas sponsoring extension for inclusion in\n * PaymentRequired.extensions.\n *\n * The server advertises that it (or its facilitator) supports broadcasting\n * a pre-signed `approve(Permit2, MaxUint256)` transaction on the client's behalf.\n * Use this for tokens that do NOT implement EIP-2612.\n *\n * @returns An object keyed by the extension identifier containing the extension declaration\n *\n * @example\n * ```typescript\n * import { declareErc20ApprovalGasSponsoringExtension } from '@x402/extensions';\n *\n * const routes = [\n * {\n * path: \"/api/data\",\n * price: { amount: \"1000\", asset: \"0x...\", extra: { assetTransferMethod: \"permit2\" } },\n * extensions: {\n * ...declareErc20ApprovalGasSponsoringExtension(),\n * },\n * },\n * ];\n * ```\n */\nexport function declareErc20ApprovalGasSponsoringExtension(): Record<\n string,\n Erc20ApprovalGasSponsoringExtension\n> {\n const key = ERC20_APPROVAL_GAS_SPONSORING.key;\n return {\n [key]: {\n info: {\n description:\n \"The facilitator broadcasts a pre-signed ERC-20 approve() transaction to grant Permit2 allowance.\",\n version: ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n },\n schema: erc20ApprovalGasSponsoringSchema,\n },\n };\n}\n","/**\n * Facilitator functions for extracting and validating ERC-20 Approval Gas Sponsoring\n * extension data.\n *\n * These functions help facilitators extract the pre-signed approve() transaction\n * from payment payloads and validate it before broadcasting and settling.\n */\n\nimport Ajv from \"ajv/dist/2020.js\";\nimport type { PaymentPayload } from \"@x402/core/types\";\nimport {\n ERC20_APPROVAL_GAS_SPONSORING,\n type Erc20ApprovalGasSponsoringInfo,\n type Erc20ApprovalGasSponsoringExtension,\n} from \"./types\";\nimport { erc20ApprovalGasSponsoringSchema } from \"./resourceService\";\n\n/**\n * Extracts the ERC-20 approval gas sponsoring info from a payment payload's extensions.\n *\n * Performs structural extraction only — checks that the extension is present and\n * contains all required fields. Does NOT validate field formats (use\n * validateErc20ApprovalGasSponsoringInfo for that).\n *\n * @param paymentPayload - The payment payload to extract from\n * @returns The ERC-20 approval gas sponsoring info, or null if not present\n */\nexport function extractErc20ApprovalGasSponsoringInfo(\n paymentPayload: PaymentPayload,\n): Erc20ApprovalGasSponsoringInfo | null {\n if (!paymentPayload.extensions) {\n return null;\n }\n\n const extension = paymentPayload.extensions[ERC20_APPROVAL_GAS_SPONSORING.key] as\n | Erc20ApprovalGasSponsoringExtension\n | undefined;\n\n if (!extension?.info) {\n return null;\n }\n\n const info = extension.info as Record<string, unknown>;\n\n if (\n !info.from ||\n !info.asset ||\n !info.spender ||\n !info.amount ||\n !info.signedTransaction ||\n !info.version\n ) {\n return null;\n }\n\n return info as unknown as Erc20ApprovalGasSponsoringInfo;\n}\n\n/**\n * Validates that the ERC-20 approval gas sponsoring info has valid format.\n *\n * Validates the info against the canonical JSON Schema, checking:\n * - All required fields are present\n * - Addresses are valid hex (0x + 40 hex chars)\n * - Amount is a numeric string\n * - signedTransaction is a hex string\n * - Version is a numeric version string\n *\n * @param info - The ERC-20 approval gas sponsoring info to validate\n * @returns True if the info is valid, false otherwise\n */\nexport function validateErc20ApprovalGasSponsoringInfo(\n info: Erc20ApprovalGasSponsoringInfo,\n): boolean {\n const ajv = new Ajv({ strict: false, allErrors: true });\n const validate = ajv.compile(erc20ApprovalGasSponsoringSchema);\n return validate(info) as boolean;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/eip2612-gas-sponsoring/types.ts","../../src/eip2612-gas-sponsoring/resourceService.ts","../../src/eip2612-gas-sponsoring/facilitator.ts","../../src/erc20-approval-gas-sponsoring/types.ts","../../src/erc20-approval-gas-sponsoring/resourceService.ts","../../src/erc20-approval-gas-sponsoring/facilitator.ts"],"sourcesContent":["/**\n * Type definitions for the EIP-2612 Gas Sponsoring Extension\n *\n * This extension enables gasless approval of the Permit2 contract for tokens\n * that implement EIP-2612. The client signs an off-chain permit, and the\n * facilitator submits it on-chain via `x402Permit2Proxy.settleWithPermit`.\n */\n\nimport type { FacilitatorExtension } from \"@x402/core/types\";\n\n/**\n * Extension identifier for the EIP-2612 gas sponsoring extension.\n */\nexport const EIP2612_GAS_SPONSORING: FacilitatorExtension = { key: \"eip2612GasSponsoring\" };\n\n/**\n * EIP-2612 gas sponsoring info populated by the client.\n *\n * Contains the EIP-2612 permit signature and parameters that the facilitator\n * needs to call `x402Permit2Proxy.settleWithPermit`.\n */\nexport interface Eip2612GasSponsoringInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** The address of the sender (token owner). */\n from: string;\n /** The address of the ERC-20 token contract. */\n asset: string;\n /** The address of the spender (Canonical Permit2). */\n spender: string;\n /** The amount to approve (uint256 as decimal string). Typically MaxUint256. */\n amount: string;\n /** The current EIP-2612 nonce of the sender (decimal string). */\n nonce: string;\n /** The timestamp at which the permit signature expires (decimal string). */\n deadline: string;\n /** The 65-byte concatenated EIP-2612 permit signature (r, s, v) as a hex string. */\n signature: string;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * Server-side EIP-2612 gas sponsoring info included in PaymentRequired.\n * Contains a description and version; the client populates the rest.\n */\nexport interface Eip2612GasSponsoringServerInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** Human-readable description of the extension. */\n description: string;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * The full extension object as it appears in PaymentRequired.extensions\n * and PaymentPayload.extensions.\n */\nexport interface Eip2612GasSponsoringExtension {\n /** Extension info - server-provided or client-enriched. */\n info: Eip2612GasSponsoringServerInfo | Eip2612GasSponsoringInfo;\n /** JSON Schema describing the expected structure of info. */\n schema: Record<string, unknown>;\n}\n","/**\n * Resource Service functions for declaring the EIP-2612 Gas Sponsoring extension.\n *\n * These functions help servers declare support for EIP-2612 gasless Permit2 approvals\n * in the PaymentRequired response extensions.\n */\n\nimport { EIP2612_GAS_SPONSORING, type Eip2612GasSponsoringExtension } from \"./types\";\n\n/**\n * The JSON Schema for the EIP-2612 gas sponsoring extension info.\n * Matches the schema defined in the spec.\n */\nconst eip2612GasSponsoringSchema: Record<string, unknown> = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n from: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the sender.\",\n },\n asset: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the ERC-20 token contract.\",\n },\n spender: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the spender (Canonical Permit2).\",\n },\n amount: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The amount to approve (uint256). Typically MaxUint.\",\n },\n nonce: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The current nonce of the sender.\",\n },\n deadline: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The timestamp at which the signature expires.\",\n },\n signature: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]+$\",\n description: \"The 65-byte concatenated signature (r, s, v) as a hex string.\",\n },\n version: {\n type: \"string\",\n pattern: \"^[0-9]+(\\\\.[0-9]+)*$\",\n description: \"Schema version identifier.\",\n },\n },\n required: [\"from\", \"asset\", \"spender\", \"amount\", \"nonce\", \"deadline\", \"signature\", \"version\"],\n};\n\n/**\n * Declares the EIP-2612 gas sponsoring extension for inclusion in\n * PaymentRequired.extensions.\n *\n * The server advertises that it (or its facilitator) supports EIP-2612\n * gasless Permit2 approval. The client will populate the info with the\n * actual permit signature data.\n *\n * @returns An object keyed by the extension identifier containing the extension declaration\n *\n * @example\n * ```typescript\n * import { declareEip2612GasSponsoringExtension } from '@x402/extensions';\n *\n * const routes = [\n * {\n * path: \"/api/data\",\n * price: \"$0.01\",\n * extensions: {\n * ...declareEip2612GasSponsoringExtension(),\n * },\n * },\n * ];\n * ```\n */\nexport function declareEip2612GasSponsoringExtension(): Record<\n string,\n Eip2612GasSponsoringExtension\n> {\n const key = EIP2612_GAS_SPONSORING.key;\n return {\n [key]: {\n info: {\n description:\n \"The facilitator accepts EIP-2612 gasless Permit to `Permit2` canonical contract.\",\n version: \"1\",\n },\n schema: eip2612GasSponsoringSchema,\n },\n };\n}\n","/**\n * Facilitator functions for extracting and validating EIP-2612 Gas Sponsoring extension data.\n *\n * These functions help facilitators extract the EIP-2612 permit data from payment\n * payloads and validate it before calling settleWithPermit.\n */\n\nimport type { PaymentPayload } from \"@x402/core/types\";\nimport {\n EIP2612_GAS_SPONSORING,\n type Eip2612GasSponsoringInfo,\n type Eip2612GasSponsoringExtension,\n} from \"./types\";\n\n/**\n * Extracts the EIP-2612 gas sponsoring info from a payment payload's extensions.\n *\n * Returns the info if the extension is present and contains the required client-populated\n * fields (from, asset, spender, amount, nonce, deadline, signature, version).\n *\n * @param paymentPayload - The payment payload to extract from\n * @returns The EIP-2612 gas sponsoring info, or null if not present\n */\nexport function extractEip2612GasSponsoringInfo(\n paymentPayload: PaymentPayload,\n): Eip2612GasSponsoringInfo | null {\n if (!paymentPayload.extensions) {\n return null;\n }\n\n const extension = paymentPayload.extensions[EIP2612_GAS_SPONSORING.key] as\n | Eip2612GasSponsoringExtension\n | undefined;\n\n if (!extension?.info) {\n return null;\n }\n\n const info = extension.info as Record<string, unknown>;\n\n // Check that the client has populated the required fields\n if (\n !info.from ||\n !info.asset ||\n !info.spender ||\n !info.amount ||\n !info.nonce ||\n !info.deadline ||\n !info.signature ||\n !info.version\n ) {\n return null;\n }\n\n return info as unknown as Eip2612GasSponsoringInfo;\n}\n\n/**\n * Validates that the EIP-2612 gas sponsoring info has valid format.\n *\n * Performs basic validation on the info fields:\n * - Addresses are valid hex (0x + 40 hex chars)\n * - Amount, nonce, deadline are numeric strings\n * - Signature is a hex string\n * - Version is a numeric version string\n *\n * @param info - The EIP-2612 gas sponsoring info to validate\n * @returns True if the info is valid, false otherwise\n */\nexport function validateEip2612GasSponsoringInfo(info: Eip2612GasSponsoringInfo): boolean {\n const addressPattern = /^0x[a-fA-F0-9]{40}$/;\n const numericPattern = /^[0-9]+$/;\n const hexPattern = /^0x[a-fA-F0-9]+$/;\n const versionPattern = /^[0-9]+(\\.[0-9]+)*$/;\n\n return (\n addressPattern.test(info.from) &&\n addressPattern.test(info.asset) &&\n addressPattern.test(info.spender) &&\n numericPattern.test(info.amount) &&\n numericPattern.test(info.nonce) &&\n numericPattern.test(info.deadline) &&\n hexPattern.test(info.signature) &&\n versionPattern.test(info.version)\n );\n}\n","/**\n * Type definitions for the ERC-20 Approval Gas Sponsoring Extension\n *\n * This extension enables gasless Permit2 approval for generic ERC-20 tokens\n * that do NOT implement EIP-2612. The client signs (but does not broadcast) a\n * raw `approve(Permit2, MaxUint256)` transaction, and the facilitator broadcasts\n * it atomically before settling the Permit2 payment.\n */\n\nimport type { FacilitatorExtension } from \"@x402/core/types\";\n\n/**\n * A single transaction to be executed by the signer.\n * - `0x${string}`: a pre-signed serialized transaction (broadcast as-is via sendRawTransaction)\n * - `{ to, data, gas? }`: an unsigned call intent (signer signs and broadcasts)\n */\nexport type TransactionRequest =\n | `0x${string}`\n | { to: `0x${string}`; data: `0x${string}`; gas?: bigint };\n\n/**\n * Signer capability carried by the ERC-20 approval extension when registered in a facilitator.\n *\n * Mirrors FacilitatorEvmSigner (from @x402/evm) plus `sendTransactions`.\n * The signer owns execution of multiple transactions, enabling production implementations\n * to bundle them atomically (e.g., Flashbots, multicall, smart account batching)\n * while simpler implementations can execute them sequentially.\n *\n * The method signatures are duplicated here (rather than extending FacilitatorEvmSigner)\n * to avoid a circular dependency between @x402/extensions and @x402/evm.\n */\nexport interface Erc20ApprovalGasSponsoringSigner {\n getAddresses(): readonly `0x${string}`[];\n readContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args?: readonly unknown[];\n }): Promise<unknown>;\n verifyTypedData(args: {\n address: `0x${string}`;\n domain: Record<string, unknown>;\n types: Record<string, unknown>;\n primaryType: string;\n message: Record<string, unknown>;\n signature: `0x${string}`;\n }): Promise<boolean>;\n writeContract(args: {\n address: `0x${string}`;\n abi: readonly unknown[];\n functionName: string;\n args: readonly unknown[];\n gas?: bigint;\n }): Promise<`0x${string}`>;\n sendTransaction(args: { to: `0x${string}`; data: `0x${string}` }): Promise<`0x${string}`>;\n waitForTransactionReceipt(args: { hash: `0x${string}` }): Promise<{ status: string }>;\n getCode(args: { address: `0x${string}` }): Promise<`0x${string}` | undefined>;\n sendTransactions(transactions: TransactionRequest[]): Promise<`0x${string}`[]>;\n}\n\n/**\n * Extension identifier for the ERC-20 approval gas sponsoring extension.\n */\nexport const ERC20_APPROVAL_GAS_SPONSORING = {\n key: \"erc20ApprovalGasSponsoring\",\n} as const satisfies FacilitatorExtension;\n\n/** Current schema version for the ERC-20 approval gas sponsoring extension info. */\nexport const ERC20_APPROVAL_GAS_SPONSORING_VERSION = \"1\";\n\n/**\n * Extended extension object registered in a facilitator via registerExtension().\n * Carries the signer that owns the full approve+settle flow for ERC-20 tokens\n * that lack EIP-2612.\n *\n * @example\n * ```typescript\n * import { createErc20ApprovalGasSponsoringExtension } from '@x402/extensions';\n *\n * facilitator.registerExtension(\n * createErc20ApprovalGasSponsoringExtension(signer),\n * );\n * ```\n */\nexport interface Erc20ApprovalGasSponsoringFacilitatorExtension extends FacilitatorExtension {\n key: \"erc20ApprovalGasSponsoring\";\n /** Default signer with approve+settle capability. Optional — settlement fails gracefully if absent. */\n signer?: Erc20ApprovalGasSponsoringSigner;\n /** Network-specific signer resolver. Takes precedence over `signer` when provided. */\n signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined;\n}\n\n/**\n * Base signer shape without `sendTransactions`.\n * Matches the FacilitatorEvmSigner shape from @x402/evm (duplicated to avoid circular dep).\n */\nexport type Erc20ApprovalGasSponsoringBaseSigner = Omit<\n Erc20ApprovalGasSponsoringSigner,\n \"sendTransactions\"\n>;\n\n/**\n * Create an ERC-20 approval gas sponsoring extension ready to register in a facilitator.\n *\n * @param signer - A complete signer with `sendTransactions` already implemented.\n * The signer decides how to execute the transactions (sequentially, batched, or atomically).\n * @param signerForNetwork - Optional network-specific signer resolver. When provided,\n * takes precedence over `signer` and allows different settlement signers per network.\n * @returns A fully configured extension to pass to `facilitator.registerExtension()`\n */\nexport function createErc20ApprovalGasSponsoringExtension(\n signer: Erc20ApprovalGasSponsoringSigner,\n signerForNetwork?: (network: string) => Erc20ApprovalGasSponsoringSigner | undefined,\n): Erc20ApprovalGasSponsoringFacilitatorExtension {\n return { ...ERC20_APPROVAL_GAS_SPONSORING, signer, signerForNetwork };\n}\n\n/**\n * ERC-20 approval gas sponsoring info populated by the client.\n *\n * Contains the RLP-encoded signed `approve(Permit2, MaxUint256)` transaction\n * that the facilitator broadcasts before settling the Permit2 payment.\n *\n * Note: Unlike EIP-2612, there is no nonce/deadline/signature — instead the\n * entire signed transaction is included as `signedTransaction`.\n */\nexport interface Erc20ApprovalGasSponsoringInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** The address of the sender (token owner who signed the tx). */\n from: `0x${string}`;\n /** The address of the ERC-20 token contract. */\n asset: `0x${string}`;\n /** The address of the spender (Canonical Permit2). */\n spender: `0x${string}`;\n /** The amount approved (uint256 as decimal string). Always MaxUint256. */\n amount: string;\n /** The RLP-encoded signed EIP-1559 transaction as a hex string. */\n signedTransaction: `0x${string}`;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * Server-side ERC-20 approval gas sponsoring info included in PaymentRequired.\n * Contains a description and version; the client populates the rest.\n */\nexport interface Erc20ApprovalGasSponsoringServerInfo {\n /** Index signature for compatibility with Record<string, unknown> */\n [key: string]: unknown;\n /** Human-readable description of the extension. */\n description: string;\n /** Schema version identifier. */\n version: string;\n}\n\n/**\n * The full extension object as it appears in PaymentRequired.extensions\n * and PaymentPayload.extensions.\n */\nexport interface Erc20ApprovalGasSponsoringExtension {\n /** Extension info - server-provided or client-enriched. */\n info: Erc20ApprovalGasSponsoringServerInfo | Erc20ApprovalGasSponsoringInfo;\n /** JSON Schema describing the expected structure of info. */\n schema: Record<string, unknown>;\n}\n","/**\n * Resource Service functions for declaring the ERC-20 Approval Gas Sponsoring extension.\n *\n * These functions help servers declare support for ERC-20 approval gas sponsoring\n * in the PaymentRequired response extensions. Use this for tokens that do NOT\n * implement EIP-2612 (generic ERC-20 tokens).\n */\n\nimport {\n ERC20_APPROVAL_GAS_SPONSORING,\n ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n type Erc20ApprovalGasSponsoringExtension,\n} from \"./types\";\n\n/**\n * The JSON Schema for the ERC-20 approval gas sponsoring extension info.\n * Matches the schema defined in the spec.\n */\nexport const erc20ApprovalGasSponsoringSchema: Record<string, unknown> = {\n $schema: \"https://json-schema.org/draft/2020-12/schema\",\n type: \"object\",\n properties: {\n from: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the sender (token owner).\",\n },\n asset: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the ERC-20 token contract.\",\n },\n spender: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]{40}$\",\n description: \"The address of the spender (Canonical Permit2).\",\n },\n amount: {\n type: \"string\",\n pattern: \"^[0-9]+$\",\n description: \"The amount approved (uint256). Always MaxUint256.\",\n },\n signedTransaction: {\n type: \"string\",\n pattern: \"^0x[a-fA-F0-9]+$\",\n description: \"The RLP-encoded signed EIP-1559 transaction as a hex string.\",\n },\n version: {\n type: \"string\",\n pattern: \"^[0-9]+(\\\\.[0-9]+)*$\",\n description: \"Schema version identifier.\",\n },\n },\n required: [\"from\", \"asset\", \"spender\", \"amount\", \"signedTransaction\", \"version\"],\n};\n\n/**\n * Declares the ERC-20 approval gas sponsoring extension for inclusion in\n * PaymentRequired.extensions.\n *\n * The server advertises that it (or its facilitator) supports broadcasting\n * a pre-signed `approve(Permit2, MaxUint256)` transaction on the client's behalf.\n * Use this for tokens that do NOT implement EIP-2612.\n *\n * @returns An object keyed by the extension identifier containing the extension declaration\n *\n * @example\n * ```typescript\n * import { declareErc20ApprovalGasSponsoringExtension } from '@x402/extensions';\n *\n * const routes = [\n * {\n * path: \"/api/data\",\n * price: { amount: \"1000\", asset: \"0x...\", extra: { assetTransferMethod: \"permit2\" } },\n * extensions: {\n * ...declareErc20ApprovalGasSponsoringExtension(),\n * },\n * },\n * ];\n * ```\n */\nexport function declareErc20ApprovalGasSponsoringExtension(): Record<\n string,\n Erc20ApprovalGasSponsoringExtension\n> {\n const key = ERC20_APPROVAL_GAS_SPONSORING.key;\n return {\n [key]: {\n info: {\n description:\n \"The facilitator broadcasts a pre-signed ERC-20 approve() transaction to grant Permit2 allowance.\",\n version: ERC20_APPROVAL_GAS_SPONSORING_VERSION,\n },\n schema: erc20ApprovalGasSponsoringSchema,\n },\n };\n}\n","/**\n * Facilitator functions for extracting and validating ERC-20 Approval Gas Sponsoring\n * extension data.\n *\n * These functions help facilitators extract the pre-signed approve() transaction\n * from payment payloads and validate it before broadcasting and settling.\n */\n\nimport Ajv from \"ajv/dist/2020.js\";\nimport type { PaymentPayload } from \"@x402/core/types\";\nimport {\n ERC20_APPROVAL_GAS_SPONSORING,\n type Erc20ApprovalGasSponsoringInfo,\n type Erc20ApprovalGasSponsoringExtension,\n} from \"./types\";\nimport { erc20ApprovalGasSponsoringSchema } from \"./resourceService\";\n\n/**\n * Extracts the ERC-20 approval gas sponsoring info from a payment payload's extensions.\n *\n * Performs structural extraction only — checks that the extension is present and\n * contains all required fields. Does NOT validate field formats (use\n * validateErc20ApprovalGasSponsoringInfo for that).\n *\n * @param paymentPayload - The payment payload to extract from\n * @returns The ERC-20 approval gas sponsoring info, or null if not present\n */\nexport function extractErc20ApprovalGasSponsoringInfo(\n paymentPayload: PaymentPayload,\n): Erc20ApprovalGasSponsoringInfo | null {\n if (!paymentPayload.extensions) {\n return null;\n }\n\n const extension = paymentPayload.extensions[ERC20_APPROVAL_GAS_SPONSORING.key] as\n | Erc20ApprovalGasSponsoringExtension\n | undefined;\n\n if (!extension?.info) {\n return null;\n }\n\n const info = extension.info as Record<string, unknown>;\n\n if (\n !info.from ||\n !info.asset ||\n !info.spender ||\n !info.amount ||\n !info.signedTransaction ||\n !info.version\n ) {\n return null;\n }\n\n return info as unknown as Erc20ApprovalGasSponsoringInfo;\n}\n\n/**\n * Validates that the ERC-20 approval gas sponsoring info has valid format.\n *\n * Validates the info against the canonical JSON Schema, checking:\n * - All required fields are present\n * - Addresses are valid hex (0x + 40 hex chars)\n * - Amount is a numeric string\n * - signedTransaction is a hex string\n * - Version is a numeric version string\n *\n * @param info - The ERC-20 approval gas sponsoring info to validate\n * @returns True if the info is valid, false otherwise\n */\nexport function validateErc20ApprovalGasSponsoringInfo(\n info: Erc20ApprovalGasSponsoringInfo,\n): boolean {\n const ajv = new Ajv({ strict: false, allErrors: true });\n const validate = ajv.compile(erc20ApprovalGasSponsoringSchema);\n return validate(info) as boolean;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaO,IAAM,yBAA+C,EAAE,KAAK,uBAAuB;;;ACA1F,IAAM,6BAAsD;AAAA,EAC1D,SAAS;AAAA,EACT,MAAM;AAAA,EACN,YAAY;AAAA,IACV,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,WAAW;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,QAAQ,SAAS,WAAW,UAAU,SAAS,YAAY,aAAa,SAAS;AAC9F;AA2BO,SAAS,uCAGd;AACA,QAAM,MAAM,uBAAuB;AACnC,SAAO;AAAA,IACL,CAAC,GAAG,GAAG;AAAA,MACL,MAAM;AAAA,QACJ,aACE;AAAA,QACF,SAAS;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AACF;;;AC9EO,SAAS,gCACd,gBACiC;AACjC,MAAI,CAAC,eAAe,YAAY;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,eAAe,WAAW,uBAAuB,GAAG;AAItE,MAAI,CAAC,WAAW,MAAM;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,UAAU;AAGvB,MACE,CAAC,KAAK,QACN,CAAC,KAAK,SACN,CAAC,KAAK,WACN,CAAC,KAAK,UACN,CAAC,KAAK,SACN,CAAC,KAAK,YACN,CAAC,KAAK,aACN,CAAC,KAAK,SACN;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAcO,SAAS,iCAAiC,MAAyC;AACxF,QAAM,iBAAiB;AACvB,QAAM,iBAAiB;AACvB,QAAM,aAAa;AACnB,QAAM,iBAAiB;AAEvB,SACE,eAAe,KAAK,KAAK,IAAI,KAC7B,eAAe,KAAK,KAAK,KAAK,KAC9B,eAAe,KAAK,KAAK,OAAO,KAChC,eAAe,KAAK,KAAK,MAAM,KAC/B,eAAe,KAAK,KAAK,KAAK,KAC9B,eAAe,KAAK,KAAK,QAAQ,KACjC,WAAW,KAAK,KAAK,SAAS,KAC9B,eAAe,KAAK,KAAK,OAAO;AAEpC;;;ACtBO,IAAM,gCAAgC;AAAA,EAC3C,KAAK;AACP;AAGO,IAAM,wCAAwC;AA0C9C,SAAS,0CACd,QACA,kBACgD;AAChD,SAAO,EAAE,GAAG,+BAA+B,QAAQ,iBAAiB;AACtE;;;ACjGO,IAAM,mCAA4D;AAAA,EACvE,SAAS;AAAA,EACT,MAAM;AAAA,EACN,YAAY;AAAA,IACV,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,mBAAmB;AAAA,MACjB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,UAAU,CAAC,QAAQ,SAAS,WAAW,UAAU,qBAAqB,SAAS;AACjF;AA2BO,SAAS,6CAGd;AACA,QAAM,MAAM,8BAA8B;AAC1C,SAAO;AAAA,IACL,CAAC,GAAG,GAAG;AAAA,MACL,MAAM;AAAA,QACJ,aACE;AAAA,QACF,SAAS;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AACF;;;ACxFA,OAAO,SAAS;AAmBT,SAAS,sCACd,gBACuC;AACvC,MAAI,CAAC,eAAe,YAAY;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,eAAe,WAAW,8BAA8B,GAAG;AAI7E,MAAI,CAAC,WAAW,MAAM;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,UAAU;AAEvB,MACE,CAAC,KAAK,QACN,CAAC,KAAK,SACN,CAAC,KAAK,WACN,CAAC,KAAK,UACN,CAAC,KAAK,qBACN,CAAC,KAAK,SACN;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAeO,SAAS,uCACd,MACS;AACT,QAAM,MAAM,IAAI,IAAI,EAAE,QAAQ,OAAO,WAAW,KAAK,CAAC;AACtD,QAAM,WAAW,IAAI,QAAQ,gCAAgC;AAC7D,SAAO,SAAS,IAAI;AACtB;","names":[]}