{"version":3,"sources":["../../src/commitment.ts","../../src/server-extension.ts","../../src/client/exact-evm-scheme.ts","../../src/client/extension-handler.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Commitment calculation utilities\n *\n * The commitment hash binds all settlement parameters to the client's signature,\n * preventing parameter tampering attacks.\n */\n\nimport { keccak256, encodePacked, type Hex } from \"viem\";\n\nimport type { CommitmentParams } from \"./types.js\";\n\n/**\n * Calculate commitment hash for x402x settlement\n *\n * This hash becomes the EIP-3009 nonce, cryptographically binding all settlement\n * parameters to the client's signature. The parameter order must exactly match\n * SettlementRouter.sol.\n *\n * @param params - All settlement parameters\n * @returns bytes32 commitment hash\n *\n * @example\n * ```typescript\n * const commitment = calculateCommitment({\n *   chainId: 84532,\n *   hub: '0x...',\n *   asset: '0x...',\n *   from: '0x...',\n *   value: '100000',\n *   validAfter: '0',\n *   validBefore: '1234567890',\n *   salt: '0x...',\n *   payTo: '0x...',\n *   facilitatorFee: '10000',\n *   hook: '0x...',\n *   hookData: '0x',\n * });\n * ```\n */\nexport function calculateCommitment(params: CommitmentParams): string {\n  // Pack parameters in exact order as in SettlementRouter.sol\n  return keccak256(\n    encodePacked(\n      [\n        \"string\", // Protocol identifier\n        \"uint256\", // Chain ID\n        \"address\", // Hub address\n        \"address\", // Token address\n        \"address\", // From (payer)\n        \"uint256\", // Value\n        \"uint256\", // Valid after\n        \"uint256\", // Valid before\n        \"bytes32\", // Salt\n        \"address\", // Pay to\n        \"uint256\", // Facilitator fee\n        \"address\", // Hook\n        \"bytes32\", // keccak256(hookData)\n      ],\n      [\n        \"X402/settle/v1\",\n        BigInt(params.chainId),\n        params.hub as Hex,\n        params.asset as Hex,\n        params.from as Hex,\n        BigInt(params.value),\n        BigInt(params.validAfter),\n        BigInt(params.validBefore),\n        params.salt as Hex,\n        params.payTo as Hex,\n        BigInt(params.facilitatorFee),\n        params.hook as Hex,\n        keccak256(params.hookData as Hex),\n      ],\n    ),\n  );\n}\n\n/**\n * Generate a random salt for settlement uniqueness\n *\n * Works in both Node.js and browser environments.\n * Uses crypto.getRandomValues (Web Crypto API) which is available in:\n * - Modern browsers\n * - Node.js 15+ (via global crypto)\n * - Older Node.js (via crypto.webcrypto)\n *\n * @returns bytes32 hex string (0x + 64 hex characters)\n *\n * @example\n * ```typescript\n * const salt = generateSalt();\n * // => '0x1234567890abcdef...'\n * ```\n */\nexport function generateSalt(): string {\n  // Try to get crypto from global (browser or Node.js 15+)\n  const globalCrypto = typeof crypto !== \"undefined\" ? crypto : undefined;\n\n  if (globalCrypto?.getRandomValues) {\n    // Use Web Crypto API (works in browser and modern Node.js)\n    const bytes = new Uint8Array(32);\n    globalCrypto.getRandomValues(bytes);\n    return `0x${Array.from(bytes)\n      .map((b) => b.toString(16).padStart(2, \"0\"))\n      .join(\"\")}`;\n  }\n\n  // Fallback: use Math.random() (less secure, but works everywhere)\n  // Note: Salt doesn't require cryptographic security - it's just for uniqueness\n  console.warn(\n    \"[generateSalt] Using Math.random() fallback - consider upgrading to Node.js 15+ or use in browser\",\n  );\n  const bytes = new Uint8Array(32);\n  for (let i = 0; i < 32; i++) {\n    bytes[i] = Math.floor(Math.random() * 256);\n  }\n  return `0x${Array.from(bytes)\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\")}`;\n}\n\n/**\n * Validate commitment parameters\n *\n * @param params - Commitment parameters to validate\n * @throws Error if validation fails\n */\nexport function validateCommitmentParams(params: CommitmentParams): void {\n  // Validate addresses\n  if (!isValidAddress(params.hub)) {\n    throw new Error(\"Invalid hub address\");\n  }\n  if (!isValidAddress(params.asset)) {\n    throw new Error(\"Invalid asset address\");\n  }\n  if (!isValidAddress(params.from)) {\n    throw new Error(\"Invalid from address\");\n  }\n  if (!isValidAddress(params.payTo)) {\n    throw new Error(\"Invalid payTo address\");\n  }\n  if (!isValidAddress(params.hook)) {\n    throw new Error(\"Invalid hook address\");\n  }\n\n  // Validate numeric values\n  try {\n    BigInt(params.value);\n    BigInt(params.validAfter);\n    BigInt(params.validBefore);\n    BigInt(params.facilitatorFee);\n  } catch {\n    throw new Error(\"Invalid numeric parameter\");\n  }\n\n  // Validate bytes32 values\n  if (!isValidHex(params.salt) || params.salt.length !== 66) {\n    throw new Error(\"Invalid salt: must be bytes32 (0x + 64 hex chars)\");\n  }\n\n  if (!isValidHex(params.hookData)) {\n    throw new Error(\"Invalid hookData: must be hex string\");\n  }\n}\n\n/**\n * Check if a string is a valid Ethereum address\n */\nfunction isValidAddress(address: string): boolean {\n  return /^0x[0-9a-fA-F]{40}$/.test(address);\n}\n\n/**\n * Check if a string is a valid hex string\n */\nfunction isValidHex(hex: string): boolean {\n  return /^0x[0-9a-fA-F]*$/.test(hex);\n}\n","/**\n * x402x Router Settlement Server Extension\n *\n * Implements ResourceServerExtension interface to integrate router settlement\n * functionality into x402 v2 resource servers.\n */\n\nimport type { x402ResourceServer } from \"@x402/core/server\";\nimport type { ResourceServerExtension } from \"@x402/core/types\";\n\nimport { generateSalt } from \"./commitment.js\";\nimport { createRouterSettlementExtension } from \"./extensions.js\";\n\n/**\n * Extension key constant\n */\nexport const ROUTER_SETTLEMENT_KEY = \"x402x-router-settlement\";\n\n/**\n * Type guard to check if context is an HTTP request context.\n *\n * @param ctx - The context to check\n * @returns True if context is an HTTPRequestContext\n */\nfunction isHTTPRequestContext(ctx: unknown): ctx is { method?: string; adapter?: unknown } {\n  return ctx !== null && typeof ctx === \"object\" && \"method\" in ctx;\n}\n\n/**\n * Router settlement extension declaration type\n */\ninterface RouterSettlementDeclaration {\n  [key: string]: unknown;\n  info?: {\n    [key: string]: unknown;\n    schemaVersion?: number;\n    description?: string;\n    /** Dynamic fields that need to be generated per-request */\n    dynamic?: {\n      salt?: boolean;\n      [key: string]: unknown;\n    };\n  };\n  schema?: Record<string, unknown>;\n}\n\n/**\n * x402x Router Settlement ResourceServerExtension\n *\n * This extension enriches PaymentRequired responses with router settlement\n * information, enabling clients to use the SettlementRouter for atomic payments.\n *\n * The extension dynamically generates per-request values like salt to ensure\n * each payment authorization is unique and cannot be replayed.\n *\n * @example\n * ```typescript\n * import { x402ResourceServer } from \"@x402/core/server\";\n * import { routerSettlementServerExtension } from \"@x402x/extensions\";\n *\n * const server = new x402ResourceServer(facilitatorClient);\n * server.registerExtension(routerSettlementServerExtension);\n * ```\n */\nexport const routerSettlementServerExtension: ResourceServerExtension = {\n  key: ROUTER_SETTLEMENT_KEY,\n\n  enrichDeclaration: (declaration, transportContext) => {\n    // Cast to typed declaration\n    const extension = declaration as RouterSettlementDeclaration;\n\n    // Generate dynamic salt for this request\n    const salt = generateSalt();\n\n    // Basic enrichment - ensure proper structure with dynamic salt\n    const enriched: RouterSettlementDeclaration = {\n      ...extension,\n      info: {\n        schemaVersion: 1,\n        ...(extension.info || {}),\n        // Add the generated salt to the info\n        salt,\n      },\n    };\n\n    // If HTTP context is available, we could add additional metadata\n    if (isHTTPRequestContext(transportContext)) {\n      // Future: could add HTTP-specific metadata here\n      // For now, the salt generation is the main dynamic enhancement\n    }\n\n    return enriched;\n  },\n};\n\n/**\n * Register router settlement extension with an x402ResourceServer\n *\n * Convenience function to register the routerSettlementServerExtension.\n * Also registers necessary hooks for handling settlement parameters.\n *\n * @param server - x402ResourceServer instance\n * @returns The server instance for chaining\n *\n * @example\n * ```typescript\n * import { x402ResourceServer } from \"@x402/core/server\";\n * import { registerExactEvmScheme } from \"@x402/evm/exact/server/register\";\n * import { registerRouterSettlement } from \"@x402x/extensions\";\n *\n * const server = new x402ResourceServer(facilitatorClient);\n * registerExactEvmScheme(server, {});\n * registerRouterSettlement(server);\n * ```\n */\nexport function registerRouterSettlement(server: x402ResourceServer): x402ResourceServer {\n  // Register the extension for enriching PaymentRequired responses\n  server.registerExtension(routerSettlementServerExtension);\n\n  // Note: Hooks for verify/settle are registered separately via\n  // registerSettlementHooks if needed for custom validation logic\n\n  return server;\n}\n\n/**\n * Create extension declaration for routes\n *\n * Helper function to create properly formatted extension declarations\n * for use in route configurations. The extension enables dynamic salt\n * generation per request and includes all settlement parameters.\n *\n * @param params - Extension parameters including settlement info\n * @returns Extension declaration object\n *\n * @example\n * ```typescript\n * const routes = {\n *   \"GET /api/data\": {\n *     accepts: { scheme: \"exact\", price: \"$0.01\", network: \"eip155:84532\", payTo: \"0x...\" },\n *     extensions: createExtensionDeclaration({\n *       description: \"Router settlement with dynamic salt\",\n *       settlementRouter: \"0x...\",\n *       hook: \"0x...\",\n *       hookData: \"0x\",\n *       finalPayTo: \"0x...\",\n *       facilitatorFee: \"0\",\n *       salt: \"0x...\" // Optional, will be auto-generated if not provided\n *     })\n *   }\n * };\n * ```\n */\nexport function createExtensionDeclaration(params?: {\n  description?: string;\n  schema?: Record<string, unknown>;\n  settlementRouter?: string;\n  hook?: string;\n  hookData?: string;\n  finalPayTo?: string;\n  facilitatorFee?: string;\n  salt?: string; // Optional salt, will be auto-generated if not provided\n}): Record<string, unknown> {\n  return {\n    [ROUTER_SETTLEMENT_KEY]: createRouterSettlementExtension(params),\n  };\n}\n","/**\n * x402x EVM Client Scheme with Router Settlement\n *\n * This scheme extends the standard EVM exact scheme to support x402x router settlement.\n * The key difference is using a commitment hash (binding all settlement parameters)\n * as the EIP-3009 nonce instead of a random value.\n */\n\nimport type { PaymentPayload, PaymentRequirements, SchemeNetworkClient } from \"@x402/core/types\";\nimport { getAddress, type Hex } from \"viem\";\n\nimport { calculateCommitment } from \"../commitment.js\";\nimport { ROUTER_SETTLEMENT_KEY } from \"../server-extension.js\";\nimport type { CommitmentParams } from \"../types.js\";\n\n/**\n * Client EVM signer interface\n * Compatible with viem WalletClient and LocalAccount\n */\nexport type ClientEvmSigner = {\n  readonly address: `0x${string}`;\n  signTypedData(message: {\n    domain: Record<string, unknown>;\n    types: Record<string, unknown>;\n    primaryType: string;\n    message: Record<string, unknown>;\n  }): Promise<`0x${string}`>;\n};\n\n/**\n * EIP-3009 TransferWithAuthorization types for EIP-712 signing\n */\nconst authorizationTypes = {\n  TransferWithAuthorization: [\n    { name: \"from\", type: \"address\" },\n    { name: \"to\", type: \"address\" },\n    { name: \"value\", type: \"uint256\" },\n    { name: \"validAfter\", type: \"uint256\" },\n    { name: \"validBefore\", type: \"uint256\" },\n    { name: \"nonce\", type: \"bytes32\" },\n  ],\n} as const;\n\n/**\n * EVM exact payment payload structure (v2)\n */\ninterface ExactEvmPayloadV2 {\n  authorization: {\n    from: string;\n    to: string;\n    value: string;\n    validAfter: string;\n    validBefore: string;\n    nonce: Hex;\n  };\n  signature: `0x${string}`;\n}\n\n/**\n * x402x router settlement extension info structure\n */\ninterface RouterSettlementExtension {\n  info: {\n    schemaVersion?: number;\n    description?: string;\n    salt: string; // bytes32 hex\n    settlementRouter?: string; // address\n    hook?: string; // address\n    hookData?: string; // bytes hex\n    finalPayTo?: string; // address\n    facilitatorFee?: string; // uint256 string\n  };\n  schema?: Record<string, unknown>;\n}\n\n/**\n * EVM client implementation for the Exact payment scheme with x402x router settlement.\n *\n * This scheme uses a commitment hash as the EIP-3009 nonce to cryptographically bind\n * all settlement parameters (salt, hook, hookData, etc.) to the user's signature,\n * preventing parameter tampering attacks.\n *\n * @example\n * ```typescript\n * import { ExactEvmSchemeWithRouterSettlement } from '@x402x/extensions/client';\n * import { x402Client } from '@x402/core/client';\n *\n * const signer = { address, signTypedData }; // viem WalletClient or LocalAccount\n * const scheme = new ExactEvmSchemeWithRouterSettlement(signer);\n *\n * const client = new x402Client()\n *   .register('eip155:84532', scheme);\n * ```\n */\nexport class ExactEvmSchemeWithRouterSettlement implements SchemeNetworkClient {\n  readonly scheme = \"exact\";\n\n  /**\n   * Per-request router settlement extension (typically sourced from PaymentRequired.extensions).\n   *\n   * IMPORTANT: We do NOT put this on `paymentRequirements.extra`, because for x402 v2 the\n   * server matches paid requests by deep-equality between `paymentPayload.accepted` and the\n   * server-side `accepts[]`. Mutating `accepted` will cause \"No matching payment requirements\".\n   */\n  private routerSettlementFromPaymentRequired?: RouterSettlementExtension;\n\n  /**\n   * Creates a new ExactEvmSchemeWithRouterSettlement instance.\n   *\n   * @param signer - The EVM signer for client operations (viem WalletClient or LocalAccount)\n   */\n  constructor(private readonly signer: ClientEvmSigner) {}\n\n  /**\n   * Set router-settlement extension data for the next payment payload creation.\n   *\n   * Intended to be called from an `x402Client.onBeforePaymentCreation` hook, which has access\n   * to `paymentRequired.extensions`.\n   */\n  setRouterSettlementExtensionFromPaymentRequired(ext: unknown | undefined): void {\n    if (!ext) {\n      this.routerSettlementFromPaymentRequired = undefined;\n      return;\n    }\n    // We keep this cast narrow and validate at use-time.\n    this.routerSettlementFromPaymentRequired = ext as RouterSettlementExtension;\n  }\n\n  /**\n   * Creates a payment payload for the Exact scheme with router settlement.\n   *\n   * This method:\n   * 1. Extracts settlement parameters from PaymentRequired.extensions\n   * 2. Calculates a commitment hash binding all parameters\n   * 3. Uses the commitment as the EIP-3009 nonce\n   * 4. Signs with settlementRouter as the 'to' address\n   *\n   * @param x402Version - The x402 protocol version (must be 2)\n   * @param paymentRequirements - The payment requirements from the server\n   * @returns Promise resolving to a payment payload\n   *\n   * @throws Error if x402Version is not 2\n   * @throws Error if x402x-router-settlement extension is missing\n   * @throws Error if required settlement parameters are missing\n   */\n  async createPaymentPayload(\n    x402Version: number,\n    paymentRequirements: PaymentRequirements,\n  ): Promise<Pick<PaymentPayload, \"x402Version\" | \"payload\">> {\n    if (x402Version !== 2) {\n      throw new Error(\n        `ExactEvmSchemeWithRouterSettlement only supports x402 version 2, got: ${x402Version}`,\n      );\n    }\n\n    // Extract x402x extension.\n    // Prefer per-requirement extra (if a server implementation provides it),\n    // otherwise use the per-request data injected from PaymentRequired.extensions.\n    const routerSettlement =\n      (paymentRequirements.extra?.[ROUTER_SETTLEMENT_KEY] as\n        | RouterSettlementExtension\n        | undefined) ?? this.routerSettlementFromPaymentRequired;\n\n    if (!routerSettlement?.info) {\n      throw new Error(\n        \"x402x-router-settlement extension not available for scheme signing. \" +\n          \"Ensure the resource server includes the extension in PaymentRequired.extensions and \" +\n          \"the client registered x402x via registerX402xScheme() (or injected the handler).\",\n      );\n    }\n\n    const { salt, settlementRouter, hook, hookData, finalPayTo, facilitatorFee } =\n      routerSettlement.info;\n\n    // Clear after read to avoid leaking between requests\n    this.routerSettlementFromPaymentRequired = undefined;\n\n    // Validate required parameters\n    if (!salt) throw new Error(\"Missing required parameter: salt\");\n    if (!settlementRouter) throw new Error(\"Missing required parameter: settlementRouter\");\n    if (!hook) throw new Error(\"Missing required parameter: hook\");\n    if (hookData === undefined) throw new Error(\"Missing required parameter: hookData\");\n    if (!finalPayTo) throw new Error(\"Missing required parameter: finalPayTo\");\n    // facilitatorFee is optional - if not provided, use \"0\" (facilitator will calculate actual fee)\n    const resolvedFacilitatorFee = facilitatorFee ?? \"0\";\n\n    // Parse chain ID from network (e.g., \"eip155:84532\" -> 84532)\n    const chainId = parseInt(paymentRequirements.network.split(\":\")[1]);\n    if (isNaN(chainId)) {\n      throw new Error(`Invalid network format: ${paymentRequirements.network}`);\n    }\n\n    // Calculate time window\n    const now = Math.floor(Date.now() / 1000);\n    const validAfter = (now - 600).toString(); // 10 minutes before\n    const validBefore = (now + paymentRequirements.maxTimeoutSeconds).toString();\n\n    // Build commitment parameters\n    const commitmentParams: CommitmentParams = {\n      chainId,\n      hub: settlementRouter,\n      asset: paymentRequirements.asset,\n      from: this.signer.address,\n      value: paymentRequirements.amount,\n      validAfter,\n      validBefore,\n      salt,\n      payTo: finalPayTo,\n      facilitatorFee: resolvedFacilitatorFee,\n      hook,\n      hookData,\n    };\n\n    // Calculate commitment hash - this becomes the nonce\n    const nonce = calculateCommitment(commitmentParams) as Hex;\n\n    // Build authorization (EIP-3009)\n    // CRITICAL: 'to' must be settlementRouter, not payTo\n    const authorization: ExactEvmPayloadV2[\"authorization\"] = {\n      from: this.signer.address,\n      to: getAddress(settlementRouter),\n      value: paymentRequirements.amount,\n      validAfter,\n      validBefore,\n      nonce,\n    };\n\n    // Sign the authorization using EIP-712\n    const signature = await this.signAuthorization(authorization, paymentRequirements, chainId);\n\n    // Build payload\n    const payload: Record<string, unknown> = {\n      authorization,\n      signature,\n    };\n\n    return {\n      x402Version,\n      payload,\n    };\n  }\n\n  /**\n   * Sign the EIP-3009 authorization using EIP-712\n   *\n   * @param authorization - The authorization to sign\n   * @param requirements - The payment requirements\n   * @param chainId - The chain ID\n   * @returns Promise resolving to the signature\n   */\n  private async signAuthorization(\n    authorization: ExactEvmPayloadV2[\"authorization\"],\n    requirements: PaymentRequirements,\n    chainId: number,\n  ): Promise<`0x${string}`> {\n    // Extract EIP-712 domain parameters from extra\n    if (!requirements.extra?.name || !requirements.extra?.version) {\n      throw new Error(\n        `EIP-712 domain parameters (name, version) are required in payment requirements for asset ${requirements.asset}`,\n      );\n    }\n\n    const { name, version } = requirements.extra;\n\n    const domain = {\n      name,\n      version,\n      chainId,\n      verifyingContract: getAddress(requirements.asset),\n    };\n\n    const message = {\n      from: getAddress(authorization.from),\n      to: getAddress(authorization.to),\n      value: BigInt(authorization.value),\n      validAfter: BigInt(authorization.validAfter),\n      validBefore: BigInt(authorization.validBefore),\n      nonce: authorization.nonce,\n    };\n\n    return await this.signer.signTypedData({\n      domain,\n      types: authorizationTypes,\n      primaryType: \"TransferWithAuthorization\",\n      message,\n    });\n  }\n}\n","/**\n * x402x Extension Handler\n *\n * Provides utilities to integrate x402x router settlement with official x402 SDK.\n *\n * The challenge: x402 v2 spec places extensions at root level in PaymentRequired,\n * but x402x scheme needs settlement parameters from PaymentRequirements.extra.\n *\n * Solution: Provide two-layer API:\n * 1. High-level: registerX402xScheme() - one line setup (recommended)\n * 2. Low-level: injectX402xExtensionHandler() - flexible configuration\n */\n\nimport { x402Client } from \"@x402/core/client\";\nimport type { Network } from \"@x402/core/types\";\n\nimport { ROUTER_SETTLEMENT_KEY } from \"../server-extension\";\n\nimport { ExactEvmSchemeWithRouterSettlement, type ClientEvmSigner } from \"./exact-evm-scheme\";\n\n/**\n * Injects x402x extension handler into x402Client (Low-level API).\n *\n * IMPORTANT (x402 v2 + x402x multi-network):\n * - Server returns per-option x402x info in `accepts[i].extra[\"x402x-router-settlement\"]`\n * - x402Client only passes `PaymentRequirements` to scheme (no root extensions)\n * - Facilitator v2 reads from `paymentPayload.extensions[\"x402x-router-settlement\"]`\n *\n * Solution: Copy the selected option's x402x info from `selectedRequirements.extra`\n * into `paymentRequired.extensions` so it gets included in `paymentPayload.extensions`.\n *\n * This does NOT mutate `selectedRequirements` (which becomes `paymentPayload.accepted`),\n * so v2 deepEqual matching still works.\n *\n * @param client - x402Client instance to inject handler into\n * @param onRouterSettlementExtension - Callback to receive the per-request extension object\n * @returns The same client instance for chaining\n *\n * @example Low-level API (for advanced users)\n * ```typescript\n * import { x402Client } from '@x402/core/client';\n * import {\n *   injectX402xExtensionHandler,\n *   ExactEvmSchemeWithRouterSettlement\n * } from '@x402x/extensions';\n *\n * const client = new x402Client();\n * const scheme = new ExactEvmSchemeWithRouterSettlement(signer);\n * injectX402xExtensionHandler(client, (ext) => scheme.setRouterSettlementExtensionFromPaymentRequired(ext))\n *   .register('eip155:84532', scheme);\n * ```\n */\nexport function injectX402xExtensionHandler(\n  client: x402Client,\n  onRouterSettlementExtension?: (extension: unknown | undefined) => void,\n): x402Client {\n  return client.onBeforePaymentCreation(async (context) => {\n    const { paymentRequired, selectedRequirements } = context;\n\n    // Debug: show what we received\n    console.log(\"[x402x-handler] onBeforePaymentCreation called\");\n    console.log(\"[x402x-handler] selectedRequirements.network:\", selectedRequirements.network);\n    console.log(\n      \"[x402x-handler] selectedRequirements.extra keys:\",\n      Object.keys(selectedRequirements.extra || {}),\n    );\n\n    // Key insight: Per-option x402x info is in selectedRequirements.extra[x402x-router-settlement].\n    // We need to copy it into paymentRequired.extensions[x402x-router-settlement] so that:\n    // 1. x402Client copies it into paymentPayload.extensions (v2 standard)\n    // 2. Facilitator v2 can read it from paymentPayload.extensions\n    // 3. We DON'T mutate selectedRequirements (which becomes paymentPayload.accepted)\n\n    const perOptionExtension = selectedRequirements.extra?.[ROUTER_SETTLEMENT_KEY];\n\n    if (perOptionExtension) {\n      // Initialize extensions object if it doesn't exist\n      if (!paymentRequired.extensions) {\n        (paymentRequired as any).extensions = {};\n      }\n\n      // Copy the per-option x402x info into root extensions\n      // This will be copied into paymentPayload.extensions by x402Client\n      (paymentRequired.extensions as any)[ROUTER_SETTLEMENT_KEY] = perOptionExtension;\n\n      console.log(\n        \"[x402x-handler] ✅ Copied per-option x402x info into PaymentRequired.extensions\",\n      );\n      console.log(\"[x402x-handler] Extension info:\", JSON.stringify(perOptionExtension, null, 2));\n    } else {\n      // Fallback: if no per-option info, use root-level extension (legacy behavior)\n      console.warn(\n        \"[x402x-handler] ⚠️ No per-option x402x info found in selectedRequirements.extra\",\n      );\n      console.warn(\n        \"[x402x-handler] This may cause facilitator errors. Check server-side createSettlementRouteConfig.\",\n      );\n    }\n\n    // Forward extension to callback (for schemes that need direct access)\n    if (onRouterSettlementExtension) {\n      const extensionToUse =\n        perOptionExtension || paymentRequired.extensions?.[ROUTER_SETTLEMENT_KEY];\n      onRouterSettlementExtension(extensionToUse);\n    }\n  });\n}\n\n/**\n * Register x402x router settlement scheme with automatic extension handling (High-level API).\n *\n * This is the recommended way to set up x402x payments. It combines:\n * 1. Extension handler injection (injectX402xExtensionHandler)\n * 2. Scheme registration (ExactEvmSchemeWithRouterSettlement)\n *\n * Use this for the simplest integration - just provide your signer and network.\n *\n * @param client - x402Client instance\n * @param network - Network identifier in CAIP-2 format (e.g., \"eip155:84532\")\n * @param signer - EVM signer with address and signTypedData method\n * @returns The client instance for chaining\n *\n * @example High-level API (recommended)\n * ```typescript\n * import { x402Client } from '@x402/core/client';\n * import { registerX402xScheme } from '@x402x/extensions';\n * import { useWalletClient } from 'wagmi';\n *\n * const { data: walletClient } = useWalletClient();\n *\n * const client = new x402Client();\n * registerX402xScheme(client, 'eip155:84532', {\n *   address: walletClient.account.address,\n *   signTypedData: walletClient.signTypedData,\n * });\n *\n * // That's it! Client is ready for x402x payments\n * ```\n *\n * @example Multiple networks\n * ```typescript\n * const client = new x402Client();\n * registerX402xScheme(client, 'eip155:84532', signer); // Base Sepolia\n * registerX402xScheme(client, 'eip155:8453', signer);  // Base Mainnet\n * ```\n */\nexport function registerX402xScheme(\n  client: x402Client,\n  network: Network,\n  signer: ClientEvmSigner,\n): x402Client {\n  const scheme = new ExactEvmSchemeWithRouterSettlement(signer);\n\n  // Inject extension handler: capture root-level extension data (incl. dynamic salt)\n  // and pass it into the scheme instance without mutating `accepted`.\n  injectX402xExtensionHandler(client, (ext) => {\n    // Scope to this specific network to avoid cross-network leakage if user registers multiple.\n    // (We don't have direct access to `selectedRequirements` here without mutating accepted,\n    // so we keep it simple: this scheme instance is per-network registration.)\n    scheme.setRouterSettlementExtensionFromPaymentRequired(ext);\n  });\n\n  // Register the x402x scheme for this network\n  client.register(network, scheme);\n\n  return client;\n}\n"]}