UNPKG

@payai/x402

Version:

PayAI-distributed wrapper for @x402/core v2

911 lines (903 loc) 31.5 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/http/index.ts var http_exports = {}; __export(http_exports, { HTTPFacilitatorClient: () => HTTPFacilitatorClient, RouteConfigurationError: () => RouteConfigurationError, decodePaymentRequiredHeader: () => decodePaymentRequiredHeader, decodePaymentResponseHeader: () => decodePaymentResponseHeader, decodePaymentSignatureHeader: () => decodePaymentSignatureHeader, encodePaymentRequiredHeader: () => encodePaymentRequiredHeader, encodePaymentResponseHeader: () => encodePaymentResponseHeader, encodePaymentSignatureHeader: () => encodePaymentSignatureHeader, x402HTTPClient: () => x402HTTPClient, x402HTTPResourceServer: () => x402HTTPResourceServer }); module.exports = __toCommonJS(http_exports); // src/utils/index.ts var Base64EncodedRegex = /^[A-Za-z0-9+/]*={0,2}$/; function safeBase64Encode(data) { if (typeof globalThis !== "undefined" && typeof globalThis.btoa === "function") { const bytes = new TextEncoder().encode(data); const binaryString = Array.from(bytes, (byte) => String.fromCharCode(byte)).join(""); return globalThis.btoa(binaryString); } return Buffer.from(data, "utf8").toString("base64"); } function safeBase64Decode(data) { if (typeof globalThis !== "undefined" && typeof globalThis.atob === "function") { const binaryString = globalThis.atob(data); const bytes = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { bytes[i] = binaryString.charCodeAt(i); } const decoder = new TextDecoder("utf-8"); return decoder.decode(bytes); } return Buffer.from(data, "base64").toString("utf-8"); } // src/types/facilitator.ts var VerifyError = class extends Error { /** * Creates a VerifyError from a failed verification response. * * @param statusCode - HTTP status code from the facilitator * @param response - The verify response containing error details */ constructor(statusCode, response) { const reason = response.invalidReason || "unknown reason"; const message = response.invalidMessage; super(message ? `${reason}: ${message}` : reason); this.name = "VerifyError"; this.statusCode = statusCode; this.invalidReason = response.invalidReason; this.invalidMessage = response.invalidMessage; this.payer = response.payer; } }; var SettleError = class extends Error { /** * Creates a SettleError from a failed settlement response. * * @param statusCode - HTTP status code from the facilitator * @param response - The settle response containing error details */ constructor(statusCode, response) { const reason = response.errorReason || "unknown reason"; const message = response.errorMessage; super(message ? `${reason}: ${message}` : reason); this.name = "SettleError"; this.statusCode = statusCode; this.errorReason = response.errorReason; this.errorMessage = response.errorMessage; this.payer = response.payer; this.transaction = response.transaction; this.network = response.network; } }; // src/index.ts var x402Version = 2; // src/http/x402HTTPResourceServer.ts var RouteConfigurationError = class extends Error { /** * Creates a new RouteConfigurationError with the given validation errors. * * @param errors - The validation errors that caused this exception. */ constructor(errors) { const message = `x402 Route Configuration Errors: ${errors.map((e) => ` - ${e.message}`).join("\n")}`; super(message); this.name = "RouteConfigurationError"; this.errors = errors; } }; var x402HTTPResourceServer = class { /** * Creates a new x402HTTPResourceServer instance. * * @param ResourceServer - The core x402ResourceServer instance to use * @param routes - Route configuration for payment-protected endpoints */ constructor(ResourceServer, routes) { this.compiledRoutes = []; this.protectedRequestHooks = []; this.ResourceServer = ResourceServer; this.routesConfig = routes; const normalizedRoutes = typeof routes === "object" && !("accepts" in routes) ? routes : { "*": routes }; for (const [pattern, config] of Object.entries(normalizedRoutes)) { const parsed = this.parseRoutePattern(pattern); this.compiledRoutes.push({ verb: parsed.verb, regex: parsed.regex, config }); } } /** * Get the underlying x402ResourceServer instance. * * @returns The underlying x402ResourceServer instance */ get server() { return this.ResourceServer; } /** * Get the routes configuration. * * @returns The routes configuration */ get routes() { return this.routesConfig; } /** * Initialize the HTTP resource server. * * This method initializes the underlying resource server (fetching facilitator support) * and then validates that all route payment configurations have corresponding * registered schemes and facilitator support. * * @throws RouteConfigurationError if any route's payment options don't have * corresponding registered schemes or facilitator support * * @example * ```typescript * const httpServer = new x402HTTPResourceServer(server, routes); * await httpServer.initialize(); * ``` */ async initialize() { await this.ResourceServer.initialize(); const errors = this.validateRouteConfiguration(); if (errors.length > 0) { throw new RouteConfigurationError(errors); } } /** * Register a custom paywall provider for generating HTML * * @param provider - PaywallProvider instance * @returns This service instance for chaining */ registerPaywallProvider(provider) { this.paywallProvider = provider; return this; } /** * Register a hook that runs on every request to a protected route, before payment processing. * Hooks are executed in order of registration. The first hook to return a non-void result wins. * * @param hook - The request hook function * @returns The x402HTTPResourceServer instance for chaining */ onProtectedRequest(hook) { this.protectedRequestHooks.push(hook); return this; } /** * Process HTTP request and return response instructions * This is the main entry point for framework middleware * * @param context - HTTP request context * @param paywallConfig - Optional paywall configuration * @returns Process result indicating next action for middleware */ async processHTTPRequest(context, paywallConfig) { const { adapter, path, method } = context; const routeConfig = this.getRouteConfig(path, method); if (!routeConfig) { return { type: "no-payment-required" }; } for (const hook of this.protectedRequestHooks) { const result = await hook(context, routeConfig); if (result && "grantAccess" in result) { return { type: "no-payment-required" }; } if (result && "abort" in result) { return { type: "payment-error", response: { status: 403, headers: { "Content-Type": "application/json" }, body: { error: result.reason } } }; } } const paymentOptions = this.normalizePaymentOptions(routeConfig); const paymentPayload = this.extractPayment(adapter); const resourceInfo = { url: routeConfig.resource || context.adapter.getUrl(), description: routeConfig.description || "", mimeType: routeConfig.mimeType || "" }; let requirements = await this.ResourceServer.buildPaymentRequirementsFromOptions( paymentOptions, context ); let extensions = routeConfig.extensions; if (extensions) { extensions = this.ResourceServer.enrichExtensions(extensions, context); } const paymentRequired = await this.ResourceServer.createPaymentRequiredResponse( requirements, resourceInfo, !paymentPayload ? "Payment required" : void 0, extensions ); if (!paymentPayload) { const unpaidBody = routeConfig.unpaidResponseBody ? await routeConfig.unpaidResponseBody(context) : void 0; return { type: "payment-error", response: this.createHTTPResponse( paymentRequired, this.isWebBrowser(adapter), paywallConfig, routeConfig.customPaywallHtml, unpaidBody ) }; } try { const matchingRequirements = this.ResourceServer.findMatchingRequirements( paymentRequired.accepts, paymentPayload ); if (!matchingRequirements) { const errorResponse = await this.ResourceServer.createPaymentRequiredResponse( requirements, resourceInfo, "No matching payment requirements", routeConfig.extensions ); return { type: "payment-error", response: this.createHTTPResponse(errorResponse, false, paywallConfig) }; } const verifyResult = await this.ResourceServer.verifyPayment( paymentPayload, matchingRequirements ); if (!verifyResult.isValid) { const errorResponse = await this.ResourceServer.createPaymentRequiredResponse( requirements, resourceInfo, verifyResult.invalidReason, routeConfig.extensions ); return { type: "payment-error", response: this.createHTTPResponse(errorResponse, false, paywallConfig) }; } return { type: "payment-verified", paymentPayload, paymentRequirements: matchingRequirements, declaredExtensions: routeConfig.extensions }; } catch (error) { const errorResponse = await this.ResourceServer.createPaymentRequiredResponse( requirements, resourceInfo, error instanceof Error ? error.message : "Payment verification failed", routeConfig.extensions ); return { type: "payment-error", response: this.createHTTPResponse(errorResponse, false, paywallConfig) }; } } /** * Process settlement after successful response * * @param paymentPayload - The verified payment payload * @param requirements - The matching payment requirements * @param declaredExtensions - Optional declared extensions (for per-key enrichment) * @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure */ async processSettlement(paymentPayload, requirements, declaredExtensions) { try { const settleResponse = await this.ResourceServer.settlePayment( paymentPayload, requirements, declaredExtensions ); if (!settleResponse.success) { return { ...settleResponse, success: false, errorReason: settleResponse.errorReason || "Settlement failed", errorMessage: settleResponse.errorMessage || settleResponse.errorReason || "Settlement failed" }; } return { ...settleResponse, success: true, headers: this.createSettlementHeaders(settleResponse), requirements }; } catch (error) { if (error instanceof SettleError) { return { success: false, errorReason: error.errorReason || error.message, errorMessage: error.errorMessage || error.errorReason || error.message, payer: error.payer, network: error.network, transaction: error.transaction }; } return { success: false, errorReason: error instanceof Error ? error.message : "Settlement failed", errorMessage: error instanceof Error ? error.message : "Settlement failed", network: requirements.network, transaction: "" }; } } /** * Check if a request requires payment based on route configuration * * @param context - HTTP request context * @returns True if the route requires payment, false otherwise */ requiresPayment(context) { const routeConfig = this.getRouteConfig(context.path, context.method); return routeConfig !== void 0; } /** * Normalizes a RouteConfig's accepts field into an array of PaymentOptions * Handles both single PaymentOption and array formats * * @param routeConfig - Route configuration * @returns Array of payment options */ normalizePaymentOptions(routeConfig) { return Array.isArray(routeConfig.accepts) ? routeConfig.accepts : [routeConfig.accepts]; } /** * Validates that all payment options in routes have corresponding registered schemes * and facilitator support. * * @returns Array of validation errors (empty if all routes are valid) */ validateRouteConfiguration() { const errors = []; const normalizedRoutes = typeof this.routesConfig === "object" && !("accepts" in this.routesConfig) ? Object.entries(this.routesConfig) : [["*", this.routesConfig]]; for (const [pattern, config] of normalizedRoutes) { const paymentOptions = this.normalizePaymentOptions(config); for (const option of paymentOptions) { if (!this.ResourceServer.hasRegisteredScheme(option.network, option.scheme)) { errors.push({ routePattern: pattern, scheme: option.scheme, network: option.network, reason: "missing_scheme", message: `Route "${pattern}": No scheme implementation registered for "${option.scheme}" on network "${option.network}"` }); continue; } const supportedKind = this.ResourceServer.getSupportedKind( x402Version, option.network, option.scheme ); if (!supportedKind) { errors.push({ routePattern: pattern, scheme: option.scheme, network: option.network, reason: "missing_facilitator", message: `Route "${pattern}": Facilitator does not support scheme "${option.scheme}" on network "${option.network}"` }); } } } return errors; } /** * Get route configuration for a request * * @param path - Request path * @param method - HTTP method * @returns Route configuration or undefined if no match */ getRouteConfig(path, method) { const normalizedPath = this.normalizePath(path); const upperMethod = method.toUpperCase(); const matchingRoute = this.compiledRoutes.find( (route) => route.regex.test(normalizedPath) && (route.verb === "*" || route.verb === upperMethod) ); return matchingRoute?.config; } /** * Extract payment from HTTP headers (handles v1 and v2) * * @param adapter - HTTP adapter * @returns Decoded payment payload or null */ extractPayment(adapter) { const header = adapter.getHeader("payment-signature") || adapter.getHeader("PAYMENT-SIGNATURE"); if (header) { try { return decodePaymentSignatureHeader(header); } catch (error) { console.warn("Failed to decode PAYMENT-SIGNATURE header:", error); } } return null; } /** * Check if request is from a web browser * * @param adapter - HTTP adapter * @returns True if request appears to be from a browser */ isWebBrowser(adapter) { const accept = adapter.getAcceptHeader(); const userAgent = adapter.getUserAgent(); return accept.includes("text/html") && userAgent.includes("Mozilla"); } /** * Create HTTP response instructions from payment required * * @param paymentRequired - Payment requirements * @param isWebBrowser - Whether request is from browser * @param paywallConfig - Paywall configuration * @param customHtml - Custom HTML template * @param unpaidResponse - Optional custom response (content type and body) for unpaid API requests * @returns Response instructions */ createHTTPResponse(paymentRequired, isWebBrowser, paywallConfig, customHtml, unpaidResponse) { const status = paymentRequired.error === "permit2_allowance_required" ? 412 : 402; if (isWebBrowser) { const html = this.generatePaywallHTML(paymentRequired, paywallConfig, customHtml); return { status, headers: { "Content-Type": "text/html" }, body: html, isHtml: true }; } const response = this.createHTTPPaymentRequiredResponse(paymentRequired); const contentType = unpaidResponse ? unpaidResponse.contentType : "application/json"; const body = unpaidResponse ? unpaidResponse.body : {}; return { status, headers: { "Content-Type": contentType, ...response.headers }, body }; } /** * Create HTTP payment required response (v1 puts in body, v2 puts in header) * * @param paymentRequired - Payment required object * @returns Headers and body for the HTTP response */ createHTTPPaymentRequiredResponse(paymentRequired) { return { headers: { "PAYMENT-REQUIRED": encodePaymentRequiredHeader(paymentRequired) } }; } /** * Create settlement response headers * * @param settleResponse - Settlement response * @returns Headers to add to response */ createSettlementHeaders(settleResponse) { const encoded = encodePaymentResponseHeader(settleResponse); return { "PAYMENT-RESPONSE": encoded }; } /** * Parse route pattern into verb and regex * * @param pattern - Route pattern like "GET /api/*" or "/api/[id]" * @returns Parsed pattern with verb and regex */ parseRoutePattern(pattern) { const [verb, path] = pattern.includes(" ") ? pattern.split(/\s+/) : ["*", pattern]; const regex = new RegExp( `^${path.replace(/[$()+.?^{|}]/g, "\\$&").replace(/\*/g, ".*?").replace(/\[([^\]]+)\]/g, "[^/]+").replace(/\//g, "\\/")}$`, "i" ); return { verb: verb.toUpperCase(), regex }; } /** * Normalize path for matching * * @param path - Raw path from request * @returns Normalized path */ normalizePath(path) { const pathWithoutQuery = path.split(/[?#]/)[0]; let decodedOrRawPath; try { decodedOrRawPath = decodeURIComponent(pathWithoutQuery); } catch { decodedOrRawPath = pathWithoutQuery; } return decodedOrRawPath.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/(.+?)\/+$/, "$1"); } /** * Generate paywall HTML for browser requests * * @param paymentRequired - Payment required response * @param paywallConfig - Optional paywall configuration * @param customHtml - Optional custom HTML template * @returns HTML string */ generatePaywallHTML(paymentRequired, paywallConfig, customHtml) { if (customHtml) { return customHtml; } if (this.paywallProvider) { return this.paywallProvider.generateHtml(paymentRequired, paywallConfig); } try { const paywall = require("@x402/paywall"); const displayAmount2 = this.getDisplayAmount(paymentRequired); const resource2 = paymentRequired.resource; return paywall.getPaywallHtml({ amount: displayAmount2, paymentRequired, currentUrl: resource2?.url || paywallConfig?.currentUrl || "", testnet: paywallConfig?.testnet ?? true, appName: paywallConfig?.appName, appLogo: paywallConfig?.appLogo, sessionTokenEndpoint: paywallConfig?.sessionTokenEndpoint }); } catch { } const resource = paymentRequired.resource; const displayAmount = this.getDisplayAmount(paymentRequired); return ` <!DOCTYPE html> <html> <head> <title>Payment Required</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> <div style="max-width: 600px; margin: 50px auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;"> ${paywallConfig?.appLogo ? `<img src="${paywallConfig.appLogo}" alt="${paywallConfig.appName || "App"}" style="max-width: 200px; margin-bottom: 20px;">` : ""} <h1>Payment Required</h1> ${resource ? `<p><strong>Resource:</strong> ${resource.description || resource.url}</p>` : ""} <p><strong>Amount:</strong> $${displayAmount.toFixed(2)} USDC</p> <div id="payment-widget" data-requirements='${JSON.stringify(paymentRequired)}' data-app-name="${paywallConfig?.appName || ""}" data-testnet="${paywallConfig?.testnet || false}"> <!-- Install @x402/paywall for full wallet integration --> <p style="margin-top: 2rem; padding: 1rem; background: #fef3c7; border-radius: 0.5rem;"> <strong>Note:</strong> Install <code>@x402/paywall</code> for full wallet connection and payment UI. </p> </div> </div> </body> </html> `; } /** * Extract display amount from payment requirements. * * @param paymentRequired - The payment required object * @returns The display amount in decimal format */ getDisplayAmount(paymentRequired) { const accepts = paymentRequired.accepts; if (accepts && accepts.length > 0) { const firstReq = accepts[0]; if ("amount" in firstReq) { return parseFloat(firstReq.amount) / 1e6; } } return 0; } }; // src/http/httpFacilitatorClient.ts var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator"; var HTTPFacilitatorClient = class { /** * Creates a new HTTPFacilitatorClient instance. * * @param config - Configuration options for the facilitator client */ constructor(config) { this.url = config?.url || DEFAULT_FACILITATOR_URL; this._createAuthHeaders = config?.createAuthHeaders; } /** * Verify a payment with the facilitator * * @param paymentPayload - The payment to verify * @param paymentRequirements - The requirements to verify against * @returns Verification response */ async verify(paymentPayload, paymentRequirements) { let headers = { "Content-Type": "application/json" }; if (this._createAuthHeaders) { const authHeaders = await this.createAuthHeaders("verify"); headers = { ...headers, ...authHeaders.headers }; } const response = await fetch(`${this.url}/verify`, { method: "POST", headers, body: JSON.stringify({ x402Version: paymentPayload.x402Version, paymentPayload: this.toJsonSafe(paymentPayload), paymentRequirements: this.toJsonSafe(paymentRequirements) }) }); const data = await response.json(); if (typeof data === "object" && data !== null && "isValid" in data) { const verifyResponse = data; if (!response.ok) { throw new VerifyError(response.status, verifyResponse); } return verifyResponse; } throw new Error(`Facilitator verify failed (${response.status}): ${JSON.stringify(data)}`); } /** * Settle a payment with the facilitator * * @param paymentPayload - The payment to settle * @param paymentRequirements - The requirements for settlement * @returns Settlement response */ async settle(paymentPayload, paymentRequirements) { let headers = { "Content-Type": "application/json" }; if (this._createAuthHeaders) { const authHeaders = await this.createAuthHeaders("settle"); headers = { ...headers, ...authHeaders.headers }; } const response = await fetch(`${this.url}/settle`, { method: "POST", headers, body: JSON.stringify({ x402Version: paymentPayload.x402Version, paymentPayload: this.toJsonSafe(paymentPayload), paymentRequirements: this.toJsonSafe(paymentRequirements) }) }); const data = await response.json(); if (typeof data === "object" && data !== null && "success" in data) { const settleResponse = data; if (!response.ok) { throw new SettleError(response.status, settleResponse); } return settleResponse; } throw new Error(`Facilitator settle failed (${response.status}): ${JSON.stringify(data)}`); } /** * Get supported payment kinds and extensions from the facilitator * * @returns Supported payment kinds and extensions */ async getSupported() { let headers = { "Content-Type": "application/json" }; if (this._createAuthHeaders) { const authHeaders = await this.createAuthHeaders("supported"); headers = { ...headers, ...authHeaders.headers }; } const response = await fetch(`${this.url}/supported`, { method: "GET", headers }); if (!response.ok) { const errorText = await response.text().catch(() => response.statusText); throw new Error(`Facilitator getSupported failed (${response.status}): ${errorText}`); } return await response.json(); } /** * Creates authentication headers for a specific path. * * @param path - The path to create authentication headers for (e.g., "verify", "settle", "supported") * @returns An object containing the authentication headers for the specified path */ async createAuthHeaders(path) { if (this._createAuthHeaders) { const authHeaders = await this._createAuthHeaders(); return { headers: authHeaders[path] ?? {} }; } return { headers: {} }; } /** * Helper to convert objects to JSON-safe format. * Handles BigInt and other non-JSON types. * * @param obj - The object to convert * @returns The JSON-safe representation of the object */ toJsonSafe(obj) { return JSON.parse( JSON.stringify(obj, (_, value) => typeof value === "bigint" ? value.toString() : value) ); } }; // src/http/x402HTTPClient.ts var x402HTTPClient = class { /** * Creates a new x402HTTPClient instance. * * @param client - The underlying x402Client for payment logic */ constructor(client) { this.client = client; this.paymentRequiredHooks = []; } /** * Register a hook to handle 402 responses before payment. * Hooks run in order; first to return headers wins. * * @param hook - The hook function to register * @returns This instance for chaining */ onPaymentRequired(hook) { this.paymentRequiredHooks.push(hook); return this; } /** * Run hooks and return headers if any hook provides them. * * @param paymentRequired - The payment required response from the server * @returns Headers to use for retry, or null to proceed to payment */ async handlePaymentRequired(paymentRequired) { for (const hook of this.paymentRequiredHooks) { const result = await hook({ paymentRequired }); if (result?.headers) { return result.headers; } } return null; } /** * Encodes a payment payload into appropriate HTTP headers based on version. * * @param paymentPayload - The payment payload to encode * @returns HTTP headers containing the encoded payment signature */ encodePaymentSignatureHeader(paymentPayload) { switch (paymentPayload.x402Version) { case 2: return { "PAYMENT-SIGNATURE": encodePaymentSignatureHeader(paymentPayload) }; case 1: return { "X-PAYMENT": encodePaymentSignatureHeader(paymentPayload) }; default: throw new Error( `Unsupported x402 version: ${paymentPayload.x402Version}` ); } } /** * Extracts payment required information from HTTP response. * * @param getHeader - Function to retrieve header value by name (case-insensitive) * @param body - Optional response body for v1 compatibility * @returns The payment required object */ getPaymentRequiredResponse(getHeader, body) { const paymentRequired = getHeader("PAYMENT-REQUIRED"); if (paymentRequired) { return decodePaymentRequiredHeader(paymentRequired); } if (body && body instanceof Object && "x402Version" in body && body.x402Version === 1) { return body; } throw new Error("Invalid payment required response"); } /** * Extracts payment settlement response from HTTP headers. * * @param getHeader - Function to retrieve header value by name (case-insensitive) * @returns The settlement response object */ getPaymentSettleResponse(getHeader) { const paymentResponse = getHeader("PAYMENT-RESPONSE"); if (paymentResponse) { return decodePaymentResponseHeader(paymentResponse); } const xPaymentResponse = getHeader("X-PAYMENT-RESPONSE"); if (xPaymentResponse) { return decodePaymentResponseHeader(xPaymentResponse); } throw new Error("Payment response header not found"); } /** * Creates a payment payload for the given payment requirements. * Delegates to the underlying x402Client. * * @param paymentRequired - The payment required response from the server * @returns Promise resolving to the payment payload */ async createPaymentPayload(paymentRequired) { return this.client.createPaymentPayload(paymentRequired); } }; // src/http/index.ts function encodePaymentSignatureHeader(paymentPayload) { return safeBase64Encode(JSON.stringify(paymentPayload)); } function decodePaymentSignatureHeader(paymentSignatureHeader) { if (!Base64EncodedRegex.test(paymentSignatureHeader)) { throw new Error("Invalid payment signature header"); } return JSON.parse(safeBase64Decode(paymentSignatureHeader)); } function encodePaymentRequiredHeader(paymentRequired) { return safeBase64Encode(JSON.stringify(paymentRequired)); } function decodePaymentRequiredHeader(paymentRequiredHeader) { if (!Base64EncodedRegex.test(paymentRequiredHeader)) { throw new Error("Invalid payment required header"); } return JSON.parse(safeBase64Decode(paymentRequiredHeader)); } function encodePaymentResponseHeader(paymentResponse) { return safeBase64Encode(JSON.stringify(paymentResponse)); } function decodePaymentResponseHeader(paymentResponseHeader) { if (!Base64EncodedRegex.test(paymentResponseHeader)) { throw new Error("Invalid payment response header"); } return JSON.parse(safeBase64Decode(paymentResponseHeader)); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { HTTPFacilitatorClient, RouteConfigurationError, decodePaymentRequiredHeader, decodePaymentResponseHeader, decodePaymentSignatureHeader, encodePaymentRequiredHeader, encodePaymentResponseHeader, encodePaymentSignatureHeader, x402HTTPClient, x402HTTPResourceServer }); //# sourceMappingURL=index.js.map