{"version":3,"sources":["../src/server.ts","../src/types.ts"],"sourcesContent":["// src/server.ts\nimport {\n  NETWORK_CAIP2,\n  USDC_ADDRESSES,\n  RELAI_FACILITATOR_URL,\n  resolveToken,\n  type NetworkToken,\n  type RelaiNetwork,\n} from './types';\nimport type { RelaiPlugin, PluginContext, PluginResult } from './plugins';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Server-side MPP verifier. When provided, protect() will accept\n * Authorization: Payment credentials and verify them via this handler.\n *\n * Compatible with mppx Mppx.create() server instances.\n *\n * @example\n * ```typescript\n * import { Mppx, tempo } from 'mppx/server';\n *\n * const mppx = Mppx.create({\n *   secretKey: process.env.MPP_SECRET_KEY,\n *   methods: [tempo.charge({ recipient: '0x...', currency: USDC, decimals: 6 })],\n * });\n *\n * const relai = new Relai({\n *   network: 'base',\n *   mpp: mppx,\n * });\n * ```\n */\n/**\n * MPP server handler — compatible with `Mppx.create()` from `mppx/server`.\n *\n * The `charge()` method returns a handler function that:\n * - On a request WITHOUT a Payment credential → returns `{ status: 402, challenge: Response }`\n * - On a request WITH a valid credential → returns `{ status: 200, withReceipt: fn }`\n */\nexport interface MppServerHandler {\n  charge(params: Record<string, unknown>): (request: Request) => Promise<MppChargeResult>;\n}\n\nexport type MppChargeResult = {\n  status: number;\n  challenge?: Response;\n  withReceipt?: (response: Response) => Response;\n  receipt?: { method?: string; reference?: string; status?: string };\n};\n\nexport interface RelaiServerConfig {\n  /** Network to accept payments on */\n  network: RelaiNetwork;\n  /** RelAI facilitator URL (default: https://facilitator.x402.fi) */\n  facilitatorUrl?: string;\n  /** Plugins to extend protect() behavior (e.g. freeTier, rateLimit) */\n  plugins?: RelaiPlugin[];\n  /**\n   * Optional MPP (Machine Payment Protocol) server handler.\n   * When set, protect() accepts Authorization: Payment credentials\n   * (Tempo, Stripe MPP) alongside standard x402 payments.\n   */\n  mpp?: MppServerHandler;\n}\n\nexport type DynamicPrice = number | ((req: any) => number | Promise<number>);\n\nexport type RelaiIntegritasFlow = 'single' | 'dual';\n\nexport interface RelaiIntegritasOptions {\n  /** Enable Integritas by default for this endpoint */\n  enabled?: boolean;\n  /** Default flow when Integritas is enabled */\n  flow?: RelaiIntegritasFlow;\n}\n\nexport interface ProtectOptions {\n  /** Price in USD (e.g., 0.01 for 1 cent) */\n  price: DynamicPrice;\n  /** Optional token asset address for networks supporting multiple tokens */\n  asset?: string;\n  /** Wallet address to receive payments, or stripePayTo() for Stripe settlement */\n  payTo: string | StripePayTo;\n  /** Description shown to payer */\n  description?: string;\n  /** MIME type of the response (default: application/json) */\n  mimeType?: string;\n  /** Maximum timeout in seconds (default: 60) */\n  maxTimeoutSeconds?: number;\n  /** Integritas options (or simple boolean enable flag) */\n  integritas?: boolean | RelaiIntegritasOptions;\n  /** Override network for this endpoint */\n  network?: RelaiNetwork;\n  /** Override feePayer address (Solana only) — bypasses facilitator /supported fetch */\n  feePayer?: string;\n  /** Custom validation after payment is settled */\n  customRules?: (req: any) => boolean | Promise<boolean>;\n  /** Callback when 402 is returned (no payment provided) */\n  onPaymentRequired?: (req: any, info: { price: number; network: RelaiNetwork }) => void;\n  /** Callback when payment is settled successfully */\n  onPaymentSettled?: (req: any, result: SettleResult) => void;\n  /** Callback on error */\n  onError?: (req: any, error: unknown) => void;\n}\n\nexport interface SettleResult {\n  success: boolean;\n  transaction?: string;\n  payer?: string;\n  network?: string;\n  splitTransfers?: Record<string, unknown>;\n  integritasFeePaid?: boolean;\n  provenance?: Record<string, unknown>;\n  integritas?: Record<string, unknown>;\n  error?: string;\n  errorReason?: string;\n}\n\nexport interface PaymentInfo {\n  verified: boolean;\n  transactionId?: string;\n  payer?: string;\n  network: RelaiNetwork;\n  amount: number;\n}\n\n// ============================================================================\n// Stripe Pay-To Helper\n// ============================================================================\n\n/** Config returned by stripePayTo() - used by protect() to create Stripe deposit addresses */\nexport interface StripePayTo {\n  readonly __brand: 'stripePayTo';\n  readonly secretKey: string;\n  /** Stripe crypto deposits network (default: 'base') */\n  readonly stripeNetwork: string;\n}\n\n/**\n * Create a Stripe pay-to configuration for x402 payments.\n * Payments settle as USD in your Stripe Dashboard - no crypto knowledge required.\n *\n * Stripe creates a fresh PaymentIntent + deposit address per request.\n * Network is auto-set to Base (Stripe settles USDC on Base).\n *\n * @example\n * ```typescript\n * import Relai, { stripePayTo } from '@relai-fi/x402/server';\n *\n * const relai = new Relai({ network: 'base' });\n *\n * app.get('/api/data', relai.protect({\n *   price: 0.01,\n *   payTo: stripePayTo(process.env.STRIPE_SECRET_KEY!),\n * }), (req, res) => {\n *   res.json({ data: 'paid content' });\n * });\n * ```\n */\nexport function stripePayTo(\n  stripeSecretKey: string,\n  options?: { network?: string },\n): StripePayTo {\n  if (!stripeSecretKey) {\n    throw new Error('stripePayTo requires a Stripe secret key');\n  }\n  return {\n    __brand: 'stripePayTo' as const,\n    secretKey: stripeSecretKey,\n    stripeNetwork: options?.network || 'base',\n  };\n}\n\nconst USD_PRICE_CACHE_TTL_MS = 60 * 1000;\nconst usdPriceCache = new Map<string, { usd: number; expiresAt: number }>();\n\nconst GECKOTERMINAL_NETWORK_BY_RELAI: Partial<Record<RelaiNetwork, string>> = {\n  polygon: 'polygon_pos',\n};\n\nconst COINGECKO_ID_BY_SYMBOL: Record<string, string> = {\n  WETH:  'ethereum',\n  WBTC:  'bitcoin',\n  USDT:  'tether',\n  EURC:  'euro-coin',\n  DAI:   'dai',\n  cbETH: 'coinbase-wrapped-staked-eth',\n  cbBTC: 'coinbase-wrapped-btc',\n};\n\nfunction isStableUsdToken(token: NetworkToken): boolean {\n  if (token.isStableUsd === true) return true;\n  const symbol = String(token.symbol || '').toUpperCase();\n  return symbol === 'USDC' || symbol === 'USDT';\n}\n\nasync function fetchUsdPriceFromCoinGecko(coinId: string): Promise<number> {\n  const now = Date.now();\n  const cached = usdPriceCache.get(coinId);\n  if (cached && cached.expiresAt > now) {\n    return cached.usd;\n  }\n\n  const url = `https://api.coingecko.com/api/v3/simple/price?ids=${encodeURIComponent(coinId)}&vs_currencies=usd`;\n  const res = await fetch(url, {\n    method: 'GET',\n    headers: {\n      Accept: 'application/json',\n    },\n  });\n\n  if (!res.ok) {\n    throw new Error(`CoinGecko price request failed: HTTP ${res.status}`);\n  }\n\n  const payload = await res.json() as Record<string, { usd?: number }>;\n  const usd = Number(payload?.[coinId]?.usd);\n  if (!Number.isFinite(usd) || usd <= 0) {\n    throw new Error(`CoinGecko returned invalid usd price for ${coinId}`);\n  }\n\n  usdPriceCache.set(coinId, {\n    usd,\n    expiresAt: now + USD_PRICE_CACHE_TTL_MS,\n  });\n\n  return usd;\n}\n\nasync function fetchUsdPriceFromGeckoTerminal(network: RelaiNetwork, tokenAddress: string): Promise<number> {\n  const geckoNetwork = GECKOTERMINAL_NETWORK_BY_RELAI[network];\n  if (!geckoNetwork) {\n    throw new Error(`GeckoTerminal network not configured for ${network}`);\n  }\n\n  const normalizedAddress = String(tokenAddress || '').trim().toLowerCase();\n  if (!normalizedAddress) {\n    throw new Error('GeckoTerminal requires a token address');\n  }\n\n  const cacheKey = `gt:${geckoNetwork}:${normalizedAddress}`;\n  const now = Date.now();\n  const cached = usdPriceCache.get(cacheKey);\n  if (cached && cached.expiresAt > now) {\n    return cached.usd;\n  }\n\n  const url = `https://api.geckoterminal.com/api/v2/networks/${encodeURIComponent(geckoNetwork)}/tokens/${encodeURIComponent(normalizedAddress)}`;\n  const res = await fetch(url, {\n    method: 'GET',\n    headers: {\n      Accept: 'application/json',\n    },\n  });\n\n  if (!res.ok) {\n    throw new Error(`GeckoTerminal price request failed: HTTP ${res.status}`);\n  }\n\n  const payload = await res.json() as { data?: { attributes?: { price_usd?: string | number } } };\n  const usd = Number(payload?.data?.attributes?.price_usd);\n  if (!Number.isFinite(usd) || usd <= 0) {\n    throw new Error(`GeckoTerminal returned invalid usd price for ${normalizedAddress} on ${geckoNetwork}`);\n  }\n\n  usdPriceCache.set(cacheKey, {\n    usd,\n    expiresAt: now + USD_PRICE_CACHE_TTL_MS,\n  });\n\n  return usd;\n}\n\nasync function resolveAmountAtomicFromUsd({\n  priceUsd,\n  token,\n  network,\n}: {\n  priceUsd: number;\n  token: NetworkToken;\n  network: RelaiNetwork;\n}): Promise<string> {\n  const decimals = Number(token.decimals);\n  if (!Number.isFinite(decimals) || decimals < 0) {\n    throw new Error(`Invalid token decimals for ${token.symbol || token.address}`);\n  }\n\n  if (isStableUsdToken(token)) {\n    const units = Math.floor(priceUsd * Math.pow(10, decimals));\n    return String(Math.max(1, units));\n  }\n\n  const symbol = String(token.symbol || '').toUpperCase();\n  const coinGeckoId = COINGECKO_ID_BY_SYMBOL[symbol];\n  if (!coinGeckoId) {\n    throw new Error(`No USD quote source configured for token ${symbol || token.address} on ${network}`);\n  }\n\n  const overrideEnv = process.env[`EVM_TOKEN_PRICE_${symbol}_USD`];\n  let usdPerToken: number;\n  if (overrideEnv && Number(overrideEnv) > 0) {\n    usdPerToken = Number(overrideEnv);\n  } else {\n    try {\n      usdPerToken = await fetchUsdPriceFromCoinGecko(coinGeckoId);\n    } catch (coinGeckoError) {\n      try {\n        usdPerToken = await fetchUsdPriceFromGeckoTerminal(network, token.address);\n      } catch (geckoTerminalError) {\n        throw new Error(\n          `USD quote failed for ${symbol || token.address} on ${network}. CoinGecko: ${coinGeckoError instanceof Error ? coinGeckoError.message : String(coinGeckoError)}; GeckoTerminal: ${geckoTerminalError instanceof Error ? geckoTerminalError.message : String(geckoTerminalError)}`,\n        );\n      }\n    }\n  }\n\n  const tokenAmount = priceUsd / usdPerToken;\n  const rawUnits = tokenAmount * Math.pow(10, decimals);\n\n  if (!Number.isFinite(rawUnits) || rawUnits <= 0) {\n    throw new Error(\n      `Invalid conversion result for token ${symbol || token.address}: priceUsd=${priceUsd}, usdPerToken=${usdPerToken}`,\n    );\n  }\n\n  return String(Math.max(1, Math.floor(rawUnits)));\n}\n\n/** @internal Type guard for StripePayTo */\nfunction isStripePayTo(payTo: unknown): payTo is StripePayTo {\n  return (\n    typeof payTo === 'object' &&\n    payTo !== null &&\n    (payTo as any).__brand === 'stripePayTo'\n  );\n}\n\nfunction parseBooleanHeader(value: unknown): boolean | null {\n  if (value == null) return null;\n  const normalized = String(value).trim().toLowerCase();\n  if (normalized === 'true' || normalized === '1' || normalized === 'yes' || normalized === 'on') {\n    return true;\n  }\n  if (normalized === 'false' || normalized === '0' || normalized === 'no' || normalized === 'off') {\n    return false;\n  }\n  return null;\n}\n\nfunction normalizeIntegritasFlow(value: unknown): RelaiIntegritasFlow | undefined {\n  const normalized = String(value || '').trim().toLowerCase();\n  if (normalized === 'single') return 'single';\n  if (normalized === 'dual') return 'dual';\n  return undefined;\n}\n\nfunction normalizeIntegritasOptions(\n  value: boolean | RelaiIntegritasOptions | undefined,\n): { enabled: boolean; flow?: RelaiIntegritasFlow } {\n  if (value === true) return { enabled: true };\n  if (value === false || value == null) return { enabled: false };\n\n  const flow = normalizeIntegritasFlow(value.flow);\n  const enabled =\n    typeof value.enabled === 'boolean'\n      ? value.enabled\n      : true;\n\n  return {\n    enabled,\n    ...(flow ? { flow } : {}),\n  };\n}\n\n/**\n * @internal Create a Stripe PaymentIntent with crypto payment method\n * and extract the deposit address.\n */\nasync function createStripeDepositAddress(\n  secretKey: string,\n  amountUsdCents: number,\n  network: string = 'base',\n): Promise<string> {\n  const params = new URLSearchParams();\n  params.append('amount', String(amountUsdCents));\n  params.append('currency', 'usd');\n  params.append('payment_method_types[]', 'crypto');\n  params.append('payment_method_data[type]', 'crypto');\n  params.append('confirm', 'true');\n\n  const res = await fetch('https://api.stripe.com/v1/payment_intents', {\n    method: 'POST',\n    headers: {\n      'Authorization': `Bearer ${secretKey}`,\n      'Content-Type': 'application/x-www-form-urlencoded',\n    },\n    body: params.toString(),\n  });\n\n  if (!res.ok) {\n    const err = await res.json().catch(() => ({})) as any;\n    const msg = err?.error?.message || res.statusText;\n\n    // Provide actionable guidance for common issues\n    if (msg.includes('unknown parameter') || msg.includes('crypto')) {\n      throw new Error(\n        `Stripe crypto payins not enabled on this account. ` +\n        `Enable at: https://support.stripe.com/questions/get-started-with-pay-with-crypto ` +\n        `(Original: ${msg})`,\n      );\n    }\n    throw new Error(`Stripe PaymentIntent creation failed: ${msg}`);\n  }\n\n  const pi = await res.json() as any;\n  const depositDetails = pi.next_action?.crypto_collect_deposit_details;\n  if (!depositDetails) {\n    throw new Error(\n      'Stripe PaymentIntent missing crypto deposit details. ' +\n      'Ensure crypto payins are enabled: https://support.stripe.com/questions/get-started-with-pay-with-crypto',\n    );\n  }\n\n  const address = depositDetails.deposit_addresses?.[network]?.address;\n  if (!address) {\n    throw new Error(`No Stripe deposit address for network: ${network}`);\n  }\n\n  return address;\n}\n\n// ============================================================================\n// Relai Server SDK\n// ============================================================================\n\n/**\n * Server-side SDK for protecting Express endpoints with x402 micropayments.\n * Settles payments through the RelAI facilitator (zero gas fees for users).\n *\n * Supports: Solana, Base, Avalanche, SKALE Base, SKALE Base Sepolia, SKALE BITE, Polygon, and Ethereum.\n *\n * @example\n * ```typescript\n * import Relai from '@relai-fi/x402/server';\n *\n * const relai = new Relai({ network: 'base' });\n *\n * app.get('/api/data', relai.protect({\n *   payTo: '0xYourWallet',\n *   price: 0.01,  // $0.01 USDC\n * }), (req, res) => {\n *   res.json({ data: 'Protected content', payment: req.payment });\n * });\n * ```\n */\nexport class Relai {\n  private network: RelaiNetwork;\n  private facilitatorUrl: string;\n  private feePayerCache: Map<string, string> = new Map(); // Cache feePayer per network\n  private plugins: RelaiPlugin[];\n  private pluginInitPromise: Promise<void> | null = null;\n  private mpp?: MppServerHandler;\n\n  constructor(config: RelaiServerConfig) {\n    this.network = config.network;\n    this.facilitatorUrl = config.facilitatorUrl || RELAI_FACILITATOR_URL;\n    this.plugins = config.plugins ?? [];\n    this.mpp = config.mpp;\n  }\n\n  private async runPluginInit(): Promise<void> {\n    for (const plugin of this.plugins) {\n      if (plugin.onInit) {\n        try {\n          await plugin.onInit();\n        } catch (err) {\n          console.warn(`[Relai] Plugin '${plugin.name}' init failed:`, err);\n        }\n      }\n    }\n  }\n\n  /**\n   * Get feePayer address for a network (cached)\n   */\n  private async getFeePayer(caip2: string): Promise<string | undefined> {\n    // Check cache first\n    if (this.feePayerCache.has(caip2)) {\n      return this.feePayerCache.get(caip2);\n    }\n\n    // If using RelAI facilitator, use hardcoded address (no fetch needed)\n    const isRelAI = this.facilitatorUrl.includes('facilitator.x402.fi') || \n                    this.facilitatorUrl.includes('relai');\n    \n    if (isRelAI) {\n      const isSolanaNetwork = caip2.startsWith('solana:');\n      const relaiFeePayer = isSolanaNetwork\n        ? '4x4ZhcqiT1FnirM8Ne97iVupkN4NcQgc2YYbE2jDZbZn'\n        : '0x1892f72fdB3A966b2AD8595aA5f7741Ef72d6085';\n      this.feePayerCache.set(caip2, relaiFeePayer);\n      return relaiFeePayer;\n    }\n\n    // For other facilitators, fetch from /supported\n    try {\n      const supportedUrl = `${this.facilitatorUrl}/supported`;\n      const supportedRes = await fetch(supportedUrl);\n      if (supportedRes.ok) {\n        const supportedData = await supportedRes.json();\n        // Cache all feePayers from supported kinds\n        supportedData.kinds?.forEach((kind: any) => {\n          if (kind.network && kind.extra?.feePayer) {\n            this.feePayerCache.set(kind.network, kind.extra.feePayer);\n          }\n        });\n        return this.feePayerCache.get(caip2);\n      }\n    } catch (err) {\n      // feePayer MUST come from facilitator - cannot use env for security\n      console.error(`[Relai] Failed to fetch feePayer from facilitator: ${err}`);\n    }\n    return undefined;\n  }\n\n  /**\n   * Express middleware to protect an endpoint with x402 micropayments.\n   *\n   * Flow:\n   * 1. No payment header → returns 402 with payment requirements\n   * 2. Payment header present → calls RelAI facilitator `/settle`\n   * 3. Settlement success → sets `PAYMENT-RESPONSE` header, attaches `req.payment`, calls `next()`\n   */\n  protect(options: ProtectOptions) {\n    const self = this;\n\n    return async (req: any, res: any, next: any) => {\n      try {\n        // -----------------------------------------------------------\n        // Preflight probe: respond 200 immediately so the preflight\n        // plugin (or external clients) can verify the endpoint is alive.\n        // -----------------------------------------------------------\n        if (req.headers['x-preflight'] === 'true' || req.headers['x-preflight'] === '1') {\n          return res.status(200).json({ status: 'ok', preflight: true });\n        }\n\n        // Resolve dynamic price\n        const resolvedPrice = typeof options.price === 'function'\n          ? await options.price(req)\n          : options.price;\n\n        if (typeof resolvedPrice !== 'number' || !isFinite(resolvedPrice) || resolvedPrice <= 0) {\n          return res.status(400).json({ error: 'Invalid price configuration' });\n        }\n\n        // Resolve network (Stripe auto-sets to base)\n        const stripeConfig = isStripePayTo(options.payTo) ? options.payTo : null;\n        const network = stripeConfig\n          ? (stripeConfig.stripeNetwork as RelaiNetwork) || 'base'\n          : (options.network || self.network);\n        const caip2 = NETWORK_CAIP2[network];\n        const requestedAsset =\n          typeof options.asset === 'string' && options.asset.trim() !== ''\n            ? options.asset.trim()\n            : undefined;\n        const explicitToken = requestedAsset ? resolveToken(network, requestedAsset) : null;\n        if (requestedAsset && !explicitToken) {\n          return res.status(400).json({\n            error: `Unsupported asset ${requestedAsset} for network ${network}`,\n          });\n        }\n\n        const fallbackToken: NetworkToken = {\n          address: USDC_ADDRESSES[network],\n          symbol: 'USDC',\n          name: network === 'skale-bite' ? 'USDC' : 'USD Coin',\n          decimals: 6,\n          domainVersion: network === 'skale-bite' ? '1' : '2',\n          isStableUsd: true,\n        };\n        const token = explicitToken || resolveToken(network) || fallbackToken;\n        const asset = token.address;\n        const tokenName = token.name || 'USD Coin';\n        const tokenVersion = token.domainVersion || (network === 'skale-bite' ? '1' : '2');\n        const tokenDecimals = Number.isFinite(Number(token.decimals)) ? Number(token.decimals) : 6;\n\n        let amount: string;\n        try {\n          amount = await resolveAmountAtomicFromUsd({\n            priceUsd: resolvedPrice,\n            token,\n            network,\n          });\n        } catch (err) {\n          console.error('[Relai] Failed to convert USD amount to token units:', err);\n          return res.status(500).json({\n            error: 'Failed to quote token amount for payment requirements',\n          });\n        }\n\n        const configuredIntegritas = normalizeIntegritasOptions(options.integritas);\n        const headerIntegritasEnabled = parseBooleanHeader(req.headers['x-integritas']);\n        const headerIntegritasFlow = normalizeIntegritasFlow(req.headers['x-integritas-flow']);\n        const integritasEnabled =\n          headerIntegritasEnabled === null\n            ? configuredIntegritas.enabled\n            : headerIntegritasEnabled;\n        const integritasFlow = headerIntegritasFlow || configuredIntegritas.flow;\n        const integritasMode =\n          integritasFlow === 'single'\n            ? 'single_signature_fee_included'\n            : (integritasFlow === 'dual' ? 'dual_signature_split' : undefined);\n\n        // Check for payment header (base64-encoded JSON)\n        const paymentHeader =\n          req.headers['x-payment'] ||\n          req.headers['payment-signature'] ||\n          req.headers['x-payment-signature'];\n\n        // -----------------------------------------------------------\n        // MPP: check for Authorization: Payment credential\n        // -----------------------------------------------------------\n        const authHeader = req.headers['authorization'] || '';\n        if (!paymentHeader && self.mpp && /^Payment\\s+/i.test(authHeader)) {\n          try {\n            // Use the same amount format as the challenge (USD with 6 decimals)\n            const mppAmount = resolvedPrice.toFixed(6);\n\n            // Build a web Request from the Express req for the mppx handler\n            const mppUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;\n            const mppHeaders = new Headers();\n            for (const [k, v] of Object.entries(req.headers)) {\n              if (typeof v === 'string') mppHeaders.set(k, v);\n            }\n            const mppRequest = new Request(mppUrl, { method: req.method, headers: mppHeaders });\n\n            // Call the charge handler — it detects the credential in Authorization header\n            // and verifies it against the HMAC-signed challenge\n            const chargeHandler = self.mpp.charge({ amount: mppAmount } as any);\n            const mppResult = await chargeHandler(mppRequest);\n            if (mppResult.status === 402 && mppResult.challenge instanceof Response) {\n              // Credential not accepted — mppx re-challenges (normal handshake)\n            }\n\n            // MPP charge genuinely failed (not a 402 re-challenge, which is normal handshake)\n            // Only notify plugins for non-402 failures (e.g. 500, invalid credential, etc.)\n            if (mppResult.status !== 200 && !mppResult.withReceipt && mppResult.status !== 402) {\n              if (self.plugins.length > 0) {\n                const mppFailCtx: PluginContext = {\n                  network,\n                  price: resolvedPrice,\n                  path: req.path || req.originalUrl || '/',\n                  method: (req.method || 'GET').toUpperCase(),\n                };\n                const mppFailResult: SettleResult = {\n                  success: false,\n                  payer: 'mpp',\n                  error: `MPP charge failed with status ${mppResult.status}`,\n                };\n                for (const plugin of self.plugins) {\n                  if (!plugin.afterSettled) continue;\n                  try {\n                    await plugin.afterSettled(req, mppFailResult, mppFailCtx);\n                  } catch (pluginErr) {\n                    console.warn(`[Relai] Plugin '${plugin.name}' afterSettled error (non-blocking):`, pluginErr);\n                  }\n                }\n              }\n            }\n\n            if (mppResult.status === 200 || mppResult.withReceipt) {\n              // Payment verified by mppx\n              const receipt = mppResult.receipt || {};\n              const paymentInfo: PaymentInfo = {\n                verified: true,\n                transactionId: receipt.reference || '',\n                payer: receipt.method || 'mpp',\n                network,\n                amount: resolvedPrice,\n              };\n              req.payment = paymentInfo;\n              req.x402Payer = receipt.method ? `${receipt.method}-mpp` : 'mpp';\n              req.x402Paid = true;\n              req.x402Transaction = receipt.reference || '';\n              req.x402Network = network;\n\n              // Use withReceipt to attach Payment-Receipt header\n              if (mppResult.withReceipt) {\n                const dummyResponse = new Response(null);\n                const receiptResponse = mppResult.withReceipt(dummyResponse);\n                const receiptHeader = receiptResponse.headers.get('payment-receipt');\n                if (receiptHeader) {\n                  res.setHeader?.('Payment-Receipt', receiptHeader);\n                  res.setHeader?.('Cache-Control', 'private');\n                }\n              }\n\n              options.onPaymentSettled?.(req, {\n                success: true,\n                transaction: receipt.reference,\n                payer: req.x402Payer,\n              } as SettleResult);\n\n              // Plugin hooks: afterSettled\n              if (self.plugins.length > 0) {\n                const settleCtx: PluginContext = {\n                  network,\n                  price: resolvedPrice,\n                  path: req.path || req.originalUrl || '/',\n                  method: (req.method || 'GET').toUpperCase(),\n                };\n                for (const plugin of self.plugins) {\n                  if (!plugin.afterSettled) continue;\n                  try {\n                    await plugin.afterSettled(req, {\n                      success: true,\n                      transaction: receipt.reference,\n                      payer: req.x402Payer,\n                    } as SettleResult, settleCtx);\n                  } catch (pluginErr) {\n                    console.warn(`[Relai] Plugin '${plugin.name}' afterSettled error (non-blocking):`, pluginErr);\n                  }\n                }\n              }\n\n              return next();\n            }\n          } catch (mppErr) {\n            console.warn(`[Relai] MPP verification failed (${mppErr instanceof Error ? mppErr.message : mppErr}), falling through to x402`);\n\n            // Notify plugins of MPP failure\n            if (self.plugins.length > 0) {\n              const mppErrCtx: PluginContext = {\n                network,\n                price: resolvedPrice,\n                path: req.path || req.originalUrl || '/',\n                method: (req.method || 'GET').toUpperCase(),\n              };\n              const mppErrResult: SettleResult = {\n                success: false,\n                payer: 'mpp',\n                error: mppErr instanceof Error ? mppErr.message : String(mppErr),\n              };\n              for (const plugin of self.plugins) {\n                if (!plugin.afterSettled) continue;\n                try {\n                  await plugin.afterSettled(req, mppErrResult, mppErrCtx);\n                } catch (pluginErr) {\n                  console.warn(`[Relai] Plugin '${plugin.name}' afterSettled error (non-blocking):`, pluginErr);\n                }\n              }\n            }\n          }\n        }\n\n        // -----------------------------------------------------------\n        // Plugin hooks: beforePaymentCheck\n        // If any plugin returns { skip: true }, bypass payment entirely.\n        // Ensure plugins are initialized (config synced) before checking.\n        // -----------------------------------------------------------\n        if (!paymentHeader && self.plugins.length > 0) {\n          if (!self.pluginInitPromise) {\n            self.pluginInitPromise = self.runPluginInit();\n          }\n          await self.pluginInitPromise;\n          const pluginCtx: PluginContext = {\n            network,\n            price: resolvedPrice,\n            path: req.path || req.originalUrl || '/',\n            method: (req.method || 'GET').toUpperCase(),\n          };\n\n          for (const plugin of self.plugins) {\n            if (!plugin.beforePaymentCheck) continue;\n            try {\n              const pluginResult = await plugin.beforePaymentCheck(req, pluginCtx);\n\n              // Reject: plugin blocks the request entirely (e.g. service unhealthy)\n              if (pluginResult?.reject) {\n                const rejectStatus = pluginResult.rejectStatus || 503;\n                if (pluginResult.headers) {\n                  for (const [k, v] of Object.entries(pluginResult.headers)) {\n                    res.setHeader(k, v);\n                  }\n                }\n                return res.status(rejectStatus).json({\n                  error: pluginResult.rejectMessage || 'Service unavailable',\n                  plugin: plugin.name,\n                });\n              }\n\n              // Skip: bypass payment and serve content for free\n              if (pluginResult?.skip) {\n                // Set plugin-provided headers\n                if (pluginResult.headers) {\n                  for (const [k, v] of Object.entries(pluginResult.headers)) {\n                    res.setHeader(k, v);\n                  }\n                }\n                // Attach plugin metadata to request\n                req.pluginMeta = { ...(req.pluginMeta || {}), ...(pluginResult.meta || {}) };\n                req.x402Paid = false;\n                req.x402Free = true;\n                req.x402Plugin = plugin.name;\n                // Still set up afterSettled interceptor so plugins (e.g. refund) can\n                // re-issue a credit if the endpoint fails on this free call too.\n                const skipPluginsWithHook = self.plugins.filter((p) => !!p.afterSettled);\n                if (skipPluginsWithHook.length > 0) {\n                  const skipCtx: PluginContext = {\n                    network,\n                    price: resolvedPrice,\n                    path: req.path || req.originalUrl || '/',\n                    method: (req.method || 'GET').toUpperCase(),\n                  };\n                  const skipResult: SettleResult = {\n                    success: true,\n                    payer: req.headers?.['x-wallet-address'] || req.headers?.['x-buyer-address'] || req.ip || req.socket?.remoteAddress || 'unknown',\n                    transaction: '',\n                  } as any;\n                  const originalJsonSkip = (res as any).json?.bind(res);\n                  const originalSendSkip = (res as any).send?.bind(res);\n                  let skipFired = false;\n                  const fireSkipAfterSettled = (statusCode: number) => {\n                    if (skipFired) return;\n                    skipFired = true;\n                    const resultWithStatus = { ...skipResult, statusCode };\n                    for (const p of skipPluginsWithHook) {\n                      p.afterSettled!(req, resultWithStatus, skipCtx).catch((e: unknown) => {\n                        console.warn(`[Relai] Plugin '${p.name}' afterSettled (skip) error:`, e);\n                      });\n                    }\n                  };\n                  if (typeof originalJsonSkip === 'function') {\n                    (res as any).json = function (body: unknown) {\n                      fireSkipAfterSettled(res.statusCode ?? 200);\n                      (res as any).json = originalJsonSkip;\n                      return originalJsonSkip(body);\n                    };\n                  }\n                  if (typeof originalSendSkip === 'function') {\n                    (res as any).send = function (body: unknown) {\n                      fireSkipAfterSettled(res.statusCode ?? 200);\n                      (res as any).send = originalSendSkip;\n                      return originalSendSkip(body);\n                    };\n                  }\n                }\n                return next();\n              }\n            } catch (pluginErr) {\n              console.warn(`[Relai] Plugin '${plugin.name}' beforePaymentCheck error (non-blocking):`, pluginErr);\n            }\n          }\n        }\n\n        // -----------------------------------------------------------\n        // No payment → return 402 Payment Required\n        // -----------------------------------------------------------\n        if (!paymentHeader) {\n          options.onPaymentRequired?.(req, { price: resolvedPrice, network });\n\n          // Resolve payTo address (Stripe creates a fresh deposit address per request)\n          let resolvedPayTo: string;\n          if (stripeConfig) {\n            const amountInCents = Math.max(1, Math.round(resolvedPrice * 100));\n            resolvedPayTo = await createStripeDepositAddress(\n              stripeConfig.secretKey,\n              amountInCents,\n              stripeConfig.stripeNetwork,\n            );\n          } else {\n            resolvedPayTo = options.payTo as string;\n          }\n\n          // Get facilitator feePayer address — use explicit override if provided, otherwise fetch\n          const feePayer = (options.feePayer as string | undefined) || await self.getFeePayer(caip2);\n\n          let paymentRequiredResponse: any = {\n            x402Version: 2,\n            error: 'Payment required',\n            resource: {\n              url: `${req.protocol}://${req.get('host')}${req.originalUrl}`,\n              description: options.description || 'API access',\n              mimeType: options.mimeType || 'application/json',\n            },\n            accepts: [{\n              scheme: 'exact',\n              network: caip2,\n              amount,\n              asset,\n              payTo: resolvedPayTo,\n              maxTimeoutSeconds: options.maxTimeoutSeconds || 60,\n              extra: {\n                name: tokenName,\n                version: tokenVersion,\n                decimals: tokenDecimals,\n                symbol: token.symbol,\n                ...(feePayer && { feePayer }), // Add feePayer if available\n                ...(integritasEnabled ? { integritasEnabled: true } : {}),\n                ...(integritasFlow ? { integritasFlow } : {}),\n                ...(integritasMode ? { integritasMode } : {}),\n                ...(integritasFlow === 'single' ? { integritasSingleSignature: true } : {}),\n              },\n            }],\n            ...((configuredIntegritas.enabled || integritasEnabled || !!integritasFlow)\n              ? {\n                  extensions: {\n                    integritas: {\n                      available: true,\n                      selectedFlow: integritasFlow || null,\n                      availableFlows: ['single', 'dual'],\n                      enabled: integritasEnabled,\n                    },\n                  },\n                }\n              : {}),\n          };\n\n          // Plugin hooks: enrich402Response (e.g. bridge adds extensions.bridge)\n          if (self.plugins.length > 0) {\n            const enrichCtx: PluginContext = {\n              network,\n              price: resolvedPrice,\n              path: req.path || req.originalUrl || '/',\n              method: (req.method || 'GET').toUpperCase(),\n            };\n            for (const plugin of self.plugins) {\n              if (!plugin.enrich402Response) continue;\n              try {\n                paymentRequiredResponse = plugin.enrich402Response(paymentRequiredResponse, enrichCtx) || paymentRequiredResponse;\n              } catch (pluginErr) {\n                console.warn(`[Relai] Plugin '${plugin.name}' enrich402Response error (non-blocking):`, pluginErr);\n              }\n            }\n          }\n\n          // Add MPP challenge header if mpp is configured\n          if (self.mpp?.charge) {\n            try {\n              const mppAmount = resolvedPrice.toFixed(6);\n              const chargeHandler = self.mpp.charge({ amount: mppAmount } as any);\n              const mockReq = new Request(`${req.protocol}://${req.get('host')}${req.originalUrl}`);\n              const mppResult = await chargeHandler(mockReq);\n              if (mppResult?.challenge instanceof Response) {\n                const wwwAuth = mppResult.challenge.headers.get('www-authenticate');\n                if (wwwAuth) {\n                  res.setHeader?.('WWW-Authenticate', wwwAuth);\n                }\n              }\n            } catch {\n              // Non-fatal — x402 response is still valid without MPP headers\n            }\n          }\n\n          res.setHeader?.('Cache-Control', 'no-store');\n          return res.status(402).json(paymentRequiredResponse);\n        }\n\n        // -----------------------------------------------------------\n        // Payment header present → parse and settle via facilitator\n        // -----------------------------------------------------------\n        let paymentProof: any;\n        try {\n          // Try base64 first (standard x402 format)\n          const decoded = Buffer.from(paymentHeader, 'base64').toString('utf-8');\n          paymentProof = JSON.parse(decoded);\n        } catch {\n          try {\n            // Fallback: raw JSON string\n            paymentProof = JSON.parse(paymentHeader);\n          } catch {\n            return res.status(400).json({\n              x402Version: 2,\n              error: 'Invalid payment header — expected base64-encoded JSON',\n            });\n          }\n        }\n\n        // -----------------------------------------------------------\n        // Standard payment: settle via facilitator\n        // (Bridged payments go through the same facilitator /settle path.\n        //  The bridge settle returns a valid xPayment that the facilitator\n        //  can verify — no special-casing needed server-side.)\n        // -----------------------------------------------------------\n\n        // Resolve payTo for settle (extract from signed proof when using Stripe)\n        let settlePayTo: string;\n        if (stripeConfig) {\n          settlePayTo =\n            paymentProof.payload?.authorization?.to ||\n            paymentProof.accepted?.payTo ||\n            '';\n          if (!settlePayTo) {\n            return res.status(400).json({\n              x402Version: 2,\n              error: 'Cannot extract destination address from payment proof',\n            });\n          }\n        } else {\n          settlePayTo = options.payTo as string;\n        }\n\n        // Build payment requirements for facilitator\n        const paymentRequirements = {\n          scheme: 'exact',\n          network: caip2,\n          amount,\n          asset,\n          payTo: settlePayTo,\n          maxTimeoutSeconds: options.maxTimeoutSeconds || 60,\n          extra: {\n            name: tokenName,\n            version: tokenVersion,\n            decimals: tokenDecimals,\n            symbol: token.symbol,\n            ...(integritasEnabled ? { integritasEnabled: true } : {}),\n            ...(integritasFlow ? { integritasFlow } : {}),\n            ...(integritasMode ? { integritasMode } : {}),\n            ...(integritasFlow === 'single' ? { integritasSingleSignature: true } : {}),\n          },\n        };\n\n        // Call facilitator /settle\n        const settleUrl = `${self.facilitatorUrl}/settle`;\n        const settleRes = await fetch(settleUrl, {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          body: JSON.stringify({\n            paymentPayload: paymentProof,\n            paymentRequirements,\n          }),\n        });\n\n        const result: SettleResult = await settleRes.json() as SettleResult;\n\n        if (!result.success) {\n          // Notify plugins of settlement failure (circuit breaker, refund, etc.)\n          if (self.plugins.length > 0) {\n            const failCtx: PluginContext = {\n              network,\n              price: resolvedPrice,\n              path: req.path || req.originalUrl || '/',\n              method: (req.method || 'GET').toUpperCase(),\n            };\n            for (const plugin of self.plugins) {\n              if (!plugin.afterSettled) continue;\n              try {\n                await plugin.afterSettled(req, result, failCtx);\n              } catch (pluginErr) {\n                console.warn(`[Relai] Plugin '${plugin.name}' afterSettled error (non-blocking):`, pluginErr);\n              }\n            }\n          }\n\n          return res.status(402).json({\n            x402Version: 2,\n            error: result.errorReason || result.error || 'Payment settlement failed',\n          });\n        }\n\n        // Attach payment info to request\n        const paymentInfo: PaymentInfo = {\n          verified: true,\n          transactionId: result.transaction,\n          payer: result.payer,\n          network,\n          amount: resolvedPrice,\n        };\n        req.payment = paymentInfo;\n        req.x402Payer = result.payer;\n        req.x402Paid = true;\n        req.x402Transaction = result.transaction;\n        req.x402Network = network;\n\n        // Set x402 v2 PAYMENT-RESPONSE header (base64 JSON)\n        const paymentResponse = {\n          x402Version: 2,\n          scheme: 'exact',\n          network: caip2,\n          transaction: result.transaction,\n          payer: result.payer,\n          amount,\n          asset,\n        };\n        res.setHeader(\n          'PAYMENT-RESPONSE',\n          Buffer.from(JSON.stringify(paymentResponse)).toString('base64'),\n        );\n\n        options.onPaymentSettled?.(req, result);\n\n        // Plugin hooks: afterSettled — called AFTER the handler responds so plugins\n        // can see the actual HTTP status code (e.g. circuit breaker, refund).\n        if (self.plugins.length > 0) {\n          const settleCtx: PluginContext = {\n            network,\n            price: resolvedPrice,\n            path: req.path || req.originalUrl || '/',\n            method: (req.method || 'GET').toUpperCase(),\n          };\n          const pluginsWithHook = self.plugins.filter((p) => !!p.afterSettled);\n          if (pluginsWithHook.length > 0) {\n            // Wrap res.json / res.send to fire afterSettled with actual statusCode\n            const originalJson = (res as any).json?.bind(res);\n            const originalSend = (res as any).send?.bind(res);\n            let afterSettledFired = false;\n            const fireAfterSettled = (statusCode: number) => {\n              if (afterSettledFired) return;\n              afterSettledFired = true;\n              const resultWithStatus = { ...result, statusCode };\n              for (const plugin of pluginsWithHook) {\n                plugin.afterSettled!(req, resultWithStatus, settleCtx).catch((e: unknown) => {\n                  console.warn(`[Relai] Plugin '${plugin.name}' afterSettled error (non-blocking):`, e);\n                });\n              }\n            };\n            if (typeof originalJson === 'function') {\n              (res as any).json = function (body: unknown) {\n                fireAfterSettled(res.statusCode ?? 200);\n                (res as any).json = originalJson; // restore\n                return originalJson(body);\n              };\n            }\n            if (typeof originalSend === 'function') {\n              (res as any).send = function (body: unknown) {\n                fireAfterSettled(res.statusCode ?? 200);\n                (res as any).send = originalSend; // restore\n                return originalSend(body);\n              };\n            }\n          }\n        }\n\n        // Custom validation after payment\n        if (options.customRules) {\n          const valid = await options.customRules(req);\n          if (!valid) {\n            return res.status(403).json({ error: 'Custom validation failed' });\n          }\n        }\n\n        next();\n      } catch (error) {\n        options.onError?.(req, error);\n        console.error('[Relai] Protection error:', error);\n        res.status(500).json({ error: 'Internal server error' });\n      }\n    };\n  }\n}\n\nexport default Relai;\n","// src/types.ts\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** RelAI Facilitator URL */\nexport const RELAI_FACILITATOR_URL = 'https://facilitator.x402.fi';\n\n// ============================================================================\n// Supported Networks\n// ============================================================================\n\n/** All networks supported by RelAI facilitator */\nexport type RelaiNetwork =\n  | 'solana'\n  | 'solana-devnet'\n  | 'base'\n  | 'avalanche'\n  | 'skale-base'\n  | 'skale-base-sepolia'\n  | 'skale-bite'\n  | 'polygon'\n  | 'ethereum'\n  | 'telos';\n\n/** CAIP-2 network identifiers */\nexport const NETWORK_CAIP2: Record<RelaiNetwork, string> = {\n  'solana': 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',\n  'solana-devnet': 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',\n  'base': 'eip155:8453',\n  'avalanche': 'eip155:43114',\n  'skale-base': 'eip155:1187947933',\n  'skale-base-sepolia': 'eip155:324705682',\n  'skale-bite': 'eip155:103698795',\n  'polygon': 'eip155:137',\n  'ethereum': 'eip155:1',\n  'telos': 'eip155:40',\n};\n\n/** Reverse lookup: CAIP-2 → simple network name */\nexport const CAIP2_TO_NETWORK: Record<string, RelaiNetwork> = Object.fromEntries(\n  Object.entries(NETWORK_CAIP2).map(([k, v]) => [v, k as RelaiNetwork])\n) as Record<string, RelaiNetwork>;\n\n/** Chain IDs for EVM networks */\nexport const CHAIN_IDS: Record<string, number> = {\n  'base': 8453,\n  'avalanche': 43114,\n  'skale-base': 1187947933,\n  'skale-base-sepolia': 324705682,\n  'skale-bite': 103698795,\n  'polygon': 137,\n  'ethereum': 1,\n  'telos': 40,\n};\n\nexport interface NetworkToken {\n  address: string;\n  symbol: string;\n  name: string;\n  decimals: number;\n  domainVersion?: string;\n  isStableUsd?: boolean;\n  standards?: string[];\n}\n\n/** Token metadata per network (default token is always the first entry) */\nexport const NETWORK_TOKENS: Partial<Record<RelaiNetwork, NetworkToken[]>> = {\n  'solana': [\n    {\n      address: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n      symbol: 'USDC',\n      name: 'USD Coin',\n      decimals: 6,\n    },\n  ],\n  'solana-devnet': [\n    {\n      address: '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n      symbol: 'USDC',\n      name: 'USD Coin (Devnet)',\n      decimals: 6,\n    },\n  ],\n  'base': [\n    { address: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', symbol: 'USDC', name: 'USD Coin', decimals: 6, domainVersion: '2', isStableUsd: true },\n  ],\n  'avalanche': [\n    {\n      address: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n      symbol: 'USDC',\n      name: 'USD Coin',\n      decimals: 6,\n      domainVersion: '2',\n      isStableUsd: true,\n    },\n  ],\n  'telos': [\n    {\n      address: '0x818ec0a7fe18ff94269904fced6ae3dae6d6dc0b',\n      symbol: 'USDC',\n      name: 'USD Coin',\n      decimals: 6,\n      isStableUsd: true,\n      standards: ['eip2612'],\n    },\n  ],\n  'skale-base': [\n    {\n      address: '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n      symbol: 'USDC',\n      name: 'Bridged USDC (SKALE Bridge)',\n      decimals: 6,\n      domainVersion: '2',\n      isStableUsd: true,\n    },\n    {\n      address: '0x2bF5bF154b515EaA82C31a65ec11554fF5aF7fCA',\n      symbol: 'USDT',\n      name: 'Bridged USDT (SKALE Bridge)',\n      decimals: 6,\n      domainVersion: '1',\n      isStableUsd: true,\n    },\n    {\n      address: '0x1aeeCFE5454c83B42D8A316246CAc9739E7f690e',\n      symbol: 'WBTC',\n      name: 'Wrapped Bitcoin',\n      decimals: 8,\n      domainVersion: '1',\n      isStableUsd: false,\n    },\n    {\n      address: '0x7bD39ABBd0Dd13103542cAe3276C7fA332bCA486',\n      symbol: 'WETH',\n      name: 'Wrapped Ether',\n      decimals: 18,\n      domainVersion: '1',\n      isStableUsd: false,\n    },\n  ],\n  'skale-base-sepolia': [\n    {\n      address: '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n      symbol: 'USDC',\n      name: 'Bridged USDC (SKALE Bridge)',\n      decimals: 6,\n      domainVersion: '2',\n      isStableUsd: true,\n    },\n    {\n      address: '0x3ca0a49f511c2c89c4dcbbf1731120d8919050bf',\n      symbol: 'USDT',\n      name: 'Bridged USDT (SKALE Bridge)',\n      decimals: 6,\n      domainVersion: '1',\n      isStableUsd: true,\n    },\n    {\n      address: '0x4512eacd4186b025186e1cf6cc0d89497c530e87',\n      symbol: 'WBTC',\n      name: 'Wrapped Bitcoin',\n      decimals: 8,\n      domainVersion: '1',\n      isStableUsd: false,\n    },\n    {\n      address: '0xf94056bd7f6965db3757e1b145f200b7346b4fc0',\n      symbol: 'WETH',\n      name: 'Wrapped Ether',\n      decimals: 18,\n      domainVersion: '1',\n      isStableUsd: false,\n    },\n  ],\n  'skale-bite': [\n    {\n      address: '0xc4083B1E81ceb461Ccef3FDa8A9F24F0d764B6D8',\n      symbol: 'USDC',\n      name: 'USDC',\n      decimals: 6,\n      domainVersion: '1',\n      isStableUsd: true,\n    },\n  ],\n  'polygon': [\n    {\n      address: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n      symbol: 'USDC',\n      name: 'USD Coin',\n      decimals: 6,\n      domainVersion: '2',\n      isStableUsd: true,\n    },\n  ],\n  'ethereum': [\n    {\n      address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n      symbol: 'USDC',\n      name: 'USD Coin',\n      decimals: 6,\n      domainVersion: '2',\n      isStableUsd: true,\n    },\n  ],\n};\n\nexport function resolveToken(network: RelaiNetwork, asset?: string): NetworkToken | null {\n  const tokens = NETWORK_TOKENS[network];\n  if (!tokens || tokens.length === 0) return null;\n  if (!asset) return tokens[0];\n\n  const normalized = String(asset).toLowerCase();\n  return tokens.find((token) => token.address.toLowerCase() === normalized) || null;\n}\n\n/** USDC contract addresses per network */\nexport const USDC_ADDRESSES: Record<RelaiNetwork, string> = {\n  'solana': 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',\n  'solana-devnet': '4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU',\n  'base': '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n  'avalanche': '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E',\n  'skale-base': '0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20',\n  'skale-base-sepolia': '0x2e08028E3C4c2356572E096d8EF835cD5C6030bD',\n  'skale-bite': '0xc4083B1E81ceb461Ccef3FDa8A9F24F0d764B6D8',\n  'polygon': '0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359',\n  'ethereum': '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',\n  'telos': '0x818ec0a7fe18ff94269904fced6ae3dae6d6dc0b',\n};\n\n/** Explorer URLs per network */\nexport const EXPLORER_TX_URL: Record<RelaiNetwork, (tx: string) => string> = {\n  'solana': (tx) => `https://solscan.io/tx/${tx}`,\n  'solana-devnet': (tx) => `https://solscan.io/tx/${tx}?cluster=devnet`,\n  'base': (tx) => `https://basescan.org/tx/${tx}`,\n  'avalanche': (tx) => `https://snowtrace.io/tx/${tx}`,\n  'skale-base': (tx) => `https://skale-base-explorer.skalenodes.com/tx/${tx}`,\n  'skale-base-sepolia': (tx) => `https://base-sepolia-testnet-explorer.skalenodes.com/tx/${tx}`,\n  'skale-bite': (tx) => `https://base-sepolia-testnet.explorer.skalenodes.com/tx/${tx}`,\n  'polygon': (tx) => `https://polygonscan.com/tx/${tx}`,\n  'ethereum': (tx) => `https://etherscan.io/tx/${tx}`,\n  'telos': (tx) => `https://teloscan.io/tx/${tx}`,\n};\n\n/** Human-readable network labels */\nexport const NETWORK_LABELS: Record<RelaiNetwork, string> = {\n  'solana': 'Solana',\n  'solana-devnet': 'Solana Devnet',\n  'base': 'Base',\n  'avalanche': 'Avalanche',\n  'skale-base': 'SKALE Base',\n  'skale-base-sepolia': 'SKALE Base Sepolia',\n  'skale-bite': 'SKALE BITE V2',\n  'polygon': 'Polygon',\n  'ethereum': 'Ethereum',\n  'telos': 'Telos EVM',\n};\n\n/** Legacy CAIP-2 exports for backward compatibility */\nexport const SOLANA_MAINNET_NETWORK = NETWORK_CAIP2['solana'];\nexport const BASE_MAINNET_NETWORK = NETWORK_CAIP2['base'];\n\n/** Legacy USDC exports for backward compatibility */\nexport const USDC_SOLANA = USDC_ADDRESSES['solana'];\nexport const USDC_BASE = USDC_ADDRESSES['base'];\n\n/** All supported RelAI networks list */\nexport const RELAI_NETWORKS: RelaiNetwork[] = [\n  'solana',\n  'solana-devnet',\n  'base',\n  'avalanche',\n  'skale-base',\n  'skale-base-sepolia',\n  'skale-bite',\n  'polygon',\n  'ethereum',\n  'telos',\n];\n\n/** Check if a network is Solana-based */\nexport function isSolana(network: string): boolean {\n  return network === 'solana' || network === 'solana-devnet' || network.startsWith('solana:');\n}\n\n/** Check if a network is EVM-based */\nexport function isEvm(network: string): boolean {\n  return ['base', 'avalanche', 'skale-base', 'skale-base-sepolia', 'skale-bite', 'polygon', 'ethereum', 'telos'].includes(network) || network.startsWith('eip155:');\n}\n\n/** Normalize CAIP-2 or simple name to RelaiNetwork */\nexport function normalizeNetwork(network: string): RelaiNetwork | null {\n  if (RELAI_NETWORKS.includes(network as RelaiNetwork)) return network as RelaiNetwork;\n  const fromCaip2 = CAIP2_TO_NETWORK[network];\n  if (fromCaip2) return fromCaip2;\n  // Partial match\n  if (network.startsWith('solana:')) return 'solana';\n  if (network.startsWith('eip155:')) {\n    const chainId = parseInt(network.split(':')[1]);\n    const entry = Object.entries(CHAIN_IDS).find(([, id]) => id === chainId);\n    if (entry) return entry[0] as RelaiNetwork;\n  }\n  return null;\n}\n\n// ============================================================================\n// Wallet Types\n// ============================================================================\n\n/** Solana wallet interface */\nexport interface SolanaWallet {\n  publicKey: { toString(): string } | null;\n  signTransaction: ((tx: unknown) => Promise<unknown>) | null;\n  signAllTransactions?: ((txs: unknown[]) => Promise<unknown[]>) | null;\n}\n\n/** EVM wallet interface (viem-compatible) */\nexport interface EvmWallet {\n  address: string;\n  signTypedData: (params: unknown) => Promise<string>;\n  chain?: { id: number };\n}\n\n/** Wallet set for multi-chain support */\nexport interface WalletSet {\n  solana?: SolanaWallet;\n  evm?: EvmWallet;\n}\n\n// ============================================================================\n// Payment Types\n// ============================================================================\n\n/** Extra fields in payment requirements */\nexport interface AcceptsExtra {\n  feePayer?: string;\n  decimals?: number;\n  name?: string;\n  version?: string;\n  [key: string]: unknown;\n}\n\n/** A single payment option */\nexport interface PaymentAccept {\n  x402Version?: 1 | 2;\n  scheme: string;\n  network: string;\n  maxAmountRequired?: string;\n  amount?: string;\n  asset: string;\n  payTo: string;\n  maxTimeoutSeconds?: number;\n  extra?: AcceptsExtra;\n  resource?: string;\n  description?: string;\n  mimeType?: string;\n  outputSchema?: unknown;\n}\n\n/** Resource info for v2 */\nexport interface ResourceInfo {\n  url: string;\n  description?: string;\n  mimeType?: string;\n}\n\n/** Payment requirements (402 response) */\nexport interface PaymentRequired {\n  x402Version: 1 | 2;\n  error?: string;\n  accepts: PaymentAccept[];\n  resource?: ResourceInfo;\n  extensions?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Config Types (server-specific types are in server.ts)\n// ============================================================================\n"],"mappings":"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","names":["paymentInfo"]}