@dexterai/x402 1.9.1 → 1.9.2
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/README.md +12 -0
- package/dist/server/index.cjs +125 -109
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +7 -6
- package/dist/server/index.d.ts +7 -6
- package/dist/server/index.js +125 -109
- package/dist/server/index.js.map +1 -1
- package/package.json +6 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/index.ts","../../src/types.ts","../../src/utils.ts","../../src/server/facilitator-client.ts","../../src/server/x402-server.ts","../../src/server/middleware.ts","../../src/server/browser-support.ts","../../src/server/access-pass.ts","../../src/server/dynamic-pricing.ts","../../src/server/token-pricing.ts","../../src/server/model-registry.ts","../../src/server/stripe-payto.ts"],"sourcesContent":["/**\n * @dexterai/x402 Server\n *\n * Server-side helpers for accepting x402 payments.\n * Works with any x402 v2 facilitator.\n *\n * @example Express Middleware (recommended)\n * ```typescript\n * import express from 'express';\n * import { x402Middleware } from '@dexterai/x402/server';\n *\n * const app = express();\n *\n * // One-liner payment protection\n * app.get('/api/protected',\n * x402Middleware({\n * payTo: 'YourSolanaAddress...',\n * amount: '0.01', // $0.01 USD\n * }),\n * (req, res) => {\n * // This only runs after successful payment\n * res.json({ data: 'protected content' });\n * }\n * );\n * ```\n *\n * @example Manual Server (advanced)\n * ```typescript\n * import { createX402Server } from '@dexterai/x402/server';\n *\n * const server = createX402Server({\n * payTo: 'YourSolanaAddress...',\n * network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n * });\n *\n * app.post('/protected', async (req, res) => {\n * const paymentSig = req.headers['payment-signature'];\n *\n * if (!paymentSig) {\n * const requirements = await server.buildRequirements({\n * amountAtomic: '50000',\n * resourceUrl: req.originalUrl,\n * });\n * res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));\n * return res.status(402).json({});\n * }\n *\n * const result = await server.settlePayment(paymentSig);\n * if (!result.success) {\n * return res.status(402).json({ error: result.errorReason });\n * }\n *\n * res.json({ data: 'protected content', transaction: result.transaction });\n * });\n * ```\n */\n\nexport { createX402Server } from './x402-server';\nexport type {\n X402ServerConfig,\n X402Server,\n BuildRequirementsOptions,\n AssetConfig,\n} from './x402-server';\n\n// Express middleware\nexport { x402Middleware } from './middleware';\nexport type { X402MiddlewareConfig, X402Request } from './middleware';\n\n// Browser support -- renders HTML paywall for browser 402 responses\nexport { x402BrowserSupport } from './browser-support';\nexport type { X402BrowserSupportConfig } from './browser-support';\n\n// Access pass middleware\nexport { x402AccessPass } from './access-pass';\nexport type { X402AccessPassConfig, X402AccessPassRequest } from './access-pass';\n\nexport { FacilitatorClient, type SupportedKind, type SupportedResponse } from './facilitator-client';\n\n// Dynamic pricing (character-based)\nexport { createDynamicPricing, formatPricing } from './dynamic-pricing';\nexport type { DynamicPricingConfig, DynamicPricing, PriceQuote } from './dynamic-pricing';\n\n// Token pricing (LLM-accurate with tiktoken)\nexport { \n createTokenPricing, \n countTokens, \n getAvailableModels, \n isValidModel, \n formatTokenPricing,\n MODEL_PRICING,\n} from './token-pricing';\nexport type { \n TokenPricingConfig, \n TokenPricing, \n TokenPriceQuote, \n ModelPricing,\n} from './token-pricing';\n\n// Model Registry - the single source of truth for all OpenAI models\nexport {\n MODEL_REGISTRY,\n MODEL_PRICING_MAP,\n getModel,\n findModel,\n isValidModelId,\n getAvailableModelIds,\n getModelsByTier,\n getModelsByFamily,\n getActiveModels,\n getTextModels,\n getCheapestModel,\n estimateCost,\n formatModelPricing,\n} from './model-registry';\nexport type {\n ModelTier,\n ModelModality,\n ModelApiType,\n ModelPricing as RegistryModelPricing,\n ModelParameters,\n ModelDefinition,\n} from './model-registry';\n\n// Stripe machine payments\nexport { stripePayTo } from './stripe-payto';\nexport type { StripePayToConfig } from './stripe-payto';\n\n// Sponsored Access (Ads for Agents) types — re-exported from @dexterai/x402-ads-types\nexport type {\n SponsoredRecommendation,\n SponsoredAccessSettlementInfo,\n SponsoredAccessPaymentRequiredInfo,\n SponsoredAccessClientConsent,\n} from '@dexterai/x402-ads-types';\nexport { SPONSORED_ACCESS_EXTENSION_KEY } from '@dexterai/x402-ads-types';\n\n// Re-export types for convenience\nexport type { VerifyResponse, SettleResponse, PaymentRequired, PaymentAccept, PayToContext, PayToProvider, PayToProviderDefaults, AccessPassTier, AccessPassInfo, AccessPassClaims, AccessPassClientConfig } from '../types';\nexport { DEXTER_FACILITATOR_URL, SOLANA_MAINNET_NETWORK, BASE_MAINNET_NETWORK, USDC_MINT, USDC_BASE } from '../types';\n","/**\n * x402 v2 SDK — Shared Types\n *\n * Chain-agnostic types for x402 v2 payments.\n * Works with Solana, Base, and any future x402-compatible networks.\n */\n\n// ============================================================================\n// Network Constants\n// ============================================================================\n\n/** CAIP-2 network identifier for Solana mainnet */\nexport const SOLANA_MAINNET_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n/** CAIP-2 network identifier for Base mainnet */\nexport const BASE_MAINNET_NETWORK = 'eip155:8453';\n\n/** Alias for Solana mainnet */\nexport const SOLANA_MAINNET = SOLANA_MAINNET_NETWORK;\n\n/** Alias for Base mainnet */\nexport const BASE_MAINNET = BASE_MAINNET_NETWORK;\n\n// ============================================================================\n// Asset Constants\n// ============================================================================\n\n/** USDC mint on Solana mainnet */\nexport const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n\n/** USDC address on Base mainnet */\nexport const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\n\n// ============================================================================\n// Facilitator Constants\n// ============================================================================\n\n/** Dexter's public x402 v2 facilitator URL */\nexport const DEXTER_FACILITATOR_URL = 'https://x402.dexter.cash';\n\n// ============================================================================\n// PayTo Provider Types (for dynamic address resolution, e.g. Stripe)\n// ============================================================================\n\n/**\n * Context passed to a PayToProvider function.\n * Contains request-scoped information for dynamic address resolution.\n */\nexport interface PayToContext {\n /** The PAYMENT-SIGNATURE header value (present on retry/verify, undefined on initial 402) */\n paymentHeader?: string;\n /** Amount in atomic units (e.g., '10000' for 0.01 USDC) */\n amountAtomic?: string;\n /** The resource URL being accessed */\n resourceUrl?: string;\n}\n\n/**\n * Optional defaults a PayToProvider can advertise for auto-configuration.\n * Attached as `_x402Defaults` on the provider function.\n */\nexport interface PayToProviderDefaults {\n /** Default CAIP-2 network (e.g., 'eip155:8453' for Base) */\n network?: string;\n /** Default facilitator URL */\n facilitatorUrl?: string;\n}\n\n/**\n * A function that dynamically resolves a payment address.\n * Used for providers like Stripe that generate per-request deposit addresses.\n *\n * @example\n * ```typescript\n * import { stripePayTo } from '@dexterai/x402/server';\n *\n * const provider = stripePayTo(process.env.STRIPE_SECRET_KEY);\n * const address = await provider({ amountAtomic: '10000' });\n * ```\n */\nexport type PayToProvider = ((context: PayToContext) => Promise<string>) & {\n /** Auto-configuration defaults (set by provider factories like stripePayTo) */\n _x402Defaults?: PayToProviderDefaults;\n};\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/**\n * Asset configuration for payments\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n /** Optional: Human-readable symbol */\n symbol?: string;\n}\n\n/**\n * Resource info included in payment requirements\n */\nexport interface ResourceInfo {\n /** Resource URL */\n url: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n}\n\n/**\n * Extra fields in payment requirements\n * Chain-specific fields may vary\n */\nexport interface AcceptsExtra {\n /** Facilitator address that pays tx fees (required for Solana) */\n feePayer?: string;\n /** Token decimals (optional - defaults to 6 for USDC) */\n decimals?: number;\n /** EIP-712: Token name (EVM only) */\n name?: string;\n /** EIP-712: Token version (EVM only) */\n version?: string;\n /** Additional chain-specific fields */\n [key: string]: unknown;\n}\n\n/**\n * A single payment option in the accepts array\n */\nexport interface PaymentAccept {\n /** x402 version (1 or 2, defaults to 2 if not specified) */\n x402Version?: 1 | 2;\n /** Payment scheme (always 'exact' for x402 v2) */\n scheme: 'exact';\n /** CAIP-2 network identifier (v1: 'solana', v2: 'solana:5eykt...') */\n network: string;\n /** Payment amount in atomic units (x402 v2 spec field) */\n amount: string;\n /** @deprecated v1 field — use `amount` instead. Kept for backwards compatibility with v1 data. */\n maxAmountRequired?: string;\n /** Token address */\n asset: string;\n /** Seller's address to receive payment */\n payTo: string;\n /** Maximum seconds until payment expires */\n maxTimeoutSeconds: number;\n /** Chain-specific extra data */\n extra?: AcceptsExtra;\n}\n\n/**\n * Full PaymentRequired structure (sent in PAYMENT-REQUIRED header)\n */\nexport interface PaymentRequired {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** Available payment options */\n accepts: PaymentAccept[];\n /** Optional error message */\n error?: string;\n /** Protocol extensions */\n extensions?: Record<string, unknown>;\n}\n\n/**\n * PaymentSignature structure (sent in PAYMENT-SIGNATURE header)\n */\nexport interface PaymentSignature {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** The payment option that was accepted */\n accepted: PaymentAccept;\n /** The signed payment */\n payload: {\n /** Signed transaction (base64 for Solana, JSON for EVM) */\n transaction: string;\n };\n /** Protocol extensions */\n extensions?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Facilitator Response Types\n// ============================================================================\n\n/**\n * Response from /verify endpoint\n */\nexport interface VerifyResponse {\n /** Whether the payment is valid */\n isValid: boolean;\n /** Reason for invalidity (if invalid) */\n invalidReason?: string;\n /** Payer address */\n payer?: string;\n}\n\n/**\n * Response from /settle endpoint\n */\nexport interface SettleResponse {\n /** Whether settlement succeeded */\n success: boolean;\n /** Transaction signature/hash */\n transaction?: string;\n /** Network the payment was made on */\n network: string;\n /** Error reason (if failed) */\n errorReason?: string;\n /** Error code (if failed) */\n errorCode?: string;\n /** Payer address */\n payer?: string;\n /** Protocol extensions returned by the facilitator (e.g., sponsored-access recommendations) */\n extensions?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Access Pass Types\n// ============================================================================\n\n/**\n * A single access pass tier offered by a seller\n */\nexport interface AccessPassTier {\n /** Tier ID (e.g., '1h', '24h') */\n id: string;\n /** Human-readable label (e.g., '1 hour') */\n label: string;\n /** Duration in seconds */\n seconds: number;\n /** Price in USD (e.g., '0.50') */\n price: string;\n /** Price in atomic units (e.g., '500000') */\n priceAtomic: string;\n}\n\n/**\n * Access pass info returned in X-ACCESS-PASS-TIERS header\n */\nexport interface AccessPassInfo {\n /** Available tiers (if tier-based pricing) */\n tiers?: AccessPassTier[];\n /** Rate per hour in USD (if custom duration pricing) */\n ratePerHour?: string;\n /** Pass issuer identifier */\n issuer?: string;\n}\n\n/**\n * JWT claims inside an access pass token\n */\nexport interface AccessPassClaims {\n /** Subject — always 'x402-access-pass' */\n sub: string;\n /** Tier ID or 'custom' */\n tier: string;\n /** Duration in seconds */\n duration: number;\n /** Issued at (unix seconds) */\n iat: number;\n /** Expires at (unix seconds) */\n exp: number;\n /** Payer wallet address */\n payer: string;\n /** Network used for payment */\n network: string;\n /** Issuer identifier */\n iss: string;\n}\n\n/**\n * Client-side access pass configuration\n */\nexport interface AccessPassClientConfig {\n /** Enable access pass mode (default: true when this config is present) */\n enabled?: boolean;\n /** Preferred tier ID (e.g., '1h') — pick this tier if available */\n preferTier?: string;\n /** Preferred custom duration in seconds (e.g., 3600) */\n preferDuration?: number;\n /** Maximum amount willing to spend in USD (e.g., '2.00') */\n maxSpend?: string;\n /** Auto-renew expired passes (default: true) */\n autoRenew?: boolean;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * SDK error codes\n */\nexport type X402ErrorCode =\n // Client errors\n | 'missing_payment_required_header'\n | 'invalid_payment_required'\n | 'unsupported_network'\n | 'no_matching_payment_option'\n | 'no_solana_accept' // Legacy, kept for compatibility\n | 'missing_fee_payer'\n | 'missing_decimals'\n | 'missing_amount'\n | 'amount_exceeds_max'\n | 'insufficient_balance'\n | 'wallet_missing_sign_transaction'\n | 'wallet_not_connected'\n | 'transaction_build_failed'\n | 'payment_rejected'\n // Server errors\n | 'invalid_payment_signature'\n | 'facilitator_verify_failed'\n | 'facilitator_settle_failed'\n | 'facilitator_request_failed'\n | 'no_matching_requirement'\n // Access pass errors\n | 'access_pass_expired'\n | 'access_pass_invalid'\n | 'access_pass_tier_not_found'\n | 'access_pass_exceeds_max_spend';\n\n/**\n * Custom error class for x402 operations\n */\nexport class X402Error extends Error {\n /** Error code for programmatic handling */\n code: X402ErrorCode;\n /** Additional error details */\n details?: unknown;\n\n constructor(code: X402ErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, X402Error.prototype);\n }\n}\n","/**\n * Utility Functions\n *\n * Chain-agnostic helpers for x402 payments.\n */\n\nimport { SOLANA_MAINNET_NETWORK, BASE_MAINNET_NETWORK } from './types';\n\n// ============================================================================\n// Amount Conversion\n// ============================================================================\n\n/**\n * Convert human-readable amount to atomic units\n *\n * @param amount - Human-readable amount (e.g., 0.05 for $0.05)\n * @param decimals - Token decimals (e.g., 6 for USDC)\n * @returns Amount in atomic units as string\n *\n * @example\n * ```typescript\n * toAtomicUnits(0.05, 6) // '50000'\n * toAtomicUnits(1.50, 6) // '1500000'\n * ```\n */\nexport function toAtomicUnits(amount: number, decimals: number): string {\n const multiplier = Math.pow(10, decimals);\n return Math.floor(amount * multiplier).toString();\n}\n\n/**\n * Convert atomic units to human-readable amount\n *\n * @param atomicUnits - Amount in smallest units\n * @param decimals - Token decimals\n * @returns Human-readable amount\n *\n * @example\n * ```typescript\n * fromAtomicUnits('50000', 6) // 0.05\n * fromAtomicUnits(1500000n, 6) // 1.5\n * ```\n */\nexport function fromAtomicUnits(\n atomicUnits: string | bigint | number,\n decimals: number\n): number {\n const divisor = Math.pow(10, decimals);\n return Number(atomicUnits) / divisor;\n}\n\n// ============================================================================\n// Network Helpers\n// ============================================================================\n\n/**\n * Network type\n */\nexport type ChainFamily = 'solana' | 'evm' | 'unknown';\n\n/**\n * Get the chain family from a CAIP-2 network identifier\n *\n * @param network - CAIP-2 network identifier\n * @returns Chain family\n *\n * @example\n * ```typescript\n * getChainFamily('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp') // 'solana'\n * getChainFamily('eip155:8453') // 'evm'\n * ```\n */\nexport function getChainFamily(network: string): ChainFamily {\n if (network.startsWith('solana:') || network === 'solana') {\n return 'solana';\n }\n if (network.startsWith('eip155:') || ['base', 'ethereum', 'arbitrum'].includes(network)) {\n return 'evm';\n }\n return 'unknown';\n}\n\n/**\n * Get default RPC URL for a network\n *\n * @param network - CAIP-2 network identifier\n * @returns Default RPC URL\n */\nexport function getDefaultRpcUrl(network: string): string {\n const family = getChainFamily(network);\n\n if (family === 'solana') {\n if (network.includes('devnet') || network === 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1') {\n return 'https://api.devnet.solana.com';\n }\n if (network.includes('testnet') || network === 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z') {\n return 'https://api.testnet.solana.com';\n }\n // Mainnet uses Dexter's RPC proxy\n return 'https://api.dexter.cash/api/solana/rpc';\n }\n\n if (family === 'evm') {\n // Extract chain ID from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainId = network.split(':')[1];\n switch (chainId) {\n case '8453': return 'https://api.dexter.cash/api/base/rpc'; // Dexter proxy\n case '84532': return 'https://sepolia.base.org';\n case '1': return 'https://eth.llamarpc.com';\n case '42161': return 'https://arb1.arbitrum.io/rpc';\n default: return 'https://api.dexter.cash/api/base/rpc';\n }\n }\n // Legacy names\n if (network === 'base') return 'https://api.dexter.cash/api/base/rpc';\n if (network === 'ethereum') return 'https://eth.llamarpc.com';\n if (network === 'arbitrum') return 'https://arb1.arbitrum.io/rpc';\n return 'https://api.dexter.cash/api/base/rpc';\n }\n\n // Unknown - return Dexter's Solana proxy\n return 'https://api.dexter.cash/api/solana/rpc';\n}\n\n/**\n * Get human-readable chain name\n *\n * @param network - CAIP-2 network identifier\n * @returns Human-readable name\n */\nexport function getChainName(network: string): string {\n const mapping: Record<string, string> = {\n [SOLANA_MAINNET_NETWORK]: 'Solana',\n 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1': 'Solana Devnet',\n 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z': 'Solana Testnet',\n 'solana': 'Solana',\n [BASE_MAINNET_NETWORK]: 'Base',\n 'eip155:84532': 'Base Sepolia',\n 'eip155:1': 'Ethereum',\n 'eip155:42161': 'Arbitrum One',\n 'base': 'Base',\n 'ethereum': 'Ethereum',\n 'arbitrum': 'Arbitrum',\n };\n return mapping[network] || network;\n}\n\n// ============================================================================\n// Transaction URL Helpers\n// ============================================================================\n\n/**\n * Get explorer URL for a transaction\n *\n * @param txSignature - Transaction signature/hash\n * @param network - CAIP-2 network identifier\n * @returns Explorer URL\n */\nexport function getExplorerUrl(txSignature: string, network: string): string {\n const family = getChainFamily(network);\n\n if (family === 'solana') {\n const isDevnet = network.includes('devnet') || network === 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\n if (isDevnet) {\n return `https://solscan.io/tx/${txSignature}?cluster=devnet`;\n }\n // Prefer Orb Markets for mainnet\n return `https://www.orbmarkets.io/tx/${txSignature}`;\n }\n\n if (family === 'evm') {\n // Extract chain ID\n let chainId = '8453'; // Default to Base\n if (network.startsWith('eip155:')) {\n chainId = network.split(':')[1];\n } else if (network === 'ethereum') {\n chainId = '1';\n } else if (network === 'arbitrum') {\n chainId = '42161';\n }\n\n switch (chainId) {\n case '8453': return `https://basescan.org/tx/${txSignature}`;\n case '84532': return `https://sepolia.basescan.org/tx/${txSignature}`;\n case '1': return `https://etherscan.io/tx/${txSignature}`;\n case '42161': return `https://arbiscan.io/tx/${txSignature}`;\n default: return `https://basescan.org/tx/${txSignature}`;\n }\n }\n\n return `https://solscan.io/tx/${txSignature}`;\n}\n\n// ============================================================================\n// Encoding Helpers\n// ============================================================================\n\n/**\n * Unicode-safe base64 encode a string.\n * Works in both Node.js and browsers, handling characters above U+00FF\n * that would cause btoa() to throw InvalidCharacterError.\n */\nfunction safeBase64Encode(str: string): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(str, 'utf-8').toString('base64');\n }\n // Browser fallback: encode UTF-8 bytes via TextEncoder\n const bytes = new TextEncoder().encode(str);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Unicode-safe base64 decode a string.\n * Works in both Node.js and browsers.\n */\nfunction safeBase64Decode(encoded: string): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(encoded, 'base64').toString('utf-8');\n }\n // Browser fallback: decode via atob then UTF-8\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n\n/**\n * Encode an object as base64 JSON (Unicode-safe)\n */\nexport function encodeBase64Json(obj: unknown): string {\n return safeBase64Encode(JSON.stringify(obj));\n}\n\n/**\n * Decode base64 JSON to object (Unicode-safe)\n */\nexport function decodeBase64Json<T>(encoded: string): T {\n return JSON.parse(safeBase64Decode(encoded)) as T;\n}\n","/**\n * Facilitator Client\n *\n * Communicates with the x402 facilitator for:\n * - /supported - Get supported payment schemes and fee payer addresses\n * - /verify - Verify a payment signature before processing\n * - /settle - Submit the payment for execution\n *\n * Includes retry with exponential backoff and request timeouts.\n * Works with any x402 v2 facilitator (Dexter or others).\n */\n\nimport type { PaymentAccept, PaymentSignature, VerifyResponse, SettleResponse } from '../types';\nimport { DEXTER_FACILITATOR_URL } from '../types';\nimport { decodeBase64Json } from '../utils';\n\n/**\n * Supported payment kind from facilitator /supported endpoint\n */\nexport interface SupportedKind {\n x402Version: number;\n scheme: string;\n network: string;\n extra?: {\n feePayer?: string;\n decimals?: number;\n name?: string;\n version?: string;\n [key: string]: unknown;\n };\n}\n\n/**\n * Response from facilitator /supported endpoint\n */\nexport interface SupportedResponse {\n kinds: SupportedKind[];\n extensions?: string[];\n signers?: Record<string, string[]>;\n}\n\n/**\n * Configuration for retry and timeout behavior\n */\nexport interface FacilitatorClientConfig {\n /** Request timeout in milliseconds @default 10000 */\n timeoutMs?: number;\n /** Maximum retry attempts for verify/settle @default 3 */\n maxRetries?: number;\n /** Base delay between retries in milliseconds (doubles each attempt) @default 500 */\n retryBaseMs?: number;\n}\n\n// Retryable: network errors and 5xx responses\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof TypeError) return true; // fetch network errors\n if (error && typeof error === 'object' && 'status' in error) {\n const status = (error as { status: number }).status;\n return status >= 500 && status < 600;\n }\n return false;\n}\n\nclass HttpError extends Error {\n status: number;\n body: string;\n constructor(status: number, body: string) {\n super(`HTTP ${status}`);\n this.status = status;\n this.body = body;\n }\n}\n\n/**\n * Client for communicating with an x402 v2 facilitator\n */\nexport class FacilitatorClient {\n private facilitatorUrl: string;\n private cachedSupported: SupportedResponse | null = null;\n private cacheTime: number = 0;\n private readonly CACHE_TTL_MS = 60_000;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly retryBaseMs: number;\n\n constructor(\n facilitatorUrl: string = DEXTER_FACILITATOR_URL,\n config?: FacilitatorClientConfig,\n ) {\n this.facilitatorUrl = facilitatorUrl.replace(/\\/$/, '');\n this.timeoutMs = config?.timeoutMs ?? 10_000;\n this.maxRetries = config?.maxRetries ?? 3;\n this.retryBaseMs = config?.retryBaseMs ?? 500;\n }\n\n private async fetchWithTimeout(\n url: string,\n init?: RequestInit,\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init?: RequestInit,\n ): Promise<Response> {\n let lastError: unknown;\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\n try {\n const response = await this.fetchWithTimeout(url, init);\n if (!response.ok && response.status >= 500) {\n throw new HttpError(response.status, await response.text());\n }\n return response;\n } catch (error) {\n lastError = error;\n if (attempt < this.maxRetries - 1 && isRetryable(error)) {\n const delay = this.retryBaseMs * Math.pow(2, attempt);\n await new Promise(r => setTimeout(r, delay));\n continue;\n }\n throw error;\n }\n }\n throw lastError;\n }\n\n /**\n * Get supported payment kinds from the facilitator.\n * Results are cached for 1 minute to reduce network calls.\n */\n async getSupported(): Promise<SupportedResponse> {\n const now = Date.now();\n if (this.cachedSupported && now - this.cacheTime < this.CACHE_TTL_MS) {\n return this.cachedSupported;\n }\n\n const response = await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);\n if (!response.ok) {\n throw new Error(`Facilitator /supported returned ${response.status}`);\n }\n\n this.cachedSupported = (await response.json()) as SupportedResponse;\n this.cacheTime = now;\n return this.cachedSupported;\n }\n\n /**\n * Get the fee payer address for a specific network\n */\n async getFeePayer(network: string): Promise<string | undefined> {\n const supported = await this.getSupported();\n const kind = supported.kinds.find(\n (k) => k.x402Version === 2 && k.scheme === 'exact' && k.network === network,\n );\n\n if (!kind) {\n throw new Error(\n `Facilitator does not support network \"${network}\" with scheme \"exact\"`,\n );\n }\n\n return kind.extra?.feePayer;\n }\n\n /**\n * Get extra data for a network (feePayer, decimals, EIP-712 data, etc.)\n */\n async getNetworkExtra(network: string): Promise<SupportedKind['extra']> {\n const supported = await this.getSupported();\n const kind = supported.kinds.find(\n (k) => k.x402Version === 2 && k.scheme === 'exact' && k.network === network,\n );\n return kind?.extra;\n }\n\n /**\n * Verify a payment with the facilitator.\n * Retries on 5xx and network errors with exponential backoff.\n */\n async verifyPayment(\n paymentSignatureHeader: string,\n requirements: PaymentAccept,\n ): Promise<VerifyResponse> {\n try {\n const paymentPayload = decodeBase64Json<PaymentSignature>(paymentSignatureHeader);\n\n const response = await this.fetchWithRetry(`${this.facilitatorUrl}/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n x402Version: 2,\n paymentPayload,\n paymentRequirements: requirements,\n }),\n });\n\n if (!response.ok) {\n return {\n isValid: false,\n invalidReason: `facilitator_error_${response.status}`,\n };\n }\n\n return (await response.json()) as VerifyResponse;\n } catch (error) {\n const reason = error instanceof HttpError\n ? `facilitator_error_${error.status}`\n : error instanceof Error && error.name === 'AbortError'\n ? 'facilitator_timeout'\n : error instanceof Error\n ? error.message\n : 'unexpected_verify_error';\n\n return { isValid: false, invalidReason: reason };\n }\n }\n\n /**\n * Settle a payment with the facilitator.\n * Retries on 5xx and network errors with exponential backoff.\n */\n async settlePayment(\n paymentSignatureHeader: string,\n requirements: PaymentAccept,\n ): Promise<SettleResponse> {\n try {\n const paymentPayload = decodeBase64Json<PaymentSignature>(paymentSignatureHeader);\n\n const response = await this.fetchWithRetry(`${this.facilitatorUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n x402Version: 2,\n paymentPayload,\n paymentRequirements: requirements,\n }),\n });\n\n if (!response.ok) {\n return {\n success: false,\n network: requirements.network,\n errorReason: `facilitator_error_${response.status}`,\n };\n }\n\n const result = (await response.json()) as SettleResponse;\n return { ...result, network: requirements.network };\n } catch (error) {\n const reason = error instanceof HttpError\n ? `facilitator_error_${error.status}`\n : error instanceof Error && error.name === 'AbortError'\n ? 'facilitator_timeout'\n : error instanceof Error\n ? error.message\n : 'unexpected_settle_error';\n\n return {\n success: false,\n network: requirements.network,\n errorReason: reason,\n };\n }\n }\n}\n","/**\n * x402 v2 Server\n *\n * Server-side helpers for accepting x402 payments.\n * Chain-agnostic - works with Solana, Base, and any x402-compatible network.\n *\n * @example\n * ```typescript\n * import { createX402Server } from '@dexterai/x402/server';\n *\n * const server = createX402Server({\n * payTo: 'YourAddress...',\n * network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n * });\n *\n * // Handle 402 responses\n * if (!paymentSignature) {\n * const requirements = await server.buildRequirements({\n * amountAtomic: '50000',\n * resourceUrl: '/api/protected',\n * });\n * res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));\n * res.status(402).json({});\n * return;\n * }\n *\n * // Verify and settle\n * const verify = await server.verifyPayment(paymentSignature);\n * if (!verify.isValid) throw new Error(verify.invalidReason);\n *\n * const settle = await server.settlePayment(paymentSignature);\n * if (!settle.success) throw new Error(settle.errorReason);\n *\n * // Payment successful!\n * res.json({ transaction: settle.transaction });\n * ```\n */\n\nimport type {\n PaymentRequired,\n PaymentAccept,\n ResourceInfo,\n AcceptsExtra,\n VerifyResponse,\n SettleResponse,\n PayToContext,\n PayToProvider,\n} from '../types';\nimport {\n SOLANA_MAINNET_NETWORK,\n USDC_MINT,\n DEXTER_FACILITATOR_URL,\n} from '../types';\nimport { FacilitatorClient, type SupportedKind } from './facilitator-client';\nimport { encodeBase64Json, decodeBase64Json } from '../utils';\n\n/**\n * Best-effort extraction of amount from a PAYMENT-SIGNATURE header.\n * Used as a fallback when the requirements cache misses (e.g., server restart\n * between initial 402 and retry). Returns the accepted amount or undefined.\n */\nfunction extractAmountFromHeader(paymentSignatureHeader: string): string | undefined {\n try {\n const decoded = decodeBase64Json<{\n accepted?: { amount?: string; maxAmountRequired?: string };\n }>(paymentSignatureHeader);\n return decoded?.accepted?.amount ?? decoded?.accepted?.maxAmountRequired;\n } catch {\n return undefined;\n }\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Asset configuration\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n}\n\n/**\n * Server configuration\n */\nexport interface X402ServerConfig {\n /**\n * Address to receive payments, or a dynamic provider function.\n * Use a string for static wallet addresses.\n * Use a PayToProvider (e.g., stripePayTo) for per-request addresses.\n */\n payTo: string | PayToProvider;\n /** Facilitator URL (defaults to Dexter) */\n facilitatorUrl?: string;\n /** CAIP-2 network identifier */\n network?: string;\n /** Asset configuration (defaults to USDC) */\n asset?: AssetConfig;\n /** Default payment timeout in seconds */\n defaultTimeoutSeconds?: number;\n}\n\n/**\n * Options for building payment requirements\n */\nexport interface BuildRequirementsOptions {\n /** Amount in atomic units (e.g., '50000' for 0.05 USDC) */\n amountAtomic: string;\n /** Full URL of the resource */\n resourceUrl: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the response */\n mimeType?: string;\n /** Override timeout for this request */\n timeoutSeconds?: number;\n}\n\n/**\n * x402 Server interface\n */\nexport interface X402Server {\n /** Build payment requirements (fetches feePayer from facilitator) */\n buildRequirements(options: BuildRequirementsOptions): Promise<PaymentRequired>;\n\n /** Encode requirements for PAYMENT-REQUIRED header */\n encodeRequirements(requirements: PaymentRequired): string;\n\n /** Create complete 402 response object */\n create402Response(requirements: PaymentRequired): {\n status: 402;\n headers: { 'PAYMENT-REQUIRED': string };\n body: Record<string, unknown>;\n };\n\n /** Verify payment with facilitator */\n verifyPayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<VerifyResponse>;\n\n /** Settle payment via facilitator */\n settlePayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<SettleResponse>;\n\n /** Get PaymentAccept for verify/settle */\n getPaymentAccept(options: BuildRequirementsOptions): Promise<PaymentAccept>;\n\n /** Get network this server is configured for */\n readonly network: string;\n\n /** Get facilitator client for advanced usage */\n readonly facilitator: FacilitatorClient;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Create an x402 server for accepting payments\n */\nexport function createX402Server(config: X402ServerConfig): X402Server {\n const {\n payTo,\n facilitatorUrl = DEXTER_FACILITATOR_URL,\n network = SOLANA_MAINNET_NETWORK,\n asset = { address: USDC_MINT, decimals: 6 },\n defaultTimeoutSeconds = 60,\n } = config;\n\n const facilitator = new FacilitatorClient(facilitatorUrl);\n\n // Cache for network extra data\n let cachedExtra: SupportedKind['extra'] | null = null;\n\n // Requirements cache: payTo address -> PaymentAccept + expiry.\n // Populated by buildRequirements/getPaymentAccept, consumed by verify/settle.\n // Prevents the bug where verify/settle fabricates requirements with amount '0'.\n // Parallels the SettlementCache pattern from coinbase/x402.\n const requirementsCache = new Map<string, { accept: PaymentAccept; expiresAt: number }>();\n const CACHE_PRUNE_INTERVAL = 30_000;\n let lastPrune = Date.now();\n\n function cacheRequirements(accept: PaymentAccept): void {\n const ttl = (accept.maxTimeoutSeconds || defaultTimeoutSeconds) * 1000;\n requirementsCache.set(accept.payTo, { accept, expiresAt: Date.now() + ttl });\n\n if (Date.now() - lastPrune > CACHE_PRUNE_INTERVAL) {\n const now = Date.now();\n for (const [key, entry] of requirementsCache) {\n if (entry.expiresAt < now) requirementsCache.delete(key);\n }\n lastPrune = now;\n }\n }\n\n function getCachedRequirements(address: string): PaymentAccept | undefined {\n const entry = requirementsCache.get(address);\n if (!entry) return undefined;\n if (entry.expiresAt < Date.now()) {\n requirementsCache.delete(address);\n return undefined;\n }\n return entry.accept;\n }\n\n /**\n * Resolve payTo to a concrete address.\n * For static strings, returns immediately.\n * For providers (e.g. Stripe), calls the function with context.\n */\n async function resolvePayTo(context?: PayToContext): Promise<string> {\n if (typeof payTo === 'string') return payTo;\n return payTo(context || {});\n }\n\n /**\n * Get extra data from facilitator (cached)\n */\n async function getNetworkExtra(): Promise<AcceptsExtra> {\n if (!cachedExtra) {\n cachedExtra = await facilitator.getNetworkExtra(network);\n }\n\n const isSvm = network.startsWith('solana:');\n\n if (isSvm && !cachedExtra?.feePayer) {\n throw new Error(`Facilitator does not provide feePayer for network \"${network}\"`);\n }\n\n return {\n ...(cachedExtra?.feePayer ? { feePayer: cachedExtra.feePayer } : {}),\n decimals: cachedExtra?.decimals ?? asset.decimals,\n name: cachedExtra?.name,\n version: cachedExtra?.version,\n };\n }\n\n /**\n * Build a PaymentAccept with a pre-resolved address (internal helper)\n */\n async function buildPaymentAccept(\n resolvedPayTo: string,\n options: BuildRequirementsOptions,\n ): Promise<PaymentAccept> {\n const {\n amountAtomic,\n timeoutSeconds = defaultTimeoutSeconds,\n } = options;\n\n const extra = await getNetworkExtra();\n\n const accept: PaymentAccept = {\n scheme: 'exact',\n network,\n amount: amountAtomic,\n maxAmountRequired: amountAtomic,\n asset: asset.address,\n payTo: resolvedPayTo,\n maxTimeoutSeconds: timeoutSeconds,\n extra,\n };\n\n cacheRequirements(accept);\n return accept;\n }\n\n /**\n * Build a PaymentAccept structure (resolves payTo dynamically)\n */\n async function getPaymentAccept(options: BuildRequirementsOptions): Promise<PaymentAccept> {\n const address = await resolvePayTo({\n amountAtomic: options.amountAtomic,\n resourceUrl: options.resourceUrl,\n });\n return buildPaymentAccept(address, options);\n }\n\n /**\n * Build payment requirements for a 402 response\n */\n async function buildRequirements(options: BuildRequirementsOptions): Promise<PaymentRequired> {\n const {\n resourceUrl,\n description,\n mimeType = 'application/json',\n } = options;\n\n const resource: ResourceInfo = {\n url: resourceUrl,\n description,\n mimeType,\n };\n\n const accept = await getPaymentAccept(options);\n\n return {\n x402Version: 2,\n resource,\n accepts: [accept],\n error: 'Payment required',\n };\n }\n\n /**\n * Encode requirements for PAYMENT-REQUIRED header\n */\n function encodeRequirements(requirements: PaymentRequired): string {\n return encodeBase64Json(requirements);\n }\n\n /**\n * Create complete 402 response object\n */\n function create402Response(requirements: PaymentRequired) {\n return {\n status: 402 as const,\n headers: {\n 'PAYMENT-REQUIRED': encodeRequirements(requirements),\n },\n body: {},\n };\n }\n\n /**\n * Verify payment with facilitator.\n * Resolves requirements from cache (populated by buildRequirements),\n * falling back to the payment header for the payTo address.\n */\n async function verifyPayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<VerifyResponse> {\n if (!requirements) {\n const address = await resolvePayTo({ paymentHeader: paymentSignatureHeader });\n requirements = getCachedRequirements(address);\n if (!requirements) {\n // Fallback: rebuild with amount from payment header if possible\n requirements = await buildPaymentAccept(address, {\n amountAtomic: extractAmountFromHeader(paymentSignatureHeader) ?? '0',\n resourceUrl: '',\n });\n }\n }\n\n return facilitator.verifyPayment(paymentSignatureHeader, requirements);\n }\n\n /**\n * Settle payment via facilitator.\n * Resolves requirements from cache (populated by buildRequirements),\n * falling back to the payment header for the payTo address.\n */\n async function settlePayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<SettleResponse> {\n if (!requirements) {\n const address = await resolvePayTo({ paymentHeader: paymentSignatureHeader });\n requirements = getCachedRequirements(address);\n if (!requirements) {\n requirements = await buildPaymentAccept(address, {\n amountAtomic: extractAmountFromHeader(paymentSignatureHeader) ?? '0',\n resourceUrl: '',\n });\n }\n }\n\n return facilitator.settlePayment(paymentSignatureHeader, requirements);\n }\n\n return {\n buildRequirements,\n encodeRequirements,\n create402Response,\n verifyPayment,\n settlePayment,\n getPaymentAccept,\n network,\n facilitator,\n };\n}\n","/**\n * Express Middleware for x402 Payments\n *\n * One-liner middleware to protect any Express endpoint with x402 payments.\n * Handles the entire flow: 402 response, payment verification, settlement.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { x402Middleware } from '@dexterai/x402/server';\n *\n * const app = express();\n *\n * app.get('/api/protected',\n * x402Middleware({\n * payTo: 'YourSolanaAddress...',\n * amount: '0.01', // $0.01 USD\n * network: 'solana:mainnet',\n * }),\n * (req, res) => {\n * // This only runs after successful payment\n * res.json({ data: 'protected content' });\n * }\n * );\n * ```\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport type { PayToProvider } from '../types';\nimport { createX402Server, type BuildRequirementsOptions } from './x402-server';\nimport { toAtomicUnits, encodeBase64Json } from '../utils';\nimport type { SponsoredRecommendation } from '@dexterai/x402-ads-types';\n\n/**\n * Middleware configuration\n */\nexport interface X402MiddlewareConfig {\n /**\n * Address to receive payments, or a dynamic provider function, or\n * a map of network-specific addresses for multi-chain support.\n *\n * - **Static address**: Pass a Solana pubkey or EVM address string.\n * - **Stripe**: Use `stripePayTo(process.env.STRIPE_SECRET_KEY)` for Base.\n * - **Multi-chain map**: Keys are CAIP-2 networks or globs (`eip155:*`, `*`).\n *\n * @example\n * ```typescript\n * // Single address (works on one network)\n * payTo: '0xYourAddress...'\n *\n * // Stripe on Base, direct wallet on other chains\n * payTo: { 'eip155:8453': stripePayTo(key), '*': '0xYourAddress...' }\n *\n * // Solana + EVM\n * payTo: { 'solana:*': 'SolAddr', 'eip155:*': '0xEvmAddr' }\n * ```\n */\n payTo: string | PayToProvider | Record<string, string | PayToProvider>;\n\n /**\n * Payment amount in USD (e.g., '0.01' for 1 cent)\n * Will be converted to atomic units automatically.\n */\n amount: string;\n\n /**\n * CAIP-2 network identifier(s).\n * Pass an array to accept payments on multiple chains simultaneously.\n * The client picks whichever chain it has a wallet for.\n *\n * @default 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' (Solana mainnet)\n *\n * @example\n * ```typescript\n * // Single network\n * network: 'eip155:8453'\n *\n * // Multiple EVM chains (same payTo address works for all)\n * network: ['eip155:8453', 'eip155:137', 'eip155:42161']\n * ```\n */\n network?: string | string[];\n\n /**\n * Asset to accept\n * @default USDC on the specified network\n */\n asset?: {\n address: string;\n decimals: number;\n };\n\n /**\n * x402 facilitator URL\n * @default 'https://x402.dexter.cash'\n */\n facilitatorUrl?: string;\n\n /**\n * Resource description (shown to users)\n */\n description?: string;\n\n /**\n * Resource URL override\n * By default, uses the full request URL\n */\n resourceUrl?: string;\n\n /**\n * MIME type of the response\n */\n mimeType?: string;\n\n /**\n * Payment timeout in seconds\n * @default 120\n */\n timeoutSeconds?: number;\n\n /**\n * Enable verbose logging\n */\n verbose?: boolean;\n\n /**\n * Custom function to get resource URL from request\n * Useful for dynamic routing\n */\n getResourceUrl?: (req: Request) => string;\n\n /**\n * Custom function to get amount from request\n * Useful for dynamic pricing based on request body/params\n */\n getAmount?: (req: Request) => string;\n\n /**\n * Custom function to get description from request\n */\n getDescription?: (req: Request) => string;\n\n /**\n * Enable sponsored-access recommendation delivery.\n *\n * When true, the middleware reads `extensions[\"sponsored-access\"]` from the\n * facilitator's SettlementResponse and injects the recommendations into the\n * JSON response body as a `_x402_sponsored` field. This is the only way\n * recommendations reach the agent's LLM (headers and receipt metadata are\n * not visible to LLMs).\n *\n * Pass `true` for default injection, or an object with a custom `inject`\n * function for full control over how recommendations appear in the response.\n *\n * @default false (off, no injection)\n *\n * @example Default injection\n * ```typescript\n * x402Middleware({ payTo: '...', amount: '0.05', sponsoredAccess: true })\n * // Agent receives: { _x402_sponsored: [...], ...originalResponse }\n * ```\n *\n * @example Custom injection\n * ```typescript\n * x402Middleware({\n * payTo: '...', amount: '0.05',\n * sponsoredAccess: {\n * inject: (body, recs) => ({ ...body, related_tools: recs })\n * }\n * })\n * ```\n */\n sponsoredAccess?: boolean | {\n /** Custom injection function. Receives the original response body and typed recommendations. */\n inject?: (body: unknown, recommendations: SponsoredRecommendation[]) => unknown;\n /** Called when sponsored recommendations are matched for a settlement. */\n onMatch?: (recommendations: SponsoredRecommendation[], settlement: { transaction: string; network: string; payer: string }) => void;\n };\n}\n\n/**\n * Extended request with payment info\n */\nexport interface X402Request extends Request {\n /**\n * Payment information (only present after successful payment)\n */\n x402?: {\n /** Transaction signature/hash */\n transaction: string;\n /** Payer address */\n payer: string;\n /** Network used */\n network: string;\n };\n}\n\n// Default network\nconst DEFAULT_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n// USDC decimals\nconst USDC_DECIMALS = 6;\n\n/**\n * Create x402 middleware for Express\n *\n * @param config - Middleware configuration\n * @returns Express middleware function\n */\n/**\n * Resolve a payTo value for a specific network from the config.\n * Supports: string, PayToProvider, or Record with glob matching.\n */\nfunction resolvePayToForNetwork(\n payTo: string | PayToProvider | Record<string, string | PayToProvider>,\n network: string,\n): string | PayToProvider {\n if (typeof payTo === 'string' || typeof payTo === 'function') return payTo;\n\n // Exact match first\n if (network in payTo) return payTo[network];\n\n // Prefix glob: 'eip155:*' matches 'eip155:8453'\n const prefix = network.split(':')[0];\n const globKey = `${prefix}:*`;\n if (globKey in payTo) return payTo[globKey];\n\n // Default fallback\n if ('*' in payTo) return payTo['*'];\n\n throw new Error(`No payTo configured for network \"${network}\"`);\n}\n\nexport function x402Middleware(config: X402MiddlewareConfig): RequestHandler {\n const {\n payTo,\n amount,\n asset,\n description,\n resourceUrl: staticResourceUrl,\n mimeType,\n timeoutSeconds,\n verbose = false,\n getResourceUrl,\n getAmount,\n getDescription,\n } = config;\n\n const log = verbose\n ? console.log.bind(console, '[x402:middleware]')\n : () => {};\n\n // Resolve networks: single string, array, or inferred from provider defaults\n const singleProviderDefaults = (typeof payTo === 'function') ? payTo._x402Defaults : undefined;\n const facilitatorUrl = config.facilitatorUrl ?? singleProviderDefaults?.facilitatorUrl;\n\n const configuredNetworks: string[] = (() => {\n if (config.network) {\n return Array.isArray(config.network) ? config.network : [config.network];\n }\n if (singleProviderDefaults?.network) return [singleProviderDefaults.network];\n return [DEFAULT_NETWORK];\n })();\n\n // Create one server per network (reused across requests)\n const servers = new Map<string, ReturnType<typeof createX402Server>>();\n for (const net of configuredNetworks) {\n const netPayTo = resolvePayToForNetwork(payTo, net);\n\n // Guard: Stripe payTo only supports Base — throw early if misconfigured\n if (typeof netPayTo === 'function' && (netPayTo as any)._stripeNetwork) {\n const stripeNet = (netPayTo as any)._stripeNetwork as string;\n if (net !== stripeNet) {\n throw new Error(\n `stripePayTo is configured for \"${stripeNet}\" but middleware includes network \"${net}\". ` +\n `Stripe only supports Base deposit addresses. Use a static payTo for other chains.`\n );\n }\n }\n\n servers.set(net, createX402Server({\n payTo: netPayTo,\n network: net,\n asset,\n facilitatorUrl,\n defaultTimeoutSeconds: timeoutSeconds,\n }));\n }\n\n // Primary server for verify/settle when we can't determine network from header\n const primaryServer = servers.get(configuredNetworks[0])!;\n\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n // Check for payment signature\n const paymentSignature = req.headers['payment-signature'] as string | undefined;\n\n if (!paymentSignature) {\n // No payment - return 402\n log('No payment signature, returning 402');\n\n // Build resource URL\n const resourceUrl = getResourceUrl?.(req) \n ?? staticResourceUrl \n ?? `${req.protocol}://${req.get('host')}${req.originalUrl}`;\n\n // Get dynamic values\n const requestAmount = getAmount?.(req) ?? amount;\n const requestDescription = getDescription?.(req) ?? description;\n\n // Convert USD to atomic units\n const decimals = asset?.decimals ?? USDC_DECIMALS;\n const amountAtomic = toAtomicUnits(parseFloat(requestAmount), decimals);\n\n const requirementsOptions: BuildRequirementsOptions = {\n amountAtomic,\n resourceUrl,\n description: requestDescription,\n mimeType,\n timeoutSeconds,\n };\n\n // Build requirements from all network servers and merge accepts arrays\n const allAccepts: import('../types').PaymentAccept[] = [];\n let requirements: import('../types').PaymentRequired | null = null;\n for (const [, srv] of servers) {\n try {\n const reqs = await srv.buildRequirements(requirementsOptions);\n allAccepts.push(...reqs.accepts);\n if (!requirements) requirements = reqs;\n } catch (e) {\n log('Failed to build requirements for a network:', e);\n }\n }\n if (!requirements || allAccepts.length === 0) {\n res.status(500).json({ error: 'Failed to build payment requirements' });\n return;\n }\n requirements = { ...requirements, accepts: allAccepts };\n const encoded = primaryServer.encodeRequirements(requirements);\n\n res.setHeader('PAYMENT-REQUIRED', encoded);\n res.status(402).json({\n error: 'Payment required',\n accepts: requirements.accepts,\n resource: requirements.resource,\n });\n return;\n }\n\n // Payment signature present - verify and settle.\n // Determine which network server to use from the payment header.\n log('Payment signature received, verifying...');\n\n let targetServer = primaryServer;\n try {\n const decoded = JSON.parse(Buffer.from(paymentSignature, 'base64').toString());\n const paymentNetwork = decoded?.accepted?.network as string | undefined;\n if (paymentNetwork && servers.has(paymentNetwork)) {\n targetServer = servers.get(paymentNetwork)!;\n }\n } catch {\n // Fall through to primary server\n }\n\n const verifyResult = await targetServer.verifyPayment(paymentSignature);\n \n if (!verifyResult.isValid) {\n log('Payment verification failed:', verifyResult.invalidReason);\n res.status(402).json({\n error: 'Payment verification failed',\n reason: verifyResult.invalidReason,\n });\n return;\n }\n\n log('Payment verified, settling...');\n\n const settleResult = await targetServer.settlePayment(paymentSignature);\n\n if (!settleResult.success) {\n log('Payment settlement failed:', settleResult.errorReason);\n res.status(402).json({\n error: 'Payment settlement failed',\n reason: settleResult.errorReason,\n });\n return;\n }\n\n log('Payment settled:', settleResult.transaction);\n\n const settledNetwork = settleResult.network || configuredNetworks[0];\n\n // Attach payment info to request\n (req as X402Request).x402 = {\n transaction: settleResult.transaction!,\n payer: verifyResult.payer ?? '',\n network: settledNetwork,\n };\n\n // Set PAYMENT-RESPONSE header per x402 v2 spec\n const paymentResponseData: Record<string, unknown> = {\n success: true,\n transaction: settleResult.transaction!,\n network: settledNetwork,\n payer: verifyResult.payer ?? '',\n };\n if (settleResult.extensions) {\n paymentResponseData.extensions = settleResult.extensions;\n }\n res.setHeader('PAYMENT-RESPONSE', encodeBase64Json(paymentResponseData));\n\n // Sponsored Access: inject recommendations into the response body\n // so the agent's LLM actually sees them (headers are invisible to LLMs)\n if (config.sponsoredAccess && settleResult.extensions?.[\"sponsored-access\"]) {\n const extData = settleResult.extensions[\"sponsored-access\"] as\n { info?: { recommendations?: SponsoredRecommendation[] }; recommendations?: SponsoredRecommendation[] } | undefined;\n // Facilitator may nest under .info.recommendations or .recommendations directly\n const recs = extData?.info?.recommendations ?? extData?.recommendations;\n if (recs && recs.length > 0) {\n log('Injecting sponsored-access recommendations into response');\n\n // Notify callback if configured\n if (typeof config.sponsoredAccess === 'object' && config.sponsoredAccess.onMatch) {\n try {\n config.sponsoredAccess.onMatch(recs, {\n transaction: settleResult.transaction!,\n network: settledNetwork,\n payer: verifyResult.payer ?? '',\n });\n } catch {\n // Don't block response for callback errors\n }\n }\n\n const originalJson = res.json.bind(res);\n res.json = function patchedJson(body: unknown) {\n if (typeof config.sponsoredAccess === 'object' && config.sponsoredAccess.inject) {\n return originalJson(config.sponsoredAccess.inject(body, recs));\n }\n if (body && typeof body === 'object' && !Array.isArray(body)) {\n return originalJson({ _x402_sponsored: recs, ...(body as Record<string, unknown>) });\n }\n return originalJson(body);\n } as typeof res.json;\n }\n }\n\n // Continue to actual handler\n next();\n } catch (error) {\n log('Middleware error:', error);\n \n // Don't expose internal errors\n res.status(500).json({\n error: 'Payment processing error',\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n };\n}\n","/**\n * x402 Browser Support Middleware\n *\n * Express middleware that automatically renders a branded HTML paywall page\n * when a browser (Accept: text/html) receives a 402 Payment Required response.\n * API clients continue to receive the standard JSON response unchanged.\n *\n * Includes a functional \"Pay\" button using the Solana Wallet Standard --\n * detects Phantom/Solflare/Backpack, constructs a USDC transfer, signs,\n * and submits the payment automatically.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { x402Middleware, x402BrowserSupport } from '@dexterai/x402/server';\n *\n * const app = express();\n * app.use(express.json());\n * app.use(x402BrowserSupport());\n *\n * app.post('/api/data',\n * x402Middleware({ payTo: '...', amount: '0.01' }),\n * (req, res) => res.json({ data: 'protected' })\n * );\n * ```\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/**\n * Configuration for x402BrowserSupport middleware.\n */\nexport interface X402BrowserSupportConfig {\n /** Custom title shown on the paywall page. @default 'Payment Required' */\n title?: string;\n /** Custom branding text. @default 'Powered by x402' */\n branding?: string;\n /** URL to link for SDK/documentation. @default 'https://docs.dexter.cash/docs/sdk/' */\n sdkUrl?: string;\n /** Whether to include the request method and path. @default true */\n showEndpoint?: boolean;\n /** Solana RPC URL for wallet transactions. @default 'https://api.dexter.cash/api/solana/rpc' */\n rpcUrl?: string;\n}\n\n/** Escape HTML to prevent XSS from untrusted payment requirement fields */\nfunction esc(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\n}\n\n/* ------------------------------------------------------------------ */\n/* USDC coin icon SVG (inline, use at ~18px) */\n/* ------------------------------------------------------------------ */\nconst USDC_ICON_SVG = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 2000 2000\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1000 2000c554.17 0 1000-445.83 1000-1000S1554.17 0 1000 0 0 445.83 0 1000s445.83 1000 1000 1000z\" fill=\"#2775ca\"/><path d=\"M1275 1158.33c0-145.83-87.5-195.83-262.5-216.66-125-16.67-150-50-150-108.34s41.67-95.83 125-95.83c75 0 116.67 25 137.5 87.5 4.17 12.5 16.67 20.83 29.17 20.83h66.66c16.67 0 29.17-12.5 29.17-29.16v-4.17c-16.67-91.67-91.67-162.5-187.5-170.83v-100c0-16.67-12.5-29.17-33.33-33.34h-62.5c-16.67 0-29.17 12.5-33.34 33.34v95.83c-125 16.67-204.16 100-204.16 204.17 0 137.5 83.33 191.66 258.33 212.5 116.67 20.83 154.17 45.83 154.17 112.5s-58.34 112.5-137.5 112.5c-108.34 0-145.84-45.84-158.34-108.34-4.16-16.66-16.66-25-29.16-25h-70.84c-16.66 0-29.16 12.5-29.16 29.17v4.17c16.66 104.16 83.33 179.16 220.83 200v100c0 16.66 12.5 29.16 33.33 33.33h62.5c16.67 0 29.17-12.5 33.34-33.33v-100c125-20.84 208.33-108.34 208.33-220.84z\" fill=\"#fff\"/><path d=\"M787.5 1595.83c-325-116.66-491.67-479.16-370.83-800 62.5-175 200-308.33 370.83-370.83 16.67-8.33 25-20.83 25-41.67V325c0-16.67-8.33-29.17-25-33.33-4.17 0-12.5 0-16.67 4.16-395.83 125-612.5 545.84-487.5 941.67 75 233.33 254.17 412.5 487.5 487.5 16.67 8.33 33.34 0 37.5-16.67 4.17-4.16 4.17-8.33 4.17-16.66v-58.34c0-12.5-12.5-29.16-25-37.5zM1229.17 295.83c-16.67-8.33-33.34 0-37.5 16.67-4.17 4.17-4.17 8.33-4.17 16.67v58.33c0 16.67 12.5 33.33 25 41.67 325 116.66 491.67 479.16 370.83 800-62.5 175-200 308.33-370.83 370.83-16.67 8.33-25 20.83-25 41.67V1700c0 16.67 8.33 29.17 25 33.33 4.17 0 12.5 0 16.67-4.16 395.83-125 612.5-545.84 487.5-941.67-75-237.5-258.34-416.67-487.5-491.67z\" fill=\"#fff\"/></svg>`;\n\n/* ------------------------------------------------------------------ */\n/* Dexter crest SVG (inline, ~40px display) */\n/* ------------------------------------------------------------------ */\nconst DEXTER_CREST_SVG = `<svg width=\"36\" height=\"36\" viewBox=\"0 0 300 300\" xmlns=\"http://www.w3.org/2000/svg\"><g><path fill=\"#F2681A\" d=\"m324.93,313.11c-115.5,0-231,0-350,0l350,0z\"/><path fill=\"#FDFAF5\" d=\"m230.43,50.62c1.1.85 2.19 1.7 3.32 2.57 6.02 4.8 11.77 9.88 17.46 15.07.92.84.92.84 1.86 1.69 1.82 1.69 3.59 3.42 5.35 5.16.61.56 1.22 1.13 1.84 1.71 5.66 5.76 6.18 10.43 6.13 18.3.02 1.16.04 2.32.06 3.52.06 3.83.06 7.65.07 11.48.02 2.68.05 5.35.08 8.03.05 5.6.09 11.21.1 16.81.02 7.15.09 14.31.17 21.46.06 5.53.1 11.05.13 16.58.02 2.64.04 5.27.07 7.91.18 17.58.12 32.82-11.24 47.32-7.35 7.27-16.54 12.06-25.42 17.22-1.97 1.16-3.94 2.33-5.91 3.49-7.16 4.24-14.34 8.44-21.53 12.62-4.8 2.79-9.59 5.6-14.38 8.42-1.25.73-2.5 1.47-3.79 2.23-2.32 1.36-4.64 2.73-6.96 4.1-27.47 16.09-27.47 16.09-42.16 12.93-8.06-2.28-14.94-5.82-22.16-10.02-1.17-.67-2.34-1.34-3.54-2.04-24.55-14.25-43.58-27.03-51.9-55.58-1.07-4.58-1.54-8.92-1.52-13.61.28-9.5.28-9.5-3.3-17.97-1.81-1.49-3.68-2.92-5.59-4.28-9.19-7.06-12.7-20.03-14.18-31.06-.54-5.77-.55-11.56-.6-17.35-.03-1.32-.07-2.63-.1-3.99-.01-1.26-.02-2.53-.03-3.83-.02-1.15-.03-2.29-.05-3.47.72-4.02 1.94-5.36 5.21-7.74 2.89-.53 2.89-.53 6.07-.46 1.71.02 1.71.02 3.46.05 1.19.04 2.37.08 3.59.12 1.2.02 2.41.04 3.65.06 2.97.05 5.93.13 8.9.23.14-1.35.29-2.7.43-4.08.63-5 1.78-9.74 3.14-14.58.22-.79.43-1.59.66-2.4.53-1.92 1.06-3.84 1.6-5.76-1.55-.45-1.55-.45-3.13-.9-9.52-3.52-17.1-10.95-21.37-20.1-3.81-9.26-3.87-20.34-.29-29.68 6.49-13.99 16.36-23.23 30.66-29.01 49.81-17.69 115.79 8.35 155.13 38.85z\"/><path fill=\"#F2671A\" d=\"m142.93,22.62c.86.19 1.73.39 2.62.59 36.12 8.21 68.79 24.98 95.38 50.75 1.02.98 2.03 1.97 3.08 2.98 10.84 10.66 10.84 10.66 11.05 14.62-2.06 3.55-5.44 4.18-9.17 5.3-.79.25-1.59.49-2.41.75-28.13 8.43-60.95 6.37-87.13-7.16-.86-.49-1.71-.97-2.6-1.48-7.37-4.05-12.59-3.36-20.59-1.54-22.76 4-48.47 1.53-68.69-9.74-4.88-3.88-8.23-8.29-10.21-14.22-.93-10.38-.67-18.44 5.83-26.83 19.57-23.38 55.99-20.36 82.83-14z\"/><path fill=\"#F16619\" d=\"m44.93,129.12c27.36-.03 54.72-.05 82.08-.06 12.7-.01 25.41-.01 38.11-.03 11.07-.01 22.14-.02 33.2-.02 5.86 0 11.73-.01 17.59-.01 5.51-.01 11.03-.01 16.54-.01 2.03 0 4.06 0 6.09-.01 2.76-.01 5.52 0 8.28 0 .81 0 1.63-.01 2.47-.01 5.51.02 5.51.02 6.81 1.32.22 3.43.22 3.43 0 7-2.75 2.75-3.42 2.66-7.15 2.82-1.41.07-1.41.07-2.85.14-1.47.05-1.47.05-2.98.11-1.49.07-1.49.07-3 .14-2.45.11-4.9.21-7.35.3-.2 1.3-.4 2.59-.6 3.93-2.57 16.08-5.93 29.89-18.89 40.86-10.35 7.28-21.87 8.49-34.17 7.71-13.11-2.33-22.52-9.19-30.33-19.83-4.49-7.64-4.8-17.05-5.83-25.67-4.24.39-8.47.77-12.83 1.17-.28 1.84-.28 1.84-.56 3.71-2.32 14.39-5.63 23.35-16.95 33.11-2.32 1.67-2.32 1.67-4.65 1.67 4 4.67 9.06 6.59 14.87 8.24 3.79 1.09 3.79 1.09 6.12 3.43-.65 5.31-.65 5.31-2.33 7-8.42-.27-15.13-2.29-22.17-7-1.09-1.21-2.17-2.43-3.25-3.65-2.72-2.81-4.45-3.84-8.36-4.16-1.67-.02-3.34-.02-5.01.01-1.77-.04-3.54-.09-5.3-.15-1.27-.04-1.27-.04-2.56-.08-9.26-.54-17.6-4.56-24.51-10.64-9.58-11.11-11.03-22.56-10.72-36.82.02-1.4.03-2.8.05-4.24.04-3.42.1-6.85.17-10.27z\"/><path fill=\"#F26117\" d=\"m172.68,203.08c7.27.09 13.23 1.97 18.87 6.65 2.88 3.07 3.86 5.12 4.25 9.32-.12 1.01-.24 2.02-.36 3.06-2.55.95-2.55.95-5.83 1.17-3.28-2.84-3.28-2.84-5.83-5.83-.36.58-.71 1.16-1.08 1.75-7.6 11.29-20.06 17.74-33.05 21.09-20.36 3.1-36.81-1.66-53.37-13.73-2.33-2.11-2.33-2.11-4.67-5.61.42-3.45.99-4.49 3.5-7 4.07.37 5.95 2.13 8.75 4.96 9.81 8.93 22.53 11.87 35.51 11.69 11.74-1.05 22.38-5.85 31.57-13.15 2.06-2.45 2.06-2.45 3.5-4.67-1.66.07-1.66.07-3.35.15-3.65-.15-3.65-.15-5.98-2.48.75-6.18 1.46-7.19 7.58-7.36z\"/></g></svg>`;\n\n/* ------------------------------------------------------------------ */\n/* Shared CSS for all Dexter-branded pages */\n/* ------------------------------------------------------------------ */\nconst DEXTER_STYLES = `\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Orbitron:wght@500;700&display=swap');\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:'Inter',system-ui,-apple-system,sans-serif;background:#0a0a0a;color:#e2e8f0;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:1rem}\n.card{max-width:460px;width:100%;background:rgba(20,20,20,.85);border:1px solid rgba(242,107,26,.12);border-radius:8px;padding:2rem 2rem 1.75rem;text-align:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}\n.crest{margin:0 auto .75rem}\nh1{font-family:'Orbitron',sans-serif;font-size:1.15rem;font-weight:700;color:#f1f5f9;letter-spacing:.04em;margin-bottom:.35rem}\n.desc{color:#94a3b8;font-size:.9rem;margin-bottom:1.25rem;line-height:1.5}\n.price{font-family:'Orbitron',sans-serif;font-size:1.6rem;font-weight:700;color:#F26B1A;margin:.75rem 0 .25rem;display:inline-flex;align-items:center;gap:.35rem}\n.price svg{width:1.3em;height:1.3em;flex-shrink:0}\n.chain{color:#525252;font-size:.75rem;margin-bottom:1.25rem;letter-spacing:.03em}\n.endpoint{background:rgba(242,107,26,.06);border:1px solid rgba(242,107,26,.12);border-radius:6px;padding:.5rem .75rem;margin-bottom:1.25rem}\n.endpoint code{font-family:'SF Mono',Monaco,Consolas,monospace;font-size:.8rem;color:#F26B1A}\n.info{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);border-radius:6px;padding:.85rem 1rem;font-size:.82rem;color:#737373;line-height:1.6;text-align:left}\n.info strong{color:#a3a3a3}\n.info code{background:rgba(242,107,26,.08);padding:2px 5px;border-radius:3px;font-size:.78rem;color:#F26B1A;font-family:'SF Mono',Monaco,Consolas,monospace}\n.info a{color:#F26B1A;text-decoration:none;font-weight:600}\n.info a:hover{text-decoration:underline}\n.footer{margin-top:1.25rem;display:flex;align-items:center;justify-content:center;gap:.75rem;font-size:.7rem;color:#404040}\n.footer a{color:#525252;text-decoration:none}\n.footer a:hover{color:#737373}\n.sep{width:3px;height:3px;border-radius:50%;background:#333}\n`;\n\n/* ------------------------------------------------------------------ */\n/* Pay button styles + states */\n/* ------------------------------------------------------------------ */\nconst PAY_BUTTON_STYLES = `\n.pay-section{margin:1.25rem 0}\n.pay-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;background:linear-gradient(135deg,#F26B1A,#D13F00);color:#fff;border:none;padding:.65rem 2rem;border-radius:6px;font-family:'Inter',sans-serif;font-size:.95rem;font-weight:600;cursor:pointer;transition:opacity .15s,transform .1s;min-width:180px}\n.pay-btn:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}\n.pay-btn:active:not(:disabled){transform:translateY(0)}\n.pay-btn:disabled{opacity:.6;cursor:not-allowed}\n.pay-btn .spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}\n@keyframes spin{to{transform:rotate(360deg)}}\n.pay-status{font-size:.8rem;color:#737373;margin-top:.5rem;min-height:1.2em}\n.pay-status.error{color:#ef4444}\n.pay-status.success{color:#22c55e}\n.pay-alt{font-size:.78rem;color:#404040;margin-top:.75rem}\n.pay-alt a{color:#F26B1A;text-decoration:none}\n.result-box{background:rgba(34,197,94,.06);border:1px solid rgba(34,197,94,.15);border-radius:6px;padding:.75rem;margin-top:.75rem;text-align:left;font-size:.78rem;max-height:200px;overflow:auto}\n.result-box pre{color:#94a3b8;font-family:'SF Mono',Monaco,Consolas,monospace;white-space:pre-wrap;word-break:break-all}\n.no-wallet{font-size:.82rem;color:#737373;margin:1rem 0}\n`;\n\n/* ------------------------------------------------------------------ */\n/* Wallet payment inline script (Solana Wallet Standard) */\n/* ------------------------------------------------------------------ */\nconst PAY_SCRIPT = `\n<script type=\"module\">\n// Payment data is embedded in #x402-data attributes\nconst dataEl = document.getElementById('x402-data');\nif (!dataEl) throw new Error('Missing payment data');\n\nconst requirements = JSON.parse(atob(dataEl.dataset.requirements));\nconst requestMethod = dataEl.dataset.method;\nconst requestUrl = dataEl.dataset.url;\nconst rpcUrl = dataEl.dataset.rpc || 'https://api.dexter.cash/api/solana/rpc';\n\n// Detect wallet provider\nfunction getWalletProvider() {\n if (window.phantom?.solana?.isPhantom) return { name: 'Phantom', provider: window.phantom.solana };\n if (window.solflare?.isSolflare) return { name: 'Solflare', provider: window.solflare };\n if (window.backpack) return { name: 'Backpack', provider: window.backpack };\n // Generic wallet-standard fallback\n if (window.solana) return { name: 'Wallet', provider: window.solana };\n return null;\n}\n\nconst walletInfo = getWalletProvider();\nconst btn = document.getElementById('pay-btn');\nconst status = document.getElementById('pay-status');\nconst section = document.getElementById('pay-section');\nconst noWallet = document.getElementById('no-wallet');\n\nif (walletInfo && btn) {\n section.style.display = 'block';\n if (noWallet) noWallet.style.display = 'none';\n} else if (noWallet) {\n noWallet.style.display = 'block';\n if (section) section.style.display = 'none';\n}\n\n// Preload Solana libraries in background\nlet solanaLibs = null;\nconst preload = (async () => {\n try {\n const [web3, spl] = await Promise.all([\n import('https://esm.sh/@solana/web3.js@1.98.0'),\n import('https://esm.sh/@solana/spl-token@0.4.9'),\n ]);\n solanaLibs = { web3, spl };\n } catch (e) {\n console.warn('[x402] Failed to preload Solana libraries:', e);\n }\n})();\n\nfunction setStatus(msg, type) {\n if (!status) return;\n status.textContent = msg;\n status.className = 'pay-status' + (type ? ' ' + type : '');\n}\n\nfunction setBtnState(text, disabled, loading) {\n if (!btn) return;\n btn.disabled = disabled;\n btn.innerHTML = loading\n ? '<span class=\"spinner\"></span>' + text\n : text;\n}\n\nif (btn) {\n btn.addEventListener('click', async () => {\n if (!walletInfo) return;\n const { provider } = walletInfo;\n\n try {\n // 1. Connect wallet\n setBtnState('Connecting...', true, true);\n setStatus('');\n await provider.connect();\n\n if (!provider.publicKey) {\n throw new Error('Wallet did not provide a public key');\n }\n\n // 2. Load Solana libraries (should already be cached from preload)\n setBtnState('Preparing...', true, true);\n await preload;\n if (!solanaLibs) {\n // Retry once\n const [web3, spl] = await Promise.all([\n import('https://esm.sh/@solana/web3.js@1.98.0'),\n import('https://esm.sh/@solana/spl-token@0.4.9'),\n ]);\n solanaLibs = { web3, spl };\n }\n\n const { web3, spl } = solanaLibs;\n const { PublicKey, Connection, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = web3;\n const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } = spl;\n\n // 3. Parse payment requirements\n const accept = requirements.accepts[0];\n if (!accept) throw new Error('No payment method available');\n\n const payTo = new PublicKey(accept.payTo);\n const amount = BigInt(accept.amount ?? accept.maxAmountRequired);\n const mintPubkey = new PublicKey(accept.asset);\n const feePayer = accept.extra?.feePayer ? new PublicKey(accept.extra.feePayer) : provider.publicKey;\n const userPubkey = provider.publicKey;\n\n // 4. Build transaction\n setBtnState('Building tx...', true, true);\n const connection = new Connection(rpcUrl, 'confirmed');\n\n const instructions = [];\n\n // ComputeBudget\n instructions.push(ComputeBudgetProgram.setComputeUnitLimit({ units: 12000 }));\n instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }));\n\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) throw new Error('Token mint not found');\n const programId = mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;\n\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n\n // ATAs\n const sourceAta = await getAssociatedTokenAddress(mintPubkey, userPubkey, false, programId);\n const destAta = await getAssociatedTokenAddress(mintPubkey, payTo, false, programId);\n\n // Verify source exists\n const sourceInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceInfo) throw new Error('No USDC token account found. Make sure you have USDC in your wallet.');\n\n // TransferChecked\n instructions.push(createTransferCheckedInstruction(sourceAta, mintPubkey, destAta, userPubkey, amount, mint.decimals, [], programId));\n\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n const message = new TransactionMessage({ payerKey: feePayer, recentBlockhash: blockhash, instructions }).compileToV0Message();\n const transaction = new VersionedTransaction(message);\n\n // 5. Sign\n setBtnState('Sign in wallet...', true, true);\n setStatus('Approve the transaction in your wallet');\n const signed = await provider.signTransaction(transaction);\n const serialized = signed.serialize();\n\n // Convert Uint8Array to base64\n let payload = '';\n const bytes = new Uint8Array(serialized);\n const chunk = 8192;\n for (let i = 0; i < bytes.length; i += chunk) {\n payload += String.fromCharCode.apply(null, bytes.slice(i, i + chunk));\n }\n payload = btoa(payload);\n\n // 6. Build payment-signature header (x402 v2 format)\n // Solana: payload must be { transaction: base64Tx } per SDK spec\n const paymentSignature = {\n x402Version: accept.x402Version ?? 2,\n resource: requirements.resource,\n accepted: accept,\n payload: { transaction: payload },\n };\n const paymentHeader = btoa(JSON.stringify(paymentSignature));\n\n // 7. Submit payment\n setBtnState('Verifying...', true, true);\n setStatus('Payment submitted, verifying...');\n\n // Use the original request body if available\n const originalBody = dataEl.dataset.body ? atob(dataEl.dataset.body) : '{}';\n const response = await fetch(requestUrl, {\n method: requestMethod,\n headers: {\n 'Content-Type': 'application/json',\n 'PAYMENT-SIGNATURE': paymentHeader,\n },\n body: requestMethod !== 'GET' ? originalBody : undefined,\n });\n\n if (response.ok) {\n const data = await response.json();\n setBtnState('Paid', true, false);\n setStatus('Payment successful', 'success');\n // Show response\n const resultBox = document.createElement('div');\n resultBox.className = 'result-box';\n resultBox.innerHTML = '<pre>' + JSON.stringify(data, null, 2).replace(/</g, '<') + '</pre>';\n section.appendChild(resultBox);\n } else {\n const err = await response.json().catch(() => ({ error: 'Payment verification failed' }));\n throw new Error(err.error || err.reason || 'Payment failed');\n }\n } catch (err) {\n console.error('[x402] Payment error:', err);\n setBtnState('Pay ' + document.getElementById('price-value').textContent, false, false);\n setStatus(err.message || 'Payment failed', 'error');\n }\n });\n}\n</script>\n`;\n\n/**\n * Generate the Dexter-branded paywall HTML with wallet pay button.\n */\nfunction generatePaywallHtml(\n paymentRequiredHeader: string,\n requestUrl: string,\n method: string,\n config: Required<Pick<X402BrowserSupportConfig, 'title' | 'branding' | 'sdkUrl' | 'showEndpoint'>>,\n rpcUrl: string,\n requestBody?: string,\n): string {\n let price = '?';\n let description = 'This resource requires payment';\n let network = '';\n\n try {\n const decoded = JSON.parse(Buffer.from(paymentRequiredHeader, 'base64').toString());\n const accept = decoded.accepts?.[0];\n if (accept) {\n const amount = accept.amount ?? accept.maxAmountRequired ?? '0';\n const decimals = accept.extra?.decimals || 6;\n price = (Number(amount) / Math.pow(10, decimals)).toFixed(decimals > 4 ? 4 : 2);\n network = accept.network || '';\n }\n if (decoded.resource?.description) {\n description = decoded.resource.description;\n }\n } catch {\n // If we can't decode, show generic paywall\n }\n\n const chainName = network.includes('solana')\n ? 'Solana'\n : network.includes('eip155')\n ? 'Base'\n : '';\n\n const endpointSection = config.showEndpoint\n ? `<div class=\"endpoint\"><code>${esc(method)} ${esc(requestUrl)}</code></div>`\n : '';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>${esc(config.title)} — ${esc(price)} USDC</title>\n<style>${DEXTER_STYLES}${PAY_BUTTON_STYLES}</style>\n</head>\n<body>\n<div class=\"card\">\n <div class=\"crest\">${DEXTER_CREST_SVG}</div>\n <h1>${esc(config.title)}</h1>\n <p class=\"desc\">${esc(description)}</p>\n <div class=\"price\">${USDC_ICON_SVG}<span id=\"price-value\">${esc(price)}</span></div>\n <div class=\"chain\">${esc(chainName)}${chainName ? ' network' : ''}</div>\n ${endpointSection}\n\n <div id=\"pay-section\" class=\"pay-section\" style=\"display:none\">\n <button id=\"pay-btn\" class=\"pay-btn\">Pay ${price}</button>\n <div id=\"pay-status\" class=\"pay-status\"></div>\n <div class=\"pay-alt\">or use <a href=\"${config.sdkUrl}\">x402 SDK</a> for programmatic access</div>\n </div>\n\n <div id=\"no-wallet\" class=\"no-wallet\" style=\"display:none\">\n <div class=\"info\">\n <strong>Access this endpoint:</strong><br><br>\n Use any x402-compatible client or a browser with a Solana wallet extension (Phantom, Solflare, Backpack).<br><br>\n <code>npm install @dexterai/x402</code><br><br>\n <a href=\"${config.sdkUrl}\">x402 SDK docs →</a>\n </div>\n </div>\n\n <div class=\"footer\">\n <a href=\"https://docs.dexter.cash/docs/sdk/\">x402</a>\n <span class=\"sep\"></span>\n <a href=\"https://dexter.cash\">Dexter</a>\n </div>\n</div>\n\n<div id=\"x402-data\" style=\"display:none\"\n data-requirements=\"${paymentRequiredHeader}\"\n data-method=\"${method}\"\n data-url=\"${requestUrl}\"\n data-rpc=\"${rpcUrl}\"\n data-body=\"${requestBody ? Buffer.from(requestBody).toString('base64') : ''}\"\n></div>\n${PAY_SCRIPT}\n</body>\n</html>`;\n}\n\n/**\n * Create x402 browser support middleware.\n *\n * Wraps `res.json()` to intercept 402 Payment Required responses.\n * When the request is from a browser (Accept: text/html) and no\n * payment-signature header is present, renders a branded HTML paywall\n * instead of raw JSON.\n *\n * API clients are completely unaffected -- they receive normal JSON.\n */\nexport function x402BrowserSupport(config: X402BrowserSupportConfig = {}): RequestHandler {\n const resolvedConfig = {\n title: config.title ?? 'Payment Required',\n branding: config.branding ?? 'Powered by <a href=\"https://docs.dexter.cash/docs/sdk/\">Dexter x402</a>',\n sdkUrl: config.sdkUrl ?? 'https://docs.dexter.cash/docs/sdk/',\n showEndpoint: config.showEndpoint ?? true,\n };\n const rpcUrl = config.rpcUrl ?? 'https://api.dexter.cash/api/solana/rpc';\n\n return (req: Request, res: Response, next: NextFunction): void => {\n const originalJson = res.json.bind(res);\n\n res.json = function (body: unknown) {\n if (\n res.statusCode === 402 &&\n req.accepts('html') &&\n !req.headers['payment-signature']\n ) {\n const paymentRequired =\n (res.getHeader('PAYMENT-REQUIRED') as string) ||\n (res.getHeader('payment-required') as string);\n\n if (paymentRequired && typeof paymentRequired === 'string') {\n // Capture the original request body for the pay button\n let bodyStr: string | undefined;\n if (req.body && typeof req.body === 'object' && Object.keys(req.body).length > 0) {\n try { bodyStr = JSON.stringify(req.body); } catch { /* ignore */ }\n }\n const html = generatePaywallHtml(\n paymentRequired,\n req.originalUrl,\n req.method,\n resolvedConfig,\n rpcUrl,\n bodyStr,\n );\n res.status(402).type('html').send(html);\n return res;\n }\n }\n\n return originalJson(body);\n } as typeof res.json;\n\n next();\n };\n}\n","/**\n * x402 Access Pass Middleware\n *\n * Pay once, get a time-limited JWT for unlimited API requests.\n * Supports both predefined tiers and custom durations.\n *\n * @example Tier-based pricing\n * ```typescript\n * app.use('/api', x402AccessPass({\n * payTo: 'YourSolanaAddress...',\n * tiers: {\n * '1h': '0.50', // $0.50 for 1 hour\n * '24h': '2.00', // $2.00 for 24 hours\n * },\n * }));\n * ```\n *\n * @example Rate-based custom durations\n * ```typescript\n * app.use('/api', x402AccessPass({\n * payTo: 'YourSolanaAddress...',\n * ratePerHour: '0.50', // $0.50/hour, any duration\n * }));\n * ```\n *\n * @example Both tiers and custom durations\n * ```typescript\n * app.use('/api', x402AccessPass({\n * payTo: 'YourSolanaAddress...',\n * tiers: { '1h': '0.50', '24h': '2.00' },\n * ratePerHour: '0.50', // fallback for custom durations\n * }));\n * ```\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { createX402Server } from './x402-server';\nimport { toAtomicUnits, encodeBase64Json } from '../utils';\nimport type { AccessPassTier, AccessPassInfo, AccessPassClaims } from '../types';\nimport crypto from 'crypto';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/**\n * Access pass middleware configuration\n */\nexport interface X402AccessPassConfig {\n /** Address to receive payments (Solana pubkey or EVM address) */\n payTo: string;\n\n /** CAIP-2 network identifier @default 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' */\n network?: string;\n\n /** x402 facilitator URL @default 'https://x402.dexter.cash' */\n facilitatorUrl?: string;\n\n /** Asset config @default USDC on specified network */\n asset?: { address: string; decimals: number };\n\n /**\n * Predefined pricing tiers.\n * Keys are tier IDs (e.g., '5m', '1h', '24h').\n * Values are prices in USD (e.g., '0.50').\n * Duration is parsed from the ID: '5m' = 5 minutes, '1h' = 1 hour, '24h' = 24 hours, '7d' = 7 days.\n */\n tiers?: Record<string, string>;\n\n /**\n * Rate per hour in USD for custom durations.\n * When set, buyers can request any duration via ?duration=<seconds> query param.\n */\n ratePerHour?: string;\n\n /** HMAC secret for JWT signing. Auto-generated if not provided. */\n secret?: Buffer;\n\n /** Issuer string for JWT 'iss' claim @default 'x402-access-pass' */\n issuer?: string;\n\n /** Enable verbose logging */\n verbose?: boolean;\n\n /** Description shown in 402 response */\n description?: string;\n}\n\n/**\n * Extended request with access pass info\n */\nexport interface X402AccessPassRequest extends Request {\n /** Access pass info (present when request is authenticated via valid pass) */\n accessPass?: {\n tier: string;\n duration: number;\n expiresAt: string;\n payer: string;\n network: string;\n };\n /** x402 payment info (present when a new pass was just purchased) */\n x402?: {\n transaction: string;\n payer: string;\n network: string;\n };\n}\n\n// ============================================================================\n// Duration Parsing\n// ============================================================================\n\nconst DURATION_REGEX = /^(\\d+)(m|h|d|w)$/;\n\nfunction parseTierDuration(tierId: string): number | null {\n const match = tierId.match(DURATION_REGEX);\n if (!match) return null;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 'm': return value * 60;\n case 'h': return value * 3600;\n case 'd': return value * 86400;\n case 'w': return value * 604800;\n default: return null;\n }\n}\n\nfunction formatDuration(seconds: number): string {\n if (seconds >= 604800 && seconds % 604800 === 0) return `${seconds / 604800} week${seconds / 604800 > 1 ? 's' : ''}`;\n if (seconds >= 86400 && seconds % 86400 === 0) return `${seconds / 86400} day${seconds / 86400 > 1 ? 's' : ''}`;\n if (seconds >= 3600 && seconds % 3600 === 0) return `${seconds / 3600} hour${seconds / 3600 > 1 ? 's' : ''}`;\n if (seconds >= 60 && seconds % 60 === 0) return `${seconds / 60} minute${seconds / 60 > 1 ? 's' : ''}`;\n return `${seconds} second${seconds > 1 ? 's' : ''}`;\n}\n\n// ============================================================================\n// JWT Helpers (built-in crypto, no external deps)\n// ============================================================================\n\nfunction signJwt(payload: AccessPassClaims, secret: Buffer): string {\n const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');\n const body = Buffer.from(JSON.stringify(payload)).toString('base64url');\n const sig = crypto.createHmac('sha256', secret).update(`${header}.${body}`).digest('base64url');\n return `${header}.${body}.${sig}`;\n}\n\nfunction verifyJwt(token: string, secret: Buffer): AccessPassClaims | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n\n const [header, body, sig] = parts;\n const expected = crypto.createHmac('sha256', secret).update(`${header}.${body}`).digest('base64url');\n if (sig !== expected) return null;\n\n const payload = JSON.parse(Buffer.from(body, 'base64url').toString()) as AccessPassClaims;\n\n // Check expiration\n if (payload.exp && Date.now() / 1000 > payload.exp) return null;\n\n // Validate sub\n if (payload.sub !== 'x402-access-pass') return null;\n\n return payload;\n } catch {\n return null;\n }\n}\n\n// ============================================================================\n// Middleware Factory\n// ============================================================================\n\nconst DEFAULT_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nconst USDC_DECIMALS = 6;\n\n/**\n * Create x402 access pass middleware for Express.\n *\n * Protects routes with time-limited access passes purchased via x402 payments.\n * Supports predefined tiers, custom durations, or both.\n */\nexport function x402AccessPass(config: X402AccessPassConfig): RequestHandler {\n const {\n payTo,\n network = DEFAULT_NETWORK,\n asset,\n facilitatorUrl,\n tiers: tierPrices,\n ratePerHour,\n secret: explicitSecret,\n issuer = 'x402-access-pass',\n verbose = false,\n description,\n } = config;\n\n const secret = explicitSecret ?? crypto.randomBytes(32);\n if (!explicitSecret) {\n console.warn('[x402:access-pass] No secret provided — access passes will be invalidated on server restart. Set `secret` for production use.');\n }\n\n // Validate config\n if (!tierPrices && !ratePerHour) {\n throw new Error('x402AccessPass: at least one of `tiers` or `ratePerHour` is required');\n }\n\n const log = verbose\n ? console.log.bind(console, '[x402:access-pass]')\n : () => {};\n\n const decimals = asset?.decimals ?? USDC_DECIMALS;\n\n // Build tier definitions\n const builtTiers: AccessPassTier[] = [];\n\n if (tierPrices) {\n for (const [id, price] of Object.entries(tierPrices)) {\n const seconds = parseTierDuration(id);\n if (!seconds) {\n console.warn(`x402AccessPass: skipping tier \"${id}\" — unrecognized duration format (use 5m, 1h, 24h, 7d)`);\n continue;\n }\n builtTiers.push({\n id,\n label: formatDuration(seconds),\n seconds,\n price,\n priceAtomic: toAtomicUnits(parseFloat(price), decimals),\n });\n }\n // Sort by duration ascending\n builtTiers.sort((a, b) => a.seconds - b.seconds);\n }\n\n // Create x402 server instance (reused across requests)\n const server = createX402Server({\n payTo,\n network,\n asset,\n facilitatorUrl,\n });\n\n // Build access pass info for X-ACCESS-PASS-TIERS header\n const passInfo: AccessPassInfo = {\n tiers: builtTiers.length > 0 ? builtTiers : undefined,\n ratePerHour: ratePerHour || undefined,\n issuer,\n };\n const passInfoEncoded = encodeBase64Json(passInfo);\n\n /**\n * Calculate price for a custom duration in seconds\n */\n function calculateCustomPrice(durationSeconds: number): { price: string; priceAtomic: string } {\n if (!ratePerHour) {\n throw new Error('Custom durations not supported — no ratePerHour configured');\n }\n const hours = durationSeconds / 3600;\n const price = (parseFloat(ratePerHour) * hours).toFixed(decimals > 4 ? 4 : 2);\n return { price, priceAtomic: toAtomicUnits(parseFloat(price), decimals) };\n }\n\n /**\n * Resolve tier/duration from request query params\n */\n function resolvePricing(req: Request): {\n tier: string;\n seconds: number;\n price: string;\n priceAtomic: string;\n label: string;\n } {\n const tierParam = req.query.tier as string | undefined;\n const durationParam = req.query.duration as string | undefined;\n\n // Explicit tier\n if (tierParam) {\n const found = builtTiers.find(t => t.id === tierParam);\n if (found) {\n return { tier: found.id, seconds: found.seconds, price: found.price, priceAtomic: found.priceAtomic, label: found.label };\n }\n }\n\n // Custom duration\n if (durationParam) {\n const seconds = parseInt(durationParam, 10);\n if (seconds > 0 && ratePerHour) {\n const pricing = calculateCustomPrice(seconds);\n return { tier: 'custom', seconds, ...pricing, label: formatDuration(seconds) };\n }\n }\n\n // Default: cheapest tier or 1h\n if (builtTiers.length > 0) {\n const t = builtTiers[0];\n return { tier: t.id, seconds: t.seconds, price: t.price, priceAtomic: t.priceAtomic, label: t.label };\n }\n\n // Rate-only: default to 1 hour\n const pricing = calculateCustomPrice(3600);\n return { tier: 'custom', seconds: 3600, ...pricing, label: '1 hour' };\n }\n\n // --------------------------------------------------------------------------\n // Middleware handler\n // --------------------------------------------------------------------------\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n // ── Step 1: Check for valid access pass JWT ──\n const auth = req.headers.authorization;\n if (auth?.startsWith('Bearer ')) {\n const claims = verifyJwt(auth.slice(7), secret);\n if (claims) {\n log('Valid access pass:', claims.tier, '| expires:', new Date(claims.exp * 1000).toISOString());\n (req as X402AccessPassRequest).accessPass = {\n tier: claims.tier,\n duration: claims.duration,\n expiresAt: new Date(claims.exp * 1000).toISOString(),\n payer: claims.payer,\n network: claims.network,\n };\n return next();\n }\n log('Invalid or expired access pass token');\n }\n\n // ── Step 2: Check for x402 payment signature (pass purchase) ──\n const paymentSignature = req.headers['payment-signature'] as string | undefined;\n\n if (paymentSignature) {\n log('Payment signature received, verifying for pass purchase...');\n\n // Verify payment\n const verifyResult = await server.verifyPayment(paymentSignature);\n if (!verifyResult.isValid) {\n log('Payment verification failed:', verifyResult.invalidReason);\n res.status(402).json({ error: 'Payment verification failed', reason: verifyResult.invalidReason });\n return;\n }\n\n // Settle payment\n const settleResult = await server.settlePayment(paymentSignature);\n if (!settleResult.success) {\n log('Payment settlement failed:', settleResult.errorReason);\n res.status(402).json({ error: 'Payment settlement failed', reason: settleResult.errorReason });\n return;\n }\n\n log('Payment settled:', settleResult.transaction);\n\n // Determine tier/duration\n const pricing = resolvePricing(req);\n\n // Issue JWT\n const now = Math.floor(Date.now() / 1000);\n const claims: AccessPassClaims = {\n sub: 'x402-access-pass',\n tier: pricing.tier,\n duration: pricing.seconds,\n iat: now,\n exp: now + pricing.seconds,\n payer: verifyResult.payer ?? '',\n network,\n iss: issuer,\n };\n const jwt = signJwt(claims, secret);\n\n // Set x402 payment info on request\n (req as X402AccessPassRequest).x402 = {\n transaction: settleResult.transaction!,\n payer: verifyResult.payer ?? '',\n network,\n };\n\n // Set PAYMENT-RESPONSE header per x402 v2 spec\n const paymentResponseData = {\n success: true,\n transaction: settleResult.transaction!,\n network,\n payer: verifyResult.payer ?? '',\n };\n res.setHeader('PAYMENT-RESPONSE', encodeBase64Json(paymentResponseData));\n\n // Set ACCESS-PASS header with the JWT\n res.setHeader('ACCESS-PASS', jwt);\n\n // Return pass details\n res.json({\n accessPass: {\n token: jwt,\n tier: pricing.tier,\n duration: pricing.label,\n durationSeconds: pricing.seconds,\n expiresAt: new Date((now + pricing.seconds) * 1000).toISOString(),\n usage: 'Include on subsequent requests as: Authorization: Bearer <token>',\n },\n transaction: settleResult.transaction,\n payer: verifyResult.payer,\n });\n return;\n }\n\n // ── Step 3: No pass, no payment — return 402 ──\n log('No access pass or payment, returning 402');\n\n const pricing = resolvePricing(req);\n const amountAtomic = pricing.priceAtomic;\n const resourceUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;\n\n const requirements = await server.buildRequirements({\n amountAtomic,\n resourceUrl,\n description: description || `Access pass: ${pricing.label}`,\n mimeType: 'application/json',\n });\n\n const encoded = server.encodeRequirements(requirements);\n\n res.setHeader('PAYMENT-REQUIRED', encoded);\n res.setHeader('X-ACCESS-PASS-TIERS', passInfoEncoded);\n\n res.status(402).json({\n error: 'Access pass required',\n message: 'Purchase an access pass to unlock unlimited API access for a time window.',\n accepts: requirements.accepts,\n resource: requirements.resource,\n accessPass: {\n tiers: builtTiers.length > 0 ? builtTiers : undefined,\n ratePerHour: ratePerHour || undefined,\n usage: 'Add ?tier=<id> or ?duration=<seconds> to your payment request to choose a pass duration.',\n },\n });\n } catch (error) {\n log('Access pass middleware error:', error);\n res.status(500).json({\n error: 'Payment processing error',\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n };\n}\n","/**\n * Dynamic Pricing for x402\n *\n * Calculate prices based on input length (characters, tokens, etc.)\n * Perfect for LLM/AI endpoints where cost scales with input size.\n *\n * @example\n * ```typescript\n * import { createDynamicPricing } from '@dexterai/x402/server';\n *\n * const pricing = createDynamicPricing({\n * unitSize: 1000, // chars per billing unit\n * ratePerUnit: 0.01, // $0.01 per unit\n * minUsd: 0.01, // floor\n * maxUsd: 10.00, // ceiling (optional)\n * });\n *\n * // Calculate price from input\n * const quote = pricing.calculate(userPrompt);\n * // → { amountAtomic: '23000', usdAmount: 0.023, quoteHash: 'abc...', units: 2.3 }\n *\n * // Validate on retry (prevents prompt manipulation)\n * const isValid = pricing.validateQuote(userPrompt, req.headers['x-quote-hash']);\n * ```\n */\n\nimport { createHmac, randomBytes } from 'crypto';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for dynamic pricing\n */\nexport interface DynamicPricingConfig {\n /**\n * Characters per billing unit.\n * Example: 1000 means every 1000 chars = 1 unit\n */\n unitSize: number;\n\n /**\n * USD per unit.\n * Example: 0.01 means $0.01 per unit\n */\n ratePerUnit: number;\n\n /**\n * Minimum USD amount (floor).\n * Recommended: 0.01 (practical minimum for settlement)\n * @default 0.01\n */\n minUsd?: number;\n\n /**\n * Maximum USD amount (ceiling).\n * Optional - prevents unexpectedly large bills.\n */\n maxUsd?: number;\n\n /**\n * Rounding mode for unit calculation.\n * - 'ceil': Always round up (fair to seller)\n * - 'floor': Always round down (fair to buyer)\n * - 'round': Standard rounding\n * @default 'ceil'\n */\n roundingMode?: 'ceil' | 'floor' | 'round';\n\n /**\n * Token decimals for atomic conversion.\n * @default 6 (USDC)\n */\n decimals?: number;\n}\n\n/**\n * Price quote returned by calculate()\n */\nexport interface PriceQuote {\n /** Amount in atomic units (for buildRequirements) */\n amountAtomic: string;\n\n /** Human-readable USD amount (for display) */\n usdAmount: number;\n\n /**\n * Quote hash for validation.\n * Includes input + config, so config changes invalidate quotes.\n * Client should send this back as X-Quote-Hash header.\n */\n quoteHash: string;\n\n /** Number of billing units */\n units: number;\n\n /** Input length in characters */\n inputLength: number;\n}\n\n/**\n * Dynamic pricing calculator\n */\nexport interface DynamicPricing {\n /** Calculate price from input */\n calculate(input: string): PriceQuote;\n\n /** Validate quote hash (returns true if valid) */\n validateQuote(input: string, quoteHash: string): boolean;\n\n /** Get pricing config (for display) */\n readonly config: Required<DynamicPricingConfig>;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/** Max age for a quote before it's considered stale (seconds) */\nconst QUOTE_MAX_AGE_SECONDS = 300; // 5 minutes\n\n/**\n * Create a dynamic pricing calculator\n */\nexport function createDynamicPricing(config: DynamicPricingConfig): DynamicPricing {\n const fullConfig: Required<DynamicPricingConfig> = {\n unitSize: config.unitSize,\n ratePerUnit: config.ratePerUnit,\n minUsd: config.minUsd ?? 0.01,\n maxUsd: config.maxUsd ?? Infinity,\n roundingMode: config.roundingMode ?? 'ceil',\n decimals: config.decimals ?? 6,\n };\n\n const { unitSize, ratePerUnit, minUsd, maxUsd, roundingMode, decimals } = fullConfig;\n\n // Validate config\n if (unitSize <= 0) throw new Error('unitSize must be positive');\n if (ratePerUnit <= 0) throw new Error('ratePerUnit must be positive');\n if (minUsd < 0) throw new Error('minUsd cannot be negative');\n if (maxUsd < minUsd) throw new Error('maxUsd must be >= minUsd');\n\n // Per-instance HMAC secret — quotes are only valid for this pricing instance.\n // Config changes (new instance) automatically invalidate old quotes.\n const hmacSecret = randomBytes(32);\n\n /**\n * Sign a quote with HMAC-SHA256. Includes input, config, and timestamp\n * so quotes are tamper-proof and time-bounded.\n */\n function signQuote(input: string, timestamp: number): string {\n const configStr = JSON.stringify({\n unitSize,\n ratePerUnit,\n minUsd,\n maxUsd: maxUsd === Infinity ? 'none' : maxUsd,\n roundingMode,\n });\n const data = `${input}|${configStr}|${timestamp}`;\n return createHmac('sha256', hmacSecret).update(data).digest('hex').slice(0, 16);\n }\n\n /**\n * Calculate price from input\n */\n function calculate(input: string): PriceQuote {\n const inputLength = input.length;\n\n // Calculate units based on rounding mode\n const rawUnits = inputLength / unitSize;\n let units: number;\n switch (roundingMode) {\n case 'ceil':\n units = Math.ceil(rawUnits);\n break;\n case 'floor':\n units = Math.floor(rawUnits);\n break;\n case 'round':\n units = Math.round(rawUnits);\n break;\n }\n\n // Ensure at least 1 unit if there's any input\n if (inputLength > 0 && units === 0) {\n units = 1;\n }\n\n // Calculate USD amount\n let usdAmount = units * ratePerUnit;\n\n // Apply min/max\n usdAmount = Math.max(minUsd, usdAmount);\n usdAmount = Math.min(maxUsd, usdAmount);\n\n // Convert to atomic units\n const multiplier = Math.pow(10, decimals);\n const amountAtomic = Math.floor(usdAmount * multiplier).toString();\n\n // Sign quote with HMAC-SHA256 (timestamp-bounded)\n const timestamp = Math.floor(Date.now() / 1000);\n const mac = signQuote(input, timestamp);\n const quoteHash = `${timestamp}.${mac}`;\n\n return {\n amountAtomic,\n usdAmount,\n quoteHash,\n units,\n inputLength,\n };\n }\n\n /**\n * Validate quote hash.\n * Verifies HMAC signature and rejects quotes older than QUOTE_MAX_AGE_SECONDS.\n */\n function validateQuote(input: string, quoteHash: string): boolean {\n if (!quoteHash) return false;\n const dotIndex = quoteHash.indexOf('.');\n if (dotIndex === -1) return false;\n\n const timestamp = parseInt(quoteHash.slice(0, dotIndex), 10);\n const mac = quoteHash.slice(dotIndex + 1);\n if (isNaN(timestamp) || !mac) return false;\n\n // Reject stale quotes\n const age = Math.floor(Date.now() / 1000) - timestamp;\n if (age < 0 || age > QUOTE_MAX_AGE_SECONDS) return false;\n\n // Verify HMAC\n const expectedMac = signQuote(input, timestamp);\n // Constant-time comparison to prevent timing attacks\n if (mac.length !== expectedMac.length) return false;\n let mismatch = 0;\n for (let i = 0; i < mac.length; i++) {\n mismatch |= mac.charCodeAt(i) ^ expectedMac.charCodeAt(i);\n }\n return mismatch === 0;\n }\n\n return {\n calculate,\n validateQuote,\n config: fullConfig,\n };\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Format pricing for display\n * Example: \"from $0.01 per 1,000 chars\"\n */\nexport function formatPricing(config: DynamicPricingConfig): string {\n const rate = config.ratePerUnit.toFixed(2);\n const units = config.unitSize.toLocaleString();\n return `from $${rate} per ${units} chars`;\n}\n\n\n\n","/**\n * Token-Based Pricing for x402\n *\n * Accurate LLM pricing using tiktoken for token counting.\n * Uses real OpenAI model rates for precise cost calculation.\n * \n * Pricing data is sourced from the Model Registry (model-registry.ts).\n *\n * @example\n * ```typescript\n * import { createTokenPricing, MODEL_PRICING } from '@dexterai/x402/server';\n *\n * const pricing = createTokenPricing({\n * model: 'gpt-4o-mini',\n * // Optional overrides:\n * // minUsd: 0.001,\n * // maxUsd: 50.0,\n * });\n *\n * // Calculate price from input\n * const quote = pricing.calculate(userPrompt);\n * // → { amountAtomic: '1500', usdAmount: 0.0015, inputTokens: 100, quoteHash: 'abc...' }\n *\n * // Validate on retry (prevents prompt manipulation)\n * const isValid = pricing.validateQuote(userPrompt, req.headers['x-quote-hash']);\n * ```\n */\n\nimport { createHash } from 'crypto';\nimport { encoding_for_model, get_encoding, type TiktokenModel } from 'tiktoken';\nimport { MODEL_PRICING_MAP } from './model-registry';\n\n// ============================================================================\n// Model Pricing Table\n// ============================================================================\n\n/**\n * Pricing info for a model\n */\nexport interface ModelPricing {\n /** USD per 1M input tokens */\n input: number;\n /** USD per 1M output tokens */\n output: number;\n /** USD per 1M cached input tokens (optional) */\n cached?: number;\n /** Default max output tokens for this model */\n maxTokens: number;\n /** Pricing tier */\n tier: 'fast' | 'standard' | 'reasoning' | 'premium' | 'specialized' | 'custom';\n}\n\n/**\n * OpenAI Model Pricing - USD per million tokens\n * \n * This is now sourced from the Model Registry (model-registry.ts).\n * The registry is the single source of truth for all model information.\n * \n * Updated: January 2026\n */\nexport const MODEL_PRICING: Record<string, ModelPricing> = MODEL_PRICING_MAP as Record<string, ModelPricing>;\n\n// Default model for fallback\nconst DEFAULT_MODEL = 'gpt-4o-mini';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for token-based pricing\n */\nexport interface TokenPricingConfig {\n /**\n * Model name. Used for display and to look up built-in pricing.\n * If not in MODEL_PRICING and no custom rates provided, falls back to gpt-4o-mini rates.\n */\n model?: string;\n\n /**\n * Custom input rate (USD per 1M tokens).\n * Overrides built-in MODEL_PRICING for this model.\n * Use this for Anthropic, Gemini, Mistral, or any custom model.\n */\n inputRate?: number;\n\n /**\n * Custom output rate (USD per 1M tokens).\n * Optional - used for display/info purposes.\n */\n outputRate?: number;\n\n /**\n * Custom max output tokens.\n * @default 4096\n */\n maxTokens?: number;\n\n /**\n * Custom tier label.\n * @default 'custom'\n */\n tier?: 'fast' | 'standard' | 'reasoning' | 'premium' | 'specialized' | 'custom';\n\n /**\n * Custom tokenizer function.\n * If not provided, uses tiktoken (cl100k_base encoding).\n * Use this for models with different tokenization (e.g., Llama, Mistral).\n * \n * @example\n * tokenizer: (text) => llamaTokenizer.encode(text).length\n */\n tokenizer?: (text: string) => number;\n\n /**\n * Minimum USD amount (floor).\n * @default 0.001\n */\n minUsd?: number;\n\n /**\n * Maximum USD amount (ceiling).\n * @default 50.0\n */\n maxUsd?: number;\n\n /**\n * Token decimals for atomic conversion.\n * @default 6 (USDC)\n */\n decimals?: number;\n}\n\n/**\n * Token price quote\n */\nexport interface TokenPriceQuote {\n /** Amount in atomic units (for buildRequirements) */\n amountAtomic: string;\n\n /** Human-readable USD amount */\n usdAmount: number;\n\n /** Number of input tokens */\n inputTokens: number;\n\n /** Model used for pricing */\n model: string;\n\n /** Pricing tier */\n tier: string;\n\n /** Input rate per million tokens */\n inputRatePerMillion: number;\n\n /** Output rate per million tokens */\n outputRatePerMillion: number;\n\n /** Max output tokens for this model */\n maxOutputTokens: number;\n\n /**\n * Quote hash for validation.\n * Client should send this back as X-Quote-Hash header.\n */\n quoteHash: string;\n}\n\n/**\n * Token pricing calculator\n */\nexport interface TokenPricing {\n /** Calculate price from input text */\n calculate(input: string, systemPrompt?: string): TokenPriceQuote;\n\n /** Validate quote hash (returns true if valid) */\n validateQuote(input: string, quoteHash: string): boolean;\n\n /** Count tokens in a string */\n countTokens(input: string): number;\n\n /** Get pricing config */\n readonly config: Required<TokenPricingConfig>;\n\n /** Get model info */\n readonly modelInfo: ModelPricing;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Get tiktoken encoding for a model.\n * Falls back to cl100k_base for unknown models.\n */\nfunction getEncodingForModel(model: string) {\n try {\n return encoding_for_model(model as TiktokenModel);\n } catch {\n // Fall back to cl100k_base (GPT-4/4o family encoding)\n return get_encoding('cl100k_base');\n }\n}\n\n/**\n * Count tokens in a string using tiktoken.\n */\nexport function countTokens(text: string, model: string = DEFAULT_MODEL): number {\n const encoding = getEncodingForModel(model);\n try {\n const tokens = encoding.encode(text);\n return tokens.length;\n } finally {\n encoding.free();\n }\n}\n\n/**\n * Generate a hash of the prompt + pricing config for validation.\n */\nfunction generateQuoteHash(prompt: string, model: string, rate: number, tokens: number): string {\n const configString = JSON.stringify({ model, rate, tokens });\n return createHash('sha256').update(prompt + configString).digest('hex').slice(0, 16);\n}\n\n/**\n * Create a token-based pricing calculator\n */\nexport function createTokenPricing(config: TokenPricingConfig = {}): TokenPricing {\n // Determine model name\n const model = config.model ?? DEFAULT_MODEL;\n \n // Get built-in pricing if available, otherwise use custom or default\n const builtInPricing = MODEL_PRICING[model];\n \n // Build effective model info (custom rates override built-in)\n const modelInfo: ModelPricing = {\n input: config.inputRate ?? builtInPricing?.input ?? MODEL_PRICING[DEFAULT_MODEL].input,\n output: config.outputRate ?? builtInPricing?.output ?? MODEL_PRICING[DEFAULT_MODEL].output,\n maxTokens: config.maxTokens ?? builtInPricing?.maxTokens ?? 4096,\n tier: config.tier ?? builtInPricing?.tier ?? 'custom',\n };\n\n // Custom tokenizer or default tiktoken\n const customTokenizer = config.tokenizer;\n\n const fullConfig: Required<TokenPricingConfig> = {\n model,\n inputRate: modelInfo.input,\n outputRate: modelInfo.output,\n maxTokens: modelInfo.maxTokens,\n tier: modelInfo.tier,\n tokenizer: customTokenizer ?? ((text: string) => countTokens(text, model)),\n minUsd: config.minUsd ?? 0.001,\n maxUsd: config.maxUsd ?? 50.0,\n decimals: config.decimals ?? 6,\n };\n\n const { minUsd, maxUsd, decimals } = fullConfig;\n\n /**\n * Count tokens in text (uses custom tokenizer if provided)\n */\n function countTokensInternal(input: string): number {\n if (customTokenizer) {\n return customTokenizer(input);\n }\n return countTokens(input, model);\n }\n\n /**\n * Calculate price from input\n */\n function calculate(input: string, systemPrompt?: string): TokenPriceQuote {\n // Count input tokens (prompt + system prompt if provided)\n const fullInput = systemPrompt ? `${systemPrompt}\\n\\n${input}` : input;\n const inputTokens = countTokensInternal(fullInput);\n\n // Calculate USD cost based on input tokens only\n // Price = (inputTokens / 1,000,000) × inputRate\n let usdAmount = (inputTokens / 1_000_000) * modelInfo.input;\n\n // Apply min/max caps\n usdAmount = Math.max(usdAmount, minUsd);\n usdAmount = Math.min(usdAmount, maxUsd);\n\n // Convert to atomic units\n const multiplier = Math.pow(10, decimals);\n const amountAtomic = Math.floor(usdAmount * multiplier).toString();\n\n // Generate quote hash for validation\n const quoteHash = generateQuoteHash(input, model, modelInfo.input, inputTokens);\n\n return {\n amountAtomic,\n usdAmount,\n inputTokens,\n model,\n tier: modelInfo.tier,\n inputRatePerMillion: modelInfo.input,\n outputRatePerMillion: modelInfo.output,\n maxOutputTokens: modelInfo.maxTokens,\n quoteHash,\n };\n }\n\n /**\n * Validate quote hash\n */\n function validateQuote(input: string, quoteHash: string): boolean {\n if (!quoteHash) return false;\n const inputTokens = countTokensInternal(input);\n const expectedHash = generateQuoteHash(input, model, modelInfo.input, inputTokens);\n return expectedHash === quoteHash;\n }\n\n return {\n calculate,\n validateQuote,\n countTokens: countTokensInternal,\n config: fullConfig,\n modelInfo,\n };\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Get list of available models with their pricing.\n */\nexport function getAvailableModels(): Array<{\n model: string;\n inputRate: number;\n outputRate: number;\n maxTokens: number;\n tier: string;\n}> {\n return Object.entries(MODEL_PRICING)\n .map(([model, pricing]) => ({\n model,\n inputRate: pricing.input,\n outputRate: pricing.output,\n maxTokens: pricing.maxTokens,\n tier: pricing.tier,\n }))\n .sort((a, b) => {\n // Sort by tier, then by input rate\n const tierOrder = { fast: 0, standard: 1, reasoning: 2, premium: 3 };\n const tierDiff = tierOrder[a.tier as keyof typeof tierOrder] - tierOrder[b.tier as keyof typeof tierOrder];\n if (tierDiff !== 0) return tierDiff;\n return a.inputRate - b.inputRate;\n });\n}\n\n/**\n * Check if a model exists in our pricing.\n */\nexport function isValidModel(model: string): boolean {\n return model in MODEL_PRICING;\n}\n\n/**\n * Format token pricing for display\n * Example: \"$0.15 per 1M tokens (gpt-4o-mini)\"\n */\nexport function formatTokenPricing(model: string = DEFAULT_MODEL): string {\n const pricing = MODEL_PRICING[model] ?? MODEL_PRICING[DEFAULT_MODEL];\n const actualModel = MODEL_PRICING[model] ? model : DEFAULT_MODEL;\n return `$${pricing.input.toFixed(2)} per 1M tokens (${actualModel})`;\n}\n\n","/**\n * OpenAI Model Registry\n * \n * The single source of truth for all OpenAI models.\n * Contains pricing, capabilities, API requirements, and constraints.\n * \n * Updated: January 2026\n * Source: https://platform.openai.com/docs/pricing\n * \n * @example\n * ```typescript\n * import { ModelRegistry, getModel, getModelsByTier } from '@dexterai/x402/server';\n * \n * // Get a specific model\n * const model = getModel('gpt-4o-mini');\n * console.log(model.pricing.input); // 0.15\n * \n * // Get all reasoning models\n * const reasoners = getModelsByTier('reasoning');\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Model capability tiers, ordered by general capability level\n */\nexport type ModelTier = \n | 'fast' // Cheapest, fastest, good for simple tasks\n | 'standard' // Balanced price/performance\n | 'reasoning' // Chain-of-thought reasoning (o-series)\n | 'premium' // Most capable, expensive\n | 'specialized'; // Special purpose (computer use, deep research, etc.)\n\n/**\n * What the model can process/generate\n */\nexport type ModelModality = 'text' | 'vision' | 'audio' | 'realtime' | 'image' | 'video';\n\n/**\n * API endpoint type\n */\nexport type ModelApiType = 'chat' | 'completion' | 'responses';\n\n/**\n * Pricing per 1M tokens (USD)\n */\nexport interface ModelPricing {\n /** Input token cost per 1M */\n input: number;\n /** Output token cost per 1M */\n output: number;\n /** Cached input token cost per 1M (if supported) */\n cached?: number;\n}\n\n/**\n * What parameters the model accepts\n */\nexport interface ModelParameters {\n /** Uses max_completion_tokens instead of max_tokens */\n usesMaxCompletionTokens: boolean;\n /** Supports temperature parameter */\n supportsTemperature: boolean;\n /** Supports top_p parameter */\n supportsTopP: boolean;\n /** Supports frequency_penalty */\n supportsFrequencyPenalty: boolean;\n /** Supports presence_penalty */\n supportsPresencePenalty: boolean;\n /** Supports reasoning_effort parameter */\n supportsReasoningEffort: boolean;\n /** Supports streaming */\n supportsStreaming: boolean;\n /** Supports system messages */\n supportsSystemMessage: boolean;\n /** Supports function/tool calling */\n supportsTools: boolean;\n /** Supports structured outputs (JSON mode) */\n supportsStructuredOutput: boolean;\n}\n\n/**\n * Complete model definition\n */\nexport interface ModelDefinition {\n /** Model ID as used in API calls */\n id: string;\n /** Human-readable display name */\n displayName: string;\n /** Model family (gpt-4o, gpt-5, o1, o3, etc.) */\n family: string;\n /** Capability tier */\n tier: ModelTier;\n /** Capability rank within tier (1 = lowest, 10 = highest) */\n capabilityRank: number;\n /** What it can process */\n modalities: ModelModality[];\n /** API type */\n apiType: ModelApiType;\n /** Pricing per 1M tokens */\n pricing: ModelPricing;\n /** Context window size (tokens) */\n contextWindow: number;\n /** Default max output tokens */\n defaultMaxOutput: number;\n /** Maximum output tokens allowed */\n maxOutputTokens: number;\n /** Parameter support */\n parameters: ModelParameters;\n /** Is this model deprecated? */\n deprecated: boolean;\n /** Brief description */\n description: string;\n}\n\n// ============================================================================\n// Default Parameter Profiles\n// ============================================================================\n\n/** Standard chat model parameters (GPT-4o, GPT-4.1 family) */\nconst STANDARD_PARAMS: ModelParameters = {\n usesMaxCompletionTokens: false,\n supportsTemperature: true,\n supportsTopP: true,\n supportsFrequencyPenalty: true,\n supportsPresencePenalty: true,\n supportsReasoningEffort: false,\n supportsStreaming: true,\n supportsSystemMessage: true,\n supportsTools: true,\n supportsStructuredOutput: true,\n};\n\n/** GPT-5 family parameters - uses max_completion_tokens, no temperature */\nconst GPT5_PARAMS: ModelParameters = {\n usesMaxCompletionTokens: true, // GPT-5 requires this!\n supportsTemperature: false, // Only default (1) is supported\n supportsTopP: false, // Likely same restriction\n supportsFrequencyPenalty: false,\n supportsPresencePenalty: false,\n supportsReasoningEffort: false,\n supportsStreaming: true,\n supportsSystemMessage: true,\n supportsTools: true,\n supportsStructuredOutput: true,\n};\n\n/** Reasoning model parameters (o1, o3, o4 series) */\nconst REASONING_PARAMS: ModelParameters = {\n usesMaxCompletionTokens: true,\n supportsTemperature: false, // Fixed at 1\n supportsTopP: false,\n supportsFrequencyPenalty: false,\n supportsPresencePenalty: false,\n supportsReasoningEffort: true,\n supportsStreaming: true,\n supportsSystemMessage: true, // Developer message\n supportsTools: true,\n supportsStructuredOutput: true,\n};\n\n/** Pro/Premium reasoning model parameters */\nconst PRO_REASONING_PARAMS: ModelParameters = {\n ...REASONING_PARAMS,\n supportsStreaming: false, // Pro models may not stream\n};\n\n// ============================================================================\n// Model Registry\n// ============================================================================\n\n/**\n * Complete registry of all OpenAI models\n * Ordered by tier, then by capability rank (ascending)\n */\nexport const MODEL_REGISTRY: ModelDefinition[] = [\n // =========================================================================\n // FAST TIER - Cheapest, fastest, good for simple tasks\n // =========================================================================\n {\n id: 'gpt-4o-mini',\n displayName: 'GPT-4o Mini',\n family: 'gpt-4o',\n tier: 'fast',\n capabilityRank: 3,\n modalities: ['text', 'vision'],\n apiType: 'chat',\n pricing: { input: 0.15, output: 0.60, cached: 0.075 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Fast, affordable small model with vision support',\n },\n {\n id: 'gpt-4.1-nano',\n displayName: 'GPT-4.1 Nano',\n family: 'gpt-4.1',\n tier: 'fast',\n capabilityRank: 2,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.10, output: 0.40, cached: 0.025 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 32768,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Smallest 4.1 model, very fast and cheap',\n },\n {\n id: 'gpt-4.1-mini',\n displayName: 'GPT-4.1 Mini',\n family: 'gpt-4.1',\n tier: 'fast',\n capabilityRank: 4,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.40, output: 1.60, cached: 0.10 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 32768,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Balanced 4.1 model, good price/performance',\n },\n {\n id: 'gpt-5-nano',\n displayName: 'GPT-5 Nano',\n family: 'gpt-5',\n tier: 'fast',\n capabilityRank: 1,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.05, output: 0.40, cached: 0.005 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Cheapest GPT-5 variant, extremely fast',\n },\n {\n id: 'gpt-5-mini',\n displayName: 'GPT-5 Mini',\n family: 'gpt-5',\n tier: 'fast',\n capabilityRank: 5,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.25, output: 2.00, cached: 0.025 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Small but capable GPT-5, great value',\n },\n\n // =========================================================================\n // STANDARD TIER - Balanced price/performance\n // =========================================================================\n {\n id: 'gpt-4o',\n displayName: 'GPT-4o',\n family: 'gpt-4o',\n tier: 'standard',\n capabilityRank: 5,\n modalities: ['text', 'vision'],\n apiType: 'chat',\n pricing: { input: 2.50, output: 10.00, cached: 1.25 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Flagship multimodal model with vision',\n },\n {\n id: 'gpt-4.1',\n displayName: 'GPT-4.1',\n family: 'gpt-4.1',\n tier: 'standard',\n capabilityRank: 6,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 2.00, output: 8.00, cached: 0.50 },\n contextWindow: 1000000, // 1M context!\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Long context specialist, 1M token window',\n },\n {\n id: 'gpt-5',\n displayName: 'GPT-5',\n family: 'gpt-5',\n tier: 'standard',\n capabilityRank: 7,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.25, output: 10.00, cached: 0.125 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Base GPT-5, excellent all-around',\n },\n {\n id: 'gpt-5.1',\n displayName: 'GPT-5.1',\n family: 'gpt-5',\n tier: 'standard',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.25, output: 10.00, cached: 0.125 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Improved GPT-5 with better instruction following',\n },\n {\n id: 'gpt-5.2',\n displayName: 'GPT-5.2',\n family: 'gpt-5',\n tier: 'standard',\n capabilityRank: 9,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.75, output: 14.00, cached: 0.175 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Latest GPT-5, most capable standard model',\n },\n\n // =========================================================================\n // REASONING TIER - Chain-of-thought reasoning (o-series)\n // =========================================================================\n {\n id: 'o1-mini',\n displayName: 'o1 Mini',\n family: 'o1',\n tier: 'reasoning',\n capabilityRank: 3,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.10, output: 4.40, cached: 0.55 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Fast reasoning model, good for math/code',\n },\n {\n id: 'o3-mini',\n displayName: 'o3 Mini',\n family: 'o3',\n tier: 'reasoning',\n capabilityRank: 4,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.10, output: 4.40, cached: 0.55 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Improved mini reasoner with better efficiency',\n },\n {\n id: 'o4-mini',\n displayName: 'o4 Mini',\n family: 'o4',\n tier: 'reasoning',\n capabilityRank: 5,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.10, output: 4.40, cached: 0.275 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Latest mini reasoner, best reasoning per dollar',\n },\n {\n id: 'o3',\n displayName: 'o3',\n family: 'o3',\n tier: 'reasoning',\n capabilityRank: 7,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 2.00, output: 8.00, cached: 0.50 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Full o3 reasoning model, excellent for complex problems',\n },\n {\n id: 'o1',\n displayName: 'o1',\n family: 'o1',\n tier: 'reasoning',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 15.00, output: 60.00, cached: 7.50 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Original full reasoning model, very capable',\n },\n\n // =========================================================================\n // PREMIUM TIER - Most capable, expensive\n // =========================================================================\n {\n id: 'gpt-5-pro',\n displayName: 'GPT-5 Pro',\n family: 'gpt-5',\n tier: 'premium',\n capabilityRank: 7,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 15.00, output: 120.00 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Enhanced GPT-5 for demanding tasks',\n },\n {\n id: 'gpt-5.2-pro',\n displayName: 'GPT-5.2 Pro',\n family: 'gpt-5',\n tier: 'premium',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 21.00, output: 168.00 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Most capable standard model available',\n },\n {\n id: 'o3-pro',\n displayName: 'o3 Pro',\n family: 'o3',\n tier: 'premium',\n capabilityRank: 9,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 20.00, output: 80.00 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: PRO_REASONING_PARAMS,\n deprecated: false,\n description: 'Premium o3 with extended thinking time',\n },\n {\n id: 'o1-pro',\n displayName: 'o1 Pro',\n family: 'o1',\n tier: 'premium',\n capabilityRank: 10,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 150.00, output: 600.00 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: PRO_REASONING_PARAMS,\n deprecated: false,\n description: 'Most capable reasoning model, extended compute',\n },\n\n // =========================================================================\n // SPECIALIZED TIER - Special purpose models\n // =========================================================================\n {\n id: 'o3-deep-research',\n displayName: 'o3 Deep Research',\n family: 'o3',\n tier: 'specialized',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'responses',\n pricing: { input: 10.00, output: 40.00, cached: 2.50 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: {\n ...REASONING_PARAMS,\n supportsStreaming: false,\n },\n deprecated: false,\n description: 'Extended research sessions with web access',\n },\n {\n id: 'o4-mini-deep-research',\n displayName: 'o4 Mini Deep Research',\n family: 'o4',\n tier: 'specialized',\n capabilityRank: 6,\n modalities: ['text'],\n apiType: 'responses',\n pricing: { input: 2.00, output: 8.00, cached: 0.50 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: {\n ...REASONING_PARAMS,\n supportsStreaming: false,\n },\n deprecated: false,\n description: 'Affordable deep research with o4 mini',\n },\n {\n id: 'computer-use-preview',\n displayName: 'Computer Use Preview',\n family: 'computer-use',\n tier: 'specialized',\n capabilityRank: 5,\n modalities: ['text', 'vision'],\n apiType: 'responses',\n pricing: { input: 3.00, output: 12.00 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: {\n ...STANDARD_PARAMS,\n supportsReasoningEffort: false,\n },\n deprecated: false,\n description: 'Can control computer interfaces via screenshots',\n },\n\n // =========================================================================\n // REALTIME TIER - Real-time audio/video\n // =========================================================================\n {\n id: 'gpt-realtime',\n displayName: 'GPT Realtime',\n family: 'gpt-realtime',\n tier: 'specialized',\n capabilityRank: 7,\n modalities: ['text', 'audio', 'realtime'],\n apiType: 'chat',\n pricing: { input: 4.00, output: 16.00, cached: 0.40 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 4096,\n parameters: {\n ...STANDARD_PARAMS,\n supportsReasoningEffort: false,\n },\n deprecated: false,\n description: 'Real-time audio conversation model',\n },\n {\n id: 'gpt-realtime-mini',\n displayName: 'GPT Realtime Mini',\n family: 'gpt-realtime',\n tier: 'specialized',\n capabilityRank: 4,\n modalities: ['text', 'audio', 'realtime'],\n apiType: 'chat',\n pricing: { input: 0.60, output: 2.40, cached: 0.06 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 4096,\n parameters: {\n ...STANDARD_PARAMS,\n supportsReasoningEffort: false,\n },\n deprecated: false,\n description: 'Affordable real-time audio model',\n },\n\n // =========================================================================\n // LEGACY MODELS - Still available but older\n // =========================================================================\n {\n id: 'gpt-4o-2024-05-13',\n displayName: 'GPT-4o (May 2024)',\n family: 'gpt-4o',\n tier: 'standard',\n capabilityRank: 4,\n modalities: ['text', 'vision'],\n apiType: 'chat',\n pricing: { input: 5.00, output: 15.00 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 4096,\n parameters: STANDARD_PARAMS,\n deprecated: true,\n description: 'Original GPT-4o snapshot, use gpt-4o instead',\n },\n];\n\n// ============================================================================\n// Lookup Functions\n// ============================================================================\n\n/** Map for O(1) lookup by model ID */\nconst MODEL_MAP = new Map<string, ModelDefinition>(\n MODEL_REGISTRY.map(m => [m.id, m])\n);\n\n/**\n * Get a model by ID\n * @throws if model not found\n */\nexport function getModel(modelId: string): ModelDefinition {\n const model = MODEL_MAP.get(modelId);\n if (!model) {\n throw new Error(`Unknown model: ${modelId}. Use getAvailableModelIds() to see valid options.`);\n }\n return model;\n}\n\n/**\n * Get a model by ID, returns undefined if not found\n */\nexport function findModel(modelId: string): ModelDefinition | undefined {\n return MODEL_MAP.get(modelId);\n}\n\n/**\n * Check if a model ID is valid\n */\nexport function isValidModelId(modelId: string): boolean {\n return MODEL_MAP.has(modelId);\n}\n\n/**\n * Get all model IDs\n */\nexport function getAvailableModelIds(): string[] {\n return MODEL_REGISTRY.map(m => m.id);\n}\n\n/**\n * Get all models in a specific tier\n */\nexport function getModelsByTier(tier: ModelTier): ModelDefinition[] {\n return MODEL_REGISTRY\n .filter(m => m.tier === tier && !m.deprecated)\n .sort((a, b) => a.capabilityRank - b.capabilityRank);\n}\n\n/**\n * Get all models in a specific family\n */\nexport function getModelsByFamily(family: string): ModelDefinition[] {\n return MODEL_REGISTRY\n .filter(m => m.family === family)\n .sort((a, b) => a.capabilityRank - b.capabilityRank);\n}\n\n/**\n * Get all non-deprecated models, ordered by tier then capability\n */\nexport function getActiveModels(): ModelDefinition[] {\n const tierOrder: Record<ModelTier, number> = {\n fast: 1,\n standard: 2,\n reasoning: 3,\n premium: 4,\n specialized: 5,\n };\n \n return MODEL_REGISTRY\n .filter(m => !m.deprecated)\n .sort((a, b) => {\n const tierDiff = tierOrder[a.tier] - tierOrder[b.tier];\n if (tierDiff !== 0) return tierDiff;\n return a.capabilityRank - b.capabilityRank;\n });\n}\n\n/**\n * Get models suitable for text generation testing\n * (excludes realtime, audio-only, etc.)\n */\nexport function getTextModels(): ModelDefinition[] {\n return MODEL_REGISTRY\n .filter(m => \n !m.deprecated && \n m.modalities.includes('text') &&\n !m.modalities.includes('realtime') &&\n m.apiType !== 'responses' // Standard chat API\n )\n .sort((a, b) => {\n const tierOrder: Record<ModelTier, number> = {\n fast: 1, standard: 2, reasoning: 3, premium: 4, specialized: 5\n };\n const tierDiff = tierOrder[a.tier] - tierOrder[b.tier];\n if (tierDiff !== 0) return tierDiff;\n return a.capabilityRank - b.capabilityRank;\n });\n}\n\n/**\n * Get the cheapest model that meets minimum capability requirements\n */\nexport function getCheapestModel(minTier: ModelTier = 'fast'): ModelDefinition {\n const tierOrder: Record<ModelTier, number> = {\n fast: 1, standard: 2, reasoning: 3, premium: 4, specialized: 5\n };\n const minTierNum = tierOrder[minTier];\n \n const candidates = MODEL_REGISTRY\n .filter(m => !m.deprecated && tierOrder[m.tier] >= minTierNum)\n .sort((a, b) => a.pricing.input - b.pricing.input);\n \n return candidates[0];\n}\n\n/**\n * Estimate cost for a request\n */\nexport function estimateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n useCached: boolean = false\n): number {\n const model = getModel(modelId);\n const inputCost = useCached && model.pricing.cached\n ? (inputTokens / 1_000_000) * model.pricing.cached\n : (inputTokens / 1_000_000) * model.pricing.input;\n const outputCost = (outputTokens / 1_000_000) * model.pricing.output;\n return inputCost + outputCost;\n}\n\n/**\n * Format pricing for display\n */\nexport function formatModelPricing(modelId: string): string {\n const model = getModel(modelId);\n return `$${model.pricing.input.toFixed(2)} in / $${model.pricing.output.toFixed(2)} out per 1M tokens`;\n}\n\n// ============================================================================\n// Export a simple pricing map for backwards compatibility\n// ============================================================================\n\n/**\n * Simple pricing map for token-pricing.ts compatibility\n */\nexport const MODEL_PRICING_MAP: Record<string, {\n input: number;\n output: number;\n cached?: number;\n maxTokens: number;\n tier: string;\n}> = Object.fromEntries(\n MODEL_REGISTRY.map(m => [m.id, {\n input: m.pricing.input,\n output: m.pricing.output,\n cached: m.pricing.cached,\n maxTokens: m.defaultMaxOutput,\n tier: m.tier,\n }])\n);\n","/**\n * Stripe Machine Payments — PayTo Provider\n *\n * Generates per-request Stripe deposit addresses via PaymentIntents.\n * Payments land in your Stripe Dashboard with full reporting, taxes, and refunds.\n *\n * Requires `stripe` npm package as a peer dependency.\n *\n * @example\n * ```typescript\n * import { x402Middleware, stripePayTo } from '@dexterai/x402/server';\n *\n * app.use('/api/data', x402Middleware({\n * amount: '0.01',\n * payTo: stripePayTo(process.env.STRIPE_SECRET_KEY),\n * }));\n * ```\n *\n * @see https://docs.stripe.com/payments/machine\n */\n\nimport type { PayToContext, PayToProvider } from '../types';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for the Stripe PayTo provider.\n */\nexport interface StripePayToConfig {\n /** Stripe secret key (sk_test_... or sk_live_...) */\n secretKey: string;\n\n /**\n * Stripe API version to use.\n * @default '2026-01-28.clover'\n */\n apiVersion?: string;\n\n /**\n * Target network for deposit addresses.\n * - 'base' → Base mainnet (eip155:8453)\n * - 'base-sepolia' → Base Sepolia testnet (eip155:84532)\n * @default 'base'\n */\n network?: 'base' | 'base-sepolia';\n}\n\n// Map our network names to Stripe deposit_addresses keys\nconst STRIPE_NETWORK_KEYS: Record<string, string> = {\n 'base': 'base',\n 'base-sepolia': 'base_sepolia',\n};\n\n// Map our network names to CAIP-2 identifiers\nconst CAIP2_NETWORKS: Record<string, string> = {\n 'base': 'eip155:8453',\n 'base-sepolia': 'eip155:84532',\n};\n\n// USDC has 6 decimals\nconst USDC_DECIMALS = 6;\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Create a Stripe-backed PayTo provider for x402 machine payments.\n *\n * On each new request, creates a Stripe PaymentIntent with a crypto deposit address.\n * When the agent sends USDC to that address, Stripe auto-captures the payment.\n * Payments appear in your Stripe Dashboard like any other transaction.\n *\n * @param secretKeyOrConfig - Stripe secret key string, or full config object\n * @returns A PayToProvider function with auto-configuration defaults\n *\n * @example Minimal usage\n * ```typescript\n * const provider = stripePayTo('sk_test_...');\n * ```\n *\n * @example With config\n * ```typescript\n * const provider = stripePayTo({\n * secretKey: 'sk_test_...',\n * network: 'base-sepolia', // testnet\n * });\n * ```\n */\nexport function stripePayTo(\n secretKeyOrConfig: string | StripePayToConfig,\n): PayToProvider {\n const config: StripePayToConfig =\n typeof secretKeyOrConfig === 'string'\n ? { secretKey: secretKeyOrConfig }\n : secretKeyOrConfig;\n\n const networkName = config.network ?? 'base';\n const stripeNetworkKey = STRIPE_NETWORK_KEYS[networkName] ?? 'base';\n const caip2Network = CAIP2_NETWORKS[networkName] ?? 'eip155:8453';\n const apiVersion = config.apiVersion ?? '2026-01-28.clover';\n\n // Lazy-loaded Stripe client (avoids import errors when stripe isn't installed).\n // Typed via import('stripe') so we get real Stripe SDK types.\n let stripeClient: import('stripe').default | null = null;\n\n async function getStripe(): Promise<import('stripe').default> {\n if (stripeClient) return stripeClient;\n\n try {\n const { default: Stripe } = await import('stripe');\n stripeClient = new Stripe(config.secretKey, {\n apiVersion: apiVersion as import('stripe').Stripe.LatestApiVersion,\n appInfo: {\n name: '@dexterai/x402',\n url: 'https://dexter.cash/sdk',\n },\n });\n return stripeClient;\n } catch {\n throw new Error(\n 'The \"stripe\" package is required for stripePayTo(). ' +\n 'Install it with: npm install stripe',\n );\n }\n }\n\n // The provider function\n const provider: PayToProvider = async (context: PayToContext): Promise<string> => {\n // ---------------------------------------------------------------\n // Retry path: extract the deposit address from the payment header\n // ---------------------------------------------------------------\n if (context.paymentHeader) {\n try {\n const decoded = JSON.parse(\n Buffer.from(context.paymentHeader, 'base64').toString(),\n );\n // EVM: address is in payload.authorization.to\n const toAddress = decoded.payload?.authorization?.to;\n if (toAddress && typeof toAddress === 'string') {\n return toAddress;\n }\n // Fallback: check accepted.payTo\n const acceptedPayTo = decoded.accepted?.payTo;\n if (acceptedPayTo && typeof acceptedPayTo === 'string') {\n return acceptedPayTo;\n }\n } catch {\n // Fall through to error\n }\n throw new Error(\n 'Could not extract deposit address from payment header. ' +\n 'Ensure the client is sending a valid x402 PAYMENT-SIGNATURE.',\n );\n }\n\n // ---------------------------------------------------------------\n // Initial path: create a Stripe PaymentIntent for a deposit address\n // ---------------------------------------------------------------\n const stripe = await getStripe();\n\n // Convert atomic USDC to Stripe cents\n // 10000 atomic USDC (6 decimals) = 0.01 USDC = $0.01 = 1 cent\n const amountAtomic = context.amountAtomic ? parseInt(context.amountAtomic, 10) : 10000;\n const amountInCents = Math.max(1, Math.round(amountAtomic / Math.pow(10, USDC_DECIMALS - 2)));\n\n // Stripe's crypto payment types aren't fully in the base SDK typedefs yet.\n // We pass the create params through a Record to avoid type errors on\n // crypto-specific fields (payment_method_types, payment_method_options).\n const paymentIntent = await stripe.paymentIntents.create({\n amount: amountInCents,\n currency: 'usd',\n payment_method_types: ['crypto'],\n payment_method_data: { type: 'crypto' },\n payment_method_options: {\n crypto: { mode: 'custom' },\n } as Record<string, unknown>,\n confirm: true,\n });\n\n // Extract the deposit address from the PaymentIntent's next_action.\n // Stripe's crypto deposit types aren't in the base SDK yet, so we use\n // a structural cast for the crypto-specific fields.\n const nextAction = paymentIntent.next_action as {\n crypto_collect_deposit_details?: {\n deposit_addresses?: Record<string, { address?: string }>;\n };\n } | null;\n if (!nextAction?.crypto_collect_deposit_details) {\n throw new Error(\n 'Stripe PaymentIntent did not return crypto deposit details. ' +\n 'Ensure your Stripe account has crypto payins enabled: ' +\n 'https://support.stripe.com/questions/get-started-with-pay-with-crypto',\n );\n }\n\n const depositDetails = nextAction.crypto_collect_deposit_details;\n const payToAddress: string | undefined =\n depositDetails.deposit_addresses?.[stripeNetworkKey]?.address;\n\n if (!payToAddress) {\n throw new Error(\n `No deposit address found for network \"${stripeNetworkKey}\". ` +\n `Available networks: ${Object.keys(depositDetails.deposit_addresses || {}).join(', ')}`,\n );\n }\n\n return payToAddress;\n };\n\n // Attach auto-configuration defaults so the middleware can set\n // network and facilitator automatically when Stripe is used\n provider._x402Defaults = {\n network: caip2Network,\n facilitatorUrl: 'https://x402.dexter.cash',\n };\n\n // Guard: Stripe only supports Base networks. Throw early if misconfigured\n // with multi-network middleware on non-Base chains.\n (provider as any)._stripeNetwork = caip2Network;\n\n return provider;\n}\n"],"mappings":"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","names":["crypto","DEFAULT_NETWORK","USDC_DECIMALS","pricing","import_crypto","import_crypto","USDC_DECIMALS"]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/index.ts","../../src/types.ts","../../src/utils.ts","../../src/server/facilitator-client.ts","../../src/server/x402-server.ts","../../src/server/stripe-payto.ts","../../src/server/middleware.ts","../../src/server/browser-support.ts","../../src/server/access-pass.ts","../../src/server/dynamic-pricing.ts","../../src/server/token-pricing.ts","../../src/server/model-registry.ts"],"sourcesContent":["/**\n * @dexterai/x402 Server\n *\n * Server-side helpers for accepting x402 payments.\n * Works with any x402 v2 facilitator.\n *\n * @example Express Middleware (recommended)\n * ```typescript\n * import express from 'express';\n * import { x402Middleware } from '@dexterai/x402/server';\n *\n * const app = express();\n *\n * // One-liner payment protection\n * app.get('/api/protected',\n * x402Middleware({\n * payTo: 'YourSolanaAddress...',\n * amount: '0.01', // $0.01 USD\n * }),\n * (req, res) => {\n * // This only runs after successful payment\n * res.json({ data: 'protected content' });\n * }\n * );\n * ```\n *\n * @example Manual Server (advanced)\n * ```typescript\n * import { createX402Server } from '@dexterai/x402/server';\n *\n * const server = createX402Server({\n * payTo: 'YourSolanaAddress...',\n * network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n * });\n *\n * app.post('/protected', async (req, res) => {\n * const paymentSig = req.headers['payment-signature'];\n *\n * if (!paymentSig) {\n * const requirements = await server.buildRequirements({\n * amountAtomic: '50000',\n * resourceUrl: req.originalUrl,\n * });\n * res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));\n * return res.status(402).json({});\n * }\n *\n * const result = await server.settlePayment(paymentSig);\n * if (!result.success) {\n * return res.status(402).json({ error: result.errorReason });\n * }\n *\n * res.json({ data: 'protected content', transaction: result.transaction });\n * });\n * ```\n */\n\nexport { createX402Server } from './x402-server';\nexport type {\n X402ServerConfig,\n X402Server,\n BuildRequirementsOptions,\n AssetConfig,\n} from './x402-server';\n\n// Express middleware\nexport { x402Middleware } from './middleware';\nexport type { X402MiddlewareConfig, X402Request } from './middleware';\n\n// Browser support -- renders HTML paywall for browser 402 responses\nexport { x402BrowserSupport } from './browser-support';\nexport type { X402BrowserSupportConfig } from './browser-support';\n\n// Access pass middleware\nexport { x402AccessPass } from './access-pass';\nexport type { X402AccessPassConfig, X402AccessPassRequest } from './access-pass';\n\nexport { FacilitatorClient, type SupportedKind, type SupportedResponse } from './facilitator-client';\n\n// Dynamic pricing (character-based)\nexport { createDynamicPricing, formatPricing } from './dynamic-pricing';\nexport type { DynamicPricingConfig, DynamicPricing, PriceQuote } from './dynamic-pricing';\n\n// Token pricing (LLM-accurate with tiktoken)\nexport { \n createTokenPricing, \n countTokens, \n getAvailableModels, \n isValidModel, \n formatTokenPricing,\n MODEL_PRICING,\n} from './token-pricing';\nexport type { \n TokenPricingConfig, \n TokenPricing, \n TokenPriceQuote, \n ModelPricing,\n} from './token-pricing';\n\n// Model Registry - the single source of truth for all OpenAI models\nexport {\n MODEL_REGISTRY,\n MODEL_PRICING_MAP,\n getModel,\n findModel,\n isValidModelId,\n getAvailableModelIds,\n getModelsByTier,\n getModelsByFamily,\n getActiveModels,\n getTextModels,\n getCheapestModel,\n estimateCost,\n formatModelPricing,\n} from './model-registry';\nexport type {\n ModelTier,\n ModelModality,\n ModelApiType,\n ModelPricing as RegistryModelPricing,\n ModelParameters,\n ModelDefinition,\n} from './model-registry';\n\n// Stripe machine payments\nexport { stripePayTo } from './stripe-payto';\nexport type { StripePayToConfig } from './stripe-payto';\n\n// Sponsored Access (Ads for Agents) types — re-exported from @dexterai/x402-ads-types\nexport type {\n SponsoredRecommendation,\n SponsoredAccessSettlementInfo,\n SponsoredAccessPaymentRequiredInfo,\n SponsoredAccessClientConsent,\n} from '@dexterai/x402-ads-types';\nexport { SPONSORED_ACCESS_EXTENSION_KEY } from '@dexterai/x402-ads-types';\n\n// Re-export types for convenience\nexport type { VerifyResponse, SettleResponse, PaymentRequired, PaymentAccept, PayToContext, PayToProvider, PayToProviderDefaults, AccessPassTier, AccessPassInfo, AccessPassClaims, AccessPassClientConfig } from '../types';\nexport { DEXTER_FACILITATOR_URL, SOLANA_MAINNET_NETWORK, BASE_MAINNET_NETWORK, USDC_MINT, USDC_BASE } from '../types';\n","/**\n * x402 v2 SDK — Shared Types\n *\n * Chain-agnostic types for x402 v2 payments.\n * Works with Solana, Base, and any future x402-compatible networks.\n */\n\n// ============================================================================\n// Network Constants\n// ============================================================================\n\n/** CAIP-2 network identifier for Solana mainnet */\nexport const SOLANA_MAINNET_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n/** CAIP-2 network identifier for Base mainnet */\nexport const BASE_MAINNET_NETWORK = 'eip155:8453';\n\n/** Alias for Solana mainnet */\nexport const SOLANA_MAINNET = SOLANA_MAINNET_NETWORK;\n\n/** Alias for Base mainnet */\nexport const BASE_MAINNET = BASE_MAINNET_NETWORK;\n\n// ============================================================================\n// Asset Constants\n// ============================================================================\n\n/** USDC mint on Solana mainnet */\nexport const USDC_MINT = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';\n\n/** USDC address on Base mainnet */\nexport const USDC_BASE = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\n\n// ============================================================================\n// Facilitator Constants\n// ============================================================================\n\n/** Dexter's public x402 v2 facilitator URL */\nexport const DEXTER_FACILITATOR_URL = 'https://x402.dexter.cash';\n\n// ============================================================================\n// PayTo Provider Types (for dynamic address resolution, e.g. Stripe)\n// ============================================================================\n\n/**\n * Context passed to a PayToProvider function.\n * Contains request-scoped information for dynamic address resolution.\n */\nexport interface PayToContext {\n /** The PAYMENT-SIGNATURE header value (present on retry/verify, undefined on initial 402) */\n paymentHeader?: string;\n /** Amount in atomic units (e.g., '10000' for 0.01 USDC) */\n amountAtomic?: string;\n /** The resource URL being accessed */\n resourceUrl?: string;\n}\n\n/**\n * Optional defaults a PayToProvider can advertise for auto-configuration.\n * Attached as `_x402Defaults` on the provider function.\n */\nexport interface PayToProviderDefaults {\n /** Default CAIP-2 network (e.g., 'eip155:8453' for Base) */\n network?: string;\n /** Default facilitator URL */\n facilitatorUrl?: string;\n}\n\n/**\n * A function that dynamically resolves a payment address.\n * Used for providers like Stripe that generate per-request deposit addresses.\n *\n * @example\n * ```typescript\n * import { stripePayTo } from '@dexterai/x402/server';\n *\n * const provider = stripePayTo(process.env.STRIPE_SECRET_KEY);\n * const address = await provider({ amountAtomic: '10000' });\n * ```\n */\nexport type PayToProvider = ((context: PayToContext) => Promise<string>) & {\n /** Auto-configuration defaults (set by provider factories like stripePayTo) */\n _x402Defaults?: PayToProviderDefaults;\n};\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/**\n * Asset configuration for payments\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n /** Optional: Human-readable symbol */\n symbol?: string;\n}\n\n/**\n * Resource info included in payment requirements\n */\nexport interface ResourceInfo {\n /** Resource URL */\n url: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the resource */\n mimeType?: string;\n}\n\n/**\n * Extra fields in payment requirements\n * Chain-specific fields may vary\n */\nexport interface AcceptsExtra {\n /** Facilitator address that pays tx fees (required for Solana) */\n feePayer?: string;\n /** Token decimals (optional - defaults to 6 for USDC) */\n decimals?: number;\n /** EIP-712: Token name (EVM only) */\n name?: string;\n /** EIP-712: Token version (EVM only) */\n version?: string;\n /** Additional chain-specific fields */\n [key: string]: unknown;\n}\n\n/**\n * A single payment option in the accepts array\n */\nexport interface PaymentAccept {\n /** x402 version (1 or 2, defaults to 2 if not specified) */\n x402Version?: 1 | 2;\n /** Payment scheme (always 'exact' for x402 v2) */\n scheme: 'exact';\n /** CAIP-2 network identifier (v1: 'solana', v2: 'solana:5eykt...') */\n network: string;\n /** Payment amount in atomic units (x402 v2 spec field) */\n amount: string;\n /** @deprecated v1 field — use `amount` instead. Kept for backwards compatibility with v1 data. */\n maxAmountRequired?: string;\n /** Token address */\n asset: string;\n /** Seller's address to receive payment */\n payTo: string;\n /** Maximum seconds until payment expires */\n maxTimeoutSeconds: number;\n /** Chain-specific extra data */\n extra?: AcceptsExtra;\n}\n\n/**\n * Full PaymentRequired structure (sent in PAYMENT-REQUIRED header)\n */\nexport interface PaymentRequired {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** Available payment options */\n accepts: PaymentAccept[];\n /** Optional error message */\n error?: string;\n /** Protocol extensions */\n extensions?: Record<string, unknown>;\n}\n\n/**\n * PaymentSignature structure (sent in PAYMENT-SIGNATURE header)\n */\nexport interface PaymentSignature {\n /** x402 version (always 2) */\n x402Version: 2;\n /** Resource being accessed */\n resource: ResourceInfo;\n /** The payment option that was accepted */\n accepted: PaymentAccept;\n /** The signed payment */\n payload: {\n /** Signed transaction (base64 for Solana, JSON for EVM) */\n transaction: string;\n };\n /** Protocol extensions */\n extensions?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Facilitator Response Types\n// ============================================================================\n\n/**\n * Response from /verify endpoint\n */\nexport interface VerifyResponse {\n /** Whether the payment is valid */\n isValid: boolean;\n /** Reason for invalidity (if invalid) */\n invalidReason?: string;\n /** Payer address */\n payer?: string;\n}\n\n/**\n * Response from /settle endpoint\n */\nexport interface SettleResponse {\n /** Whether settlement succeeded */\n success: boolean;\n /** Transaction signature/hash */\n transaction?: string;\n /** Network the payment was made on */\n network: string;\n /** Error reason (if failed) */\n errorReason?: string;\n /** Error code (if failed) */\n errorCode?: string;\n /** Payer address */\n payer?: string;\n /** Protocol extensions returned by the facilitator (e.g., sponsored-access recommendations) */\n extensions?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Access Pass Types\n// ============================================================================\n\n/**\n * A single access pass tier offered by a seller\n */\nexport interface AccessPassTier {\n /** Tier ID (e.g., '1h', '24h') */\n id: string;\n /** Human-readable label (e.g., '1 hour') */\n label: string;\n /** Duration in seconds */\n seconds: number;\n /** Price in USD (e.g., '0.50') */\n price: string;\n /** Price in atomic units (e.g., '500000') */\n priceAtomic: string;\n}\n\n/**\n * Access pass info returned in X-ACCESS-PASS-TIERS header\n */\nexport interface AccessPassInfo {\n /** Available tiers (if tier-based pricing) */\n tiers?: AccessPassTier[];\n /** Rate per hour in USD (if custom duration pricing) */\n ratePerHour?: string;\n /** Pass issuer identifier */\n issuer?: string;\n}\n\n/**\n * JWT claims inside an access pass token\n */\nexport interface AccessPassClaims {\n /** Subject — always 'x402-access-pass' */\n sub: string;\n /** Tier ID or 'custom' */\n tier: string;\n /** Duration in seconds */\n duration: number;\n /** Issued at (unix seconds) */\n iat: number;\n /** Expires at (unix seconds) */\n exp: number;\n /** Payer wallet address */\n payer: string;\n /** Network used for payment */\n network: string;\n /** Issuer identifier */\n iss: string;\n}\n\n/**\n * Client-side access pass configuration\n */\nexport interface AccessPassClientConfig {\n /** Enable access pass mode (default: true when this config is present) */\n enabled?: boolean;\n /** Preferred tier ID (e.g., '1h') — pick this tier if available */\n preferTier?: string;\n /** Preferred custom duration in seconds (e.g., 3600) */\n preferDuration?: number;\n /** Maximum amount willing to spend in USD (e.g., '2.00') */\n maxSpend?: string;\n /** Auto-renew expired passes (default: true) */\n autoRenew?: boolean;\n}\n\n// ============================================================================\n// Error Types\n// ============================================================================\n\n/**\n * SDK error codes\n */\nexport type X402ErrorCode =\n // Client errors\n | 'missing_payment_required_header'\n | 'invalid_payment_required'\n | 'unsupported_network'\n | 'no_matching_payment_option'\n | 'no_solana_accept' // Legacy, kept for compatibility\n | 'missing_fee_payer'\n | 'missing_decimals'\n | 'missing_amount'\n | 'amount_exceeds_max'\n | 'insufficient_balance'\n | 'wallet_missing_sign_transaction'\n | 'wallet_not_connected'\n | 'transaction_build_failed'\n | 'payment_rejected'\n // Server errors\n | 'invalid_payment_signature'\n | 'facilitator_verify_failed'\n | 'facilitator_settle_failed'\n | 'facilitator_request_failed'\n | 'no_matching_requirement'\n // Access pass errors\n | 'access_pass_expired'\n | 'access_pass_invalid'\n | 'access_pass_tier_not_found'\n | 'access_pass_exceeds_max_spend';\n\n/**\n * Custom error class for x402 operations\n */\nexport class X402Error extends Error {\n /** Error code for programmatic handling */\n code: X402ErrorCode;\n /** Additional error details */\n details?: unknown;\n\n constructor(code: X402ErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'X402Error';\n this.code = code;\n this.details = details;\n // Maintain proper prototype chain\n Object.setPrototypeOf(this, X402Error.prototype);\n }\n}\n","/**\n * Utility Functions\n *\n * Chain-agnostic helpers for x402 payments.\n */\n\nimport { SOLANA_MAINNET_NETWORK, BASE_MAINNET_NETWORK } from './types';\n\n// ============================================================================\n// Amount Conversion\n// ============================================================================\n\n/**\n * Convert human-readable amount to atomic units\n *\n * @param amount - Human-readable amount (e.g., 0.05 for $0.05)\n * @param decimals - Token decimals (e.g., 6 for USDC)\n * @returns Amount in atomic units as string\n *\n * @example\n * ```typescript\n * toAtomicUnits(0.05, 6) // '50000'\n * toAtomicUnits(1.50, 6) // '1500000'\n * ```\n */\nexport function toAtomicUnits(amount: number, decimals: number): string {\n const multiplier = Math.pow(10, decimals);\n return Math.floor(amount * multiplier).toString();\n}\n\n/**\n * Convert atomic units to human-readable amount\n *\n * @param atomicUnits - Amount in smallest units\n * @param decimals - Token decimals\n * @returns Human-readable amount\n *\n * @example\n * ```typescript\n * fromAtomicUnits('50000', 6) // 0.05\n * fromAtomicUnits(1500000n, 6) // 1.5\n * ```\n */\nexport function fromAtomicUnits(\n atomicUnits: string | bigint | number,\n decimals: number\n): number {\n const divisor = Math.pow(10, decimals);\n return Number(atomicUnits) / divisor;\n}\n\n// ============================================================================\n// Network Helpers\n// ============================================================================\n\n/**\n * Network type\n */\nexport type ChainFamily = 'solana' | 'evm' | 'unknown';\n\n/**\n * Get the chain family from a CAIP-2 network identifier\n *\n * @param network - CAIP-2 network identifier\n * @returns Chain family\n *\n * @example\n * ```typescript\n * getChainFamily('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp') // 'solana'\n * getChainFamily('eip155:8453') // 'evm'\n * ```\n */\nexport function getChainFamily(network: string): ChainFamily {\n if (network.startsWith('solana:') || network === 'solana') {\n return 'solana';\n }\n if (network.startsWith('eip155:') || ['base', 'ethereum', 'arbitrum'].includes(network)) {\n return 'evm';\n }\n return 'unknown';\n}\n\n/**\n * Get default RPC URL for a network\n *\n * @param network - CAIP-2 network identifier\n * @returns Default RPC URL\n */\nexport function getDefaultRpcUrl(network: string): string {\n const family = getChainFamily(network);\n\n if (family === 'solana') {\n if (network.includes('devnet') || network === 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1') {\n return 'https://api.devnet.solana.com';\n }\n if (network.includes('testnet') || network === 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z') {\n return 'https://api.testnet.solana.com';\n }\n // Mainnet uses Dexter's RPC proxy\n return 'https://api.dexter.cash/api/solana/rpc';\n }\n\n if (family === 'evm') {\n // Extract chain ID from CAIP-2\n if (network.startsWith('eip155:')) {\n const chainId = network.split(':')[1];\n switch (chainId) {\n case '8453': return 'https://api.dexter.cash/api/base/rpc'; // Dexter proxy\n case '84532': return 'https://sepolia.base.org';\n case '1': return 'https://eth.llamarpc.com';\n case '42161': return 'https://arb1.arbitrum.io/rpc';\n default: return 'https://api.dexter.cash/api/base/rpc';\n }\n }\n // Legacy names\n if (network === 'base') return 'https://api.dexter.cash/api/base/rpc';\n if (network === 'ethereum') return 'https://eth.llamarpc.com';\n if (network === 'arbitrum') return 'https://arb1.arbitrum.io/rpc';\n return 'https://api.dexter.cash/api/base/rpc';\n }\n\n // Unknown - return Dexter's Solana proxy\n return 'https://api.dexter.cash/api/solana/rpc';\n}\n\n/**\n * Get human-readable chain name\n *\n * @param network - CAIP-2 network identifier\n * @returns Human-readable name\n */\nexport function getChainName(network: string): string {\n const mapping: Record<string, string> = {\n [SOLANA_MAINNET_NETWORK]: 'Solana',\n 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1': 'Solana Devnet',\n 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z': 'Solana Testnet',\n 'solana': 'Solana',\n [BASE_MAINNET_NETWORK]: 'Base',\n 'eip155:84532': 'Base Sepolia',\n 'eip155:1': 'Ethereum',\n 'eip155:42161': 'Arbitrum One',\n 'base': 'Base',\n 'ethereum': 'Ethereum',\n 'arbitrum': 'Arbitrum',\n };\n return mapping[network] || network;\n}\n\n// ============================================================================\n// Transaction URL Helpers\n// ============================================================================\n\n/**\n * Get explorer URL for a transaction\n *\n * @param txSignature - Transaction signature/hash\n * @param network - CAIP-2 network identifier\n * @returns Explorer URL\n */\nexport function getExplorerUrl(txSignature: string, network: string): string {\n const family = getChainFamily(network);\n\n if (family === 'solana') {\n const isDevnet = network.includes('devnet') || network === 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1';\n if (isDevnet) {\n return `https://solscan.io/tx/${txSignature}?cluster=devnet`;\n }\n // Prefer Orb Markets for mainnet\n return `https://www.orbmarkets.io/tx/${txSignature}`;\n }\n\n if (family === 'evm') {\n // Extract chain ID\n let chainId = '8453'; // Default to Base\n if (network.startsWith('eip155:')) {\n chainId = network.split(':')[1];\n } else if (network === 'ethereum') {\n chainId = '1';\n } else if (network === 'arbitrum') {\n chainId = '42161';\n }\n\n switch (chainId) {\n case '8453': return `https://basescan.org/tx/${txSignature}`;\n case '84532': return `https://sepolia.basescan.org/tx/${txSignature}`;\n case '1': return `https://etherscan.io/tx/${txSignature}`;\n case '42161': return `https://arbiscan.io/tx/${txSignature}`;\n default: return `https://basescan.org/tx/${txSignature}`;\n }\n }\n\n return `https://solscan.io/tx/${txSignature}`;\n}\n\n// ============================================================================\n// Encoding Helpers\n// ============================================================================\n\n/**\n * Unicode-safe base64 encode a string.\n * Works in both Node.js and browsers, handling characters above U+00FF\n * that would cause btoa() to throw InvalidCharacterError.\n */\nfunction safeBase64Encode(str: string): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(str, 'utf-8').toString('base64');\n }\n // Browser fallback: encode UTF-8 bytes via TextEncoder\n const bytes = new TextEncoder().encode(str);\n let binary = '';\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * Unicode-safe base64 decode a string.\n * Works in both Node.js and browsers.\n */\nfunction safeBase64Decode(encoded: string): string {\n if (typeof Buffer !== 'undefined') {\n return Buffer.from(encoded, 'base64').toString('utf-8');\n }\n // Browser fallback: decode via atob then UTF-8\n const binary = atob(encoded);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n}\n\n/**\n * Encode an object as base64 JSON (Unicode-safe)\n */\nexport function encodeBase64Json(obj: unknown): string {\n return safeBase64Encode(JSON.stringify(obj));\n}\n\n/**\n * Decode base64 JSON to object (Unicode-safe)\n */\nexport function decodeBase64Json<T>(encoded: string): T {\n return JSON.parse(safeBase64Decode(encoded)) as T;\n}\n","/**\n * Facilitator Client\n *\n * Communicates with the x402 facilitator for:\n * - /supported - Get supported payment schemes and fee payer addresses\n * - /verify - Verify a payment signature before processing\n * - /settle - Submit the payment for execution\n *\n * Includes retry with exponential backoff and request timeouts.\n * Works with any x402 v2 facilitator (Dexter or others).\n */\n\nimport type { PaymentAccept, PaymentSignature, VerifyResponse, SettleResponse } from '../types';\nimport { DEXTER_FACILITATOR_URL } from '../types';\nimport { decodeBase64Json } from '../utils';\n\n/**\n * Supported payment kind from facilitator /supported endpoint\n */\nexport interface SupportedKind {\n x402Version: number;\n scheme: string;\n network: string;\n extra?: {\n feePayer?: string;\n decimals?: number;\n name?: string;\n version?: string;\n [key: string]: unknown;\n };\n}\n\n/**\n * Response from facilitator /supported endpoint\n */\nexport interface SupportedResponse {\n kinds: SupportedKind[];\n extensions?: string[];\n signers?: Record<string, string[]>;\n}\n\n/**\n * Configuration for retry and timeout behavior\n */\nexport interface FacilitatorClientConfig {\n /** Request timeout in milliseconds @default 10000 */\n timeoutMs?: number;\n /** Maximum retry attempts for verify/settle @default 3 */\n maxRetries?: number;\n /** Base delay between retries in milliseconds (doubles each attempt) @default 500 */\n retryBaseMs?: number;\n}\n\n// Retryable: network errors and 5xx responses\nfunction isRetryable(error: unknown): boolean {\n if (error instanceof TypeError) return true; // fetch network errors\n if (error && typeof error === 'object' && 'status' in error) {\n const status = (error as { status: number }).status;\n return status >= 500 && status < 600;\n }\n return false;\n}\n\nclass HttpError extends Error {\n status: number;\n body: string;\n constructor(status: number, body: string) {\n super(`HTTP ${status}`);\n this.status = status;\n this.body = body;\n }\n}\n\n/**\n * Client for communicating with an x402 v2 facilitator\n */\nexport class FacilitatorClient {\n private facilitatorUrl: string;\n private cachedSupported: SupportedResponse | null = null;\n private cacheTime: number = 0;\n private readonly CACHE_TTL_MS = 60_000;\n private readonly timeoutMs: number;\n private readonly maxRetries: number;\n private readonly retryBaseMs: number;\n\n constructor(\n facilitatorUrl: string = DEXTER_FACILITATOR_URL,\n config?: FacilitatorClientConfig,\n ) {\n this.facilitatorUrl = facilitatorUrl.replace(/\\/$/, '');\n this.timeoutMs = config?.timeoutMs ?? 10_000;\n this.maxRetries = config?.maxRetries ?? 3;\n this.retryBaseMs = config?.retryBaseMs ?? 500;\n }\n\n private async fetchWithTimeout(\n url: string,\n init?: RequestInit,\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), this.timeoutMs);\n try {\n return await fetch(url, { ...init, signal: controller.signal });\n } finally {\n clearTimeout(timer);\n }\n }\n\n private async fetchWithRetry(\n url: string,\n init?: RequestInit,\n ): Promise<Response> {\n let lastError: unknown;\n for (let attempt = 0; attempt < this.maxRetries; attempt++) {\n try {\n const response = await this.fetchWithTimeout(url, init);\n if (!response.ok && response.status >= 500) {\n throw new HttpError(response.status, await response.text());\n }\n return response;\n } catch (error) {\n lastError = error;\n if (attempt < this.maxRetries - 1 && isRetryable(error)) {\n const delay = this.retryBaseMs * Math.pow(2, attempt);\n await new Promise(r => setTimeout(r, delay));\n continue;\n }\n throw error;\n }\n }\n throw lastError;\n }\n\n /**\n * Get supported payment kinds from the facilitator.\n * Results are cached for 1 minute to reduce network calls.\n */\n async getSupported(): Promise<SupportedResponse> {\n const now = Date.now();\n if (this.cachedSupported && now - this.cacheTime < this.CACHE_TTL_MS) {\n return this.cachedSupported;\n }\n\n const response = await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);\n if (!response.ok) {\n throw new Error(`Facilitator /supported returned ${response.status}`);\n }\n\n this.cachedSupported = (await response.json()) as SupportedResponse;\n this.cacheTime = now;\n return this.cachedSupported;\n }\n\n /**\n * Get the fee payer address for a specific network\n */\n async getFeePayer(network: string): Promise<string | undefined> {\n const supported = await this.getSupported();\n const kind = supported.kinds.find(\n (k) => k.x402Version === 2 && k.scheme === 'exact' && k.network === network,\n );\n\n if (!kind) {\n throw new Error(\n `Facilitator does not support network \"${network}\" with scheme \"exact\"`,\n );\n }\n\n return kind.extra?.feePayer;\n }\n\n /**\n * Get extra data for a network (feePayer, decimals, EIP-712 data, etc.)\n */\n async getNetworkExtra(network: string): Promise<SupportedKind['extra']> {\n const supported = await this.getSupported();\n const kind = supported.kinds.find(\n (k) => k.x402Version === 2 && k.scheme === 'exact' && k.network === network,\n );\n return kind?.extra;\n }\n\n /**\n * Verify a payment with the facilitator.\n * Retries on 5xx and network errors with exponential backoff.\n */\n async verifyPayment(\n paymentSignatureHeader: string,\n requirements: PaymentAccept,\n ): Promise<VerifyResponse> {\n try {\n const paymentPayload = decodeBase64Json<PaymentSignature>(paymentSignatureHeader);\n\n const response = await this.fetchWithRetry(`${this.facilitatorUrl}/verify`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n x402Version: 2,\n paymentPayload,\n paymentRequirements: requirements,\n }),\n });\n\n if (!response.ok) {\n return {\n isValid: false,\n invalidReason: `facilitator_error_${response.status}`,\n };\n }\n\n return (await response.json()) as VerifyResponse;\n } catch (error) {\n const reason = error instanceof HttpError\n ? `facilitator_error_${error.status}`\n : error instanceof Error && error.name === 'AbortError'\n ? 'facilitator_timeout'\n : error instanceof Error\n ? error.message\n : 'unexpected_verify_error';\n\n return { isValid: false, invalidReason: reason };\n }\n }\n\n /**\n * Settle a payment with the facilitator.\n * Retries on 5xx and network errors with exponential backoff.\n */\n async settlePayment(\n paymentSignatureHeader: string,\n requirements: PaymentAccept,\n ): Promise<SettleResponse> {\n try {\n const paymentPayload = decodeBase64Json<PaymentSignature>(paymentSignatureHeader);\n\n const response = await this.fetchWithRetry(`${this.facilitatorUrl}/settle`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n x402Version: 2,\n paymentPayload,\n paymentRequirements: requirements,\n }),\n });\n\n if (!response.ok) {\n return {\n success: false,\n network: requirements.network,\n errorReason: `facilitator_error_${response.status}`,\n };\n }\n\n const result = (await response.json()) as SettleResponse;\n return { ...result, network: requirements.network };\n } catch (error) {\n const reason = error instanceof HttpError\n ? `facilitator_error_${error.status}`\n : error instanceof Error && error.name === 'AbortError'\n ? 'facilitator_timeout'\n : error instanceof Error\n ? error.message\n : 'unexpected_settle_error';\n\n return {\n success: false,\n network: requirements.network,\n errorReason: reason,\n };\n }\n }\n}\n","/**\n * x402 v2 Server\n *\n * Server-side helpers for accepting x402 payments.\n * Chain-agnostic - works with Solana, Base, and any x402-compatible network.\n *\n * @example\n * ```typescript\n * import { createX402Server } from '@dexterai/x402/server';\n *\n * const server = createX402Server({\n * payTo: 'YourAddress...',\n * network: 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n * });\n *\n * // Handle 402 responses\n * if (!paymentSignature) {\n * const requirements = await server.buildRequirements({\n * amountAtomic: '50000',\n * resourceUrl: '/api/protected',\n * });\n * res.setHeader('PAYMENT-REQUIRED', server.encodeRequirements(requirements));\n * res.status(402).json({});\n * return;\n * }\n *\n * // Verify and settle\n * const verify = await server.verifyPayment(paymentSignature);\n * if (!verify.isValid) throw new Error(verify.invalidReason);\n *\n * const settle = await server.settlePayment(paymentSignature);\n * if (!settle.success) throw new Error(settle.errorReason);\n *\n * // Payment successful!\n * res.json({ transaction: settle.transaction });\n * ```\n */\n\nimport type {\n PaymentRequired,\n PaymentAccept,\n ResourceInfo,\n AcceptsExtra,\n VerifyResponse,\n SettleResponse,\n PayToContext,\n PayToProvider,\n} from '../types';\nimport {\n SOLANA_MAINNET_NETWORK,\n USDC_MINT,\n DEXTER_FACILITATOR_URL,\n} from '../types';\nimport { FacilitatorClient, type SupportedKind } from './facilitator-client';\nimport { encodeBase64Json, decodeBase64Json } from '../utils';\n\n/**\n * Best-effort extraction of amount from a PAYMENT-SIGNATURE header.\n * Used as a fallback when the requirements cache misses (e.g., server restart\n * between initial 402 and retry). Returns the accepted amount or undefined.\n */\nfunction extractAmountFromHeader(paymentSignatureHeader: string): string | undefined {\n try {\n const decoded = decodeBase64Json<{\n accepted?: { amount?: string; maxAmountRequired?: string };\n }>(paymentSignatureHeader);\n return decoded?.accepted?.amount ?? decoded?.accepted?.maxAmountRequired;\n } catch {\n return undefined;\n }\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Asset configuration\n */\nexport interface AssetConfig {\n /** Token address (mint on Solana, contract on EVM) */\n address: string;\n /** Token decimals */\n decimals: number;\n}\n\n/**\n * Server configuration\n */\nexport interface X402ServerConfig {\n /**\n * Address to receive payments, or a dynamic provider function.\n * Use a string for static wallet addresses.\n * Use a PayToProvider (e.g., stripePayTo) for per-request addresses.\n */\n payTo: string | PayToProvider;\n /** Facilitator URL (defaults to Dexter) */\n facilitatorUrl?: string;\n /** CAIP-2 network identifier */\n network?: string;\n /** Asset configuration (defaults to USDC) */\n asset?: AssetConfig;\n /** Default payment timeout in seconds */\n defaultTimeoutSeconds?: number;\n}\n\n/**\n * Options for building payment requirements\n */\nexport interface BuildRequirementsOptions {\n /** Amount in atomic units (e.g., '50000' for 0.05 USDC) */\n amountAtomic: string;\n /** Full URL of the resource */\n resourceUrl: string;\n /** Human-readable description */\n description?: string;\n /** MIME type of the response */\n mimeType?: string;\n /** Override timeout for this request */\n timeoutSeconds?: number;\n}\n\n/**\n * x402 Server interface\n */\nexport interface X402Server {\n /** Build payment requirements (fetches feePayer from facilitator) */\n buildRequirements(options: BuildRequirementsOptions): Promise<PaymentRequired>;\n\n /** Encode requirements for PAYMENT-REQUIRED header */\n encodeRequirements(requirements: PaymentRequired): string;\n\n /** Create complete 402 response object */\n create402Response(requirements: PaymentRequired): {\n status: 402;\n headers: { 'PAYMENT-REQUIRED': string };\n body: Record<string, unknown>;\n };\n\n /** Verify payment with facilitator */\n verifyPayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<VerifyResponse>;\n\n /** Settle payment via facilitator */\n settlePayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<SettleResponse>;\n\n /** Get PaymentAccept for verify/settle */\n getPaymentAccept(options: BuildRequirementsOptions): Promise<PaymentAccept>;\n\n /** Get network this server is configured for */\n readonly network: string;\n\n /** Get facilitator client for advanced usage */\n readonly facilitator: FacilitatorClient;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Create an x402 server for accepting payments\n */\nexport function createX402Server(config: X402ServerConfig): X402Server {\n const {\n payTo,\n facilitatorUrl = DEXTER_FACILITATOR_URL,\n network = SOLANA_MAINNET_NETWORK,\n asset = { address: USDC_MINT, decimals: 6 },\n defaultTimeoutSeconds = 60,\n } = config;\n\n const facilitator = new FacilitatorClient(facilitatorUrl);\n\n // Cache for network extra data\n let cachedExtra: SupportedKind['extra'] | null = null;\n\n // Requirements cache: payTo address -> PaymentAccept + expiry.\n // Populated by buildRequirements/getPaymentAccept, consumed by verify/settle.\n // Prevents the bug where verify/settle fabricates requirements with amount '0'.\n // Parallels the SettlementCache pattern from coinbase/x402.\n const requirementsCache = new Map<string, { accept: PaymentAccept; expiresAt: number }>();\n const CACHE_PRUNE_INTERVAL = 30_000;\n let lastPrune = Date.now();\n\n function cacheRequirements(accept: PaymentAccept): void {\n const ttl = (accept.maxTimeoutSeconds || defaultTimeoutSeconds) * 1000;\n requirementsCache.set(accept.payTo, { accept, expiresAt: Date.now() + ttl });\n\n if (Date.now() - lastPrune > CACHE_PRUNE_INTERVAL) {\n const now = Date.now();\n for (const [key, entry] of requirementsCache) {\n if (entry.expiresAt < now) requirementsCache.delete(key);\n }\n lastPrune = now;\n }\n }\n\n function getCachedRequirements(address: string): PaymentAccept | undefined {\n const entry = requirementsCache.get(address);\n if (!entry) return undefined;\n if (entry.expiresAt < Date.now()) {\n requirementsCache.delete(address);\n return undefined;\n }\n return entry.accept;\n }\n\n /**\n * Resolve payTo to a concrete address.\n * For static strings, returns immediately.\n * For providers (e.g. Stripe), calls the function with context.\n */\n async function resolvePayTo(context?: PayToContext): Promise<string> {\n if (typeof payTo === 'string') return payTo;\n return payTo(context || {});\n }\n\n /**\n * Get extra data from facilitator (cached)\n */\n async function getNetworkExtra(): Promise<AcceptsExtra> {\n if (!cachedExtra) {\n cachedExtra = await facilitator.getNetworkExtra(network);\n }\n\n const isSvm = network.startsWith('solana:');\n\n if (isSvm && !cachedExtra?.feePayer) {\n throw new Error(`Facilitator does not provide feePayer for network \"${network}\"`);\n }\n\n return {\n ...(cachedExtra?.feePayer ? { feePayer: cachedExtra.feePayer } : {}),\n decimals: cachedExtra?.decimals ?? asset.decimals,\n name: cachedExtra?.name,\n version: cachedExtra?.version,\n };\n }\n\n /**\n * Build a PaymentAccept with a pre-resolved address (internal helper)\n */\n async function buildPaymentAccept(\n resolvedPayTo: string,\n options: BuildRequirementsOptions,\n ): Promise<PaymentAccept> {\n const {\n amountAtomic,\n timeoutSeconds = defaultTimeoutSeconds,\n } = options;\n\n const extra = await getNetworkExtra();\n\n const accept: PaymentAccept = {\n scheme: 'exact',\n network,\n amount: amountAtomic,\n maxAmountRequired: amountAtomic,\n asset: asset.address,\n payTo: resolvedPayTo,\n maxTimeoutSeconds: timeoutSeconds,\n extra,\n };\n\n cacheRequirements(accept);\n return accept;\n }\n\n /**\n * Build a PaymentAccept structure (resolves payTo dynamically)\n */\n async function getPaymentAccept(options: BuildRequirementsOptions): Promise<PaymentAccept> {\n const address = await resolvePayTo({\n amountAtomic: options.amountAtomic,\n resourceUrl: options.resourceUrl,\n });\n return buildPaymentAccept(address, options);\n }\n\n /**\n * Build payment requirements for a 402 response\n */\n async function buildRequirements(options: BuildRequirementsOptions): Promise<PaymentRequired> {\n const {\n resourceUrl,\n description,\n mimeType = 'application/json',\n } = options;\n\n const resource: ResourceInfo = {\n url: resourceUrl,\n description,\n mimeType,\n };\n\n const accept = await getPaymentAccept(options);\n\n return {\n x402Version: 2,\n resource,\n accepts: [accept],\n error: 'Payment required',\n };\n }\n\n /**\n * Encode requirements for PAYMENT-REQUIRED header\n */\n function encodeRequirements(requirements: PaymentRequired): string {\n return encodeBase64Json(requirements);\n }\n\n /**\n * Create complete 402 response object\n */\n function create402Response(requirements: PaymentRequired) {\n return {\n status: 402 as const,\n headers: {\n 'PAYMENT-REQUIRED': encodeRequirements(requirements),\n },\n body: {},\n };\n }\n\n /**\n * Verify payment with facilitator.\n * Resolves requirements from cache (populated by buildRequirements),\n * falling back to the payment header for the payTo address.\n */\n async function verifyPayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<VerifyResponse> {\n if (!requirements) {\n const address = await resolvePayTo({ paymentHeader: paymentSignatureHeader });\n requirements = getCachedRequirements(address);\n if (!requirements) {\n // Fallback: rebuild with amount from payment header if possible\n requirements = await buildPaymentAccept(address, {\n amountAtomic: extractAmountFromHeader(paymentSignatureHeader) ?? '0',\n resourceUrl: '',\n });\n }\n }\n\n return facilitator.verifyPayment(paymentSignatureHeader, requirements);\n }\n\n /**\n * Settle payment via facilitator.\n * Resolves requirements from cache (populated by buildRequirements),\n * falling back to the payment header for the payTo address.\n */\n async function settlePayment(\n paymentSignatureHeader: string,\n requirements?: PaymentAccept\n ): Promise<SettleResponse> {\n if (!requirements) {\n const address = await resolvePayTo({ paymentHeader: paymentSignatureHeader });\n requirements = getCachedRequirements(address);\n if (!requirements) {\n requirements = await buildPaymentAccept(address, {\n amountAtomic: extractAmountFromHeader(paymentSignatureHeader) ?? '0',\n resourceUrl: '',\n });\n }\n }\n\n return facilitator.settlePayment(paymentSignatureHeader, requirements);\n }\n\n return {\n buildRequirements,\n encodeRequirements,\n create402Response,\n verifyPayment,\n settlePayment,\n getPaymentAccept,\n network,\n facilitator,\n };\n}\n","/**\n * Stripe Machine Payments — PayTo Provider\n *\n * Generates per-request Stripe deposit addresses via PaymentIntents.\n * Payments land in your Stripe Dashboard with full reporting, taxes, and refunds.\n *\n * Requires `stripe` npm package as a peer dependency.\n *\n * @example\n * ```typescript\n * import { x402Middleware, stripePayTo } from '@dexterai/x402/server';\n *\n * app.use('/api/data', x402Middleware({\n * amount: '0.01',\n * payTo: stripePayTo(process.env.STRIPE_SECRET_KEY),\n * }));\n * ```\n *\n * @see https://docs.stripe.com/payments/machine\n */\n\nimport type { PayToContext, PayToProvider } from '../types';\n\n/**\n * Registry of Stripe PayTo providers and their configured networks.\n * Uses WeakMap so the tag survives wrapping, proxying, or bind().\n */\nconst stripeProviderNetworks = new WeakMap<PayToProvider, string>();\n\n/** Get the network a Stripe PayTo provider is configured for, or undefined if not a Stripe provider. */\nexport function getStripeProviderNetwork(provider: PayToProvider): string | undefined {\n return stripeProviderNetworks.get(provider);\n}\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for the Stripe PayTo provider.\n */\nexport interface StripePayToConfig {\n /** Stripe secret key (sk_test_... or sk_live_...) */\n secretKey: string;\n\n /**\n * Stripe API version to use.\n * @default '2026-01-28.clover'\n */\n apiVersion?: string;\n\n /**\n * Target network for deposit addresses.\n * - 'base' → Base mainnet (eip155:8453)\n * - 'base-sepolia' → Base Sepolia testnet (eip155:84532)\n * @default 'base'\n */\n network?: 'base' | 'base-sepolia';\n}\n\n// Map our network names to Stripe deposit_addresses keys\nconst STRIPE_NETWORK_KEYS: Record<string, string> = {\n 'base': 'base',\n 'base-sepolia': 'base_sepolia',\n};\n\n// Map our network names to CAIP-2 identifiers\nconst CAIP2_NETWORKS: Record<string, string> = {\n 'base': 'eip155:8453',\n 'base-sepolia': 'eip155:84532',\n};\n\n// USDC has 6 decimals\nconst USDC_DECIMALS = 6;\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Create a Stripe-backed PayTo provider for x402 machine payments.\n *\n * On each new request, creates a Stripe PaymentIntent with a crypto deposit address.\n * When the agent sends USDC to that address, Stripe auto-captures the payment.\n * Payments appear in your Stripe Dashboard like any other transaction.\n *\n * @param secretKeyOrConfig - Stripe secret key string, or full config object\n * @returns A PayToProvider function with auto-configuration defaults\n *\n * @example Minimal usage\n * ```typescript\n * const provider = stripePayTo('sk_test_...');\n * ```\n *\n * @example With config\n * ```typescript\n * const provider = stripePayTo({\n * secretKey: 'sk_test_...',\n * network: 'base-sepolia', // testnet\n * });\n * ```\n */\nexport function stripePayTo(\n secretKeyOrConfig: string | StripePayToConfig,\n): PayToProvider {\n const config: StripePayToConfig =\n typeof secretKeyOrConfig === 'string'\n ? { secretKey: secretKeyOrConfig }\n : secretKeyOrConfig;\n\n const networkName = config.network ?? 'base';\n const stripeNetworkKey = STRIPE_NETWORK_KEYS[networkName] ?? 'base';\n const caip2Network = CAIP2_NETWORKS[networkName] ?? 'eip155:8453';\n const apiVersion = config.apiVersion ?? '2026-01-28.clover';\n\n // Lazy-loaded Stripe client (avoids import errors when stripe isn't installed).\n // Typed via import('stripe') so we get real Stripe SDK types.\n let stripeClient: import('stripe').default | null = null;\n\n async function getStripe(): Promise<import('stripe').default> {\n if (stripeClient) return stripeClient;\n\n try {\n const { default: Stripe } = await import('stripe');\n stripeClient = new Stripe(config.secretKey, {\n apiVersion: apiVersion as import('stripe').Stripe.LatestApiVersion,\n appInfo: {\n name: '@dexterai/x402',\n url: 'https://dexter.cash/sdk',\n },\n });\n return stripeClient;\n } catch {\n throw new Error(\n 'The \"stripe\" package is required for stripePayTo(). ' +\n 'Install it with: npm install stripe',\n );\n }\n }\n\n // The provider function\n const provider: PayToProvider = async (context: PayToContext): Promise<string> => {\n // ---------------------------------------------------------------\n // Retry path: extract the deposit address from the payment header\n // ---------------------------------------------------------------\n if (context.paymentHeader) {\n try {\n const decoded = JSON.parse(\n Buffer.from(context.paymentHeader, 'base64').toString(),\n );\n // EVM: address is in payload.authorization.to\n const toAddress = decoded.payload?.authorization?.to;\n if (toAddress && typeof toAddress === 'string') {\n return toAddress;\n }\n // Fallback: check accepted.payTo\n const acceptedPayTo = decoded.accepted?.payTo;\n if (acceptedPayTo && typeof acceptedPayTo === 'string') {\n return acceptedPayTo;\n }\n } catch {\n // Fall through to error\n }\n throw new Error(\n 'Could not extract deposit address from payment header. ' +\n 'Ensure the client is sending a valid x402 PAYMENT-SIGNATURE.',\n );\n }\n\n // ---------------------------------------------------------------\n // Initial path: create a Stripe PaymentIntent for a deposit address\n // ---------------------------------------------------------------\n const stripe = await getStripe();\n\n // Convert atomic USDC to Stripe cents\n // 10000 atomic USDC (6 decimals) = 0.01 USDC = $0.01 = 1 cent\n const amountAtomic = context.amountAtomic ? parseInt(context.amountAtomic, 10) : 10000;\n const amountInCents = Math.max(1, Math.round(amountAtomic / Math.pow(10, USDC_DECIMALS - 2)));\n\n // Stripe's crypto payment types aren't fully in the base SDK typedefs yet.\n // We pass the create params through a Record to avoid type errors on\n // crypto-specific fields (payment_method_types, payment_method_options).\n const paymentIntent = await stripe.paymentIntents.create({\n amount: amountInCents,\n currency: 'usd',\n payment_method_types: ['crypto'],\n payment_method_data: { type: 'crypto' },\n payment_method_options: {\n crypto: { mode: 'custom' },\n } as Record<string, unknown>,\n confirm: true,\n });\n\n // Extract the deposit address from the PaymentIntent's next_action.\n // Stripe's crypto deposit types aren't in the base SDK yet, so we use\n // a structural cast for the crypto-specific fields.\n const nextAction = paymentIntent.next_action as {\n crypto_collect_deposit_details?: {\n deposit_addresses?: Record<string, { address?: string }>;\n };\n } | null;\n if (!nextAction?.crypto_collect_deposit_details) {\n throw new Error(\n 'Stripe PaymentIntent did not return crypto deposit details. ' +\n 'Ensure your Stripe account has crypto payins enabled: ' +\n 'https://support.stripe.com/questions/get-started-with-pay-with-crypto',\n );\n }\n\n const depositDetails = nextAction.crypto_collect_deposit_details;\n const payToAddress: string | undefined =\n depositDetails.deposit_addresses?.[stripeNetworkKey]?.address;\n\n if (!payToAddress) {\n throw new Error(\n `No deposit address found for network \"${stripeNetworkKey}\". ` +\n `Available networks: ${Object.keys(depositDetails.deposit_addresses || {}).join(', ')}`,\n );\n }\n\n return payToAddress;\n };\n\n // Attach auto-configuration defaults so the middleware can set\n // network and facilitator automatically when Stripe is used\n provider._x402Defaults = {\n network: caip2Network,\n facilitatorUrl: 'https://x402.dexter.cash',\n };\n\n // Register in WeakMap so middleware can detect Stripe providers and\n // guard against non-Base networks (survives wrapping/proxying)\n stripeProviderNetworks.set(provider, caip2Network);\n\n return provider;\n}\n","/**\n * Express Middleware for x402 Payments\n *\n * One-liner middleware to protect any Express endpoint with x402 payments.\n * Handles the entire flow: 402 response, payment verification, settlement.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { x402Middleware } from '@dexterai/x402/server';\n *\n * const app = express();\n *\n * app.get('/api/protected',\n * x402Middleware({\n * payTo: 'YourSolanaAddress...',\n * amount: '0.01', // $0.01 USD\n * network: 'solana:mainnet',\n * }),\n * (req, res) => {\n * // This only runs after successful payment\n * res.json({ data: 'protected content' });\n * }\n * );\n * ```\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport type { PayToProvider } from '../types';\nimport { createX402Server, type BuildRequirementsOptions } from './x402-server';\nimport { toAtomicUnits, encodeBase64Json } from '../utils';\nimport type { SponsoredRecommendation } from '@dexterai/x402-ads-types';\nimport { getStripeProviderNetwork } from './stripe-payto';\n\n/**\n * Middleware configuration\n */\nexport interface X402MiddlewareConfig {\n /**\n * Address to receive payments, or a dynamic provider function, or\n * a map of network-specific addresses for multi-chain support.\n *\n * - **Static address**: Pass a Solana pubkey or EVM address string.\n * - **Stripe**: Use `stripePayTo(process.env.STRIPE_SECRET_KEY)` for Base.\n * - **Multi-chain map**: Keys are CAIP-2 networks or globs (`eip155:*`, `*`).\n *\n * @example\n * ```typescript\n * // Single address (works on one network)\n * payTo: '0xYourAddress...'\n *\n * // Stripe on Base, direct wallet on other chains\n * payTo: { 'eip155:8453': stripePayTo(key), '*': '0xYourAddress...' }\n *\n * // Solana + EVM\n * payTo: { 'solana:*': 'SolAddr', 'eip155:*': '0xEvmAddr' }\n * ```\n */\n payTo: string | PayToProvider | Record<string, string | PayToProvider>;\n\n /**\n * Payment amount in USD (e.g., '0.01' for 1 cent)\n * Will be converted to atomic units automatically.\n */\n amount: string;\n\n /**\n * CAIP-2 network identifier(s).\n * Pass an array to accept payments on multiple chains simultaneously.\n * The client picks whichever chain it has a wallet for.\n *\n * @default 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' (Solana mainnet)\n *\n * @example\n * ```typescript\n * // Single network\n * network: 'eip155:8453'\n *\n * // Multiple EVM chains (same payTo address works for all)\n * network: ['eip155:8453', 'eip155:137', 'eip155:42161']\n * ```\n */\n network?: string | string[];\n\n /**\n * Asset to accept\n * @default USDC on the specified network\n */\n asset?: {\n address: string;\n decimals: number;\n };\n\n /**\n * x402 facilitator URL\n * @default 'https://x402.dexter.cash'\n */\n facilitatorUrl?: string;\n\n /**\n * Resource description (shown to users)\n */\n description?: string;\n\n /**\n * Resource URL override\n * By default, uses the full request URL\n */\n resourceUrl?: string;\n\n /**\n * MIME type of the response\n */\n mimeType?: string;\n\n /**\n * Payment timeout in seconds\n * @default 120\n */\n timeoutSeconds?: number;\n\n /**\n * Enable verbose logging\n */\n verbose?: boolean;\n\n /**\n * Custom function to get resource URL from request\n * Useful for dynamic routing\n */\n getResourceUrl?: (req: Request) => string;\n\n /**\n * Custom function to get amount from request\n * Useful for dynamic pricing based on request body/params\n */\n getAmount?: (req: Request) => string;\n\n /**\n * Custom function to get description from request\n */\n getDescription?: (req: Request) => string;\n\n /**\n * Enable sponsored-access recommendation delivery.\n *\n * When true, the middleware reads `extensions[\"sponsored-access\"]` from the\n * facilitator's SettlementResponse and injects the recommendations into the\n * JSON response body as a `_x402_sponsored` field. This is the only way\n * recommendations reach the agent's LLM (headers and receipt metadata are\n * not visible to LLMs).\n *\n * Pass `true` for default injection, or an object with a custom `inject`\n * function for full control over how recommendations appear in the response.\n *\n * @default false (off, no injection)\n *\n * @example Default injection\n * ```typescript\n * x402Middleware({ payTo: '...', amount: '0.05', sponsoredAccess: true })\n * // Agent receives: { _x402_sponsored: [...], ...originalResponse }\n * ```\n *\n * @example Custom injection\n * ```typescript\n * x402Middleware({\n * payTo: '...', amount: '0.05',\n * sponsoredAccess: {\n * inject: (body, recs) => ({ ...body, related_tools: recs })\n * }\n * })\n * ```\n */\n sponsoredAccess?: boolean | {\n /** Custom injection function. Receives the original response body and typed recommendations. */\n inject?: (body: unknown, recommendations: SponsoredRecommendation[]) => unknown;\n /** Called when sponsored recommendations are matched for a settlement. */\n onMatch?: (recommendations: SponsoredRecommendation[], settlement: { transaction: string; network: string; payer: string }) => void;\n };\n}\n\n/**\n * Extended request with payment info\n */\nexport interface X402Request extends Request {\n /**\n * Payment information (only present after successful payment)\n */\n x402?: {\n /** Transaction signature/hash */\n transaction: string;\n /** Payer address */\n payer: string;\n /** Network used */\n network: string;\n };\n}\n\n// Default network\nconst DEFAULT_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\n\n// USDC decimals\nconst USDC_DECIMALS = 6;\n\n/**\n * Create x402 middleware for Express\n *\n * @param config - Middleware configuration\n * @returns Express middleware function\n */\n/**\n * Resolve a payTo value for a specific network from the config.\n * Supports: string, PayToProvider, or Record with glob matching.\n */\nfunction resolvePayToForNetwork(\n payTo: string | PayToProvider | Record<string, string | PayToProvider>,\n network: string,\n): string | PayToProvider {\n if (typeof payTo === 'string' || typeof payTo === 'function') return payTo;\n\n // Exact match first\n if (network in payTo) return payTo[network];\n\n // Prefix glob: 'eip155:*' matches 'eip155:8453'\n const prefix = network.split(':')[0];\n const globKey = `${prefix}:*`;\n if (globKey in payTo) return payTo[globKey];\n\n // Default fallback\n if ('*' in payTo) return payTo['*'];\n\n throw new Error(`No payTo configured for network \"${network}\"`);\n}\n\nexport function x402Middleware(config: X402MiddlewareConfig): RequestHandler {\n const {\n payTo,\n amount,\n asset,\n description,\n resourceUrl: staticResourceUrl,\n mimeType,\n timeoutSeconds,\n verbose = false,\n getResourceUrl,\n getAmount,\n getDescription,\n } = config;\n\n const log = verbose\n ? console.log.bind(console, '[x402:middleware]')\n : () => {};\n\n // Resolve networks: single string, array, or inferred from provider defaults\n const singleProviderDefaults = (typeof payTo === 'function') ? payTo._x402Defaults : undefined;\n const facilitatorUrl = config.facilitatorUrl ?? singleProviderDefaults?.facilitatorUrl;\n\n const configuredNetworks: string[] = (() => {\n if (config.network) {\n return Array.isArray(config.network) ? config.network : [config.network];\n }\n if (singleProviderDefaults?.network) return [singleProviderDefaults.network];\n return [DEFAULT_NETWORK];\n })();\n\n // Create one server per network (reused across requests)\n const servers = new Map<string, ReturnType<typeof createX402Server>>();\n for (const net of configuredNetworks) {\n const netPayTo = resolvePayToForNetwork(payTo, net);\n\n // Guard: Stripe payTo only supports Base — throw early if misconfigured\n if (typeof netPayTo === 'function') {\n const stripeNet = getStripeProviderNetwork(netPayTo as PayToProvider);\n if (stripeNet && net !== stripeNet) {\n throw new Error(\n `stripePayTo is configured for \"${stripeNet}\" but middleware includes network \"${net}\". ` +\n `Stripe only supports Base deposit addresses. Use a static payTo for other chains.`\n );\n }\n }\n\n servers.set(net, createX402Server({\n payTo: netPayTo,\n network: net,\n asset,\n facilitatorUrl,\n defaultTimeoutSeconds: timeoutSeconds,\n }));\n }\n\n // Primary server for verify/settle when we can't determine network from header\n const primaryServer = servers.get(configuredNetworks[0])!;\n\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n // Check for payment signature\n const paymentSignature = req.headers['payment-signature'] as string | undefined;\n\n if (!paymentSignature) {\n // No payment - return 402\n log('No payment signature, returning 402');\n\n // Build resource URL\n const resourceUrl = getResourceUrl?.(req) \n ?? staticResourceUrl \n ?? `${req.protocol}://${req.get('host')}${req.originalUrl}`;\n\n // Get dynamic values\n const requestAmount = getAmount?.(req) ?? amount;\n const requestDescription = getDescription?.(req) ?? description;\n\n // Convert USD to atomic units\n const decimals = asset?.decimals ?? USDC_DECIMALS;\n const amountAtomic = toAtomicUnits(parseFloat(requestAmount), decimals);\n\n const requirementsOptions: BuildRequirementsOptions = {\n amountAtomic,\n resourceUrl,\n description: requestDescription,\n mimeType,\n timeoutSeconds,\n };\n\n // Build requirements from all network servers and merge accepts arrays\n const allAccepts: import('../types').PaymentAccept[] = [];\n let requirements: import('../types').PaymentRequired | null = null;\n for (const [, srv] of servers) {\n try {\n const reqs = await srv.buildRequirements(requirementsOptions);\n allAccepts.push(...reqs.accepts);\n if (!requirements) requirements = reqs;\n } catch (e) {\n log('Failed to build requirements for a network:', e);\n }\n }\n if (!requirements || allAccepts.length === 0) {\n res.status(500).json({ error: 'Failed to build payment requirements' });\n return;\n }\n requirements = { ...requirements, accepts: allAccepts };\n const encoded = primaryServer.encodeRequirements(requirements);\n\n res.setHeader('PAYMENT-REQUIRED', encoded);\n res.status(402).json({\n error: 'Payment required',\n accepts: requirements.accepts,\n resource: requirements.resource,\n });\n return;\n }\n\n // Payment signature present - verify and settle.\n // Determine which network server to use from the payment header.\n log('Payment signature received, verifying...');\n\n let targetServer = primaryServer;\n try {\n const decoded = JSON.parse(Buffer.from(paymentSignature, 'base64').toString());\n const paymentNetwork = decoded?.accepted?.network as string | undefined;\n if (paymentNetwork && servers.has(paymentNetwork)) {\n targetServer = servers.get(paymentNetwork)!;\n }\n } catch {\n // Fall through to primary server\n }\n\n const verifyResult = await targetServer.verifyPayment(paymentSignature);\n \n if (!verifyResult.isValid) {\n log('Payment verification failed:', verifyResult.invalidReason);\n res.status(402).json({\n error: 'Payment verification failed',\n reason: verifyResult.invalidReason,\n });\n return;\n }\n\n log('Payment verified, settling...');\n\n const settleResult = await targetServer.settlePayment(paymentSignature);\n\n if (!settleResult.success) {\n log('Payment settlement failed:', settleResult.errorReason);\n res.status(402).json({\n error: 'Payment settlement failed',\n reason: settleResult.errorReason,\n });\n return;\n }\n\n log('Payment settled:', settleResult.transaction);\n\n const settledNetwork = settleResult.network || configuredNetworks[0];\n\n // Attach payment info to request\n (req as X402Request).x402 = {\n transaction: settleResult.transaction!,\n payer: verifyResult.payer ?? '',\n network: settledNetwork,\n };\n\n // Set PAYMENT-RESPONSE header per x402 v2 spec\n const paymentResponseData: Record<string, unknown> = {\n success: true,\n transaction: settleResult.transaction!,\n network: settledNetwork,\n payer: verifyResult.payer ?? '',\n };\n if (settleResult.extensions) {\n paymentResponseData.extensions = settleResult.extensions;\n }\n res.setHeader('PAYMENT-RESPONSE', encodeBase64Json(paymentResponseData));\n\n // Sponsored Access: inject recommendations into the response body\n // so the agent's LLM actually sees them (headers are invisible to LLMs)\n if (config.sponsoredAccess && settleResult.extensions?.[\"sponsored-access\"]) {\n const extData = settleResult.extensions[\"sponsored-access\"] as\n { info?: { recommendations?: SponsoredRecommendation[] }; recommendations?: SponsoredRecommendation[] } | undefined;\n // Facilitator may nest under .info.recommendations or .recommendations directly\n const recs = extData?.info?.recommendations ?? extData?.recommendations;\n if (recs && recs.length > 0) {\n log('Injecting sponsored-access recommendations into response');\n\n // Notify callback if configured\n if (typeof config.sponsoredAccess === 'object' && config.sponsoredAccess.onMatch) {\n try {\n config.sponsoredAccess.onMatch(recs, {\n transaction: settleResult.transaction!,\n network: settledNetwork,\n payer: verifyResult.payer ?? '',\n });\n } catch {\n // Don't block response for callback errors\n }\n }\n\n const originalJson = res.json.bind(res);\n res.json = function patchedJson(body: unknown) {\n if (typeof config.sponsoredAccess === 'object' && config.sponsoredAccess.inject) {\n return originalJson(config.sponsoredAccess.inject(body, recs));\n }\n if (body && typeof body === 'object' && !Array.isArray(body)) {\n return originalJson({ _x402_sponsored: recs, ...(body as Record<string, unknown>) });\n }\n return originalJson(body);\n } as typeof res.json;\n }\n }\n\n // Continue to actual handler\n next();\n } catch (error) {\n log('Middleware error:', error);\n \n // Don't expose internal errors\n res.status(500).json({\n error: 'Payment processing error',\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n };\n}\n","/**\n * x402 Browser Support Middleware\n *\n * Express middleware that automatically renders a branded HTML paywall page\n * when a browser (Accept: text/html) receives a 402 Payment Required response.\n * API clients continue to receive the standard JSON response unchanged.\n *\n * Includes a functional \"Pay\" button using the Solana Wallet Standard --\n * detects Phantom/Solflare/Backpack, constructs a USDC transfer, signs,\n * and submits the payment automatically.\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { x402Middleware, x402BrowserSupport } from '@dexterai/x402/server';\n *\n * const app = express();\n * app.use(express.json());\n * app.use(x402BrowserSupport());\n *\n * app.post('/api/data',\n * x402Middleware({ payTo: '...', amount: '0.01' }),\n * (req, res) => res.json({ data: 'protected' })\n * );\n * ```\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\n\n/**\n * Configuration for x402BrowserSupport middleware.\n */\nexport interface X402BrowserSupportConfig {\n /** Custom title shown on the paywall page. @default 'Payment Required' */\n title?: string;\n /** Custom branding text. @default 'Powered by x402' */\n branding?: string;\n /** URL to link for SDK/documentation. @default 'https://docs.dexter.cash/docs/sdk/' */\n sdkUrl?: string;\n /** Whether to include the request method and path. @default true */\n showEndpoint?: boolean;\n /** Solana RPC URL for wallet transactions. @default 'https://api.dexter.cash/api/solana/rpc' */\n rpcUrl?: string;\n}\n\n/** Escape HTML to prevent XSS from untrusted payment requirement fields */\nfunction esc(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"').replace(/'/g, ''');\n}\n\n/* ------------------------------------------------------------------ */\n/* USDC coin icon SVG (inline, use at ~18px) */\n/* ------------------------------------------------------------------ */\nconst USDC_ICON_SVG = `<svg width=\"18\" height=\"18\" viewBox=\"0 0 2000 2000\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1000 2000c554.17 0 1000-445.83 1000-1000S1554.17 0 1000 0 0 445.83 0 1000s445.83 1000 1000 1000z\" fill=\"#2775ca\"/><path d=\"M1275 1158.33c0-145.83-87.5-195.83-262.5-216.66-125-16.67-150-50-150-108.34s41.67-95.83 125-95.83c75 0 116.67 25 137.5 87.5 4.17 12.5 16.67 20.83 29.17 20.83h66.66c16.67 0 29.17-12.5 29.17-29.16v-4.17c-16.67-91.67-91.67-162.5-187.5-170.83v-100c0-16.67-12.5-29.17-33.33-33.34h-62.5c-16.67 0-29.17 12.5-33.34 33.34v95.83c-125 16.67-204.16 100-204.16 204.17 0 137.5 83.33 191.66 258.33 212.5 116.67 20.83 154.17 45.83 154.17 112.5s-58.34 112.5-137.5 112.5c-108.34 0-145.84-45.84-158.34-108.34-4.16-16.66-16.66-25-29.16-25h-70.84c-16.66 0-29.16 12.5-29.16 29.17v4.17c16.66 104.16 83.33 179.16 220.83 200v100c0 16.66 12.5 29.16 33.33 33.33h62.5c16.67 0 29.17-12.5 33.34-33.33v-100c125-20.84 208.33-108.34 208.33-220.84z\" fill=\"#fff\"/><path d=\"M787.5 1595.83c-325-116.66-491.67-479.16-370.83-800 62.5-175 200-308.33 370.83-370.83 16.67-8.33 25-20.83 25-41.67V325c0-16.67-8.33-29.17-25-33.33-4.17 0-12.5 0-16.67 4.16-395.83 125-612.5 545.84-487.5 941.67 75 233.33 254.17 412.5 487.5 487.5 16.67 8.33 33.34 0 37.5-16.67 4.17-4.16 4.17-8.33 4.17-16.66v-58.34c0-12.5-12.5-29.16-25-37.5zM1229.17 295.83c-16.67-8.33-33.34 0-37.5 16.67-4.17 4.17-4.17 8.33-4.17 16.67v58.33c0 16.67 12.5 33.33 25 41.67 325 116.66 491.67 479.16 370.83 800-62.5 175-200 308.33-370.83 370.83-16.67 8.33-25 20.83-25 41.67V1700c0 16.67 8.33 29.17 25 33.33 4.17 0 12.5 0 16.67-4.16 395.83-125 612.5-545.84 487.5-941.67-75-237.5-258.34-416.67-487.5-491.67z\" fill=\"#fff\"/></svg>`;\n\n/* ------------------------------------------------------------------ */\n/* Dexter crest SVG (inline, ~40px display) */\n/* ------------------------------------------------------------------ */\nconst DEXTER_CREST_SVG = `<svg width=\"36\" height=\"36\" viewBox=\"0 0 300 300\" xmlns=\"http://www.w3.org/2000/svg\"><g><path fill=\"#F2681A\" d=\"m324.93,313.11c-115.5,0-231,0-350,0l350,0z\"/><path fill=\"#FDFAF5\" d=\"m230.43,50.62c1.1.85 2.19 1.7 3.32 2.57 6.02 4.8 11.77 9.88 17.46 15.07.92.84.92.84 1.86 1.69 1.82 1.69 3.59 3.42 5.35 5.16.61.56 1.22 1.13 1.84 1.71 5.66 5.76 6.18 10.43 6.13 18.3.02 1.16.04 2.32.06 3.52.06 3.83.06 7.65.07 11.48.02 2.68.05 5.35.08 8.03.05 5.6.09 11.21.1 16.81.02 7.15.09 14.31.17 21.46.06 5.53.1 11.05.13 16.58.02 2.64.04 5.27.07 7.91.18 17.58.12 32.82-11.24 47.32-7.35 7.27-16.54 12.06-25.42 17.22-1.97 1.16-3.94 2.33-5.91 3.49-7.16 4.24-14.34 8.44-21.53 12.62-4.8 2.79-9.59 5.6-14.38 8.42-1.25.73-2.5 1.47-3.79 2.23-2.32 1.36-4.64 2.73-6.96 4.1-27.47 16.09-27.47 16.09-42.16 12.93-8.06-2.28-14.94-5.82-22.16-10.02-1.17-.67-2.34-1.34-3.54-2.04-24.55-14.25-43.58-27.03-51.9-55.58-1.07-4.58-1.54-8.92-1.52-13.61.28-9.5.28-9.5-3.3-17.97-1.81-1.49-3.68-2.92-5.59-4.28-9.19-7.06-12.7-20.03-14.18-31.06-.54-5.77-.55-11.56-.6-17.35-.03-1.32-.07-2.63-.1-3.99-.01-1.26-.02-2.53-.03-3.83-.02-1.15-.03-2.29-.05-3.47.72-4.02 1.94-5.36 5.21-7.74 2.89-.53 2.89-.53 6.07-.46 1.71.02 1.71.02 3.46.05 1.19.04 2.37.08 3.59.12 1.2.02 2.41.04 3.65.06 2.97.05 5.93.13 8.9.23.14-1.35.29-2.7.43-4.08.63-5 1.78-9.74 3.14-14.58.22-.79.43-1.59.66-2.4.53-1.92 1.06-3.84 1.6-5.76-1.55-.45-1.55-.45-3.13-.9-9.52-3.52-17.1-10.95-21.37-20.1-3.81-9.26-3.87-20.34-.29-29.68 6.49-13.99 16.36-23.23 30.66-29.01 49.81-17.69 115.79 8.35 155.13 38.85z\"/><path fill=\"#F2671A\" d=\"m142.93,22.62c.86.19 1.73.39 2.62.59 36.12 8.21 68.79 24.98 95.38 50.75 1.02.98 2.03 1.97 3.08 2.98 10.84 10.66 10.84 10.66 11.05 14.62-2.06 3.55-5.44 4.18-9.17 5.3-.79.25-1.59.49-2.41.75-28.13 8.43-60.95 6.37-87.13-7.16-.86-.49-1.71-.97-2.6-1.48-7.37-4.05-12.59-3.36-20.59-1.54-22.76 4-48.47 1.53-68.69-9.74-4.88-3.88-8.23-8.29-10.21-14.22-.93-10.38-.67-18.44 5.83-26.83 19.57-23.38 55.99-20.36 82.83-14z\"/><path fill=\"#F16619\" d=\"m44.93,129.12c27.36-.03 54.72-.05 82.08-.06 12.7-.01 25.41-.01 38.11-.03 11.07-.01 22.14-.02 33.2-.02 5.86 0 11.73-.01 17.59-.01 5.51-.01 11.03-.01 16.54-.01 2.03 0 4.06 0 6.09-.01 2.76-.01 5.52 0 8.28 0 .81 0 1.63-.01 2.47-.01 5.51.02 5.51.02 6.81 1.32.22 3.43.22 3.43 0 7-2.75 2.75-3.42 2.66-7.15 2.82-1.41.07-1.41.07-2.85.14-1.47.05-1.47.05-2.98.11-1.49.07-1.49.07-3 .14-2.45.11-4.9.21-7.35.3-.2 1.3-.4 2.59-.6 3.93-2.57 16.08-5.93 29.89-18.89 40.86-10.35 7.28-21.87 8.49-34.17 7.71-13.11-2.33-22.52-9.19-30.33-19.83-4.49-7.64-4.8-17.05-5.83-25.67-4.24.39-8.47.77-12.83 1.17-.28 1.84-.28 1.84-.56 3.71-2.32 14.39-5.63 23.35-16.95 33.11-2.32 1.67-2.32 1.67-4.65 1.67 4 4.67 9.06 6.59 14.87 8.24 3.79 1.09 3.79 1.09 6.12 3.43-.65 5.31-.65 5.31-2.33 7-8.42-.27-15.13-2.29-22.17-7-1.09-1.21-2.17-2.43-3.25-3.65-2.72-2.81-4.45-3.84-8.36-4.16-1.67-.02-3.34-.02-5.01.01-1.77-.04-3.54-.09-5.3-.15-1.27-.04-1.27-.04-2.56-.08-9.26-.54-17.6-4.56-24.51-10.64-9.58-11.11-11.03-22.56-10.72-36.82.02-1.4.03-2.8.05-4.24.04-3.42.1-6.85.17-10.27z\"/><path fill=\"#F26117\" d=\"m172.68,203.08c7.27.09 13.23 1.97 18.87 6.65 2.88 3.07 3.86 5.12 4.25 9.32-.12 1.01-.24 2.02-.36 3.06-2.55.95-2.55.95-5.83 1.17-3.28-2.84-3.28-2.84-5.83-5.83-.36.58-.71 1.16-1.08 1.75-7.6 11.29-20.06 17.74-33.05 21.09-20.36 3.1-36.81-1.66-53.37-13.73-2.33-2.11-2.33-2.11-4.67-5.61.42-3.45.99-4.49 3.5-7 4.07.37 5.95 2.13 8.75 4.96 9.81 8.93 22.53 11.87 35.51 11.69 11.74-1.05 22.38-5.85 31.57-13.15 2.06-2.45 2.06-2.45 3.5-4.67-1.66.07-1.66.07-3.35.15-3.65-.15-3.65-.15-5.98-2.48.75-6.18 1.46-7.19 7.58-7.36z\"/></g></svg>`;\n\n/* ------------------------------------------------------------------ */\n/* Shared CSS for all Dexter-branded pages */\n/* ------------------------------------------------------------------ */\nconst DEXTER_STYLES = `\n@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Orbitron:wght@500;700&display=swap');\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:'Inter',system-ui,-apple-system,sans-serif;background:#0a0a0a;color:#e2e8f0;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:1rem}\n.card{max-width:460px;width:100%;background:rgba(20,20,20,.85);border:1px solid rgba(242,107,26,.12);border-radius:8px;padding:2rem 2rem 1.75rem;text-align:center;backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px)}\n.crest{margin:0 auto .75rem}\nh1{font-family:'Orbitron',sans-serif;font-size:1.15rem;font-weight:700;color:#f1f5f9;letter-spacing:.04em;margin-bottom:.35rem}\n.desc{color:#94a3b8;font-size:.9rem;margin-bottom:1.25rem;line-height:1.5}\n.price{font-family:'Orbitron',sans-serif;font-size:1.6rem;font-weight:700;color:#F26B1A;margin:.75rem 0 .25rem;display:inline-flex;align-items:center;gap:.35rem}\n.price svg{width:1.3em;height:1.3em;flex-shrink:0}\n.chain{color:#525252;font-size:.75rem;margin-bottom:1.25rem;letter-spacing:.03em}\n.endpoint{background:rgba(242,107,26,.06);border:1px solid rgba(242,107,26,.12);border-radius:6px;padding:.5rem .75rem;margin-bottom:1.25rem}\n.endpoint code{font-family:'SF Mono',Monaco,Consolas,monospace;font-size:.8rem;color:#F26B1A}\n.info{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);border-radius:6px;padding:.85rem 1rem;font-size:.82rem;color:#737373;line-height:1.6;text-align:left}\n.info strong{color:#a3a3a3}\n.info code{background:rgba(242,107,26,.08);padding:2px 5px;border-radius:3px;font-size:.78rem;color:#F26B1A;font-family:'SF Mono',Monaco,Consolas,monospace}\n.info a{color:#F26B1A;text-decoration:none;font-weight:600}\n.info a:hover{text-decoration:underline}\n.footer{margin-top:1.25rem;display:flex;align-items:center;justify-content:center;gap:.75rem;font-size:.7rem;color:#404040}\n.footer a{color:#525252;text-decoration:none}\n.footer a:hover{color:#737373}\n.sep{width:3px;height:3px;border-radius:50%;background:#333}\n`;\n\n/* ------------------------------------------------------------------ */\n/* Pay button styles + states */\n/* ------------------------------------------------------------------ */\nconst PAY_BUTTON_STYLES = `\n.pay-section{margin:1.25rem 0}\n.pay-btn{display:inline-flex;align-items:center;justify-content:center;gap:.5rem;background:linear-gradient(135deg,#F26B1A,#D13F00);color:#fff;border:none;padding:.65rem 2rem;border-radius:6px;font-family:'Inter',sans-serif;font-size:.95rem;font-weight:600;cursor:pointer;transition:opacity .15s,transform .1s;min-width:180px}\n.pay-btn:hover:not(:disabled){opacity:.9;transform:translateY(-1px)}\n.pay-btn:active:not(:disabled){transform:translateY(0)}\n.pay-btn:disabled{opacity:.6;cursor:not-allowed}\n.pay-btn .spinner{width:16px;height:16px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:spin .6s linear infinite}\n@keyframes spin{to{transform:rotate(360deg)}}\n.pay-status{font-size:.8rem;color:#737373;margin-top:.5rem;min-height:1.2em}\n.pay-status.error{color:#ef4444}\n.pay-status.success{color:#22c55e}\n.pay-alt{font-size:.78rem;color:#404040;margin-top:.75rem}\n.pay-alt a{color:#F26B1A;text-decoration:none}\n.result-box{background:rgba(34,197,94,.06);border:1px solid rgba(34,197,94,.15);border-radius:6px;padding:.75rem;margin-top:.75rem;text-align:left;font-size:.78rem;max-height:200px;overflow:auto}\n.result-box pre{color:#94a3b8;font-family:'SF Mono',Monaco,Consolas,monospace;white-space:pre-wrap;word-break:break-all}\n.no-wallet{font-size:.82rem;color:#737373;margin:1rem 0}\n`;\n\n/* ------------------------------------------------------------------ */\n/* Wallet payment inline script (Solana Wallet Standard) */\n/* ------------------------------------------------------------------ */\nconst PAY_SCRIPT = `\n<script type=\"module\">\n// Payment data is embedded in #x402-data attributes\nconst dataEl = document.getElementById('x402-data');\nif (!dataEl) throw new Error('Missing payment data');\n\nconst requirements = JSON.parse(atob(dataEl.dataset.requirements));\nconst requestMethod = dataEl.dataset.method;\nconst requestUrl = dataEl.dataset.url;\nconst rpcUrl = dataEl.dataset.rpc || 'https://api.dexter.cash/api/solana/rpc';\n\n// Detect wallet provider\nfunction getWalletProvider() {\n if (window.phantom?.solana?.isPhantom) return { name: 'Phantom', provider: window.phantom.solana };\n if (window.solflare?.isSolflare) return { name: 'Solflare', provider: window.solflare };\n if (window.backpack) return { name: 'Backpack', provider: window.backpack };\n // Generic wallet-standard fallback\n if (window.solana) return { name: 'Wallet', provider: window.solana };\n return null;\n}\n\nconst walletInfo = getWalletProvider();\nconst btn = document.getElementById('pay-btn');\nconst status = document.getElementById('pay-status');\nconst section = document.getElementById('pay-section');\nconst noWallet = document.getElementById('no-wallet');\n\nif (walletInfo && btn) {\n section.style.display = 'block';\n if (noWallet) noWallet.style.display = 'none';\n} else if (noWallet) {\n noWallet.style.display = 'block';\n if (section) section.style.display = 'none';\n}\n\n// Preload Solana libraries in background\nlet solanaLibs = null;\nconst preload = (async () => {\n try {\n const [web3, spl] = await Promise.all([\n import('https://esm.sh/@solana/web3.js@1.98.0'),\n import('https://esm.sh/@solana/spl-token@0.4.9'),\n ]);\n solanaLibs = { web3, spl };\n } catch (e) {\n console.warn('[x402] Failed to preload Solana libraries:', e);\n }\n})();\n\nfunction setStatus(msg, type) {\n if (!status) return;\n status.textContent = msg;\n status.className = 'pay-status' + (type ? ' ' + type : '');\n}\n\nfunction setBtnState(text, disabled, loading) {\n if (!btn) return;\n btn.disabled = disabled;\n btn.innerHTML = loading\n ? '<span class=\"spinner\"></span>' + text\n : text;\n}\n\nif (btn) {\n btn.addEventListener('click', async () => {\n if (!walletInfo) return;\n const { provider } = walletInfo;\n\n try {\n // 1. Connect wallet\n setBtnState('Connecting...', true, true);\n setStatus('');\n await provider.connect();\n\n if (!provider.publicKey) {\n throw new Error('Wallet did not provide a public key');\n }\n\n // 2. Load Solana libraries (should already be cached from preload)\n setBtnState('Preparing...', true, true);\n await preload;\n if (!solanaLibs) {\n // Retry once\n const [web3, spl] = await Promise.all([\n import('https://esm.sh/@solana/web3.js@1.98.0'),\n import('https://esm.sh/@solana/spl-token@0.4.9'),\n ]);\n solanaLibs = { web3, spl };\n }\n\n const { web3, spl } = solanaLibs;\n const { PublicKey, Connection, TransactionMessage, VersionedTransaction, ComputeBudgetProgram } = web3;\n const { getAssociatedTokenAddress, createTransferCheckedInstruction, getMint, TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID } = spl;\n\n // 3. Parse payment requirements\n const accept = requirements.accepts[0];\n if (!accept) throw new Error('No payment method available');\n\n const payTo = new PublicKey(accept.payTo);\n const amount = BigInt(accept.amount ?? accept.maxAmountRequired);\n const mintPubkey = new PublicKey(accept.asset);\n const feePayer = accept.extra?.feePayer ? new PublicKey(accept.extra.feePayer) : provider.publicKey;\n const userPubkey = provider.publicKey;\n\n // 4. Build transaction\n setBtnState('Building tx...', true, true);\n const connection = new Connection(rpcUrl, 'confirmed');\n\n const instructions = [];\n\n // ComputeBudget\n instructions.push(ComputeBudgetProgram.setComputeUnitLimit({ units: 12000 }));\n instructions.push(ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }));\n\n // Determine token program\n const mintInfo = await connection.getAccountInfo(mintPubkey, 'confirmed');\n if (!mintInfo) throw new Error('Token mint not found');\n const programId = mintInfo.owner.toBase58() === TOKEN_2022_PROGRAM_ID.toBase58() ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;\n\n const mint = await getMint(connection, mintPubkey, undefined, programId);\n\n // ATAs\n const sourceAta = await getAssociatedTokenAddress(mintPubkey, userPubkey, false, programId);\n const destAta = await getAssociatedTokenAddress(mintPubkey, payTo, false, programId);\n\n // Verify source exists\n const sourceInfo = await connection.getAccountInfo(sourceAta, 'confirmed');\n if (!sourceInfo) throw new Error('No USDC token account found. Make sure you have USDC in your wallet.');\n\n // TransferChecked\n instructions.push(createTransferCheckedInstruction(sourceAta, mintPubkey, destAta, userPubkey, amount, mint.decimals, [], programId));\n\n const { blockhash } = await connection.getLatestBlockhash('confirmed');\n const message = new TransactionMessage({ payerKey: feePayer, recentBlockhash: blockhash, instructions }).compileToV0Message();\n const transaction = new VersionedTransaction(message);\n\n // 5. Sign\n setBtnState('Sign in wallet...', true, true);\n setStatus('Approve the transaction in your wallet');\n const signed = await provider.signTransaction(transaction);\n const serialized = signed.serialize();\n\n // Convert Uint8Array to base64\n let payload = '';\n const bytes = new Uint8Array(serialized);\n const chunk = 8192;\n for (let i = 0; i < bytes.length; i += chunk) {\n payload += String.fromCharCode.apply(null, bytes.slice(i, i + chunk));\n }\n payload = btoa(payload);\n\n // 6. Build payment-signature header (x402 v2 format)\n // Solana: payload must be { transaction: base64Tx } per SDK spec\n const paymentSignature = {\n x402Version: accept.x402Version ?? 2,\n resource: requirements.resource,\n accepted: accept,\n payload: { transaction: payload },\n };\n const paymentHeader = btoa(JSON.stringify(paymentSignature));\n\n // 7. Submit payment\n setBtnState('Verifying...', true, true);\n setStatus('Payment submitted, verifying...');\n\n // Use the original request body if available\n const originalBody = dataEl.dataset.body ? atob(dataEl.dataset.body) : '{}';\n const response = await fetch(requestUrl, {\n method: requestMethod,\n headers: {\n 'Content-Type': 'application/json',\n 'PAYMENT-SIGNATURE': paymentHeader,\n },\n body: requestMethod !== 'GET' ? originalBody : undefined,\n });\n\n if (response.ok) {\n const data = await response.json();\n setBtnState('Paid', true, false);\n setStatus('Payment successful', 'success');\n // Show response\n const resultBox = document.createElement('div');\n resultBox.className = 'result-box';\n resultBox.innerHTML = '<pre>' + JSON.stringify(data, null, 2).replace(/</g, '<') + '</pre>';\n section.appendChild(resultBox);\n } else {\n const err = await response.json().catch(() => ({ error: 'Payment verification failed' }));\n throw new Error(err.error || err.reason || 'Payment failed');\n }\n } catch (err) {\n console.error('[x402] Payment error:', err);\n setBtnState('Pay ' + document.getElementById('price-value').textContent, false, false);\n setStatus(err.message || 'Payment failed', 'error');\n }\n });\n}\n</script>\n`;\n\n/**\n * Generate the Dexter-branded paywall HTML with wallet pay button.\n */\nfunction generatePaywallHtml(\n paymentRequiredHeader: string,\n requestUrl: string,\n method: string,\n config: Required<Pick<X402BrowserSupportConfig, 'title' | 'branding' | 'sdkUrl' | 'showEndpoint'>>,\n rpcUrl: string,\n requestBody?: string,\n): string {\n let price = '?';\n let description = 'This resource requires payment';\n let network = '';\n\n try {\n const decoded = JSON.parse(Buffer.from(paymentRequiredHeader, 'base64').toString());\n const accept = decoded.accepts?.[0];\n if (accept) {\n const amount = accept.amount ?? accept.maxAmountRequired ?? '0';\n const decimals = accept.extra?.decimals || 6;\n price = (Number(amount) / Math.pow(10, decimals)).toFixed(decimals > 4 ? 4 : 2);\n network = accept.network || '';\n }\n if (decoded.resource?.description) {\n description = decoded.resource.description;\n }\n } catch {\n // If we can't decode, show generic paywall\n }\n\n const chainName = network.includes('solana')\n ? 'Solana'\n : network.includes('eip155')\n ? 'Base'\n : '';\n\n const endpointSection = config.showEndpoint\n ? `<div class=\"endpoint\"><code>${esc(method)} ${esc(requestUrl)}</code></div>`\n : '';\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n<title>${esc(config.title)} — ${esc(price)} USDC</title>\n<style>${DEXTER_STYLES}${PAY_BUTTON_STYLES}</style>\n</head>\n<body>\n<div class=\"card\">\n <div class=\"crest\">${DEXTER_CREST_SVG}</div>\n <h1>${esc(config.title)}</h1>\n <p class=\"desc\">${esc(description)}</p>\n <div class=\"price\">${USDC_ICON_SVG}<span id=\"price-value\">${esc(price)}</span></div>\n <div class=\"chain\">${esc(chainName)}${chainName ? ' network' : ''}</div>\n ${endpointSection}\n\n <div id=\"pay-section\" class=\"pay-section\" style=\"display:none\">\n <button id=\"pay-btn\" class=\"pay-btn\">Pay ${price}</button>\n <div id=\"pay-status\" class=\"pay-status\"></div>\n <div class=\"pay-alt\">or use <a href=\"${config.sdkUrl}\">x402 SDK</a> for programmatic access</div>\n </div>\n\n <div id=\"no-wallet\" class=\"no-wallet\" style=\"display:none\">\n <div class=\"info\">\n <strong>Access this endpoint:</strong><br><br>\n Use any x402-compatible client or a browser with a Solana wallet extension (Phantom, Solflare, Backpack).<br><br>\n <code>npm install @dexterai/x402</code><br><br>\n <a href=\"${config.sdkUrl}\">x402 SDK docs →</a>\n </div>\n </div>\n\n <div class=\"footer\">\n <a href=\"https://docs.dexter.cash/docs/sdk/\">x402</a>\n <span class=\"sep\"></span>\n <a href=\"https://dexter.cash\">Dexter</a>\n </div>\n</div>\n\n<div id=\"x402-data\" style=\"display:none\"\n data-requirements=\"${paymentRequiredHeader}\"\n data-method=\"${method}\"\n data-url=\"${requestUrl}\"\n data-rpc=\"${rpcUrl}\"\n data-body=\"${requestBody ? Buffer.from(requestBody).toString('base64') : ''}\"\n></div>\n${PAY_SCRIPT}\n</body>\n</html>`;\n}\n\n/**\n * Create x402 browser support middleware.\n *\n * Wraps `res.json()` to intercept 402 Payment Required responses.\n * When the request is from a browser (Accept: text/html) and no\n * payment-signature header is present, renders a branded HTML paywall\n * instead of raw JSON.\n *\n * API clients are completely unaffected -- they receive normal JSON.\n */\nexport function x402BrowserSupport(config: X402BrowserSupportConfig = {}): RequestHandler {\n const resolvedConfig = {\n title: config.title ?? 'Payment Required',\n branding: config.branding ?? 'Powered by <a href=\"https://docs.dexter.cash/docs/sdk/\">Dexter x402</a>',\n sdkUrl: config.sdkUrl ?? 'https://docs.dexter.cash/docs/sdk/',\n showEndpoint: config.showEndpoint ?? true,\n };\n const rpcUrl = config.rpcUrl ?? 'https://api.dexter.cash/api/solana/rpc';\n\n return (req: Request, res: Response, next: NextFunction): void => {\n const originalJson = res.json.bind(res);\n\n res.json = function (body: unknown) {\n if (\n res.statusCode === 402 &&\n req.accepts('html') &&\n !req.headers['payment-signature']\n ) {\n const paymentRequired =\n (res.getHeader('PAYMENT-REQUIRED') as string) ||\n (res.getHeader('payment-required') as string);\n\n if (paymentRequired && typeof paymentRequired === 'string') {\n // Capture the original request body for the pay button\n let bodyStr: string | undefined;\n if (req.body && typeof req.body === 'object' && Object.keys(req.body).length > 0) {\n try { bodyStr = JSON.stringify(req.body); } catch { /* ignore */ }\n }\n const html = generatePaywallHtml(\n paymentRequired,\n req.originalUrl,\n req.method,\n resolvedConfig,\n rpcUrl,\n bodyStr,\n );\n res.status(402).type('html').send(html);\n return res;\n }\n }\n\n return originalJson(body);\n } as typeof res.json;\n\n next();\n };\n}\n","/**\n * x402 Access Pass Middleware\n *\n * Pay once, get a time-limited JWT for unlimited API requests.\n * Supports both predefined tiers and custom durations.\n *\n * @example Tier-based pricing\n * ```typescript\n * app.use('/api', x402AccessPass({\n * payTo: 'YourSolanaAddress...',\n * tiers: {\n * '1h': '0.50', // $0.50 for 1 hour\n * '24h': '2.00', // $2.00 for 24 hours\n * },\n * }));\n * ```\n *\n * @example Rate-based custom durations\n * ```typescript\n * app.use('/api', x402AccessPass({\n * payTo: 'YourSolanaAddress...',\n * ratePerHour: '0.50', // $0.50/hour, any duration\n * }));\n * ```\n *\n * @example Both tiers and custom durations\n * ```typescript\n * app.use('/api', x402AccessPass({\n * payTo: 'YourSolanaAddress...',\n * tiers: { '1h': '0.50', '24h': '2.00' },\n * ratePerHour: '0.50', // fallback for custom durations\n * }));\n * ```\n */\n\nimport type { Request, Response, NextFunction, RequestHandler } from 'express';\nimport { createX402Server } from './x402-server';\nimport { toAtomicUnits, encodeBase64Json } from '../utils';\nimport type { AccessPassTier, AccessPassInfo, AccessPassClaims } from '../types';\nimport crypto from 'crypto';\n\n// ============================================================================\n// Configuration\n// ============================================================================\n\n/**\n * Access pass middleware configuration\n */\nexport interface X402AccessPassConfig {\n /** Address to receive payments (Solana pubkey or EVM address) */\n payTo: string;\n\n /** CAIP-2 network identifier @default 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' */\n network?: string;\n\n /** x402 facilitator URL @default 'https://x402.dexter.cash' */\n facilitatorUrl?: string;\n\n /** Asset config @default USDC on specified network */\n asset?: { address: string; decimals: number };\n\n /**\n * Predefined pricing tiers.\n * Keys are tier IDs (e.g., '5m', '1h', '24h').\n * Values are prices in USD (e.g., '0.50').\n * Duration is parsed from the ID: '5m' = 5 minutes, '1h' = 1 hour, '24h' = 24 hours, '7d' = 7 days.\n */\n tiers?: Record<string, string>;\n\n /**\n * Rate per hour in USD for custom durations.\n * When set, buyers can request any duration via ?duration=<seconds> query param.\n */\n ratePerHour?: string;\n\n /** HMAC secret for JWT signing. Auto-generated if not provided. */\n secret?: Buffer;\n\n /** Issuer string for JWT 'iss' claim @default 'x402-access-pass' */\n issuer?: string;\n\n /** Enable verbose logging */\n verbose?: boolean;\n\n /** Description shown in 402 response */\n description?: string;\n}\n\n/**\n * Extended request with access pass info\n */\nexport interface X402AccessPassRequest extends Request {\n /** Access pass info (present when request is authenticated via valid pass) */\n accessPass?: {\n tier: string;\n duration: number;\n expiresAt: string;\n payer: string;\n network: string;\n };\n /** x402 payment info (present when a new pass was just purchased) */\n x402?: {\n transaction: string;\n payer: string;\n network: string;\n };\n}\n\n// ============================================================================\n// Duration Parsing\n// ============================================================================\n\nconst DURATION_REGEX = /^(\\d+)(m|h|d|w)$/;\n\nfunction parseTierDuration(tierId: string): number | null {\n const match = tierId.match(DURATION_REGEX);\n if (!match) return null;\n\n const value = parseInt(match[1], 10);\n const unit = match[2];\n\n switch (unit) {\n case 'm': return value * 60;\n case 'h': return value * 3600;\n case 'd': return value * 86400;\n case 'w': return value * 604800;\n default: return null;\n }\n}\n\nfunction formatDuration(seconds: number): string {\n if (seconds >= 604800 && seconds % 604800 === 0) return `${seconds / 604800} week${seconds / 604800 > 1 ? 's' : ''}`;\n if (seconds >= 86400 && seconds % 86400 === 0) return `${seconds / 86400} day${seconds / 86400 > 1 ? 's' : ''}`;\n if (seconds >= 3600 && seconds % 3600 === 0) return `${seconds / 3600} hour${seconds / 3600 > 1 ? 's' : ''}`;\n if (seconds >= 60 && seconds % 60 === 0) return `${seconds / 60} minute${seconds / 60 > 1 ? 's' : ''}`;\n return `${seconds} second${seconds > 1 ? 's' : ''}`;\n}\n\n// ============================================================================\n// JWT Helpers (built-in crypto, no external deps)\n// ============================================================================\n\nfunction signJwt(payload: AccessPassClaims, secret: Buffer): string {\n const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');\n const body = Buffer.from(JSON.stringify(payload)).toString('base64url');\n const sig = crypto.createHmac('sha256', secret).update(`${header}.${body}`).digest('base64url');\n return `${header}.${body}.${sig}`;\n}\n\nfunction verifyJwt(token: string, secret: Buffer): AccessPassClaims | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n\n const [header, body, sig] = parts;\n const expected = crypto.createHmac('sha256', secret).update(`${header}.${body}`).digest('base64url');\n if (sig !== expected) return null;\n\n const payload = JSON.parse(Buffer.from(body, 'base64url').toString()) as AccessPassClaims;\n\n // Check expiration\n if (payload.exp && Date.now() / 1000 > payload.exp) return null;\n\n // Validate sub\n if (payload.sub !== 'x402-access-pass') return null;\n\n return payload;\n } catch {\n return null;\n }\n}\n\n// ============================================================================\n// Middleware Factory\n// ============================================================================\n\nconst DEFAULT_NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';\nconst USDC_DECIMALS = 6;\n\n/**\n * Create x402 access pass middleware for Express.\n *\n * Protects routes with time-limited access passes purchased via x402 payments.\n * Supports predefined tiers, custom durations, or both.\n */\nexport function x402AccessPass(config: X402AccessPassConfig): RequestHandler {\n const {\n payTo,\n network = DEFAULT_NETWORK,\n asset,\n facilitatorUrl,\n tiers: tierPrices,\n ratePerHour,\n secret: explicitSecret,\n issuer = 'x402-access-pass',\n verbose = false,\n description,\n } = config;\n\n const secret = explicitSecret ?? crypto.randomBytes(32);\n if (!explicitSecret) {\n console.warn('[x402:access-pass] No secret provided — access passes will be invalidated on server restart. Set `secret` for production use.');\n }\n\n // Validate config\n if (!tierPrices && !ratePerHour) {\n throw new Error('x402AccessPass: at least one of `tiers` or `ratePerHour` is required');\n }\n\n const log = verbose\n ? console.log.bind(console, '[x402:access-pass]')\n : () => {};\n\n const decimals = asset?.decimals ?? USDC_DECIMALS;\n\n // Build tier definitions\n const builtTiers: AccessPassTier[] = [];\n\n if (tierPrices) {\n for (const [id, price] of Object.entries(tierPrices)) {\n const seconds = parseTierDuration(id);\n if (!seconds) {\n console.warn(`x402AccessPass: skipping tier \"${id}\" — unrecognized duration format (use 5m, 1h, 24h, 7d)`);\n continue;\n }\n builtTiers.push({\n id,\n label: formatDuration(seconds),\n seconds,\n price,\n priceAtomic: toAtomicUnits(parseFloat(price), decimals),\n });\n }\n // Sort by duration ascending\n builtTiers.sort((a, b) => a.seconds - b.seconds);\n }\n\n // Create x402 server instance (reused across requests)\n const server = createX402Server({\n payTo,\n network,\n asset,\n facilitatorUrl,\n });\n\n // Build access pass info for X-ACCESS-PASS-TIERS header\n const passInfo: AccessPassInfo = {\n tiers: builtTiers.length > 0 ? builtTiers : undefined,\n ratePerHour: ratePerHour || undefined,\n issuer,\n };\n const passInfoEncoded = encodeBase64Json(passInfo);\n\n /**\n * Calculate price for a custom duration in seconds\n */\n function calculateCustomPrice(durationSeconds: number): { price: string; priceAtomic: string } {\n if (!ratePerHour) {\n throw new Error('Custom durations not supported — no ratePerHour configured');\n }\n const hours = durationSeconds / 3600;\n const price = (parseFloat(ratePerHour) * hours).toFixed(decimals > 4 ? 4 : 2);\n return { price, priceAtomic: toAtomicUnits(parseFloat(price), decimals) };\n }\n\n /**\n * Resolve tier/duration from request query params\n */\n function resolvePricing(req: Request): {\n tier: string;\n seconds: number;\n price: string;\n priceAtomic: string;\n label: string;\n } {\n const tierParam = req.query.tier as string | undefined;\n const durationParam = req.query.duration as string | undefined;\n\n // Explicit tier\n if (tierParam) {\n const found = builtTiers.find(t => t.id === tierParam);\n if (found) {\n return { tier: found.id, seconds: found.seconds, price: found.price, priceAtomic: found.priceAtomic, label: found.label };\n }\n }\n\n // Custom duration\n if (durationParam) {\n const seconds = parseInt(durationParam, 10);\n if (seconds > 0 && ratePerHour) {\n const pricing = calculateCustomPrice(seconds);\n return { tier: 'custom', seconds, ...pricing, label: formatDuration(seconds) };\n }\n }\n\n // Default: cheapest tier or 1h\n if (builtTiers.length > 0) {\n const t = builtTiers[0];\n return { tier: t.id, seconds: t.seconds, price: t.price, priceAtomic: t.priceAtomic, label: t.label };\n }\n\n // Rate-only: default to 1 hour\n const pricing = calculateCustomPrice(3600);\n return { tier: 'custom', seconds: 3600, ...pricing, label: '1 hour' };\n }\n\n // --------------------------------------------------------------------------\n // Middleware handler\n // --------------------------------------------------------------------------\n return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n try {\n // ── Step 1: Check for valid access pass JWT ──\n const auth = req.headers.authorization;\n if (auth?.startsWith('Bearer ')) {\n const claims = verifyJwt(auth.slice(7), secret);\n if (claims) {\n log('Valid access pass:', claims.tier, '| expires:', new Date(claims.exp * 1000).toISOString());\n (req as X402AccessPassRequest).accessPass = {\n tier: claims.tier,\n duration: claims.duration,\n expiresAt: new Date(claims.exp * 1000).toISOString(),\n payer: claims.payer,\n network: claims.network,\n };\n return next();\n }\n log('Invalid or expired access pass token');\n }\n\n // ── Step 2: Check for x402 payment signature (pass purchase) ──\n const paymentSignature = req.headers['payment-signature'] as string | undefined;\n\n if (paymentSignature) {\n log('Payment signature received, verifying for pass purchase...');\n\n // Verify payment\n const verifyResult = await server.verifyPayment(paymentSignature);\n if (!verifyResult.isValid) {\n log('Payment verification failed:', verifyResult.invalidReason);\n res.status(402).json({ error: 'Payment verification failed', reason: verifyResult.invalidReason });\n return;\n }\n\n // Settle payment\n const settleResult = await server.settlePayment(paymentSignature);\n if (!settleResult.success) {\n log('Payment settlement failed:', settleResult.errorReason);\n res.status(402).json({ error: 'Payment settlement failed', reason: settleResult.errorReason });\n return;\n }\n\n log('Payment settled:', settleResult.transaction);\n\n // Determine tier/duration\n const pricing = resolvePricing(req);\n\n // Issue JWT\n const now = Math.floor(Date.now() / 1000);\n const claims: AccessPassClaims = {\n sub: 'x402-access-pass',\n tier: pricing.tier,\n duration: pricing.seconds,\n iat: now,\n exp: now + pricing.seconds,\n payer: verifyResult.payer ?? '',\n network,\n iss: issuer,\n };\n const jwt = signJwt(claims, secret);\n\n // Set x402 payment info on request\n (req as X402AccessPassRequest).x402 = {\n transaction: settleResult.transaction!,\n payer: verifyResult.payer ?? '',\n network,\n };\n\n // Set PAYMENT-RESPONSE header per x402 v2 spec\n const paymentResponseData = {\n success: true,\n transaction: settleResult.transaction!,\n network,\n payer: verifyResult.payer ?? '',\n };\n res.setHeader('PAYMENT-RESPONSE', encodeBase64Json(paymentResponseData));\n\n // Set ACCESS-PASS header with the JWT\n res.setHeader('ACCESS-PASS', jwt);\n\n // Return pass details\n res.json({\n accessPass: {\n token: jwt,\n tier: pricing.tier,\n duration: pricing.label,\n durationSeconds: pricing.seconds,\n expiresAt: new Date((now + pricing.seconds) * 1000).toISOString(),\n usage: 'Include on subsequent requests as: Authorization: Bearer <token>',\n },\n transaction: settleResult.transaction,\n payer: verifyResult.payer,\n });\n return;\n }\n\n // ── Step 3: No pass, no payment — return 402 ──\n log('No access pass or payment, returning 402');\n\n const pricing = resolvePricing(req);\n const amountAtomic = pricing.priceAtomic;\n const resourceUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;\n\n const requirements = await server.buildRequirements({\n amountAtomic,\n resourceUrl,\n description: description || `Access pass: ${pricing.label}`,\n mimeType: 'application/json',\n });\n\n const encoded = server.encodeRequirements(requirements);\n\n res.setHeader('PAYMENT-REQUIRED', encoded);\n res.setHeader('X-ACCESS-PASS-TIERS', passInfoEncoded);\n\n res.status(402).json({\n error: 'Access pass required',\n message: 'Purchase an access pass to unlock unlimited API access for a time window.',\n accepts: requirements.accepts,\n resource: requirements.resource,\n accessPass: {\n tiers: builtTiers.length > 0 ? builtTiers : undefined,\n ratePerHour: ratePerHour || undefined,\n usage: 'Add ?tier=<id> or ?duration=<seconds> to your payment request to choose a pass duration.',\n },\n });\n } catch (error) {\n log('Access pass middleware error:', error);\n res.status(500).json({\n error: 'Payment processing error',\n message: error instanceof Error ? error.message : 'Unknown error',\n });\n }\n };\n}\n","/**\n * Dynamic Pricing for x402\n *\n * Calculate prices based on input length (characters, tokens, etc.)\n * Perfect for LLM/AI endpoints where cost scales with input size.\n *\n * @example\n * ```typescript\n * import { createDynamicPricing } from '@dexterai/x402/server';\n *\n * const pricing = createDynamicPricing({\n * unitSize: 1000, // chars per billing unit\n * ratePerUnit: 0.01, // $0.01 per unit\n * minUsd: 0.01, // floor\n * maxUsd: 10.00, // ceiling (optional)\n * });\n *\n * // Calculate price from input\n * const quote = pricing.calculate(userPrompt);\n * // → { amountAtomic: '23000', usdAmount: 0.023, quoteHash: 'abc...', units: 2.3 }\n *\n * // Validate on retry (prevents prompt manipulation)\n * const isValid = pricing.validateQuote(userPrompt, req.headers['x-quote-hash']);\n * ```\n */\n\nimport { createHmac, randomBytes } from 'crypto';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for dynamic pricing\n */\nexport interface DynamicPricingConfig {\n /**\n * Characters per billing unit.\n * Example: 1000 means every 1000 chars = 1 unit\n */\n unitSize: number;\n\n /**\n * USD per unit.\n * Example: 0.01 means $0.01 per unit\n */\n ratePerUnit: number;\n\n /**\n * Minimum USD amount (floor).\n * Recommended: 0.01 (practical minimum for settlement)\n * @default 0.01\n */\n minUsd?: number;\n\n /**\n * Maximum USD amount (ceiling).\n * Optional - prevents unexpectedly large bills.\n */\n maxUsd?: number;\n\n /**\n * Rounding mode for unit calculation.\n * - 'ceil': Always round up (fair to seller)\n * - 'floor': Always round down (fair to buyer)\n * - 'round': Standard rounding\n * @default 'ceil'\n */\n roundingMode?: 'ceil' | 'floor' | 'round';\n\n /**\n * Token decimals for atomic conversion.\n * @default 6 (USDC)\n */\n decimals?: number;\n}\n\n/**\n * Price quote returned by calculate()\n */\nexport interface PriceQuote {\n /** Amount in atomic units (for buildRequirements) */\n amountAtomic: string;\n\n /** Human-readable USD amount (for display) */\n usdAmount: number;\n\n /**\n * Quote hash for validation.\n * Includes input + config, so config changes invalidate quotes.\n * Client should send this back as X-Quote-Hash header.\n */\n quoteHash: string;\n\n /** Number of billing units */\n units: number;\n\n /** Input length in characters */\n inputLength: number;\n}\n\n/**\n * Dynamic pricing calculator\n */\nexport interface DynamicPricing {\n /** Calculate price from input */\n calculate(input: string): PriceQuote;\n\n /** Validate quote hash (returns true if valid) */\n validateQuote(input: string, quoteHash: string): boolean;\n\n /** Get pricing config (for display) */\n readonly config: Required<DynamicPricingConfig>;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/** Max age for a quote before it's considered stale (seconds) */\nconst QUOTE_MAX_AGE_SECONDS = 300; // 5 minutes\n\n/**\n * Create a dynamic pricing calculator\n */\nexport function createDynamicPricing(config: DynamicPricingConfig): DynamicPricing {\n const fullConfig: Required<DynamicPricingConfig> = {\n unitSize: config.unitSize,\n ratePerUnit: config.ratePerUnit,\n minUsd: config.minUsd ?? 0.01,\n maxUsd: config.maxUsd ?? Infinity,\n roundingMode: config.roundingMode ?? 'ceil',\n decimals: config.decimals ?? 6,\n };\n\n const { unitSize, ratePerUnit, minUsd, maxUsd, roundingMode, decimals } = fullConfig;\n\n // Validate config\n if (unitSize <= 0) throw new Error('unitSize must be positive');\n if (ratePerUnit <= 0) throw new Error('ratePerUnit must be positive');\n if (minUsd < 0) throw new Error('minUsd cannot be negative');\n if (maxUsd < minUsd) throw new Error('maxUsd must be >= minUsd');\n\n // Per-instance HMAC secret — quotes are only valid for this pricing instance.\n // Config changes (new instance) automatically invalidate old quotes.\n const hmacSecret = randomBytes(32);\n\n /**\n * Sign a quote with HMAC-SHA256. Includes input, config, and timestamp\n * so quotes are tamper-proof and time-bounded.\n */\n function signQuote(input: string, timestamp: number): string {\n const configStr = JSON.stringify({\n unitSize,\n ratePerUnit,\n minUsd,\n maxUsd: maxUsd === Infinity ? 'none' : maxUsd,\n roundingMode,\n });\n const data = `${input}|${configStr}|${timestamp}`;\n return createHmac('sha256', hmacSecret).update(data).digest('hex').slice(0, 16);\n }\n\n /**\n * Calculate price from input\n */\n function calculate(input: string): PriceQuote {\n const inputLength = input.length;\n\n // Calculate units based on rounding mode\n const rawUnits = inputLength / unitSize;\n let units: number;\n switch (roundingMode) {\n case 'ceil':\n units = Math.ceil(rawUnits);\n break;\n case 'floor':\n units = Math.floor(rawUnits);\n break;\n case 'round':\n units = Math.round(rawUnits);\n break;\n }\n\n // Ensure at least 1 unit if there's any input\n if (inputLength > 0 && units === 0) {\n units = 1;\n }\n\n // Calculate USD amount\n let usdAmount = units * ratePerUnit;\n\n // Apply min/max\n usdAmount = Math.max(minUsd, usdAmount);\n usdAmount = Math.min(maxUsd, usdAmount);\n\n // Convert to atomic units\n const multiplier = Math.pow(10, decimals);\n const amountAtomic = Math.floor(usdAmount * multiplier).toString();\n\n // Sign quote with HMAC-SHA256 (timestamp-bounded)\n const timestamp = Math.floor(Date.now() / 1000);\n const mac = signQuote(input, timestamp);\n const quoteHash = `${timestamp}.${mac}`;\n\n return {\n amountAtomic,\n usdAmount,\n quoteHash,\n units,\n inputLength,\n };\n }\n\n /**\n * Validate quote hash.\n * Verifies HMAC signature and rejects quotes older than QUOTE_MAX_AGE_SECONDS.\n */\n function validateQuote(input: string, quoteHash: string): boolean {\n if (!quoteHash) return false;\n const dotIndex = quoteHash.indexOf('.');\n if (dotIndex === -1) return false;\n\n const timestamp = parseInt(quoteHash.slice(0, dotIndex), 10);\n const mac = quoteHash.slice(dotIndex + 1);\n if (isNaN(timestamp) || !mac) return false;\n\n // Reject stale quotes\n const age = Math.floor(Date.now() / 1000) - timestamp;\n if (age < 0 || age > QUOTE_MAX_AGE_SECONDS) return false;\n\n // Verify HMAC\n const expectedMac = signQuote(input, timestamp);\n // Constant-time comparison to prevent timing attacks\n if (mac.length !== expectedMac.length) return false;\n let mismatch = 0;\n for (let i = 0; i < mac.length; i++) {\n mismatch |= mac.charCodeAt(i) ^ expectedMac.charCodeAt(i);\n }\n return mismatch === 0;\n }\n\n return {\n calculate,\n validateQuote,\n config: fullConfig,\n };\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Format pricing for display\n * Example: \"from $0.01 per 1,000 chars\"\n */\nexport function formatPricing(config: DynamicPricingConfig): string {\n const rate = config.ratePerUnit.toFixed(2);\n const units = config.unitSize.toLocaleString();\n return `from $${rate} per ${units} chars`;\n}\n\n\n\n","/**\n * Token-Based Pricing for x402\n *\n * Accurate LLM pricing using tiktoken for token counting.\n * Uses real OpenAI model rates for precise cost calculation.\n * \n * Pricing data is sourced from the Model Registry (model-registry.ts).\n *\n * @example\n * ```typescript\n * import { createTokenPricing, MODEL_PRICING } from '@dexterai/x402/server';\n *\n * const pricing = createTokenPricing({\n * model: 'gpt-4o-mini',\n * // Optional overrides:\n * // minUsd: 0.001,\n * // maxUsd: 50.0,\n * });\n *\n * // Calculate price from input\n * const quote = pricing.calculate(userPrompt);\n * // → { amountAtomic: '1500', usdAmount: 0.0015, inputTokens: 100, quoteHash: 'abc...' }\n *\n * // Validate on retry (prevents prompt manipulation)\n * const isValid = pricing.validateQuote(userPrompt, req.headers['x-quote-hash']);\n * ```\n */\n\nimport { createHash } from 'crypto';\nimport { MODEL_PRICING_MAP } from './model-registry';\n\n// tiktoken is loaded lazily — only imported when countTokens() is actually called.\n// This avoids the 5MB+ WASM binary cost for consumers who don't use token pricing.\ntype TiktokenModule = typeof import('tiktoken');\nlet _tiktoken: TiktokenModule | null = null;\n\nasync function loadTiktoken(): Promise<TiktokenModule> {\n if (_tiktoken) return _tiktoken;\n try {\n _tiktoken = await import('tiktoken');\n return _tiktoken;\n } catch {\n throw new Error(\n 'Token pricing requires the \"tiktoken\" package. Install with: npm install tiktoken'\n );\n }\n}\n\n// ============================================================================\n// Model Pricing Table\n// ============================================================================\n\n/**\n * Pricing info for a model\n */\nexport interface ModelPricing {\n /** USD per 1M input tokens */\n input: number;\n /** USD per 1M output tokens */\n output: number;\n /** USD per 1M cached input tokens (optional) */\n cached?: number;\n /** Default max output tokens for this model */\n maxTokens: number;\n /** Pricing tier */\n tier: 'fast' | 'standard' | 'reasoning' | 'premium' | 'specialized' | 'custom';\n}\n\n/**\n * OpenAI Model Pricing - USD per million tokens\n * \n * This is now sourced from the Model Registry (model-registry.ts).\n * The registry is the single source of truth for all model information.\n * \n * Updated: January 2026\n */\nexport const MODEL_PRICING: Record<string, ModelPricing> = MODEL_PRICING_MAP as Record<string, ModelPricing>;\n\n// Default model for fallback\nconst DEFAULT_MODEL = 'gpt-4o-mini';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Configuration for token-based pricing\n */\nexport interface TokenPricingConfig {\n /**\n * Model name. Used for display and to look up built-in pricing.\n * If not in MODEL_PRICING and no custom rates provided, falls back to gpt-4o-mini rates.\n */\n model?: string;\n\n /**\n * Custom input rate (USD per 1M tokens).\n * Overrides built-in MODEL_PRICING for this model.\n * Use this for Anthropic, Gemini, Mistral, or any custom model.\n */\n inputRate?: number;\n\n /**\n * Custom output rate (USD per 1M tokens).\n * Optional - used for display/info purposes.\n */\n outputRate?: number;\n\n /**\n * Custom max output tokens.\n * @default 4096\n */\n maxTokens?: number;\n\n /**\n * Custom tier label.\n * @default 'custom'\n */\n tier?: 'fast' | 'standard' | 'reasoning' | 'premium' | 'specialized' | 'custom';\n\n /**\n * Custom tokenizer function.\n * If not provided, uses tiktoken (cl100k_base encoding).\n * Use this for models with different tokenization (e.g., Llama, Mistral).\n * \n * @example\n * tokenizer: (text) => llamaTokenizer.encode(text).length\n */\n tokenizer?: (text: string) => number | Promise<number>;\n\n /**\n * Minimum USD amount (floor).\n * @default 0.001\n */\n minUsd?: number;\n\n /**\n * Maximum USD amount (ceiling).\n * @default 50.0\n */\n maxUsd?: number;\n\n /**\n * Token decimals for atomic conversion.\n * @default 6 (USDC)\n */\n decimals?: number;\n}\n\n/**\n * Token price quote\n */\nexport interface TokenPriceQuote {\n /** Amount in atomic units (for buildRequirements) */\n amountAtomic: string;\n\n /** Human-readable USD amount */\n usdAmount: number;\n\n /** Number of input tokens */\n inputTokens: number;\n\n /** Model used for pricing */\n model: string;\n\n /** Pricing tier */\n tier: string;\n\n /** Input rate per million tokens */\n inputRatePerMillion: number;\n\n /** Output rate per million tokens */\n outputRatePerMillion: number;\n\n /** Max output tokens for this model */\n maxOutputTokens: number;\n\n /**\n * Quote hash for validation.\n * Client should send this back as X-Quote-Hash header.\n */\n quoteHash: string;\n}\n\n/**\n * Token pricing calculator\n */\nexport interface TokenPricing {\n /** Calculate price from input text */\n calculate(input: string, systemPrompt?: string): Promise<TokenPriceQuote>;\n\n /** Validate quote hash (returns true if valid) */\n validateQuote(input: string, quoteHash: string): Promise<boolean>;\n\n /** Count tokens in a string (lazy-loads tiktoken on first call) */\n countTokens(input: string): Promise<number>;\n\n /** Get pricing config */\n readonly config: Required<TokenPricingConfig>;\n\n /** Get model info */\n readonly modelInfo: ModelPricing;\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\n/**\n * Get tiktoken encoding for a model.\n * Falls back to cl100k_base for unknown models.\n * Lazy-loads tiktoken on first call.\n */\nasync function getEncodingForModel(model: string) {\n const tiktoken = await loadTiktoken();\n try {\n return tiktoken.encoding_for_model(model as import('tiktoken').TiktokenModel);\n } catch {\n // Fall back to cl100k_base (GPT-4/4o family encoding)\n return tiktoken.get_encoding('cl100k_base');\n }\n}\n\n/**\n * Count tokens in a string using tiktoken.\n * Lazy-loads tiktoken on first call — no cost if never used.\n */\nexport async function countTokens(text: string, model: string = DEFAULT_MODEL): Promise<number> {\n const encoding = await getEncodingForModel(model);\n try {\n const tokens = encoding.encode(text);\n return tokens.length;\n } finally {\n encoding.free();\n }\n}\n\n/**\n * Generate a hash of the prompt + pricing config for validation.\n */\nfunction generateQuoteHash(prompt: string, model: string, rate: number, tokens: number): string {\n const configString = JSON.stringify({ model, rate, tokens });\n return createHash('sha256').update(prompt + configString).digest('hex').slice(0, 16);\n}\n\n/**\n * Create a token-based pricing calculator\n */\nexport function createTokenPricing(config: TokenPricingConfig = {}): TokenPricing {\n // Determine model name\n const model = config.model ?? DEFAULT_MODEL;\n \n // Get built-in pricing if available, otherwise use custom or default\n const builtInPricing = MODEL_PRICING[model];\n \n // Build effective model info (custom rates override built-in)\n const modelInfo: ModelPricing = {\n input: config.inputRate ?? builtInPricing?.input ?? MODEL_PRICING[DEFAULT_MODEL].input,\n output: config.outputRate ?? builtInPricing?.output ?? MODEL_PRICING[DEFAULT_MODEL].output,\n maxTokens: config.maxTokens ?? builtInPricing?.maxTokens ?? 4096,\n tier: config.tier ?? builtInPricing?.tier ?? 'custom',\n };\n\n // Custom tokenizer or default tiktoken\n const customTokenizer = config.tokenizer;\n\n const fullConfig: Required<TokenPricingConfig> = {\n model,\n inputRate: modelInfo.input,\n outputRate: modelInfo.output,\n maxTokens: modelInfo.maxTokens,\n tier: modelInfo.tier,\n tokenizer: customTokenizer ?? ((text: string): Promise<number> => countTokens(text, model)),\n minUsd: config.minUsd ?? 0.001,\n maxUsd: config.maxUsd ?? 50.0,\n decimals: config.decimals ?? 6,\n };\n\n const { minUsd, maxUsd, decimals } = fullConfig;\n\n /**\n * Count tokens in text (uses custom tokenizer if provided)\n */\n async function countTokensInternal(input: string): Promise<number> {\n if (customTokenizer) {\n return customTokenizer(input);\n }\n return countTokens(input, model);\n }\n\n /**\n * Calculate price from input\n */\n async function calculate(input: string, systemPrompt?: string): Promise<TokenPriceQuote> {\n // Count input tokens (prompt + system prompt if provided)\n const fullInput = systemPrompt ? `${systemPrompt}\\n\\n${input}` : input;\n const inputTokens = await countTokensInternal(fullInput);\n\n // Calculate USD cost based on input tokens only\n // Price = (inputTokens / 1,000,000) × inputRate\n let usdAmount = (inputTokens / 1_000_000) * modelInfo.input;\n\n // Apply min/max caps\n usdAmount = Math.max(usdAmount, minUsd);\n usdAmount = Math.min(usdAmount, maxUsd);\n\n // Convert to atomic units\n const multiplier = Math.pow(10, decimals);\n const amountAtomic = Math.floor(usdAmount * multiplier).toString();\n\n // Generate quote hash for validation\n const quoteHash = generateQuoteHash(input, model, modelInfo.input, inputTokens);\n\n return {\n amountAtomic,\n usdAmount,\n inputTokens,\n model,\n tier: modelInfo.tier,\n inputRatePerMillion: modelInfo.input,\n outputRatePerMillion: modelInfo.output,\n maxOutputTokens: modelInfo.maxTokens,\n quoteHash,\n };\n }\n\n /**\n * Validate quote hash\n */\n async function validateQuote(input: string, quoteHash: string): Promise<boolean> {\n if (!quoteHash) return false;\n const inputTokens = await countTokensInternal(input);\n const expectedHash = generateQuoteHash(input, model, modelInfo.input, inputTokens);\n return expectedHash === quoteHash;\n }\n\n return {\n calculate,\n validateQuote,\n countTokens: countTokensInternal,\n config: fullConfig,\n modelInfo,\n };\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Get list of available models with their pricing.\n */\nexport function getAvailableModels(): Array<{\n model: string;\n inputRate: number;\n outputRate: number;\n maxTokens: number;\n tier: string;\n}> {\n return Object.entries(MODEL_PRICING)\n .map(([model, pricing]) => ({\n model,\n inputRate: pricing.input,\n outputRate: pricing.output,\n maxTokens: pricing.maxTokens,\n tier: pricing.tier,\n }))\n .sort((a, b) => {\n // Sort by tier, then by input rate\n const tierOrder = { fast: 0, standard: 1, reasoning: 2, premium: 3 };\n const tierDiff = tierOrder[a.tier as keyof typeof tierOrder] - tierOrder[b.tier as keyof typeof tierOrder];\n if (tierDiff !== 0) return tierDiff;\n return a.inputRate - b.inputRate;\n });\n}\n\n/**\n * Check if a model exists in our pricing.\n */\nexport function isValidModel(model: string): boolean {\n return model in MODEL_PRICING;\n}\n\n/**\n * Format token pricing for display\n * Example: \"$0.15 per 1M tokens (gpt-4o-mini)\"\n */\nexport function formatTokenPricing(model: string = DEFAULT_MODEL): string {\n const pricing = MODEL_PRICING[model] ?? MODEL_PRICING[DEFAULT_MODEL];\n const actualModel = MODEL_PRICING[model] ? model : DEFAULT_MODEL;\n return `$${pricing.input.toFixed(2)} per 1M tokens (${actualModel})`;\n}\n\n","/**\n * OpenAI Model Registry\n * \n * The single source of truth for all OpenAI models.\n * Contains pricing, capabilities, API requirements, and constraints.\n * \n * Updated: January 2026\n * Source: https://platform.openai.com/docs/pricing\n * \n * @example\n * ```typescript\n * import { ModelRegistry, getModel, getModelsByTier } from '@dexterai/x402/server';\n * \n * // Get a specific model\n * const model = getModel('gpt-4o-mini');\n * console.log(model.pricing.input); // 0.15\n * \n * // Get all reasoning models\n * const reasoners = getModelsByTier('reasoning');\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Model capability tiers, ordered by general capability level\n */\nexport type ModelTier = \n | 'fast' // Cheapest, fastest, good for simple tasks\n | 'standard' // Balanced price/performance\n | 'reasoning' // Chain-of-thought reasoning (o-series)\n | 'premium' // Most capable, expensive\n | 'specialized'; // Special purpose (computer use, deep research, etc.)\n\n/**\n * What the model can process/generate\n */\nexport type ModelModality = 'text' | 'vision' | 'audio' | 'realtime' | 'image' | 'video';\n\n/**\n * API endpoint type\n */\nexport type ModelApiType = 'chat' | 'completion' | 'responses';\n\n/**\n * Pricing per 1M tokens (USD)\n */\nexport interface ModelPricing {\n /** Input token cost per 1M */\n input: number;\n /** Output token cost per 1M */\n output: number;\n /** Cached input token cost per 1M (if supported) */\n cached?: number;\n}\n\n/**\n * What parameters the model accepts\n */\nexport interface ModelParameters {\n /** Uses max_completion_tokens instead of max_tokens */\n usesMaxCompletionTokens: boolean;\n /** Supports temperature parameter */\n supportsTemperature: boolean;\n /** Supports top_p parameter */\n supportsTopP: boolean;\n /** Supports frequency_penalty */\n supportsFrequencyPenalty: boolean;\n /** Supports presence_penalty */\n supportsPresencePenalty: boolean;\n /** Supports reasoning_effort parameter */\n supportsReasoningEffort: boolean;\n /** Supports streaming */\n supportsStreaming: boolean;\n /** Supports system messages */\n supportsSystemMessage: boolean;\n /** Supports function/tool calling */\n supportsTools: boolean;\n /** Supports structured outputs (JSON mode) */\n supportsStructuredOutput: boolean;\n}\n\n/**\n * Complete model definition\n */\nexport interface ModelDefinition {\n /** Model ID as used in API calls */\n id: string;\n /** Human-readable display name */\n displayName: string;\n /** Model family (gpt-4o, gpt-5, o1, o3, etc.) */\n family: string;\n /** Capability tier */\n tier: ModelTier;\n /** Capability rank within tier (1 = lowest, 10 = highest) */\n capabilityRank: number;\n /** What it can process */\n modalities: ModelModality[];\n /** API type */\n apiType: ModelApiType;\n /** Pricing per 1M tokens */\n pricing: ModelPricing;\n /** Context window size (tokens) */\n contextWindow: number;\n /** Default max output tokens */\n defaultMaxOutput: number;\n /** Maximum output tokens allowed */\n maxOutputTokens: number;\n /** Parameter support */\n parameters: ModelParameters;\n /** Is this model deprecated? */\n deprecated: boolean;\n /** Brief description */\n description: string;\n}\n\n// ============================================================================\n// Default Parameter Profiles\n// ============================================================================\n\n/** Standard chat model parameters (GPT-4o, GPT-4.1 family) */\nconst STANDARD_PARAMS: ModelParameters = {\n usesMaxCompletionTokens: false,\n supportsTemperature: true,\n supportsTopP: true,\n supportsFrequencyPenalty: true,\n supportsPresencePenalty: true,\n supportsReasoningEffort: false,\n supportsStreaming: true,\n supportsSystemMessage: true,\n supportsTools: true,\n supportsStructuredOutput: true,\n};\n\n/** GPT-5 family parameters - uses max_completion_tokens, no temperature */\nconst GPT5_PARAMS: ModelParameters = {\n usesMaxCompletionTokens: true, // GPT-5 requires this!\n supportsTemperature: false, // Only default (1) is supported\n supportsTopP: false, // Likely same restriction\n supportsFrequencyPenalty: false,\n supportsPresencePenalty: false,\n supportsReasoningEffort: false,\n supportsStreaming: true,\n supportsSystemMessage: true,\n supportsTools: true,\n supportsStructuredOutput: true,\n};\n\n/** Reasoning model parameters (o1, o3, o4 series) */\nconst REASONING_PARAMS: ModelParameters = {\n usesMaxCompletionTokens: true,\n supportsTemperature: false, // Fixed at 1\n supportsTopP: false,\n supportsFrequencyPenalty: false,\n supportsPresencePenalty: false,\n supportsReasoningEffort: true,\n supportsStreaming: true,\n supportsSystemMessage: true, // Developer message\n supportsTools: true,\n supportsStructuredOutput: true,\n};\n\n/** Pro/Premium reasoning model parameters */\nconst PRO_REASONING_PARAMS: ModelParameters = {\n ...REASONING_PARAMS,\n supportsStreaming: false, // Pro models may not stream\n};\n\n// ============================================================================\n// Model Registry\n// ============================================================================\n\n/**\n * Complete registry of all OpenAI models\n * Ordered by tier, then by capability rank (ascending)\n */\nexport const MODEL_REGISTRY: ModelDefinition[] = [\n // =========================================================================\n // FAST TIER - Cheapest, fastest, good for simple tasks\n // =========================================================================\n {\n id: 'gpt-4o-mini',\n displayName: 'GPT-4o Mini',\n family: 'gpt-4o',\n tier: 'fast',\n capabilityRank: 3,\n modalities: ['text', 'vision'],\n apiType: 'chat',\n pricing: { input: 0.15, output: 0.60, cached: 0.075 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Fast, affordable small model with vision support',\n },\n {\n id: 'gpt-4.1-nano',\n displayName: 'GPT-4.1 Nano',\n family: 'gpt-4.1',\n tier: 'fast',\n capabilityRank: 2,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.10, output: 0.40, cached: 0.025 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 32768,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Smallest 4.1 model, very fast and cheap',\n },\n {\n id: 'gpt-4.1-mini',\n displayName: 'GPT-4.1 Mini',\n family: 'gpt-4.1',\n tier: 'fast',\n capabilityRank: 4,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.40, output: 1.60, cached: 0.10 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 32768,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Balanced 4.1 model, good price/performance',\n },\n {\n id: 'gpt-5-nano',\n displayName: 'GPT-5 Nano',\n family: 'gpt-5',\n tier: 'fast',\n capabilityRank: 1,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.05, output: 0.40, cached: 0.005 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Cheapest GPT-5 variant, extremely fast',\n },\n {\n id: 'gpt-5-mini',\n displayName: 'GPT-5 Mini',\n family: 'gpt-5',\n tier: 'fast',\n capabilityRank: 5,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 0.25, output: 2.00, cached: 0.025 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Small but capable GPT-5, great value',\n },\n\n // =========================================================================\n // STANDARD TIER - Balanced price/performance\n // =========================================================================\n {\n id: 'gpt-4o',\n displayName: 'GPT-4o',\n family: 'gpt-4o',\n tier: 'standard',\n capabilityRank: 5,\n modalities: ['text', 'vision'],\n apiType: 'chat',\n pricing: { input: 2.50, output: 10.00, cached: 1.25 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Flagship multimodal model with vision',\n },\n {\n id: 'gpt-4.1',\n displayName: 'GPT-4.1',\n family: 'gpt-4.1',\n tier: 'standard',\n capabilityRank: 6,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 2.00, output: 8.00, cached: 0.50 },\n contextWindow: 1000000, // 1M context!\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: STANDARD_PARAMS,\n deprecated: false,\n description: 'Long context specialist, 1M token window',\n },\n {\n id: 'gpt-5',\n displayName: 'GPT-5',\n family: 'gpt-5',\n tier: 'standard',\n capabilityRank: 7,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.25, output: 10.00, cached: 0.125 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Base GPT-5, excellent all-around',\n },\n {\n id: 'gpt-5.1',\n displayName: 'GPT-5.1',\n family: 'gpt-5',\n tier: 'standard',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.25, output: 10.00, cached: 0.125 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Improved GPT-5 with better instruction following',\n },\n {\n id: 'gpt-5.2',\n displayName: 'GPT-5.2',\n family: 'gpt-5',\n tier: 'standard',\n capabilityRank: 9,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.75, output: 14.00, cached: 0.175 },\n contextWindow: 128000,\n defaultMaxOutput: 8192,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Latest GPT-5, most capable standard model',\n },\n\n // =========================================================================\n // REASONING TIER - Chain-of-thought reasoning (o-series)\n // =========================================================================\n {\n id: 'o1-mini',\n displayName: 'o1 Mini',\n family: 'o1',\n tier: 'reasoning',\n capabilityRank: 3,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.10, output: 4.40, cached: 0.55 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Fast reasoning model, good for math/code',\n },\n {\n id: 'o3-mini',\n displayName: 'o3 Mini',\n family: 'o3',\n tier: 'reasoning',\n capabilityRank: 4,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.10, output: 4.40, cached: 0.55 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Improved mini reasoner with better efficiency',\n },\n {\n id: 'o4-mini',\n displayName: 'o4 Mini',\n family: 'o4',\n tier: 'reasoning',\n capabilityRank: 5,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 1.10, output: 4.40, cached: 0.275 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Latest mini reasoner, best reasoning per dollar',\n },\n {\n id: 'o3',\n displayName: 'o3',\n family: 'o3',\n tier: 'reasoning',\n capabilityRank: 7,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 2.00, output: 8.00, cached: 0.50 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Full o3 reasoning model, excellent for complex problems',\n },\n {\n id: 'o1',\n displayName: 'o1',\n family: 'o1',\n tier: 'reasoning',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 15.00, output: 60.00, cached: 7.50 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: REASONING_PARAMS,\n deprecated: false,\n description: 'Original full reasoning model, very capable',\n },\n\n // =========================================================================\n // PREMIUM TIER - Most capable, expensive\n // =========================================================================\n {\n id: 'gpt-5-pro',\n displayName: 'GPT-5 Pro',\n family: 'gpt-5',\n tier: 'premium',\n capabilityRank: 7,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 15.00, output: 120.00 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Enhanced GPT-5 for demanding tasks',\n },\n {\n id: 'gpt-5.2-pro',\n displayName: 'GPT-5.2 Pro',\n family: 'gpt-5',\n tier: 'premium',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 21.00, output: 168.00 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 32768,\n parameters: GPT5_PARAMS,\n deprecated: false,\n description: 'Most capable standard model available',\n },\n {\n id: 'o3-pro',\n displayName: 'o3 Pro',\n family: 'o3',\n tier: 'premium',\n capabilityRank: 9,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 20.00, output: 80.00 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: PRO_REASONING_PARAMS,\n deprecated: false,\n description: 'Premium o3 with extended thinking time',\n },\n {\n id: 'o1-pro',\n displayName: 'o1 Pro',\n family: 'o1',\n tier: 'premium',\n capabilityRank: 10,\n modalities: ['text'],\n apiType: 'chat',\n pricing: { input: 150.00, output: 600.00 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: PRO_REASONING_PARAMS,\n deprecated: false,\n description: 'Most capable reasoning model, extended compute',\n },\n\n // =========================================================================\n // SPECIALIZED TIER - Special purpose models\n // =========================================================================\n {\n id: 'o3-deep-research',\n displayName: 'o3 Deep Research',\n family: 'o3',\n tier: 'specialized',\n capabilityRank: 8,\n modalities: ['text'],\n apiType: 'responses',\n pricing: { input: 10.00, output: 40.00, cached: 2.50 },\n contextWindow: 200000,\n defaultMaxOutput: 32768,\n maxOutputTokens: 100000,\n parameters: {\n ...REASONING_PARAMS,\n supportsStreaming: false,\n },\n deprecated: false,\n description: 'Extended research sessions with web access',\n },\n {\n id: 'o4-mini-deep-research',\n displayName: 'o4 Mini Deep Research',\n family: 'o4',\n tier: 'specialized',\n capabilityRank: 6,\n modalities: ['text'],\n apiType: 'responses',\n pricing: { input: 2.00, output: 8.00, cached: 0.50 },\n contextWindow: 128000,\n defaultMaxOutput: 16384,\n maxOutputTokens: 65536,\n parameters: {\n ...REASONING_PARAMS,\n supportsStreaming: false,\n },\n deprecated: false,\n description: 'Affordable deep research with o4 mini',\n },\n {\n id: 'computer-use-preview',\n displayName: 'Computer Use Preview',\n family: 'computer-use',\n tier: 'specialized',\n capabilityRank: 5,\n modalities: ['text', 'vision'],\n apiType: 'responses',\n pricing: { input: 3.00, output: 12.00 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 16384,\n parameters: {\n ...STANDARD_PARAMS,\n supportsReasoningEffort: false,\n },\n deprecated: false,\n description: 'Can control computer interfaces via screenshots',\n },\n\n // =========================================================================\n // REALTIME TIER - Real-time audio/video\n // =========================================================================\n {\n id: 'gpt-realtime',\n displayName: 'GPT Realtime',\n family: 'gpt-realtime',\n tier: 'specialized',\n capabilityRank: 7,\n modalities: ['text', 'audio', 'realtime'],\n apiType: 'chat',\n pricing: { input: 4.00, output: 16.00, cached: 0.40 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 4096,\n parameters: {\n ...STANDARD_PARAMS,\n supportsReasoningEffort: false,\n },\n deprecated: false,\n description: 'Real-time audio conversation model',\n },\n {\n id: 'gpt-realtime-mini',\n displayName: 'GPT Realtime Mini',\n family: 'gpt-realtime',\n tier: 'specialized',\n capabilityRank: 4,\n modalities: ['text', 'audio', 'realtime'],\n apiType: 'chat',\n pricing: { input: 0.60, output: 2.40, cached: 0.06 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 4096,\n parameters: {\n ...STANDARD_PARAMS,\n supportsReasoningEffort: false,\n },\n deprecated: false,\n description: 'Affordable real-time audio model',\n },\n\n // =========================================================================\n // LEGACY MODELS - Still available but older\n // =========================================================================\n {\n id: 'gpt-4o-2024-05-13',\n displayName: 'GPT-4o (May 2024)',\n family: 'gpt-4o',\n tier: 'standard',\n capabilityRank: 4,\n modalities: ['text', 'vision'],\n apiType: 'chat',\n pricing: { input: 5.00, output: 15.00 },\n contextWindow: 128000,\n defaultMaxOutput: 4096,\n maxOutputTokens: 4096,\n parameters: STANDARD_PARAMS,\n deprecated: true,\n description: 'Original GPT-4o snapshot, use gpt-4o instead',\n },\n];\n\n// ============================================================================\n// Lookup Functions\n// ============================================================================\n\n/** Map for O(1) lookup by model ID */\nconst MODEL_MAP = new Map<string, ModelDefinition>(\n MODEL_REGISTRY.map(m => [m.id, m])\n);\n\n/**\n * Get a model by ID\n * @throws if model not found\n */\nexport function getModel(modelId: string): ModelDefinition {\n const model = MODEL_MAP.get(modelId);\n if (!model) {\n throw new Error(`Unknown model: ${modelId}. Use getAvailableModelIds() to see valid options.`);\n }\n return model;\n}\n\n/**\n * Get a model by ID, returns undefined if not found\n */\nexport function findModel(modelId: string): ModelDefinition | undefined {\n return MODEL_MAP.get(modelId);\n}\n\n/**\n * Check if a model ID is valid\n */\nexport function isValidModelId(modelId: string): boolean {\n return MODEL_MAP.has(modelId);\n}\n\n/**\n * Get all model IDs\n */\nexport function getAvailableModelIds(): string[] {\n return MODEL_REGISTRY.map(m => m.id);\n}\n\n/**\n * Get all models in a specific tier\n */\nexport function getModelsByTier(tier: ModelTier): ModelDefinition[] {\n return MODEL_REGISTRY\n .filter(m => m.tier === tier && !m.deprecated)\n .sort((a, b) => a.capabilityRank - b.capabilityRank);\n}\n\n/**\n * Get all models in a specific family\n */\nexport function getModelsByFamily(family: string): ModelDefinition[] {\n return MODEL_REGISTRY\n .filter(m => m.family === family)\n .sort((a, b) => a.capabilityRank - b.capabilityRank);\n}\n\n/**\n * Get all non-deprecated models, ordered by tier then capability\n */\nexport function getActiveModels(): ModelDefinition[] {\n const tierOrder: Record<ModelTier, number> = {\n fast: 1,\n standard: 2,\n reasoning: 3,\n premium: 4,\n specialized: 5,\n };\n \n return MODEL_REGISTRY\n .filter(m => !m.deprecated)\n .sort((a, b) => {\n const tierDiff = tierOrder[a.tier] - tierOrder[b.tier];\n if (tierDiff !== 0) return tierDiff;\n return a.capabilityRank - b.capabilityRank;\n });\n}\n\n/**\n * Get models suitable for text generation testing\n * (excludes realtime, audio-only, etc.)\n */\nexport function getTextModels(): ModelDefinition[] {\n return MODEL_REGISTRY\n .filter(m => \n !m.deprecated && \n m.modalities.includes('text') &&\n !m.modalities.includes('realtime') &&\n m.apiType !== 'responses' // Standard chat API\n )\n .sort((a, b) => {\n const tierOrder: Record<ModelTier, number> = {\n fast: 1, standard: 2, reasoning: 3, premium: 4, specialized: 5\n };\n const tierDiff = tierOrder[a.tier] - tierOrder[b.tier];\n if (tierDiff !== 0) return tierDiff;\n return a.capabilityRank - b.capabilityRank;\n });\n}\n\n/**\n * Get the cheapest model that meets minimum capability requirements\n */\nexport function getCheapestModel(minTier: ModelTier = 'fast'): ModelDefinition {\n const tierOrder: Record<ModelTier, number> = {\n fast: 1, standard: 2, reasoning: 3, premium: 4, specialized: 5\n };\n const minTierNum = tierOrder[minTier];\n \n const candidates = MODEL_REGISTRY\n .filter(m => !m.deprecated && tierOrder[m.tier] >= minTierNum)\n .sort((a, b) => a.pricing.input - b.pricing.input);\n \n return candidates[0];\n}\n\n/**\n * Estimate cost for a request\n */\nexport function estimateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n useCached: boolean = false\n): number {\n const model = getModel(modelId);\n const inputCost = useCached && model.pricing.cached\n ? (inputTokens / 1_000_000) * model.pricing.cached\n : (inputTokens / 1_000_000) * model.pricing.input;\n const outputCost = (outputTokens / 1_000_000) * model.pricing.output;\n return inputCost + outputCost;\n}\n\n/**\n * Format pricing for display\n */\nexport function formatModelPricing(modelId: string): string {\n const model = getModel(modelId);\n return `$${model.pricing.input.toFixed(2)} in / $${model.pricing.output.toFixed(2)} out per 1M tokens`;\n}\n\n// ============================================================================\n// Export a simple pricing map for backwards compatibility\n// ============================================================================\n\n/**\n * Simple pricing map for token-pricing.ts compatibility\n */\nexport const MODEL_PRICING_MAP: Record<string, {\n input: number;\n output: number;\n cached?: number;\n maxTokens: number;\n tier: string;\n}> = Object.fromEntries(\n MODEL_REGISTRY.map(m => [m.id, {\n input: m.pricing.input,\n output: m.pricing.output,\n cached: m.pricing.cached,\n maxTokens: m.defaultMaxOutput,\n tier: m.tier,\n }])\n);\n"],"mappings":"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","names":["USDC_DECIMALS","crypto","DEFAULT_NETWORK","USDC_DECIMALS","pricing","import_crypto","import_crypto"]}
|