{"version":3,"file":"client-C_HEuq0f.mjs","names":[],"sources":["../src/mcp/client.ts"],"sourcesContent":["import { wrapFetchWithPaymentFromConfig } from '@x402/fetch'\nimport { ExactEvmScheme } from '@x402/evm'\nimport { UptoEvmScheme } from '@x402/evm/upto/client'\nimport { privateKeyToAccount } from 'viem/accounts'\nimport type { InvestigatorConfig } from '../config/schema.js'\nimport { prepareWalletForPaidCalls, resolveMaxAutoApprovalUnits } from '../wallet/tools.js'\n\ntype FetchLike = typeof fetch\ntype FetchInput = Parameters<FetchLike>[0]\ntype FetchInit = Parameters<FetchLike>[1]\n\nexport class PaymentRequiredError extends Error {\n  constructor(message: string) {\n    super(message)\n    this.name = 'PaymentRequiredError'\n  }\n}\n\nexport function applyMcpAuthHeaders(headers: Headers, authToken: string): Headers {\n  headers.set('X-MCP-Debug-Token', authToken)\n  headers.set('X-MCP-Test-Key', authToken)\n  headers.set('X-Chain-Insights-Test-Key', authToken)\n  headers.set('Authorization', `Bearer ${authToken}`)\n  return headers\n}\n\nfunction createHeaderFetch(authToken: string, baseFetch: FetchLike): FetchLike {\n  return (async (input: FetchInput, init?: FetchInit) => {\n    const requestHeaders = input instanceof Request ? input.headers : undefined\n    const headers = new Headers(init?.headers ?? requestHeaders)\n    applyMcpAuthHeaders(headers, authToken)\n\n    return baseFetch(input, {\n      ...init,\n      headers,\n    })\n  }) as FetchLike\n}\n\nexport const PAYMENT_NEXT_STEPS =\n  'Next steps: run `chain-insights wallet ready` to check funding and finish one-time payment setup, ' +\n  'run `chain-insights wallet topup` if it says the wallet needs USDC, ' +\n  'or `chain-insights access-key set <key>` if you have been given test access.'\n\ninterface PaymentRequirementDetails {\n  reason: string\n  scheme?: string\n  network?: string\n  amount?: string\n  amountUnits?: bigint\n  payTo?: string\n}\n\nfunction paymentRequirementFromResponse(response: Response): PaymentRequirementDetails | null {\n  const encoded = response.headers.get('payment-required')\n  if (!encoded) return null\n\n  try {\n    const decoded = Buffer.from(encoded, 'base64').toString('utf8')\n    const parsed = JSON.parse(decoded) as {\n      error?: unknown\n      accepts?: Array<{ scheme?: unknown; network?: unknown; amount?: unknown; payTo?: unknown }>\n    }\n    const reason = typeof parsed.error === 'string' && parsed.error.trim() ? parsed.error.trim() : 'payment_required'\n    const firstRequirement = Array.isArray(parsed.accepts) ? parsed.accepts[0] : undefined\n    const amount = typeof firstRequirement?.amount === 'string' ? firstRequirement.amount.trim() : undefined\n    return {\n      reason,\n      scheme: typeof firstRequirement?.scheme === 'string' ? firstRequirement.scheme : undefined,\n      network: typeof firstRequirement?.network === 'string' ? firstRequirement.network : undefined,\n      amount,\n      amountUnits: amount && /^\\d+$/.test(amount) ? BigInt(amount) : undefined,\n      payTo: typeof firstRequirement?.payTo === 'string' ? firstRequirement.payTo.trim() : undefined,\n    }\n  } catch {\n    return null\n  }\n}\n\nfunction describePaymentRequiredResponse(response: Response, payerAddress?: string): string {\n  const requirement = paymentRequirementFromResponse(response)\n  if (!requirement) return `Payment required — this tool costs USDC on Base via x402 micropayments. ${PAYMENT_NEXT_STEPS}`\n\n  try {\n    const { reason, payTo } = requirement\n    if (payerAddress && payTo && payerAddress.toLowerCase() === payTo.toLowerCase()) {\n      return 'Local payment wallet matches the MCP payTo address. Configure a separate payer wallet with USDC on Base; do not use the service recipient wallet as the client payment wallet.'\n    }\n    const details = [\n      requirement.scheme ? `scheme=${requirement.scheme}` : undefined,\n      requirement.network ? `network=${requirement.network}` : undefined,\n      requirement.amount ? `amount=${requirement.amount}` : undefined,\n    ].filter(Boolean).join(' ')\n    const message = details ? `x402 payment failed: ${reason} (${details})` : `x402 payment failed: ${reason}`\n    if (reason.includes('allowance_required')) {\n      return `${message}. The payment wallet needs one-time setup before paid MCP calls can settle. Run \\`chain-insights wallet ready\\`; Base ETH is used for the setup gas.`\n    }\n    if (reason === 'payment_required') {\n      return `${message}. ${PAYMENT_NEXT_STEPS}`\n    }\n    return `${message}. ${PAYMENT_NEXT_STEPS}`\n  } catch {\n    return `Payment required — this tool costs USDC on Base via x402 micropayments. ${PAYMENT_NEXT_STEPS}`\n  }\n}\n\nfunction createPaymentFailureReportingFetch(\n  baseFetch: FetchLike,\n  payerAddress?: string,\n  paymentWallet?: { address: `0x${string}`; privateKey: `0x${string}` },\n): FetchLike {\n  const reportingFetch = (async (input: FetchInput, init?: FetchInit) => {\n    const response = await baseFetch(input, init)\n    if (response.status !== 402) return response\n    const requirement = paymentRequirementFromResponse(response)\n    if (paymentWallet && requirement?.reason.includes('allowance_required')) {\n      try {\n        await prepareWalletForPaidCalls({\n          account: paymentWallet,\n          // The endpoint dictates requirement.amountUnits; cap it so a hostile\n          // endpoint cannot drive an unbounded Permit2 approval / wallet drain.\n          maxApprovalUnits: resolveMaxAutoApprovalUnits(),\n          ...(requirement.amountUnits === undefined ? {} : { minimumApprovalUnits: requirement.amountUnits }),\n        })\n      } catch (err) {\n        throw new PaymentRequiredError(\n          'Payment setup is not ready yet. Run `chain-insights wallet ready` and try again. ' +\n          `${(err as Error).message}`,\n        )\n      }\n      const retryResponse = await baseFetch(input, init)\n      if (retryResponse.status !== 402) return retryResponse\n      throw new PaymentRequiredError(describePaymentRequiredResponse(retryResponse, payerAddress))\n    }\n    throw new PaymentRequiredError(describePaymentRequiredResponse(response, payerAddress))\n  }) as FetchLike\n  return Object.assign(reportingFetch, baseFetch)\n}\n\n/**\n * Creates an x402-payment-wrapped fetch function for the Chain Insights MCP.\n * Payments are made in USDC on Base Mainnet (eip155:8453).\n *\n * The factory is pure — no side effects, no state, no caching.\n * If called with an invalid private key format, viem throws — the error propagates.\n *\n * @param privateKey - 0x-prefixed EVM private key (decrypted from wallet.json)\n * @returns A fetch-compatible function that auto-handles HTTP 402 payment challenges\n */\nexport function createMcpFetchClient(privateKey: `0x${string}`, authToken?: string) {\n  const account = privateKeyToAccount(privateKey)\n  const paymentFetch = wrapFetchWithPaymentFromConfig(fetch, {\n    schemes: [\n      {\n        network: 'eip155:8453', // Base Mainnet — dynamic MCP pricing uses the x402 upto scheme\n        client: new UptoEvmScheme(account),\n      },\n      {\n        network: 'eip155:8453', // Base Mainnet — only supported chain in v1\n        client: new ExactEvmScheme(account),\n      },\n    ],\n  })\n  const reportingFetch = createPaymentFailureReportingFetch(\n    paymentFetch,\n    account.address,\n    { address: account.address, privateKey },\n  )\n  return authToken ? createHeaderFetch(authToken, reportingFetch) : reportingFetch\n}\n\n/**\n * Creates a bearer/debug-token fetch for local Chain Insights Graph testing.\n *\n * Chain Insights Graph deployments accept test access through the public debug header,\n * staging test-key headers, or Authorization: Bearer depending on the route.\n * Sending all supported auth headers lets one config value work across hosted\n * MCP calls, metadata reads, and private M2M endpoints.\n *\n * Wraps with 402 interception so that if the server still requires payment\n * (e.g. token not accepted for paid tools), the user sees actionable guidance\n * instead of a generic transport error.\n */\nexport function createMcpAuthFetchClient(authToken: string, baseFetch: FetchLike = fetch): FetchLike {\n  const headerFetch = createHeaderFetch(authToken, baseFetch)\n  return createPaymentFailureReportingFetch(headerFetch)\n}\n\nexport function resolveGraphMcpEndpoint(config: Pick<InvestigatorConfig, 'graphMcpEndpoint'>): string {\n  return config.graphMcpEndpoint.trim()\n}\n\nasync function createConfiguredGraphPaidOrFreeFetch(): Promise<FetchLike> {\n  const { isWalletConfigured, decryptKey } = await import('../wallet/index.js')\n  if (!(await isWalletConfigured())) {\n    return createPaymentFailureReportingFetch(fetch)\n  }\n\n  const privateKey = await decryptKey()\n  return createMcpFetchClient(privateKey as `0x${string}`)\n}\n\nexport async function createConfiguredGraphMcpFetch(\n  config: Pick<InvestigatorConfig, 'graphMcpAuthToken' | 'graphMcpMode'>,\n): Promise<FetchLike> {\n  if (config.graphMcpMode === 'debug') {\n    const authToken = config.graphMcpAuthToken?.trim()\n    if (!authToken) {\n      throw new Error('Chain Insights Graph debug mode requires graphMcpAuthToken. Run `cia access-key set <key>` or `cia debug on --token <token>`.')\n    }\n    return createMcpAuthFetchClient(authToken)\n  }\n\n  return createConfiguredGraphPaidOrFreeFetch()\n}\n"],"mappings":"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"}