@agent-score/commerce 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{checkout-BoFwnVsj.d.ts → checkout-B1JuEcbx.d.ts} +8 -0
- package/dist/{checkout-DRbQ0Fsh.d.mts → checkout-BN5i1Fi7.d.mts} +8 -0
- package/dist/core.js +1 -1
- package/dist/core.mjs +1 -1
- package/dist/discovery/index.d.mts +1 -1
- package/dist/discovery/index.d.ts +1 -1
- package/dist/identity/express.js +1 -1
- package/dist/identity/express.mjs +1 -1
- package/dist/identity/fastify.js +1 -1
- package/dist/identity/fastify.mjs +1 -1
- package/dist/identity/hono.js +1 -1
- package/dist/identity/hono.mjs +1 -1
- package/dist/identity/nextjs.js +1 -1
- package/dist/identity/nextjs.mjs +1 -1
- package/dist/identity/policy.js +19751 -106
- package/dist/identity/policy.js.map +1 -1
- package/dist/identity/policy.mjs +19756 -91
- package/dist/identity/policy.mjs.map +1 -1
- package/dist/identity/web.js +1 -1
- package/dist/identity/web.mjs +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19881 -236
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19897 -232
- package/dist/index.mjs.map +1 -1
- package/dist/payment/index.d.mts +42 -1
- package/dist/payment/index.d.ts +42 -1
- package/dist/payment/index.js +19 -0
- package/dist/payment/index.js.map +1 -1
- package/dist/payment/index.mjs +17 -0
- package/dist/payment/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/payment/index.ts","../../src/payment/networks.ts","../../src/payment/usdc.ts","../../src/payment/rails.ts","../../src/payment/directive.ts","../../src/payment/rail_spec.ts","../../src/payment/x402.ts","../../src/payment/x402_server.ts","../../src/payment/x402_settle.ts","../../src/payment/x402_validation.ts","../../src/stripe-multichain/mppx_stripe.ts","../../src/payment/mppx_server.ts","../../src/payment/dispatch.ts","../../src/payment/wwwauthenticate.ts","../../src/payment/headers.ts","../../src/payment/idempotency.ts","../../src/signer.ts","../../src/payment/settlement_override.ts","../../src/payment/amounts.ts","../../src/payment/zero-settle.ts","../../src/payment/lazy.ts","../../src/payment/solana.ts"],"sourcesContent":["export * from './directive';\nexport * from './networks';\nexport * from './usdc';\nexport * from './rails';\nexport * from './rail_spec';\nexport * from './x402';\nexport * from './x402_server';\nexport * from './x402_settle';\nexport * from './x402_validation';\nexport * from './mppx_server';\nexport * from './dispatch';\nexport * from './wwwauthenticate';\nexport * from './headers';\nexport * from './idempotency';\nexport * from './signer';\nexport * from './settlement_override';\nexport * from './amounts';\nexport * from './zero-settle';\nexport * from './lazy';\nexport * from './solana';\n","/**\n * Named network registry. Vendors reference symbolic names (`networks.base.mainnet.caip2`)\n * instead of magic strings. Lifted from agentscore-pay's constants.\n */\nexport const networks = {\n base: {\n mainnet: { caip2: 'eip155:8453' as const, chainId: 8453 },\n sepolia: { caip2: 'eip155:84532' as const, chainId: 84532 },\n },\n solana: {\n mainnet: { caip2: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' as const },\n devnet: { caip2: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1' as const },\n },\n tempo: {\n mainnet: { caip2: 'eip155:4217' as const, chainId: 4217 },\n testnet: { caip2: 'eip155:42431' as const, chainId: 42431 },\n },\n} as const;\n\nexport type NetworkFamily = keyof typeof networks;\n\n/**\n * Returns the family name (base/solana/tempo) for a given CAIP-2 network string,\n * or null if the network isn't in the registry. Useful for routing settlement\n * by network.\n */\nexport function networkFamily(caip2: string): NetworkFamily | null {\n if (caip2 === networks.base.mainnet.caip2 || caip2 === networks.base.sepolia.caip2) return 'base';\n if (caip2 === networks.solana.mainnet.caip2 || caip2 === networks.solana.devnet.caip2) return 'solana';\n if (caip2 === networks.tempo.mainnet.caip2 || caip2 === networks.tempo.testnet.caip2) return 'tempo';\n if (caip2.startsWith('solana:')) return 'solana';\n return null;\n}\n","/**\n * USDC token registry per network. Used by paymentDirective and rail definitions.\n * Lifted from agentscore-pay's constants.\n */\nexport const USDC = {\n base: {\n mainnet: { address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const, decimals: 6 },\n sepolia: { address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e' as const, decimals: 6 },\n },\n solana: {\n mainnet: { mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6 },\n devnet: { mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', decimals: 6 },\n },\n tempo: {\n mainnet: { address: '0x20C000000000000000000000b9537d11c60E8b50' as const, decimals: 6 },\n testnet: { address: '0x20c0000000000000000000000000000000000000' as const, decimals: 6 },\n },\n} as const;\n","import { networks } from './networks';\nimport { USDC } from './usdc';\n\n/**\n * Symbolic rail names mapped to their protocol details. Vendors pass `rail: 'tempo-mainnet'`\n * to the directive builder and the SDK fills in method/network/decimals/currency from this\n * registry. Custom rails not in this registry can be passed by setting the lower-level\n * fields directly on the directive builder.\n */\nexport const rails = {\n 'tempo-mainnet': {\n method: 'tempo',\n network: networks.tempo.mainnet.caip2,\n chainId: networks.tempo.mainnet.chainId,\n currency: USDC.tempo.mainnet.address,\n decimals: USDC.tempo.mainnet.decimals,\n asset: USDC.tempo.mainnet.address,\n },\n 'tempo-testnet': {\n method: 'tempo',\n network: networks.tempo.testnet.caip2,\n chainId: networks.tempo.testnet.chainId,\n currency: USDC.tempo.testnet.address,\n decimals: USDC.tempo.testnet.decimals,\n asset: USDC.tempo.testnet.address,\n },\n 'x402-base-mainnet': {\n method: 'x402',\n network: networks.base.mainnet.caip2,\n chainId: networks.base.mainnet.chainId,\n currency: USDC.base.mainnet.address,\n decimals: USDC.base.mainnet.decimals,\n asset: USDC.base.mainnet.address,\n },\n 'x402-base-sepolia': {\n method: 'x402',\n network: networks.base.sepolia.caip2,\n chainId: networks.base.sepolia.chainId,\n currency: USDC.base.sepolia.address,\n decimals: USDC.base.sepolia.decimals,\n asset: USDC.base.sepolia.address,\n },\n // Upto rails — pay UP TO a max amount (Permit2-based, vs EIP-3009 for exact). Use for\n // variable-cost APIs where the actual cost depends on output (LLM tokens, bandwidth, etc.).\n // Only available on EVM networks; Solana svm doesn't ship an upto scheme yet.\n 'x402-base-mainnet-upto': {\n method: 'x402-upto',\n network: networks.base.mainnet.caip2,\n chainId: networks.base.mainnet.chainId,\n currency: USDC.base.mainnet.address,\n decimals: USDC.base.mainnet.decimals,\n asset: USDC.base.mainnet.address,\n },\n 'x402-base-sepolia-upto': {\n method: 'x402-upto',\n network: networks.base.sepolia.caip2,\n chainId: networks.base.sepolia.chainId,\n currency: USDC.base.sepolia.address,\n decimals: USDC.base.sepolia.decimals,\n asset: USDC.base.sepolia.address,\n },\n 'mpp-solana-mainnet': {\n method: 'solana',\n network: networks.solana.mainnet.caip2,\n currency: USDC.solana.mainnet.mint,\n decimals: USDC.solana.mainnet.decimals,\n asset: USDC.solana.mainnet.mint,\n },\n 'mpp-solana-devnet': {\n method: 'solana',\n network: networks.solana.devnet.caip2,\n currency: USDC.solana.devnet.mint,\n decimals: USDC.solana.devnet.decimals,\n asset: USDC.solana.devnet.mint,\n },\n 'stripe-spt': {\n method: 'stripe',\n currency: 'usd',\n decimals: 2,\n },\n} as const;\n\nexport type RailName = keyof typeof rails;\n\nexport interface RailDefinition {\n method: string;\n network?: string;\n chainId?: number;\n currency: string;\n decimals: number;\n asset?: string;\n}\n\n/**\n * Lookup a rail definition by symbolic name. Returns undefined if the rail isn't in\n * the registry — vendors with custom rails should pass the low-level fields directly.\n */\nexport function lookupRail(name: string): RailDefinition | undefined {\n return rails[name as RailName] as RailDefinition | undefined;\n}\n","import { lookupRail } from './rails';\n\n/**\n * Build the base64-encoded `request` blob for an MPP Payment directive (per the\n * paymentauth.org spec). Output shape matches what link-cli `mpp decode` expects:\n *\n * { amount: \"<raw_integer>\", currency: \"<token>\", recipient?: \"<addr>\",\n * methodDetails?: { chainId?: number, networkId?: string } }\n */\nexport function buildPaymentRequestBlob({\n rail,\n amountUsd,\n currency,\n decimals,\n recipient,\n chainId,\n networkId,\n}: {\n /** Symbolic rail name (e.g., 'tempo-mainnet', 'x402-base-mainnet') — fills in defaults */\n rail?: string;\n /** Amount in USD as a number or string. Converted to raw integer using `decimals`. */\n amountUsd: string | number;\n /** Token contract address or currency code. Defaults from rail. */\n currency?: string;\n /** Decimal precision for the amount. Defaults from rail (6 for USDC, 2 for USD). */\n decimals?: number;\n /** Recipient address (on-chain). Optional for stripe-style rails. */\n recipient?: string;\n /** EVM chain ID (goes into methodDetails.chainId). Defaults from rail. */\n chainId?: number;\n /** Stripe profile_id or similar (goes into methodDetails.networkId — note camelCase per link-cli's mpp decode validator). */\n networkId?: string;\n}): string {\n const railDef = rail ? lookupRail(rail) : undefined;\n const decimalsResolved = decimals ?? railDef?.decimals ?? 6;\n const currencyResolved = currency ?? railDef?.currency ?? 'usd';\n const chainIdResolved = chainId ?? railDef?.chainId;\n\n const amountNum = typeof amountUsd === 'string' ? Number(amountUsd) : amountUsd;\n const amountRaw = BigInt(Math.round(amountNum * 10 ** decimalsResolved)).toString();\n const blob: Record<string, unknown> = { amount: amountRaw, currency: currencyResolved, decimals: decimalsResolved };\n if (recipient) blob.recipient = recipient;\n const methodDetails: Record<string, unknown> = {};\n if (chainIdResolved !== undefined) methodDetails.chainId = chainIdResolved;\n if (networkId) methodDetails.networkId = networkId;\n if (Object.keys(methodDetails).length > 0) blob.methodDetails = methodDetails;\n return Buffer.from(JSON.stringify(blob)).toString('base64url');\n}\n\n/**\n * Format an MPP Payment directive string for the WWW-Authenticate header.\n * Output shape: `Payment id=\"...\", realm=\"...\", method=\"...\", intent=\"charge\",\n * expires=\"...\", request=\"<base64>\"`\n */\nexport function paymentDirective({\n rail,\n id,\n realm,\n method,\n intent,\n expires,\n request,\n}: {\n /** Symbolic rail name — sets `method` automatically */\n rail?: string;\n /** Challenge id (unique per request, used to correlate retries) */\n id: string;\n /** Realm — the host of the merchant URL (e.g., \"agents.merchant.example\") */\n realm: string;\n /** MPP method name. Defaults from rail (e.g., 'tempo', 'stripe'). */\n method?: string;\n /** MPP intent. Defaults to 'charge'. */\n intent?: string;\n /** ISO-8601 expiry timestamp. Defaults to now + 5 minutes. */\n expires?: string;\n /** Base64-encoded request blob. Pass the result of buildPaymentRequestBlob. */\n request: string;\n}): string {\n const railDef = rail ? lookupRail(rail) : undefined;\n const methodResolved = method ?? railDef?.method ?? 'unknown';\n const intentResolved = intent ?? 'charge';\n const expiresResolved = expires ?? new Date(Date.now() + 5 * 60 * 1000).toISOString();\n return `Payment id=\"${id}\", realm=\"${realm}\", method=\"${methodResolved}\", intent=\"${intentResolved}\", expires=\"${expiresResolved}\", request=\"${request}\"`;\n}\n\n/**\n * Convenience: build the request blob and the directive in one call. Most vendors\n * want this rather than the two-step form.\n */\nexport function buildPaymentDirective({\n rail,\n id,\n realm,\n amountUsd,\n currency,\n decimals,\n recipient,\n chainId,\n networkId,\n method,\n intent,\n expires,\n}: {\n rail: string;\n id: string;\n realm: string;\n amountUsd: string | number;\n currency?: string;\n decimals?: number;\n recipient?: string;\n chainId?: number;\n networkId?: string;\n method?: string;\n intent?: string;\n expires?: string;\n}): string {\n const request = buildPaymentRequestBlob({\n rail,\n amountUsd,\n currency,\n decimals,\n recipient,\n chainId,\n networkId,\n });\n return paymentDirective({\n rail,\n id,\n realm,\n method,\n intent,\n expires,\n request,\n });\n}\n","/**\n * Canonical `*RailSpec` types — one shape per rail, consumed by every helper.\n *\n * A merchant accepting Tempo + Base + Solana + Stripe declares one `*RailSpec`\n * per rail and passes it to every helper (`buildAcceptedMethods`,\n * `buildHowToPay`, `mppPaymentHandler`, `createMppxServer`, ...). One canonical\n * shape per rail means the recipient address, network identifier, and token\n * defaults are declared once and reused everywhere.\n *\n * `RecipientLike` is polymorphic over `string | (() => string | Promise<string>)`\n * so per-order recipients (Stripe-multichain mints fresh deposit addresses per\n * PaymentIntent) flow through identically to static-treasury recipients. The\n * factory is called once per helper invocation; callers cache externally.\n */\n\nimport { USDC } from './usdc';\n\nexport type RecipientLike = string | (() => string | Promise<string>);\n\n/**\n * Resolve a `RecipientLike` to a concrete address string. Accepts a string\n * (returned verbatim), a sync callable (called once), or an async callable\n * (awaited once). Helpers call this on every invocation; callers that want\n * once-per-session resolution should cache externally.\n */\nexport async function resolveRecipient(r: RecipientLike): Promise<string> {\n if (typeof r === 'string') return r;\n return Promise.resolve(r());\n}\n\n/** Canonical config for the Tempo MPP rail. */\nexport interface TempoRailSpec {\n recipient: RecipientLike;\n network?: string;\n chainId?: number;\n token?: string;\n symbol?: string;\n decimals?: number;\n testnet?: boolean;\n recommend?: 'tempo' | 'agentscore-pay' | 'both';\n}\n\n/** Canonical config for the x402 EVM (Base) rail. */\nexport interface X402BaseRailSpec {\n recipient: RecipientLike;\n /** CAIP-2 canonical, e.g. `eip155:8453`. */\n network?: string;\n chainId?: number;\n token?: string;\n symbol?: string;\n decimals?: number;\n mode?: 'exact' | 'upto';\n}\n\n/**\n * Canonical config for the Solana MPP rail.\n *\n * `signer` is an optional fee-payer signer for server-side fee sponsorship —\n * typed as `unknown` to avoid hard-importing `@solana/kit` types here. Pass any\n * `TransactionPartialSigner`.\n */\nexport interface SolanaMppRailSpec {\n recipient: RecipientLike;\n network?: string;\n token?: string;\n symbol?: string;\n decimals?: number;\n rpcUrl?: string;\n signer?: unknown;\n tokenProgram?: string;\n}\n\n/**\n * Canonical config for the Stripe SPT rail.\n *\n * `recipient` is intentionally absent — Stripe rails use `profileId` as the\n * merchant-side network identifier the agent's SPT is scoped to; the\n * transaction recipient is the merchant's Stripe account, not an on-chain\n * address.\n */\nexport interface StripeRailSpec {\n profileId?: string | null;\n rails?: ('card' | 'link' | 'shared_payment_token')[];\n paymentMethodTypes?: string[];\n productName?: string;\n secretKey?: string;\n}\n\n/**\n * Canonical config for the Tempo session MPP rail (pay-as-you-go channels).\n *\n * `escrowContract` is the merchant-deployed on-chain escrow that holds channel\n * deposits + pays out cumulative vouchers on settlement. `store` is a\n * `ChannelStore` instance — typed as `unknown` to avoid hard-importing `mppx`'s\n * store interface here.\n */\nexport interface TempoSessionRailSpec {\n recipient: RecipientLike;\n escrowContract: string;\n store: unknown;\n currency?: string;\n testnet?: boolean;\n chains?: unknown;\n}\n\n/**\n * Default field values for each `*RailSpec`. Mirrors python-commerce's\n * `*RailSpec` dataclass defaults — callers can spread these into their spec\n * literal when they want defaults without typing them out. Sourced from the\n * USDC registry so they stay in sync with on-chain reality.\n */\nexport const RAIL_SPEC_DEFAULTS = {\n tempo: {\n network: 'tempo-mainnet',\n chainId: 4217,\n token: USDC.tempo.mainnet.address,\n symbol: 'USDC.e',\n decimals: 6,\n testnet: false,\n recommend: 'both' as const,\n },\n x402Base: {\n network: 'eip155:8453',\n chainId: 8453,\n token: USDC.base.mainnet.address,\n symbol: 'USDC',\n decimals: 6,\n mode: 'exact' as const,\n },\n solanaMpp: {\n network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n token: USDC.solana.mainnet.mint,\n symbol: 'USDC',\n decimals: 6,\n },\n stripe: {\n rails: ['card', 'link', 'shared_payment_token'] as ('card' | 'link' | 'shared_payment_token')[],\n },\n tempoSession: {\n currency: USDC.tempo.mainnet.address,\n testnet: false,\n },\n} as const;\n","/**\n * Generic x402 server interface. Different versions of @x402/core may expose different\n * shapes; we only require register() and (optionally) registerV1().\n */\nexport interface X402ServerLike {\n register(network: string, scheme: unknown): void;\n registerV1?(network: string, scheme: unknown): void;\n}\n\n/**\n * Registers an x402 scheme on both v1 and v2 of the protocol.\n *\n * Why: the @x402/core HTTP parser hardcodes `x402Version === 1`, while the client's\n * `.register()` defaults to v2. Without registering on both versions, a merchant\n * emitting a v1 response gets \"No client registered for x402 version: 1\" even\n * though the scheme handler is identical between versions. Every merchant trips\n * on this; the helper hides the workaround.\n */\nexport function registerX402SchemesV1V2(\n server: X402ServerLike,\n network: string,\n scheme: unknown,\n): void {\n server.register(network, scheme);\n if (typeof server.registerV1 === 'function') {\n server.registerV1(network, scheme);\n }\n}\n","import { networks } from './networks';\nimport { registerX402SchemesV1V2 } from './x402';\n\nexport type X402SymbolicRail =\n | 'x402-base-mainnet'\n | 'x402-base-sepolia'\n | 'x402-base-mainnet-upto'\n | 'x402-base-sepolia-upto';\n\nexport type X402FacilitatorChoice = 'coinbase' | 'http' | unknown;\n\nexport interface CreateX402ServerOptions {\n /**\n * Facilitator selection:\n * - 'coinbase' → Coinbase CDP facilitator (requires `@coinbase/x402` installed)\n * - 'http' → HTTP-only public testnet facilitator\n * - any object → custom facilitator instance, used directly\n * - omitted → defaults to 'http'\n */\n facilitator?: X402FacilitatorChoice;\n /**\n * Symbolic rail names to register schemes for. Each gets v1+v2 dual-register applied.\n * Requires `@x402/evm` peer dep installed.\n */\n rails?: X402SymbolicRail[];\n /** Advanced: register custom {network, scheme} pairs (in addition to or instead of `rails`). */\n schemes?: { network: string; scheme: unknown }[];\n /** Register the Bazaar discovery extension. Requires `@x402/extensions` installed. */\n bazaar?: boolean;\n /** Initialize the server immediately (calls facilitator). Default true. */\n initialize?: boolean;\n}\n\n/**\n * Loose type for the x402 resource server. We name the methods commerce calls during\n * setup; everything else (settlePayment, buildPaymentRequirements, processPaymentRequest,\n * enrichExtensions, etc.) is callable via the index signature so vendor code can use the\n * full @x402/core surface without us having to mirror every method signature.\n */\nexport interface X402Server {\n register(network: string, scheme: unknown): void;\n registerV1?(network: string, scheme: unknown): void;\n registerExtension(ext: unknown): void;\n initialize(): Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\ninterface X402CoreModule {\n x402ResourceServer: new (facilitator?: unknown) => X402Server;\n HTTPFacilitatorClient: new (facilitator?: unknown) => unknown;\n}\n\ninterface SchemeModule {\n ExactEvmScheme?: new () => unknown;\n UptoEvmScheme?: new () => unknown;\n}\n\ninterface CoinbaseModule {\n facilitator?: unknown;\n}\n\ninterface BazaarModule {\n bazaarResourceServerExtension?: unknown;\n}\n\n/**\n * One-call x402 server setup. Resolves facilitator, constructs the server, registers\n * schemes per network with v1+v2 dual-register, optionally adds the Bazaar extension,\n * and initializes — replaces ~15 lines of boilerplate with a single config call.\n *\n * x402 packages are peer dependencies — vendors install only the schemes they use.\n * Throws a guiding error if a required peer is missing.\n *\n * const server = await createX402Server({\n * facilitator: 'coinbase',\n * rails: ['x402-base-mainnet'],\n * bazaar: true,\n * });\n */\nexport async function createX402Server(opts: CreateX402ServerOptions = {}): Promise<X402Server> {\n const x402Core = (await dynamicImport<X402CoreModule>('@x402/core/server')) ?? null;\n /* v8 ignore start -- peer-dep-absence guard; @x402/core is installed in test env */\n if (!x402Core) {\n throw new Error(\n '@x402/core not installed — `npm install @x402/core` to use createX402Server.',\n );\n }\n /* v8 ignore stop */\n\n let facilitator: unknown;\n // Auto-select the Coinbase CDP facilitator when both env vars are present.\n // Lets merchants drop `facilitator: process.env.CDP_API_KEY_ID && ... ? 'coinbase' : 'http'`\n // boilerplate. Explicit `facilitator` opt still wins.\n const facilitatorChoice =\n opts.facilitator ??\n (process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET ? 'coinbase' : 'http');\n if (facilitatorChoice === 'coinbase') {\n const cb = await dynamicImport<CoinbaseModule>('@coinbase/x402');\n /* v8 ignore start -- peer-dep-absence guard; @coinbase/x402 is installed in test env */\n if (!cb?.facilitator) {\n throw new Error(\n '@coinbase/x402 not installed — `npm install @coinbase/x402` for facilitator: \"coinbase\".',\n );\n }\n /* v8 ignore stop */\n facilitator = new x402Core.HTTPFacilitatorClient(cb.facilitator);\n } else if (facilitatorChoice === 'http') {\n facilitator = new x402Core.HTTPFacilitatorClient();\n } else {\n facilitator = facilitatorChoice;\n }\n\n const server = new x402Core.x402ResourceServer(facilitator);\n\n let evmExactModule: SchemeModule | null = null;\n let evmUptoModule: SchemeModule | null = null;\n for (const rail of opts.rails ?? []) {\n const isUpto = rail.endsWith('-upto');\n if (rail.startsWith('x402-base')) {\n const baseRail = isUpto ? rail.slice(0, -5) : rail;\n const network =\n baseRail === 'x402-base-mainnet' ? networks.base.mainnet.caip2 : networks.base.sepolia.caip2;\n if (isUpto) {\n evmUptoModule ??= await dynamicImport<SchemeModule>('@x402/evm/upto/server');\n /* v8 ignore start -- peer-dep-absence guard; @x402/evm is installed in test env */\n if (!evmUptoModule?.UptoEvmScheme) {\n throw new Error('@x402/evm not installed — `npm install @x402/evm` for x402 base upto rails.');\n }\n /* v8 ignore stop */\n registerX402SchemesV1V2(server, network, new evmUptoModule.UptoEvmScheme());\n } else {\n evmExactModule ??= await dynamicImport<SchemeModule>('@x402/evm/exact/server');\n /* v8 ignore start -- peer-dep-absence guard; @x402/evm is installed in test env */\n if (!evmExactModule?.ExactEvmScheme) {\n throw new Error('@x402/evm not installed — `npm install @x402/evm` for x402 base rails.');\n }\n /* v8 ignore stop */\n registerX402SchemesV1V2(server, network, new evmExactModule.ExactEvmScheme());\n }\n }\n }\n\n for (const { network, scheme } of opts.schemes ?? []) {\n registerX402SchemesV1V2(server, network, scheme);\n }\n\n if (opts.bazaar) {\n const bazaar = await dynamicImport<BazaarModule>('@x402/extensions/bazaar');\n /* v8 ignore start -- peer-dep-absence guard; @x402/extensions is installed in test env */\n if (!bazaar?.bazaarResourceServerExtension) {\n throw new Error(\n '@x402/extensions not installed — `npm install @x402/extensions` for bazaar discovery.',\n );\n }\n /* v8 ignore stop */\n server.registerExtension(bazaar.bazaarResourceServerExtension);\n }\n\n if (opts.initialize !== false) {\n await server.initialize();\n }\n return server;\n}\n\nexport interface BuildX402AcceptsForOptions {\n network: string;\n price: string;\n payTo: string;\n scheme?: string;\n maxTimeoutSeconds?: number;\n extensions?: string[];\n}\n\n/**\n * Build x402 `accepts[]` entries for a 402 challenge body.\n *\n * Wraps `server.buildPaymentRequirements(...)` so merchants don't have to:\n *\n * 1. Construct the resource-config object themselves\n * 2. Remember to serialize each Pydantic-equivalent requirement back to a\n * plain object before stitching it into the 402 body\n * 3. Hardcode `extra` (which differs by the actual on-chain contract — base\n * mainnet USDC has `name: \"USD Coin\"`, base sepolia USDC has `name: \"USDC\"`;\n * EIP-712 domain hashes differ, so getting this wrong silently breaks every\n * signature verify at the facilitator)\n *\n * Returns a list of plain objects in the shape that x402 expects on the wire —\n * drop them straight into the `accepts` field of the 402 challenge body.\n */\nexport async function buildX402AcceptsFor402(\n server: X402Server,\n opts: BuildX402AcceptsForOptions,\n): Promise<unknown[]> {\n const requirements = await server.buildPaymentRequirements(\n {\n scheme: opts.scheme ?? 'exact',\n network: opts.network,\n price: opts.price,\n payTo: opts.payTo,\n maxTimeoutSeconds: opts.maxTimeoutSeconds ?? 300,\n },\n opts.extensions,\n );\n return Array.isArray(requirements) ? requirements : [];\n}\n\nasync function dynamicImport<T>(moduleName: string): Promise<T | null> {\n try {\n return (await import(moduleName)) as T;\n } catch {\n return null;\n }\n}\n","/**\n * `processX402Settle`: single-call x402 verify+settle for merchants.\n *\n * Wraps the four x402-server steps every x402-accepting merchant repeats:\n * 1. `buildPaymentRequirements(resourceConfig)`: builds the requirement entries the\n * facilitator validates against\n * 2. `enrichExtensions(extension, transportContext)`: folds in Bazaar (or other)\n * extensions for the verify step\n * 3. `processPaymentRequest(payload, resourceConfig, resourceMeta, extensions)`:\n * runs verify against the facilitator\n * 4. `settlePayment(payload, matchedRequirement)`: settles on-chain\n *\n * Returns a tagged result so the caller can map errors to merchant-shaped responses\n * without owning the orchestration boilerplate. Use `classifyX402SettleResult` to\n * map the tagged result to a recommended HTTP response.\n */\n\nimport type { X402Server } from './x402_server';\n\nexport type ProcessX402SettleResult =\n | {\n success: true;\n /** The matched requirement passed to `settlePayment`. */\n matchedRequirement: unknown;\n /** The settlement response from the facilitator. */\n settleResult: unknown;\n /** Base64-encoded JSON of `settleResult`, ready to set as the `payment-response`\n * HTTP header on the merchant's success response. x402 clients (`@x402/fetch`,\n * `agentscore-pay`) read this to confirm settlement landed. `undefined` when\n * there's no settle result (shouldn't happen on success path but typed defensively). */\n paymentResponseHeader: string | undefined;\n /** The x402 server's `processPaymentRequest` verify result. */\n verifyResult: { success: true; [key: string]: unknown };\n }\n /** No-requirements branch: `buildPaymentRequirements` returned an empty array, so\n * there is nothing to verify against. Indicates a merchant-side misconfiguration\n * (resource config doesn't match any registered scheme/network).\n * Recommended response: log `reason` server-side; map to a controlled 500 to the\n * consumer via `classifyX402SettleResult`. */\n | { success: false; phase: 'no_requirements'; reason: string }\n /** Verify-failed branch: the facilitator's verify step ran and returned\n * `{ success: false, ... }`. Payload is structurally invalid, expired, signed by\n * the wrong wallet, or otherwise rejected by facilitator policy.\n * Recommended response: log `verifyResult` server-side; map to a controlled 400\n * with `payment_proof_invalid` to the consumer via `classifyX402SettleResult`. */\n | { success: false; phase: 'verify_failed'; verifyResult: unknown }\n /** Settle-failed branch: verify succeeded but `settlePayment` threw (on-chain\n * rejection, RPC outage, facilitator broadcast failure, etc.). The agent's\n * credential was valid; funds did not move.\n * Recommended response: log raw `error` server-side; map to a controlled 503 with\n * `payment_provider_unavailable` to the consumer via `classifyX402SettleResult`. */\n | { success: false; phase: 'settle_failed'; error: unknown; matchedRequirement: unknown }\n | {\n success: false;\n /** Facilitator threw an unexpected error during one of the verify-stage calls\n * (build requirements, extension enrich, or processPaymentRequest). Most common\n * cause: the facilitator client rejects the configured network. Coinbase's CDP\n * facilitator throws on Solana devnet because it only supports mainnet networks;\n * Stripe's SPT facilitator throws on EVM networks; etc.\n * Recommended response: log raw `error` server-side; map to a controlled 503\n * with `payment_provider_unavailable` to the consumer via `classifyX402SettleResult`\n * so the agent can pick a different rail. */\n phase: 'facilitator_error';\n /** Which verify-stage step threw. */\n step: 'build_requirements' | 'enrich_extensions' | 'verify_payment';\n error: unknown;\n };\n\n/**\n * The merchant-shaped response for a non-success `ProcessX402SettleResult`.\n *\n * `status` / `code` / `message` are safe to send back to the consumer. `nextSteps`\n * is the agent-instructions block describing what the agent should do next. Raw\n * facilitator errors stay server-side: do NOT serialize the original `error` /\n * `verifyResult` / `reason` to the consumer; log them yourself.\n */\nexport interface ClassifiedX402Error {\n status: 400 | 500 | 503;\n code:\n | 'payment_proof_invalid'\n | 'payment_provider_unavailable'\n | 'payment_internal_error';\n message: string;\n nextSteps: {\n action: string;\n user_message: string;\n retry_after_seconds?: number;\n };\n}\n\n/**\n * Map a `ProcessX402SettleResult` to the recommended merchant response.\n *\n * Returns `null` for `success: true`. For each error phase, returns a controlled\n * status / code / message / nextSteps tuple. Replaces error-message string-sniffing\n * with a phase-based dispatch so merchants stop coupling to facilitator-specific\n * error text.\n *\n * Phase mapping:\n * - `verify_failed` → 400 `payment_proof_invalid` / `regenerate_payment_credential`\n * - `facilitator_error` → 503 `payment_provider_unavailable` / `try_different_rail`\n * - `settle_failed` → 503 `payment_provider_unavailable` / `retry_or_swap_method`\n * - `no_requirements` → 500 `payment_internal_error` / `contact_support`\n *\n * Always log the raw `result` server-side before responding; the returned object\n * is intentionally facilitator-agnostic and never carries raw error detail.\n */\nexport function classifyX402SettleResult(\n result: ProcessX402SettleResult,\n): ClassifiedX402Error | null {\n if (result.success) return null;\n switch (result.phase) {\n case 'no_requirements':\n return {\n status: 500,\n code: 'payment_internal_error',\n message: 'Failed to build x402 payment requirements for this configuration',\n nextSteps: {\n action: 'contact_support',\n user_message:\n 'The merchant could not produce a payment challenge for this request. Try again later or contact support.',\n },\n };\n case 'verify_failed':\n return {\n status: 400,\n code: 'payment_proof_invalid',\n message: 'Payment credential failed verification; regenerate from a fresh 402 challenge',\n nextSteps: {\n action: 'regenerate_payment_credential',\n user_message:\n 'The payment credential was rejected at verify time. Discard it, fetch a fresh 402 challenge, and re-sign.',\n },\n };\n case 'facilitator_error':\n return {\n status: 503,\n code: 'payment_provider_unavailable',\n message: 'Payment provider could not process this network configuration',\n nextSteps: {\n action: 'try_different_rail',\n user_message:\n 'This rail is currently unavailable. Pick a different rail from the 402 challenge and retry.',\n },\n };\n case 'settle_failed':\n return {\n status: 503,\n code: 'payment_provider_unavailable',\n message: 'Payment credential verified but on-chain settlement failed',\n nextSteps: {\n action: 'retry_or_swap_method',\n retry_after_seconds: 10,\n user_message:\n 'Transient settlement error. Retry in a few seconds, or pick a different rail from the 402 challenge.',\n },\n };\n }\n}\n\n/**\n * Classify a thrown error during the 402 orchestration.\n *\n * Catches errors that escape `processX402Settle` (e.g. raised by `mppx.compose`,\n * a Stripe SDK call, or any other payment-side library code wrapped in a single\n * `try/catch` around the full settle flow). Returns a `ClassifiedX402Error`\n * when the error message matches a known pattern; `null` otherwise.\n *\n * Callers should rethrow on `null` — this helper never swallows unknown errors.\n *\n * Pattern matching is case-insensitive substring on the error message:\n * - `\"x402version\"` / `\"invalid payment\"` / `\"unsupported x402\"` →\n * 400 `payment_proof_invalid` / `regenerate_payment_credential`\n * - `\"stripe\"` / `\"facilitator\"` / `\"cdp\"` →\n * 503 `payment_provider_unavailable` / `retry_or_swap_method`\n * - Anything else → `null` (caller rethrows)\n *\n * Substring matching is intentionally narrow. New error families should land\n * here explicitly rather than have the helper grow opaque heuristics. For\n * tagged failure results that already classify themselves, use\n * `classifyX402SettleResult`.\n */\nexport function classifyOrchestrationError(err: unknown): ClassifiedX402Error | null {\n let msg: string;\n if (err instanceof Error) {\n msg = err.message;\n } else if (typeof err === 'string') {\n msg = err;\n } else {\n return null;\n }\n const msgLower = msg.toLowerCase();\n\n if (\n msgLower.includes('x402version') ||\n msgLower.includes('invalid payment') ||\n msgLower.includes('unsupported x402')\n ) {\n return {\n status: 400,\n code: 'payment_proof_invalid',\n message: 'Payment credential is malformed or uses an unsupported version',\n nextSteps: {\n action: 'regenerate_payment_credential',\n user_message:\n 'The payment credential is malformed or uses an unsupported version. Regenerate from a fresh 402 challenge and re-sign.',\n },\n };\n }\n\n if (\n msgLower.includes('stripe') ||\n msgLower.includes('facilitator') ||\n msgLower.includes('cdp')\n ) {\n return {\n status: 503,\n code: 'payment_provider_unavailable',\n message: 'Payment provider returned an error',\n nextSteps: {\n action: 'retry_or_swap_method',\n retry_after_seconds: 10,\n user_message:\n 'Transient payment-provider error. Retry in a few seconds, or pick a different rail from the 402 challenge.',\n },\n };\n }\n\n return null;\n}\n\nexport async function processX402Settle({\n x402Server,\n payload,\n resourceConfig,\n resourceMeta,\n extension,\n transportContext,\n}: {\n /** The x402 server instance from `createX402Server`. */\n x402Server: X402Server;\n /** The verified x402 payload extracted from the X-Payment header. */\n payload: unknown;\n /** Resource configuration the facilitator validates against (network, price, payTo,\n * asset, maxTimeoutSeconds, etc.). Shape is x402-server-specific. */\n resourceConfig: unknown;\n /** Resource metadata exposed to the facilitator (URL, description, mime type). */\n resourceMeta: { url: string; description: string; mimeType: string };\n /** Optional extension to enrich during verify (e.g. Bazaar). */\n extension?: unknown;\n /** Transport context for the extension enrich step. Defaults to `{ method: 'POST',\n * adapter: { getPath: () => new URL(resourceMeta.url).pathname }, routePattern: <pathname> }`. */\n transportContext?: unknown;\n}): Promise<ProcessX402SettleResult> {\n const server = x402Server as unknown as {\n buildPaymentRequirements: (cfg: unknown) => Promise<unknown[]>;\n enrichExtensions: (ext: unknown, ctx: unknown) => unknown;\n verifyPayment: (\n paymentPayload: unknown,\n requirements: unknown,\n declaredExtensions?: unknown,\n transportContext?: unknown,\n ) => Promise<{ success: boolean; [key: string]: unknown } | { isValid?: boolean; [key: string]: unknown }>;\n settlePayment: (\n paymentPayload: unknown,\n requirements: unknown,\n declaredExtensions?: unknown,\n transportContext?: unknown,\n ) => Promise<unknown>;\n };\n\n let builtRequirements: unknown[];\n try {\n builtRequirements = await server.buildPaymentRequirements(resourceConfig);\n } catch (err) {\n console.warn('[x402_settle] build_requirements failed:', err instanceof Error ? err.message : err);\n return { success: false, phase: 'facilitator_error', step: 'build_requirements', error: err };\n }\n const matchedRequirement = builtRequirements[0];\n if (!matchedRequirement) {\n return { success: false, phase: 'no_requirements', reason: 'x402Server.buildPaymentRequirements returned empty' };\n }\n\n const resolvedTransportContext = transportContext ?? (() => {\n const path = new URL(resourceMeta.url).pathname;\n return { method: 'POST', adapter: { getPath: () => path }, routePattern: path };\n })();\n\n let enrichedExt: unknown;\n try {\n enrichedExt = extension !== undefined\n ? server.enrichExtensions(extension, resolvedTransportContext)\n : undefined;\n } catch (err) {\n console.warn('[x402_settle] enrich_extensions failed:', err instanceof Error ? err.message : err);\n return { success: false, phase: 'facilitator_error', step: 'enrich_extensions', error: err };\n }\n\n let verifyResult: { success?: boolean; isValid?: boolean; [key: string]: unknown };\n try {\n verifyResult = await server.verifyPayment(\n payload,\n matchedRequirement,\n enrichedExt as Record<string, unknown> | undefined,\n resolvedTransportContext,\n );\n } catch (err) {\n console.warn('[x402_settle] verify_payment failed:', err instanceof Error ? err.message : err);\n return { success: false, phase: 'facilitator_error', step: 'verify_payment', error: err };\n }\n\n // x402/core's ResourceVerifyResponse uses `isValid` (per spec). Accept the\n // legacy `success` field too for older facilitator builds.\n const verifyOk = verifyResult.isValid === true || verifyResult.success === true;\n if (!verifyOk) {\n return { success: false, phase: 'verify_failed', verifyResult };\n }\n\n try {\n const settleResult = await server.settlePayment(\n payload,\n matchedRequirement,\n enrichedExt as Record<string, unknown> | undefined,\n resolvedTransportContext,\n );\n const paymentResponseHeader = settleResult\n ? Buffer.from(JSON.stringify(settleResult)).toString('base64')\n : undefined;\n return {\n success: true,\n matchedRequirement,\n settleResult,\n paymentResponseHeader,\n verifyResult: verifyResult as { success: true; [key: string]: unknown },\n };\n } catch (err) {\n return { success: false, phase: 'settle_failed', error: err, matchedRequirement };\n }\n}\n","/**\n * x402 boot-time + per-request validation helpers.\n *\n * Two layers of validation every x402-accepting merchant repeats:\n *\n * - **Boot-time**: validate the configured `X402_BASE_NETWORK` env var is in the\n * supported set. Failing loud at boot is much better than per-request \"unsupported\n * network\" errors after a misconfigured deploy.\n *\n * - **Per-request**: when an x402 X-Payment header arrives, parse the base64 payload,\n * extract the signed network + payTo, validate against the merchant's accepted\n * network, validate the payTo address shape, and check that the payTo was minted by\n * THIS merchant (cache hit). Each step has its own denial code and `next_steps`\n * shape — getting the message right by hand across 4 conditions is fiddly.\n */\n\nimport { networks } from './networks';\n\n/** CAIP-2 networks the commerce SDK supports for x402 Base (EVM USDC). */\nexport const X402_SUPPORTED_BASE_NETWORKS = new Set<string>([\n networks.base.mainnet.caip2,\n networks.base.sepolia.caip2,\n]);\n\n/**\n * Boot-time guard: throws if the base network isn't supported. Call once at module\n * init / server boot.\n *\n * Throws `Error` with a message that names the unsupported value AND lists the valid\n * options — agents tracking down a misconfigured deploy don't need to grep for the\n * supported list.\n */\nexport function validateX402NetworkConfig({ baseNetwork }: { baseNetwork: string }): void {\n if (!X402_SUPPORTED_BASE_NETWORKS.has(baseNetwork)) {\n throw new Error(\n `X402_BASE_NETWORK=${baseNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_BASE_NETWORKS].join(', ')}`,\n );\n }\n}\n\nconst EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;\n\nexport type VerifyX402RequestResult =\n | {\n ok: true;\n /** The base64-decoded JSON payload from the X-Payment header. */\n payload: { accepted?: { network?: string; payTo?: string }; [key: string]: unknown };\n /** The CAIP-2 network the agent signed for. */\n signedNetwork: string;\n /** The on-chain pay-to address the agent signed for (already validated). */\n signedPayTo: string;\n }\n | {\n ok: false;\n /** Suitable as a JSON body for the merchant's denial response. Includes\n * `next_steps` with `regenerate_payment_credential` action + a per-condition\n * `user_message` and a footgun `warning` so agents can recover deterministically\n * from the response alone. */\n body: {\n error: { code: string; message: string };\n next_steps: {\n action: 'regenerate_payment_credential';\n user_message: string;\n warning: string;\n };\n };\n /** HTTP status to use for the denial response. */\n status: 400;\n };\n\nconst REGENERATE_WARNING =\n 'Use `agentscore-pay pay --chain base` (or `tempo request` for Tempo USDC) so the credential is signed and submitted via the protocol handshake. Do NOT use `tempo wallet transfer` — that sends USDC on-chain but does not complete the handshake.';\n\nfunction regenerateBody(message: string, userMessage: string) {\n return {\n error: { code: 'payment_proof_invalid' as const, message },\n next_steps: {\n action: 'regenerate_payment_credential' as const,\n user_message: userMessage,\n warning: REGENERATE_WARNING,\n },\n };\n}\n\n/**\n * Per-request: parse the x402 X-Payment header, validate the network + payTo, and\n * confirm the address was minted by this merchant. One call replaces ~45 lines of\n * inline header decode + regex validation + cache lookup.\n *\n * Returns `{ok: true, payload, signedNetwork, signedPayTo}` when valid; the caller\n * passes `payload` straight into `processX402Settle`.\n *\n * Returns `{ok: false, body, status}` when invalid — the merchant just does\n * `return c.json(body, status)` (or framework equivalent).\n *\n * Reads the header from `payment-signature` first, falling back to `x-payment` (both\n * are in the wild as the binary-friendly transport name evolved).\n */\nexport async function verifyX402Request({\n request,\n isCachedAddress,\n acceptedNetwork,\n}: {\n /** The incoming Request — `verifyX402Request` reads the X-Payment / payment-signature header. */\n request: Request;\n /** Async lookup that returns true when the address was minted by this merchant\n * (typically `piCache.hasAddress`). The check validates that the credential's\n * deposit address matches one the merchant actually minted. */\n isCachedAddress: (address: string) => Promise<boolean>;\n /** The merchant's accepted Base network. CAIP-2, e.g. `'eip155:8453'`. */\n acceptedNetwork: string;\n}): Promise<VerifyX402RequestResult> {\n const headerValue =\n request.headers.get('payment-signature')\n ?? request.headers.get('x-payment');\n if (!headerValue) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n 'X-Payment header missing',\n 'No X-Payment header was sent. Generate the credential from the 402 challenge and resubmit on the same endpoint.',\n ),\n };\n }\n\n let payload: { accepted?: { network?: string; payTo?: string }; [key: string]: unknown };\n try {\n payload = JSON.parse(Buffer.from(headerValue, 'base64').toString());\n } catch {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n 'X-Payment header is not valid base64 JSON',\n 'The payment credential could not be decoded. Reconstruct the credential from the 402 challenge and retry.',\n ),\n };\n }\n\n const signedNetwork = payload.accepted?.network;\n const signedPayTo = payload.accepted?.payTo;\n\n if (!signedNetwork || signedNetwork !== acceptedNetwork) {\n if (signedNetwork && signedNetwork.toLowerCase().startsWith('solana:')) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n `x402 on ${signedNetwork} is not accepted; Solana payments must use the \\`solana/charge\\` rail advertised in the 402 challenge. This server accepts x402 on ${acceptedNetwork} only.`,\n 'Solana payments are not accepted over x402 at this merchant. Pick the `solana/charge` rail from the 402 challenge and re-sign.',\n ),\n };\n }\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n `Unsupported x402 network ${signedNetwork ?? '<missing>'}; this server accepts ${acceptedNetwork}.`,\n 'The credential signed for an unsupported network. Pick the accepted network from the 402 challenge and re-sign.',\n ),\n };\n }\n\n const addressShapeOk = typeof signedPayTo === 'string' && EVM_ADDRESS_RE.test(signedPayTo);\n\n if (!signedPayTo || !addressShapeOk) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n `Payment payload missing or malformed accepted.payTo address for network ${signedNetwork}`,\n 'The credential payload is missing or malformed payTo for the signed network. Reconstruct the credential from the 402 challenge.',\n ),\n };\n }\n\n if (!(await isCachedAddress(signedPayTo))) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n 'payTo address not found in cache or expired. Request a fresh 402 challenge and retry.',\n 'The deposit address is unknown or expired on this server. Request a fresh 402 challenge and re-sign against the new payTo.',\n ),\n };\n }\n\n return { ok: true, payload, signedNetwork, signedPayTo };\n}\n","/**\n * Wraps the `mppStripe.charge(...)` boilerplate from `mppx/server`. Returns the value\n * vendors pass into `Mppx.create({ methods: [...] })`. mppx is an OPTIONAL peer dependency —\n * vendors who don't use Stripe SPT don't need to install it.\n *\n * Example:\n *\n * import { Mppx, tempo } from 'mppx/server';\n * import { createMppxStripe } from '@agent-score/commerce/stripe-multichain';\n *\n * const stripeMethod = await createMppxStripe({\n * profileId: process.env.STRIPE_PROFILE_ID!,\n * secretKey: process.env.STRIPE_SECRET_KEY!,\n * });\n *\n * const mppx = Mppx.create({\n * methods: [tempo.charge({...}), stripeMethod],\n * secretKey: process.env.MPP_SECRET_KEY!,\n * });\n *\n * Throws if mppx is not installed.\n */\nexport async function createMppxStripe({\n profileId,\n secretKey,\n paymentMethodTypes,\n}: {\n /** Stripe profile_id / network_id (the value advertised in your `stripe/charge` accepted_methods entry). */\n profileId: string;\n /** Stripe secret key — mppx uses it to validate inbound SharedPaymentTokens. */\n secretKey: string;\n /** Payment method types this stripe rail accepts. Default ['card', 'link']. */\n paymentMethodTypes?: string[];\n}): Promise<unknown> {\n const moduleName = 'mppx/server';\n const mppx = (await import(moduleName).catch(() => null)) as {\n stripe?: {\n charge: (config: {\n networkId: string;\n paymentMethodTypes?: string[];\n secretKey: string;\n }) => unknown;\n };\n } | null;\n /* v8 ignore start -- peer-dep-absence guard; mppx is installed in the test env so this branch can't be exercised without mocking the dynamic import */\n if (!mppx?.stripe?.charge) {\n throw new Error(\n 'mppx not installed — install with `npm install mppx` to use createMppxStripe.',\n );\n }\n /* v8 ignore stop */\n return mppx.stripe.charge({\n networkId: profileId,\n paymentMethodTypes: paymentMethodTypes ?? ['card', 'link'],\n secretKey,\n });\n}\n","import { createMppxStripe } from '../stripe-multichain/mppx_stripe';\nimport { networks } from './networks';\nimport {\n resolveRecipient,\n type SolanaMppRailSpec,\n type StripeRailSpec,\n type TempoRailSpec,\n type TempoSessionRailSpec,\n} from './rail_spec';\nimport { USDC } from './usdc';\n\nexport type MppxRailSpec =\n | TempoRailSpec\n | SolanaMppRailSpec\n | TempoSessionRailSpec\n | StripeRailSpec;\n\ntype SolanaMppNetwork = 'mainnet-beta' | 'devnet' | 'localnet';\n\ninterface MppxModule {\n Mppx?: { create: (opts: { methods: unknown[]; secretKey: string }) => unknown };\n tempo?: {\n charge: (opts: { currency: string; recipient: string; testnet?: boolean }) => unknown;\n session?: (opts: {\n currency: string;\n recipient: string;\n escrowContract: string;\n store: unknown;\n testnet?: boolean;\n chains?: unknown;\n }) => unknown;\n };\n}\n\ninterface SolanaMppModule {\n charge?: (opts: {\n recipient: string;\n currency?: string;\n decimals?: number;\n network?: string;\n rpcUrl?: string;\n signer?: unknown;\n tokenProgram?: string;\n }) => unknown;\n}\n\nfunction isStripeRailSpec(s: MppxRailSpec): s is StripeRailSpec {\n return !('recipient' in s);\n}\n\nfunction isTempoSessionRailSpec(s: MppxRailSpec): s is TempoSessionRailSpec {\n return 'escrowContract' in s && 'store' in s;\n}\n\nfunction isSolanaMppRailSpec(s: MppxRailSpec): s is SolanaMppRailSpec {\n if (!('recipient' in s)) return false;\n if ('escrowContract' in s) return false;\n if ('rpcUrl' in s || 'tokenProgram' in s) return true;\n return (s as { network?: string }).network?.startsWith('solana:') ?? false;\n}\n\nfunction solanaNetworkFromCAIP2(caip2: string | undefined): SolanaMppNetwork {\n if (caip2 === networks.solana.devnet.caip2) return 'devnet';\n return 'mainnet-beta';\n}\n\nfunction solanaDefaultRpcUrl(network: SolanaMppNetwork): string {\n if (network === 'mainnet-beta') return 'https://api.mainnet-beta.solana.com';\n if (network === 'devnet') return 'https://api.devnet.solana.com';\n return 'http://localhost:8899';\n}\n\n/**\n * One-call mppx server setup. Wires `tempo.charge(...)`, `tempo.session(...)`,\n * `@solana/mpp.charge(...)`, and Stripe SPT (via createMppxStripe) from canonical\n * `*RailSpec` configs, replacing the boilerplate of constructing each method by\n * hand.\n *\n * const mppx = await createMppxServer({\n * rails: {\n * tempo: { recipient: TEMPO_ADDR } satisfies TempoRailSpec,\n * solana: { recipient: SOL_ADDR } satisfies SolanaMppRailSpec,\n * stripe: { profileId: STRIPE_PROFILE_ID, secretKey: STRIPE_SECRET_KEY } satisfies StripeRailSpec,\n * },\n * secretKey: MPP_SECRET_KEY,\n * });\n *\n * Keys are rail names (`tempo` / `solana` / `tempo_session` / `stripe`); values\n * are the matching `*RailSpec` types every other helper also consumes.\n *\n * `mppx` is an OPTIONAL peer dependency — install it only if you accept MPP rails.\n */\nexport async function createMppxServer({\n rails,\n methods: extraMethods,\n secretKey,\n}: {\n rails?: Record<string, MppxRailSpec>;\n methods?: unknown[];\n secretKey: string;\n}): Promise<unknown> {\n const mppx = await dynamicImport<MppxModule>('mppx/server');\n /* v8 ignore start -- peer-dep-absence guard; mppx is installed in the test env */\n if (!mppx?.Mppx?.create) {\n throw new Error('mppx not installed — `npm install mppx` to use createMppxServer.');\n }\n /* v8 ignore stop */\n\n const methods: unknown[] = [...(extraMethods ?? [])];\n\n for (const [name, spec] of Object.entries(rails ?? {})) {\n if (isStripeRailSpec(spec)) {\n methods.push(await registerStripe(spec));\n continue;\n }\n if (isTempoSessionRailSpec(spec)) {\n methods.push(await registerTempoSession(mppx, spec));\n continue;\n }\n if (isSolanaMppRailSpec(spec)) {\n methods.push(await registerSolana(spec));\n continue;\n }\n // Default: TempoRailSpec (bare `{recipient, ...}` with no Solana / session markers).\n methods.push(registerTempo(mppx, spec as TempoRailSpec, name));\n }\n\n return mppx.Mppx.create({ methods, secretKey });\n}\n\nfunction registerTempo(mppx: MppxModule, spec: TempoRailSpec, _name: string): unknown {\n /* v8 ignore start -- peer-dep version-mismatch guard; current mppx ships tempo.charge */\n if (!mppx.tempo?.charge) {\n throw new Error('mppx.tempo.charge not available — check installed mppx version.');\n }\n /* v8 ignore stop */\n const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;\n if (typeof spec.recipient !== 'string') {\n throw new TypeError(\n 'createMppxServer: TempoRailSpec requires a string recipient (per-order factories not supported here).',\n );\n }\n return mppx.tempo.charge({\n currency: spec.token ?? defaultCurrency,\n recipient: spec.recipient,\n testnet: spec.testnet ?? false,\n });\n}\n\nasync function registerTempoSession(mppx: MppxModule, spec: TempoSessionRailSpec): Promise<unknown> {\n /* v8 ignore start -- peer-dep version-mismatch guard; current mppx ships tempo.session */\n if (!mppx.tempo?.session) {\n throw new Error(\n 'mppx.tempo.session not available — your mppx version may not support sessions yet. Upgrade with `npm install mppx@latest`.',\n );\n }\n /* v8 ignore stop */\n const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;\n return mppx.tempo.session({\n currency: spec.currency ?? defaultCurrency,\n recipient: await resolveRecipient(spec.recipient),\n escrowContract: spec.escrowContract,\n store: spec.store,\n testnet: spec.testnet ?? false,\n ...(spec.chains ? { chains: spec.chains } : {}),\n });\n}\n\nasync function registerSolana(spec: SolanaMppRailSpec): Promise<unknown> {\n const solanaMpp = await dynamicImport<SolanaMppModule>('@solana/mpp/server');\n if (!solanaMpp?.charge) {\n throw new Error(\n '@solana/mpp not installed — `npm install @solana/mpp @solana/kit` to use the solana rail.',\n );\n }\n const network = solanaNetworkFromCAIP2(spec.network);\n const defaultMint =\n network === 'mainnet-beta' ? USDC.solana.mainnet.mint : USDC.solana.devnet.mint;\n const defaultDecimals =\n network === 'mainnet-beta' ? USDC.solana.mainnet.decimals : USDC.solana.devnet.decimals;\n if (typeof spec.recipient !== 'string') {\n throw new TypeError(\n 'createMppxServer: SolanaMppRailSpec requires a string recipient (per-order factories not supported here).',\n );\n }\n const baseMethod = solanaMpp.charge({\n recipient: spec.recipient,\n currency: spec.token ?? defaultMint,\n decimals: spec.decimals ?? defaultDecimals,\n network,\n ...(spec.rpcUrl ? { rpcUrl: spec.rpcUrl } : {}),\n ...(spec.signer ? { signer: spec.signer } : {}),\n ...(spec.tokenProgram ? { tokenProgram: spec.tokenProgram } : {}),\n }) as SolanaChargeMethod;\n return wrapSolanaChargeWithFinalizedBlockhash(baseMethod, spec.rpcUrl ?? solanaDefaultRpcUrl(network));\n}\n\nasync function registerStripe(spec: StripeRailSpec): Promise<unknown> {\n if (!spec.profileId || !spec.secretKey) {\n throw new Error(\n 'createMppxServer: StripeRailSpec requires both profileId and secretKey.',\n );\n }\n return createMppxStripe({\n profileId: spec.profileId,\n secretKey: spec.secretKey,\n paymentMethodTypes: spec.paymentMethodTypes,\n });\n}\n\nasync function dynamicImport<T>(moduleName: string): Promise<T | null> {\n try {\n return (await import(moduleName)) as T;\n } catch {\n return null;\n }\n}\n\ntype SolanaChargeRequestArgs = { credential?: unknown; request?: unknown };\ntype SolanaChargeMethod = {\n request?: (args: SolanaChargeRequestArgs) => Promise<unknown>;\n} & Record<string, unknown>;\n\n/**\n * Wraps `@solana/mpp.charge()`'s Method so the issued challenge carries a\n * `finalized` blockhash instead of `confirmed`.\n *\n * `@solana/mpp` <= 0.5.2 fetches `getLatestBlockhash` with `commitment: 'confirmed'`\n * but its broadcast `sendTransaction` sets `skipPreflight: false` without an\n * overridden `preflightCommitment`. The RPC server's default preflight commitment\n * is `finalized`, which rejects any blockhash that hasn't yet finalized with a\n * \"Blockhash not found\" error. Handing the client a `finalized` blockhash up\n * front sidesteps the mismatch.\n *\n * Trade-off: the signing window shrinks from ~58s (confirmed) to ~46s (finalized).\n * Fine for agent-driven flows; manual signing flows still have plenty of margin.\n */\nexport function wrapSolanaChargeWithFinalizedBlockhash(\n baseMethod: SolanaChargeMethod,\n rpcUrl: string,\n): SolanaChargeMethod {\n return {\n ...baseMethod,\n async request(args: SolanaChargeRequestArgs) {\n const orig = (await baseMethod.request!(args)) as\n | { methodDetails?: Record<string, unknown> }\n | undefined;\n if (args.credential || !orig || typeof orig !== 'object') return orig;\n try {\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: 1,\n jsonrpc: '2.0',\n method: 'getLatestBlockhash',\n params: [{ commitment: 'finalized' }],\n }),\n });\n const data = (await res.json()) as { result?: { value?: { blockhash?: string } } };\n const finalized = data?.result?.value?.blockhash;\n if (finalized) {\n return {\n ...orig,\n methodDetails: { ...(orig.methodDetails ?? {}), recentBlockhash: finalized },\n };\n }\n } catch {\n /* fall back to upstream's confirmed blockhash */\n }\n return orig;\n },\n };\n}\n","/**\n * Detect which payment-protocol family the inbound request carries.\n *\n * Returns `\"mpp\"` when an `Authorization` header starts with the `Payment`\n * scheme (case-insensitive per RFC 7235). Returns `\"x402\"` when a non-empty\n * `payment-signature` or `x-payment` header is present. Returns `null` otherwise.\n *\n * In practice a client constructs a request with exactly one protocol's headers;\n * both arriving together is a client bug or misconfigured proxy. The helper checks\n * MPP first so the rare degenerate case resolves to MPP. Empty header values are\n * treated as absent. Header-name lookups are case-insensitive (RFC 7230 §3.2).\n * The narrower rail naming (`\"tempo\"` vs `\"solana\"` inside MPP) is merchant-side,\n * derived from the credential body, not this helper.\n *\n * Accepts either a Web Fetch `Headers` instance (case-insensitive lookup native)\n * or a plain object (case-insensitive lookup applied internally).\n */\nexport function detectRailFromHeaders(\n headers: Headers | Record<string, string | string[] | undefined>,\n): 'x402' | 'mpp' | null {\n const get = (name: string): string => {\n if (headers instanceof Headers) {\n return headers.get(name) ?? '';\n }\n const lower = name.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) {\n // `null` is outside the TypeScript input type, but plain-JS callers can\n // still reach here with `{ 'x-payment': null }`; guard so `.toLowerCase()`\n // on the result doesn't throw downstream.\n if (v === undefined || v === null) return '';\n return Array.isArray(v) ? (v[0] ?? '') : v;\n }\n }\n return '';\n };\n\n const auth = get('authorization');\n if (auth.toLowerCase().startsWith('payment ')) {\n return 'mpp';\n }\n if (get('payment-signature') || get('x-payment')) {\n return 'x402';\n }\n return null;\n}\n\nexport interface SettlementHandlers<TPayload, TResult> {\n evm?: (payload: TPayload) => TResult | Promise<TResult>;\n svm?: (payload: TPayload) => TResult | Promise<TResult>;\n}\n\nexport interface SettlementPayloadLike {\n accepted: { network: string };\n}\n\n/**\n * Dispatches a settlement payload to the right network-family handler based on\n * the CAIP-2 network string in `payload.accepted.network`:\n *\n * - eip155:* → handlers.evm\n * - solana:* → handlers.svm\n *\n * Throws if the network is unrecognized or the matching handler is missing.\n * Most vendors will register handlers for both rail families they accept.\n */\nexport async function dispatchSettlementByNetwork<\n TPayload extends SettlementPayloadLike,\n TResult,\n>(\n payload: TPayload,\n handlers: SettlementHandlers<TPayload, TResult>,\n): Promise<TResult> {\n const network = payload.accepted.network;\n if (network.startsWith('eip155:')) {\n if (!handlers.evm) {\n throw new Error(`No EVM settlement handler registered (network: ${network})`);\n }\n return handlers.evm(payload);\n }\n if (network.startsWith('solana:')) {\n if (!handlers.svm) {\n throw new Error(`No Solana settlement handler registered (network: ${network})`);\n }\n return handlers.svm(payload);\n }\n throw new Error(`Unrecognized network in settlement payload: ${network}`);\n}\n","/**\n * Joins multiple Payment directives into a single WWW-Authenticate header value.\n * Per RFC 7235, multiple challenges are comma-separated.\n */\nexport function wwwAuthenticateHeader(directives: string[]): string {\n return directives.join(', ');\n}\n\n/**\n * Add the v1↔v2 amount-field alias to each accepts entry. Idempotent. Used by both\n * `paymentRequiredHeader` (header emit) and `build402Body` (body emit) so every\n * x402 entry on the wire carries BOTH `amount` (v2 spec) AND `maxAmountRequired`\n * (v1 spec) — strict v1-only parsers (e.g. Coinbase awal at `payments-mcp.coinbase.com`,\n * which is hardcoded to read `maxAmountRequired`) work alongside strict v2 parsers,\n * which ignore the alias.\n */\nexport function aliasAmountFields(accepts: unknown[]): unknown[] {\n return accepts.map((entry) => {\n if (entry === null || typeof entry !== 'object') return entry;\n const e = entry as Record<string, unknown>;\n const hasAmount = e.amount !== undefined;\n const hasMaxAmount = e.maxAmountRequired !== undefined;\n if (hasAmount && !hasMaxAmount) return { ...e, maxAmountRequired: e.amount };\n if (hasMaxAmount && !hasAmount) return { ...e, amount: e.maxAmountRequired };\n return e;\n });\n}\n\n/**\n * Encode the standard x402 PAYMENT-REQUIRED header (base64-encoded JSON of the\n * PaymentRequired object). Clients that recognize the header (`@x402/fetch`,\n * `@x402/core` HTTPClient, `agentscore-pay`) prefer it over body fields.\n *\n * Note: do NOT add a v1↔v2 amount-field alias here. `@x402/core`'s\n * `findMatchingRequirements` uses `deepEqual` against the agent's signed\n * `accepted` payload — any field present on one side and missing on the other\n * (e.g. `maxAmountRequired` on the wire body but not in `buildPaymentRequirements`'s\n * output) makes the match silently fail at settle time. Keep `accepts` shape\n * identical to whatever `buildPaymentRequirements` produces server-side.\n */\nexport function paymentRequiredHeader({\n x402Version,\n accepts,\n resource,\n}: {\n x402Version: 1 | 2;\n accepts: unknown[];\n resource?: { url: string; mimeType?: string };\n}): string {\n return Buffer.from(JSON.stringify({ x402Version, accepts, ...(resource ? { resource } : {}) })).toString('base64');\n}\n","/**\n * Multi-rail payment header bundle — one call composes both `WWW-Authenticate` (the\n * `paymentauth.org` Payment directives) and the standard x402 `PAYMENT-REQUIRED` header\n * from a single rails declaration. Reduces ~10 lines of merchant boilerplate per 402\n * response.\n *\n * Layered on top of `paymentDirective` / `wwwAuthenticateHeader` / `paymentRequiredHeader`\n * — those primitives stay exposed for vendors who want full control.\n */\n\nimport { buildPaymentDirective } from './directive';\nimport { paymentRequiredHeader, wwwAuthenticateHeader } from './wwwauthenticate';\n\nexport interface PaymentHeadersRail {\n /** Symbolic rail name — `tempo-mainnet`, `x402-base-mainnet`, `stripe`, etc. */\n rail: string;\n /** Amount in USD as a number or string. */\n amountUsd: string | number;\n /** Recipient address (on-chain) — required for crypto rails. */\n recipient?: string;\n /** Stripe profile_id / network_id — required for `stripe` rail. */\n networkId?: string;\n /** EVM chain id override — usually inferred from rail. */\n chainId?: number;\n /** Token contract / currency override — usually inferred from rail. */\n currency?: string;\n /** Decimal precision override — usually inferred from rail (USDC=6, etc.). */\n decimals?: number;\n /** MPP method override — usually inferred from rail. */\n method?: string;\n /** MPP intent. Default `charge`. */\n intent?: string;\n /** ISO-8601 expiry. Default now + 5 min. */\n expires?: string;\n}\n\nexport interface PaymentHeadersResult {\n 'www-authenticate': string;\n 'PAYMENT-REQUIRED'?: string;\n}\n\n/**\n * Compose `WWW-Authenticate` (multi-directive) and `PAYMENT-REQUIRED` (x402 base64) headers\n * from a single rails declaration. Returns an object suitable for spreading into a\n * `Headers` constructor or the `headers` field of a `Response`.\n *\n * Example:\n * ```ts\n * const headers = buildPaymentHeaders({\n * orderId: 'ord_123',\n * realm: 'agents.merchant.example',\n * rails: [\n * { rail: 'tempo-mainnet', amountUsd: 25, recipient: TEMPO_ADDR },\n * { rail: 'x402-base-mainnet', amountUsd: 25, recipient: BASE_ADDR },\n * { rail: 'stripe', amountUsd: 25, networkId: STRIPE_PROFILE_ID },\n * ],\n * x402: { accepts: x402Accepts, version: 1 },\n * });\n * return new Response(JSON.stringify(body), { status: 402, headers });\n * ```\n */\nexport function buildPaymentHeaders({\n rails,\n orderId,\n realm,\n x402,\n}: {\n /** Rails the merchant accepts on this 402. Each becomes one `Payment` directive. */\n rails: PaymentHeadersRail[];\n /** Order id used as the directive challenge id (per-rail it becomes `${orderId}-${rail}`). */\n orderId: string;\n /** Realm — the host of the merchant URL (e.g. `agents.merchant.example`). */\n realm: string;\n /**\n * Optional x402 `accepts` array — included as the standard PAYMENT-REQUIRED header so\n * x402 clients (`@x402/fetch`, `@x402/core` HTTPClient, `agentscore-pay`) can parse the\n * base64-encoded JSON form instead of the WWW-Authenticate text directives. Pass\n * `undefined` (or omit) to skip the PAYMENT-REQUIRED header.\n */\n x402?: { accepts: unknown[]; version?: 1 | 2; resource?: { url: string; mimeType?: string } };\n}): PaymentHeadersResult {\n const directives = rails.map((rail) =>\n buildPaymentDirective({\n id: `${orderId}-${rail.rail}`,\n realm,\n rail: rail.rail,\n amountUsd: rail.amountUsd,\n ...(rail.recipient !== undefined ? { recipient: rail.recipient } : {}),\n ...(rail.networkId !== undefined ? { networkId: rail.networkId } : {}),\n ...(rail.chainId !== undefined ? { chainId: rail.chainId } : {}),\n ...(rail.currency !== undefined ? { currency: rail.currency } : {}),\n ...(rail.decimals !== undefined ? { decimals: rail.decimals } : {}),\n ...(rail.method !== undefined ? { method: rail.method } : {}),\n ...(rail.intent !== undefined ? { intent: rail.intent } : {}),\n ...(rail.expires !== undefined ? { expires: rail.expires } : {}),\n }),\n );\n\n const result: PaymentHeadersResult = {\n 'www-authenticate': wwwAuthenticateHeader(directives),\n };\n\n if (x402) {\n result['PAYMENT-REQUIRED'] = paymentRequiredHeader({\n x402Version: x402.version ?? 2,\n accepts: x402.accepts,\n ...(x402.resource ? { resource: x402.resource } : {}),\n });\n }\n\n return result;\n}\n","/**\n * Idempotency-key composition.\n *\n * Stable per-payment keys that retries of the same logical payment can reuse, so AgentScore's\n * `/v1/credentials/wallets` capture endpoint dedupes correctly and the operator's\n * `transaction_count` doesn't inflate.\n *\n * Convention:\n * 1. Prefer the upstream payment-rail's stable identifier (Stripe PaymentIntent id, x402\n * tx hash) when one exists — those are already idempotent on their side.\n * 2. Fall back to a synthesized `pi-{orderId}-{amountCents}` key when no upstream id is\n * available (e.g. pre-creation, or rails without a PI concept).\n * 3. Server caps idempotency keys at 200 chars; this helper warns when that boundary is\n * crossed so a future caller doesn't silently get truncation collisions.\n */\n\nconst SERVER_IDEMPOTENCY_KEY_MAX = 200;\n\n/**\n * Compose a stable idempotency key for AgentScore wallet capture and other retry-safe POSTs.\n *\n * Returns `undefined` when no inputs are present (caller should treat as \"no idempotency\n * key — first attempt only\", same shape as omitting the field entirely).\n *\n * Examples:\n * ```ts\n * buildIdempotencyKey({ paymentIntentId: 'pi_abc' }); // → 'pi_abc'\n * buildIdempotencyKey({ orderId: 'ord_x', amountCents: 25000 }); // → 'pi-ord_x-25000'\n * buildIdempotencyKey({ orderId: 'ord_x' }); // → 'pi-ord_x'\n * buildIdempotencyKey({ paymentIntentId: 'pi_abc', prefix: 'refund' }); // → 'refund-pi_abc'\n * buildIdempotencyKey({}); // → undefined\n * ```\n */\nexport function buildIdempotencyKey({\n paymentIntentId,\n orderId,\n amountCents,\n prefix,\n}: {\n /** Upstream rail's stable payment id — Stripe PaymentIntent id, x402 tx hash, etc. Wins when present. */\n paymentIntentId?: string | null;\n /** Order id — used to compose a fallback key when no paymentIntentId exists. */\n orderId?: string | null;\n /** Amount in cents (or smallest currency unit) — added to the fallback for extra collision resistance. */\n amountCents?: number;\n /** Optional extra prefix to namespace the key (e.g. `\"refund\"`, `\"void\"`). */\n prefix?: string;\n}): string | undefined {\n const prefixPart = prefix ? `${prefix}-` : '';\n\n if (paymentIntentId) {\n const key = `${prefixPart}${paymentIntentId}`;\n return clampKey(key);\n }\n\n if (orderId) {\n const amountSuffix = amountCents !== undefined ? `-${amountCents}` : '';\n const key = `${prefixPart}pi-${orderId}${amountSuffix}`;\n return clampKey(key);\n }\n\n return undefined;\n}\n\nfunction clampKey(key: string): string {\n if (key.length <= SERVER_IDEMPOTENCY_KEY_MAX) return key;\n // Server truncates anyway; surfacing the warning here gives callers a chance to design\n // shorter inputs. We still return the original key (server-side truncation is the source\n // of truth) — clamping client-side would change semantics for any caller already\n // depending on the full string for their own dedup.\n console.warn(\n `[agentscore-commerce] idempotency key longer than ${SERVER_IDEMPOTENCY_KEY_MAX} chars — server will truncate, may cause silent collisions if multiple keys share the first ${SERVER_IDEMPOTENCY_KEY_MAX} chars.`,\n );\n return key;\n}\n","/**\n * Payment-signer extraction.\n *\n * Shared between merchants and the gate. Three paths recover a wallet signer:\n *\n * - **Tempo MPP** — `Authorization: Payment <base64>`; credential `source` is a DID of the\n * form `did:pkh:eip155:<chain>:<address>`.\n * - **Solana MPP `solana/charge`** — `Authorization: Payment <base64>`; recovery via either\n * a `did:pkh:solana:<genesis>:<address>` source (when set by the client) or by decoding\n * the credential's signed-tx payload and reading the SPL `TransferChecked` authority\n * (pull mode only — `payload.type === 'transaction'`).\n * - **x402 EIP-3009 (EVM, e.g. Base/Sepolia)** — `payment-signature` / `x-payment`;\n * decoded payload carries `payload.authorization.from`.\n *\n * Optional peer deps: `mppx` for MPP credentials, `@solana/kit` for the Solana tx-decode\n * fallback. Both dynamic-imported; merchants who don't accept that rail don't need them.\n */\n\nexport type SignerNetwork = 'evm' | 'solana';\n\nconst TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';\nconst TOKEN_2022_PROGRAM = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb';\nconst TRANSFER_CHECKED_DISCRIMINATOR = 12;\n\ninterface SolanaKitMinimal {\n getBase64Codec: () => { encode: (s: string) => Uint8Array };\n getTransactionDecoder: () => { decode: (b: Uint8Array) => { messageBytes: Uint8Array } };\n getCompiledTransactionMessageDecoder: () => {\n decode: (b: Uint8Array) => {\n staticAccounts: ReadonlyArray<string>;\n instructions: ReadonlyArray<{\n programAddressIndex: number;\n accountIndices?: number[];\n data?: Uint8Array;\n }>;\n };\n };\n}\n\n/**\n * Decode a Solana MPP `solana/charge` credential's `payload.transaction` (base64-encoded\n * signed Solana tx) and return the SPL `TransferChecked` authority — the source-ATA owner,\n * which is the buyer's wallet. Pull mode only (`payload.type === 'transaction'`); push mode\n * (`payload.type === 'signature'`) returns null because recovery would require an RPC fetch.\n */\nasync function extractSolanaSignerFromCredential(credential: unknown): Promise<string | null> {\n const payload = (credential as { payload?: { transaction?: string; type?: string } }).payload;\n if (!payload?.transaction || payload.type !== 'transaction') return null;\n\n const moduleName = '@solana/kit';\n const kit = (await import(moduleName).catch(() => null)) as SolanaKitMinimal | null;\n if (!kit?.getBase64Codec || !kit.getTransactionDecoder || !kit.getCompiledTransactionMessageDecoder) {\n return null;\n }\n\n try {\n const txBytes = kit.getBase64Codec().encode(payload.transaction);\n const decoded = kit.getTransactionDecoder().decode(txBytes);\n const message = kit.getCompiledTransactionMessageDecoder().decode(decoded.messageBytes);\n\n // SPL TransferChecked accounts: [source ATA, mint, destination ATA, authority, ...signers].\n // Returns the FIRST matched authority. For multi-recipient `splits` txs, the buyer\n // signs ONE tx with N TransferChecked instructions all sharing the same authority,\n // so first-match is correct; if a tx ever surfaces with mismatched authorities the\n // first one wins (acceptable since both belong to whoever signed the tx).\n for (const ix of message.instructions) {\n const programId = message.staticAccounts[ix.programAddressIndex];\n if (programId !== TOKEN_PROGRAM && programId !== TOKEN_2022_PROGRAM) continue;\n const data = ix.data;\n if (!data || data.length === 0 || data[0] !== TRANSFER_CHECKED_DISCRIMINATOR) continue;\n const accountIndices = ix.accountIndices ?? [];\n const authorityIndex = accountIndices[3];\n if (authorityIndex === undefined) continue;\n // v0 transactions can carry account indices that resolve via address lookup tables;\n // staticAccounts only holds the static set. If the index is out of range, the\n // authority sits in a lookup table we'd need RPC to resolve. Skip cleanly with a\n // warning rather than returning the wrong address.\n if (authorityIndex >= message.staticAccounts.length) {\n console.warn(\n '[gate] Solana TransferChecked authority resolves through an address lookup table; ' +\n 'signer-match recovery requires the static-account form. Skipping.',\n );\n continue;\n }\n const authority = message.staticAccounts[authorityIndex];\n if (authority) return authority;\n }\n return null;\n } catch (err) {\n console.warn('[gate] Solana credential decode failed:', err instanceof Error ? err.message : err);\n return null;\n }\n}\n\nexport interface PaymentSigner {\n /** Recovered wallet address (EVM lowercased; Solana base58 preserved verbatim). */\n address: string;\n /** Network family — used by `captureWallet` and downstream cross-chain attribution. */\n network: SignerNetwork;\n}\n\n/**\n * Recover the signer wallet from the incoming payment credential, including the network\n * family. Returns `null` when no wallet signature is present (e.g. Stripe SPT, card-only\n * payments, or no credential yet).\n *\n * @param request - the inbound `Request`\n * @param x402PaymentHeader - the value of `payment-signature` or `x-payment` header, if any.\n * Extracted separately because some frameworks (Express) don't expose a web `Request` object.\n */\nexport async function extractPaymentSigner(\n request: Request,\n x402PaymentHeader?: string,\n): Promise<PaymentSigner | null> {\n // MPP — Authorization: Payment <base64>\n const authHeader = request.headers.get('authorization');\n if (authHeader) {\n try {\n const moduleName = 'mppx';\n const mppx = (await import(moduleName).catch(() => null)) as {\n Credential?: {\n extractPaymentScheme: (h: string) => unknown;\n fromRequest: (r: Request) => unknown;\n };\n } | null;\n if (mppx?.Credential?.extractPaymentScheme(authHeader)) {\n const credential = mppx.Credential.fromRequest(request);\n const source = (credential as { source?: string }).source;\n const evmMatch = source?.match(/^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/);\n if (evmMatch) return { address: evmMatch[1]!.toLowerCase(), network: 'evm' };\n // Solana CAIP-10: did:pkh:solana:<genesis-base58>:<address-base58>\n const solMatch = source?.match(/^did:pkh:solana:[1-9A-HJ-NP-Za-km-z]{32,44}:([1-9A-HJ-NP-Za-km-z]{32,44})$/);\n if (solMatch) return { address: solMatch[1]!, network: 'solana' };\n // Fallback: source not set by upstream client. Decode the credential's signed-tx\n // payload to find the SPL TransferChecked authority (= source-ATA owner = buyer\n // wallet). Pull mode only.\n const solanaFromTx = await extractSolanaSignerFromCredential(credential);\n if (solanaFromTx) return { address: solanaFromTx, network: 'solana' };\n }\n } catch (err) {\n console.warn('[gate] MPP signer extraction failed:', err instanceof Error ? err.message : err);\n }\n }\n\n // x402 — base64 JSON, EIP-3009 only. EVM `payload.authorization.from` is the signer.\n if (x402PaymentHeader) {\n try {\n const decoded = atob(x402PaymentHeader);\n const parsed = JSON.parse(decoded) as {\n payload?: { authorization?: { from?: string } };\n };\n const from = parsed?.payload?.authorization?.from;\n if (typeof from === 'string' && /^0x[0-9a-fA-F]{40}$/.test(from)) {\n return { address: from.toLowerCase(), network: 'evm' };\n }\n } catch (err) {\n console.warn('[gate] x402 signer extraction failed:', err instanceof Error ? err.message : err);\n }\n }\n\n return null;\n}\n\n/**\n * Headers-only variant for adapters that don't natively expose a Web Fetch `Request`\n * (Express, Fastify, ASGI-bridged frameworks). Constructs a synthetic Request carrying\n * only the `authorization` header and delegates to {@link extractPaymentSigner}. Works\n * because the MPP and x402 paths only read `request.headers.get('authorization')` and\n * the explicit `x402PaymentHeader` arg — no body, query, or method semantics needed.\n */\nexport async function extractPaymentSignerFromAuth(\n authHeader: string | null | undefined,\n x402PaymentHeader?: string,\n): Promise<PaymentSigner | null> {\n const request = new Request('http://internal.gate/', {\n headers: authHeader ? { authorization: authHeader } : {},\n });\n return extractPaymentSigner(request, x402PaymentHeader);\n}\n\n/**\n * Read the x402 payment header from a `Request`, matching the alternate names merchants might\n * use. Falls back to reading either header directly.\n */\nexport function readX402PaymentHeader(request: Request): string | undefined {\n return (\n request.headers.get('payment-signature') ??\n request.headers.get('x-payment') ??\n undefined\n );\n}\n\nfunction lowerHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;\n return out;\n}\n\n/**\n * One-call signer extraction across both supported credential formats.\n *\n * Tries the x402 `payment-signature` / `x-payment` header first (EIP-3009\n * `payload.authorization.from`), then falls back to the MPP\n * `Authorization: Payment` header DID. Returns the first one that resolves,\n * or `null`.\n *\n * Use this for wallet-cap prechecks and other \"did the agent claim to sign as\n * X?\" checks where you need the signer BEFORE invoking Checkout. Checkout's\n * own settle path runs verification separately and surfaces the verified\n * signer on `SettleOutcome.signerAddress`.\n *\n * Accepts a plain headers dict so it works regardless of which framework the\n * merchant uses (the gate adapters all serialize headers down to a dict by\n * the time they reach the merchant's hooks).\n */\nexport async function extractSignerForPrecheck(\n headers: Record<string, string>,\n): Promise<PaymentSigner | null> {\n const lower = lowerHeaders(headers);\n const x402 = lower['payment-signature'] ?? lower['x-payment'];\n if (x402) {\n const signer = await extractPaymentSignerFromAuth(undefined, x402);\n if (signer !== null) return signer;\n }\n const authorization = lower['authorization'];\n if (authorization && authorization.toLowerCase().startsWith('payment ')) {\n return await extractPaymentSignerFromAuth(authorization);\n }\n return null;\n}\n","/**\n * x402 Settlement-Overrides header helpers — used with the `upto` scheme to specify the\n * actual amount to charge after the work is done. The header is JSON-encoded and lives\n * on the merchant's response; the facilitator settles for that amount instead of the\n * advertised maximum.\n *\n * Per the x402 docs (https://docs.x402.org/getting-started/quickstart-for-sellers), the\n * amount field accepts three formats:\n * - raw atomic units, e.g., '1000' for $0.001 USDC at 6 decimals\n * - percentage, e.g., '50%' of the authorized maximum\n * - dollar price, e.g., '$0.05' (converted to atomic via the network's default token)\n */\n\nexport const SETTLEMENT_OVERRIDES_HEADER = 'Settlement-Overrides';\n\nexport interface SettlementOverrides {\n /** Raw atomic units, '<n>%' percentage, or '$X.YZ' dollar price. */\n amount: string;\n}\n\n/**\n * Build a `{ name, value }` pair for the x402 Settlement-Overrides header. Vendors\n * set this on their response to direct the facilitator to settle for the actual amount\n * (used in the upto scheme flow):\n *\n * const { name, value } = settlementOverrideHeader({ amount: '1500' });\n * res.setHeader(name, value); // Express\n * c.header(name, value); // Hono\n */\nexport function settlementOverrideHeader(overrides: SettlementOverrides): { name: string; value: string } {\n return { name: SETTLEMENT_OVERRIDES_HEADER, value: JSON.stringify(overrides) };\n}\n","/**\n * USD ↔ atomic-unit conversion for token amounts.\n *\n * `usdToAtomic(usd, { decimals: 6 })` returns the bigint atomic value of a USD\n * amount for a token with `decimals` places of precision (USDC is 6). String\n * parsing + bigint arithmetic so the result is exact; ROUND_HALF_UP at the\n * rounding boundary matches the cross-language Python sibling.\n *\n * Rejects negative, NaN, infinite, and unparseable inputs. Fixed-notation only;\n * scientific notation (e.g. `\"1e6\"`) is not parsed (mirrors the locked cross-\n * language fixture corpus, which uses fixed notation exclusively).\n */\n\n/**\n * Convert a USD amount to atomic units for a token with `decimals` places.\n *\n * @param usd USD amount. Strings (`\"1.23\"`) and `number`s (`1.23`) are accepted.\n * `number` is converted via `String(usd)` before parsing, so JS float precision\n * limits apply when the float can't represent the value exactly.\n * @param opts.decimals Number of decimal places in the atomic unit (6 for USDC,\n * 18 for ETH, etc.). Must be a non-negative integer.\n *\n * @returns Integer atomic units as a `bigint`. `\"1.23\"` with `decimals: 6`\n * returns `1_230_000n`.\n *\n * @throws RangeError when `usd` is negative, NaN, infinite, or `decimals` is\n * not a non-negative integer.\n * @throws SyntaxError when `usd` cannot be parsed as a fixed-notation decimal.\n */\nexport function usdToAtomic(usd: string | number, opts: { decimals: number }): bigint {\n const { decimals } = opts;\n if (!Number.isInteger(decimals) || decimals < 0) {\n throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);\n }\n\n // Reject NaN / Infinity / negative on the typed-number path before stringifying,\n // so the error names the original numeric value rather than the stringified form.\n if (typeof usd === 'number') {\n if (!Number.isFinite(usd)) {\n throw new RangeError(`usd must be finite, got ${usd}`);\n }\n if (usd < 0) {\n throw new RangeError(`usd must be non-negative, got ${usd}`);\n }\n }\n\n const s = (typeof usd === 'number' ? usd.toString() : usd).trim();\n\n if (s.startsWith('-')) {\n throw new RangeError(`usd must be non-negative, got ${s}`);\n }\n if (s === 'NaN' || s === 'Infinity') {\n throw new RangeError(`usd must be finite, got ${s}`);\n }\n\n // Fixed notation only: optional digits, optional `.`, optional digits.\n // Reject empty, lone `.`, and anything containing non-digit/non-dot characters.\n const match = /^(\\d*)(?:\\.(\\d*))?$/.exec(s);\n if (!match || (match[1] === '' && (match[2] === undefined || match[2] === ''))) {\n throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);\n }\n\n const intPart = match[1] || '0';\n const fracPart = match[2] ?? '';\n\n // Fractional shorter than (or equal to) decimals: pad with trailing zeros, return exact.\n if (fracPart.length <= decimals) {\n return BigInt(intPart + fracPart.padEnd(decimals, '0'));\n }\n\n // Fractional longer than decimals: truncate to `decimals` digits, then round-half-up\n // via the next-position digit. A digit ≥ '5' rounds the combined value up by 1;\n // matches Python's Decimal ROUND_HALF_UP semantics for non-negative inputs.\n const kept = fracPart.slice(0, decimals);\n const roundDigit = fracPart[decimals];\n let result = BigInt(intPart + kept);\n if (roundDigit >= '5') {\n result += 1n;\n }\n return result;\n}\n\n/**\n * Format an integer cent amount as a fixed-2-decimal USD string.\n *\n * `formatUsdCents(500)` returns `\"5.00\"`. Negative values are formatted with a\n * leading minus. Use everywhere a merchant emits `(cents / 100).toFixed(2)`;\n * consistent formatting across catalog rows, order responses, and 402 bodies\n * prevents agent-side string-comparison flakiness.\n */\nexport function formatUsdCents(cents: number): string {\n return (cents / 100).toFixed(2);\n}\n","/**\n * Zero-amount carve-out: skip upstream verify+settle for $0 orders.\n *\n * CDP rejects EIP-3009 `transferWithAuthorization` with `value=0` as\n * `invalid_payload`; `mppx`'s tempo intents accept only `hash` and\n * `transaction` payload types (rejecting the `proof` payload that gets\n * emitted for $0 settles). Both upstream verify+settle paths fail when the\n * authorized amount is zero, so merchants that drop the settle to $0 in a\n * redemption-code flow need a way to skip verify+settle entirely while\n * still recovering the signer for wallet-capture attribution.\n *\n * `zeroAmountCarveOut` is that path: parse the credential, lift the\n * signer, return `{ signerAddress, signerNetwork, txHash: null }`. Identity\n * is still authenticated by the merchant's gate above; the redemption code\n * is single-use; nothing on-chain to verify.\n *\n * The MPP path uses inline base64+JSON parsing (no `mppx` dependency at\n * runtime) so the cross-language byte-parity fixtures with the Python\n * sibling resolve to identical results. The full `extractPaymentSigner`\n * path is still mppx-backed for production traffic where the credential\n * is a real mppx-shaped object.\n */\n\nimport type { SignerNetwork } from '../signer';\n\nconst EVM_RE = /^0x[0-9a-fA-F]{40}$/;\nconst SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\nexport type ZeroSettleRail = 'x402-base' | 'tempo' | 'solana';\n\nexport interface ZeroSettleResult {\n /** Recovered signer address, or `null` when the credential is malformed\n * or shaped wrong for the requested rail. */\n signerAddress: string | null;\n /** `\"evm\"` or `\"solana\"`, matching the recovered signer's key family.\n * `null` when no signer was recoverable. */\n signerNetwork: SignerNetwork | null;\n /** Always `null`. A zero-amount carve-out skips on-chain settlement, so\n * no transaction hash exists. The field is present so callers can use\n * `ZeroSettleResult` interchangeably with the success path of\n * `processX402Settle` etc. without branching on shape. */\n txHash: null;\n}\n\nconst NULL_RESULT: ZeroSettleResult = {\n signerAddress: null,\n signerNetwork: null,\n txHash: null,\n};\n\n/**\n * Skip verify+settle for a zero-amount order; recover the signer from the credential.\n *\n * Returns a `ZeroSettleResult`. `signerAddress` / `signerNetwork` are `null`\n * when the credential is malformed, missing required fields, or shaped wrong\n * for the requested rail. `txHash` is always `null` since no on-chain settle runs.\n */\nexport function zeroAmountCarveOut({\n rail,\n payload,\n authorizationHeader,\n}: {\n rail: ZeroSettleRail;\n /** For `rail: 'x402-base'`: the verified x402 payload (decoded JSON\n * from `verifyX402Request(...).payload`). Reads\n * `payload.payload.authorization.from`. */\n payload?: Record<string, unknown> | null;\n /** For `rail: 'tempo'` / `'solana'`: the full `Authorization: Payment <base64>`\n * header value. Reads the `did:pkh:*` source DID. */\n authorizationHeader?: string | null;\n}): ZeroSettleResult {\n if (rail === 'x402-base') {\n return x402SignerFromPayload(payload);\n }\n if (rail === 'tempo' || rail === 'solana') {\n return mppSignerFromAuth(authorizationHeader);\n }\n return NULL_RESULT;\n}\n\nfunction x402SignerFromPayload(payload: Record<string, unknown> | null | undefined): ZeroSettleResult {\n if (!payload || typeof payload !== 'object') return NULL_RESULT;\n const inner = (payload as { payload?: unknown }).payload;\n if (!inner || typeof inner !== 'object') return NULL_RESULT;\n const authorization = (inner as { authorization?: unknown }).authorization;\n if (!authorization || typeof authorization !== 'object') return NULL_RESULT;\n const fromAddr = (authorization as { from?: unknown }).from;\n if (typeof fromAddr !== 'string' || !EVM_RE.test(fromAddr)) return NULL_RESULT;\n return {\n signerAddress: fromAddr.toLowerCase(),\n signerNetwork: 'evm',\n txHash: null,\n };\n}\n\nfunction mppSignerFromAuth(\n authorizationHeader: string | null | undefined,\n): ZeroSettleResult {\n if (typeof authorizationHeader !== 'string') return NULL_RESULT;\n if (!authorizationHeader.toLowerCase().startsWith('payment ')) return NULL_RESULT;\n const token = authorizationHeader.slice('payment '.length).trim();\n if (!token) return NULL_RESULT;\n\n let credential: unknown;\n try {\n credential = JSON.parse(atob(token));\n } catch {\n return NULL_RESULT;\n }\n if (!credential || typeof credential !== 'object') return NULL_RESULT;\n\n let source = (credential as { source?: unknown }).source;\n if (typeof source !== 'string') {\n const challenge = (credential as { challenge?: unknown }).challenge;\n if (challenge && typeof challenge === 'object') {\n source = (challenge as { source?: unknown }).source;\n }\n }\n if (typeof source !== 'string') return NULL_RESULT;\n\n const parts = source.split(':');\n if (parts.length < 4 || parts[0] !== 'did' || parts[1] !== 'pkh') return NULL_RESULT;\n const family = parts[2];\n const addr = parts[parts.length - 1] ?? '';\n\n if (family === 'eip155' && EVM_RE.test(addr)) {\n return { signerAddress: addr.toLowerCase(), signerNetwork: 'evm', txHash: null };\n }\n if (family === 'solana' && SOLANA_BASE58_RE.test(addr)) {\n return { signerAddress: addr, signerNetwork: 'solana', txHash: null };\n }\n return NULL_RESULT;\n}\n","/**\n * Lazy-init helpers for x402 + mppx servers.\n *\n * Every merchant accepting these rails writes the same singleton-with-lock\n * pattern around `createX402Server` / `createMppxServer`. These helpers collapse\n * the boilerplate to a single call; the returned getter is safe to call from\n * any number of concurrent handlers; only one server instance is ever\n * constructed per merchant.\n *\n * The x402 helper also derives the facilitator choice (`coinbase` vs `http`)\n * from optional CDP credentials so merchants don't repeat the boot-time\n * conditional.\n */\nimport { createMppxServer, type MppxRailSpec } from './mppx_server';\nimport { createX402Server, type X402Server, type X402SymbolicRail } from './x402_server';\nimport type { X402BaseRailSpec } from './rail_spec';\n\nfunction x402RailName(spec: X402BaseRailSpec): X402SymbolicRail {\n const network = spec.network ?? 'eip155:8453';\n if (network === 'eip155:8453') return 'x402-base-mainnet';\n if (network === 'eip155:84532') return 'x402-base-sepolia';\n throw new Error(\n `lazyX402Server: unsupported X402BaseRailSpec.network=${JSON.stringify(network)}`,\n );\n}\n\n/**\n * Build a memoized async getter for an x402 server.\n *\n * First call constructs the server; subsequent calls return the cached\n * instance. Concurrent first-callers serialize on a Promise lock so we never\n * construct two and discard one.\n *\n * When both CDP creds are passed, the server uses Coinbase's facilitator;\n * otherwise it falls back to the public HTTP facilitator. Merchants who only\n * have one of the two creds get the HTTP fallback.\n */\nexport function lazyX402Server(opts: {\n spec: X402BaseRailSpec;\n cdpApiKeyId?: string;\n cdpApiKeySecret?: string;\n}): () => Promise<X402Server> {\n const { spec, cdpApiKeyId, cdpApiKeySecret } = opts;\n const railName = x402RailName(spec);\n const useCdp = Boolean(cdpApiKeyId && cdpApiKeySecret);\n const facilitator: 'coinbase' | 'http' = useCdp ? 'coinbase' : 'http';\n\n let cached: X402Server | undefined;\n let pending: Promise<X402Server> | undefined;\n\n return async (): Promise<X402Server> => {\n if (cached !== undefined) return cached;\n if (pending !== undefined) return pending;\n pending = (async () => {\n const server = await createX402Server({ facilitator, rails: [railName] });\n cached = server;\n pending = undefined;\n return server;\n })();\n return pending;\n };\n}\n\n/**\n * Build a memoized async getter for an mppx server.\n *\n * Same singleton + lock semantics as {@link lazyX402Server}. Forwards `rails`\n * + `secretKey` unchanged to {@link createMppxServer}.\n */\nexport function lazyMppxServer(opts: {\n rails: Record<string, MppxRailSpec>;\n secretKey: string;\n}): () => Promise<unknown> {\n const { rails, secretKey } = opts;\n let cached: unknown;\n let pending: Promise<unknown> | undefined;\n\n return async (): Promise<unknown> => {\n if (cached !== undefined) return cached;\n if (pending !== undefined) return pending;\n pending = (async () => {\n const server = await createMppxServer({ secretKey, rails });\n cached = server;\n pending = undefined;\n return server;\n })();\n return pending;\n };\n}\n","/**\n * Solana MPP fee-payer signer loader.\n *\n * Buyers paying via Solana MPP USDC don't typically carry SOL for transaction\n * fees, so merchants commonly co-sign the buyer's `solana/charge` tx as the\n * fee payer (~5000 lamports per tx; negligible vs the USDC value moved).\n *\n * `loadSolanaFeePayer({ privateKey })` accepts a Solana keypair in any of the\n * three forms agents commonly export it as:\n *\n * - **base58** (Phantom export format) — 64-byte secret+public, or 32-byte\n * secret-only\n * - **hex** — 128-char string (64 bytes hex: 32-byte secret + 32-byte public)\n *\n * Returns a `KeyPairSigner` from `@solana/kit` ready to pass as the `signer`\n * field on a `SolanaMppRailSpec`. Returns `undefined` when `privateKey` is\n * empty / absent (so consumers can use `process.env.X` directly without\n * null-checks).\n *\n * Requires the `@solana/kit` peer dependency.\n */\nexport async function loadSolanaFeePayer(opts: {\n privateKey: string | undefined;\n}): Promise<unknown | undefined> {\n const raw = opts.privateKey;\n if (!raw) return undefined;\n const moduleName = '@solana/kit';\n const kit = (await import(moduleName).catch(() => null)) as {\n createKeyPairSignerFromPrivateKeyBytes?: (bytes: Uint8Array) => Promise<unknown>;\n getBase58Codec?: () => { encode: (s: string) => Uint8Array };\n } | null;\n if (!kit?.createKeyPairSignerFromPrivateKeyBytes || !kit.getBase58Codec) {\n throw new Error(\n '@solana/kit not installed — `npm install @solana/kit` for loadSolanaFeePayer.',\n );\n }\n let bytes: Uint8Array;\n if (/^[0-9a-fA-F]{128}$/.test(raw)) {\n bytes = new Uint8Array(raw.match(/.{2}/g)!.map((h) => parseInt(h, 16))).slice(0, 32);\n } else {\n const decoded = new Uint8Array(kit.getBase58Codec().encode(raw));\n bytes = decoded.length === 64 ? decoded.slice(0, 32) : decoded;\n }\n return kit.createKeyPairSignerFromPrivateKeyBytes(bytes);\n}\n"],"mappings":"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","names":["rails","dynamicImport","rails","rails"]}
|
|
1
|
+
{"version":3,"sources":["../../src/payment/index.ts","../../src/payment/networks.ts","../../src/payment/usdc.ts","../../src/payment/rails.ts","../../src/payment/directive.ts","../../src/payment/rail_spec.ts","../../src/payment/x402.ts","../../src/payment/x402_server.ts","../../src/payment/x402_settle.ts","../../src/payment/x402_validation.ts","../../src/stripe-multichain/mppx_stripe.ts","../../src/payment/mppx_server.ts","../../src/payment/dispatch.ts","../../src/payment/wwwauthenticate.ts","../../src/payment/headers.ts","../../src/payment/idempotency.ts","../../src/signer.ts","../../src/payment/settlement_override.ts","../../src/payment/amounts.ts","../../src/payment/zero-settle.ts","../../src/payment/lazy.ts","../../src/payment/solana.ts"],"sourcesContent":["export * from './directive';\nexport * from './networks';\nexport * from './usdc';\nexport * from './rails';\nexport * from './rail_spec';\nexport * from './x402';\nexport * from './x402_server';\nexport * from './x402_settle';\nexport * from './x402_validation';\nexport * from './mppx_server';\nexport * from './dispatch';\nexport * from './wwwauthenticate';\nexport * from './headers';\nexport * from './idempotency';\nexport * from './signer';\nexport * from './settlement_override';\nexport * from './amounts';\nexport * from './zero-settle';\nexport * from './lazy';\nexport * from './solana';\n","/**\n * Named network registry. Vendors reference symbolic names (`networks.base.mainnet.caip2`)\n * instead of magic strings. Lifted from agentscore-pay's constants.\n */\nexport const networks = {\n base: {\n mainnet: { caip2: 'eip155:8453' as const, chainId: 8453 },\n sepolia: { caip2: 'eip155:84532' as const, chainId: 84532 },\n },\n solana: {\n mainnet: { caip2: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' as const },\n devnet: { caip2: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1' as const },\n },\n tempo: {\n mainnet: { caip2: 'eip155:4217' as const, chainId: 4217 },\n testnet: { caip2: 'eip155:42431' as const, chainId: 42431 },\n },\n} as const;\n\nexport type NetworkFamily = keyof typeof networks;\n\n/**\n * Returns the family name (base/solana/tempo) for a given CAIP-2 network string,\n * or null if the network isn't in the registry. Useful for routing settlement\n * by network.\n */\nexport function networkFamily(caip2: string): NetworkFamily | null {\n if (caip2 === networks.base.mainnet.caip2 || caip2 === networks.base.sepolia.caip2) return 'base';\n if (caip2 === networks.solana.mainnet.caip2 || caip2 === networks.solana.devnet.caip2) return 'solana';\n if (caip2 === networks.tempo.mainnet.caip2 || caip2 === networks.tempo.testnet.caip2) return 'tempo';\n if (caip2.startsWith('solana:')) return 'solana';\n return null;\n}\n","/**\n * USDC token registry per network. Used by paymentDirective and rail definitions.\n * Lifted from agentscore-pay's constants.\n */\nexport const USDC = {\n base: {\n mainnet: { address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const, decimals: 6 },\n sepolia: { address: '0x036CbD53842c5426634e7929541eC2318f3dCF7e' as const, decimals: 6 },\n },\n solana: {\n mainnet: { mint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', decimals: 6 },\n devnet: { mint: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU', decimals: 6 },\n },\n tempo: {\n mainnet: { address: '0x20C000000000000000000000b9537d11c60E8b50' as const, decimals: 6 },\n testnet: { address: '0x20c0000000000000000000000000000000000000' as const, decimals: 6 },\n },\n} as const;\n","import { networks } from './networks';\nimport { USDC } from './usdc';\n\n/**\n * Symbolic rail names mapped to their protocol details. Vendors pass `rail: 'tempo-mainnet'`\n * to the directive builder and the SDK fills in method/network/decimals/currency from this\n * registry. Custom rails not in this registry can be passed by setting the lower-level\n * fields directly on the directive builder.\n */\nexport const rails = {\n 'tempo-mainnet': {\n method: 'tempo',\n network: networks.tempo.mainnet.caip2,\n chainId: networks.tempo.mainnet.chainId,\n currency: USDC.tempo.mainnet.address,\n decimals: USDC.tempo.mainnet.decimals,\n asset: USDC.tempo.mainnet.address,\n },\n 'tempo-testnet': {\n method: 'tempo',\n network: networks.tempo.testnet.caip2,\n chainId: networks.tempo.testnet.chainId,\n currency: USDC.tempo.testnet.address,\n decimals: USDC.tempo.testnet.decimals,\n asset: USDC.tempo.testnet.address,\n },\n 'x402-base-mainnet': {\n method: 'x402',\n network: networks.base.mainnet.caip2,\n chainId: networks.base.mainnet.chainId,\n currency: USDC.base.mainnet.address,\n decimals: USDC.base.mainnet.decimals,\n asset: USDC.base.mainnet.address,\n },\n 'x402-base-sepolia': {\n method: 'x402',\n network: networks.base.sepolia.caip2,\n chainId: networks.base.sepolia.chainId,\n currency: USDC.base.sepolia.address,\n decimals: USDC.base.sepolia.decimals,\n asset: USDC.base.sepolia.address,\n },\n // Upto rails — pay UP TO a max amount (Permit2-based, vs EIP-3009 for exact). Use for\n // variable-cost APIs where the actual cost depends on output (LLM tokens, bandwidth, etc.).\n // Only available on EVM networks; Solana svm doesn't ship an upto scheme yet.\n 'x402-base-mainnet-upto': {\n method: 'x402-upto',\n network: networks.base.mainnet.caip2,\n chainId: networks.base.mainnet.chainId,\n currency: USDC.base.mainnet.address,\n decimals: USDC.base.mainnet.decimals,\n asset: USDC.base.mainnet.address,\n },\n 'x402-base-sepolia-upto': {\n method: 'x402-upto',\n network: networks.base.sepolia.caip2,\n chainId: networks.base.sepolia.chainId,\n currency: USDC.base.sepolia.address,\n decimals: USDC.base.sepolia.decimals,\n asset: USDC.base.sepolia.address,\n },\n 'mpp-solana-mainnet': {\n method: 'solana',\n network: networks.solana.mainnet.caip2,\n currency: USDC.solana.mainnet.mint,\n decimals: USDC.solana.mainnet.decimals,\n asset: USDC.solana.mainnet.mint,\n },\n 'mpp-solana-devnet': {\n method: 'solana',\n network: networks.solana.devnet.caip2,\n currency: USDC.solana.devnet.mint,\n decimals: USDC.solana.devnet.decimals,\n asset: USDC.solana.devnet.mint,\n },\n 'stripe-spt': {\n method: 'stripe',\n currency: 'usd',\n decimals: 2,\n },\n} as const;\n\nexport type RailName = keyof typeof rails;\n\nexport interface RailDefinition {\n method: string;\n network?: string;\n chainId?: number;\n currency: string;\n decimals: number;\n asset?: string;\n}\n\n/**\n * Lookup a rail definition by symbolic name. Returns undefined if the rail isn't in\n * the registry — vendors with custom rails should pass the low-level fields directly.\n */\nexport function lookupRail(name: string): RailDefinition | undefined {\n return rails[name as RailName] as RailDefinition | undefined;\n}\n","import { lookupRail } from './rails';\n\n/**\n * Build the base64-encoded `request` blob for an MPP Payment directive (per the\n * paymentauth.org spec). Output shape matches what link-cli `mpp decode` expects:\n *\n * { amount: \"<raw_integer>\", currency: \"<token>\", recipient?: \"<addr>\",\n * methodDetails?: { chainId?: number, networkId?: string } }\n */\nexport function buildPaymentRequestBlob({\n rail,\n amountUsd,\n currency,\n decimals,\n recipient,\n chainId,\n networkId,\n}: {\n /** Symbolic rail name (e.g., 'tempo-mainnet', 'x402-base-mainnet') — fills in defaults */\n rail?: string;\n /** Amount in USD as a number or string. Converted to raw integer using `decimals`. */\n amountUsd: string | number;\n /** Token contract address or currency code. Defaults from rail. */\n currency?: string;\n /** Decimal precision for the amount. Defaults from rail (6 for USDC, 2 for USD). */\n decimals?: number;\n /** Recipient address (on-chain). Optional for stripe-style rails. */\n recipient?: string;\n /** EVM chain ID (goes into methodDetails.chainId). Defaults from rail. */\n chainId?: number;\n /** Stripe profile_id or similar (goes into methodDetails.networkId — note camelCase per link-cli's mpp decode validator). */\n networkId?: string;\n}): string {\n const railDef = rail ? lookupRail(rail) : undefined;\n const decimalsResolved = decimals ?? railDef?.decimals ?? 6;\n const currencyResolved = currency ?? railDef?.currency ?? 'usd';\n const chainIdResolved = chainId ?? railDef?.chainId;\n\n const amountNum = typeof amountUsd === 'string' ? Number(amountUsd) : amountUsd;\n const amountRaw = BigInt(Math.round(amountNum * 10 ** decimalsResolved)).toString();\n const blob: Record<string, unknown> = { amount: amountRaw, currency: currencyResolved, decimals: decimalsResolved };\n if (recipient) blob.recipient = recipient;\n const methodDetails: Record<string, unknown> = {};\n if (chainIdResolved !== undefined) methodDetails.chainId = chainIdResolved;\n if (networkId) methodDetails.networkId = networkId;\n if (Object.keys(methodDetails).length > 0) blob.methodDetails = methodDetails;\n return Buffer.from(JSON.stringify(blob)).toString('base64url');\n}\n\n/**\n * Format an MPP Payment directive string for the WWW-Authenticate header.\n * Output shape: `Payment id=\"...\", realm=\"...\", method=\"...\", intent=\"charge\",\n * expires=\"...\", request=\"<base64>\"`\n */\nexport function paymentDirective({\n rail,\n id,\n realm,\n method,\n intent,\n expires,\n request,\n}: {\n /** Symbolic rail name — sets `method` automatically */\n rail?: string;\n /** Challenge id (unique per request, used to correlate retries) */\n id: string;\n /** Realm — the host of the merchant URL (e.g., \"agents.merchant.example\") */\n realm: string;\n /** MPP method name. Defaults from rail (e.g., 'tempo', 'stripe'). */\n method?: string;\n /** MPP intent. Defaults to 'charge'. */\n intent?: string;\n /** ISO-8601 expiry timestamp. Defaults to now + 5 minutes. */\n expires?: string;\n /** Base64-encoded request blob. Pass the result of buildPaymentRequestBlob. */\n request: string;\n}): string {\n const railDef = rail ? lookupRail(rail) : undefined;\n const methodResolved = method ?? railDef?.method ?? 'unknown';\n const intentResolved = intent ?? 'charge';\n const expiresResolved = expires ?? new Date(Date.now() + 5 * 60 * 1000).toISOString();\n return `Payment id=\"${id}\", realm=\"${realm}\", method=\"${methodResolved}\", intent=\"${intentResolved}\", expires=\"${expiresResolved}\", request=\"${request}\"`;\n}\n\n/**\n * Convenience: build the request blob and the directive in one call. Most vendors\n * want this rather than the two-step form.\n */\nexport function buildPaymentDirective({\n rail,\n id,\n realm,\n amountUsd,\n currency,\n decimals,\n recipient,\n chainId,\n networkId,\n method,\n intent,\n expires,\n}: {\n rail: string;\n id: string;\n realm: string;\n amountUsd: string | number;\n currency?: string;\n decimals?: number;\n recipient?: string;\n chainId?: number;\n networkId?: string;\n method?: string;\n intent?: string;\n expires?: string;\n}): string {\n const request = buildPaymentRequestBlob({\n rail,\n amountUsd,\n currency,\n decimals,\n recipient,\n chainId,\n networkId,\n });\n return paymentDirective({\n rail,\n id,\n realm,\n method,\n intent,\n expires,\n request,\n });\n}\n","/**\n * Canonical `*RailSpec` types — one shape per rail, consumed by every helper.\n *\n * A merchant accepting Tempo + Base + Solana + Stripe declares one `*RailSpec`\n * per rail and passes it to every helper (`buildAcceptedMethods`,\n * `buildHowToPay`, `mppPaymentHandler`, `createMppxServer`, ...). One canonical\n * shape per rail means the recipient address, network identifier, and token\n * defaults are declared once and reused everywhere.\n *\n * `RecipientLike` is polymorphic over `string | (() => string | Promise<string>)`\n * so per-order recipients (Stripe-multichain mints fresh deposit addresses per\n * PaymentIntent) flow through identically to static-treasury recipients. The\n * factory is called once per helper invocation; callers cache externally.\n */\n\nimport { USDC } from './usdc';\n\nexport type RecipientLike = string | (() => string | Promise<string>);\n\n/**\n * Resolve a `RecipientLike` to a concrete address string. Accepts a string\n * (returned verbatim), a sync callable (called once), or an async callable\n * (awaited once). Helpers call this on every invocation; callers that want\n * once-per-session resolution should cache externally.\n */\nexport async function resolveRecipient(r: RecipientLike): Promise<string> {\n if (typeof r === 'string') return r;\n return Promise.resolve(r());\n}\n\n/** Canonical config for the Tempo MPP rail. */\nexport interface TempoRailSpec {\n recipient: RecipientLike;\n network?: string;\n chainId?: number;\n token?: string;\n symbol?: string;\n decimals?: number;\n testnet?: boolean;\n recommend?: 'tempo' | 'agentscore-pay' | 'both';\n}\n\n/** Canonical config for the x402 EVM (Base) rail. */\nexport interface X402BaseRailSpec {\n recipient: RecipientLike;\n /** CAIP-2 canonical, e.g. `eip155:8453`. */\n network?: string;\n chainId?: number;\n token?: string;\n symbol?: string;\n decimals?: number;\n mode?: 'exact' | 'upto';\n}\n\n/**\n * Canonical config for the Solana MPP rail.\n *\n * `signer` is an optional fee-payer signer for server-side fee sponsorship —\n * typed as `unknown` to avoid hard-importing `@solana/kit` types here. Pass any\n * `TransactionPartialSigner`.\n */\nexport interface SolanaMppRailSpec {\n recipient: RecipientLike;\n network?: string;\n token?: string;\n symbol?: string;\n decimals?: number;\n rpcUrl?: string;\n signer?: unknown;\n tokenProgram?: string;\n}\n\n/**\n * Canonical config for the Stripe SPT rail.\n *\n * `recipient` is intentionally absent — Stripe rails use `profileId` as the\n * merchant-side network identifier the agent's SPT is scoped to; the\n * transaction recipient is the merchant's Stripe account, not an on-chain\n * address.\n */\nexport interface StripeRailSpec {\n profileId?: string | null;\n rails?: ('card' | 'link' | 'shared_payment_token')[];\n paymentMethodTypes?: string[];\n productName?: string;\n secretKey?: string;\n}\n\n/**\n * Canonical config for the Tempo session MPP rail (pay-as-you-go channels).\n *\n * `escrowContract` is the merchant-deployed on-chain escrow that holds channel\n * deposits + pays out cumulative vouchers on settlement. `store` is a\n * `ChannelStore` instance — typed as `unknown` to avoid hard-importing `mppx`'s\n * store interface here.\n */\nexport interface TempoSessionRailSpec {\n recipient: RecipientLike;\n escrowContract: string;\n store: unknown;\n currency?: string;\n testnet?: boolean;\n chains?: unknown;\n}\n\n/**\n * Default field values for each `*RailSpec`. Mirrors python-commerce's\n * `*RailSpec` dataclass defaults — callers can spread these into their spec\n * literal when they want defaults without typing them out. Sourced from the\n * USDC registry so they stay in sync with on-chain reality.\n */\nexport const RAIL_SPEC_DEFAULTS = {\n tempo: {\n network: 'tempo-mainnet',\n chainId: 4217,\n token: USDC.tempo.mainnet.address,\n symbol: 'USDC.e',\n decimals: 6,\n testnet: false,\n recommend: 'both' as const,\n },\n x402Base: {\n network: 'eip155:8453',\n chainId: 8453,\n token: USDC.base.mainnet.address,\n symbol: 'USDC',\n decimals: 6,\n mode: 'exact' as const,\n },\n solanaMpp: {\n network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n token: USDC.solana.mainnet.mint,\n symbol: 'USDC',\n decimals: 6,\n },\n stripe: {\n rails: ['card', 'link', 'shared_payment_token'] as ('card' | 'link' | 'shared_payment_token')[],\n },\n tempoSession: {\n currency: USDC.tempo.mainnet.address,\n testnet: false,\n },\n} as const;\n","/**\n * Generic x402 server interface. Different versions of @x402/core may expose different\n * shapes; we only require register() and (optionally) registerV1().\n */\nexport interface X402ServerLike {\n register(network: string, scheme: unknown): void;\n registerV1?(network: string, scheme: unknown): void;\n}\n\n/**\n * Registers an x402 scheme on both v1 and v2 of the protocol.\n *\n * Why: the @x402/core HTTP parser hardcodes `x402Version === 1`, while the client's\n * `.register()` defaults to v2. Without registering on both versions, a merchant\n * emitting a v1 response gets \"No client registered for x402 version: 1\" even\n * though the scheme handler is identical between versions. Every merchant trips\n * on this; the helper hides the workaround.\n */\nexport function registerX402SchemesV1V2(\n server: X402ServerLike,\n network: string,\n scheme: unknown,\n): void {\n server.register(network, scheme);\n if (typeof server.registerV1 === 'function') {\n server.registerV1(network, scheme);\n }\n}\n","import { networks } from './networks';\nimport { registerX402SchemesV1V2 } from './x402';\n\nexport type X402SymbolicRail =\n | 'x402-base-mainnet'\n | 'x402-base-sepolia'\n | 'x402-base-mainnet-upto'\n | 'x402-base-sepolia-upto';\n\nexport type X402FacilitatorChoice = 'coinbase' | 'http' | unknown;\n\nexport interface CreateX402ServerOptions {\n /**\n * Facilitator selection:\n * - 'coinbase' → Coinbase CDP facilitator (requires `@coinbase/x402` installed)\n * - 'http' → HTTP-only public testnet facilitator\n * - any object → custom facilitator instance, used directly\n * - omitted → defaults to 'http'\n */\n facilitator?: X402FacilitatorChoice;\n /**\n * Symbolic rail names to register schemes for. Each gets v1+v2 dual-register applied.\n * Requires `@x402/evm` peer dep installed.\n */\n rails?: X402SymbolicRail[];\n /** Advanced: register custom {network, scheme} pairs (in addition to or instead of `rails`). */\n schemes?: { network: string; scheme: unknown }[];\n /** Register the Bazaar discovery extension. Requires `@x402/extensions` installed. */\n bazaar?: boolean;\n /** Initialize the server immediately (calls facilitator). Default true. */\n initialize?: boolean;\n}\n\n/**\n * Loose type for the x402 resource server. We name the methods commerce calls during\n * setup; everything else (settlePayment, buildPaymentRequirements, processPaymentRequest,\n * enrichExtensions, etc.) is callable via the index signature so vendor code can use the\n * full @x402/core surface without us having to mirror every method signature.\n */\nexport interface X402Server {\n register(network: string, scheme: unknown): void;\n registerV1?(network: string, scheme: unknown): void;\n registerExtension(ext: unknown): void;\n initialize(): Promise<void>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n}\n\ninterface X402CoreModule {\n x402ResourceServer: new (facilitator?: unknown) => X402Server;\n HTTPFacilitatorClient: new (facilitator?: unknown) => unknown;\n}\n\ninterface SchemeModule {\n ExactEvmScheme?: new () => unknown;\n UptoEvmScheme?: new () => unknown;\n}\n\ninterface CoinbaseModule {\n facilitator?: unknown;\n}\n\ninterface BazaarModule {\n bazaarResourceServerExtension?: unknown;\n}\n\n/**\n * One-call x402 server setup. Resolves facilitator, constructs the server, registers\n * schemes per network with v1+v2 dual-register, optionally adds the Bazaar extension,\n * and initializes — replaces ~15 lines of boilerplate with a single config call.\n *\n * x402 packages are peer dependencies — vendors install only the schemes they use.\n * Throws a guiding error if a required peer is missing.\n *\n * const server = await createX402Server({\n * facilitator: 'coinbase',\n * rails: ['x402-base-mainnet'],\n * bazaar: true,\n * });\n */\nexport async function createX402Server(opts: CreateX402ServerOptions = {}): Promise<X402Server> {\n const x402Core = (await dynamicImport<X402CoreModule>('@x402/core/server')) ?? null;\n /* v8 ignore start -- peer-dep-absence guard; @x402/core is installed in test env */\n if (!x402Core) {\n throw new Error(\n '@x402/core not installed — `npm install @x402/core` to use createX402Server.',\n );\n }\n /* v8 ignore stop */\n\n let facilitator: unknown;\n // Auto-select the Coinbase CDP facilitator when both env vars are present.\n // Lets merchants drop `facilitator: process.env.CDP_API_KEY_ID && ... ? 'coinbase' : 'http'`\n // boilerplate. Explicit `facilitator` opt still wins.\n const facilitatorChoice =\n opts.facilitator ??\n (process.env.CDP_API_KEY_ID && process.env.CDP_API_KEY_SECRET ? 'coinbase' : 'http');\n if (facilitatorChoice === 'coinbase') {\n const cb = await dynamicImport<CoinbaseModule>('@coinbase/x402');\n /* v8 ignore start -- peer-dep-absence guard; @coinbase/x402 is installed in test env */\n if (!cb?.facilitator) {\n throw new Error(\n '@coinbase/x402 not installed — `npm install @coinbase/x402` for facilitator: \"coinbase\".',\n );\n }\n /* v8 ignore stop */\n facilitator = new x402Core.HTTPFacilitatorClient(cb.facilitator);\n } else if (facilitatorChoice === 'http') {\n facilitator = new x402Core.HTTPFacilitatorClient();\n } else {\n facilitator = facilitatorChoice;\n }\n\n const server = new x402Core.x402ResourceServer(facilitator);\n\n let evmExactModule: SchemeModule | null = null;\n let evmUptoModule: SchemeModule | null = null;\n for (const rail of opts.rails ?? []) {\n const isUpto = rail.endsWith('-upto');\n if (rail.startsWith('x402-base')) {\n const baseRail = isUpto ? rail.slice(0, -5) : rail;\n const network =\n baseRail === 'x402-base-mainnet' ? networks.base.mainnet.caip2 : networks.base.sepolia.caip2;\n if (isUpto) {\n evmUptoModule ??= await dynamicImport<SchemeModule>('@x402/evm/upto/server');\n /* v8 ignore start -- peer-dep-absence guard; @x402/evm is installed in test env */\n if (!evmUptoModule?.UptoEvmScheme) {\n throw new Error('@x402/evm not installed — `npm install @x402/evm` for x402 base upto rails.');\n }\n /* v8 ignore stop */\n registerX402SchemesV1V2(server, network, new evmUptoModule.UptoEvmScheme());\n } else {\n evmExactModule ??= await dynamicImport<SchemeModule>('@x402/evm/exact/server');\n /* v8 ignore start -- peer-dep-absence guard; @x402/evm is installed in test env */\n if (!evmExactModule?.ExactEvmScheme) {\n throw new Error('@x402/evm not installed — `npm install @x402/evm` for x402 base rails.');\n }\n /* v8 ignore stop */\n registerX402SchemesV1V2(server, network, new evmExactModule.ExactEvmScheme());\n }\n }\n }\n\n for (const { network, scheme } of opts.schemes ?? []) {\n registerX402SchemesV1V2(server, network, scheme);\n }\n\n if (opts.bazaar) {\n const bazaar = await dynamicImport<BazaarModule>('@x402/extensions/bazaar');\n /* v8 ignore start -- peer-dep-absence guard; @x402/extensions is installed in test env */\n if (!bazaar?.bazaarResourceServerExtension) {\n throw new Error(\n '@x402/extensions not installed — `npm install @x402/extensions` for bazaar discovery.',\n );\n }\n /* v8 ignore stop */\n server.registerExtension(bazaar.bazaarResourceServerExtension);\n }\n\n if (opts.initialize !== false) {\n await server.initialize();\n }\n return server;\n}\n\nexport interface BuildX402AcceptsForOptions {\n network: string;\n price: string;\n payTo: string;\n scheme?: string;\n maxTimeoutSeconds?: number;\n extensions?: string[];\n}\n\n/**\n * Build x402 `accepts[]` entries for a 402 challenge body.\n *\n * Wraps `server.buildPaymentRequirements(...)` so merchants don't have to:\n *\n * 1. Construct the resource-config object themselves\n * 2. Remember to serialize each Pydantic-equivalent requirement back to a\n * plain object before stitching it into the 402 body\n * 3. Hardcode `extra` (which differs by the actual on-chain contract — base\n * mainnet USDC has `name: \"USD Coin\"`, base sepolia USDC has `name: \"USDC\"`;\n * EIP-712 domain hashes differ, so getting this wrong silently breaks every\n * signature verify at the facilitator)\n *\n * Returns a list of plain objects in the shape that x402 expects on the wire —\n * drop them straight into the `accepts` field of the 402 challenge body.\n */\nexport async function buildX402AcceptsFor402(\n server: X402Server,\n opts: BuildX402AcceptsForOptions,\n): Promise<unknown[]> {\n const requirements = await server.buildPaymentRequirements(\n {\n scheme: opts.scheme ?? 'exact',\n network: opts.network,\n price: opts.price,\n payTo: opts.payTo,\n maxTimeoutSeconds: opts.maxTimeoutSeconds ?? 300,\n },\n opts.extensions,\n );\n return Array.isArray(requirements) ? requirements : [];\n}\n\nasync function dynamicImport<T>(moduleName: string): Promise<T | null> {\n try {\n return (await import(moduleName)) as T;\n } catch {\n return null;\n }\n}\n","/**\n * `processX402Settle`: single-call x402 verify+settle for merchants.\n *\n * Wraps the four x402-server steps every x402-accepting merchant repeats:\n * 1. `buildPaymentRequirements(resourceConfig)`: builds the requirement entries the\n * facilitator validates against\n * 2. `enrichExtensions(extension, transportContext)`: folds in Bazaar (or other)\n * extensions for the verify step\n * 3. `processPaymentRequest(payload, resourceConfig, resourceMeta, extensions)`:\n * runs verify against the facilitator\n * 4. `settlePayment(payload, matchedRequirement)`: settles on-chain\n *\n * Returns a tagged result so the caller can map errors to merchant-shaped responses\n * without owning the orchestration boilerplate. Use `classifyX402SettleResult` to\n * map the tagged result to a recommended HTTP response.\n */\n\nimport type { X402Server } from './x402_server';\n\nexport type ProcessX402SettleResult =\n | {\n success: true;\n /** The matched requirement passed to `settlePayment`. */\n matchedRequirement: unknown;\n /** The settlement response from the facilitator. */\n settleResult: unknown;\n /** Base64-encoded JSON of `settleResult`, ready to set as the `payment-response`\n * HTTP header on the merchant's success response. x402 clients (`@x402/fetch`,\n * `agentscore-pay`) read this to confirm settlement landed. `undefined` when\n * there's no settle result (shouldn't happen on success path but typed defensively). */\n paymentResponseHeader: string | undefined;\n /** The x402 server's `processPaymentRequest` verify result. */\n verifyResult: { success: true; [key: string]: unknown };\n }\n /** No-requirements branch: `buildPaymentRequirements` returned an empty array, so\n * there is nothing to verify against. Indicates a merchant-side misconfiguration\n * (resource config doesn't match any registered scheme/network).\n * Recommended response: log `reason` server-side; map to a controlled 500 to the\n * consumer via `classifyX402SettleResult`. */\n | { success: false; phase: 'no_requirements'; reason: string }\n /** Verify-failed branch: the facilitator's verify step ran and returned\n * `{ success: false, ... }`. Payload is structurally invalid, expired, signed by\n * the wrong wallet, or otherwise rejected by facilitator policy.\n * Recommended response: log `verifyResult` server-side; map to a controlled 400\n * with `payment_proof_invalid` to the consumer via `classifyX402SettleResult`. */\n | { success: false; phase: 'verify_failed'; verifyResult: unknown }\n /** Settle-failed branch: verify succeeded but `settlePayment` threw (on-chain\n * rejection, RPC outage, facilitator broadcast failure, etc.). The agent's\n * credential was valid; funds did not move.\n * Recommended response: log raw `error` server-side; map to a controlled 503 with\n * `payment_provider_unavailable` to the consumer via `classifyX402SettleResult`. */\n | { success: false; phase: 'settle_failed'; error: unknown; matchedRequirement: unknown }\n | {\n success: false;\n /** Facilitator threw an unexpected error during one of the verify-stage calls\n * (build requirements, extension enrich, or processPaymentRequest). Most common\n * cause: the facilitator client rejects the configured network. Coinbase's CDP\n * facilitator throws on Solana devnet because it only supports mainnet networks;\n * Stripe's SPT facilitator throws on EVM networks; etc.\n * Recommended response: log raw `error` server-side; map to a controlled 503\n * with `payment_provider_unavailable` to the consumer via `classifyX402SettleResult`\n * so the agent can pick a different rail. */\n phase: 'facilitator_error';\n /** Which verify-stage step threw. */\n step: 'build_requirements' | 'enrich_extensions' | 'verify_payment';\n error: unknown;\n };\n\n/**\n * The merchant-shaped response for a non-success `ProcessX402SettleResult`.\n *\n * `status` / `code` / `message` are safe to send back to the consumer. `nextSteps`\n * is the agent-instructions block describing what the agent should do next. Raw\n * facilitator errors stay server-side: do NOT serialize the original `error` /\n * `verifyResult` / `reason` to the consumer; log them yourself.\n */\nexport interface ClassifiedX402Error {\n status: 400 | 500 | 503;\n code:\n | 'payment_proof_invalid'\n | 'payment_provider_unavailable'\n | 'payment_internal_error';\n message: string;\n nextSteps: {\n action: string;\n user_message: string;\n retry_after_seconds?: number;\n };\n}\n\n/**\n * Map a `ProcessX402SettleResult` to the recommended merchant response.\n *\n * Returns `null` for `success: true`. For each error phase, returns a controlled\n * status / code / message / nextSteps tuple. Replaces error-message string-sniffing\n * with a phase-based dispatch so merchants stop coupling to facilitator-specific\n * error text.\n *\n * Phase mapping:\n * - `verify_failed` → 400 `payment_proof_invalid` / `regenerate_payment_credential`\n * - `facilitator_error` → 503 `payment_provider_unavailable` / `try_different_rail`\n * - `settle_failed` → 503 `payment_provider_unavailable` / `retry_or_swap_method`\n * - `no_requirements` → 500 `payment_internal_error` / `contact_support`\n *\n * Always log the raw `result` server-side before responding; the returned object\n * is intentionally facilitator-agnostic and never carries raw error detail.\n */\nexport function classifyX402SettleResult(\n result: ProcessX402SettleResult,\n): ClassifiedX402Error | null {\n if (result.success) return null;\n switch (result.phase) {\n case 'no_requirements':\n return {\n status: 500,\n code: 'payment_internal_error',\n message: 'Failed to build x402 payment requirements for this configuration',\n nextSteps: {\n action: 'contact_support',\n user_message:\n 'The merchant could not produce a payment challenge for this request. Try again later or contact support.',\n },\n };\n case 'verify_failed':\n return {\n status: 400,\n code: 'payment_proof_invalid',\n message: 'Payment credential failed verification; regenerate from a fresh 402 challenge',\n nextSteps: {\n action: 'regenerate_payment_credential',\n user_message:\n 'The payment credential was rejected at verify time. Discard it, fetch a fresh 402 challenge, and re-sign.',\n },\n };\n case 'facilitator_error':\n return {\n status: 503,\n code: 'payment_provider_unavailable',\n message: 'Payment provider could not process this network configuration',\n nextSteps: {\n action: 'try_different_rail',\n user_message:\n 'This rail is currently unavailable. Pick a different rail from the 402 challenge and retry.',\n },\n };\n case 'settle_failed':\n return {\n status: 503,\n code: 'payment_provider_unavailable',\n message: 'Payment credential verified but on-chain settlement failed',\n nextSteps: {\n action: 'retry_or_swap_method',\n retry_after_seconds: 10,\n user_message:\n 'Transient settlement error. Retry in a few seconds, or pick a different rail from the 402 challenge.',\n },\n };\n }\n}\n\n/**\n * Classify a thrown error during the 402 orchestration.\n *\n * Catches errors that escape `processX402Settle` (e.g. raised by `mppx.compose`,\n * a Stripe SDK call, or any other payment-side library code wrapped in a single\n * `try/catch` around the full settle flow). Returns a `ClassifiedX402Error`\n * when the error message matches a known pattern; `null` otherwise.\n *\n * Callers should rethrow on `null` — this helper never swallows unknown errors.\n *\n * Pattern matching is case-insensitive substring on the error message:\n * - `\"x402version\"` / `\"invalid payment\"` / `\"unsupported x402\"` →\n * 400 `payment_proof_invalid` / `regenerate_payment_credential`\n * - `\"stripe\"` / `\"facilitator\"` / `\"cdp\"` →\n * 503 `payment_provider_unavailable` / `retry_or_swap_method`\n * - Anything else → `null` (caller rethrows)\n *\n * Substring matching is intentionally narrow. New error families should land\n * here explicitly rather than have the helper grow opaque heuristics. For\n * tagged failure results that already classify themselves, use\n * `classifyX402SettleResult`.\n */\nexport function classifyOrchestrationError(err: unknown): ClassifiedX402Error | null {\n let msg: string;\n if (err instanceof Error) {\n msg = err.message;\n } else if (typeof err === 'string') {\n msg = err;\n } else {\n return null;\n }\n const msgLower = msg.toLowerCase();\n\n if (\n msgLower.includes('x402version') ||\n msgLower.includes('invalid payment') ||\n msgLower.includes('unsupported x402')\n ) {\n return {\n status: 400,\n code: 'payment_proof_invalid',\n message: 'Payment credential is malformed or uses an unsupported version',\n nextSteps: {\n action: 'regenerate_payment_credential',\n user_message:\n 'The payment credential is malformed or uses an unsupported version. Regenerate from a fresh 402 challenge and re-sign.',\n },\n };\n }\n\n if (\n msgLower.includes('stripe') ||\n msgLower.includes('facilitator') ||\n msgLower.includes('cdp')\n ) {\n return {\n status: 503,\n code: 'payment_provider_unavailable',\n message: 'Payment provider returned an error',\n nextSteps: {\n action: 'retry_or_swap_method',\n retry_after_seconds: 10,\n user_message:\n 'Transient payment-provider error. Retry in a few seconds, or pick a different rail from the 402 challenge.',\n },\n };\n }\n\n return null;\n}\n\nexport async function processX402Settle({\n x402Server,\n payload,\n resourceConfig,\n resourceMeta,\n extension,\n transportContext,\n}: {\n /** The x402 server instance from `createX402Server`. */\n x402Server: X402Server;\n /** The verified x402 payload extracted from the X-Payment header. */\n payload: unknown;\n /** Resource configuration the facilitator validates against (network, price, payTo,\n * asset, maxTimeoutSeconds, etc.). Shape is x402-server-specific. */\n resourceConfig: unknown;\n /** Resource metadata exposed to the facilitator (URL, description, mime type). */\n resourceMeta: { url: string; description: string; mimeType: string };\n /** Optional extension to enrich during verify (e.g. Bazaar). */\n extension?: unknown;\n /** Transport context for the extension enrich step. Defaults to `{ method: 'POST',\n * adapter: { getPath: () => new URL(resourceMeta.url).pathname }, routePattern: <pathname> }`. */\n transportContext?: unknown;\n}): Promise<ProcessX402SettleResult> {\n const server = x402Server as unknown as {\n buildPaymentRequirements: (cfg: unknown) => Promise<unknown[]>;\n enrichExtensions: (ext: unknown, ctx: unknown) => unknown;\n verifyPayment: (\n paymentPayload: unknown,\n requirements: unknown,\n declaredExtensions?: unknown,\n transportContext?: unknown,\n ) => Promise<{ success: boolean; [key: string]: unknown } | { isValid?: boolean; [key: string]: unknown }>;\n settlePayment: (\n paymentPayload: unknown,\n requirements: unknown,\n declaredExtensions?: unknown,\n transportContext?: unknown,\n ) => Promise<unknown>;\n };\n\n let builtRequirements: unknown[];\n try {\n builtRequirements = await server.buildPaymentRequirements(resourceConfig);\n } catch (err) {\n console.warn('[x402_settle] build_requirements failed:', err instanceof Error ? err.message : err);\n return { success: false, phase: 'facilitator_error', step: 'build_requirements', error: err };\n }\n const matchedRequirement = builtRequirements[0];\n if (!matchedRequirement) {\n return { success: false, phase: 'no_requirements', reason: 'x402Server.buildPaymentRequirements returned empty' };\n }\n\n const resolvedTransportContext = transportContext ?? (() => {\n const path = new URL(resourceMeta.url).pathname;\n return { method: 'POST', adapter: { getPath: () => path }, routePattern: path };\n })();\n\n let enrichedExt: unknown;\n try {\n enrichedExt = extension !== undefined\n ? server.enrichExtensions(extension, resolvedTransportContext)\n : undefined;\n } catch (err) {\n console.warn('[x402_settle] enrich_extensions failed:', err instanceof Error ? err.message : err);\n return { success: false, phase: 'facilitator_error', step: 'enrich_extensions', error: err };\n }\n\n let verifyResult: { success?: boolean; isValid?: boolean; [key: string]: unknown };\n try {\n verifyResult = await server.verifyPayment(\n payload,\n matchedRequirement,\n enrichedExt as Record<string, unknown> | undefined,\n resolvedTransportContext,\n );\n } catch (err) {\n console.warn('[x402_settle] verify_payment failed:', err instanceof Error ? err.message : err);\n return { success: false, phase: 'facilitator_error', step: 'verify_payment', error: err };\n }\n\n // x402/core's ResourceVerifyResponse uses `isValid` (per spec). Accept the\n // legacy `success` field too for older facilitator builds.\n const verifyOk = verifyResult.isValid === true || verifyResult.success === true;\n if (!verifyOk) {\n return { success: false, phase: 'verify_failed', verifyResult };\n }\n\n try {\n const settleResult = await server.settlePayment(\n payload,\n matchedRequirement,\n enrichedExt as Record<string, unknown> | undefined,\n resolvedTransportContext,\n );\n const paymentResponseHeader = settleResult\n ? Buffer.from(JSON.stringify(settleResult)).toString('base64')\n : undefined;\n return {\n success: true,\n matchedRequirement,\n settleResult,\n paymentResponseHeader,\n verifyResult: verifyResult as { success: true; [key: string]: unknown },\n };\n } catch (err) {\n return { success: false, phase: 'settle_failed', error: err, matchedRequirement };\n }\n}\n","/**\n * x402 boot-time + per-request validation helpers.\n *\n * Two layers of validation every x402-accepting merchant repeats:\n *\n * - **Boot-time**: validate the configured `X402_BASE_NETWORK` env var is in the\n * supported set. Failing loud at boot is much better than per-request \"unsupported\n * network\" errors after a misconfigured deploy.\n *\n * - **Per-request**: when an x402 X-Payment header arrives, parse the base64 payload,\n * extract the signed network + payTo, validate against the merchant's accepted\n * network, validate the payTo address shape, and check that the payTo was minted by\n * THIS merchant (cache hit). Each step has its own denial code and `next_steps`\n * shape — getting the message right by hand across 4 conditions is fiddly.\n */\n\nimport { networks } from './networks';\n\n/** CAIP-2 networks the commerce SDK supports for x402 Base (EVM USDC). */\nexport const X402_SUPPORTED_BASE_NETWORKS = new Set<string>([\n networks.base.mainnet.caip2,\n networks.base.sepolia.caip2,\n]);\n\n/**\n * Boot-time guard: throws if the base network isn't supported. Call once at module\n * init / server boot.\n *\n * Throws `Error` with a message that names the unsupported value AND lists the valid\n * options — agents tracking down a misconfigured deploy don't need to grep for the\n * supported list.\n */\nexport function validateX402NetworkConfig({ baseNetwork }: { baseNetwork: string }): void {\n if (!X402_SUPPORTED_BASE_NETWORKS.has(baseNetwork)) {\n throw new Error(\n `X402_BASE_NETWORK=${baseNetwork} is not supported. Use one of: ${[...X402_SUPPORTED_BASE_NETWORKS].join(', ')}`,\n );\n }\n}\n\nconst EVM_ADDRESS_RE = /^0x[0-9a-fA-F]{40}$/;\n\nexport type VerifyX402RequestResult =\n | {\n ok: true;\n /** The base64-decoded JSON payload from the X-Payment header. */\n payload: { accepted?: { network?: string; payTo?: string }; [key: string]: unknown };\n /** The CAIP-2 network the agent signed for. */\n signedNetwork: string;\n /** The on-chain pay-to address the agent signed for (already validated). */\n signedPayTo: string;\n }\n | {\n ok: false;\n /** Suitable as a JSON body for the merchant's denial response. Includes\n * `next_steps` with `regenerate_payment_credential` action + a per-condition\n * `user_message` and a footgun `warning` so agents can recover deterministically\n * from the response alone. */\n body: {\n error: { code: string; message: string };\n next_steps: {\n action: 'regenerate_payment_credential';\n user_message: string;\n warning: string;\n };\n };\n /** HTTP status to use for the denial response. */\n status: 400;\n };\n\nconst REGENERATE_WARNING =\n 'Use `agentscore-pay pay --chain base` (or `tempo request` for Tempo USDC) so the credential is signed and submitted via the protocol handshake. Do NOT use `tempo wallet transfer` — that sends USDC on-chain but does not complete the handshake.';\n\nfunction regenerateBody(message: string, userMessage: string) {\n return {\n error: { code: 'payment_proof_invalid' as const, message },\n next_steps: {\n action: 'regenerate_payment_credential' as const,\n user_message: userMessage,\n warning: REGENERATE_WARNING,\n },\n };\n}\n\n/**\n * Per-request: parse the x402 X-Payment header, validate the network + payTo, and\n * confirm the address was minted by this merchant. One call replaces ~45 lines of\n * inline header decode + regex validation + cache lookup.\n *\n * Returns `{ok: true, payload, signedNetwork, signedPayTo}` when valid; the caller\n * passes `payload` straight into `processX402Settle`.\n *\n * Returns `{ok: false, body, status}` when invalid — the merchant just does\n * `return c.json(body, status)` (or framework equivalent).\n *\n * Reads the header from `payment-signature` first, falling back to `x-payment` (both\n * are in the wild as the binary-friendly transport name evolved).\n */\nexport async function verifyX402Request({\n request,\n isCachedAddress,\n acceptedNetwork,\n}: {\n /** The incoming Request — `verifyX402Request` reads the X-Payment / payment-signature header. */\n request: Request;\n /** Async lookup that returns true when the address was minted by this merchant\n * (typically `piCache.hasAddress`). The check validates that the credential's\n * deposit address matches one the merchant actually minted. */\n isCachedAddress: (address: string) => Promise<boolean>;\n /** The merchant's accepted Base network. CAIP-2, e.g. `'eip155:8453'`. */\n acceptedNetwork: string;\n}): Promise<VerifyX402RequestResult> {\n const headerValue =\n request.headers.get('payment-signature')\n ?? request.headers.get('x-payment');\n if (!headerValue) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n 'X-Payment header missing',\n 'No X-Payment header was sent. Generate the credential from the 402 challenge and resubmit on the same endpoint.',\n ),\n };\n }\n\n let payload: { accepted?: { network?: string; payTo?: string }; [key: string]: unknown };\n try {\n payload = JSON.parse(Buffer.from(headerValue, 'base64').toString());\n } catch {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n 'X-Payment header is not valid base64 JSON',\n 'The payment credential could not be decoded. Reconstruct the credential from the 402 challenge and retry.',\n ),\n };\n }\n\n const signedNetwork = payload.accepted?.network;\n const signedPayTo = payload.accepted?.payTo;\n\n if (!signedNetwork || signedNetwork !== acceptedNetwork) {\n if (signedNetwork && signedNetwork.toLowerCase().startsWith('solana:')) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n `x402 on ${signedNetwork} is not accepted; Solana payments must use the \\`solana/charge\\` rail advertised in the 402 challenge. This server accepts x402 on ${acceptedNetwork} only.`,\n 'Solana payments are not accepted over x402 at this merchant. Pick the `solana/charge` rail from the 402 challenge and re-sign.',\n ),\n };\n }\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n `Unsupported x402 network ${signedNetwork ?? '<missing>'}; this server accepts ${acceptedNetwork}.`,\n 'The credential signed for an unsupported network. Pick the accepted network from the 402 challenge and re-sign.',\n ),\n };\n }\n\n const addressShapeOk = typeof signedPayTo === 'string' && EVM_ADDRESS_RE.test(signedPayTo);\n\n if (!signedPayTo || !addressShapeOk) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n `Payment payload missing or malformed accepted.payTo address for network ${signedNetwork}`,\n 'The credential payload is missing or malformed payTo for the signed network. Reconstruct the credential from the 402 challenge.',\n ),\n };\n }\n\n if (!(await isCachedAddress(signedPayTo))) {\n return {\n ok: false,\n status: 400,\n body: regenerateBody(\n 'payTo address not found in cache or expired. Request a fresh 402 challenge and retry.',\n 'The deposit address is unknown or expired on this server. Request a fresh 402 challenge and re-sign against the new payTo.',\n ),\n };\n }\n\n return { ok: true, payload, signedNetwork, signedPayTo };\n}\n","/**\n * Wraps the `mppStripe.charge(...)` boilerplate from `mppx/server`. Returns the value\n * vendors pass into `Mppx.create({ methods: [...] })`. mppx is an OPTIONAL peer dependency —\n * vendors who don't use Stripe SPT don't need to install it.\n *\n * Example:\n *\n * import { Mppx, tempo } from 'mppx/server';\n * import { createMppxStripe } from '@agent-score/commerce/stripe-multichain';\n *\n * const stripeMethod = await createMppxStripe({\n * profileId: process.env.STRIPE_PROFILE_ID!,\n * secretKey: process.env.STRIPE_SECRET_KEY!,\n * });\n *\n * const mppx = Mppx.create({\n * methods: [tempo.charge({...}), stripeMethod],\n * secretKey: process.env.MPP_SECRET_KEY!,\n * });\n *\n * Throws if mppx is not installed.\n */\nexport async function createMppxStripe({\n profileId,\n secretKey,\n paymentMethodTypes,\n}: {\n /** Stripe profile_id / network_id (the value advertised in your `stripe/charge` accepted_methods entry). */\n profileId: string;\n /** Stripe secret key — mppx uses it to validate inbound SharedPaymentTokens. */\n secretKey: string;\n /** Payment method types this stripe rail accepts. Default ['card', 'link']. */\n paymentMethodTypes?: string[];\n}): Promise<unknown> {\n const moduleName = 'mppx/server';\n const mppx = (await import(moduleName).catch(() => null)) as {\n stripe?: {\n charge: (config: {\n networkId: string;\n paymentMethodTypes?: string[];\n secretKey: string;\n }) => unknown;\n };\n } | null;\n /* v8 ignore start -- peer-dep-absence guard; mppx is installed in the test env so this branch can't be exercised without mocking the dynamic import */\n if (!mppx?.stripe?.charge) {\n throw new Error(\n 'mppx not installed — install with `npm install mppx` to use createMppxStripe.',\n );\n }\n /* v8 ignore stop */\n return mppx.stripe.charge({\n networkId: profileId,\n paymentMethodTypes: paymentMethodTypes ?? ['card', 'link'],\n secretKey,\n });\n}\n","import { createMppxStripe } from '../stripe-multichain/mppx_stripe';\nimport { networks } from './networks';\nimport {\n resolveRecipient,\n type SolanaMppRailSpec,\n type StripeRailSpec,\n type TempoRailSpec,\n type TempoSessionRailSpec,\n} from './rail_spec';\nimport { USDC } from './usdc';\n\nexport type MppxRailSpec =\n | TempoRailSpec\n | SolanaMppRailSpec\n | TempoSessionRailSpec\n | StripeRailSpec;\n\ntype SolanaMppNetwork = 'mainnet-beta' | 'devnet' | 'localnet';\n\ninterface MppxModule {\n Mppx?: { create: (opts: { methods: unknown[]; secretKey: string }) => unknown };\n tempo?: {\n charge: (opts: { currency: string; recipient: string; testnet?: boolean }) => unknown;\n session?: (opts: {\n currency: string;\n recipient: string;\n escrowContract: string;\n store: unknown;\n testnet?: boolean;\n chains?: unknown;\n }) => unknown;\n };\n}\n\ninterface SolanaMppModule {\n charge?: (opts: {\n recipient: string;\n currency?: string;\n decimals?: number;\n network?: string;\n rpcUrl?: string;\n signer?: unknown;\n tokenProgram?: string;\n }) => unknown;\n}\n\nfunction isStripeRailSpec(s: MppxRailSpec): s is StripeRailSpec {\n return !('recipient' in s);\n}\n\nfunction isTempoSessionRailSpec(s: MppxRailSpec): s is TempoSessionRailSpec {\n return 'escrowContract' in s && 'store' in s;\n}\n\nfunction isSolanaMppRailSpec(s: MppxRailSpec): s is SolanaMppRailSpec {\n if (!('recipient' in s)) return false;\n if ('escrowContract' in s) return false;\n if ('rpcUrl' in s || 'tokenProgram' in s) return true;\n return (s as { network?: string }).network?.startsWith('solana:') ?? false;\n}\n\nfunction solanaNetworkFromCAIP2(caip2: string | undefined): SolanaMppNetwork {\n if (caip2 === networks.solana.devnet.caip2) return 'devnet';\n return 'mainnet-beta';\n}\n\nfunction solanaDefaultRpcUrl(network: SolanaMppNetwork): string {\n if (network === 'mainnet-beta') return 'https://api.mainnet-beta.solana.com';\n if (network === 'devnet') return 'https://api.devnet.solana.com';\n return 'http://localhost:8899';\n}\n\n/**\n * One-call mppx server setup. Wires `tempo.charge(...)`, `tempo.session(...)`,\n * `@solana/mpp.charge(...)`, and Stripe SPT (via createMppxStripe) from canonical\n * `*RailSpec` configs, replacing the boilerplate of constructing each method by\n * hand.\n *\n * const mppx = await createMppxServer({\n * rails: {\n * tempo: { recipient: TEMPO_ADDR } satisfies TempoRailSpec,\n * solana: { recipient: SOL_ADDR } satisfies SolanaMppRailSpec,\n * stripe: { profileId: STRIPE_PROFILE_ID, secretKey: STRIPE_SECRET_KEY } satisfies StripeRailSpec,\n * },\n * secretKey: MPP_SECRET_KEY,\n * });\n *\n * Keys are rail names (`tempo` / `solana` / `tempo_session` / `stripe`); values\n * are the matching `*RailSpec` types every other helper also consumes.\n *\n * `mppx` is an OPTIONAL peer dependency — install it only if you accept MPP rails.\n */\nexport async function createMppxServer({\n rails,\n methods: extraMethods,\n secretKey,\n}: {\n rails?: Record<string, MppxRailSpec>;\n methods?: unknown[];\n secretKey: string;\n}): Promise<unknown> {\n const mppx = await dynamicImport<MppxModule>('mppx/server');\n /* v8 ignore start -- peer-dep-absence guard; mppx is installed in the test env */\n if (!mppx?.Mppx?.create) {\n throw new Error('mppx not installed — `npm install mppx` to use createMppxServer.');\n }\n /* v8 ignore stop */\n\n const methods: unknown[] = [...(extraMethods ?? [])];\n\n for (const [name, spec] of Object.entries(rails ?? {})) {\n if (isStripeRailSpec(spec)) {\n methods.push(await registerStripe(spec));\n continue;\n }\n if (isTempoSessionRailSpec(spec)) {\n methods.push(await registerTempoSession(mppx, spec));\n continue;\n }\n if (isSolanaMppRailSpec(spec)) {\n methods.push(await registerSolana(spec));\n continue;\n }\n // Default: TempoRailSpec (bare `{recipient, ...}` with no Solana / session markers).\n methods.push(registerTempo(mppx, spec as TempoRailSpec, name));\n }\n\n return mppx.Mppx.create({ methods, secretKey });\n}\n\nfunction registerTempo(mppx: MppxModule, spec: TempoRailSpec, _name: string): unknown {\n /* v8 ignore start -- peer-dep version-mismatch guard; current mppx ships tempo.charge */\n if (!mppx.tempo?.charge) {\n throw new Error('mppx.tempo.charge not available — check installed mppx version.');\n }\n /* v8 ignore stop */\n const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;\n if (typeof spec.recipient !== 'string') {\n throw new TypeError(\n 'createMppxServer: TempoRailSpec requires a string recipient (per-order factories not supported here).',\n );\n }\n return mppx.tempo.charge({\n currency: spec.token ?? defaultCurrency,\n recipient: spec.recipient,\n testnet: spec.testnet ?? false,\n });\n}\n\nasync function registerTempoSession(mppx: MppxModule, spec: TempoSessionRailSpec): Promise<unknown> {\n /* v8 ignore start -- peer-dep version-mismatch guard; current mppx ships tempo.session */\n if (!mppx.tempo?.session) {\n throw new Error(\n 'mppx.tempo.session not available — your mppx version may not support sessions yet. Upgrade with `npm install mppx@latest`.',\n );\n }\n /* v8 ignore stop */\n const defaultCurrency = spec.testnet ? USDC.tempo.testnet.address : USDC.tempo.mainnet.address;\n return mppx.tempo.session({\n currency: spec.currency ?? defaultCurrency,\n recipient: await resolveRecipient(spec.recipient),\n escrowContract: spec.escrowContract,\n store: spec.store,\n testnet: spec.testnet ?? false,\n ...(spec.chains ? { chains: spec.chains } : {}),\n });\n}\n\nasync function registerSolana(spec: SolanaMppRailSpec): Promise<unknown> {\n const solanaMpp = await dynamicImport<SolanaMppModule>('@solana/mpp/server');\n if (!solanaMpp?.charge) {\n throw new Error(\n '@solana/mpp not installed — `npm install @solana/mpp @solana/kit` to use the solana rail.',\n );\n }\n const network = solanaNetworkFromCAIP2(spec.network);\n const defaultMint =\n network === 'mainnet-beta' ? USDC.solana.mainnet.mint : USDC.solana.devnet.mint;\n const defaultDecimals =\n network === 'mainnet-beta' ? USDC.solana.mainnet.decimals : USDC.solana.devnet.decimals;\n if (typeof spec.recipient !== 'string') {\n throw new TypeError(\n 'createMppxServer: SolanaMppRailSpec requires a string recipient (per-order factories not supported here).',\n );\n }\n const baseMethod = solanaMpp.charge({\n recipient: spec.recipient,\n currency: spec.token ?? defaultMint,\n decimals: spec.decimals ?? defaultDecimals,\n network,\n ...(spec.rpcUrl ? { rpcUrl: spec.rpcUrl } : {}),\n ...(spec.signer ? { signer: spec.signer } : {}),\n ...(spec.tokenProgram ? { tokenProgram: spec.tokenProgram } : {}),\n }) as SolanaChargeMethod;\n return wrapSolanaChargeWithFinalizedBlockhash(baseMethod, spec.rpcUrl ?? solanaDefaultRpcUrl(network));\n}\n\nasync function registerStripe(spec: StripeRailSpec): Promise<unknown> {\n if (!spec.profileId || !spec.secretKey) {\n throw new Error(\n 'createMppxServer: StripeRailSpec requires both profileId and secretKey.',\n );\n }\n return createMppxStripe({\n profileId: spec.profileId,\n secretKey: spec.secretKey,\n paymentMethodTypes: spec.paymentMethodTypes,\n });\n}\n\nasync function dynamicImport<T>(moduleName: string): Promise<T | null> {\n try {\n return (await import(moduleName)) as T;\n } catch {\n return null;\n }\n}\n\ntype SolanaChargeRequestArgs = { credential?: unknown; request?: unknown };\ntype SolanaChargeMethod = {\n request?: (args: SolanaChargeRequestArgs) => Promise<unknown>;\n} & Record<string, unknown>;\n\n/**\n * Wraps `@solana/mpp.charge()`'s Method so the issued challenge carries a\n * `finalized` blockhash instead of `confirmed`.\n *\n * `@solana/mpp` <= 0.5.2 fetches `getLatestBlockhash` with `commitment: 'confirmed'`\n * but its broadcast `sendTransaction` sets `skipPreflight: false` without an\n * overridden `preflightCommitment`. The RPC server's default preflight commitment\n * is `finalized`, which rejects any blockhash that hasn't yet finalized with a\n * \"Blockhash not found\" error. Handing the client a `finalized` blockhash up\n * front sidesteps the mismatch.\n *\n * Trade-off: the signing window shrinks from ~58s (confirmed) to ~46s (finalized).\n * Fine for agent-driven flows; manual signing flows still have plenty of margin.\n */\nexport function wrapSolanaChargeWithFinalizedBlockhash(\n baseMethod: SolanaChargeMethod,\n rpcUrl: string,\n): SolanaChargeMethod {\n return {\n ...baseMethod,\n async request(args: SolanaChargeRequestArgs) {\n const orig = (await baseMethod.request!(args)) as\n | { methodDetails?: Record<string, unknown> }\n | undefined;\n if (args.credential || !orig || typeof orig !== 'object') return orig;\n try {\n const res = await fetch(rpcUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n id: 1,\n jsonrpc: '2.0',\n method: 'getLatestBlockhash',\n params: [{ commitment: 'finalized' }],\n }),\n });\n const data = (await res.json()) as { result?: { value?: { blockhash?: string } } };\n const finalized = data?.result?.value?.blockhash;\n if (finalized) {\n return {\n ...orig,\n methodDetails: { ...(orig.methodDetails ?? {}), recentBlockhash: finalized },\n };\n }\n } catch {\n /* fall back to upstream's confirmed blockhash */\n }\n return orig;\n },\n };\n}\n\n/**\n * Result shape of `composeMppxRequest`. mppx's `mppx.compose(...)(request)`\n * resolves to one of two variants — type-narrowed here so consumers can\n * `if (result.status === 200) { result.withReceipt(...) }` without an\n * `as any` cast.\n */\nexport type MppxComposeResult =\n | {\n status: 200;\n /** Wraps a Response with the `Payment-Receipt` header attached. */\n withReceipt: (response: Response) => Response;\n [k: string]: unknown;\n }\n | {\n status: 402;\n /** The 402 challenge Response mppx emitted (carries WWW-Authenticate). */\n challenge: Response;\n [k: string]: unknown;\n };\n\n/**\n * Run `mppx.compose(...intents)(request)` with a typed return. Replaces the\n * `(mppx as any).compose(...intents)(request)` cast every hand-rolled\n * `composeMppx` hook ends up writing.\n *\n * @example\n * ```ts\n * const result = await composeMppxRequest(mppx, [\n * ['tempo/charge', { amount, currency, decimals, recipient }],\n * ['stripe/charge', { amount, currency: 'usd', decimals: 2 }],\n * ], ctx.request.raw);\n * if (result.status === 402) return { status: 402, headers: mppxChallengeHeaders(result) };\n * return { status: 200, raw: result };\n * ```\n */\nexport async function composeMppxRequest(\n mppx: unknown,\n intents: readonly unknown[],\n request: Request,\n): Promise<MppxComposeResult> {\n if (!mppx || typeof mppx !== 'object' || !('compose' in mppx)) {\n throw new Error('composeMppxRequest: argument is not an mppx server instance');\n }\n const compose = (mppx as { compose: unknown }).compose;\n if (typeof compose !== 'function') {\n throw new Error('composeMppxRequest: mppx.compose is not a function');\n }\n const typedCompose = compose as (...intents: readonly unknown[]) => (req: Request) => Promise<MppxComposeResult>;\n const handler = typedCompose.apply(mppx, [...intents]);\n return handler(request);\n}\n\n/**\n * Extract the 402 challenge response's headers as a plain `Record<string, string>`,\n * the shape `MppxComposeOutcome.headers` accepts. Wraps the one-liner every\n * hand-rolled compose hook writes.\n */\nexport function mppxChallengeHeaders(result: { challenge: Response }): Record<string, string> {\n return Object.fromEntries(result.challenge.headers);\n}\n","/**\n * Detect which payment-protocol family the inbound request carries.\n *\n * Returns `\"mpp\"` when an `Authorization` header starts with the `Payment`\n * scheme (case-insensitive per RFC 7235). Returns `\"x402\"` when a non-empty\n * `payment-signature` or `x-payment` header is present. Returns `null` otherwise.\n *\n * In practice a client constructs a request with exactly one protocol's headers;\n * both arriving together is a client bug or misconfigured proxy. The helper checks\n * MPP first so the rare degenerate case resolves to MPP. Empty header values are\n * treated as absent. Header-name lookups are case-insensitive (RFC 7230 §3.2).\n * The narrower rail naming (`\"tempo\"` vs `\"solana\"` inside MPP) is merchant-side,\n * derived from the credential body, not this helper.\n *\n * Accepts either a Web Fetch `Headers` instance (case-insensitive lookup native)\n * or a plain object (case-insensitive lookup applied internally).\n */\nexport function detectRailFromHeaders(\n headers: Headers | Record<string, string | string[] | undefined>,\n): 'x402' | 'mpp' | null {\n const get = (name: string): string => {\n if (headers instanceof Headers) {\n return headers.get(name) ?? '';\n }\n const lower = name.toLowerCase();\n for (const [k, v] of Object.entries(headers)) {\n if (k.toLowerCase() === lower) {\n // `null` is outside the TypeScript input type, but plain-JS callers can\n // still reach here with `{ 'x-payment': null }`; guard so `.toLowerCase()`\n // on the result doesn't throw downstream.\n if (v === undefined || v === null) return '';\n return Array.isArray(v) ? (v[0] ?? '') : v;\n }\n }\n return '';\n };\n\n const auth = get('authorization');\n if (auth.toLowerCase().startsWith('payment ')) {\n return 'mpp';\n }\n if (get('payment-signature') || get('x-payment')) {\n return 'x402';\n }\n return null;\n}\n\nexport interface SettlementHandlers<TPayload, TResult> {\n evm?: (payload: TPayload) => TResult | Promise<TResult>;\n svm?: (payload: TPayload) => TResult | Promise<TResult>;\n}\n\nexport interface SettlementPayloadLike {\n accepted: { network: string };\n}\n\n/**\n * Dispatches a settlement payload to the right network-family handler based on\n * the CAIP-2 network string in `payload.accepted.network`:\n *\n * - eip155:* → handlers.evm\n * - solana:* → handlers.svm\n *\n * Throws if the network is unrecognized or the matching handler is missing.\n * Most vendors will register handlers for both rail families they accept.\n */\nexport async function dispatchSettlementByNetwork<\n TPayload extends SettlementPayloadLike,\n TResult,\n>(\n payload: TPayload,\n handlers: SettlementHandlers<TPayload, TResult>,\n): Promise<TResult> {\n const network = payload.accepted.network;\n if (network.startsWith('eip155:')) {\n if (!handlers.evm) {\n throw new Error(`No EVM settlement handler registered (network: ${network})`);\n }\n return handlers.evm(payload);\n }\n if (network.startsWith('solana:')) {\n if (!handlers.svm) {\n throw new Error(`No Solana settlement handler registered (network: ${network})`);\n }\n return handlers.svm(payload);\n }\n throw new Error(`Unrecognized network in settlement payload: ${network}`);\n}\n","/**\n * Joins multiple Payment directives into a single WWW-Authenticate header value.\n * Per RFC 7235, multiple challenges are comma-separated.\n */\nexport function wwwAuthenticateHeader(directives: string[]): string {\n return directives.join(', ');\n}\n\n/**\n * Add the v1↔v2 amount-field alias to each accepts entry. Idempotent. Used by both\n * `paymentRequiredHeader` (header emit) and `build402Body` (body emit) so every\n * x402 entry on the wire carries BOTH `amount` (v2 spec) AND `maxAmountRequired`\n * (v1 spec) — strict v1-only parsers (e.g. Coinbase awal at `payments-mcp.coinbase.com`,\n * which is hardcoded to read `maxAmountRequired`) work alongside strict v2 parsers,\n * which ignore the alias.\n */\nexport function aliasAmountFields(accepts: unknown[]): unknown[] {\n return accepts.map((entry) => {\n if (entry === null || typeof entry !== 'object') return entry;\n const e = entry as Record<string, unknown>;\n const hasAmount = e.amount !== undefined;\n const hasMaxAmount = e.maxAmountRequired !== undefined;\n if (hasAmount && !hasMaxAmount) return { ...e, maxAmountRequired: e.amount };\n if (hasMaxAmount && !hasAmount) return { ...e, amount: e.maxAmountRequired };\n return e;\n });\n}\n\n/**\n * Encode the standard x402 PAYMENT-REQUIRED header (base64-encoded JSON of the\n * PaymentRequired object). Clients that recognize the header (`@x402/fetch`,\n * `@x402/core` HTTPClient, `agentscore-pay`) prefer it over body fields.\n *\n * Note: do NOT add a v1↔v2 amount-field alias here. `@x402/core`'s\n * `findMatchingRequirements` uses `deepEqual` against the agent's signed\n * `accepted` payload — any field present on one side and missing on the other\n * (e.g. `maxAmountRequired` on the wire body but not in `buildPaymentRequirements`'s\n * output) makes the match silently fail at settle time. Keep `accepts` shape\n * identical to whatever `buildPaymentRequirements` produces server-side.\n */\nexport function paymentRequiredHeader({\n x402Version,\n accepts,\n resource,\n}: {\n x402Version: 1 | 2;\n accepts: unknown[];\n resource?: { url: string; mimeType?: string };\n}): string {\n return Buffer.from(JSON.stringify({ x402Version, accepts, ...(resource ? { resource } : {}) })).toString('base64');\n}\n","/**\n * Multi-rail payment header bundle — one call composes both `WWW-Authenticate` (the\n * `paymentauth.org` Payment directives) and the standard x402 `PAYMENT-REQUIRED` header\n * from a single rails declaration. Reduces ~10 lines of merchant boilerplate per 402\n * response.\n *\n * Layered on top of `paymentDirective` / `wwwAuthenticateHeader` / `paymentRequiredHeader`\n * — those primitives stay exposed for vendors who want full control.\n */\n\nimport { buildPaymentDirective } from './directive';\nimport { paymentRequiredHeader, wwwAuthenticateHeader } from './wwwauthenticate';\n\nexport interface PaymentHeadersRail {\n /** Symbolic rail name — `tempo-mainnet`, `x402-base-mainnet`, `stripe`, etc. */\n rail: string;\n /** Amount in USD as a number or string. */\n amountUsd: string | number;\n /** Recipient address (on-chain) — required for crypto rails. */\n recipient?: string;\n /** Stripe profile_id / network_id — required for `stripe` rail. */\n networkId?: string;\n /** EVM chain id override — usually inferred from rail. */\n chainId?: number;\n /** Token contract / currency override — usually inferred from rail. */\n currency?: string;\n /** Decimal precision override — usually inferred from rail (USDC=6, etc.). */\n decimals?: number;\n /** MPP method override — usually inferred from rail. */\n method?: string;\n /** MPP intent. Default `charge`. */\n intent?: string;\n /** ISO-8601 expiry. Default now + 5 min. */\n expires?: string;\n}\n\nexport interface PaymentHeadersResult {\n 'www-authenticate': string;\n 'PAYMENT-REQUIRED'?: string;\n}\n\n/**\n * Compose `WWW-Authenticate` (multi-directive) and `PAYMENT-REQUIRED` (x402 base64) headers\n * from a single rails declaration. Returns an object suitable for spreading into a\n * `Headers` constructor or the `headers` field of a `Response`.\n *\n * Example:\n * ```ts\n * const headers = buildPaymentHeaders({\n * orderId: 'ord_123',\n * realm: 'agents.merchant.example',\n * rails: [\n * { rail: 'tempo-mainnet', amountUsd: 25, recipient: TEMPO_ADDR },\n * { rail: 'x402-base-mainnet', amountUsd: 25, recipient: BASE_ADDR },\n * { rail: 'stripe', amountUsd: 25, networkId: STRIPE_PROFILE_ID },\n * ],\n * x402: { accepts: x402Accepts, version: 1 },\n * });\n * return new Response(JSON.stringify(body), { status: 402, headers });\n * ```\n */\nexport function buildPaymentHeaders({\n rails,\n orderId,\n realm,\n x402,\n}: {\n /** Rails the merchant accepts on this 402. Each becomes one `Payment` directive. */\n rails: PaymentHeadersRail[];\n /** Order id used as the directive challenge id (per-rail it becomes `${orderId}-${rail}`). */\n orderId: string;\n /** Realm — the host of the merchant URL (e.g. `agents.merchant.example`). */\n realm: string;\n /**\n * Optional x402 `accepts` array — included as the standard PAYMENT-REQUIRED header so\n * x402 clients (`@x402/fetch`, `@x402/core` HTTPClient, `agentscore-pay`) can parse the\n * base64-encoded JSON form instead of the WWW-Authenticate text directives. Pass\n * `undefined` (or omit) to skip the PAYMENT-REQUIRED header.\n */\n x402?: { accepts: unknown[]; version?: 1 | 2; resource?: { url: string; mimeType?: string } };\n}): PaymentHeadersResult {\n const directives = rails.map((rail) =>\n buildPaymentDirective({\n id: `${orderId}-${rail.rail}`,\n realm,\n rail: rail.rail,\n amountUsd: rail.amountUsd,\n ...(rail.recipient !== undefined ? { recipient: rail.recipient } : {}),\n ...(rail.networkId !== undefined ? { networkId: rail.networkId } : {}),\n ...(rail.chainId !== undefined ? { chainId: rail.chainId } : {}),\n ...(rail.currency !== undefined ? { currency: rail.currency } : {}),\n ...(rail.decimals !== undefined ? { decimals: rail.decimals } : {}),\n ...(rail.method !== undefined ? { method: rail.method } : {}),\n ...(rail.intent !== undefined ? { intent: rail.intent } : {}),\n ...(rail.expires !== undefined ? { expires: rail.expires } : {}),\n }),\n );\n\n const result: PaymentHeadersResult = {\n 'www-authenticate': wwwAuthenticateHeader(directives),\n };\n\n if (x402) {\n result['PAYMENT-REQUIRED'] = paymentRequiredHeader({\n x402Version: x402.version ?? 2,\n accepts: x402.accepts,\n ...(x402.resource ? { resource: x402.resource } : {}),\n });\n }\n\n return result;\n}\n","/**\n * Idempotency-key composition.\n *\n * Stable per-payment keys that retries of the same logical payment can reuse, so AgentScore's\n * `/v1/credentials/wallets` capture endpoint dedupes correctly and the operator's\n * `transaction_count` doesn't inflate.\n *\n * Convention:\n * 1. Prefer the upstream payment-rail's stable identifier (Stripe PaymentIntent id, x402\n * tx hash) when one exists — those are already idempotent on their side.\n * 2. Fall back to a synthesized `pi-{orderId}-{amountCents}` key when no upstream id is\n * available (e.g. pre-creation, or rails without a PI concept).\n * 3. Server caps idempotency keys at 200 chars; this helper warns when that boundary is\n * crossed so a future caller doesn't silently get truncation collisions.\n */\n\nconst SERVER_IDEMPOTENCY_KEY_MAX = 200;\n\n/**\n * Compose a stable idempotency key for AgentScore wallet capture and other retry-safe POSTs.\n *\n * Returns `undefined` when no inputs are present (caller should treat as \"no idempotency\n * key — first attempt only\", same shape as omitting the field entirely).\n *\n * Examples:\n * ```ts\n * buildIdempotencyKey({ paymentIntentId: 'pi_abc' }); // → 'pi_abc'\n * buildIdempotencyKey({ orderId: 'ord_x', amountCents: 25000 }); // → 'pi-ord_x-25000'\n * buildIdempotencyKey({ orderId: 'ord_x' }); // → 'pi-ord_x'\n * buildIdempotencyKey({ paymentIntentId: 'pi_abc', prefix: 'refund' }); // → 'refund-pi_abc'\n * buildIdempotencyKey({}); // → undefined\n * ```\n */\nexport function buildIdempotencyKey({\n paymentIntentId,\n orderId,\n amountCents,\n prefix,\n}: {\n /** Upstream rail's stable payment id — Stripe PaymentIntent id, x402 tx hash, etc. Wins when present. */\n paymentIntentId?: string | null;\n /** Order id — used to compose a fallback key when no paymentIntentId exists. */\n orderId?: string | null;\n /** Amount in cents (or smallest currency unit) — added to the fallback for extra collision resistance. */\n amountCents?: number;\n /** Optional extra prefix to namespace the key (e.g. `\"refund\"`, `\"void\"`). */\n prefix?: string;\n}): string | undefined {\n const prefixPart = prefix ? `${prefix}-` : '';\n\n if (paymentIntentId) {\n const key = `${prefixPart}${paymentIntentId}`;\n return clampKey(key);\n }\n\n if (orderId) {\n const amountSuffix = amountCents !== undefined ? `-${amountCents}` : '';\n const key = `${prefixPart}pi-${orderId}${amountSuffix}`;\n return clampKey(key);\n }\n\n return undefined;\n}\n\nfunction clampKey(key: string): string {\n if (key.length <= SERVER_IDEMPOTENCY_KEY_MAX) return key;\n // Server truncates anyway; surfacing the warning here gives callers a chance to design\n // shorter inputs. We still return the original key (server-side truncation is the source\n // of truth) — clamping client-side would change semantics for any caller already\n // depending on the full string for their own dedup.\n console.warn(\n `[agentscore-commerce] idempotency key longer than ${SERVER_IDEMPOTENCY_KEY_MAX} chars — server will truncate, may cause silent collisions if multiple keys share the first ${SERVER_IDEMPOTENCY_KEY_MAX} chars.`,\n );\n return key;\n}\n","/**\n * Payment-signer extraction.\n *\n * Shared between merchants and the gate. Three paths recover a wallet signer:\n *\n * - **Tempo MPP** — `Authorization: Payment <base64>`; credential `source` is a DID of the\n * form `did:pkh:eip155:<chain>:<address>`.\n * - **Solana MPP `solana/charge`** — `Authorization: Payment <base64>`; recovery via either\n * a `did:pkh:solana:<genesis>:<address>` source (when set by the client) or by decoding\n * the credential's signed-tx payload and reading the SPL `TransferChecked` authority\n * (pull mode only — `payload.type === 'transaction'`).\n * - **x402 EIP-3009 (EVM, e.g. Base/Sepolia)** — `payment-signature` / `x-payment`;\n * decoded payload carries `payload.authorization.from`.\n *\n * Optional peer deps: `mppx` for MPP credentials, `@solana/kit` for the Solana tx-decode\n * fallback. Both dynamic-imported; merchants who don't accept that rail don't need them.\n */\n\nexport type SignerNetwork = 'evm' | 'solana';\n\nconst TOKEN_PROGRAM = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA';\nconst TOKEN_2022_PROGRAM = 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb';\nconst TRANSFER_CHECKED_DISCRIMINATOR = 12;\n\ninterface SolanaKitMinimal {\n getBase64Codec: () => { encode: (s: string) => Uint8Array };\n getTransactionDecoder: () => { decode: (b: Uint8Array) => { messageBytes: Uint8Array } };\n getCompiledTransactionMessageDecoder: () => {\n decode: (b: Uint8Array) => {\n staticAccounts: ReadonlyArray<string>;\n instructions: ReadonlyArray<{\n programAddressIndex: number;\n accountIndices?: number[];\n data?: Uint8Array;\n }>;\n };\n };\n}\n\n/**\n * Decode a Solana MPP `solana/charge` credential's `payload.transaction` (base64-encoded\n * signed Solana tx) and return the SPL `TransferChecked` authority — the source-ATA owner,\n * which is the buyer's wallet. Pull mode only (`payload.type === 'transaction'`); push mode\n * (`payload.type === 'signature'`) returns null because recovery would require an RPC fetch.\n */\nasync function extractSolanaSignerFromCredential(credential: unknown): Promise<string | null> {\n const payload = (credential as { payload?: { transaction?: string; type?: string } }).payload;\n if (!payload?.transaction || payload.type !== 'transaction') return null;\n\n const moduleName = '@solana/kit';\n const kit = (await import(moduleName).catch(() => null)) as SolanaKitMinimal | null;\n if (!kit?.getBase64Codec || !kit.getTransactionDecoder || !kit.getCompiledTransactionMessageDecoder) {\n return null;\n }\n\n try {\n const txBytes = kit.getBase64Codec().encode(payload.transaction);\n const decoded = kit.getTransactionDecoder().decode(txBytes);\n const message = kit.getCompiledTransactionMessageDecoder().decode(decoded.messageBytes);\n\n // SPL TransferChecked accounts: [source ATA, mint, destination ATA, authority, ...signers].\n // Returns the FIRST matched authority. For multi-recipient `splits` txs, the buyer\n // signs ONE tx with N TransferChecked instructions all sharing the same authority,\n // so first-match is correct; if a tx ever surfaces with mismatched authorities the\n // first one wins (acceptable since both belong to whoever signed the tx).\n for (const ix of message.instructions) {\n const programId = message.staticAccounts[ix.programAddressIndex];\n if (programId !== TOKEN_PROGRAM && programId !== TOKEN_2022_PROGRAM) continue;\n const data = ix.data;\n if (!data || data.length === 0 || data[0] !== TRANSFER_CHECKED_DISCRIMINATOR) continue;\n const accountIndices = ix.accountIndices ?? [];\n const authorityIndex = accountIndices[3];\n if (authorityIndex === undefined) continue;\n // v0 transactions can carry account indices that resolve via address lookup tables;\n // staticAccounts only holds the static set. If the index is out of range, the\n // authority sits in a lookup table we'd need RPC to resolve. Skip cleanly with a\n // warning rather than returning the wrong address.\n if (authorityIndex >= message.staticAccounts.length) {\n console.warn(\n '[gate] Solana TransferChecked authority resolves through an address lookup table; ' +\n 'signer-match recovery requires the static-account form. Skipping.',\n );\n continue;\n }\n const authority = message.staticAccounts[authorityIndex];\n if (authority) return authority;\n }\n return null;\n } catch (err) {\n console.warn('[gate] Solana credential decode failed:', err instanceof Error ? err.message : err);\n return null;\n }\n}\n\nexport interface PaymentSigner {\n /** Recovered wallet address (EVM lowercased; Solana base58 preserved verbatim). */\n address: string;\n /** Network family — used by `captureWallet` and downstream cross-chain attribution. */\n network: SignerNetwork;\n}\n\n/**\n * Recover the signer wallet from the incoming payment credential, including the network\n * family. Returns `null` when no wallet signature is present (e.g. Stripe SPT, card-only\n * payments, or no credential yet).\n *\n * @param request - the inbound `Request`\n * @param x402PaymentHeader - the value of `payment-signature` or `x-payment` header, if any.\n * Extracted separately because some frameworks (Express) don't expose a web `Request` object.\n */\nexport async function extractPaymentSigner(\n request: Request,\n x402PaymentHeader?: string,\n): Promise<PaymentSigner | null> {\n // MPP — Authorization: Payment <base64>\n const authHeader = request.headers.get('authorization');\n if (authHeader) {\n try {\n const moduleName = 'mppx';\n const mppx = (await import(moduleName).catch(() => null)) as {\n Credential?: {\n extractPaymentScheme: (h: string) => unknown;\n fromRequest: (r: Request) => unknown;\n };\n } | null;\n if (mppx?.Credential?.extractPaymentScheme(authHeader)) {\n const credential = mppx.Credential.fromRequest(request);\n const source = (credential as { source?: string }).source;\n const evmMatch = source?.match(/^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/);\n if (evmMatch) return { address: evmMatch[1]!.toLowerCase(), network: 'evm' };\n // Solana CAIP-10: did:pkh:solana:<genesis-base58>:<address-base58>\n const solMatch = source?.match(/^did:pkh:solana:[1-9A-HJ-NP-Za-km-z]{32,44}:([1-9A-HJ-NP-Za-km-z]{32,44})$/);\n if (solMatch) return { address: solMatch[1]!, network: 'solana' };\n // Fallback: source not set by upstream client. Decode the credential's signed-tx\n // payload to find the SPL TransferChecked authority (= source-ATA owner = buyer\n // wallet). Pull mode only.\n const solanaFromTx = await extractSolanaSignerFromCredential(credential);\n if (solanaFromTx) return { address: solanaFromTx, network: 'solana' };\n }\n } catch (err) {\n console.warn('[gate] MPP signer extraction failed:', err instanceof Error ? err.message : err);\n }\n }\n\n // x402 — base64 JSON, EIP-3009 only. EVM `payload.authorization.from` is the signer.\n if (x402PaymentHeader) {\n try {\n const decoded = atob(x402PaymentHeader);\n const parsed = JSON.parse(decoded) as {\n payload?: { authorization?: { from?: string } };\n };\n const from = parsed?.payload?.authorization?.from;\n if (typeof from === 'string' && /^0x[0-9a-fA-F]{40}$/.test(from)) {\n return { address: from.toLowerCase(), network: 'evm' };\n }\n } catch (err) {\n console.warn('[gate] x402 signer extraction failed:', err instanceof Error ? err.message : err);\n }\n }\n\n return null;\n}\n\n/**\n * Headers-only variant for adapters that don't natively expose a Web Fetch `Request`\n * (Express, Fastify, ASGI-bridged frameworks). Constructs a synthetic Request carrying\n * only the `authorization` header and delegates to {@link extractPaymentSigner}. Works\n * because the MPP and x402 paths only read `request.headers.get('authorization')` and\n * the explicit `x402PaymentHeader` arg — no body, query, or method semantics needed.\n */\nexport async function extractPaymentSignerFromAuth(\n authHeader: string | null | undefined,\n x402PaymentHeader?: string,\n): Promise<PaymentSigner | null> {\n const request = new Request('http://internal.gate/', {\n headers: authHeader ? { authorization: authHeader } : {},\n });\n return extractPaymentSigner(request, x402PaymentHeader);\n}\n\n/**\n * Read the x402 payment header from a `Request`, matching the alternate names merchants might\n * use. Falls back to reading either header directly.\n */\nexport function readX402PaymentHeader(request: Request): string | undefined {\n return (\n request.headers.get('payment-signature') ??\n request.headers.get('x-payment') ??\n undefined\n );\n}\n\nfunction lowerHeaders(headers: Record<string, string>): Record<string, string> {\n const out: Record<string, string> = {};\n for (const [k, v] of Object.entries(headers)) out[k.toLowerCase()] = v;\n return out;\n}\n\n/**\n * One-call signer extraction across both supported credential formats.\n *\n * Tries the x402 `payment-signature` / `x-payment` header first (EIP-3009\n * `payload.authorization.from`), then falls back to the MPP\n * `Authorization: Payment` header DID. Returns the first one that resolves,\n * or `null`.\n *\n * Use this for wallet-cap prechecks and other \"did the agent claim to sign as\n * X?\" checks where you need the signer BEFORE invoking Checkout. Checkout's\n * own settle path runs verification separately and surfaces the verified\n * signer on `SettleOutcome.signerAddress`.\n *\n * Accepts a plain headers dict so it works regardless of which framework the\n * merchant uses (the gate adapters all serialize headers down to a dict by\n * the time they reach the merchant's hooks).\n */\nexport async function extractSignerForPrecheck(\n headers: Record<string, string>,\n): Promise<PaymentSigner | null> {\n const lower = lowerHeaders(headers);\n const x402 = lower['payment-signature'] ?? lower['x-payment'];\n if (x402) {\n const signer = await extractPaymentSignerFromAuth(undefined, x402);\n if (signer !== null) return signer;\n }\n const authorization = lower['authorization'];\n if (authorization && authorization.toLowerCase().startsWith('payment ')) {\n return await extractPaymentSignerFromAuth(authorization);\n }\n return null;\n}\n","/**\n * x402 Settlement-Overrides header helpers — used with the `upto` scheme to specify the\n * actual amount to charge after the work is done. The header is JSON-encoded and lives\n * on the merchant's response; the facilitator settles for that amount instead of the\n * advertised maximum.\n *\n * Per the x402 docs (https://docs.x402.org/getting-started/quickstart-for-sellers), the\n * amount field accepts three formats:\n * - raw atomic units, e.g., '1000' for $0.001 USDC at 6 decimals\n * - percentage, e.g., '50%' of the authorized maximum\n * - dollar price, e.g., '$0.05' (converted to atomic via the network's default token)\n */\n\nexport const SETTLEMENT_OVERRIDES_HEADER = 'Settlement-Overrides';\n\nexport interface SettlementOverrides {\n /** Raw atomic units, '<n>%' percentage, or '$X.YZ' dollar price. */\n amount: string;\n}\n\n/**\n * Build a `{ name, value }` pair for the x402 Settlement-Overrides header. Vendors\n * set this on their response to direct the facilitator to settle for the actual amount\n * (used in the upto scheme flow):\n *\n * const { name, value } = settlementOverrideHeader({ amount: '1500' });\n * res.setHeader(name, value); // Express\n * c.header(name, value); // Hono\n */\nexport function settlementOverrideHeader(overrides: SettlementOverrides): { name: string; value: string } {\n return { name: SETTLEMENT_OVERRIDES_HEADER, value: JSON.stringify(overrides) };\n}\n","/**\n * USD ↔ atomic-unit conversion for token amounts.\n *\n * `usdToAtomic(usd, { decimals: 6 })` returns the bigint atomic value of a USD\n * amount for a token with `decimals` places of precision (USDC is 6). String\n * parsing + bigint arithmetic so the result is exact; ROUND_HALF_UP at the\n * rounding boundary matches the cross-language Python sibling.\n *\n * Rejects negative, NaN, infinite, and unparseable inputs. Fixed-notation only;\n * scientific notation (e.g. `\"1e6\"`) is not parsed (mirrors the locked cross-\n * language fixture corpus, which uses fixed notation exclusively).\n */\n\n/**\n * Convert a USD amount to atomic units for a token with `decimals` places.\n *\n * @param usd USD amount. Strings (`\"1.23\"`) and `number`s (`1.23`) are accepted.\n * `number` is converted via `String(usd)` before parsing, so JS float precision\n * limits apply when the float can't represent the value exactly.\n * @param opts.decimals Number of decimal places in the atomic unit (6 for USDC,\n * 18 for ETH, etc.). Must be a non-negative integer.\n *\n * @returns Integer atomic units as a `bigint`. `\"1.23\"` with `decimals: 6`\n * returns `1_230_000n`.\n *\n * @throws RangeError when `usd` is negative, NaN, infinite, or `decimals` is\n * not a non-negative integer.\n * @throws SyntaxError when `usd` cannot be parsed as a fixed-notation decimal.\n */\nexport function usdToAtomic(usd: string | number, opts: { decimals: number }): bigint {\n const { decimals } = opts;\n if (!Number.isInteger(decimals) || decimals < 0) {\n throw new RangeError(`decimals must be a non-negative integer, got ${decimals}`);\n }\n\n // Reject NaN / Infinity / negative on the typed-number path before stringifying,\n // so the error names the original numeric value rather than the stringified form.\n if (typeof usd === 'number') {\n if (!Number.isFinite(usd)) {\n throw new RangeError(`usd must be finite, got ${usd}`);\n }\n if (usd < 0) {\n throw new RangeError(`usd must be non-negative, got ${usd}`);\n }\n }\n\n const s = (typeof usd === 'number' ? usd.toString() : usd).trim();\n\n if (s.startsWith('-')) {\n throw new RangeError(`usd must be non-negative, got ${s}`);\n }\n if (s === 'NaN' || s === 'Infinity') {\n throw new RangeError(`usd must be finite, got ${s}`);\n }\n\n // Fixed notation only: optional digits, optional `.`, optional digits.\n // Reject empty, lone `.`, and anything containing non-digit/non-dot characters.\n const match = /^(\\d*)(?:\\.(\\d*))?$/.exec(s);\n if (!match || (match[1] === '' && (match[2] === undefined || match[2] === ''))) {\n throw new SyntaxError(`invalid usd value: ${JSON.stringify(usd)}`);\n }\n\n const intPart = match[1] || '0';\n const fracPart = match[2] ?? '';\n\n // Fractional shorter than (or equal to) decimals: pad with trailing zeros, return exact.\n if (fracPart.length <= decimals) {\n return BigInt(intPart + fracPart.padEnd(decimals, '0'));\n }\n\n // Fractional longer than decimals: truncate to `decimals` digits, then round-half-up\n // via the next-position digit. A digit ≥ '5' rounds the combined value up by 1;\n // matches Python's Decimal ROUND_HALF_UP semantics for non-negative inputs.\n const kept = fracPart.slice(0, decimals);\n const roundDigit = fracPart[decimals];\n let result = BigInt(intPart + kept);\n if (roundDigit >= '5') {\n result += 1n;\n }\n return result;\n}\n\n/**\n * Format an integer cent amount as a fixed-2-decimal USD string.\n *\n * `formatUsdCents(500)` returns `\"5.00\"`. Negative values are formatted with a\n * leading minus. Use everywhere a merchant emits `(cents / 100).toFixed(2)`;\n * consistent formatting across catalog rows, order responses, and 402 bodies\n * prevents agent-side string-comparison flakiness.\n */\nexport function formatUsdCents(cents: number): string {\n return (cents / 100).toFixed(2);\n}\n","/**\n * Zero-amount carve-out: skip upstream verify+settle for $0 orders.\n *\n * CDP rejects EIP-3009 `transferWithAuthorization` with `value=0` as\n * `invalid_payload`; `mppx`'s tempo intents accept only `hash` and\n * `transaction` payload types (rejecting the `proof` payload that gets\n * emitted for $0 settles). Both upstream verify+settle paths fail when the\n * authorized amount is zero, so merchants that drop the settle to $0 in a\n * redemption-code flow need a way to skip verify+settle entirely while\n * still recovering the signer for wallet-capture attribution.\n *\n * `zeroAmountCarveOut` is that path: parse the credential, lift the\n * signer, return `{ signerAddress, signerNetwork, txHash: null }`. Identity\n * is still authenticated by the merchant's gate above; the redemption code\n * is single-use; nothing on-chain to verify.\n *\n * The MPP path uses inline base64+JSON parsing (no `mppx` dependency at\n * runtime) so the cross-language byte-parity fixtures with the Python\n * sibling resolve to identical results. The full `extractPaymentSigner`\n * path is still mppx-backed for production traffic where the credential\n * is a real mppx-shaped object.\n */\n\nimport type { SignerNetwork } from '../signer';\n\nconst EVM_RE = /^0x[0-9a-fA-F]{40}$/;\nconst SOLANA_BASE58_RE = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;\n\nexport type ZeroSettleRail = 'x402-base' | 'tempo' | 'solana';\n\nexport interface ZeroSettleResult {\n /** Recovered signer address, or `null` when the credential is malformed\n * or shaped wrong for the requested rail. */\n signerAddress: string | null;\n /** `\"evm\"` or `\"solana\"`, matching the recovered signer's key family.\n * `null` when no signer was recoverable. */\n signerNetwork: SignerNetwork | null;\n /** Always `null`. A zero-amount carve-out skips on-chain settlement, so\n * no transaction hash exists. The field is present so callers can use\n * `ZeroSettleResult` interchangeably with the success path of\n * `processX402Settle` etc. without branching on shape. */\n txHash: null;\n}\n\nconst NULL_RESULT: ZeroSettleResult = {\n signerAddress: null,\n signerNetwork: null,\n txHash: null,\n};\n\n/**\n * Skip verify+settle for a zero-amount order; recover the signer from the credential.\n *\n * Returns a `ZeroSettleResult`. `signerAddress` / `signerNetwork` are `null`\n * when the credential is malformed, missing required fields, or shaped wrong\n * for the requested rail. `txHash` is always `null` since no on-chain settle runs.\n */\nexport function zeroAmountCarveOut({\n rail,\n payload,\n authorizationHeader,\n}: {\n rail: ZeroSettleRail;\n /** For `rail: 'x402-base'`: the verified x402 payload (decoded JSON\n * from `verifyX402Request(...).payload`). Reads\n * `payload.payload.authorization.from`. */\n payload?: Record<string, unknown> | null;\n /** For `rail: 'tempo'` / `'solana'`: the full `Authorization: Payment <base64>`\n * header value. Reads the `did:pkh:*` source DID. */\n authorizationHeader?: string | null;\n}): ZeroSettleResult {\n if (rail === 'x402-base') {\n return x402SignerFromPayload(payload);\n }\n if (rail === 'tempo' || rail === 'solana') {\n return mppSignerFromAuth(authorizationHeader);\n }\n return NULL_RESULT;\n}\n\nfunction x402SignerFromPayload(payload: Record<string, unknown> | null | undefined): ZeroSettleResult {\n if (!payload || typeof payload !== 'object') return NULL_RESULT;\n const inner = (payload as { payload?: unknown }).payload;\n if (!inner || typeof inner !== 'object') return NULL_RESULT;\n const authorization = (inner as { authorization?: unknown }).authorization;\n if (!authorization || typeof authorization !== 'object') return NULL_RESULT;\n const fromAddr = (authorization as { from?: unknown }).from;\n if (typeof fromAddr !== 'string' || !EVM_RE.test(fromAddr)) return NULL_RESULT;\n return {\n signerAddress: fromAddr.toLowerCase(),\n signerNetwork: 'evm',\n txHash: null,\n };\n}\n\nfunction mppSignerFromAuth(\n authorizationHeader: string | null | undefined,\n): ZeroSettleResult {\n if (typeof authorizationHeader !== 'string') return NULL_RESULT;\n if (!authorizationHeader.toLowerCase().startsWith('payment ')) return NULL_RESULT;\n const token = authorizationHeader.slice('payment '.length).trim();\n if (!token) return NULL_RESULT;\n\n let credential: unknown;\n try {\n credential = JSON.parse(atob(token));\n } catch {\n return NULL_RESULT;\n }\n if (!credential || typeof credential !== 'object') return NULL_RESULT;\n\n let source = (credential as { source?: unknown }).source;\n if (typeof source !== 'string') {\n const challenge = (credential as { challenge?: unknown }).challenge;\n if (challenge && typeof challenge === 'object') {\n source = (challenge as { source?: unknown }).source;\n }\n }\n if (typeof source !== 'string') return NULL_RESULT;\n\n const parts = source.split(':');\n if (parts.length < 4 || parts[0] !== 'did' || parts[1] !== 'pkh') return NULL_RESULT;\n const family = parts[2];\n const addr = parts[parts.length - 1] ?? '';\n\n if (family === 'eip155' && EVM_RE.test(addr)) {\n return { signerAddress: addr.toLowerCase(), signerNetwork: 'evm', txHash: null };\n }\n if (family === 'solana' && SOLANA_BASE58_RE.test(addr)) {\n return { signerAddress: addr, signerNetwork: 'solana', txHash: null };\n }\n return NULL_RESULT;\n}\n","/**\n * Lazy-init helpers for x402 + mppx servers.\n *\n * Every merchant accepting these rails writes the same singleton-with-lock\n * pattern around `createX402Server` / `createMppxServer`. These helpers collapse\n * the boilerplate to a single call; the returned getter is safe to call from\n * any number of concurrent handlers; only one server instance is ever\n * constructed per merchant.\n *\n * The x402 helper also derives the facilitator choice (`coinbase` vs `http`)\n * from optional CDP credentials so merchants don't repeat the boot-time\n * conditional.\n */\nimport { createMppxServer, type MppxRailSpec } from './mppx_server';\nimport { createX402Server, type X402Server, type X402SymbolicRail } from './x402_server';\nimport type { X402BaseRailSpec } from './rail_spec';\n\nfunction x402RailName(spec: X402BaseRailSpec): X402SymbolicRail {\n const network = spec.network ?? 'eip155:8453';\n if (network === 'eip155:8453') return 'x402-base-mainnet';\n if (network === 'eip155:84532') return 'x402-base-sepolia';\n throw new Error(\n `lazyX402Server: unsupported X402BaseRailSpec.network=${JSON.stringify(network)}`,\n );\n}\n\n/**\n * Build a memoized async getter for an x402 server.\n *\n * First call constructs the server; subsequent calls return the cached\n * instance. Concurrent first-callers serialize on a Promise lock so we never\n * construct two and discard one.\n *\n * When both CDP creds are passed, the server uses Coinbase's facilitator;\n * otherwise it falls back to the public HTTP facilitator. Merchants who only\n * have one of the two creds get the HTTP fallback.\n */\nexport function lazyX402Server(opts: {\n spec: X402BaseRailSpec;\n cdpApiKeyId?: string;\n cdpApiKeySecret?: string;\n}): () => Promise<X402Server> {\n const { spec, cdpApiKeyId, cdpApiKeySecret } = opts;\n const railName = x402RailName(spec);\n const useCdp = Boolean(cdpApiKeyId && cdpApiKeySecret);\n const facilitator: 'coinbase' | 'http' = useCdp ? 'coinbase' : 'http';\n\n let cached: X402Server | undefined;\n let pending: Promise<X402Server> | undefined;\n\n return async (): Promise<X402Server> => {\n if (cached !== undefined) return cached;\n if (pending !== undefined) return pending;\n pending = (async () => {\n const server = await createX402Server({ facilitator, rails: [railName] });\n cached = server;\n pending = undefined;\n return server;\n })();\n return pending;\n };\n}\n\n/**\n * Build a memoized async getter for an mppx server.\n *\n * Same singleton + lock semantics as {@link lazyX402Server}. Forwards `rails`\n * + `secretKey` unchanged to {@link createMppxServer}.\n */\nexport function lazyMppxServer(opts: {\n rails: Record<string, MppxRailSpec>;\n secretKey: string;\n}): () => Promise<unknown> {\n const { rails, secretKey } = opts;\n let cached: unknown;\n let pending: Promise<unknown> | undefined;\n\n return async (): Promise<unknown> => {\n if (cached !== undefined) return cached;\n if (pending !== undefined) return pending;\n pending = (async () => {\n const server = await createMppxServer({ secretKey, rails });\n cached = server;\n pending = undefined;\n return server;\n })();\n return pending;\n };\n}\n","/**\n * Solana MPP fee-payer signer loader.\n *\n * Buyers paying via Solana MPP USDC don't typically carry SOL for transaction\n * fees, so merchants commonly co-sign the buyer's `solana/charge` tx as the\n * fee payer (~5000 lamports per tx; negligible vs the USDC value moved).\n *\n * `loadSolanaFeePayer({ privateKey })` accepts a Solana keypair in any of the\n * three forms agents commonly export it as:\n *\n * - **base58** (Phantom export format) — 64-byte secret+public, or 32-byte\n * secret-only\n * - **hex** — 128-char string (64 bytes hex: 32-byte secret + 32-byte public)\n *\n * Returns a `KeyPairSigner` from `@solana/kit` ready to pass as the `signer`\n * field on a `SolanaMppRailSpec`. Returns `undefined` when `privateKey` is\n * empty / absent (so consumers can use `process.env.X` directly without\n * null-checks).\n *\n * Requires the `@solana/kit` peer dependency.\n */\nexport async function loadSolanaFeePayer(opts: {\n privateKey: string | undefined;\n}): Promise<unknown | undefined> {\n const raw = opts.privateKey;\n if (!raw) return undefined;\n const moduleName = '@solana/kit';\n const kit = (await import(moduleName).catch(() => null)) as {\n createKeyPairSignerFromPrivateKeyBytes?: (bytes: Uint8Array) => Promise<unknown>;\n getBase58Codec?: () => { encode: (s: string) => Uint8Array };\n } | null;\n if (!kit?.createKeyPairSignerFromPrivateKeyBytes || !kit.getBase58Codec) {\n throw new Error(\n '@solana/kit not installed — `npm install @solana/kit` for loadSolanaFeePayer.',\n );\n }\n let bytes: Uint8Array;\n if (/^[0-9a-fA-F]{128}$/.test(raw)) {\n bytes = new Uint8Array(raw.match(/.{2}/g)!.map((h) => parseInt(h, 16))).slice(0, 32);\n } else {\n const decoded = new Uint8Array(kit.getBase58Codec().encode(raw));\n bytes = decoded.length === 64 ? decoded.slice(0, 32) : decoded;\n }\n return kit.createKeyPairSignerFromPrivateKeyBytes(bytes);\n}\n"],"mappings":"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","names":["rails","dynamicImport","rails","rails"]}
|