{"version":3,"sources":["../../src/types/x402-protocol.ts","../../src/utils/helpers.ts","../../src/server/facilitator-client.ts","../../src/server/payment-handler.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Network } from \"@payai/x402/types\";\n\n/**\n * Solana-specific x402 Protocol Types (v2)\n * These are Solana-only variants of x402 protocol types\n */\n\n// CAIP-2 network identifiers for Solana\nexport const SOLANA_MAINNET_CAIP2 =\n  \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\" as const;\nexport const SOLANA_DEVNET_CAIP2 =\n  \"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1\" as const;\n\n/**\n * Solana network type - supports both simple and CAIP-2 formats\n * Simple: \"solana\" | \"solana-devnet\" (for user-facing config)\n * CAIP-2: \"solana:chainId\" (used in protocol)\n */\nexport type SolanaNetworkSimple = \"solana\" | \"solana-devnet\";\nexport type SolanaNetworkCAIP2 =\n  | typeof SOLANA_MAINNET_CAIP2\n  | typeof SOLANA_DEVNET_CAIP2;\nexport type SolanaNetwork = SolanaNetworkSimple | SolanaNetworkCAIP2;\n\n/**\n * Check if a network string is a Solana network (any format)\n */\nexport function isSolanaNetwork(network: string): network is SolanaNetwork {\n  return (\n    network === \"solana\" ||\n    network === \"solana-devnet\" ||\n    network.startsWith(\"solana:\")\n  );\n}\n\n/**\n * Check if network is mainnet\n */\nexport function isSolanaMainnet(network: string): boolean {\n  return network === \"solana\" || network === SOLANA_MAINNET_CAIP2;\n}\n\n/**\n * Check if network is devnet\n */\nexport function isSolanaDevnet(network: string): boolean {\n  return network === \"solana-devnet\" || network === SOLANA_DEVNET_CAIP2;\n}\n\n/**\n * Convert simple network name to CAIP-2 format\n */\nexport function toCAIP2Network(network: SolanaNetworkSimple): Network {\n  switch (network) {\n    case \"solana\":\n      return SOLANA_MAINNET_CAIP2;\n    case \"solana-devnet\":\n      return SOLANA_DEVNET_CAIP2;\n  }\n}\n\n/**\n * Convert CAIP-2 network to simple name (for display/config)\n */\nexport function toSimpleNetwork(network: string): SolanaNetworkSimple {\n  if (network === SOLANA_MAINNET_CAIP2 || network === \"solana\") {\n    return \"solana\";\n  }\n  return \"solana-devnet\";\n}\n","import type { VersionedTransaction } from \"@solana/web3.js\";\nimport type { PaymentRequirements, PaymentPayload } from \"@payai/x402/types\";\nimport {\n  type TokenAsset,\n  SOLANA_MAINNET_CAIP2,\n  SOLANA_DEVNET_CAIP2,\n  isSolanaMainnet,\n} from \"../types\";\n\n/**\n * Helper utilities for x402 payment processing (v2)\n */\n\n// USDC token addresses\nconst USDC_MAINNET = \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\";\nconst USDC_DEVNET = \"4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU\";\n\n/**\n * Create v2 payment payload from a signed transaction\n * Encodes transaction and payment details for PAYMENT-SIGNATURE header\n *\n * @param transaction - Signed Solana VersionedTransaction\n * @param paymentRequirements - The accepted payment requirements\n * @param resourceUrl - URL of the protected resource\n * @returns Base64-encoded payment payload for PAYMENT-SIGNATURE header\n */\nexport function createPaymentPayload(\n  transaction: VersionedTransaction,\n  paymentRequirements: PaymentRequirements,\n  resourceUrl: string,\n): string {\n  // Serialize the signed transaction to base64\n  const base64Transaction = Buffer.from(transaction.serialize()).toString(\n    \"base64\",\n  );\n\n  // Create v2 payment payload\n  const paymentPayload: PaymentPayload = {\n    x402Version: 2,\n    resource: {\n      url: resourceUrl,\n      description: (paymentRequirements.extra?.description as string) || \"\",\n      mimeType:\n        (paymentRequirements.extra?.mimeType as string) || \"application/json\",\n    },\n    accepted: paymentRequirements,\n    payload: {\n      transaction: base64Transaction,\n    },\n  };\n\n  // Encode payment payload as base64 for PAYMENT-SIGNATURE header\n  const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');\n\n  return paymentHeader;\n}\n\n/**\n * Create v1 payment payload from a signed transaction\n * Encodes transaction for X-PAYMENT header (v1 format)\n *\n * @param transaction - Signed Solana VersionedTransaction\n * @param paymentRequirements - The accepted payment requirements\n * @returns Base64-encoded payment payload for X-PAYMENT header\n */\nexport function createPaymentPayloadV1(\n  transaction: VersionedTransaction,\n  paymentRequirements: PaymentRequirements\n): string {\n  // Serialize the signed transaction to base64\n  const base64Transaction = Buffer.from(transaction.serialize()).toString('base64');\n\n  // Create v1 payment payload (simpler format)\n  const paymentPayload = {\n    x402Version: 1,\n    scheme: paymentRequirements.scheme,\n    network: paymentRequirements.network,\n    payload: {\n      transaction: base64Transaction,\n    },\n  };\n\n  // Encode payment payload as base64 for X-PAYMENT header\n  const paymentHeader = Buffer.from(JSON.stringify(paymentPayload)).toString(\n    \"base64\",\n  );\n\n  return paymentHeader;\n}\n\n/**\n * Get default RPC URL for a given Solana network\n * @param network - Network in any format (simple or CAIP-2)\n * @returns Default RPC URL for the network\n */\nexport function getDefaultRpcUrl(network: string): string {\n  if (isSolanaMainnet(network)) {\n    return \"https://api.mainnet-beta.solana.com\";\n  }\n  return \"https://api.devnet.solana.com\";\n}\n\n/**\n * Get RPC URL for a CAIP-2 network identifier\n * @param network - Network in CAIP-2 format (e.g., \"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp\")\n * @returns RPC URL for the network\n */\nexport function getRpcUrlForNetwork(network: string): string {\n  if (network === SOLANA_MAINNET_CAIP2) {\n    return \"https://api.mainnet-beta.solana.com\";\n  }\n  if (network === SOLANA_DEVNET_CAIP2) {\n    return \"https://api.devnet.solana.com\";\n  }\n  // Fallback for unknown networks\n  return \"https://api.devnet.solana.com\";\n}\n\n/**\n * Get default USDC token asset for a given Solana network\n * @param network - Network in any format (simple or CAIP-2)\n * @returns USDC token asset configuration\n */\nexport function getDefaultTokenAsset(network: string): TokenAsset {\n  if (isSolanaMainnet(network)) {\n    return {\n      address: USDC_MAINNET,\n      decimals: 6,\n    };\n  }\n  return {\n    address: USDC_DEVNET,\n    decimals: 6,\n  };\n}\n\n/**\n * Convert human-readable amount to token's smallest unit (atomic units)\n * @param amount - Human-readable amount (e.g., 2.5 for 2.5 USDC)\n * @param decimals - Token decimals (e.g., 6 for USDC, 9 for SOL)\n * @returns Amount in atomic units as string\n */\nexport function toAtomicUnits(amount: number, decimals: number): string {\n  return Math.floor(amount * Math.pow(10, decimals)).toString();\n}\n\n/**\n * Convert token's atomic units to human-readable amount\n * @param atomicUnits - Token amount in smallest units (as string or bigint)\n * @param decimals - Token decimals (e.g., 6 for USDC, 9 for SOL)\n * @returns Human-readable amount\n */\nexport function fromAtomicUnits(\n  atomicUnits: string | bigint | number,\n  decimals: number,\n): number {\n  return Number(atomicUnits) / Math.pow(10, decimals);\n}\n","import type {\n  PaymentRequirements,\n  PaymentPayload,\n  VerifyResponse,\n  SettleResponse,\n  SupportedResponse,\n} from '@payai/x402/types';\nimport { getOrGenerateJwt } from '@payai/facilitator';\nimport { isSolanaNetwork } from '../types';\n\n/**\n * Facilitator supported kind (from /supported endpoint)\n */\ninterface SupportedKind {\n  x402Version: number;\n  scheme: string;\n  network: string;\n  extra?: {\n    feePayer?: string;\n    [key: string]: unknown;\n  };\n}\n\n/**\n * Configuration for the facilitator client\n */\ninterface FacilitatorClientConfig {\n  url: string;\n  /** PayAI API Key ID for JWT auth */\n  apiKeyId?: string | undefined;\n  /** PayAI API Key Secret for JWT auth */\n  apiKeySecret?: string | undefined;\n}\n\n/**\n * Client for communicating with x402 facilitator service (v2).\n *\n * When `apiKeyId` and `apiKeySecret` are provided, all requests are\n * automatically authenticated with a JWT Bearer token (cached and refreshed).\n */\nexport class FacilitatorClient {\n  private readonly facilitatorUrl: string;\n  private readonly apiKeyId: string | undefined;\n  private readonly apiKeySecret: string | undefined;\n\n  constructor(config: FacilitatorClientConfig) {\n    this.facilitatorUrl = config.url;\n    this.apiKeyId = config.apiKeyId;\n    this.apiKeySecret = config.apiKeySecret;\n  }\n\n  /**\n   * Build auth headers when API keys are configured.\n   * Returns an empty object when no keys are present.\n   */\n  private async getAuthHeaders(): Promise<Record<string, string>> {\n    if (!this.apiKeyId || !this.apiKeySecret) {\n      return {};\n    }\n\n    const jwt = await getOrGenerateJwt({\n      apiKeyId: this.apiKeyId,\n      apiKeySecret: this.apiKeySecret,\n    });\n\n    return { Authorization: `Bearer ${jwt}` };\n  }\n\n  /**\n   * Get supported payment kinds from facilitator\n   */\n  async getSupported(): Promise<SupportedResponse> {\n    const authHeaders = await this.getAuthHeaders();\n\n    const response = await fetch(`${this.facilitatorUrl}/supported`, {\n      headers: { ...authHeaders },\n    });\n\n    if (!response.ok) {\n      throw new Error(`Facilitator /supported returned ${response.status}`);\n    }\n    return response.json();\n  }\n\n  /**\n   * Get fee payer address for a Solana network\n   * @param network - Network in any format (simple or CAIP-2)\n   */\n  async getFeePayer(network: string): Promise<string> {\n    const supportedData = await this.getSupported();\n\n    // Look for network support - match by CAIP-2 prefix for Solana networks\n    const networkSupport = (supportedData.kinds as SupportedKind[])?.find(\n      kind =>\n        kind.scheme === 'exact' &&\n        isSolanaNetwork(kind.network) &&\n        isSolanaNetwork(network) &&\n        // Match if both are same network type (mainnet or devnet)\n        (kind.network.includes('devnet') === network.includes('devnet') || kind.network === network)\n    );\n\n    if (!networkSupport?.extra?.feePayer) {\n      throw new Error(\n        `Facilitator does not support network \"${network}\" with scheme \"exact\" or feePayer not provided`\n      );\n    }\n\n    return networkSupport.extra.feePayer;\n  }\n\n  /**\n   * Verify payment with facilitator\n   * @returns VerifyResponse with isValid and optional invalidReason\n   */\n  async verifyPayment(\n    paymentHeader: string,\n    paymentRequirements: PaymentRequirements\n  ): Promise<VerifyResponse> {\n    try {\n      // Decode the base64 payment payload\n      const paymentPayload: PaymentPayload = JSON.parse(\n        Buffer.from(paymentHeader, 'base64').toString('utf8')\n      );\n\n      const verifyPayload = {\n        paymentPayload,\n        paymentRequirements,\n      };\n\n      const authHeaders = await this.getAuthHeaders();\n\n      const response = await fetch(`${this.facilitatorUrl}/verify`, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          ...authHeaders,\n        },\n        body: JSON.stringify(verifyPayload),\n      });\n\n      if (!response.ok) {\n        const errorBody = await response.text();\n        console.error(`Facilitator /verify returned ${response.status}:`, errorBody);\n        return {\n          isValid: false,\n          invalidReason: 'unexpected_verify_error',\n        };\n      }\n\n      // Facilitator returns VerifyResponse with status 200 even when validation fails\n      const facilitatorResponse: VerifyResponse = await response.json();\n      return facilitatorResponse;\n    } catch (error) {\n      console.error('Payment verification failed:', error);\n      return {\n        isValid: false,\n        invalidReason: 'unexpected_verify_error',\n      };\n    }\n  }\n\n  /**\n   * Settle payment with facilitator\n   * @returns SettleResponse with success status and optional errorReason\n   */\n  async settlePayment(\n    paymentHeader: string,\n    paymentRequirements: PaymentRequirements\n  ): Promise<SettleResponse> {\n    try {\n      // Decode the base64 payment payload\n      const paymentPayload: PaymentPayload = JSON.parse(\n        Buffer.from(paymentHeader, 'base64').toString('utf8')\n      );\n\n      const settlePayload = {\n        paymentPayload,\n        paymentRequirements,\n      };\n\n      const authHeaders = await this.getAuthHeaders();\n\n      const response = await fetch(`${this.facilitatorUrl}/settle`, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          ...authHeaders,\n        },\n        body: JSON.stringify(settlePayload),\n      });\n\n      if (!response.ok) {\n        const errorBody = await response.text();\n        console.error(`Facilitator /settle returned ${response.status}:`, errorBody);\n        return {\n          success: false,\n          errorReason: 'unexpected_settle_error',\n          transaction: '',\n          network: paymentRequirements.network,\n        };\n      }\n\n      // Facilitator returns SettleResponse with status 200 even when settlement fails\n      const facilitatorResponse: SettleResponse = await response.json();\n      return facilitatorResponse;\n    } catch (error) {\n      console.error('Payment settlement failed:', error);\n      return {\n        success: false,\n        errorReason: 'unexpected_settle_error',\n        transaction: '',\n        network: paymentRequirements.network,\n      };\n    }\n  }\n}\n","import type {\n  PaymentRequirements,\n  PaymentRequired,\n  VerifyResponse,\n  SettleResponse,\n  Network,\n} from '@payai/x402/types';\nimport type { X402ServerConfig, RouteConfig, TokenAsset } from '../types';\nimport { toCAIP2Network } from '../types';\nimport { getDefaultRpcUrl, getDefaultTokenAsset } from '../utils';\nimport { FacilitatorClient } from './facilitator-client';\n\n/**\n * Internal configuration with defaults resolved\n */\ninterface InternalConfig {\n  network: string; // CAIP-2 format\n  treasuryAddress: string;\n  facilitatorUrl: string;\n  rpcUrl: string;\n  defaultToken: TokenAsset;\n  defaultDescription: string;\n  defaultTimeoutSeconds: number;\n}\n\n/**\n * x402 Payment Handler for server-side payment processing (v2)\n * Framework agnostic - works with any Node.js HTTP framework\n */\nexport class X402PaymentHandler {\n  private facilitatorClient: FacilitatorClient;\n  private config: InternalConfig;\n\n  constructor(config: X402ServerConfig) {\n    const defaultToken = config.defaultToken || getDefaultTokenAsset(config.network);\n\n    this.config = {\n      network: toCAIP2Network(config.network),\n      treasuryAddress: config.treasuryAddress,\n      facilitatorUrl: config.facilitatorUrl,\n      rpcUrl: config.rpcUrl || getDefaultRpcUrl(config.network),\n      defaultToken,\n      defaultDescription: config.defaultDescription || 'Payment required',\n      defaultTimeoutSeconds: config.defaultTimeoutSeconds || 300,\n    };\n\n    this.facilitatorClient = new FacilitatorClient({\n      url: config.facilitatorUrl,\n      apiKeyId: config.apiKeyId,\n      apiKeySecret: config.apiKeySecret,\n    });\n  }\n\n  /**\n   * Extract payment header from request headers (v2)\n   * Pass in headers object from any framework (Next.js, Express, etc.)\n   *\n   * Note: v2 uses PAYMENT-SIGNATURE header (v1 used X-PAYMENT)\n   */\n  extractPayment(headers: Record<string, string | string[] | undefined> | Headers): string | null {\n    // Handle Headers object (Next.js, Fetch API)\n    if (headers instanceof Headers) {\n      // v2 header (PAYMENT-SIGNATURE)\n      return headers.get('PAYMENT-SIGNATURE') || headers.get('payment-signature');\n    }\n\n    // Handle plain object (Express, Fastify, etc.)\n    // v2 header (PAYMENT-SIGNATURE)\n    const paymentSignature = headers['PAYMENT-SIGNATURE'] || headers['payment-signature'];\n    return Array.isArray(paymentSignature) ? paymentSignature[0] || null : paymentSignature || null;\n  }\n\n  /**\n   * Create payment requirements for a protected resource\n   *\n   * @param routeConfig - Route-specific configuration\n   * @param resourceUrl - URL of the protected resource\n   * @returns Payment requirements object\n   */\n  async createPaymentRequirements(\n    routeConfig: RouteConfig,\n    resourceUrl: string\n  ): Promise<PaymentRequirements> {\n    // Get fee payer from facilitator\n    const feePayer = await this.facilitatorClient.getFeePayer(this.config.network);\n\n    const paymentRequirements: PaymentRequirements = {\n      scheme: 'exact',\n      network: this.config.network as Network,\n      amount: routeConfig.amount,\n      payTo: this.config.treasuryAddress,\n      maxTimeoutSeconds: routeConfig.maxTimeoutSeconds || this.config.defaultTimeoutSeconds,\n      asset: routeConfig.asset.address,\n      extra: {\n        feePayer,\n        description: routeConfig.description || this.config.defaultDescription,\n        mimeType: routeConfig.mimeType || 'application/json',\n        resource: resourceUrl,\n      },\n    };\n\n    return paymentRequirements;\n  }\n\n  /**\n   * Create a 402 Payment Required response body (v2)\n   * Use this with your framework's response method\n   *\n   * @param requirements - Payment requirements (from createPaymentRequirements)\n   * @param resourceUrl - URL of the protected resource\n   */\n  create402Response(\n    requirements: PaymentRequirements,\n    resourceUrl: string\n  ): {\n    status: 402;\n    body: PaymentRequired;\n  } {\n    return {\n      status: 402,\n      body: {\n        x402Version: 2,\n        resource: {\n          url: resourceUrl,\n          description: (requirements.extra?.description as string) || '',\n          mimeType: (requirements.extra?.mimeType as string) || 'application/json',\n        },\n        accepts: [requirements],\n        error: 'Payment required',\n      },\n    };\n  }\n\n  /**\n   * Verify payment with facilitator\n   * @returns VerifyResponse with isValid and optional invalidReason\n   */\n  async verifyPayment(\n    paymentHeader: string,\n    paymentRequirements: PaymentRequirements\n  ): Promise<VerifyResponse> {\n    return this.facilitatorClient.verifyPayment(paymentHeader, paymentRequirements);\n  }\n\n  /**\n   * Settle payment with facilitator\n   * @returns SettleResponse with success status and optional errorReason\n   */\n  async settlePayment(\n    paymentHeader: string,\n    paymentRequirements: PaymentRequirements\n  ): Promise<SettleResponse> {\n    return this.facilitatorClient.settlePayment(paymentHeader, paymentRequirements);\n  }\n\n  /**\n   * Get the network in CAIP-2 format\n   */\n  getNetwork(): string {\n    return this.config.network;\n  }\n\n  /**\n   * Get the treasury address\n   */\n  getTreasuryAddress(): string {\n    return this.config.treasuryAddress;\n  }\n}\n"]}