@x402/fetch
Advanced tools
| import { x402Client, x402HTTPClient, x402ClientConfig } from '@x402/core/client'; | ||
| export { PaymentPolicy, SchemeRegistration, SelectPaymentRequirements, x402Client, x402ClientConfig, x402HTTPClient, x402PaymentResult } from '@x402/core/client'; | ||
| export { HTTPResourceResponse, PaymentPolicy, SchemeRegistration, SelectPaymentRequirements, x402Client, x402ClientConfig, x402HTTPClient } from '@x402/core/client'; | ||
| export { decodePaymentResponseHeader } from '@x402/core/http'; | ||
@@ -4,0 +4,0 @@ export { Network, PaymentPayload, PaymentRequired, PaymentRequirements, SchemeNetworkClient } from '@x402/core/types'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import { x402Client, x402ClientConfig, x402HTTPClient } from \"@x402/core/client\";\nimport { type PaymentRequired } from \"@x402/core/types\";\n\n/**\n * Enables the payment of APIs using the x402 payment protocol v2.\n *\n * This function wraps the native fetch API to automatically handle 402 Payment Required responses\n * by creating and sending payment headers. It will:\n * 1. Make the initial request\n * 2. If a 402 response is received, parse the payment requirements\n * 3. Create a payment header using the configured x402HTTPClient\n * 4. Retry the request with the payment header\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param client - Configured x402Client or x402HTTPClient instance for handling payments\n * @returns A wrapped fetch function that handles 402 responses automatically\n *\n * @example\n * ```typescript\n * import { wrapFetchWithPayment, x402Client } from '@x402/fetch';\n * import { ExactEvmScheme } from '@x402/evm';\n * import { ExactSvmScheme } from '@x402/svm';\n *\n * const client = new x402Client()\n * .register('eip155:8453', new ExactEvmScheme(evmSigner))\n * .register('solana:mainnet', new ExactSvmScheme(svmSigner))\n * .register('eip155:1', new ExactEvmScheme(evmSigner), 1); // v1 protocol\n *\n * const fetchWithPay = wrapFetchWithPayment(fetch, client);\n *\n * // Make a request that may require payment\n * const response = await fetchWithPay('https://api.example.com/paid-endpoint');\n * ```\n *\n * @throws {Error} If no schemes are provided\n * @throws {Error} If the request configuration is missing\n * @throws {Error} If a payment has already been attempted for this request\n * @throws {Error} If there's an error creating the payment header\n */\nexport function wrapFetchWithPayment(\n fetch: typeof globalThis.fetch,\n client: x402Client | x402HTTPClient,\n) {\n const httpClient = client instanceof x402HTTPClient ? client : new x402HTTPClient(client);\n\n return async (input: RequestInfo | URL, init?: RequestInit) => {\n const request = new Request(input, init);\n const clonedRequest = request.clone();\n\n const response = await fetch(request);\n\n if (response.status !== 402) {\n return response;\n }\n\n // Parse payment requirements from response\n let paymentRequired: PaymentRequired;\n try {\n // Create getHeader function for case-insensitive header lookup\n const getHeader = (name: string) => response.headers.get(name);\n\n // Try to get from headers first (v2), then from body (v1)\n let body: PaymentRequired | undefined;\n try {\n const responseText = await response.text();\n if (responseText) {\n body = JSON.parse(responseText) as PaymentRequired;\n }\n } catch {\n // Ignore JSON parse errors - might be header-only response\n }\n\n paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);\n } catch (error) {\n throw new Error(\n `Failed to parse payment requirements: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Run payment required hooks\n const hookHeaders = await httpClient.handlePaymentRequired(paymentRequired);\n if (hookHeaders) {\n const hookRequest = clonedRequest.clone();\n for (const [key, value] of Object.entries(hookHeaders)) {\n hookRequest.headers.set(key, value);\n }\n const hookResponse = await fetch(hookRequest);\n if (hookResponse.status !== 402) {\n return hookResponse; // Hook succeeded\n }\n // Hook's retry got 402, fall through to payment\n }\n\n // Create payment payload (copy extensions from PaymentRequired)\n let paymentPayload;\n try {\n paymentPayload = await client.createPaymentPayload(paymentRequired);\n } catch (error) {\n throw new Error(\n `Failed to create payment payload: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Encode payment header\n const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload);\n\n // Check if this is already a retry to prevent infinite loops\n if (clonedRequest.headers.has(\"PAYMENT-SIGNATURE\") || clonedRequest.headers.has(\"X-PAYMENT\")) {\n throw new Error(\"Payment already attempted\");\n }\n\n // Add payment headers to cloned request\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n clonedRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n\n // Retry the request with payment\n const secondResponse = await fetch(clonedRequest);\n\n // Fire payment response hooks and handle recovery\n const result = await httpClient.processPaymentResult(\n paymentPayload,\n name => secondResponse.headers.get(name),\n secondResponse.status,\n );\n\n if (result.recovered) {\n // Hook fixed state — retry with fresh payload (bounded to one recovery)\n const freshPayload = await client.createPaymentPayload(paymentRequired);\n const retryHeaders = httpClient.encodePaymentSignatureHeader(freshPayload);\n const retryRequest = new Request(input, init);\n for (const [k, v] of Object.entries(retryHeaders)) {\n retryRequest.headers.set(k, v);\n }\n retryRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n const retryResponse = await fetch(retryRequest);\n // Fire hooks on retry response — no further recovery to prevent loops\n await httpClient.processPaymentResult(\n freshPayload,\n name => retryResponse.headers.get(name),\n retryResponse.status,\n );\n return retryResponse;\n }\n\n return secondResponse;\n };\n}\n\n/**\n * Creates a payment-enabled fetch function from a configuration object.\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param config - Configuration options including scheme registrations and selectors\n * @returns A wrapped fetch function that handles 402 responses automatically\n */\nexport function wrapFetchWithPaymentFromConfig(\n fetch: typeof globalThis.fetch,\n config: x402ClientConfig,\n) {\n const client = x402Client.fromConfig(config);\n return wrapFetchWithPayment(fetch, client);\n}\n\n// Re-export types and utilities for convenience\nexport { x402Client, x402HTTPClient } from \"@x402/core/client\";\nexport type { x402PaymentResult } from \"@x402/core/client\";\nexport type {\n PaymentPolicy,\n SchemeRegistration,\n SelectPaymentRequirements,\n x402ClientConfig,\n} from \"@x402/core/client\";\nexport { decodePaymentResponseHeader } from \"@x402/core/http\";\nexport type {\n Network,\n PaymentPayload,\n PaymentRequired,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\n"],"mappings":"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","names":["import_client"]} | ||
| {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import { x402Client, x402ClientConfig, x402HTTPClient } from \"@x402/core/client\";\nimport { type PaymentRequired } from \"@x402/core/types\";\n\n/**\n * Enables the payment of APIs using the x402 payment protocol v2.\n *\n * This function wraps the native fetch API to automatically handle 402 Payment Required responses\n * by creating and sending payment headers. It will:\n * 1. Make the initial request\n * 2. If a 402 response is received, parse the payment requirements\n * 3. Create a payment header using the configured x402HTTPClient\n * 4. Retry the request with the payment header\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param client - Configured x402Client or x402HTTPClient instance for handling payments\n * @returns A wrapped fetch function that handles 402 responses automatically\n *\n * @example\n * ```typescript\n * import { wrapFetchWithPayment, x402Client } from '@x402/fetch';\n * import { ExactEvmScheme } from '@x402/evm';\n * import { ExactSvmScheme } from '@x402/svm';\n *\n * const client = new x402Client()\n * .register('eip155:8453', new ExactEvmScheme(evmSigner))\n * .register('solana:mainnet', new ExactSvmScheme(svmSigner))\n * .register('eip155:1', new ExactEvmScheme(evmSigner), 1); // v1 protocol\n *\n * const fetchWithPay = wrapFetchWithPayment(fetch, client);\n *\n * // Make a request that may require payment\n * const response = await fetchWithPay('https://api.example.com/paid-endpoint');\n * ```\n *\n * @throws {Error} If no schemes are provided\n * @throws {Error} If the request configuration is missing\n * @throws {Error} If a payment has already been attempted for this request\n * @throws {Error} If there's an error creating the payment header\n */\nexport function wrapFetchWithPayment(\n fetch: typeof globalThis.fetch,\n client: x402Client | x402HTTPClient,\n) {\n const httpClient = client instanceof x402HTTPClient ? client : new x402HTTPClient(client);\n\n return async (input: RequestInfo | URL, init?: RequestInit) => {\n const request = new Request(input, init);\n const clonedRequest = request.clone();\n\n const response = await fetch(request);\n\n if (response.status !== 402) {\n return response;\n }\n\n // Parse payment requirements from response\n let paymentRequired: PaymentRequired;\n try {\n // Create getHeader function for case-insensitive header lookup\n const getHeader = (name: string) => response.headers.get(name);\n\n // Try to get from headers first (v2), then from body (v1)\n let body: PaymentRequired | undefined;\n try {\n const responseText = await response.text();\n if (responseText) {\n body = JSON.parse(responseText) as PaymentRequired;\n }\n } catch {\n // Ignore JSON parse errors - might be header-only response\n }\n\n paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);\n } catch (error) {\n throw new Error(\n `Failed to parse payment requirements: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Run payment required hooks\n const hookHeaders = await httpClient.handlePaymentRequired(paymentRequired);\n if (hookHeaders) {\n const hookRequest = clonedRequest.clone();\n for (const [key, value] of Object.entries(hookHeaders)) {\n hookRequest.headers.set(key, value);\n }\n const hookResponse = await fetch(hookRequest);\n if (hookResponse.status !== 402) {\n return hookResponse; // Hook succeeded\n }\n // Hook's retry got 402, fall through to payment\n }\n\n // Create payment payload (copy extensions from PaymentRequired)\n let paymentPayload;\n try {\n paymentPayload = await client.createPaymentPayload(paymentRequired);\n } catch (error) {\n throw new Error(\n `Failed to create payment payload: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Encode payment header\n const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload);\n\n // Check if this is already a retry to prevent infinite loops\n if (clonedRequest.headers.has(\"PAYMENT-SIGNATURE\") || clonedRequest.headers.has(\"X-PAYMENT\")) {\n throw new Error(\"Payment already attempted\");\n }\n\n // Add payment headers to cloned request\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n clonedRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n\n // Retry the request with payment\n const secondResponse = await fetch(clonedRequest);\n\n // Fire payment response hooks and handle recovery\n const result = await httpClient.processPaymentResult(\n paymentPayload,\n name => secondResponse.headers.get(name),\n secondResponse.status,\n );\n\n if (result.recovered) {\n // Hook fixed state — retry with fresh payload (bounded to one recovery)\n const freshPayload = await client.createPaymentPayload(paymentRequired);\n const retryHeaders = httpClient.encodePaymentSignatureHeader(freshPayload);\n const retryRequest = new Request(input, init);\n for (const [k, v] of Object.entries(retryHeaders)) {\n retryRequest.headers.set(k, v);\n }\n retryRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n const retryResponse = await fetch(retryRequest);\n // Fire hooks on retry response — no further recovery to prevent loops\n await httpClient.processPaymentResult(\n freshPayload,\n name => retryResponse.headers.get(name),\n retryResponse.status,\n );\n return retryResponse;\n }\n\n return secondResponse;\n };\n}\n\n/**\n * Creates a payment-enabled fetch function from a configuration object.\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param config - Configuration options including scheme registrations and selectors\n * @returns A wrapped fetch function that handles 402 responses automatically\n */\nexport function wrapFetchWithPaymentFromConfig(\n fetch: typeof globalThis.fetch,\n config: x402ClientConfig,\n) {\n const client = x402Client.fromConfig(config);\n return wrapFetchWithPayment(fetch, client);\n}\n\n// Re-export types and utilities for convenience\nexport { x402Client, x402HTTPClient } from \"@x402/core/client\";\nexport type { HTTPResourceResponse } from \"@x402/core/client\";\nexport type {\n PaymentPolicy,\n SchemeRegistration,\n SelectPaymentRequirements,\n x402ClientConfig,\n} from \"@x402/core/client\";\nexport { decodePaymentResponseHeader } from \"@x402/core/http\";\nexport type {\n Network,\n PaymentPayload,\n PaymentRequired,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\n"],"mappings":"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","names":["import_client"]} |
| import { x402Client, x402HTTPClient, x402ClientConfig } from '@x402/core/client'; | ||
| export { PaymentPolicy, SchemeRegistration, SelectPaymentRequirements, x402Client, x402ClientConfig, x402HTTPClient, x402PaymentResult } from '@x402/core/client'; | ||
| export { HTTPResourceResponse, PaymentPolicy, SchemeRegistration, SelectPaymentRequirements, x402Client, x402ClientConfig, x402HTTPClient } from '@x402/core/client'; | ||
| export { decodePaymentResponseHeader } from '@x402/core/http'; | ||
@@ -4,0 +4,0 @@ export { Network, PaymentPayload, PaymentRequired, PaymentRequirements, SchemeNetworkClient } from '@x402/core/types'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import { x402Client, x402ClientConfig, x402HTTPClient } from \"@x402/core/client\";\nimport { type PaymentRequired } from \"@x402/core/types\";\n\n/**\n * Enables the payment of APIs using the x402 payment protocol v2.\n *\n * This function wraps the native fetch API to automatically handle 402 Payment Required responses\n * by creating and sending payment headers. It will:\n * 1. Make the initial request\n * 2. If a 402 response is received, parse the payment requirements\n * 3. Create a payment header using the configured x402HTTPClient\n * 4. Retry the request with the payment header\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param client - Configured x402Client or x402HTTPClient instance for handling payments\n * @returns A wrapped fetch function that handles 402 responses automatically\n *\n * @example\n * ```typescript\n * import { wrapFetchWithPayment, x402Client } from '@x402/fetch';\n * import { ExactEvmScheme } from '@x402/evm';\n * import { ExactSvmScheme } from '@x402/svm';\n *\n * const client = new x402Client()\n * .register('eip155:8453', new ExactEvmScheme(evmSigner))\n * .register('solana:mainnet', new ExactSvmScheme(svmSigner))\n * .register('eip155:1', new ExactEvmScheme(evmSigner), 1); // v1 protocol\n *\n * const fetchWithPay = wrapFetchWithPayment(fetch, client);\n *\n * // Make a request that may require payment\n * const response = await fetchWithPay('https://api.example.com/paid-endpoint');\n * ```\n *\n * @throws {Error} If no schemes are provided\n * @throws {Error} If the request configuration is missing\n * @throws {Error} If a payment has already been attempted for this request\n * @throws {Error} If there's an error creating the payment header\n */\nexport function wrapFetchWithPayment(\n fetch: typeof globalThis.fetch,\n client: x402Client | x402HTTPClient,\n) {\n const httpClient = client instanceof x402HTTPClient ? client : new x402HTTPClient(client);\n\n return async (input: RequestInfo | URL, init?: RequestInit) => {\n const request = new Request(input, init);\n const clonedRequest = request.clone();\n\n const response = await fetch(request);\n\n if (response.status !== 402) {\n return response;\n }\n\n // Parse payment requirements from response\n let paymentRequired: PaymentRequired;\n try {\n // Create getHeader function for case-insensitive header lookup\n const getHeader = (name: string) => response.headers.get(name);\n\n // Try to get from headers first (v2), then from body (v1)\n let body: PaymentRequired | undefined;\n try {\n const responseText = await response.text();\n if (responseText) {\n body = JSON.parse(responseText) as PaymentRequired;\n }\n } catch {\n // Ignore JSON parse errors - might be header-only response\n }\n\n paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);\n } catch (error) {\n throw new Error(\n `Failed to parse payment requirements: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Run payment required hooks\n const hookHeaders = await httpClient.handlePaymentRequired(paymentRequired);\n if (hookHeaders) {\n const hookRequest = clonedRequest.clone();\n for (const [key, value] of Object.entries(hookHeaders)) {\n hookRequest.headers.set(key, value);\n }\n const hookResponse = await fetch(hookRequest);\n if (hookResponse.status !== 402) {\n return hookResponse; // Hook succeeded\n }\n // Hook's retry got 402, fall through to payment\n }\n\n // Create payment payload (copy extensions from PaymentRequired)\n let paymentPayload;\n try {\n paymentPayload = await client.createPaymentPayload(paymentRequired);\n } catch (error) {\n throw new Error(\n `Failed to create payment payload: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Encode payment header\n const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload);\n\n // Check if this is already a retry to prevent infinite loops\n if (clonedRequest.headers.has(\"PAYMENT-SIGNATURE\") || clonedRequest.headers.has(\"X-PAYMENT\")) {\n throw new Error(\"Payment already attempted\");\n }\n\n // Add payment headers to cloned request\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n clonedRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n\n // Retry the request with payment\n const secondResponse = await fetch(clonedRequest);\n\n // Fire payment response hooks and handle recovery\n const result = await httpClient.processPaymentResult(\n paymentPayload,\n name => secondResponse.headers.get(name),\n secondResponse.status,\n );\n\n if (result.recovered) {\n // Hook fixed state — retry with fresh payload (bounded to one recovery)\n const freshPayload = await client.createPaymentPayload(paymentRequired);\n const retryHeaders = httpClient.encodePaymentSignatureHeader(freshPayload);\n const retryRequest = new Request(input, init);\n for (const [k, v] of Object.entries(retryHeaders)) {\n retryRequest.headers.set(k, v);\n }\n retryRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n const retryResponse = await fetch(retryRequest);\n // Fire hooks on retry response — no further recovery to prevent loops\n await httpClient.processPaymentResult(\n freshPayload,\n name => retryResponse.headers.get(name),\n retryResponse.status,\n );\n return retryResponse;\n }\n\n return secondResponse;\n };\n}\n\n/**\n * Creates a payment-enabled fetch function from a configuration object.\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param config - Configuration options including scheme registrations and selectors\n * @returns A wrapped fetch function that handles 402 responses automatically\n */\nexport function wrapFetchWithPaymentFromConfig(\n fetch: typeof globalThis.fetch,\n config: x402ClientConfig,\n) {\n const client = x402Client.fromConfig(config);\n return wrapFetchWithPayment(fetch, client);\n}\n\n// Re-export types and utilities for convenience\nexport { x402Client, x402HTTPClient } from \"@x402/core/client\";\nexport type { x402PaymentResult } from \"@x402/core/client\";\nexport type {\n PaymentPolicy,\n SchemeRegistration,\n SelectPaymentRequirements,\n x402ClientConfig,\n} from \"@x402/core/client\";\nexport { decodePaymentResponseHeader } from \"@x402/core/http\";\nexport type {\n Network,\n PaymentPayload,\n PaymentRequired,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\n"],"mappings":"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","names":["x402Client","x402HTTPClient"]} | ||
| {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["import { x402Client, x402ClientConfig, x402HTTPClient } from \"@x402/core/client\";\nimport { type PaymentRequired } from \"@x402/core/types\";\n\n/**\n * Enables the payment of APIs using the x402 payment protocol v2.\n *\n * This function wraps the native fetch API to automatically handle 402 Payment Required responses\n * by creating and sending payment headers. It will:\n * 1. Make the initial request\n * 2. If a 402 response is received, parse the payment requirements\n * 3. Create a payment header using the configured x402HTTPClient\n * 4. Retry the request with the payment header\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param client - Configured x402Client or x402HTTPClient instance for handling payments\n * @returns A wrapped fetch function that handles 402 responses automatically\n *\n * @example\n * ```typescript\n * import { wrapFetchWithPayment, x402Client } from '@x402/fetch';\n * import { ExactEvmScheme } from '@x402/evm';\n * import { ExactSvmScheme } from '@x402/svm';\n *\n * const client = new x402Client()\n * .register('eip155:8453', new ExactEvmScheme(evmSigner))\n * .register('solana:mainnet', new ExactSvmScheme(svmSigner))\n * .register('eip155:1', new ExactEvmScheme(evmSigner), 1); // v1 protocol\n *\n * const fetchWithPay = wrapFetchWithPayment(fetch, client);\n *\n * // Make a request that may require payment\n * const response = await fetchWithPay('https://api.example.com/paid-endpoint');\n * ```\n *\n * @throws {Error} If no schemes are provided\n * @throws {Error} If the request configuration is missing\n * @throws {Error} If a payment has already been attempted for this request\n * @throws {Error} If there's an error creating the payment header\n */\nexport function wrapFetchWithPayment(\n fetch: typeof globalThis.fetch,\n client: x402Client | x402HTTPClient,\n) {\n const httpClient = client instanceof x402HTTPClient ? client : new x402HTTPClient(client);\n\n return async (input: RequestInfo | URL, init?: RequestInit) => {\n const request = new Request(input, init);\n const clonedRequest = request.clone();\n\n const response = await fetch(request);\n\n if (response.status !== 402) {\n return response;\n }\n\n // Parse payment requirements from response\n let paymentRequired: PaymentRequired;\n try {\n // Create getHeader function for case-insensitive header lookup\n const getHeader = (name: string) => response.headers.get(name);\n\n // Try to get from headers first (v2), then from body (v1)\n let body: PaymentRequired | undefined;\n try {\n const responseText = await response.text();\n if (responseText) {\n body = JSON.parse(responseText) as PaymentRequired;\n }\n } catch {\n // Ignore JSON parse errors - might be header-only response\n }\n\n paymentRequired = httpClient.getPaymentRequiredResponse(getHeader, body);\n } catch (error) {\n throw new Error(\n `Failed to parse payment requirements: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Run payment required hooks\n const hookHeaders = await httpClient.handlePaymentRequired(paymentRequired);\n if (hookHeaders) {\n const hookRequest = clonedRequest.clone();\n for (const [key, value] of Object.entries(hookHeaders)) {\n hookRequest.headers.set(key, value);\n }\n const hookResponse = await fetch(hookRequest);\n if (hookResponse.status !== 402) {\n return hookResponse; // Hook succeeded\n }\n // Hook's retry got 402, fall through to payment\n }\n\n // Create payment payload (copy extensions from PaymentRequired)\n let paymentPayload;\n try {\n paymentPayload = await client.createPaymentPayload(paymentRequired);\n } catch (error) {\n throw new Error(\n `Failed to create payment payload: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n\n // Encode payment header\n const paymentHeaders = httpClient.encodePaymentSignatureHeader(paymentPayload);\n\n // Check if this is already a retry to prevent infinite loops\n if (clonedRequest.headers.has(\"PAYMENT-SIGNATURE\") || clonedRequest.headers.has(\"X-PAYMENT\")) {\n throw new Error(\"Payment already attempted\");\n }\n\n // Add payment headers to cloned request\n for (const [key, value] of Object.entries(paymentHeaders)) {\n clonedRequest.headers.set(key, value);\n }\n clonedRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n\n // Retry the request with payment\n const secondResponse = await fetch(clonedRequest);\n\n // Fire payment response hooks and handle recovery\n const result = await httpClient.processPaymentResult(\n paymentPayload,\n name => secondResponse.headers.get(name),\n secondResponse.status,\n );\n\n if (result.recovered) {\n // Hook fixed state — retry with fresh payload (bounded to one recovery)\n const freshPayload = await client.createPaymentPayload(paymentRequired);\n const retryHeaders = httpClient.encodePaymentSignatureHeader(freshPayload);\n const retryRequest = new Request(input, init);\n for (const [k, v] of Object.entries(retryHeaders)) {\n retryRequest.headers.set(k, v);\n }\n retryRequest.headers.set(\n \"Access-Control-Expose-Headers\",\n \"PAYMENT-RESPONSE,X-PAYMENT-RESPONSE\",\n );\n const retryResponse = await fetch(retryRequest);\n // Fire hooks on retry response — no further recovery to prevent loops\n await httpClient.processPaymentResult(\n freshPayload,\n name => retryResponse.headers.get(name),\n retryResponse.status,\n );\n return retryResponse;\n }\n\n return secondResponse;\n };\n}\n\n/**\n * Creates a payment-enabled fetch function from a configuration object.\n *\n * @param fetch - The fetch function to wrap (typically globalThis.fetch)\n * @param config - Configuration options including scheme registrations and selectors\n * @returns A wrapped fetch function that handles 402 responses automatically\n */\nexport function wrapFetchWithPaymentFromConfig(\n fetch: typeof globalThis.fetch,\n config: x402ClientConfig,\n) {\n const client = x402Client.fromConfig(config);\n return wrapFetchWithPayment(fetch, client);\n}\n\n// Re-export types and utilities for convenience\nexport { x402Client, x402HTTPClient } from \"@x402/core/client\";\nexport type { HTTPResourceResponse } from \"@x402/core/client\";\nexport type {\n PaymentPolicy,\n SchemeRegistration,\n SelectPaymentRequirements,\n x402ClientConfig,\n} from \"@x402/core/client\";\nexport { decodePaymentResponseHeader } from \"@x402/core/http\";\nexport type {\n Network,\n PaymentPayload,\n PaymentRequired,\n PaymentRequirements,\n SchemeNetworkClient,\n} from \"@x402/core/types\";\n"],"mappings":"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","names":["x402Client","x402HTTPClient"]} |
+2
-2
| { | ||
| "name": "@x402/fetch", | ||
| "version": "2.14.0", | ||
| "version": "2.15.0", | ||
| "main": "./dist/cjs/index.js", | ||
@@ -30,3 +30,3 @@ "module": "./dist/esm/index.js", | ||
| "dependencies": { | ||
| "@x402/core": "~2.14.0" | ||
| "@x402/core": "~2.15.0" | ||
| }, | ||
@@ -33,0 +33,0 @@ "exports": { |
39736
0.03%+ Added
- Removed
Updated