Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@x402/core

Package Overview
Dependencies
Maintainers
2
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@x402/core - npm Package Compare versions

Comparing version
2.11.0
to
2.12.0
+1268
dist/cjs/x402Client-DmgwYAFT.d.ts
type PaymentRequirementsV1 = {
scheme: string;
network: Network;
maxAmountRequired: string;
resource: string;
description: string;
mimeType: string;
outputSchema: Record<string, unknown>;
payTo: string;
maxTimeoutSeconds: number;
asset: string;
extra: Record<string, unknown>;
};
type PaymentRequiredV1 = {
x402Version: 1;
error?: string;
accepts: PaymentRequirementsV1[];
};
type PaymentPayloadV1 = {
x402Version: 1;
scheme: string;
network: Network;
payload: Record<string, unknown>;
};
type VerifyRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleResponseV1 = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
};
type SupportedResponseV1 = {
kinds: {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
}[];
};
/**
* Recursive readonly for hook contexts so accidental in-place mutation is visible at compile time.
* (Runtime mutation is still possible via other references; see extension enrich validation.)
*/
type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends object ? {
readonly [K in keyof T]: DeepReadonly<T[K]>;
} : T;
interface FacilitatorConfig {
url?: string;
createAuthHeaders?: () => Promise<{
verify: Record<string, string>;
settle: Record<string, string>;
supported: Record<string, string>;
bazaar?: Record<string, string>;
}>;
}
/**
* Interface for facilitator clients
* Can be implemented for HTTP-based or local facilitators
*/
interface FacilitatorClient {
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
}
/**
* HTTP-based client for interacting with x402 facilitator services
* Handles HTTP communication with facilitator endpoints
*/
declare class HTTPFacilitatorClient implements FacilitatorClient {
readonly url: string;
private readonly _createAuthHeaders?;
/**
* Creates a new HTTPFacilitatorClient instance.
*
* @param config - Configuration options for the facilitator client
*/
constructor(config?: FacilitatorConfig);
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator.
* Retries with exponential backoff on 429 rate limit errors.
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
/**
* 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
*/
createAuthHeaders(path: string): Promise<{
headers: Record<string, string>;
}>;
/**
* 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
*/
private toJsonSafe;
}
/**
* Configuration for a protected resource
* Only contains payment-specific configuration, not resource metadata
*/
interface ResourceConfig {
scheme: string;
/**
* Payment recipient. Use a **vacant** value (`""` or whitespace-only) when an extension must
* fill `payTo` during `enrichPaymentRequiredResponse`; non-vacant values are **immutable** there
* so extensions cannot redirect funds to an arbitrary address.
*/
payTo: string;
price: Price;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Context for `enrichPaymentRequiredResponse`. Extensions may merge extension payload via the
* return value. In-place edits to `paymentRequiredResponse.accepts` are **allowlisted** only
* (see {@link assertAcceptsAllowlistedAfterExtensionEnrich}): `scheme`, `network`, and
* `maxTimeoutSeconds` are immutable; `payTo`, `amount`, and `asset` may change only when the
* baseline value was vacant; `extra` may add keys but must not change or remove baseline keys.
*/
interface PaymentRequiredContext {
requirements: PaymentRequirements[];
resourceInfo: ResourceInfo;
error?: string;
paymentRequiredResponse: PaymentRequired;
transportContext?: unknown;
}
/**
* Verify / settle lifecycle hook context: treat as **read-only** for core protocol fields.
* Control flow uses **abort** / **recover** return values only, not in-place mutation.
*/
interface VerifyContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface VerifyResultContext extends VerifyContext {
result: DeepReadonly<VerifyResponse>;
}
/**
* Optional acknowledgement body returned to the caller when an `AfterVerifyHook`
* requests that the resource handler be skipped for a self-contained operation
* (e.g. cooperative refund). Travels in-process only — never on the facilitator wire.
*/
interface SkipHandlerDirective {
contentType?: string;
body?: unknown;
}
type ResourceVerifyRespone = VerifyResponse & {
skipHandler?: SkipHandlerDirective;
};
interface VerifyFailureContext extends VerifyContext {
error: Error;
}
interface SettleContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface SettleResultContext extends SettleContext {
result: DeepReadonly<SettleResponse>;
}
interface SettleFailureContext extends SettleContext {
error: Error;
}
type VerifiedPaymentCancellationReason = "handler_threw" | "handler_failed";
interface VerifiedPaymentCanceledContext extends SettleContext {
reason: VerifiedPaymentCancellationReason;
error?: unknown;
responseStatus?: number;
}
interface VerifiedPaymentCancelOptions {
reason: VerifiedPaymentCancellationReason;
error?: unknown;
responseStatus?: number;
}
interface PaymentCancellationDispatcher {
cancel(options: VerifiedPaymentCancelOptions): Promise<void>;
}
type BeforeVerifyHook = (context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: VerifyResponse;
}>;
type AfterVerifyHook = (context: VerifyResultContext) => Promise<void | {
skipHandler: true;
response?: SkipHandlerDirective;
}>;
type OnVerifyFailureHook = (context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
type BeforeSettleHook = (context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: SettleResponse;
}>;
type AfterSettleHook = (context: SettleResultContext) => Promise<void>;
type OnSettleFailureHook = (context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
type OnVerifiedPaymentCanceledHook = (context: VerifiedPaymentCanceledContext) => Promise<void>;
/**
* Optional overrides for settlement parameters.
* Used to support partial settlement (e.g., upto scheme billing by actual usage).
*
* Note: Overriding the amount to a value different from the agreed-upon
* `PaymentRequirements.amount` is only valid in schemes that explicitly support
* partial settlement, such as the `upto` scheme. Using this with standard
* x402 schemes (e.g., `exact`) will likely cause settlement verification to fail.
*/
interface SettlementOverrides {
/**
* Amount to settle. Supports three formats:
*
* - **Raw atomic units** — e.g., `"1000"` settles exactly 1000 atomic units.
* - **Percent** — e.g., `"50%"` settles 50% of `PaymentRequirements.amount`.
* Supports up to two decimal places (e.g., `"33.33%"`). The result is floored
* to the nearest atomic unit.
* - **Dollar price** — e.g., `"$0.05"` converts a USD-denominated price to
* atomic units. Decimals are determined from the registered scheme's
* `getAssetDecimals` method, falling back to 6 (standard for USDC stablecoins).
* The result is rounded to the nearest atomic unit.
*
* The resolved amount must be <= the authorized maximum in `PaymentRequirements`.
*
* Note: Setting this to an amount other than `PaymentRequirements.amount` is
* only valid in schemes that support partial settlement, such as `upto`.
*/
amount?: string;
}
/**
* Core x402 protocol server for resource protection
* Transport-agnostic implementation of the x402 payment protocol
*/
declare class x402ResourceServer {
private facilitatorClients;
private registeredServerSchemes;
private schemeHookAdapters;
private supportedResponsesMap;
private facilitatorClientsMap;
private registeredExtensions;
private extensionHookAdapters;
private beforeVerifyHooks;
private afterVerifyHooks;
private onVerifyFailureHooks;
private beforeSettleHooks;
private afterSettleHooks;
private onSettleFailureHooks;
private onVerifiedPaymentCanceledHooks;
/**
* Creates a new x402ResourceServer instance.
*
* @param facilitatorClients - Optional facilitator client(s) for payment processing
*/
constructor(facilitatorClients?: FacilitatorClient | FacilitatorClient[]);
/**
* Register a scheme/network server implementation.
*
* @param network - The network identifier
* @param server - The scheme/network server implementation
* @returns The x402ResourceServer instance for chaining
*/
register(network: Network, server: SchemeNetworkServer): x402ResourceServer;
/**
* Check if a scheme is registered for a given network.
*
* @param network - The network identifier
* @param scheme - The payment scheme name
* @returns True if the scheme is registered for the network, false otherwise
*/
hasRegisteredScheme(network: Network, scheme: string): boolean;
/**
* Returns the decimal precision for the asset specified in the given payment requirements.
* Looks up the registered scheme for the network and delegates to its getAssetDecimals
* method if available. Falls back to 6 (standard for USDC stablecoins) when the scheme
* does not implement getAssetDecimals or is not registered.
*
* @param requirements - The payment requirements containing scheme, network, and asset
* @returns The number of decimal places for the asset
*/
getAssetDecimalsForRequirements(requirements: PaymentRequirements): number;
/**
* Registers a resource server extension (enrichment and optional verify/settle hooks).
* Re-registering the same key overwrites; omitting `hooks` removes adapter handles for that key.
*
* @param extension - Extension definition including `key` and optional `hooks`
* @returns This server instance for chaining
*/
registerExtension(extension: ResourceServerExtension): this;
/**
* Check if an extension is registered.
*
* @param key - The extension key
* @returns True if the extension is registered
*/
hasExtension(key: string): boolean;
/**
* Get all registered extensions.
*
* @returns Array of registered extensions
*/
getExtensions(): ResourceServerExtension[];
/**
* Enriches declared extensions using registered extension hooks.
*
* @param declaredExtensions - Extensions declared on the route
* @param transportContext - Transport-specific context (HTTP, A2A, MCP, etc.)
* @returns Enriched extensions map
*/
enrichExtensions(declaredExtensions: Record<string, unknown>, transportContext: unknown): Record<string, unknown>;
/**
* Register a hook to execute before payment verification.
* Can abort verification by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeVerify(hook: BeforeVerifyHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment verification.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterVerify(hook: AfterVerifyHook): x402ResourceServer;
/**
* Register a hook to execute when payment verification fails.
* Can recover from failure by returning { recovered: true, result: VerifyResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifyFailure(hook: OnVerifyFailureHook): x402ResourceServer;
/**
* Register a hook to execute before payment settlement.
* Can abort settlement by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeSettle(hook: BeforeSettleHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterSettle(hook: AfterSettleHook): x402ResourceServer;
/**
* Register a hook to execute when payment settlement fails.
* Can recover from failure by returning { recovered: true, result: SettleResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onSettleFailure(hook: OnSettleFailureHook): x402ResourceServer;
/**
* Register a hook to execute when verified payment work is canceled before settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifiedPaymentCanceled(hook: OnVerifiedPaymentCanceledHook): x402ResourceServer;
/**
* Initialize by fetching supported kinds from all facilitators
* Creates mappings for supported responses and facilitator clients
* Earlier facilitators in the array get precedence
*/
initialize(): Promise<void>;
/**
* Get supported kind for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The supported kind or undefined if not found
*/
getSupportedKind(x402Version: number, network: Network, scheme: string): SupportedKind | undefined;
/**
* Get facilitator extensions for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator extensions or empty array if not found
*/
getFacilitatorExtensions(x402Version: number, network: Network, scheme: string): string[];
/**
* Build payment requirements for a protected resource
*
* @param resourceConfig - Configuration for the protected resource
* @returns Array of payment requirements
*/
buildPaymentRequirements(resourceConfig: ResourceConfig): Promise<PaymentRequirements[]>;
/**
* Build payment requirements from multiple payment options
* This method handles resolving dynamic payTo/price functions and builds requirements for each option
*
* @param paymentOptions - Array of payment options to convert
* @param context - HTTP request context for resolving dynamic functions
* @returns Array of payment requirements (one per option)
*/
buildPaymentRequirementsFromOptions<TContext = unknown>(paymentOptions: Array<{
scheme: string;
payTo: string | ((context: TContext) => string | Promise<string>);
price: Price | ((context: TContext) => Price | Promise<Price>);
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}>, context: TContext): Promise<PaymentRequirements[]>;
/**
* Create a payment required response
*
* @param requirements - Payment requirements
* @param resourceInfo - Resource information
* @param error - Error message
* @param extensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request, MCP tool context)
* @param paymentPayload - Optional failed payment payload for response-time scheme enrichment
* @returns Payment required response object
*/
createPaymentRequiredResponse(requirements: PaymentRequirements[], resourceInfo: ResourceInfo, error?: string, extensions?: Record<string, unknown>, transportContext?: unknown, paymentPayload?: PaymentPayload): Promise<PaymentRequired>;
/**
* Verifies a payment against requirements, running manual and in-use extension hooks.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context (e.g. HTTP, MCP)
* @returns Facilitator verify outcome (optionally carrying a `skipHandler` directive),
* or abort/recovery as driven by hooks
*/
verifyPayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown): Promise<ResourceVerifyRespone>;
/**
* Create cancellation controls for a verified payment attempt.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context
* @returns Cancellation controls for the verified payment attempt
*/
createPaymentCancellationDispatcher(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown): PaymentCancellationDispatcher;
/**
* Settle a verified payment
*
* @param paymentPayload - The payment payload to settle
* @param requirements - The payment requirements
* @param declaredExtensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request/response, MCP tool context)
* @param settlementOverrides - Optional overrides for settlement parameters (e.g., partial settlement amount)
* @returns Settlement response
*/
settlePayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown, settlementOverrides?: SettlementOverrides): Promise<SettleResponse>;
/**
* Find matching payment requirements for a payment
*
* @param availableRequirements - Array of available payment requirements
* @param paymentPayload - The payment payload
* @returns Matching payment requirements or undefined
*/
findMatchingRequirements(availableRequirements: PaymentRequirements[], paymentPayload: PaymentPayload): PaymentRequirements | undefined;
/**
* Logs a warning when a manual or extension adapter lifecycle hook throws.
*
* @param phase - Lifecycle phase name (e.g. `beforeVerify`)
* @param label - Hook source label from {@link getLabeledHooks} (manual index or extension key)
* @param error - Thrown value or rejection reason
*/
private warnResourceServerHookFailure;
/**
* Logs a warning when a registered extension enrichment hook throws.
*
* @param extensionKey - Registered extension identifier
* @param hookName - Hook method name (e.g. `enrichDeclaration`)
* @param error - Thrown value or rejection reason
*/
private warnExtensionHookFailure;
/**
* Executes after-verify hooks for facilitator and hook-provided verify results.
*
* @param verifyResult - Verify response passed to after-verify hooks.
* @param context - Verify context shared with before-verify hooks.
* @param extensionKeysInUse - Declared extension keys for this request.
* @param matchedScheme - Scheme/network selected for this payment.
* @param matchedScheme.network - Matched payment network.
* @param matchedScheme.scheme - Matched payment scheme.
* @returns Verify response with any in-process skip handler directive.
*/
private runAfterVerifyHooks;
/**
* Runs response enrichment after settlement lifecycle hooks complete.
*
* @param settleResult - Mutable settlement result being returned to the caller
* @param context - Read-only hook context for enrichment callbacks
* @param declaredExtensions - Extension declarations present on this payment
* @param matchedScheme - Scheme/network selected for this settlement
* @param matchedScheme.network - Matched payment network
* @param matchedScheme.scheme - Matched payment scheme
*/
private enrichSettlementResponse;
/**
* Notify hooks that verified work ended before settlement.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param options - Cancellation reason and optional diagnostics
* @param fallbackTransportContext - Optional transport-specific context
*/
private dispatchVerifiedPaymentCanceled;
/**
* Manual hooks first, then the matched scheme adapter, then extension adapters for keys in use.
* Each entry carries a stable label for logging when a hook throws.
*
* @param phase - Hook slot (e.g. `beforeVerify`)
* @param extensionKeysInUse - Declared extension keys for this request
* @param matchedScheme - Scheme/network selected for this payment
* @param matchedScheme.network - Matched payment network
* @param matchedScheme.scheme - Matched payment scheme
* @returns Hooks in invocation order with source labels
*/
private getLabeledHooks;
/**
* Get facilitator client for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator client or undefined if not found
*/
private getFacilitatorClient;
}
interface FacilitatorExtension {
key: string;
}
/**
* Per-extension verify/settle hooks. Contexts are **read-only** for core protocol fields; use
* **abort** / **recover** return values instead of mutating `paymentPayload`, `requirements`, etc.
*/
interface ResourceServerExtensionHooks {
onBeforeVerify?: (declaration: unknown, context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: VerifyResponse;
}>;
onAfterVerify?: (declaration: unknown, context: VerifyResultContext) => Promise<void>;
onVerifyFailure?: (declaration: unknown, context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
onBeforeSettle?: (declaration: unknown, context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: SettleResponse;
}>;
onAfterSettle?: (declaration: unknown, context: SettleResultContext) => Promise<void>;
onSettleFailure?: (declaration: unknown, context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
onVerifiedPaymentCanceled?: (declaration: unknown, context: VerifiedPaymentCanceledContext) => Promise<void>;
}
interface ResourceServerExtension {
key: string;
enrichDeclaration?: (declaration: unknown, transportContext: unknown) => unknown;
/**
* Return value merges into `extensions[key]`. In-place edits to `accepts` are allowlisted only
* (see server `assertAcceptsAllowlistedAfterExtensionEnrich`): vacant `payTo` / `amount` / `asset`
* may be filled; locked values and `scheme` / `network` / `maxTimeoutSeconds` / baseline `extra`
* entries are immutable.
*/
enrichPaymentRequiredResponse?: (declaration: unknown, context: PaymentRequiredContext) => Promise<unknown>;
/**
* Return value merges into `settleResult.extensions[key]`. Facilitator fields (`success`,
* `transaction`, `network`, etc.) must not be changed; only `extensions` is merged from the hook.
*/
enrichSettlementResponse?: (declaration: unknown, context: SettleResultContext) => Promise<unknown>;
/** Installed on `registerExtension`; runs only when `declaredExtensions[key]` is defined. */
hooks?: ResourceServerExtensionHooks;
}
type Network = `${string}:${string}`;
type Money = string | number;
type AssetAmount = {
asset: string;
amount: string;
extra?: Record<string, unknown>;
};
type Price = Money | AssetAmount;
interface ResourceInfo {
url: string;
description?: string;
mimeType?: string;
serviceName?: string;
tags?: string[];
iconUrl?: string;
}
type PaymentRequirements = {
scheme: string;
network: Network;
asset: string;
amount: string;
payTo: string;
maxTimeoutSeconds: number;
extra: Record<string, unknown>;
};
type PaymentRequired = {
x402Version: number;
error?: string;
resource: ResourceInfo;
accepts: PaymentRequirements[];
extensions?: Record<string, unknown>;
};
type PaymentPayload = {
x402Version: number;
resource?: ResourceInfo;
accepted: PaymentRequirements;
payload: Record<string, unknown>;
extensions?: Record<string, unknown>;
};
type VerifyRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type VerifyResponse = {
isValid: boolean;
invalidReason?: string;
invalidMessage?: string;
payer?: string;
extensions?: Record<string, unknown>;
extra?: Record<string, unknown>;
};
type SettleRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type SettleResponse = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
/** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */
amount?: string;
extensions?: Record<string, unknown>;
extra?: Record<string, unknown>;
};
type SupportedKind = {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
};
type SupportedResponse = {
kinds: SupportedKind[];
extensions: string[];
signers: Record<string, string[]>;
};
/**
* Error thrown when payment verification fails.
*/
declare class VerifyError extends Error {
readonly invalidReason?: string;
readonly invalidMessage?: string;
readonly payer?: string;
readonly statusCode: number;
/**
* Creates a VerifyError from a failed verification response.
*
* @param statusCode - HTTP status code from the facilitator
* @param response - The verify response containing failure details
*/
constructor(statusCode: number, response: VerifyResponse);
}
/**
* Error thrown when payment settlement fails.
*/
declare class SettleError extends Error {
readonly errorReason?: string;
readonly errorMessage?: string;
readonly payer?: string;
readonly transaction: string;
readonly network: Network;
readonly statusCode: number;
/**
* 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: number, response: SettleResponse);
}
/**
* Error thrown when a facilitator returns malformed success payload data.
*/
declare class FacilitatorResponseError extends Error {
/**
* Creates a FacilitatorResponseError for malformed facilitator responses.
*
* @param message - The boundary error message
*/
constructor(message: string);
}
/**
* Walks an error cause chain to find the first facilitator response error.
*
* @param error - The thrown value to inspect
* @returns The nested facilitator response error, if present
*/
declare function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null;
/**
* Money parser function that converts a numeric amount to an AssetAmount
* Receives the amount as a decimal number (e.g., 1.50 for $1.50)
* Returns null to indicate "cannot handle this amount", causing fallback to next parser
* Always returns a Promise for consistency - use async/await
*
* @param amount - The decimal amount (e.g., 1.50)
* @param network - The network identifier for context
* @returns AssetAmount or null to try next parser
*/
type MoneyParser = (amount: number, network: Network) => Promise<AssetAmount | null>;
/**
* Result of createPaymentPayload - the core payload fields.
* Contains the x402 version, scheme-specific payload data, and optional extension data.
* Schemes may return extensions (e.g., EIP-2612 gas sponsoring) that get merged
* with server-declared extensions in the final PaymentPayload.
*/
type PaymentPayloadResult = Pick<PaymentPayload, "x402Version" | "payload"> & {
extensions?: Record<string, unknown>;
};
/**
* Context passed to scheme's createPaymentPayload for extensions awareness.
* Contains the server-declared extensions from PaymentRequired so the scheme
* can check which extensions are advertised and respond accordingly.
*/
interface PaymentPayloadContext {
extensions?: Record<string, unknown>;
}
interface SchemeClientHooks {
onBeforePaymentCreation?: BeforePaymentCreationHook;
onAfterPaymentCreation?: AfterPaymentCreationHook;
onPaymentCreationFailure?: OnPaymentCreationFailureHook;
onPaymentResponse?: OnPaymentResponseHook;
}
interface SchemeNetworkClient {
readonly scheme: string;
readonly schemeHooks?: SchemeClientHooks;
createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
}
/**
* Context passed to SchemeNetworkFacilitator.verify/settle, providing
* access to registered facilitator extensions. Mechanism implementations
* use this to retrieve extension-provided capabilities (e.g., a batch signer).
*/
interface FacilitatorContext {
getExtension<T extends FacilitatorExtension = FacilitatorExtension>(key: string): T | undefined;
}
interface SchemeNetworkFacilitator {
readonly scheme: string;
/**
* CAIP family pattern that this facilitator supports.
* Used to group signers by blockchain family in the supported response.
*
* @example
* // EVM facilitators
* readonly caipFamily = "eip155:*";
*
* @example
* // SVM facilitators
* readonly caipFamily = "solana:*";
*/
readonly caipFamily: string;
/**
* Get mechanism-specific extra data needed for the supported kinds endpoint.
* This method is called when building the facilitator's supported response.
*
* @param network - The network identifier for context
* @returns Extra data object or undefined if no extra data is needed
*
* @example
* // EVM schemes return undefined (no extra data needed)
* getExtra(network: Network): undefined {
* return undefined;
* }
*
* @example
* // SVM schemes return feePayer address
* getExtra(network: Network): Record<string, unknown> | undefined {
* return { feePayer: this.signer.address };
* }
*/
getExtra(network: Network): Record<string, unknown> | undefined;
/**
* Get signer addresses used by this facilitator for a given network.
* These are included in the supported response to help clients understand
* which addresses might sign/pay for transactions.
*
* Supports multiple addresses for load balancing, key rotation, and high availability.
*
* @param network - The network identifier
* @returns Array of signer addresses (wallet addresses, fee payer addresses, etc.)
*
* @example
* // EVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*
* @example
* // SVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*/
getSigners(network: string): string[];
verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
}
interface SchemeServerHooks {
onBeforeVerify?: BeforeVerifyHook;
onAfterVerify?: AfterVerifyHook;
onBeforeSettle?: BeforeSettleHook;
onAfterSettle?: AfterSettleHook;
onVerifyFailure?: OnVerifyFailureHook;
onSettleFailure?: OnSettleFailureHook;
onVerifiedPaymentCanceled?: OnVerifiedPaymentCanceledHook;
}
type SchemeEnrichSettlementPayloadHook = (ctx: SettleContext) => Promise<Record<string, unknown> | void>;
type SchemeEnrichSettlementResponseHook = (ctx: SettleResultContext) => Promise<Record<string, unknown> | void>;
interface SchemePaymentRequiredContext {
requirements: PaymentRequirements[];
paymentPayload?: DeepReadonly<PaymentPayload>;
resourceInfo: ResourceInfo;
error?: string;
paymentRequiredResponse: PaymentRequired;
transportContext?: unknown;
}
type SchemeEnrichPaymentRequiredResponseHook = (ctx: SchemePaymentRequiredContext) => Promise<PaymentRequirements[] | void>;
interface SchemeNetworkServer {
readonly scheme: string;
readonly schemeHooks?: SchemeServerHooks;
enrichPaymentRequiredResponse?: SchemeEnrichPaymentRequiredResponseHook;
enrichSettlementPayload?: SchemeEnrichSettlementPayloadHook;
enrichSettlementResponse?: SchemeEnrichSettlementResponseHook;
/**
* Convert a user-friendly price to the scheme's specific amount and asset format
* Always returns a Promise for consistency
*
* @param price - User-friendly price (e.g., "$0.10", "0.10", { amount: "100000", asset: "USDC" })
* @param network - The network identifier for context
* @returns Promise that resolves to the converted amount, asset identifier, and any extra metadata
*
* @example
* // For EVM networks with USDC:
* await parsePrice("$0.10", "eip155:8453") => { amount: "100000", asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
*
* // For custom schemes:
* await parsePrice("10 points", "custom:network") => { amount: "10", asset: "points" }
*/
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
/**
* Optional: Return the decimal precision of the asset for a given network.
* Used by `resolveSettlementOverrideAmount` to convert dollar-format overrides to atomic units.
* Defaults to 6 when not implemented.
*
* @param asset - The asset address or symbol
* @param network - The network identifier
* @returns Number of decimal places for the asset
*/
getAssetDecimals?(asset: string, network: Network): number;
/**
* Build payment requirements for this scheme/network combination
*
* @param paymentRequirements - Base payment requirements with amount/asset already set
* @param supportedKind - The supported kind from facilitator's /supported endpoint
* @param supportedKind.x402Version - The x402 version
* @param supportedKind.scheme - The payment scheme
* @param supportedKind.network - The network identifier
* @param supportedKind.extra - Optional extra metadata
* @param facilitatorExtensions - Extensions supported by the facilitator
* @returns Enhanced payment requirements ready to be sent to clients
*/
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: SupportedKind, facilitatorExtensions: string[]): Promise<PaymentRequirements>;
}
/**
* Client Hook Context Interfaces
*/
interface PaymentCreationContext {
paymentRequired: PaymentRequired;
selectedRequirements: PaymentRequirements;
}
interface PaymentCreatedContext extends PaymentCreationContext {
paymentPayload: PaymentPayload;
}
interface PaymentCreationFailureContext extends PaymentCreationContext {
error: Error;
}
/**
* Client Hook Type Definitions
*/
type BeforePaymentCreationHook = (context: PaymentCreationContext) => Promise<void | {
abort: true;
reason: string;
}>;
type AfterPaymentCreationHook = (context: PaymentCreatedContext) => Promise<void>;
type OnPaymentCreationFailureHook = (context: PaymentCreationFailureContext) => Promise<void | {
recovered: true;
payload: PaymentPayload;
}>;
/**
* Context provided to payment response hooks after the paid request completes.
*
* Discriminate by what's present:
* - `settleResponse` with `success: true` → settle succeeded
* - `settleResponse` with `success: false` → settle failed
* - `paymentRequired` (no `settleResponse`) → verify failed
* - `error` → transport or parse error
*/
interface PaymentResponseContext {
paymentPayload: PaymentPayload;
requirements: PaymentRequirements;
settleResponse?: SettleResponse;
paymentRequired?: PaymentRequired;
error?: Error;
}
/**
* Hook fired after a paid request completes.
* Return `{ recovered: true }` to signal the transport should retry with a fresh payload.
*/
type OnPaymentResponseHook = (ctx: PaymentResponseContext) => Promise<void | {
recovered: true;
}>;
type SelectPaymentRequirements = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements;
/**
* Extension that can enrich payment payloads on the client side.
*
* Client extensions are invoked after the scheme creates the base payment payload
* but before it is returned. This allows mechanism-specific logic (e.g., EVM EIP-2612
* permit signing) to enrich the payload's extensions data.
*/
interface ClientExtension {
/**
* Unique key identifying this extension (e.g., "eip2612GasSponsoring").
* Must match the extension key used in PaymentRequired.extensions.
*/
key: string;
/**
* Called after payload creation when the extension key is present in
* paymentRequired.extensions. Allows the extension to enrich the payload
* with extension-specific data (e.g., signing an EIP-2612 permit).
*
* @param paymentPayload - The payment payload to enrich
* @param paymentRequired - The original PaymentRequired response
* @returns The enriched payment payload
*/
enrichPaymentPayload?: (paymentPayload: PaymentPayload, paymentRequired: PaymentRequired) => Promise<PaymentPayload>;
}
/**
* A policy function that filters or transforms payment requirements.
* Policies are applied in order before the selector chooses the final option.
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of payment requirements to filter/transform
* @returns Filtered array of payment requirements
*/
type PaymentPolicy = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements[];
/**
* Configuration for registering a payment scheme with a specific network
*/
interface SchemeRegistration {
/**
* The network identifier (e.g., 'eip155:8453', 'solana:mainnet')
*/
network: Network;
/**
* The scheme client implementation for this network
*/
client: SchemeNetworkClient;
/**
* The x402 protocol version to use for this scheme
*
* @default 2
*/
x402Version?: number;
}
/**
* Configuration options for the fetch wrapper
*/
interface x402ClientConfig {
/**
* Array of scheme registrations defining which payment methods are supported
*/
schemes: SchemeRegistration[];
/**
* Policies to apply to the client
*/
policies?: PaymentPolicy[];
/**
* Custom payment requirements selector function
* If not provided, uses the default selector (first available option)
*/
paymentRequirementsSelector?: SelectPaymentRequirements;
}
/**
* Core client for managing x402 payment schemes and creating payment payloads.
*
* Handles registration of payment schemes, policy-based filtering of payment requirements,
* and creation of payment payloads based on server requirements.
*/
declare class x402Client {
private readonly paymentRequirementsSelector;
private readonly registeredClientSchemes;
private readonly schemeClientHookAdapters;
private readonly policies;
private readonly registeredExtensions;
private beforePaymentCreationHooks;
private afterPaymentCreationHooks;
private onPaymentCreationFailureHooks;
private paymentResponseHooks;
/**
* Creates a new x402Client instance.
*
* @param paymentRequirementsSelector - Function to select payment requirements from available options
*/
constructor(paymentRequirementsSelector?: SelectPaymentRequirements);
/**
* Creates a new x402Client instance from a configuration object.
*
* @param config - The client configuration including schemes, policies, and payment requirements selector
* @returns A configured x402Client instance
*/
static fromConfig(config: x402ClientConfig): x402Client;
/**
* Registers a scheme client for the current x402 version.
*
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
register(network: Network, client: SchemeNetworkClient): x402Client;
/**
* Registers a scheme client for x402 version 1.
*
* @param network - The v1 network identifier (e.g., 'base-sepolia', 'solana-devnet')
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
registerV1(network: string, client: SchemeNetworkClient): x402Client;
/**
* Registers a policy to filter or transform payment requirements.
*
* Policies are applied in order after filtering by registered schemes
* and before the selector chooses the final payment requirement.
*
* @param policy - Function to filter/transform payment requirements
* @returns The x402Client instance for chaining
*
* @example
* ```typescript
* // Prefer cheaper options
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => BigInt(r.value) < BigInt('1000000'))
* );
*
* // Prefer specific networks
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => r.network.startsWith('eip155:'))
* );
* ```
*/
registerPolicy(policy: PaymentPolicy): x402Client;
/**
* Registers a client extension that can enrich payment payloads.
*
* Extensions are invoked after the scheme creates the base payload and the
* payload is wrapped with extensions/resource/accepted data. If the extension's
* key is present in `paymentRequired.extensions`, the extension's
* `enrichPaymentPayload` hook is called to modify the payload.
*
* @param extension - The client extension to register
* @returns The x402Client instance for chaining
*/
registerExtension(extension: ClientExtension): x402Client;
/**
* Register a hook to execute before payment payload creation.
* Can abort creation by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onBeforePaymentCreation(hook: BeforePaymentCreationHook): x402Client;
/**
* Register a hook to execute after successful payment payload creation.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onAfterPaymentCreation(hook: AfterPaymentCreationHook): x402Client;
/**
* Register a hook to execute when payment payload creation fails.
* Can recover from failure by returning { recovered: true, payload: PaymentPayload }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentCreationFailure(hook: OnPaymentCreationFailureHook): x402Client;
/**
* Register a hook to execute after a paid request completes.
* Can signal recovery by returning { recovered: true }, causing the transport to retry.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentResponse(hook: OnPaymentResponseHook): x402Client;
/**
* Fires all registered payment response hooks in order.
* Returns `{ recovered: true }` if any hook signals recovery (first wins).
*
* @param ctx - The payment response context
* @returns Recovery signal or undefined
*/
handlePaymentResponse(ctx: PaymentResponseContext): Promise<{
recovered: true;
} | undefined>;
/**
* Creates a payment payload based on a PaymentRequired response.
*
* Automatically extracts x402Version, resource, and extensions from the PaymentRequired
* response and constructs a complete PaymentPayload with the accepted requirements.
*
* @param paymentRequired - The PaymentRequired response from the server
* @returns Promise resolving to the complete payment payload
*/
createPaymentPayload(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
/**
* Merges server-declared extensions with scheme-provided extensions.
* Scheme extensions overlay on top of server extensions at each key,
* preserving server-provided schema while overlaying scheme-provided info.
*
* @param serverExtensions - Extensions declared by the server in the 402 response
* @param schemeExtensions - Extensions provided by the scheme client (e.g. EIP-2612)
* @returns The merged extensions object, or undefined if both inputs are undefined
*/
private mergeExtensions;
/**
* Enriches a payment payload by calling registered extension hooks.
* For each extension key present in the PaymentRequired response,
* invokes the corresponding extension's enrichPaymentPayload callback.
*
* @param paymentPayload - The payment payload to enrich with extension data
* @param paymentRequired - The PaymentRequired response containing extension declarations
* @returns The enriched payment payload with extension data applied
*/
private enrichPaymentPayloadWithExtensions;
/**
* Selects appropriate payment requirements based on registered clients and policies.
*
* Selection process:
* 1. Filter by registered schemes (network + scheme support)
* 2. Apply all registered policies in order
* 3. Use selector to choose final requirement
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of available payment requirements
* @returns The selected payment requirements
*/
private selectPaymentRequirements;
/**
* Internal method to register a scheme client.
*
* @param x402Version - The x402 protocol version
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
private _registerScheme;
/**
* Returns manual hooks followed by the hook for the selected scheme, if present.
*
* @param phase - Hook slot to collect
* @param x402Version - Protocol version for the selected requirement
* @param requirements - Selected payment requirement
* @returns Hooks in invocation order
*/
private getLabeledHooks;
}
export { type SchemeRegistration as $, type AfterVerifyHook as A, type BeforeVerifyHook as B, type SchemeEnrichPaymentRequiredResponseHook as C, type SchemePaymentRequiredContext as D, type SchemeEnrichSettlementPayloadHook as E, type FacilitatorExtension as F, type SchemeEnrichSettlementResponseHook as G, HTTPFacilitatorClient as H, type Price as I, x402Client as J, type PaymentCreationContext as K, type PaymentCreatedContext as L, type PaymentCreationFailureContext as M, type Network as N, type OnVerifyFailureHook as O, type PaymentPayload as P, type BeforePaymentCreationHook as Q, type ResourceConfig as R, type SettleResponse as S, type AfterPaymentCreationHook as T, type OnPaymentCreationFailureHook as U, type VerifyResponse as V, type PaymentResponseContext as W, type OnPaymentResponseHook as X, type SelectPaymentRequirements as Y, type ClientExtension as Z, type PaymentPolicy as _, type PaymentRequirements as a, type x402ClientConfig as a0, type PaymentRequirementsV1 as a1, type PaymentRequiredV1 as a2, type PaymentPayloadV1 as a3, type VerifyRequestV1 as a4, type SettleRequestV1 as a5, type SettleResponseV1 as a6, type SupportedResponseV1 as a7, type Money as a8, type AssetAmount as a9, type VerifyRequest as aa, type SettleRequest as ab, type SupportedResponse as ac, type SupportedKind as ad, VerifyError as ae, SettleError as af, type ResourceInfo as ag, type SchemeNetworkClient as ah, type SchemeClientHooks as ai, type SchemeNetworkServer as aj, type SchemeServerHooks as ak, type MoneyParser as al, type PaymentPayloadResult as am, type PaymentPayloadContext as an, type FacilitatorContext as ao, type ResourceServerExtension as ap, type ResourceServerExtensionHooks as aq, type DeepReadonly as ar, type SchemeNetworkFacilitator as b, type PaymentRequired as c, type FacilitatorClient as d, type FacilitatorConfig as e, FacilitatorResponseError as f, getFacilitatorResponseError as g, type PaymentRequiredContext as h, type VerifyContext as i, type VerifyResultContext as j, type VerifyFailureContext as k, type SettleContext as l, type SettleResultContext as m, type SettleFailureContext as n, type VerifiedPaymentCanceledContext as o, type VerifiedPaymentCancellationReason as p, type VerifiedPaymentCancelOptions as q, type PaymentCancellationDispatcher as r, type SettlementOverrides as s, type SkipHandlerDirective as t, type ResourceVerifyRespone as u, type BeforeSettleHook as v, type AfterSettleHook as w, x402ResourceServer as x, type OnSettleFailureHook as y, type OnVerifiedPaymentCanceledHook as z };
import { x as x402ResourceServer, I as Price, N as Network, S as SettleResponse, c as PaymentRequired, r as PaymentCancellationDispatcher, P as PaymentPayload, a as PaymentRequirements, s as SettlementOverrides } from './x402Client-DmgwYAFT.js';
declare const SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
/**
* Framework-agnostic HTTP adapter interface
* Implementations provide framework-specific HTTP operations
*/
interface HTTPAdapter {
getHeader(name: string): string | undefined;
getMethod(): string;
getPath(): string;
getUrl(): string;
getAcceptHeader(): string;
getUserAgent(): string;
/**
* Get query parameters from the request URL
*
* @returns Record of query parameter key-value pairs
*/
getQueryParams?(): Record<string, string | string[]>;
/**
* Get a specific query parameter by name
*
* @param name - The query parameter name
* @returns The query parameter value(s) or undefined
*/
getQueryParam?(name: string): string | string[] | undefined;
/**
* Get the parsed request body
* Framework adapters should parse JSON/form data appropriately
*
* @returns The parsed request body
*/
getBody?(): unknown;
}
/**
* Paywall configuration for HTML responses
*/
interface PaywallConfig {
appName?: string;
appLogo?: string;
sessionTokenEndpoint?: string;
currentUrl?: string;
testnet?: boolean;
}
/**
* Paywall provider interface for generating HTML
*/
interface PaywallProvider {
generateHtml(paymentRequired: PaymentRequired, config?: PaywallConfig): string;
}
/**
* Dynamic payTo function that receives HTTP request context
*/
type DynamicPayTo = (context: HTTPRequestContext) => string | Promise<string>;
/**
* Dynamic price function that receives HTTP request context
*/
type DynamicPrice = (context: HTTPRequestContext) => Price | Promise<Price>;
/**
* Result of response body callbacks containing content type and body.
*/
interface HTTPResponseBody {
/**
* The content type for the response (e.g., 'application/json', 'text/plain').
*/
contentType: string;
/**
* The response body to include in the 402 response.
*/
body: unknown;
}
/**
* Dynamic function to generate a custom response for unpaid requests.
* Receives the HTTP request context and returns the content type and body to include in the 402 response.
*/
type UnpaidResponseBody = (context: HTTPRequestContext) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* Dynamic function to generate a custom response for settlement failures.
* Receives the HTTP request context and settle failure result, returns the content type and body.
*/
type SettlementFailedResponseBody = (context: HTTPRequestContext, settleResult: Omit<ProcessSettleFailureResponse, "response">) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* A single payment option for a route
* Represents one way a client can pay for access to the resource
*/
interface PaymentOption {
scheme: string;
payTo: string | DynamicPayTo;
price: Price | DynamicPrice;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Route configuration for HTTP endpoints
*
* The 'accepts' field defines payment options for the route.
* Can be a single PaymentOption or an array of PaymentOptions for multiple payment methods.
*/
interface RouteConfig {
accepts: PaymentOption | PaymentOption[];
resource?: string;
description?: string;
mimeType?: string;
customPaywallHtml?: string;
/**
* Optional callback to generate a custom response for unpaid API requests.
* This allows servers to return preview data, error messages, or other content
* when a request lacks payment.
*
* For browser requests (Accept: text/html), the paywall HTML takes precedence.
* This callback is only used for API clients.
*
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @returns An object containing both contentType and body for the 402 response
*/
unpaidResponseBody?: UnpaidResponseBody;
/**
* Optional callback to generate a custom response for settlement failures.
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @param settleResult - The settlement failure result
* @returns An object containing both contentType and body for the 402 response
*/
settlementFailedResponseBody?: SettlementFailedResponseBody;
extensions?: Record<string, unknown>;
}
/**
* Routes configuration - maps path patterns to route configs
*/
type RoutesConfig = Record<string, RouteConfig> | RouteConfig;
/**
* Check if any routes in the configuration declare bazaar extensions.
*
* @param routes - Route configuration
* @returns True if any route has extensions.bazaar defined
*/
declare function checkIfBazaarNeeded(routes: RoutesConfig): boolean;
/**
* Hook that runs on every request to a protected route, before payment processing.
* Can grant access without payment, deny the request, or continue to payment flow.
*
* @returns
* - `void` - Continue to payment processing (default behavior)
* - `{ grantAccess: true }` - Grant access without requiring payment
* - `{ abort: true; reason: string }` - Deny the request (returns 403)
*/
type ProtectedRequestHook = (context: HTTPRequestContext, routeConfig: RouteConfig) => Promise<void | {
grantAccess: true;
} | {
abort: true;
reason: string;
}>;
/**
* Compiled route for efficient matching
*/
interface CompiledRoute {
verb: string;
regex: RegExp;
config: RouteConfig;
pattern: string;
}
/**
* HTTP request context that encapsulates all request data
*/
interface HTTPRequestContext {
adapter: HTTPAdapter;
path: string;
method: string;
paymentHeader?: string;
routePattern?: string;
}
/**
* HTTP transport context contains both request context and optional response data.
*/
interface HTTPTransportContext {
/** The HTTP request context */
request: HTTPRequestContext;
/** The response body buffer */
responseBody?: Buffer;
/** Response headers set by the route handler (used for settlement overrides) */
responseHeaders?: Record<string, string>;
}
/**
* HTTP response instructions for the framework middleware
*/
interface HTTPResponseInstructions {
status: number;
headers: Record<string, string>;
body?: unknown;
isHtml?: boolean;
}
/**
* Result of processing an HTTP request for payment
*/
type HTTPProcessResult = {
type: "no-payment-required";
} | {
type: "payment-verified";
cancellationDispatcher: PaymentCancellationDispatcher;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
declaredExtensions?: Record<string, unknown>;
} | {
type: "payment-error";
response: HTTPResponseInstructions;
};
/**
* Result of processSettlement
*/
type ProcessSettleSuccessResponse = SettleResponse & {
success: true;
headers: Record<string, string>;
requirements: PaymentRequirements;
};
type ProcessSettleFailureResponse = SettleResponse & {
success: false;
errorReason: string;
errorMessage?: string;
headers: Record<string, string>;
response: HTTPResponseInstructions;
};
type ProcessSettleResultResponse = ProcessSettleSuccessResponse | ProcessSettleFailureResponse;
/**
* Represents a validation error for a specific route's payment configuration.
*/
interface RouteValidationError {
/** The route pattern (e.g., "GET /api/weather") */
routePattern: string;
/** The payment scheme that failed validation */
scheme: string;
/** The network that failed validation */
network: Network;
/** The type of validation failure */
reason: "missing_scheme" | "missing_facilitator";
/** Human-readable error message */
message: string;
}
/**
* Error thrown when route configuration validation fails.
*/
declare class RouteConfigurationError extends Error {
/** The validation errors that caused this exception */
readonly errors: RouteValidationError[];
/**
* Creates a new RouteConfigurationError with the given validation errors.
*
* @param errors - The validation errors that caused this exception.
*/
constructor(errors: RouteValidationError[]);
}
/**
* HTTP-enhanced x402 resource server
* Provides framework-agnostic HTTP protocol handling
*/
declare class x402HTTPResourceServer {
private ResourceServer;
private compiledRoutes;
private routesConfig;
private paywallProvider?;
private protectedRequestHooks;
/**
* Creates a new x402HTTPResourceServer instance.
*
* @param ResourceServer - The core x402ResourceServer instance to use
* @param routes - Route configuration for payment-protected endpoints
*/
constructor(ResourceServer: x402ResourceServer, routes: RoutesConfig);
/**
* Get the underlying x402ResourceServer instance.
*
* @returns The underlying x402ResourceServer instance
*/
get server(): x402ResourceServer;
/**
* Get the routes configuration.
*
* @returns The routes configuration
*/
get routes(): 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();
* ```
*/
initialize(): Promise<void>;
/**
* Register a custom paywall provider for generating HTML
*
* @param provider - PaywallProvider instance
* @returns This service instance for chaining
*/
registerPaywallProvider(provider: PaywallProvider): 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: ProtectedRequestHook): 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
*/
processHTTPRequest(context: HTTPRequestContext, paywallConfig?: PaywallConfig): Promise<HTTPProcessResult>;
/**
* 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)
* @param transportContext - Optional HTTP transport context
* @param settlementOverrides - Optional settlement overrides (e.g., partial settlement amount)
* @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
*/
processSettlement(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: HTTPTransportContext, settlementOverrides?: SettlementOverrides): Promise<ProcessSettleResultResponse>;
/**
* 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: HTTPRequestContext): boolean;
/**
* Settle a verified payment that requested `skipHandler`, packaging the
* result as a `payment-error` HTTPProcessResult so framework adapters can
* write the response without invoking the route handler.
*
* - On success: status 200 + PAYMENT-RESPONSE header + configured body.
* - On failure: the standard 402 settlement-failure response.
*
* @param paymentPayload - Verified payment payload.
* @param requirements - Matched payment requirements.
* @param declaredExtensions - Optional declared extensions for the route.
* @param transportContext - Optional HTTP transport context.
* @param skipHandlerResponse - Optional content type + body to return on success.
* @returns A `payment-error` HTTPProcessResult carrying the final response.
*/
private processSkipHandlerSettlement;
/**
* Build HTTPResponseInstructions for settlement failure.
* Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
*
* @param failure - Settlement failure result with headers
* @param transportContext - Optional HTTP transport context for the request
* @returns HTTP response instructions for the 402 settlement failure response
*/
private buildSettlementFailureResponse;
/**
* 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
*/
private normalizePaymentOptions;
/**
* 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)
*/
private validateRouteConfiguration;
/**
* Get route configuration for a request
*
* @param path - Request path
* @param method - HTTP method
* @returns Route configuration and pattern, or undefined if no match
*/
private getRouteConfig;
/**
* Extract payment from HTTP headers (handles v1 and v2)
*
* @param adapter - HTTP adapter
* @returns Decoded payment payload or null
*/
private extractPayment;
/**
* Check if request is from a web browser
*
* @param adapter - HTTP adapter
* @returns True if request appears to be from a browser
*/
private isWebBrowser;
/**
* 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
*/
private createHTTPResponse;
/**
* 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
*/
private createHTTPPaymentRequiredResponse;
/**
* Create settlement response headers
*
* @param settleResponse - Settlement response
* @returns Headers to add to response
*/
private createSettlementHeaders;
/**
* Parse route pattern into verb and regex
*
* @param pattern - Route pattern like "GET /api/*", "/api/[id]", or "/api/:id"
* @returns Parsed pattern with verb and regex
*/
private parseRoutePattern;
/**
* Normalize path for matching
*
* @param path - Raw path from request
* @returns Normalized path
*/
private normalizePath;
/**
* 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
*/
private generatePaywallHTML;
/**
* Extract display amount from payment requirements.
* Uses the registered scheme's decimal precision for the asset, falling back to 6.
*
* @param paymentRequired - The payment required object
* @returns The display amount in decimal format
*/
private getDisplayAmount;
}
export { type CompiledRoute as C, type DynamicPayTo as D, type HTTPAdapter as H, type PaywallConfig as P, type RouteConfig as R, type SettlementFailedResponseBody as S, type UnpaidResponseBody as U, type HTTPRequestContext as a, type HTTPTransportContext as b, type HTTPResponseInstructions as c, type HTTPProcessResult as d, type PaywallProvider as e, type PaymentOption as f, type RoutesConfig as g, type DynamicPrice as h, type HTTPResponseBody as i, type ProcessSettleResultResponse as j, type ProcessSettleSuccessResponse as k, type ProcessSettleFailureResponse as l, type RouteValidationError as m, RouteConfigurationError as n, type ProtectedRequestHook as o, SETTLEMENT_OVERRIDES_HEADER as p, checkIfBazaarNeeded as q, x402HTTPResourceServer as x };
// 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 failure 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;
}
};
var FacilitatorResponseError = class extends Error {
/**
* Creates a FacilitatorResponseError for malformed facilitator responses.
*
* @param message - The boundary error message
*/
constructor(message) {
super(message);
this.name = "FacilitatorResponseError";
}
};
function getFacilitatorResponseError(error) {
let current = error;
while (current instanceof Error) {
if (current instanceof FacilitatorResponseError) {
return current;
}
current = current.cause;
}
return null;
}
export {
VerifyError,
SettleError,
FacilitatorResponseError,
getFacilitatorResponseError
};
//# sourceMappingURL=chunk-AGOUMC4P.mjs.map
{"version":3,"sources":["../../src/types/facilitator.ts"],"sourcesContent":["import { PaymentPayload, PaymentRequirements } from \"./payments\";\nimport { Network } from \"./\";\n\nexport type VerifyRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type VerifyResponse = {\n isValid: boolean;\n invalidReason?: string;\n invalidMessage?: string;\n payer?: string;\n extensions?: Record<string, unknown>;\n extra?: Record<string, unknown>;\n};\n\nexport type SettleRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type SettleResponse = {\n success: boolean;\n errorReason?: string;\n errorMessage?: string;\n payer?: string;\n transaction: string;\n network: Network;\n /** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */\n amount?: string;\n extensions?: Record<string, unknown>;\n extra?: Record<string, unknown>;\n};\n\nexport type SupportedKind = {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n};\n\nexport type SupportedResponse = {\n kinds: SupportedKind[];\n extensions: string[];\n signers: Record<string, string[]>; // CAIP family pattern → Signer addresses\n};\n\n/**\n * Error thrown when payment verification fails.\n */\nexport class VerifyError extends Error {\n readonly invalidReason?: string;\n readonly invalidMessage?: string;\n readonly payer?: string;\n readonly statusCode: number;\n\n /**\n * Creates a VerifyError from a failed verification response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The verify response containing failure details\n */\n constructor(statusCode: number, response: VerifyResponse) {\n const reason = response.invalidReason || \"unknown reason\";\n const message = response.invalidMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"VerifyError\";\n this.statusCode = statusCode;\n this.invalidReason = response.invalidReason;\n this.invalidMessage = response.invalidMessage;\n this.payer = response.payer;\n }\n}\n\n/**\n * Error thrown when payment settlement fails.\n */\nexport class SettleError extends Error {\n readonly errorReason?: string;\n readonly errorMessage?: string;\n readonly payer?: string;\n readonly transaction: string;\n readonly network: Network;\n readonly statusCode: number;\n\n /**\n * Creates a SettleError from a failed settlement response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The settle response containing error details\n */\n constructor(statusCode: number, response: SettleResponse) {\n const reason = response.errorReason || \"unknown reason\";\n const message = response.errorMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"SettleError\";\n this.statusCode = statusCode;\n this.errorReason = response.errorReason;\n this.errorMessage = response.errorMessage;\n this.payer = response.payer;\n this.transaction = response.transaction;\n this.network = response.network;\n }\n}\n\n/**\n * Error thrown when a facilitator returns malformed success payload data.\n */\nexport class FacilitatorResponseError extends Error {\n /**\n * Creates a FacilitatorResponseError for malformed facilitator responses.\n *\n * @param message - The boundary error message\n */\n constructor(message: string) {\n super(message);\n this.name = \"FacilitatorResponseError\";\n }\n}\n\n/**\n * Walks an error cause chain to find the first facilitator response error.\n *\n * @param error - The thrown value to inspect\n * @returns The nested facilitator response error, if present\n */\nexport function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null {\n let current = error;\n\n while (current instanceof Error) {\n if (current instanceof FacilitatorResponseError) {\n return current;\n }\n current = current.cause;\n }\n\n return null;\n}\n"],"mappings":";AAqDO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,iBAAiB;AACzC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,gBAAgB,SAAS;AAC9B,SAAK,iBAAiB,SAAS;AAC/B,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAKO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,eAAe;AACvC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,cAAc,SAAS;AAC5B,SAAK,eAAe,SAAS;AAC7B,SAAK,QAAQ,SAAS;AACtB,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,SAAS;AAAA,EAC1B;AACF;AAKO,IAAM,2BAAN,cAAuC,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAQO,SAAS,4BAA4B,OAAiD;AAC3F,MAAI,UAAU;AAEd,SAAO,mBAAmB,OAAO;AAC/B,QAAI,mBAAmB,0BAA0B;AAC/C,aAAO;AAAA,IACT;AACA,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;","names":[]}
// src/schemas/index.ts
import { z } from "zod";
import { z as z2 } from "zod";
var NonEmptyString = z.string().min(1);
var Any = z.record(z.unknown());
var OptionalAny = z.record(z.unknown()).optional().nullable();
var NetworkSchemaV1 = NonEmptyString;
var NetworkSchemaV2 = z.string().min(3).refine((val) => val.includes(":"), {
message: "Network must be in CAIP-2 format (e.g., 'eip155:84532')"
});
var NetworkSchema = z.union([NetworkSchemaV1, NetworkSchemaV2]);
var PRINTABLE_ASCII_REGEX = /^[\x20-\x7e]+$/;
var ResourceInfoSchema = z.object({
url: NonEmptyString,
description: z.string().optional(),
mimeType: z.string().optional(),
serviceName: z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX).optional(),
tags: z.array(z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX)).max(5).optional(),
iconUrl: z.string().max(2048).optional()
});
var PaymentRequirementsV1Schema = z.object({
scheme: NonEmptyString,
network: NetworkSchemaV1,
maxAmountRequired: NonEmptyString,
resource: NonEmptyString,
// URL string in V1
description: z.string(),
mimeType: z.string().optional(),
outputSchema: Any.optional().nullable(),
payTo: NonEmptyString,
maxTimeoutSeconds: z.number().positive(),
asset: NonEmptyString,
extra: OptionalAny
});
var PaymentRequiredV1Schema = z.object({
x402Version: z.literal(1),
error: z.string().optional(),
accepts: z.array(PaymentRequirementsV1Schema).min(1)
});
var PaymentPayloadV1Schema = z.object({
x402Version: z.literal(1),
scheme: NonEmptyString,
network: NetworkSchemaV1,
payload: Any
});
var PaymentRequirementsV2Schema = z.object({
scheme: NonEmptyString,
network: NetworkSchemaV2,
amount: NonEmptyString,
asset: NonEmptyString,
payTo: NonEmptyString,
maxTimeoutSeconds: z.number().positive(),
extra: OptionalAny
});
var PaymentRequiredV2Schema = z.object({
x402Version: z.literal(2),
error: z.string().optional(),
resource: ResourceInfoSchema,
accepts: z.array(PaymentRequirementsV2Schema).min(1),
extensions: OptionalAny
});
var PaymentPayloadV2Schema = z.object({
x402Version: z.literal(2),
resource: ResourceInfoSchema.optional(),
accepted: PaymentRequirementsV2Schema,
payload: Any,
extensions: OptionalAny
});
var PaymentRequirementsSchema = z.union([
PaymentRequirementsV1Schema,
PaymentRequirementsV2Schema
]);
var PaymentRequiredSchema = z.discriminatedUnion("x402Version", [
PaymentRequiredV1Schema,
PaymentRequiredV2Schema
]);
var PaymentPayloadSchema = z.discriminatedUnion("x402Version", [
PaymentPayloadV1Schema,
PaymentPayloadV2Schema
]);
function parsePaymentRequired(value) {
return PaymentRequiredSchema.safeParse(value);
}
function validatePaymentRequired(value) {
return PaymentRequiredSchema.parse(value);
}
function isPaymentRequired(value) {
return PaymentRequiredSchema.safeParse(value).success;
}
function parsePaymentRequirements(value) {
return PaymentRequirementsSchema.safeParse(value);
}
function validatePaymentRequirements(value) {
return PaymentRequirementsSchema.parse(value);
}
function isPaymentRequirements(value) {
return PaymentRequirementsSchema.safeParse(value).success;
}
function parsePaymentPayload(value) {
return PaymentPayloadSchema.safeParse(value);
}
function validatePaymentPayload(value) {
return PaymentPayloadSchema.parse(value);
}
function isPaymentPayload(value) {
return PaymentPayloadSchema.safeParse(value).success;
}
function isPaymentRequiredV1(value) {
return PaymentRequiredV1Schema.safeParse(value).success;
}
function isPaymentRequiredV2(value) {
return PaymentRequiredV2Schema.safeParse(value).success;
}
function isPaymentRequirementsV1(value) {
return PaymentRequirementsV1Schema.safeParse(value).success;
}
function isPaymentRequirementsV2(value) {
return PaymentRequirementsV2Schema.safeParse(value).success;
}
function isPaymentPayloadV1(value) {
return PaymentPayloadV1Schema.safeParse(value).success;
}
function isPaymentPayloadV2(value) {
return PaymentPayloadV2Schema.safeParse(value).success;
}
export {
NonEmptyString,
Any,
OptionalAny,
NetworkSchemaV1,
NetworkSchemaV2,
NetworkSchema,
ResourceInfoSchema,
PaymentRequirementsV1Schema,
PaymentRequiredV1Schema,
PaymentPayloadV1Schema,
PaymentRequirementsV2Schema,
PaymentRequiredV2Schema,
PaymentPayloadV2Schema,
PaymentRequirementsSchema,
PaymentRequiredSchema,
PaymentPayloadSchema,
parsePaymentRequired,
validatePaymentRequired,
isPaymentRequired,
parsePaymentRequirements,
validatePaymentRequirements,
isPaymentRequirements,
parsePaymentPayload,
validatePaymentPayload,
isPaymentPayload,
isPaymentRequiredV1,
isPaymentRequiredV2,
isPaymentRequirementsV1,
isPaymentRequirementsV2,
isPaymentPayloadV1,
isPaymentPayloadV2,
z2 as z
};
//# sourceMappingURL=chunk-FPXAE3OS.mjs.map
{"version":3,"sources":["../../src/schemas/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ============================================================================\n// Reusable Primitive Schemas\n// ============================================================================\n\n/**\n * Non-empty string schema - a string with at least one character.\n * Used for required string fields that cannot be empty.\n */\nexport const NonEmptyString = z.string().min(1);\nexport type NonEmptyString = z.infer<typeof NonEmptyString>;\n\n/**\n * Any record schema - an object with unknown keys and values.\n * Used for scheme-specific payloads and other extensible objects.\n */\nexport const Any = z.record(z.unknown());\nexport type Any = z.infer<typeof Any>;\n\n/**\n * Optional any record schema - an optional object with unknown keys and values.\n * Used for optional extension fields like `extra` and `extensions`.\n */\nexport const OptionalAny = z.record(z.unknown()).optional().nullable();\nexport type OptionalAny = z.infer<typeof OptionalAny>;\n\n// ============================================================================\n// Network Schemas\n// ============================================================================\n\n/**\n * Network identifier schema for V1 - loose validation.\n * V1 accepts any non-empty string for backwards compatibility.\n */\nexport const NetworkSchemaV1 = NonEmptyString;\nexport type NetworkV1 = z.infer<typeof NetworkSchemaV1>;\n\n/**\n * Network identifier schema for V2 - CAIP-2 format validation.\n * V2 requires minimum length of 3 and a colon separator (e.g., \"eip155:84532\", \"solana:devnet\").\n */\nexport const NetworkSchemaV2 = z\n .string()\n .min(3)\n .refine(val => val.includes(\":\"), {\n message: \"Network must be in CAIP-2 format (e.g., 'eip155:84532')\",\n });\nexport type NetworkV2 = z.infer<typeof NetworkSchemaV2>;\n\n/**\n * Union network schema - accepts either V1 or V2 format.\n */\nexport const NetworkSchema = z.union([NetworkSchemaV1, NetworkSchemaV2]);\nexport type Network = z.infer<typeof NetworkSchema>;\n\n// ============================================================================\n// Shared Schemas\n// ============================================================================\n\n/**\n * ResourceInfo schema for V2 - describes the protected resource.\n */\n// Printable ASCII (U+0020–U+007E) — matches the bazaar-facilitator\n// `isValidServiceName` / `sanitizeTags` regex. Constraining to ASCII keeps\n// the length cap consistent across TS / Python / Go (where String.length /\n// len() / len() otherwise diverge for multi-byte input).\nconst PRINTABLE_ASCII_REGEX = /^[\\x20-\\x7e]+$/;\n\nexport const ResourceInfoSchema = z.object({\n url: NonEmptyString,\n description: z.string().optional(),\n mimeType: z.string().optional(),\n serviceName: z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX).optional(),\n tags: z.array(z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX)).max(5).optional(),\n iconUrl: z.string().max(2048).optional(),\n});\nexport type ResourceInfo = z.infer<typeof ResourceInfoSchema>;\n\n// ============================================================================\n// V1 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V1.\n * V1 includes resource info directly in the requirements object.\n */\nexport const PaymentRequirementsV1Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n maxAmountRequired: NonEmptyString,\n resource: NonEmptyString, // URL string in V1\n description: z.string(),\n mimeType: z.string().optional(),\n outputSchema: Any.optional().nullable(),\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n asset: NonEmptyString,\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV1 = z.infer<typeof PaymentRequirementsV1Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V1.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV1Schema = z.object({\n x402Version: z.literal(1),\n error: z.string().optional(),\n accepts: z.array(PaymentRequirementsV1Schema).min(1),\n});\nexport type PaymentRequiredV1 = z.infer<typeof PaymentRequiredV1Schema>;\n\n/**\n * PaymentPayload schema for V1.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV1Schema = z.object({\n x402Version: z.literal(1),\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n payload: Any,\n});\nexport type PaymentPayloadV1 = z.infer<typeof PaymentPayloadV1Schema>;\n\n// ============================================================================\n// V2 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V2.\n * V2 uses \"amount\" instead of \"maxAmountRequired\" and doesn't include resource info.\n */\nexport const PaymentRequirementsV2Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV2,\n amount: NonEmptyString,\n asset: NonEmptyString,\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV2 = z.infer<typeof PaymentRequirementsV2Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V2.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV2Schema = z.object({\n x402Version: z.literal(2),\n error: z.string().optional(),\n resource: ResourceInfoSchema,\n accepts: z.array(PaymentRequirementsV2Schema).min(1),\n extensions: OptionalAny,\n});\nexport type PaymentRequiredV2 = z.infer<typeof PaymentRequiredV2Schema>;\n\n/**\n * PaymentPayload schema for V2.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV2Schema = z.object({\n x402Version: z.literal(2),\n resource: ResourceInfoSchema.optional(),\n accepted: PaymentRequirementsV2Schema,\n payload: Any,\n extensions: OptionalAny,\n});\nexport type PaymentPayloadV2 = z.infer<typeof PaymentPayloadV2Schema>;\n\n// ============================================================================\n// Union Schemas (V1 | V2)\n// ============================================================================\n\n/**\n * PaymentRequirements union schema - accepts either V1 or V2 format.\n * Use this when you need to handle both versions.\n */\nexport const PaymentRequirementsSchema = z.union([\n PaymentRequirementsV1Schema,\n PaymentRequirementsV2Schema,\n]);\nexport type PaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;\n\n/**\n * PaymentRequired union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentRequiredSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentRequiredV1Schema,\n PaymentRequiredV2Schema,\n]);\nexport type PaymentRequired = z.infer<typeof PaymentRequiredSchema>;\n\n/**\n * PaymentPayload union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentPayloadSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentPayloadV1Schema,\n PaymentPayloadV2Schema,\n]);\nexport type PaymentPayload = z.infer<typeof PaymentPayloadSchema>;\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n/**\n * Validates a PaymentRequired object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequired(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequired> {\n return PaymentRequiredSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequired object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequired\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequired(value: unknown): PaymentRequired {\n return PaymentRequiredSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequired (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequired\n */\nexport function isPaymentRequired(value: unknown): value is PaymentRequired {\n return PaymentRequiredSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentRequirements object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequirements(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequirements> {\n return PaymentRequirementsSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequirements object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequirements\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequirements(value: unknown): PaymentRequirements {\n return PaymentRequirementsSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequirements (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirements\n */\nexport function isPaymentRequirements(value: unknown): value is PaymentRequirements {\n return PaymentRequirementsSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentPayload object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentPayload(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentPayload> {\n return PaymentPayloadSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentPayload object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentPayload\n * @throws ZodError if validation fails\n */\nexport function validatePaymentPayload(value: unknown): PaymentPayload {\n return PaymentPayloadSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentPayload (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayload\n */\nexport function isPaymentPayload(value: unknown): value is PaymentPayload {\n return PaymentPayloadSchema.safeParse(value).success;\n}\n\n// ============================================================================\n// Version-Specific Type Guards\n// ============================================================================\n\n/**\n * Type guard for PaymentRequiredV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV1\n */\nexport function isPaymentRequiredV1(value: unknown): value is PaymentRequiredV1 {\n return PaymentRequiredV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequiredV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV2\n */\nexport function isPaymentRequiredV2(value: unknown): value is PaymentRequiredV2 {\n return PaymentRequiredV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV1\n */\nexport function isPaymentRequirementsV1(value: unknown): value is PaymentRequirementsV1 {\n return PaymentRequirementsV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV2\n */\nexport function isPaymentRequirementsV2(value: unknown): value is PaymentRequirementsV2 {\n return PaymentRequirementsV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV1\n */\nexport function isPaymentPayloadV1(value: unknown): value is PaymentPayloadV1 {\n return PaymentPayloadV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV2\n */\nexport function isPaymentPayloadV2(value: unknown): value is PaymentPayloadV2 {\n return PaymentPayloadV2Schema.safeParse(value).success;\n}\n\n// ============================================================================\n// Re-export zod for convenience\n// ============================================================================\n\nexport { z } from \"zod\";\n"],"mappings":"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","names":["z"]}
import {
z
} from "./chunk-FPXAE3OS.mjs";
import {
x402Version
} from "./chunk-VE37GDG2.mjs";
import {
FacilitatorResponseError,
SettleError,
VerifyError
} from "./chunk-AGOUMC4P.mjs";
import {
Base64EncodedRegex,
safeBase64Decode,
safeBase64Encode
} from "./chunk-4BKQ2IT7.mjs";
import {
__require
} from "./chunk-BJTO5JO5.mjs";
// src/http/x402HTTPResourceServer.ts
var SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
function checkIfBazaarNeeded(routes) {
if ("accepts" in routes) {
return !!(routes.extensions && "bazaar" in routes.extensions);
}
return Object.values(routes).some((routeConfig) => {
return !!(routeConfig.extensions && "bazaar" in routeConfig.extensions);
});
}
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,
pattern: parsed.path
});
}
}
/**
* 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 method = context.method || context.adapter.getMethod();
context = { ...context, method };
const { adapter, path } = context;
const routeMatch = this.getRouteConfig(path, method);
if (!routeMatch) {
return { type: "no-payment-required" };
}
const { config: routeConfig, pattern: routePattern } = routeMatch;
const enrichedContext = { ...context, routePattern };
for (const hook of this.protectedRequestHooks) {
const result = await hook(enrichedContext, 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 || enrichedContext.adapter.getUrl(),
description: routeConfig.description || "",
mimeType: routeConfig.mimeType || ""
};
let requirements = await this.ResourceServer.buildPaymentRequirementsFromOptions(
paymentOptions,
enrichedContext
);
let extensions = routeConfig.extensions;
if (extensions) {
extensions = this.ResourceServer.enrichExtensions(extensions, enrichedContext);
}
const transportContext = { request: enrichedContext };
const paymentRequired = await this.ResourceServer.createPaymentRequiredResponse(
requirements,
resourceInfo,
!paymentPayload ? "Payment required" : void 0,
extensions,
transportContext
);
if (!paymentPayload) {
const unpaidBody = routeConfig.unpaidResponseBody ? await routeConfig.unpaidResponseBody(enrichedContext) : 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",
extensions ?? {},
transportContext
);
return {
type: "payment-error",
response: this.createHTTPResponse(errorResponse, false, paywallConfig)
};
}
const verifyResult = await this.ResourceServer.verifyPayment(
paymentPayload,
matchingRequirements,
extensions ?? {},
transportContext
);
if (!verifyResult.isValid) {
const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
requirements,
resourceInfo,
verifyResult.invalidReason,
extensions ?? {},
transportContext,
paymentPayload
);
return {
type: "payment-error",
response: this.createHTTPResponse(errorResponse, false, paywallConfig)
};
}
if (verifyResult.skipHandler) {
return await this.processSkipHandlerSettlement(
paymentPayload,
matchingRequirements,
extensions ?? {},
transportContext,
verifyResult.skipHandler
);
}
const cancellationDispatcher = this.ResourceServer.createPaymentCancellationDispatcher(
paymentPayload,
matchingRequirements,
extensions ?? {},
transportContext
);
return {
type: "payment-verified",
cancellationDispatcher,
paymentPayload,
paymentRequirements: matchingRequirements,
declaredExtensions: extensions ?? {}
};
} catch (error) {
if (error instanceof FacilitatorResponseError) {
throw error;
}
const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
requirements,
resourceInfo,
error instanceof Error ? error.message : "Payment verification failed",
extensions ?? {},
transportContext
);
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)
* @param transportContext - Optional HTTP transport context
* @param settlementOverrides - Optional settlement overrides (e.g., partial settlement amount)
* @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
*/
async processSettlement(paymentPayload, requirements, declaredExtensions, transportContext, settlementOverrides) {
if (transportContext?.request && !transportContext.request.method) {
transportContext = {
...transportContext,
request: {
...transportContext.request,
method: transportContext.request.adapter.getMethod()
}
};
}
try {
let resolvedOverrides = settlementOverrides;
if (!resolvedOverrides && transportContext?.responseHeaders) {
const overridesKey = SETTLEMENT_OVERRIDES_HEADER.toLowerCase();
const rawValue = Object.entries(transportContext.responseHeaders).find(
([key]) => key.toLowerCase() === overridesKey
)?.[1];
if (rawValue) {
try {
resolvedOverrides = JSON.parse(rawValue);
} catch {
}
}
}
const settleResponse = await this.ResourceServer.settlePayment(
paymentPayload,
requirements,
declaredExtensions,
transportContext,
resolvedOverrides
);
if (!settleResponse.success) {
const failure = {
...settleResponse,
success: false,
errorReason: settleResponse.errorReason || "Settlement failed",
errorMessage: settleResponse.errorMessage || settleResponse.errorReason || "Settlement failed",
headers: this.createSettlementHeaders(settleResponse)
};
const response = await this.buildSettlementFailureResponse(failure, transportContext);
return { ...failure, response };
}
return {
...settleResponse,
success: true,
headers: this.createSettlementHeaders(settleResponse),
requirements
};
} catch (error) {
if (error instanceof FacilitatorResponseError) {
throw error;
}
if (error instanceof SettleError) {
const errorReason2 = error.errorReason || error.message;
const settleResponse2 = {
success: false,
errorReason: errorReason2,
errorMessage: error.errorMessage || errorReason2,
payer: error.payer,
network: error.network,
transaction: error.transaction
};
const failure2 = {
...settleResponse2,
success: false,
errorReason: errorReason2,
headers: this.createSettlementHeaders(settleResponse2)
};
const response2 = await this.buildSettlementFailureResponse(failure2, transportContext);
return { ...failure2, response: response2 };
}
const errorReason = error instanceof Error ? error.message : "Settlement failed";
const settleResponse = {
success: false,
errorReason,
errorMessage: errorReason,
network: requirements.network,
transaction: ""
};
const failure = {
...settleResponse,
success: false,
errorReason,
headers: this.createSettlementHeaders(settleResponse)
};
const response = await this.buildSettlementFailureResponse(failure, transportContext);
return { ...failure, response };
}
}
/**
* 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 method = context.method || context.adapter.getMethod();
return this.getRouteConfig(context.path, method) !== void 0;
}
/**
* Settle a verified payment that requested `skipHandler`, packaging the
* result as a `payment-error` HTTPProcessResult so framework adapters can
* write the response without invoking the route handler.
*
* - On success: status 200 + PAYMENT-RESPONSE header + configured body.
* - On failure: the standard 402 settlement-failure response.
*
* @param paymentPayload - Verified payment payload.
* @param requirements - Matched payment requirements.
* @param declaredExtensions - Optional declared extensions for the route.
* @param transportContext - Optional HTTP transport context.
* @param skipHandlerResponse - Optional content type + body to return on success.
* @returns A `payment-error` HTTPProcessResult carrying the final response.
*/
async processSkipHandlerSettlement(paymentPayload, requirements, declaredExtensions, transportContext, skipHandlerResponse) {
const settleResult = await this.processSettlement(
paymentPayload,
requirements,
declaredExtensions,
transportContext
);
if (!settleResult.success) {
return { type: "payment-error", response: settleResult.response };
}
const contentType = skipHandlerResponse?.contentType ?? "application/json";
const body = skipHandlerResponse?.body ?? {};
return {
type: "payment-error",
response: {
status: 200,
headers: {
"Content-Type": contentType,
...settleResult.headers
},
body,
isHtml: contentType.includes("text/html")
}
};
}
/**
* Build HTTPResponseInstructions for settlement failure.
* Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
*
* @param failure - Settlement failure result with headers
* @param transportContext - Optional HTTP transport context for the request
* @returns HTTP response instructions for the 402 settlement failure response
*/
async buildSettlementFailureResponse(failure, transportContext) {
const settlementHeaders = failure.headers;
const routeConfig = transportContext ? this.getRouteConfig(transportContext.request.path, transportContext.request.method) : void 0;
const customBody = routeConfig?.config.settlementFailedResponseBody ? await routeConfig.config.settlementFailedResponseBody(transportContext.request, failure) : void 0;
const contentType = customBody ? customBody.contentType : "application/json";
const body = customBody ? customBody.body : {};
return {
status: 402,
headers: {
"Content-Type": contentType,
...settlementHeaders
},
body,
isHtml: contentType.includes("text/html")
};
}
/**
* 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 pathPart = pattern.includes(" ") ? pattern.split(/\s+/)[1] : pattern;
if (pathPart && pathPart.includes("*") && config.extensions && "bazaar" in config.extensions) {
console.warn(
`[x402] Route "${pattern}": Wildcard (*) patterns with bazaar discovery extensions will auto-generate parameter names (var1, var2, ...). Consider using named parameters instead (e.g. /weather/:city) for better discovery metadata.`
);
}
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 and pattern, 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)
);
if (!matchingRoute) return void 0;
return { config: matchingRoute.config, pattern: matchingRoute.pattern };
}
/**
* 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/*", "/api/[id]", 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, "[^/]+").replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "[^/]+").replace(/\//g, "\\/")}$`,
"i"
);
return { verb: verb.toUpperCase(), regex, path };
}
/**
* 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);
const firstAccept = paymentRequired.accepts?.[0];
const decimals = firstAccept && "amount" in firstAccept ? this.ResourceServer.getAssetDecimalsForRequirements(firstAccept) : 6;
const safeDecimals = Math.min(Math.max(decimals, 0), 100);
const displayAmountText = parseFloat(displayAmount.toFixed(safeDecimals)).toString();
const assetLabel = typeof firstAccept?.extra?.name === "string" ? firstAccept.extra.name : firstAccept?.asset ? `...${firstAccept.asset.slice(-6)}` : "Token";
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> ${displayAmountText} ${assetLabel}</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.
* Uses the registered scheme's decimal precision for the asset, falling back to 6.
*
* @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) {
const decimals = this.ResourceServer.getAssetDecimalsForRequirements(firstReq);
return parseFloat(firstReq.amount) / 10 ** decimals;
}
}
return 0;
}
};
// src/http/httpFacilitatorClient.ts
var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
var GET_SUPPORTED_RETRIES = 3;
var GET_SUPPORTED_RETRY_DELAY_MS = 1e3;
var verifyResponseSchema = z.object({
isValid: z.boolean(),
invalidReason: z.string().nullish().transform((v) => v ?? void 0),
invalidMessage: z.string().nullish().transform((v) => v ?? void 0),
payer: z.string().nullish().transform((v) => v ?? void 0),
extensions: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0),
extra: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0)
});
var settleResponseSchema = z.object({
success: z.boolean(),
errorReason: z.string().nullish().transform((v) => v ?? void 0),
errorMessage: z.string().nullish().transform((v) => v ?? void 0),
payer: z.string().nullish().transform((v) => v ?? void 0),
transaction: z.string(),
network: z.custom((value) => typeof value === "string"),
amount: z.string().nullish().transform((v) => v ?? void 0),
extensions: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0),
extra: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0)
});
var supportedKindSchema = z.object({
x402Version: z.number(),
scheme: z.string(),
network: z.custom(
(value) => typeof value === "string"
),
extra: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0)
});
var supportedResponseSchema = z.object({
kinds: z.array(supportedKindSchema),
extensions: z.array(z.string()).default([]),
signers: z.record(z.string(), z.array(z.string())).default({})
});
function responseExcerpt(text, limit = 200) {
const compact = text.trim().replace(/\s+/g, " ");
if (!compact) {
return "<empty response>";
}
if (compact.length <= limit) {
return compact;
}
return `${compact.slice(0, limit - 3)}...`;
}
var EXTENSION_RESPONSE_LOG_FIELD_ALLOWLIST = ["status", "rejectedReason", "reason", "code"];
function logExtensionResponsesHeader(response) {
const header = response.headers.get("EXTENSION-RESPONSES");
if (!header) return;
try {
const decoded = JSON.parse(safeBase64Decode(header));
if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return;
const sanitized = {};
for (const [extensionKey, payload] of Object.entries(decoded)) {
const source = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
const filtered = {};
for (const key of EXTENSION_RESPONSE_LOG_FIELD_ALLOWLIST) {
if (source[key] !== void 0) {
filtered[key] = source[key];
}
}
sanitized[extensionKey] = filtered;
}
console.log(`[x402] extension responses: ${JSON.stringify(sanitized)}`);
} catch {
}
}
async function parseSuccessResponse(response, schema, operation) {
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new FacilitatorResponseError(
`Facilitator ${operation} returned invalid JSON: ${responseExcerpt(text)}`
);
}
const parsed = schema.safeParse(data);
if (!parsed.success) {
throw new FacilitatorResponseError(
`Facilitator ${operation} returned invalid data: ${responseExcerpt(text)}`
);
}
return parsed.data;
}
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).replace(/\/+$/, "");
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,
redirect: "follow",
body: JSON.stringify({
x402Version: paymentPayload.x402Version,
paymentPayload: this.toJsonSafe(paymentPayload),
paymentRequirements: this.toJsonSafe(paymentRequirements)
})
});
if (!response.ok) {
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new Error(`Facilitator verify failed (${response.status}): ${responseExcerpt(text)}`);
}
if (typeof data === "object" && data !== null && "isValid" in data) {
throw new VerifyError(response.status, data);
}
throw new Error(
`Facilitator verify failed (${response.status}): ${responseExcerpt(JSON.stringify(data))}`
);
}
const verifyResult = await parseSuccessResponse(response, verifyResponseSchema, "verify");
logExtensionResponsesHeader(response);
return verifyResult;
}
/**
* 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,
redirect: "follow",
body: JSON.stringify({
x402Version: paymentPayload.x402Version,
paymentPayload: this.toJsonSafe(paymentPayload),
paymentRequirements: this.toJsonSafe(paymentRequirements)
})
});
if (!response.ok) {
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new Error(`Facilitator settle failed (${response.status}): ${responseExcerpt(text)}`);
}
if (typeof data === "object" && data !== null && "success" in data) {
throw new SettleError(response.status, data);
}
throw new Error(
`Facilitator settle failed (${response.status}): ${responseExcerpt(JSON.stringify(data))}`
);
}
const settleResult = await parseSuccessResponse(response, settleResponseSchema, "settle");
logExtensionResponsesHeader(response);
return settleResult;
}
/**
* Get supported payment kinds and extensions from the facilitator.
* Retries with exponential backoff on 429 rate limit errors.
*
* @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 };
}
let lastError = null;
for (let attempt = 0; attempt < GET_SUPPORTED_RETRIES; attempt++) {
const response = await fetch(`${this.url}/supported`, {
method: "GET",
headers,
redirect: "follow"
});
if (response.ok) {
return parseSuccessResponse(response, supportedResponseSchema, "supported");
}
const errorText = await response.text().catch(() => response.statusText);
lastError = new Error(
`Facilitator getSupported failed (${response.status}): ${responseExcerpt(errorText)}`
);
if (response.status === 429 && attempt < GET_SUPPORTED_RETRIES - 1) {
const delay = GET_SUPPORTED_RETRY_DELAY_MS * Math.pow(2, attempt);
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
throw lastError;
}
throw lastError ?? new Error("Facilitator getSupported failed after retries");
}
/**
* 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);
}
/**
* Parses response headers into protocol types, fires payment response hooks,
* and returns whether a hook signaled recovery.
*
* Called by transport wrappers (fetch, axios) after the paid request completes.
*
* @param paymentPayload - The payload that was sent with the request
* @param getHeader - Function to retrieve a response header by name
* @param status - The HTTP status code of the response
* @returns Whether a hook recovered and the parsed settle response (if any)
*/
async processPaymentResult(paymentPayload, getHeader, status) {
const requirements = paymentPayload.accepted;
let settleResponse;
try {
settleResponse = this.getPaymentSettleResponse(getHeader);
} catch {
}
let paymentRequired;
if (!settleResponse && status === 402) {
try {
paymentRequired = this.getPaymentRequiredResponse(getHeader);
} catch {
}
}
const ctx = {
paymentPayload,
requirements,
...settleResponse ? { settleResponse } : {},
...paymentRequired ? { paymentRequired } : {}
};
const result = await this.client.handlePaymentResponse(ctx);
return { recovered: result?.recovered === true, settleResponse };
}
/**
* Parses a fetch Response into a discriminated `x402PaymentResult` for app-level convenience.
*
* @param response - The fetch Response to process
* @returns A discriminated union describing the payment outcome
*/
async processResponse(response) {
const getHeader = (name) => response.headers.get(name);
let settleResponse;
try {
settleResponse = this.getPaymentSettleResponse(getHeader);
} catch {
}
const contentType = response.headers.get("content-type") ?? "";
const body = contentType.includes("application/json") ? await response.json() : await response.text();
if (settleResponse && settleResponse.success) {
return { kind: "success", response, body, settleResponse };
}
if (settleResponse && !settleResponse.success) {
return { kind: "settle_failed", response, body, settleResponse };
}
if (response.status === 402) {
try {
const paymentRequired = this.getPaymentRequiredResponse(getHeader, body);
return { kind: "payment_required", response, paymentRequired };
} catch {
}
}
if (response.ok) {
return { kind: "passthrough", response, body };
}
return { kind: "error", response, status: response.status, body };
}
};
// 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));
}
export {
SETTLEMENT_OVERRIDES_HEADER,
checkIfBazaarNeeded,
RouteConfigurationError,
x402HTTPResourceServer,
HTTPFacilitatorClient,
encodePaymentSignatureHeader,
decodePaymentSignatureHeader,
encodePaymentRequiredHeader,
decodePaymentRequiredHeader,
encodePaymentResponseHeader,
decodePaymentResponseHeader,
x402HTTPClient
};
//# sourceMappingURL=chunk-FTDK7NUZ.mjs.map

Sorry, the diff of this file is too big to display

type PaymentRequirementsV1 = {
scheme: string;
network: Network;
maxAmountRequired: string;
resource: string;
description: string;
mimeType: string;
outputSchema: Record<string, unknown>;
payTo: string;
maxTimeoutSeconds: number;
asset: string;
extra: Record<string, unknown>;
};
type PaymentRequiredV1 = {
x402Version: 1;
error?: string;
accepts: PaymentRequirementsV1[];
};
type PaymentPayloadV1 = {
x402Version: 1;
scheme: string;
network: Network;
payload: Record<string, unknown>;
};
type VerifyRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleResponseV1 = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
};
type SupportedResponseV1 = {
kinds: {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
}[];
};
/**
* Recursive readonly for hook contexts so accidental in-place mutation is visible at compile time.
* (Runtime mutation is still possible via other references; see extension enrich validation.)
*/
type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends object ? {
readonly [K in keyof T]: DeepReadonly<T[K]>;
} : T;
interface FacilitatorConfig {
url?: string;
createAuthHeaders?: () => Promise<{
verify: Record<string, string>;
settle: Record<string, string>;
supported: Record<string, string>;
bazaar?: Record<string, string>;
}>;
}
/**
* Interface for facilitator clients
* Can be implemented for HTTP-based or local facilitators
*/
interface FacilitatorClient {
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
}
/**
* HTTP-based client for interacting with x402 facilitator services
* Handles HTTP communication with facilitator endpoints
*/
declare class HTTPFacilitatorClient implements FacilitatorClient {
readonly url: string;
private readonly _createAuthHeaders?;
/**
* Creates a new HTTPFacilitatorClient instance.
*
* @param config - Configuration options for the facilitator client
*/
constructor(config?: FacilitatorConfig);
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator.
* Retries with exponential backoff on 429 rate limit errors.
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
/**
* 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
*/
createAuthHeaders(path: string): Promise<{
headers: Record<string, string>;
}>;
/**
* 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
*/
private toJsonSafe;
}
/**
* Configuration for a protected resource
* Only contains payment-specific configuration, not resource metadata
*/
interface ResourceConfig {
scheme: string;
/**
* Payment recipient. Use a **vacant** value (`""` or whitespace-only) when an extension must
* fill `payTo` during `enrichPaymentRequiredResponse`; non-vacant values are **immutable** there
* so extensions cannot redirect funds to an arbitrary address.
*/
payTo: string;
price: Price;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Context for `enrichPaymentRequiredResponse`. Extensions may merge extension payload via the
* return value. In-place edits to `paymentRequiredResponse.accepts` are **allowlisted** only
* (see {@link assertAcceptsAllowlistedAfterExtensionEnrich}): `scheme`, `network`, and
* `maxTimeoutSeconds` are immutable; `payTo`, `amount`, and `asset` may change only when the
* baseline value was vacant; `extra` may add keys but must not change or remove baseline keys.
*/
interface PaymentRequiredContext {
requirements: PaymentRequirements[];
resourceInfo: ResourceInfo;
error?: string;
paymentRequiredResponse: PaymentRequired;
transportContext?: unknown;
}
/**
* Verify / settle lifecycle hook context: treat as **read-only** for core protocol fields.
* Control flow uses **abort** / **recover** return values only, not in-place mutation.
*/
interface VerifyContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface VerifyResultContext extends VerifyContext {
result: DeepReadonly<VerifyResponse>;
}
/**
* Optional acknowledgement body returned to the caller when an `AfterVerifyHook`
* requests that the resource handler be skipped for a self-contained operation
* (e.g. cooperative refund). Travels in-process only — never on the facilitator wire.
*/
interface SkipHandlerDirective {
contentType?: string;
body?: unknown;
}
type ResourceVerifyRespone = VerifyResponse & {
skipHandler?: SkipHandlerDirective;
};
interface VerifyFailureContext extends VerifyContext {
error: Error;
}
interface SettleContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface SettleResultContext extends SettleContext {
result: DeepReadonly<SettleResponse>;
}
interface SettleFailureContext extends SettleContext {
error: Error;
}
type VerifiedPaymentCancellationReason = "handler_threw" | "handler_failed";
interface VerifiedPaymentCanceledContext extends SettleContext {
reason: VerifiedPaymentCancellationReason;
error?: unknown;
responseStatus?: number;
}
interface VerifiedPaymentCancelOptions {
reason: VerifiedPaymentCancellationReason;
error?: unknown;
responseStatus?: number;
}
interface PaymentCancellationDispatcher {
cancel(options: VerifiedPaymentCancelOptions): Promise<void>;
}
type BeforeVerifyHook = (context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: VerifyResponse;
}>;
type AfterVerifyHook = (context: VerifyResultContext) => Promise<void | {
skipHandler: true;
response?: SkipHandlerDirective;
}>;
type OnVerifyFailureHook = (context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
type BeforeSettleHook = (context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: SettleResponse;
}>;
type AfterSettleHook = (context: SettleResultContext) => Promise<void>;
type OnSettleFailureHook = (context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
type OnVerifiedPaymentCanceledHook = (context: VerifiedPaymentCanceledContext) => Promise<void>;
/**
* Optional overrides for settlement parameters.
* Used to support partial settlement (e.g., upto scheme billing by actual usage).
*
* Note: Overriding the amount to a value different from the agreed-upon
* `PaymentRequirements.amount` is only valid in schemes that explicitly support
* partial settlement, such as the `upto` scheme. Using this with standard
* x402 schemes (e.g., `exact`) will likely cause settlement verification to fail.
*/
interface SettlementOverrides {
/**
* Amount to settle. Supports three formats:
*
* - **Raw atomic units** — e.g., `"1000"` settles exactly 1000 atomic units.
* - **Percent** — e.g., `"50%"` settles 50% of `PaymentRequirements.amount`.
* Supports up to two decimal places (e.g., `"33.33%"`). The result is floored
* to the nearest atomic unit.
* - **Dollar price** — e.g., `"$0.05"` converts a USD-denominated price to
* atomic units. Decimals are determined from the registered scheme's
* `getAssetDecimals` method, falling back to 6 (standard for USDC stablecoins).
* The result is rounded to the nearest atomic unit.
*
* The resolved amount must be <= the authorized maximum in `PaymentRequirements`.
*
* Note: Setting this to an amount other than `PaymentRequirements.amount` is
* only valid in schemes that support partial settlement, such as `upto`.
*/
amount?: string;
}
/**
* Core x402 protocol server for resource protection
* Transport-agnostic implementation of the x402 payment protocol
*/
declare class x402ResourceServer {
private facilitatorClients;
private registeredServerSchemes;
private schemeHookAdapters;
private supportedResponsesMap;
private facilitatorClientsMap;
private registeredExtensions;
private extensionHookAdapters;
private beforeVerifyHooks;
private afterVerifyHooks;
private onVerifyFailureHooks;
private beforeSettleHooks;
private afterSettleHooks;
private onSettleFailureHooks;
private onVerifiedPaymentCanceledHooks;
/**
* Creates a new x402ResourceServer instance.
*
* @param facilitatorClients - Optional facilitator client(s) for payment processing
*/
constructor(facilitatorClients?: FacilitatorClient | FacilitatorClient[]);
/**
* Register a scheme/network server implementation.
*
* @param network - The network identifier
* @param server - The scheme/network server implementation
* @returns The x402ResourceServer instance for chaining
*/
register(network: Network, server: SchemeNetworkServer): x402ResourceServer;
/**
* Check if a scheme is registered for a given network.
*
* @param network - The network identifier
* @param scheme - The payment scheme name
* @returns True if the scheme is registered for the network, false otherwise
*/
hasRegisteredScheme(network: Network, scheme: string): boolean;
/**
* Returns the decimal precision for the asset specified in the given payment requirements.
* Looks up the registered scheme for the network and delegates to its getAssetDecimals
* method if available. Falls back to 6 (standard for USDC stablecoins) when the scheme
* does not implement getAssetDecimals or is not registered.
*
* @param requirements - The payment requirements containing scheme, network, and asset
* @returns The number of decimal places for the asset
*/
getAssetDecimalsForRequirements(requirements: PaymentRequirements): number;
/**
* Registers a resource server extension (enrichment and optional verify/settle hooks).
* Re-registering the same key overwrites; omitting `hooks` removes adapter handles for that key.
*
* @param extension - Extension definition including `key` and optional `hooks`
* @returns This server instance for chaining
*/
registerExtension(extension: ResourceServerExtension): this;
/**
* Check if an extension is registered.
*
* @param key - The extension key
* @returns True if the extension is registered
*/
hasExtension(key: string): boolean;
/**
* Get all registered extensions.
*
* @returns Array of registered extensions
*/
getExtensions(): ResourceServerExtension[];
/**
* Enriches declared extensions using registered extension hooks.
*
* @param declaredExtensions - Extensions declared on the route
* @param transportContext - Transport-specific context (HTTP, A2A, MCP, etc.)
* @returns Enriched extensions map
*/
enrichExtensions(declaredExtensions: Record<string, unknown>, transportContext: unknown): Record<string, unknown>;
/**
* Register a hook to execute before payment verification.
* Can abort verification by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeVerify(hook: BeforeVerifyHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment verification.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterVerify(hook: AfterVerifyHook): x402ResourceServer;
/**
* Register a hook to execute when payment verification fails.
* Can recover from failure by returning { recovered: true, result: VerifyResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifyFailure(hook: OnVerifyFailureHook): x402ResourceServer;
/**
* Register a hook to execute before payment settlement.
* Can abort settlement by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeSettle(hook: BeforeSettleHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterSettle(hook: AfterSettleHook): x402ResourceServer;
/**
* Register a hook to execute when payment settlement fails.
* Can recover from failure by returning { recovered: true, result: SettleResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onSettleFailure(hook: OnSettleFailureHook): x402ResourceServer;
/**
* Register a hook to execute when verified payment work is canceled before settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifiedPaymentCanceled(hook: OnVerifiedPaymentCanceledHook): x402ResourceServer;
/**
* Initialize by fetching supported kinds from all facilitators
* Creates mappings for supported responses and facilitator clients
* Earlier facilitators in the array get precedence
*/
initialize(): Promise<void>;
/**
* Get supported kind for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The supported kind or undefined if not found
*/
getSupportedKind(x402Version: number, network: Network, scheme: string): SupportedKind | undefined;
/**
* Get facilitator extensions for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator extensions or empty array if not found
*/
getFacilitatorExtensions(x402Version: number, network: Network, scheme: string): string[];
/**
* Build payment requirements for a protected resource
*
* @param resourceConfig - Configuration for the protected resource
* @returns Array of payment requirements
*/
buildPaymentRequirements(resourceConfig: ResourceConfig): Promise<PaymentRequirements[]>;
/**
* Build payment requirements from multiple payment options
* This method handles resolving dynamic payTo/price functions and builds requirements for each option
*
* @param paymentOptions - Array of payment options to convert
* @param context - HTTP request context for resolving dynamic functions
* @returns Array of payment requirements (one per option)
*/
buildPaymentRequirementsFromOptions<TContext = unknown>(paymentOptions: Array<{
scheme: string;
payTo: string | ((context: TContext) => string | Promise<string>);
price: Price | ((context: TContext) => Price | Promise<Price>);
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}>, context: TContext): Promise<PaymentRequirements[]>;
/**
* Create a payment required response
*
* @param requirements - Payment requirements
* @param resourceInfo - Resource information
* @param error - Error message
* @param extensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request, MCP tool context)
* @param paymentPayload - Optional failed payment payload for response-time scheme enrichment
* @returns Payment required response object
*/
createPaymentRequiredResponse(requirements: PaymentRequirements[], resourceInfo: ResourceInfo, error?: string, extensions?: Record<string, unknown>, transportContext?: unknown, paymentPayload?: PaymentPayload): Promise<PaymentRequired>;
/**
* Verifies a payment against requirements, running manual and in-use extension hooks.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context (e.g. HTTP, MCP)
* @returns Facilitator verify outcome (optionally carrying a `skipHandler` directive),
* or abort/recovery as driven by hooks
*/
verifyPayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown): Promise<ResourceVerifyRespone>;
/**
* Create cancellation controls for a verified payment attempt.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context
* @returns Cancellation controls for the verified payment attempt
*/
createPaymentCancellationDispatcher(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown): PaymentCancellationDispatcher;
/**
* Settle a verified payment
*
* @param paymentPayload - The payment payload to settle
* @param requirements - The payment requirements
* @param declaredExtensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request/response, MCP tool context)
* @param settlementOverrides - Optional overrides for settlement parameters (e.g., partial settlement amount)
* @returns Settlement response
*/
settlePayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown, settlementOverrides?: SettlementOverrides): Promise<SettleResponse>;
/**
* Find matching payment requirements for a payment
*
* @param availableRequirements - Array of available payment requirements
* @param paymentPayload - The payment payload
* @returns Matching payment requirements or undefined
*/
findMatchingRequirements(availableRequirements: PaymentRequirements[], paymentPayload: PaymentPayload): PaymentRequirements | undefined;
/**
* Logs a warning when a manual or extension adapter lifecycle hook throws.
*
* @param phase - Lifecycle phase name (e.g. `beforeVerify`)
* @param label - Hook source label from {@link getLabeledHooks} (manual index or extension key)
* @param error - Thrown value or rejection reason
*/
private warnResourceServerHookFailure;
/**
* Logs a warning when a registered extension enrichment hook throws.
*
* @param extensionKey - Registered extension identifier
* @param hookName - Hook method name (e.g. `enrichDeclaration`)
* @param error - Thrown value or rejection reason
*/
private warnExtensionHookFailure;
/**
* Executes after-verify hooks for facilitator and hook-provided verify results.
*
* @param verifyResult - Verify response passed to after-verify hooks.
* @param context - Verify context shared with before-verify hooks.
* @param extensionKeysInUse - Declared extension keys for this request.
* @param matchedScheme - Scheme/network selected for this payment.
* @param matchedScheme.network - Matched payment network.
* @param matchedScheme.scheme - Matched payment scheme.
* @returns Verify response with any in-process skip handler directive.
*/
private runAfterVerifyHooks;
/**
* Runs response enrichment after settlement lifecycle hooks complete.
*
* @param settleResult - Mutable settlement result being returned to the caller
* @param context - Read-only hook context for enrichment callbacks
* @param declaredExtensions - Extension declarations present on this payment
* @param matchedScheme - Scheme/network selected for this settlement
* @param matchedScheme.network - Matched payment network
* @param matchedScheme.scheme - Matched payment scheme
*/
private enrichSettlementResponse;
/**
* Notify hooks that verified work ended before settlement.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param options - Cancellation reason and optional diagnostics
* @param fallbackTransportContext - Optional transport-specific context
*/
private dispatchVerifiedPaymentCanceled;
/**
* Manual hooks first, then the matched scheme adapter, then extension adapters for keys in use.
* Each entry carries a stable label for logging when a hook throws.
*
* @param phase - Hook slot (e.g. `beforeVerify`)
* @param extensionKeysInUse - Declared extension keys for this request
* @param matchedScheme - Scheme/network selected for this payment
* @param matchedScheme.network - Matched payment network
* @param matchedScheme.scheme - Matched payment scheme
* @returns Hooks in invocation order with source labels
*/
private getLabeledHooks;
/**
* Get facilitator client for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator client or undefined if not found
*/
private getFacilitatorClient;
}
interface FacilitatorExtension {
key: string;
}
/**
* Per-extension verify/settle hooks. Contexts are **read-only** for core protocol fields; use
* **abort** / **recover** return values instead of mutating `paymentPayload`, `requirements`, etc.
*/
interface ResourceServerExtensionHooks {
onBeforeVerify?: (declaration: unknown, context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: VerifyResponse;
}>;
onAfterVerify?: (declaration: unknown, context: VerifyResultContext) => Promise<void>;
onVerifyFailure?: (declaration: unknown, context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
onBeforeSettle?: (declaration: unknown, context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
} | {
skip: true;
result: SettleResponse;
}>;
onAfterSettle?: (declaration: unknown, context: SettleResultContext) => Promise<void>;
onSettleFailure?: (declaration: unknown, context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
onVerifiedPaymentCanceled?: (declaration: unknown, context: VerifiedPaymentCanceledContext) => Promise<void>;
}
interface ResourceServerExtension {
key: string;
enrichDeclaration?: (declaration: unknown, transportContext: unknown) => unknown;
/**
* Return value merges into `extensions[key]`. In-place edits to `accepts` are allowlisted only
* (see server `assertAcceptsAllowlistedAfterExtensionEnrich`): vacant `payTo` / `amount` / `asset`
* may be filled; locked values and `scheme` / `network` / `maxTimeoutSeconds` / baseline `extra`
* entries are immutable.
*/
enrichPaymentRequiredResponse?: (declaration: unknown, context: PaymentRequiredContext) => Promise<unknown>;
/**
* Return value merges into `settleResult.extensions[key]`. Facilitator fields (`success`,
* `transaction`, `network`, etc.) must not be changed; only `extensions` is merged from the hook.
*/
enrichSettlementResponse?: (declaration: unknown, context: SettleResultContext) => Promise<unknown>;
/** Installed on `registerExtension`; runs only when `declaredExtensions[key]` is defined. */
hooks?: ResourceServerExtensionHooks;
}
type Network = `${string}:${string}`;
type Money = string | number;
type AssetAmount = {
asset: string;
amount: string;
extra?: Record<string, unknown>;
};
type Price = Money | AssetAmount;
interface ResourceInfo {
url: string;
description?: string;
mimeType?: string;
serviceName?: string;
tags?: string[];
iconUrl?: string;
}
type PaymentRequirements = {
scheme: string;
network: Network;
asset: string;
amount: string;
payTo: string;
maxTimeoutSeconds: number;
extra: Record<string, unknown>;
};
type PaymentRequired = {
x402Version: number;
error?: string;
resource: ResourceInfo;
accepts: PaymentRequirements[];
extensions?: Record<string, unknown>;
};
type PaymentPayload = {
x402Version: number;
resource?: ResourceInfo;
accepted: PaymentRequirements;
payload: Record<string, unknown>;
extensions?: Record<string, unknown>;
};
type VerifyRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type VerifyResponse = {
isValid: boolean;
invalidReason?: string;
invalidMessage?: string;
payer?: string;
extensions?: Record<string, unknown>;
extra?: Record<string, unknown>;
};
type SettleRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type SettleResponse = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
/** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */
amount?: string;
extensions?: Record<string, unknown>;
extra?: Record<string, unknown>;
};
type SupportedKind = {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
};
type SupportedResponse = {
kinds: SupportedKind[];
extensions: string[];
signers: Record<string, string[]>;
};
/**
* Error thrown when payment verification fails.
*/
declare class VerifyError extends Error {
readonly invalidReason?: string;
readonly invalidMessage?: string;
readonly payer?: string;
readonly statusCode: number;
/**
* Creates a VerifyError from a failed verification response.
*
* @param statusCode - HTTP status code from the facilitator
* @param response - The verify response containing failure details
*/
constructor(statusCode: number, response: VerifyResponse);
}
/**
* Error thrown when payment settlement fails.
*/
declare class SettleError extends Error {
readonly errorReason?: string;
readonly errorMessage?: string;
readonly payer?: string;
readonly transaction: string;
readonly network: Network;
readonly statusCode: number;
/**
* 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: number, response: SettleResponse);
}
/**
* Error thrown when a facilitator returns malformed success payload data.
*/
declare class FacilitatorResponseError extends Error {
/**
* Creates a FacilitatorResponseError for malformed facilitator responses.
*
* @param message - The boundary error message
*/
constructor(message: string);
}
/**
* Walks an error cause chain to find the first facilitator response error.
*
* @param error - The thrown value to inspect
* @returns The nested facilitator response error, if present
*/
declare function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null;
/**
* Money parser function that converts a numeric amount to an AssetAmount
* Receives the amount as a decimal number (e.g., 1.50 for $1.50)
* Returns null to indicate "cannot handle this amount", causing fallback to next parser
* Always returns a Promise for consistency - use async/await
*
* @param amount - The decimal amount (e.g., 1.50)
* @param network - The network identifier for context
* @returns AssetAmount or null to try next parser
*/
type MoneyParser = (amount: number, network: Network) => Promise<AssetAmount | null>;
/**
* Result of createPaymentPayload - the core payload fields.
* Contains the x402 version, scheme-specific payload data, and optional extension data.
* Schemes may return extensions (e.g., EIP-2612 gas sponsoring) that get merged
* with server-declared extensions in the final PaymentPayload.
*/
type PaymentPayloadResult = Pick<PaymentPayload, "x402Version" | "payload"> & {
extensions?: Record<string, unknown>;
};
/**
* Context passed to scheme's createPaymentPayload for extensions awareness.
* Contains the server-declared extensions from PaymentRequired so the scheme
* can check which extensions are advertised and respond accordingly.
*/
interface PaymentPayloadContext {
extensions?: Record<string, unknown>;
}
interface SchemeClientHooks {
onBeforePaymentCreation?: BeforePaymentCreationHook;
onAfterPaymentCreation?: AfterPaymentCreationHook;
onPaymentCreationFailure?: OnPaymentCreationFailureHook;
onPaymentResponse?: OnPaymentResponseHook;
}
interface SchemeNetworkClient {
readonly scheme: string;
readonly schemeHooks?: SchemeClientHooks;
createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
}
/**
* Context passed to SchemeNetworkFacilitator.verify/settle, providing
* access to registered facilitator extensions. Mechanism implementations
* use this to retrieve extension-provided capabilities (e.g., a batch signer).
*/
interface FacilitatorContext {
getExtension<T extends FacilitatorExtension = FacilitatorExtension>(key: string): T | undefined;
}
interface SchemeNetworkFacilitator {
readonly scheme: string;
/**
* CAIP family pattern that this facilitator supports.
* Used to group signers by blockchain family in the supported response.
*
* @example
* // EVM facilitators
* readonly caipFamily = "eip155:*";
*
* @example
* // SVM facilitators
* readonly caipFamily = "solana:*";
*/
readonly caipFamily: string;
/**
* Get mechanism-specific extra data needed for the supported kinds endpoint.
* This method is called when building the facilitator's supported response.
*
* @param network - The network identifier for context
* @returns Extra data object or undefined if no extra data is needed
*
* @example
* // EVM schemes return undefined (no extra data needed)
* getExtra(network: Network): undefined {
* return undefined;
* }
*
* @example
* // SVM schemes return feePayer address
* getExtra(network: Network): Record<string, unknown> | undefined {
* return { feePayer: this.signer.address };
* }
*/
getExtra(network: Network): Record<string, unknown> | undefined;
/**
* Get signer addresses used by this facilitator for a given network.
* These are included in the supported response to help clients understand
* which addresses might sign/pay for transactions.
*
* Supports multiple addresses for load balancing, key rotation, and high availability.
*
* @param network - The network identifier
* @returns Array of signer addresses (wallet addresses, fee payer addresses, etc.)
*
* @example
* // EVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*
* @example
* // SVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*/
getSigners(network: string): string[];
verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
}
interface SchemeServerHooks {
onBeforeVerify?: BeforeVerifyHook;
onAfterVerify?: AfterVerifyHook;
onBeforeSettle?: BeforeSettleHook;
onAfterSettle?: AfterSettleHook;
onVerifyFailure?: OnVerifyFailureHook;
onSettleFailure?: OnSettleFailureHook;
onVerifiedPaymentCanceled?: OnVerifiedPaymentCanceledHook;
}
type SchemeEnrichSettlementPayloadHook = (ctx: SettleContext) => Promise<Record<string, unknown> | void>;
type SchemeEnrichSettlementResponseHook = (ctx: SettleResultContext) => Promise<Record<string, unknown> | void>;
interface SchemePaymentRequiredContext {
requirements: PaymentRequirements[];
paymentPayload?: DeepReadonly<PaymentPayload>;
resourceInfo: ResourceInfo;
error?: string;
paymentRequiredResponse: PaymentRequired;
transportContext?: unknown;
}
type SchemeEnrichPaymentRequiredResponseHook = (ctx: SchemePaymentRequiredContext) => Promise<PaymentRequirements[] | void>;
interface SchemeNetworkServer {
readonly scheme: string;
readonly schemeHooks?: SchemeServerHooks;
enrichPaymentRequiredResponse?: SchemeEnrichPaymentRequiredResponseHook;
enrichSettlementPayload?: SchemeEnrichSettlementPayloadHook;
enrichSettlementResponse?: SchemeEnrichSettlementResponseHook;
/**
* Convert a user-friendly price to the scheme's specific amount and asset format
* Always returns a Promise for consistency
*
* @param price - User-friendly price (e.g., "$0.10", "0.10", { amount: "100000", asset: "USDC" })
* @param network - The network identifier for context
* @returns Promise that resolves to the converted amount, asset identifier, and any extra metadata
*
* @example
* // For EVM networks with USDC:
* await parsePrice("$0.10", "eip155:8453") => { amount: "100000", asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
*
* // For custom schemes:
* await parsePrice("10 points", "custom:network") => { amount: "10", asset: "points" }
*/
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
/**
* Optional: Return the decimal precision of the asset for a given network.
* Used by `resolveSettlementOverrideAmount` to convert dollar-format overrides to atomic units.
* Defaults to 6 when not implemented.
*
* @param asset - The asset address or symbol
* @param network - The network identifier
* @returns Number of decimal places for the asset
*/
getAssetDecimals?(asset: string, network: Network): number;
/**
* Build payment requirements for this scheme/network combination
*
* @param paymentRequirements - Base payment requirements with amount/asset already set
* @param supportedKind - The supported kind from facilitator's /supported endpoint
* @param supportedKind.x402Version - The x402 version
* @param supportedKind.scheme - The payment scheme
* @param supportedKind.network - The network identifier
* @param supportedKind.extra - Optional extra metadata
* @param facilitatorExtensions - Extensions supported by the facilitator
* @returns Enhanced payment requirements ready to be sent to clients
*/
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: SupportedKind, facilitatorExtensions: string[]): Promise<PaymentRequirements>;
}
/**
* Client Hook Context Interfaces
*/
interface PaymentCreationContext {
paymentRequired: PaymentRequired;
selectedRequirements: PaymentRequirements;
}
interface PaymentCreatedContext extends PaymentCreationContext {
paymentPayload: PaymentPayload;
}
interface PaymentCreationFailureContext extends PaymentCreationContext {
error: Error;
}
/**
* Client Hook Type Definitions
*/
type BeforePaymentCreationHook = (context: PaymentCreationContext) => Promise<void | {
abort: true;
reason: string;
}>;
type AfterPaymentCreationHook = (context: PaymentCreatedContext) => Promise<void>;
type OnPaymentCreationFailureHook = (context: PaymentCreationFailureContext) => Promise<void | {
recovered: true;
payload: PaymentPayload;
}>;
/**
* Context provided to payment response hooks after the paid request completes.
*
* Discriminate by what's present:
* - `settleResponse` with `success: true` → settle succeeded
* - `settleResponse` with `success: false` → settle failed
* - `paymentRequired` (no `settleResponse`) → verify failed
* - `error` → transport or parse error
*/
interface PaymentResponseContext {
paymentPayload: PaymentPayload;
requirements: PaymentRequirements;
settleResponse?: SettleResponse;
paymentRequired?: PaymentRequired;
error?: Error;
}
/**
* Hook fired after a paid request completes.
* Return `{ recovered: true }` to signal the transport should retry with a fresh payload.
*/
type OnPaymentResponseHook = (ctx: PaymentResponseContext) => Promise<void | {
recovered: true;
}>;
type SelectPaymentRequirements = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements;
/**
* Extension that can enrich payment payloads on the client side.
*
* Client extensions are invoked after the scheme creates the base payment payload
* but before it is returned. This allows mechanism-specific logic (e.g., EVM EIP-2612
* permit signing) to enrich the payload's extensions data.
*/
interface ClientExtension {
/**
* Unique key identifying this extension (e.g., "eip2612GasSponsoring").
* Must match the extension key used in PaymentRequired.extensions.
*/
key: string;
/**
* Called after payload creation when the extension key is present in
* paymentRequired.extensions. Allows the extension to enrich the payload
* with extension-specific data (e.g., signing an EIP-2612 permit).
*
* @param paymentPayload - The payment payload to enrich
* @param paymentRequired - The original PaymentRequired response
* @returns The enriched payment payload
*/
enrichPaymentPayload?: (paymentPayload: PaymentPayload, paymentRequired: PaymentRequired) => Promise<PaymentPayload>;
}
/**
* A policy function that filters or transforms payment requirements.
* Policies are applied in order before the selector chooses the final option.
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of payment requirements to filter/transform
* @returns Filtered array of payment requirements
*/
type PaymentPolicy = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements[];
/**
* Configuration for registering a payment scheme with a specific network
*/
interface SchemeRegistration {
/**
* The network identifier (e.g., 'eip155:8453', 'solana:mainnet')
*/
network: Network;
/**
* The scheme client implementation for this network
*/
client: SchemeNetworkClient;
/**
* The x402 protocol version to use for this scheme
*
* @default 2
*/
x402Version?: number;
}
/**
* Configuration options for the fetch wrapper
*/
interface x402ClientConfig {
/**
* Array of scheme registrations defining which payment methods are supported
*/
schemes: SchemeRegistration[];
/**
* Policies to apply to the client
*/
policies?: PaymentPolicy[];
/**
* Custom payment requirements selector function
* If not provided, uses the default selector (first available option)
*/
paymentRequirementsSelector?: SelectPaymentRequirements;
}
/**
* Core client for managing x402 payment schemes and creating payment payloads.
*
* Handles registration of payment schemes, policy-based filtering of payment requirements,
* and creation of payment payloads based on server requirements.
*/
declare class x402Client {
private readonly paymentRequirementsSelector;
private readonly registeredClientSchemes;
private readonly schemeClientHookAdapters;
private readonly policies;
private readonly registeredExtensions;
private beforePaymentCreationHooks;
private afterPaymentCreationHooks;
private onPaymentCreationFailureHooks;
private paymentResponseHooks;
/**
* Creates a new x402Client instance.
*
* @param paymentRequirementsSelector - Function to select payment requirements from available options
*/
constructor(paymentRequirementsSelector?: SelectPaymentRequirements);
/**
* Creates a new x402Client instance from a configuration object.
*
* @param config - The client configuration including schemes, policies, and payment requirements selector
* @returns A configured x402Client instance
*/
static fromConfig(config: x402ClientConfig): x402Client;
/**
* Registers a scheme client for the current x402 version.
*
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
register(network: Network, client: SchemeNetworkClient): x402Client;
/**
* Registers a scheme client for x402 version 1.
*
* @param network - The v1 network identifier (e.g., 'base-sepolia', 'solana-devnet')
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
registerV1(network: string, client: SchemeNetworkClient): x402Client;
/**
* Registers a policy to filter or transform payment requirements.
*
* Policies are applied in order after filtering by registered schemes
* and before the selector chooses the final payment requirement.
*
* @param policy - Function to filter/transform payment requirements
* @returns The x402Client instance for chaining
*
* @example
* ```typescript
* // Prefer cheaper options
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => BigInt(r.value) < BigInt('1000000'))
* );
*
* // Prefer specific networks
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => r.network.startsWith('eip155:'))
* );
* ```
*/
registerPolicy(policy: PaymentPolicy): x402Client;
/**
* Registers a client extension that can enrich payment payloads.
*
* Extensions are invoked after the scheme creates the base payload and the
* payload is wrapped with extensions/resource/accepted data. If the extension's
* key is present in `paymentRequired.extensions`, the extension's
* `enrichPaymentPayload` hook is called to modify the payload.
*
* @param extension - The client extension to register
* @returns The x402Client instance for chaining
*/
registerExtension(extension: ClientExtension): x402Client;
/**
* Register a hook to execute before payment payload creation.
* Can abort creation by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onBeforePaymentCreation(hook: BeforePaymentCreationHook): x402Client;
/**
* Register a hook to execute after successful payment payload creation.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onAfterPaymentCreation(hook: AfterPaymentCreationHook): x402Client;
/**
* Register a hook to execute when payment payload creation fails.
* Can recover from failure by returning { recovered: true, payload: PaymentPayload }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentCreationFailure(hook: OnPaymentCreationFailureHook): x402Client;
/**
* Register a hook to execute after a paid request completes.
* Can signal recovery by returning { recovered: true }, causing the transport to retry.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentResponse(hook: OnPaymentResponseHook): x402Client;
/**
* Fires all registered payment response hooks in order.
* Returns `{ recovered: true }` if any hook signals recovery (first wins).
*
* @param ctx - The payment response context
* @returns Recovery signal or undefined
*/
handlePaymentResponse(ctx: PaymentResponseContext): Promise<{
recovered: true;
} | undefined>;
/**
* Creates a payment payload based on a PaymentRequired response.
*
* Automatically extracts x402Version, resource, and extensions from the PaymentRequired
* response and constructs a complete PaymentPayload with the accepted requirements.
*
* @param paymentRequired - The PaymentRequired response from the server
* @returns Promise resolving to the complete payment payload
*/
createPaymentPayload(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
/**
* Merges server-declared extensions with scheme-provided extensions.
* Scheme extensions overlay on top of server extensions at each key,
* preserving server-provided schema while overlaying scheme-provided info.
*
* @param serverExtensions - Extensions declared by the server in the 402 response
* @param schemeExtensions - Extensions provided by the scheme client (e.g. EIP-2612)
* @returns The merged extensions object, or undefined if both inputs are undefined
*/
private mergeExtensions;
/**
* Enriches a payment payload by calling registered extension hooks.
* For each extension key present in the PaymentRequired response,
* invokes the corresponding extension's enrichPaymentPayload callback.
*
* @param paymentPayload - The payment payload to enrich with extension data
* @param paymentRequired - The PaymentRequired response containing extension declarations
* @returns The enriched payment payload with extension data applied
*/
private enrichPaymentPayloadWithExtensions;
/**
* Selects appropriate payment requirements based on registered clients and policies.
*
* Selection process:
* 1. Filter by registered schemes (network + scheme support)
* 2. Apply all registered policies in order
* 3. Use selector to choose final requirement
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of available payment requirements
* @returns The selected payment requirements
*/
private selectPaymentRequirements;
/**
* Internal method to register a scheme client.
*
* @param x402Version - The x402 protocol version
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
private _registerScheme;
/**
* Returns manual hooks followed by the hook for the selected scheme, if present.
*
* @param phase - Hook slot to collect
* @param x402Version - Protocol version for the selected requirement
* @param requirements - Selected payment requirement
* @returns Hooks in invocation order
*/
private getLabeledHooks;
}
export { type SchemeRegistration as $, type AfterVerifyHook as A, type BeforeVerifyHook as B, type SchemeEnrichPaymentRequiredResponseHook as C, type SchemePaymentRequiredContext as D, type SchemeEnrichSettlementPayloadHook as E, type FacilitatorExtension as F, type SchemeEnrichSettlementResponseHook as G, HTTPFacilitatorClient as H, type Price as I, x402Client as J, type PaymentCreationContext as K, type PaymentCreatedContext as L, type PaymentCreationFailureContext as M, type Network as N, type OnVerifyFailureHook as O, type PaymentPayload as P, type BeforePaymentCreationHook as Q, type ResourceConfig as R, type SettleResponse as S, type AfterPaymentCreationHook as T, type OnPaymentCreationFailureHook as U, type VerifyResponse as V, type PaymentResponseContext as W, type OnPaymentResponseHook as X, type SelectPaymentRequirements as Y, type ClientExtension as Z, type PaymentPolicy as _, type PaymentRequirements as a, type x402ClientConfig as a0, type PaymentRequirementsV1 as a1, type PaymentRequiredV1 as a2, type PaymentPayloadV1 as a3, type VerifyRequestV1 as a4, type SettleRequestV1 as a5, type SettleResponseV1 as a6, type SupportedResponseV1 as a7, type Money as a8, type AssetAmount as a9, type VerifyRequest as aa, type SettleRequest as ab, type SupportedResponse as ac, type SupportedKind as ad, VerifyError as ae, SettleError as af, type ResourceInfo as ag, type SchemeNetworkClient as ah, type SchemeClientHooks as ai, type SchemeNetworkServer as aj, type SchemeServerHooks as ak, type MoneyParser as al, type PaymentPayloadResult as am, type PaymentPayloadContext as an, type FacilitatorContext as ao, type ResourceServerExtension as ap, type ResourceServerExtensionHooks as aq, type DeepReadonly as ar, type SchemeNetworkFacilitator as b, type PaymentRequired as c, type FacilitatorClient as d, type FacilitatorConfig as e, FacilitatorResponseError as f, getFacilitatorResponseError as g, type PaymentRequiredContext as h, type VerifyContext as i, type VerifyResultContext as j, type VerifyFailureContext as k, type SettleContext as l, type SettleResultContext as m, type SettleFailureContext as n, type VerifiedPaymentCanceledContext as o, type VerifiedPaymentCancellationReason as p, type VerifiedPaymentCancelOptions as q, type PaymentCancellationDispatcher as r, type SettlementOverrides as s, type SkipHandlerDirective as t, type ResourceVerifyRespone as u, type BeforeSettleHook as v, type AfterSettleHook as w, x402ResourceServer as x, type OnSettleFailureHook as y, type OnVerifiedPaymentCanceledHook as z };
import { x as x402ResourceServer, I as Price, N as Network, S as SettleResponse, c as PaymentRequired, r as PaymentCancellationDispatcher, P as PaymentPayload, a as PaymentRequirements, s as SettlementOverrides } from './x402Client-DmgwYAFT.mjs';
declare const SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
/**
* Framework-agnostic HTTP adapter interface
* Implementations provide framework-specific HTTP operations
*/
interface HTTPAdapter {
getHeader(name: string): string | undefined;
getMethod(): string;
getPath(): string;
getUrl(): string;
getAcceptHeader(): string;
getUserAgent(): string;
/**
* Get query parameters from the request URL
*
* @returns Record of query parameter key-value pairs
*/
getQueryParams?(): Record<string, string | string[]>;
/**
* Get a specific query parameter by name
*
* @param name - The query parameter name
* @returns The query parameter value(s) or undefined
*/
getQueryParam?(name: string): string | string[] | undefined;
/**
* Get the parsed request body
* Framework adapters should parse JSON/form data appropriately
*
* @returns The parsed request body
*/
getBody?(): unknown;
}
/**
* Paywall configuration for HTML responses
*/
interface PaywallConfig {
appName?: string;
appLogo?: string;
sessionTokenEndpoint?: string;
currentUrl?: string;
testnet?: boolean;
}
/**
* Paywall provider interface for generating HTML
*/
interface PaywallProvider {
generateHtml(paymentRequired: PaymentRequired, config?: PaywallConfig): string;
}
/**
* Dynamic payTo function that receives HTTP request context
*/
type DynamicPayTo = (context: HTTPRequestContext) => string | Promise<string>;
/**
* Dynamic price function that receives HTTP request context
*/
type DynamicPrice = (context: HTTPRequestContext) => Price | Promise<Price>;
/**
* Result of response body callbacks containing content type and body.
*/
interface HTTPResponseBody {
/**
* The content type for the response (e.g., 'application/json', 'text/plain').
*/
contentType: string;
/**
* The response body to include in the 402 response.
*/
body: unknown;
}
/**
* Dynamic function to generate a custom response for unpaid requests.
* Receives the HTTP request context and returns the content type and body to include in the 402 response.
*/
type UnpaidResponseBody = (context: HTTPRequestContext) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* Dynamic function to generate a custom response for settlement failures.
* Receives the HTTP request context and settle failure result, returns the content type and body.
*/
type SettlementFailedResponseBody = (context: HTTPRequestContext, settleResult: Omit<ProcessSettleFailureResponse, "response">) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* A single payment option for a route
* Represents one way a client can pay for access to the resource
*/
interface PaymentOption {
scheme: string;
payTo: string | DynamicPayTo;
price: Price | DynamicPrice;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Route configuration for HTTP endpoints
*
* The 'accepts' field defines payment options for the route.
* Can be a single PaymentOption or an array of PaymentOptions for multiple payment methods.
*/
interface RouteConfig {
accepts: PaymentOption | PaymentOption[];
resource?: string;
description?: string;
mimeType?: string;
customPaywallHtml?: string;
/**
* Optional callback to generate a custom response for unpaid API requests.
* This allows servers to return preview data, error messages, or other content
* when a request lacks payment.
*
* For browser requests (Accept: text/html), the paywall HTML takes precedence.
* This callback is only used for API clients.
*
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @returns An object containing both contentType and body for the 402 response
*/
unpaidResponseBody?: UnpaidResponseBody;
/**
* Optional callback to generate a custom response for settlement failures.
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @param settleResult - The settlement failure result
* @returns An object containing both contentType and body for the 402 response
*/
settlementFailedResponseBody?: SettlementFailedResponseBody;
extensions?: Record<string, unknown>;
}
/**
* Routes configuration - maps path patterns to route configs
*/
type RoutesConfig = Record<string, RouteConfig> | RouteConfig;
/**
* Check if any routes in the configuration declare bazaar extensions.
*
* @param routes - Route configuration
* @returns True if any route has extensions.bazaar defined
*/
declare function checkIfBazaarNeeded(routes: RoutesConfig): boolean;
/**
* Hook that runs on every request to a protected route, before payment processing.
* Can grant access without payment, deny the request, or continue to payment flow.
*
* @returns
* - `void` - Continue to payment processing (default behavior)
* - `{ grantAccess: true }` - Grant access without requiring payment
* - `{ abort: true; reason: string }` - Deny the request (returns 403)
*/
type ProtectedRequestHook = (context: HTTPRequestContext, routeConfig: RouteConfig) => Promise<void | {
grantAccess: true;
} | {
abort: true;
reason: string;
}>;
/**
* Compiled route for efficient matching
*/
interface CompiledRoute {
verb: string;
regex: RegExp;
config: RouteConfig;
pattern: string;
}
/**
* HTTP request context that encapsulates all request data
*/
interface HTTPRequestContext {
adapter: HTTPAdapter;
path: string;
method: string;
paymentHeader?: string;
routePattern?: string;
}
/**
* HTTP transport context contains both request context and optional response data.
*/
interface HTTPTransportContext {
/** The HTTP request context */
request: HTTPRequestContext;
/** The response body buffer */
responseBody?: Buffer;
/** Response headers set by the route handler (used for settlement overrides) */
responseHeaders?: Record<string, string>;
}
/**
* HTTP response instructions for the framework middleware
*/
interface HTTPResponseInstructions {
status: number;
headers: Record<string, string>;
body?: unknown;
isHtml?: boolean;
}
/**
* Result of processing an HTTP request for payment
*/
type HTTPProcessResult = {
type: "no-payment-required";
} | {
type: "payment-verified";
cancellationDispatcher: PaymentCancellationDispatcher;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
declaredExtensions?: Record<string, unknown>;
} | {
type: "payment-error";
response: HTTPResponseInstructions;
};
/**
* Result of processSettlement
*/
type ProcessSettleSuccessResponse = SettleResponse & {
success: true;
headers: Record<string, string>;
requirements: PaymentRequirements;
};
type ProcessSettleFailureResponse = SettleResponse & {
success: false;
errorReason: string;
errorMessage?: string;
headers: Record<string, string>;
response: HTTPResponseInstructions;
};
type ProcessSettleResultResponse = ProcessSettleSuccessResponse | ProcessSettleFailureResponse;
/**
* Represents a validation error for a specific route's payment configuration.
*/
interface RouteValidationError {
/** The route pattern (e.g., "GET /api/weather") */
routePattern: string;
/** The payment scheme that failed validation */
scheme: string;
/** The network that failed validation */
network: Network;
/** The type of validation failure */
reason: "missing_scheme" | "missing_facilitator";
/** Human-readable error message */
message: string;
}
/**
* Error thrown when route configuration validation fails.
*/
declare class RouteConfigurationError extends Error {
/** The validation errors that caused this exception */
readonly errors: RouteValidationError[];
/**
* Creates a new RouteConfigurationError with the given validation errors.
*
* @param errors - The validation errors that caused this exception.
*/
constructor(errors: RouteValidationError[]);
}
/**
* HTTP-enhanced x402 resource server
* Provides framework-agnostic HTTP protocol handling
*/
declare class x402HTTPResourceServer {
private ResourceServer;
private compiledRoutes;
private routesConfig;
private paywallProvider?;
private protectedRequestHooks;
/**
* Creates a new x402HTTPResourceServer instance.
*
* @param ResourceServer - The core x402ResourceServer instance to use
* @param routes - Route configuration for payment-protected endpoints
*/
constructor(ResourceServer: x402ResourceServer, routes: RoutesConfig);
/**
* Get the underlying x402ResourceServer instance.
*
* @returns The underlying x402ResourceServer instance
*/
get server(): x402ResourceServer;
/**
* Get the routes configuration.
*
* @returns The routes configuration
*/
get routes(): 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();
* ```
*/
initialize(): Promise<void>;
/**
* Register a custom paywall provider for generating HTML
*
* @param provider - PaywallProvider instance
* @returns This service instance for chaining
*/
registerPaywallProvider(provider: PaywallProvider): 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: ProtectedRequestHook): 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
*/
processHTTPRequest(context: HTTPRequestContext, paywallConfig?: PaywallConfig): Promise<HTTPProcessResult>;
/**
* 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)
* @param transportContext - Optional HTTP transport context
* @param settlementOverrides - Optional settlement overrides (e.g., partial settlement amount)
* @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
*/
processSettlement(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: HTTPTransportContext, settlementOverrides?: SettlementOverrides): Promise<ProcessSettleResultResponse>;
/**
* 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: HTTPRequestContext): boolean;
/**
* Settle a verified payment that requested `skipHandler`, packaging the
* result as a `payment-error` HTTPProcessResult so framework adapters can
* write the response without invoking the route handler.
*
* - On success: status 200 + PAYMENT-RESPONSE header + configured body.
* - On failure: the standard 402 settlement-failure response.
*
* @param paymentPayload - Verified payment payload.
* @param requirements - Matched payment requirements.
* @param declaredExtensions - Optional declared extensions for the route.
* @param transportContext - Optional HTTP transport context.
* @param skipHandlerResponse - Optional content type + body to return on success.
* @returns A `payment-error` HTTPProcessResult carrying the final response.
*/
private processSkipHandlerSettlement;
/**
* Build HTTPResponseInstructions for settlement failure.
* Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
*
* @param failure - Settlement failure result with headers
* @param transportContext - Optional HTTP transport context for the request
* @returns HTTP response instructions for the 402 settlement failure response
*/
private buildSettlementFailureResponse;
/**
* 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
*/
private normalizePaymentOptions;
/**
* 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)
*/
private validateRouteConfiguration;
/**
* Get route configuration for a request
*
* @param path - Request path
* @param method - HTTP method
* @returns Route configuration and pattern, or undefined if no match
*/
private getRouteConfig;
/**
* Extract payment from HTTP headers (handles v1 and v2)
*
* @param adapter - HTTP adapter
* @returns Decoded payment payload or null
*/
private extractPayment;
/**
* Check if request is from a web browser
*
* @param adapter - HTTP adapter
* @returns True if request appears to be from a browser
*/
private isWebBrowser;
/**
* 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
*/
private createHTTPResponse;
/**
* 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
*/
private createHTTPPaymentRequiredResponse;
/**
* Create settlement response headers
*
* @param settleResponse - Settlement response
* @returns Headers to add to response
*/
private createSettlementHeaders;
/**
* Parse route pattern into verb and regex
*
* @param pattern - Route pattern like "GET /api/*", "/api/[id]", or "/api/:id"
* @returns Parsed pattern with verb and regex
*/
private parseRoutePattern;
/**
* Normalize path for matching
*
* @param path - Raw path from request
* @returns Normalized path
*/
private normalizePath;
/**
* 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
*/
private generatePaywallHTML;
/**
* Extract display amount from payment requirements.
* Uses the registered scheme's decimal precision for the asset, falling back to 6.
*
* @param paymentRequired - The payment required object
* @returns The display amount in decimal format
*/
private getDisplayAmount;
}
export { type CompiledRoute as C, type DynamicPayTo as D, type HTTPAdapter as H, type PaywallConfig as P, type RouteConfig as R, type SettlementFailedResponseBody as S, type UnpaidResponseBody as U, type HTTPRequestContext as a, type HTTPTransportContext as b, type HTTPResponseInstructions as c, type HTTPProcessResult as d, type PaywallProvider as e, type PaymentOption as f, type RoutesConfig as g, type DynamicPrice as h, type HTTPResponseBody as i, type ProcessSettleResultResponse as j, type ProcessSettleSuccessResponse as k, type ProcessSettleFailureResponse as l, type RouteValidationError as m, RouteConfigurationError as n, type ProtectedRequestHook as o, SETTLEMENT_OVERRIDES_HEADER as p, checkIfBazaarNeeded as q, x402HTTPResourceServer as x };
+52
-253

@@ -1,255 +0,5 @@

import { c as PaymentRequired, a as PaymentRequirements, P as PaymentPayload, N as Network, t as SchemeNetworkClient, S as SettleResponse } from '../mechanisms-C6YmSXgy.js';
import { c as PaymentRequired, J as x402Client, P as PaymentPayload, S as SettleResponse } from '../x402Client-DmgwYAFT.js';
export { T as AfterPaymentCreationHook, Q as BeforePaymentCreationHook, Z as ClientExtension, U as OnPaymentCreationFailureHook, X as OnPaymentResponseHook, L as PaymentCreatedContext, K as PaymentCreationContext, M as PaymentCreationFailureContext, _ as PaymentPolicy, W as PaymentResponseContext, $ as SchemeRegistration, Y as SelectPaymentRequirements, a0 as x402ClientConfig } from '../x402Client-DmgwYAFT.js';
/**
* Client Hook Context Interfaces
*/
interface PaymentCreationContext {
paymentRequired: PaymentRequired;
selectedRequirements: PaymentRequirements;
}
interface PaymentCreatedContext extends PaymentCreationContext {
paymentPayload: PaymentPayload;
}
interface PaymentCreationFailureContext extends PaymentCreationContext {
error: Error;
}
/**
* Client Hook Type Definitions
*/
type BeforePaymentCreationHook = (context: PaymentCreationContext) => Promise<void | {
abort: true;
reason: string;
}>;
type AfterPaymentCreationHook = (context: PaymentCreatedContext) => Promise<void>;
type OnPaymentCreationFailureHook = (context: PaymentCreationFailureContext) => Promise<void | {
recovered: true;
payload: PaymentPayload;
}>;
type SelectPaymentRequirements = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements;
/**
* Extension that can enrich payment payloads on the client side.
*
* Client extensions are invoked after the scheme creates the base payment payload
* but before it is returned. This allows mechanism-specific logic (e.g., EVM EIP-2612
* permit signing) to enrich the payload's extensions data.
*/
interface ClientExtension {
/**
* Unique key identifying this extension (e.g., "eip2612GasSponsoring").
* Must match the extension key used in PaymentRequired.extensions.
*/
key: string;
/**
* Called after payload creation when the extension key is present in
* paymentRequired.extensions. Allows the extension to enrich the payload
* with extension-specific data (e.g., signing an EIP-2612 permit).
*
* @param paymentPayload - The payment payload to enrich
* @param paymentRequired - The original PaymentRequired response
* @returns The enriched payment payload
*/
enrichPaymentPayload?: (paymentPayload: PaymentPayload, paymentRequired: PaymentRequired) => Promise<PaymentPayload>;
}
/**
* A policy function that filters or transforms payment requirements.
* Policies are applied in order before the selector chooses the final option.
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of payment requirements to filter/transform
* @returns Filtered array of payment requirements
*/
type PaymentPolicy = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements[];
/**
* Configuration for registering a payment scheme with a specific network
*/
interface SchemeRegistration {
/**
* The network identifier (e.g., 'eip155:8453', 'solana:mainnet')
*/
network: Network;
/**
* The scheme client implementation for this network
*/
client: SchemeNetworkClient;
/**
* The x402 protocol version to use for this scheme
*
* @default 2
*/
x402Version?: number;
}
/**
* Configuration options for the fetch wrapper
*/
interface x402ClientConfig {
/**
* Array of scheme registrations defining which payment methods are supported
*/
schemes: SchemeRegistration[];
/**
* Policies to apply to the client
*/
policies?: PaymentPolicy[];
/**
* Custom payment requirements selector function
* If not provided, uses the default selector (first available option)
*/
paymentRequirementsSelector?: SelectPaymentRequirements;
}
/**
* Core client for managing x402 payment schemes and creating payment payloads.
*
* Handles registration of payment schemes, policy-based filtering of payment requirements,
* and creation of payment payloads based on server requirements.
*/
declare class x402Client {
private readonly paymentRequirementsSelector;
private readonly registeredClientSchemes;
private readonly policies;
private readonly registeredExtensions;
private beforePaymentCreationHooks;
private afterPaymentCreationHooks;
private onPaymentCreationFailureHooks;
/**
* Creates a new x402Client instance.
*
* @param paymentRequirementsSelector - Function to select payment requirements from available options
*/
constructor(paymentRequirementsSelector?: SelectPaymentRequirements);
/**
* Creates a new x402Client instance from a configuration object.
*
* @param config - The client configuration including schemes, policies, and payment requirements selector
* @returns A configured x402Client instance
*/
static fromConfig(config: x402ClientConfig): x402Client;
/**
* Registers a scheme client for the current x402 version.
*
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
register(network: Network, client: SchemeNetworkClient): x402Client;
/**
* Registers a scheme client for x402 version 1.
*
* @param network - The v1 network identifier (e.g., 'base-sepolia', 'solana-devnet')
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
registerV1(network: string, client: SchemeNetworkClient): x402Client;
/**
* Registers a policy to filter or transform payment requirements.
*
* Policies are applied in order after filtering by registered schemes
* and before the selector chooses the final payment requirement.
*
* @param policy - Function to filter/transform payment requirements
* @returns The x402Client instance for chaining
*
* @example
* ```typescript
* // Prefer cheaper options
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => BigInt(r.value) < BigInt('1000000'))
* );
*
* // Prefer specific networks
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => r.network.startsWith('eip155:'))
* );
* ```
*/
registerPolicy(policy: PaymentPolicy): x402Client;
/**
* Registers a client extension that can enrich payment payloads.
*
* Extensions are invoked after the scheme creates the base payload and the
* payload is wrapped with extensions/resource/accepted data. If the extension's
* key is present in `paymentRequired.extensions`, the extension's
* `enrichPaymentPayload` hook is called to modify the payload.
*
* @param extension - The client extension to register
* @returns The x402Client instance for chaining
*/
registerExtension(extension: ClientExtension): x402Client;
/**
* Register a hook to execute before payment payload creation.
* Can abort creation by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onBeforePaymentCreation(hook: BeforePaymentCreationHook): x402Client;
/**
* Register a hook to execute after successful payment payload creation.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onAfterPaymentCreation(hook: AfterPaymentCreationHook): x402Client;
/**
* Register a hook to execute when payment payload creation fails.
* Can recover from failure by returning { recovered: true, payload: PaymentPayload }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentCreationFailure(hook: OnPaymentCreationFailureHook): x402Client;
/**
* Creates a payment payload based on a PaymentRequired response.
*
* Automatically extracts x402Version, resource, and extensions from the PaymentRequired
* response and constructs a complete PaymentPayload with the accepted requirements.
*
* @param paymentRequired - The PaymentRequired response from the server
* @returns Promise resolving to the complete payment payload
*/
createPaymentPayload(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
/**
* Merges server-declared extensions with scheme-provided extensions.
* Scheme extensions overlay on top of server extensions at each key,
* preserving server-provided schema while overlaying scheme-provided info.
*
* @param serverExtensions - Extensions declared by the server in the 402 response
* @param schemeExtensions - Extensions provided by the scheme client (e.g. EIP-2612)
* @returns The merged extensions object, or undefined if both inputs are undefined
*/
private mergeExtensions;
/**
* Enriches a payment payload by calling registered extension hooks.
* For each extension key present in the PaymentRequired response,
* invokes the corresponding extension's enrichPaymentPayload callback.
*
* @param paymentPayload - The payment payload to enrich with extension data
* @param paymentRequired - The PaymentRequired response containing extension declarations
* @returns The enriched payment payload with extension data applied
*/
private enrichPaymentPayloadWithExtensions;
/**
* Selects appropriate payment requirements based on registered clients and policies.
*
* Selection process:
* 1. Filter by registered schemes (network + scheme support)
* 2. Apply all registered policies in order
* 3. Use selector to choose final requirement
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of available payment requirements
* @returns The selected payment requirements
*/
private selectPaymentRequirements;
/**
* Internal method to register a scheme client.
*
* @param x402Version - The x402 protocol version
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
private _registerScheme;
}
/**
* Context provided to onPaymentRequired hooks.

@@ -327,4 +77,53 @@ */

createPaymentPayload(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
/**
* Parses response headers into protocol types, fires payment response hooks,
* and returns whether a hook signaled recovery.
*
* Called by transport wrappers (fetch, axios) after the paid request completes.
*
* @param paymentPayload - The payload that was sent with the request
* @param getHeader - Function to retrieve a response header by name
* @param status - The HTTP status code of the response
* @returns Whether a hook recovered and the parsed settle response (if any)
*/
processPaymentResult(paymentPayload: PaymentPayload, getHeader: (name: string) => string | null | undefined, status: number): Promise<{
recovered: boolean;
settleResponse?: SettleResponse;
}>;
/**
* Parses a fetch Response into a discriminated `x402PaymentResult` for app-level convenience.
*
* @param response - The fetch Response to process
* @returns A discriminated union describing the payment outcome
*/
processResponse(response: Response): Promise<x402PaymentResult>;
}
/**
* Discriminated union describing the outcome of a payment-enabled request.
*/
type x402PaymentResult = {
kind: "success";
response: Response;
body: unknown;
settleResponse: SettleResponse;
} | {
kind: "settle_failed";
response: Response;
body: unknown;
settleResponse: SettleResponse;
} | {
kind: "payment_required";
response: Response;
paymentRequired: PaymentRequired;
} | {
kind: "error";
response: Response;
status: number;
body: unknown;
} | {
kind: "passthrough";
response: Response;
body: unknown;
};
export { type AfterPaymentCreationHook, type BeforePaymentCreationHook, type ClientExtension, type OnPaymentCreationFailureHook, type PaymentCreatedContext, type PaymentCreationContext, type PaymentCreationFailureContext, type PaymentPolicy, type PaymentRequiredContext, type PaymentRequiredHook, type SchemeRegistration, type SelectPaymentRequirements, x402Client, type x402ClientConfig, x402HTTPClient };
export { type PaymentRequiredContext, type PaymentRequiredHook, x402Client, x402HTTPClient, type x402PaymentResult };

@@ -80,2 +80,3 @@ "use strict";

this.registeredClientSchemes = /* @__PURE__ */ new Map();
this.schemeClientHookAdapters = /* @__PURE__ */ new Map();
this.policies = [];

@@ -86,2 +87,3 @@ this.registeredExtensions = /* @__PURE__ */ new Map();

this.onPaymentCreationFailureHooks = [];
this.paymentResponseHooks = [];
this.paymentRequirementsSelector = paymentRequirementsSelector || ((x402Version2, accepts) => accepts[0]);

@@ -203,2 +205,33 @@ }

/**
* Register a hook to execute after a paid request completes.
* Can signal recovery by returning { recovered: true }, causing the transport to retry.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentResponse(hook) {
this.paymentResponseHooks.push(hook);
return this;
}
/**
* Fires all registered payment response hooks in order.
* Returns `{ recovered: true }` if any hook signals recovery (first wins).
*
* @param ctx - The payment response context
* @returns Recovery signal or undefined
*/
async handlePaymentResponse(ctx) {
for (const hook of this.getLabeledHooks(
"onPaymentResponse",
ctx.paymentPayload.x402Version,
ctx.requirements
)) {
const result = await hook(ctx);
if (result && "recovered" in result && result.recovered) {
return { recovered: true };
}
}
return void 0;
}
/**
* Creates a payment payload based on a PaymentRequired response.

@@ -222,3 +255,7 @@ *

};
for (const hook of this.beforePaymentCreationHooks) {
for (const hook of this.getLabeledHooks(
"beforePaymentCreation",
paymentRequired.x402Version,
requirements
)) {
const result = await hook(context);

@@ -260,3 +297,7 @@ if (result && "abort" in result && result.abort) {

};
for (const hook of this.afterPaymentCreationHooks) {
for (const hook of this.getLabeledHooks(
"afterPaymentCreation",
paymentRequired.x402Version,
requirements
)) {
await hook(createdContext);

@@ -270,3 +311,7 @@ }

};
for (const hook of this.onPaymentCreationFailureHooks) {
for (const hook of this.getLabeledHooks(
"onPaymentCreationFailure",
paymentRequired.x402Version,
requirements
)) {
const result = await hook(failureContext);

@@ -383,7 +428,69 @@ if (result && "recovered" in result && result.recovered) {

const clientByScheme = clientSchemesByNetwork.get(network);
if (!clientByScheme.has(client.scheme)) {
clientByScheme.set(client.scheme, client);
clientByScheme.set(client.scheme, client);
if (!this.schemeClientHookAdapters.has(x402Version2)) {
this.schemeClientHookAdapters.set(x402Version2, /* @__PURE__ */ new Map());
}
const adaptersByNetwork = this.schemeClientHookAdapters.get(x402Version2);
if (!adaptersByNetwork.has(network)) {
adaptersByNetwork.set(network, /* @__PURE__ */ new Map());
}
const adaptersByScheme = adaptersByNetwork.get(network);
const hooks = client.schemeHooks;
if (!hooks) {
adaptersByScheme.delete(client.scheme);
return this;
}
const handles = {};
if (hooks.onBeforePaymentCreation) {
handles.beforePaymentCreation = hooks.onBeforePaymentCreation;
}
if (hooks.onAfterPaymentCreation) {
handles.afterPaymentCreation = hooks.onAfterPaymentCreation;
}
if (hooks.onPaymentCreationFailure) {
handles.onPaymentCreationFailure = hooks.onPaymentCreationFailure;
}
if (hooks.onPaymentResponse) {
handles.onPaymentResponse = hooks.onPaymentResponse;
}
if (Object.keys(handles).length > 0) {
adaptersByScheme.set(client.scheme, handles);
} else {
adaptersByScheme.delete(client.scheme);
}
return this;
}
/**
* Returns manual hooks followed by the hook for the selected scheme, if present.
*
* @param phase - Hook slot to collect
* @param x402Version - Protocol version for the selected requirement
* @param requirements - Selected payment requirement
* @returns Hooks in invocation order
*/
getLabeledHooks(phase, x402Version2, requirements) {
let manual;
switch (phase) {
case "beforePaymentCreation":
manual = this.beforePaymentCreationHooks;
break;
case "afterPaymentCreation":
manual = this.afterPaymentCreationHooks;
break;
case "onPaymentCreationFailure":
manual = this.onPaymentCreationFailureHooks;
break;
case "onPaymentResponse":
manual = this.paymentResponseHooks;
break;
}
const out = [...manual];
const adaptersByNetwork = this.schemeClientHookAdapters.get(x402Version2);
const schemeAdapter = adaptersByNetwork ? findByNetworkAndScheme(adaptersByNetwork, requirements.scheme, requirements.network) : void 0;
const hook = schemeAdapter?.[phase];
if (hook !== void 0) {
out.push(hook);
}
return out;
}
};

@@ -402,6 +509,10 @@

var NetworkSchema = import_zod.z.union([NetworkSchemaV1, NetworkSchemaV2]);
var PRINTABLE_ASCII_REGEX = /^[\x20-\x7e]+$/;
var ResourceInfoSchema = import_zod.z.object({
url: NonEmptyString,
description: import_zod.z.string().optional(),
mimeType: import_zod.z.string().optional()
mimeType: import_zod.z.string().optional(),
serviceName: import_zod.z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX).optional(),
tags: import_zod.z.array(import_zod.z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX)).max(5).optional(),
iconUrl: import_zod.z.string().max(2048).optional()
});

@@ -475,3 +586,4 @@ var PaymentRequirementsV1Schema = import_zod.z.object({

payer: import_zod2.z.string().nullish().transform((v) => v ?? void 0),
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0),
extra: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
});

@@ -485,3 +597,5 @@ var settleResponseSchema = import_zod2.z.object({

network: import_zod2.z.custom((value) => typeof value === "string"),
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
amount: import_zod2.z.string().nullish().transform((v) => v ?? void 0),
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0),
extra: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
});

@@ -622,2 +736,69 @@ var supportedKindSchema = import_zod2.z.object({

}
/**
* Parses response headers into protocol types, fires payment response hooks,
* and returns whether a hook signaled recovery.
*
* Called by transport wrappers (fetch, axios) after the paid request completes.
*
* @param paymentPayload - The payload that was sent with the request
* @param getHeader - Function to retrieve a response header by name
* @param status - The HTTP status code of the response
* @returns Whether a hook recovered and the parsed settle response (if any)
*/
async processPaymentResult(paymentPayload, getHeader, status) {
const requirements = paymentPayload.accepted;
let settleResponse;
try {
settleResponse = this.getPaymentSettleResponse(getHeader);
} catch {
}
let paymentRequired;
if (!settleResponse && status === 402) {
try {
paymentRequired = this.getPaymentRequiredResponse(getHeader);
} catch {
}
}
const ctx = {
paymentPayload,
requirements,
...settleResponse ? { settleResponse } : {},
...paymentRequired ? { paymentRequired } : {}
};
const result = await this.client.handlePaymentResponse(ctx);
return { recovered: result?.recovered === true, settleResponse };
}
/**
* Parses a fetch Response into a discriminated `x402PaymentResult` for app-level convenience.
*
* @param response - The fetch Response to process
* @returns A discriminated union describing the payment outcome
*/
async processResponse(response) {
const getHeader = (name) => response.headers.get(name);
let settleResponse;
try {
settleResponse = this.getPaymentSettleResponse(getHeader);
} catch {
}
const contentType = response.headers.get("content-type") ?? "";
const body = contentType.includes("application/json") ? await response.json() : await response.text();
if (settleResponse && settleResponse.success) {
return { kind: "success", response, body, settleResponse };
}
if (settleResponse && !settleResponse.success) {
return { kind: "settle_failed", response, body, settleResponse };
}
if (response.status === 402) {
try {
const paymentRequired = this.getPaymentRequiredResponse(getHeader, body);
return { kind: "payment_required", response, paymentRequired };
} catch {
}
}
if (response.ok) {
return { kind: "passthrough", response, body };
}
return { kind: "error", response, status: response.status, body };
}
};

@@ -624,0 +805,0 @@ // Annotate the CommonJS export names for ESM import in node:

@@ -1,2 +0,2 @@

import { P as PaymentPayload, a as PaymentRequirements, V as VerifyResponse, S as SettleResponse, N as Network, b as SchemeNetworkFacilitator, F as FacilitatorExtension } from '../mechanisms-C6YmSXgy.js';
import { P as PaymentPayload, a as PaymentRequirements, V as VerifyResponse, S as SettleResponse, N as Network, b as SchemeNetworkFacilitator, F as FacilitatorExtension } from '../x402Client-DmgwYAFT.js';

@@ -3,0 +3,0 @@ /**

@@ -1,4 +0,4 @@

import { P as PaymentPayload, c as PaymentRequired, S as SettleResponse } from '../mechanisms-C6YmSXgy.js';
export { d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, g as getFacilitatorResponseError } from '../mechanisms-C6YmSXgy.js';
export { C as CompiledRoute, D as DynamicPayTo, h as DynamicPrice, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, f as PaymentOption, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, S as SettlementFailedResponseBody, U as UnpaidResponseBody, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-CVhfZSvj.js';
import { P as PaymentPayload, c as PaymentRequired, S as SettleResponse } from '../x402Client-DmgwYAFT.js';
export { d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, g as getFacilitatorResponseError } from '../x402Client-DmgwYAFT.js';
export { C as CompiledRoute, D as DynamicPayTo, h as DynamicPrice, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, f as PaymentOption, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, S as SettlementFailedResponseBody, U as UnpaidResponseBody, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-D1-CDqp9.js';
export { PaymentRequiredContext, PaymentRequiredHook, x402HTTPClient } from '../client/index.js';

@@ -5,0 +5,0 @@

@@ -67,3 +67,3 @@ "use strict";

* @param statusCode - HTTP status code from the facilitator
* @param response - The verify response containing error details
* @param response - The verify response containing failure details
*/

@@ -325,3 +325,4 @@ constructor(statusCode, response) {

extensions ?? {},
transportContext
transportContext,
paymentPayload
);

@@ -333,4 +334,20 @@ return {

}
if (verifyResult.skipHandler) {
return await this.processSkipHandlerSettlement(
paymentPayload,
matchingRequirements,
extensions ?? {},
transportContext,
verifyResult.skipHandler
);
}
const cancellationDispatcher = this.ResourceServer.createPaymentCancellationDispatcher(
paymentPayload,
matchingRequirements,
extensions ?? {},
transportContext
);
return {
type: "payment-verified",
cancellationDispatcher,
paymentPayload,

@@ -467,2 +484,42 @@ paymentRequirements: matchingRequirements,

/**
* Settle a verified payment that requested `skipHandler`, packaging the
* result as a `payment-error` HTTPProcessResult so framework adapters can
* write the response without invoking the route handler.
*
* - On success: status 200 + PAYMENT-RESPONSE header + configured body.
* - On failure: the standard 402 settlement-failure response.
*
* @param paymentPayload - Verified payment payload.
* @param requirements - Matched payment requirements.
* @param declaredExtensions - Optional declared extensions for the route.
* @param transportContext - Optional HTTP transport context.
* @param skipHandlerResponse - Optional content type + body to return on success.
* @returns A `payment-error` HTTPProcessResult carrying the final response.
*/
async processSkipHandlerSettlement(paymentPayload, requirements, declaredExtensions, transportContext, skipHandlerResponse) {
const settleResult = await this.processSettlement(
paymentPayload,
requirements,
declaredExtensions,
transportContext
);
if (!settleResult.success) {
return { type: "payment-error", response: settleResult.response };
}
const contentType = skipHandlerResponse?.contentType ?? "application/json";
const body = skipHandlerResponse?.body ?? {};
return {
type: "payment-error",
response: {
status: 200,
headers: {
"Content-Type": contentType,
...settleResult.headers
},
body,
isHtml: contentType.includes("text/html")
}
};
}
/**
* Build HTTPResponseInstructions for settlement failure.

@@ -773,6 +830,10 @@ * Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.

var NetworkSchema = import_zod.z.union([NetworkSchemaV1, NetworkSchemaV2]);
var PRINTABLE_ASCII_REGEX = /^[\x20-\x7e]+$/;
var ResourceInfoSchema = import_zod.z.object({
url: NonEmptyString,
description: import_zod.z.string().optional(),
mimeType: import_zod.z.string().optional()
mimeType: import_zod.z.string().optional(),
serviceName: import_zod.z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX).optional(),
tags: import_zod.z.array(import_zod.z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX)).max(5).optional(),
iconUrl: import_zod.z.string().max(2048).optional()
});

@@ -849,3 +910,4 @@ var PaymentRequirementsV1Schema = import_zod.z.object({

payer: import_zod2.z.string().nullish().transform((v) => v ?? void 0),
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0),
extra: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
});

@@ -859,3 +921,5 @@ var settleResponseSchema = import_zod2.z.object({

network: import_zod2.z.custom((value) => typeof value === "string"),
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
amount: import_zod2.z.string().nullish().transform((v) => v ?? void 0),
extensions: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0),
extra: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).nullish().transform((v) => v ?? void 0)
});

@@ -885,2 +949,24 @@ var supportedKindSchema = import_zod2.z.object({

}
var EXTENSION_RESPONSE_LOG_FIELD_ALLOWLIST = ["status", "rejectedReason", "reason", "code"];
function logExtensionResponsesHeader(response) {
const header = response.headers.get("EXTENSION-RESPONSES");
if (!header) return;
try {
const decoded = JSON.parse(safeBase64Decode(header));
if (!decoded || typeof decoded !== "object" || Array.isArray(decoded)) return;
const sanitized = {};
for (const [extensionKey, payload] of Object.entries(decoded)) {
const source = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
const filtered = {};
for (const key of EXTENSION_RESPONSE_LOG_FIELD_ALLOWLIST) {
if (source[key] !== void 0) {
filtered[key] = source[key];
}
}
sanitized[extensionKey] = filtered;
}
console.log(`[x402] extension responses: ${JSON.stringify(sanitized)}`);
} catch {
}
}
async function parseSuccessResponse(response, schema, operation) {

@@ -954,3 +1040,5 @@ const text = await response.text();

}
return parseSuccessResponse(response, verifyResponseSchema, "verify");
const verifyResult = await parseSuccessResponse(response, verifyResponseSchema, "verify");
logExtensionResponsesHeader(response);
return verifyResult;
}

@@ -997,3 +1085,5 @@ /**

}
return parseSuccessResponse(response, settleResponseSchema, "settle");
const settleResult = await parseSuccessResponse(response, settleResponseSchema, "settle");
logExtensionResponsesHeader(response);
return settleResult;
}

@@ -1171,2 +1261,69 @@ /**

}
/**
* Parses response headers into protocol types, fires payment response hooks,
* and returns whether a hook signaled recovery.
*
* Called by transport wrappers (fetch, axios) after the paid request completes.
*
* @param paymentPayload - The payload that was sent with the request
* @param getHeader - Function to retrieve a response header by name
* @param status - The HTTP status code of the response
* @returns Whether a hook recovered and the parsed settle response (if any)
*/
async processPaymentResult(paymentPayload, getHeader, status) {
const requirements = paymentPayload.accepted;
let settleResponse;
try {
settleResponse = this.getPaymentSettleResponse(getHeader);
} catch {
}
let paymentRequired;
if (!settleResponse && status === 402) {
try {
paymentRequired = this.getPaymentRequiredResponse(getHeader);
} catch {
}
}
const ctx = {
paymentPayload,
requirements,
...settleResponse ? { settleResponse } : {},
...paymentRequired ? { paymentRequired } : {}
};
const result = await this.client.handlePaymentResponse(ctx);
return { recovered: result?.recovered === true, settleResponse };
}
/**
* Parses a fetch Response into a discriminated `x402PaymentResult` for app-level convenience.
*
* @param response - The fetch Response to process
* @returns A discriminated union describing the payment outcome
*/
async processResponse(response) {
const getHeader = (name) => response.headers.get(name);
let settleResponse;
try {
settleResponse = this.getPaymentSettleResponse(getHeader);
} catch {
}
const contentType = response.headers.get("content-type") ?? "";
const body = contentType.includes("application/json") ? await response.json() : await response.text();
if (settleResponse && settleResponse.success) {
return { kind: "success", response, body, settleResponse };
}
if (settleResponse && !settleResponse.success) {
return { kind: "settle_failed", response, body, settleResponse };
}
if (response.status === 402) {
try {
const paymentRequired = this.getPaymentRequiredResponse(getHeader, body);
return { kind: "payment_required", response, paymentRequired };
} catch {
}
}
if (response.ok) {
return { kind: "passthrough", response, body };
}
return { kind: "error", response, status: response.status, body };
}
};

@@ -1173,0 +1330,0 @@

@@ -39,5 +39,2 @@ import { z } from 'zod';

type Network = z.infer<typeof NetworkSchema>;
/**
* ResourceInfo schema for V2 - describes the protected resource.
*/
declare const ResourceInfoSchema: z.ZodObject<{

@@ -47,2 +44,5 @@ url: z.ZodString;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -52,2 +52,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -57,2 +60,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>;

@@ -85,5 +91,5 @@ type ResourceInfo = z.infer<typeof ResourceInfoSchema>;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -98,5 +104,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>;

@@ -132,5 +138,5 @@ type PaymentRequirementsV1 = z.infer<typeof PaymentRequirementsV1Schema>;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -145,5 +151,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>, "many">;

@@ -161,5 +167,5 @@ }, "strip", z.ZodTypeAny, {

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -178,5 +184,5 @@ error?: string | undefined;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -248,2 +254,5 @@ error?: string | undefined;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -253,2 +262,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -258,2 +270,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>;

@@ -291,2 +306,5 @@ accepts: z.ZodArray<z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -310,2 +328,5 @@ x402Version: 2;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -336,2 +357,5 @@ x402Version: 2;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -341,2 +365,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -346,2 +373,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>>;

@@ -392,2 +422,5 @@ accepted: z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -411,2 +444,5 @@ }, {

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -440,5 +476,5 @@ }>;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -453,5 +489,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>, z.ZodObject<{

@@ -511,5 +547,5 @@ scheme: z.ZodString;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -524,5 +560,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>, "many">;

@@ -540,5 +576,5 @@ }, "strip", z.ZodTypeAny, {

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -557,5 +593,5 @@ error?: string | undefined;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -570,2 +606,5 @@ error?: string | undefined;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -575,2 +614,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -580,2 +622,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>;

@@ -613,2 +658,5 @@ accepts: z.ZodArray<z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -632,2 +680,5 @@ x402Version: 2;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -673,2 +724,5 @@ x402Version: 2;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -678,2 +732,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -683,2 +740,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>>;

@@ -729,2 +789,5 @@ accepted: z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -748,2 +811,5 @@ }, {

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -750,0 +816,0 @@ }>]>;

@@ -67,6 +67,10 @@ "use strict";

var NetworkSchema = import_zod.z.union([NetworkSchemaV1, NetworkSchemaV2]);
var PRINTABLE_ASCII_REGEX = /^[\x20-\x7e]+$/;
var ResourceInfoSchema = import_zod.z.object({
url: NonEmptyString,
description: import_zod.z.string().optional(),
mimeType: import_zod.z.string().optional()
mimeType: import_zod.z.string().optional(),
serviceName: import_zod.z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX).optional(),
tags: import_zod.z.array(import_zod.z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX)).max(5).optional(),
iconUrl: import_zod.z.string().max(2048).optional()
});

@@ -73,0 +77,0 @@ var PaymentRequirementsV1Schema = import_zod.z.object({

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../src/schemas/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ============================================================================\n// Reusable Primitive Schemas\n// ============================================================================\n\n/**\n * Non-empty string schema - a string with at least one character.\n * Used for required string fields that cannot be empty.\n */\nexport const NonEmptyString = z.string().min(1);\nexport type NonEmptyString = z.infer<typeof NonEmptyString>;\n\n/**\n * Any record schema - an object with unknown keys and values.\n * Used for scheme-specific payloads and other extensible objects.\n */\nexport const Any = z.record(z.unknown());\nexport type Any = z.infer<typeof Any>;\n\n/**\n * Optional any record schema - an optional object with unknown keys and values.\n * Used for optional extension fields like `extra` and `extensions`.\n */\nexport const OptionalAny = z.record(z.unknown()).optional().nullable();\nexport type OptionalAny = z.infer<typeof OptionalAny>;\n\n// ============================================================================\n// Network Schemas\n// ============================================================================\n\n/**\n * Network identifier schema for V1 - loose validation.\n * V1 accepts any non-empty string for backwards compatibility.\n */\nexport const NetworkSchemaV1 = NonEmptyString;\nexport type NetworkV1 = z.infer<typeof NetworkSchemaV1>;\n\n/**\n * Network identifier schema for V2 - CAIP-2 format validation.\n * V2 requires minimum length of 3 and a colon separator (e.g., \"eip155:84532\", \"solana:devnet\").\n */\nexport const NetworkSchemaV2 = z\n .string()\n .min(3)\n .refine(val => val.includes(\":\"), {\n message: \"Network must be in CAIP-2 format (e.g., 'eip155:84532')\",\n });\nexport type NetworkV2 = z.infer<typeof NetworkSchemaV2>;\n\n/**\n * Union network schema - accepts either V1 or V2 format.\n */\nexport const NetworkSchema = z.union([NetworkSchemaV1, NetworkSchemaV2]);\nexport type Network = z.infer<typeof NetworkSchema>;\n\n// ============================================================================\n// Shared Schemas\n// ============================================================================\n\n/**\n * ResourceInfo schema for V2 - describes the protected resource.\n */\nexport const ResourceInfoSchema = z.object({\n url: NonEmptyString,\n description: z.string().optional(),\n mimeType: z.string().optional(),\n});\nexport type ResourceInfo = z.infer<typeof ResourceInfoSchema>;\n\n// ============================================================================\n// V1 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V1.\n * V1 includes resource info directly in the requirements object.\n */\nexport const PaymentRequirementsV1Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n maxAmountRequired: NonEmptyString,\n resource: NonEmptyString, // URL string in V1\n description: z.string(),\n mimeType: z.string().optional(),\n outputSchema: Any.optional().nullable(),\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n asset: NonEmptyString,\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV1 = z.infer<typeof PaymentRequirementsV1Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V1.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV1Schema = z.object({\n x402Version: z.literal(1),\n error: z.string().optional(),\n accepts: z.array(PaymentRequirementsV1Schema).min(1),\n});\nexport type PaymentRequiredV1 = z.infer<typeof PaymentRequiredV1Schema>;\n\n/**\n * PaymentPayload schema for V1.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV1Schema = z.object({\n x402Version: z.literal(1),\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n payload: Any,\n});\nexport type PaymentPayloadV1 = z.infer<typeof PaymentPayloadV1Schema>;\n\n// ============================================================================\n// V2 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V2.\n * V2 uses \"amount\" instead of \"maxAmountRequired\" and doesn't include resource info.\n */\nexport const PaymentRequirementsV2Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV2,\n amount: NonEmptyString,\n asset: NonEmptyString,\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV2 = z.infer<typeof PaymentRequirementsV2Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V2.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV2Schema = z.object({\n x402Version: z.literal(2),\n error: z.string().optional(),\n resource: ResourceInfoSchema,\n accepts: z.array(PaymentRequirementsV2Schema).min(1),\n extensions: OptionalAny,\n});\nexport type PaymentRequiredV2 = z.infer<typeof PaymentRequiredV2Schema>;\n\n/**\n * PaymentPayload schema for V2.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV2Schema = z.object({\n x402Version: z.literal(2),\n resource: ResourceInfoSchema.optional(),\n accepted: PaymentRequirementsV2Schema,\n payload: Any,\n extensions: OptionalAny,\n});\nexport type PaymentPayloadV2 = z.infer<typeof PaymentPayloadV2Schema>;\n\n// ============================================================================\n// Union Schemas (V1 | V2)\n// ============================================================================\n\n/**\n * PaymentRequirements union schema - accepts either V1 or V2 format.\n * Use this when you need to handle both versions.\n */\nexport const PaymentRequirementsSchema = z.union([\n PaymentRequirementsV1Schema,\n PaymentRequirementsV2Schema,\n]);\nexport type PaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;\n\n/**\n * PaymentRequired union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentRequiredSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentRequiredV1Schema,\n PaymentRequiredV2Schema,\n]);\nexport type PaymentRequired = z.infer<typeof PaymentRequiredSchema>;\n\n/**\n * PaymentPayload union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentPayloadSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentPayloadV1Schema,\n PaymentPayloadV2Schema,\n]);\nexport type PaymentPayload = z.infer<typeof PaymentPayloadSchema>;\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n/**\n * Validates a PaymentRequired object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequired(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequired> {\n return PaymentRequiredSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequired object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequired\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequired(value: unknown): PaymentRequired {\n return PaymentRequiredSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequired (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequired\n */\nexport function isPaymentRequired(value: unknown): value is PaymentRequired {\n return PaymentRequiredSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentRequirements object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequirements(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequirements> {\n return PaymentRequirementsSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequirements object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequirements\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequirements(value: unknown): PaymentRequirements {\n return PaymentRequirementsSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequirements (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirements\n */\nexport function isPaymentRequirements(value: unknown): value is PaymentRequirements {\n return PaymentRequirementsSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentPayload object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentPayload(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentPayload> {\n return PaymentPayloadSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentPayload object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentPayload\n * @throws ZodError if validation fails\n */\nexport function validatePaymentPayload(value: unknown): PaymentPayload {\n return PaymentPayloadSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentPayload (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayload\n */\nexport function isPaymentPayload(value: unknown): value is PaymentPayload {\n return PaymentPayloadSchema.safeParse(value).success;\n}\n\n// ============================================================================\n// Version-Specific Type Guards\n// ============================================================================\n\n/**\n * Type guard for PaymentRequiredV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV1\n */\nexport function isPaymentRequiredV1(value: unknown): value is PaymentRequiredV1 {\n return PaymentRequiredV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequiredV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV2\n */\nexport function isPaymentRequiredV2(value: unknown): value is PaymentRequiredV2 {\n return PaymentRequiredV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV1\n */\nexport function isPaymentRequirementsV1(value: unknown): value is PaymentRequirementsV1 {\n return PaymentRequirementsV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV2\n */\nexport function isPaymentRequirementsV2(value: unknown): value is PaymentRequirementsV2 {\n return PaymentRequirementsV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV1\n */\nexport function isPaymentPayloadV1(value: unknown): value is PaymentPayloadV1 {\n return PaymentPayloadV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV2\n */\nexport function isPaymentPayloadV2(value: unknown): value is PaymentPayloadV2 {\n return PaymentPayloadV2Schema.safeParse(value).success;\n}\n\n// ============================================================================\n// Re-export zod for convenience\n// ============================================================================\n\nexport { z } from \"zod\";\n"],"mappings":"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","names":["import_zod"]}
{"version":3,"sources":["../../../src/schemas/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ============================================================================\n// Reusable Primitive Schemas\n// ============================================================================\n\n/**\n * Non-empty string schema - a string with at least one character.\n * Used for required string fields that cannot be empty.\n */\nexport const NonEmptyString = z.string().min(1);\nexport type NonEmptyString = z.infer<typeof NonEmptyString>;\n\n/**\n * Any record schema - an object with unknown keys and values.\n * Used for scheme-specific payloads and other extensible objects.\n */\nexport const Any = z.record(z.unknown());\nexport type Any = z.infer<typeof Any>;\n\n/**\n * Optional any record schema - an optional object with unknown keys and values.\n * Used for optional extension fields like `extra` and `extensions`.\n */\nexport const OptionalAny = z.record(z.unknown()).optional().nullable();\nexport type OptionalAny = z.infer<typeof OptionalAny>;\n\n// ============================================================================\n// Network Schemas\n// ============================================================================\n\n/**\n * Network identifier schema for V1 - loose validation.\n * V1 accepts any non-empty string for backwards compatibility.\n */\nexport const NetworkSchemaV1 = NonEmptyString;\nexport type NetworkV1 = z.infer<typeof NetworkSchemaV1>;\n\n/**\n * Network identifier schema for V2 - CAIP-2 format validation.\n * V2 requires minimum length of 3 and a colon separator (e.g., \"eip155:84532\", \"solana:devnet\").\n */\nexport const NetworkSchemaV2 = z\n .string()\n .min(3)\n .refine(val => val.includes(\":\"), {\n message: \"Network must be in CAIP-2 format (e.g., 'eip155:84532')\",\n });\nexport type NetworkV2 = z.infer<typeof NetworkSchemaV2>;\n\n/**\n * Union network schema - accepts either V1 or V2 format.\n */\nexport const NetworkSchema = z.union([NetworkSchemaV1, NetworkSchemaV2]);\nexport type Network = z.infer<typeof NetworkSchema>;\n\n// ============================================================================\n// Shared Schemas\n// ============================================================================\n\n/**\n * ResourceInfo schema for V2 - describes the protected resource.\n */\n// Printable ASCII (U+0020–U+007E) — matches the bazaar-facilitator\n// `isValidServiceName` / `sanitizeTags` regex. Constraining to ASCII keeps\n// the length cap consistent across TS / Python / Go (where String.length /\n// len() / len() otherwise diverge for multi-byte input).\nconst PRINTABLE_ASCII_REGEX = /^[\\x20-\\x7e]+$/;\n\nexport const ResourceInfoSchema = z.object({\n url: NonEmptyString,\n description: z.string().optional(),\n mimeType: z.string().optional(),\n serviceName: z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX).optional(),\n tags: z.array(z.string().min(1).max(32).regex(PRINTABLE_ASCII_REGEX)).max(5).optional(),\n iconUrl: z.string().max(2048).optional(),\n});\nexport type ResourceInfo = z.infer<typeof ResourceInfoSchema>;\n\n// ============================================================================\n// V1 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V1.\n * V1 includes resource info directly in the requirements object.\n */\nexport const PaymentRequirementsV1Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n maxAmountRequired: NonEmptyString,\n resource: NonEmptyString, // URL string in V1\n description: z.string(),\n mimeType: z.string().optional(),\n outputSchema: Any.optional().nullable(),\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n asset: NonEmptyString,\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV1 = z.infer<typeof PaymentRequirementsV1Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V1.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV1Schema = z.object({\n x402Version: z.literal(1),\n error: z.string().optional(),\n accepts: z.array(PaymentRequirementsV1Schema).min(1),\n});\nexport type PaymentRequiredV1 = z.infer<typeof PaymentRequiredV1Schema>;\n\n/**\n * PaymentPayload schema for V1.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV1Schema = z.object({\n x402Version: z.literal(1),\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n payload: Any,\n});\nexport type PaymentPayloadV1 = z.infer<typeof PaymentPayloadV1Schema>;\n\n// ============================================================================\n// V2 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V2.\n * V2 uses \"amount\" instead of \"maxAmountRequired\" and doesn't include resource info.\n */\nexport const PaymentRequirementsV2Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV2,\n amount: NonEmptyString,\n asset: NonEmptyString,\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV2 = z.infer<typeof PaymentRequirementsV2Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V2.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV2Schema = z.object({\n x402Version: z.literal(2),\n error: z.string().optional(),\n resource: ResourceInfoSchema,\n accepts: z.array(PaymentRequirementsV2Schema).min(1),\n extensions: OptionalAny,\n});\nexport type PaymentRequiredV2 = z.infer<typeof PaymentRequiredV2Schema>;\n\n/**\n * PaymentPayload schema for V2.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV2Schema = z.object({\n x402Version: z.literal(2),\n resource: ResourceInfoSchema.optional(),\n accepted: PaymentRequirementsV2Schema,\n payload: Any,\n extensions: OptionalAny,\n});\nexport type PaymentPayloadV2 = z.infer<typeof PaymentPayloadV2Schema>;\n\n// ============================================================================\n// Union Schemas (V1 | V2)\n// ============================================================================\n\n/**\n * PaymentRequirements union schema - accepts either V1 or V2 format.\n * Use this when you need to handle both versions.\n */\nexport const PaymentRequirementsSchema = z.union([\n PaymentRequirementsV1Schema,\n PaymentRequirementsV2Schema,\n]);\nexport type PaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;\n\n/**\n * PaymentRequired union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentRequiredSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentRequiredV1Schema,\n PaymentRequiredV2Schema,\n]);\nexport type PaymentRequired = z.infer<typeof PaymentRequiredSchema>;\n\n/**\n * PaymentPayload union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentPayloadSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentPayloadV1Schema,\n PaymentPayloadV2Schema,\n]);\nexport type PaymentPayload = z.infer<typeof PaymentPayloadSchema>;\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n/**\n * Validates a PaymentRequired object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequired(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequired> {\n return PaymentRequiredSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequired object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequired\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequired(value: unknown): PaymentRequired {\n return PaymentRequiredSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequired (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequired\n */\nexport function isPaymentRequired(value: unknown): value is PaymentRequired {\n return PaymentRequiredSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentRequirements object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequirements(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequirements> {\n return PaymentRequirementsSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequirements object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequirements\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequirements(value: unknown): PaymentRequirements {\n return PaymentRequirementsSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequirements (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirements\n */\nexport function isPaymentRequirements(value: unknown): value is PaymentRequirements {\n return PaymentRequirementsSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentPayload object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentPayload(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentPayload> {\n return PaymentPayloadSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentPayload object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentPayload\n * @throws ZodError if validation fails\n */\nexport function validatePaymentPayload(value: unknown): PaymentPayload {\n return PaymentPayloadSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentPayload (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayload\n */\nexport function isPaymentPayload(value: unknown): value is PaymentPayload {\n return PaymentPayloadSchema.safeParse(value).success;\n}\n\n// ============================================================================\n// Version-Specific Type Guards\n// ============================================================================\n\n/**\n * Type guard for PaymentRequiredV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV1\n */\nexport function isPaymentRequiredV1(value: unknown): value is PaymentRequiredV1 {\n return PaymentRequiredV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequiredV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV2\n */\nexport function isPaymentRequiredV2(value: unknown): value is PaymentRequiredV2 {\n return PaymentRequiredV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV1\n */\nexport function isPaymentRequirementsV1(value: unknown): value is PaymentRequirementsV1 {\n return PaymentRequirementsV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV2\n */\nexport function isPaymentRequirementsV2(value: unknown): value is PaymentRequirementsV2 {\n return PaymentRequirementsV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV1\n */\nexport function isPaymentPayloadV1(value: unknown): value is PaymentPayloadV1 {\n return PaymentPayloadV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV2\n */\nexport function isPaymentPayloadV2(value: unknown): value is PaymentPayloadV2 {\n return PaymentPayloadV2Schema.safeParse(value).success;\n}\n\n// ============================================================================\n// Re-export zod for convenience\n// ============================================================================\n\nexport { z } from \"zod\";\n"],"mappings":"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","names":["import_zod"]}

@@ -1,4 +0,4 @@

import { a as PaymentRequirements, S as SettleResponse } from '../mechanisms-C6YmSXgy.js';
export { q as AfterSettleHook, A as AfterVerifyHook, p as BeforeSettleHook, B as BeforeVerifyHook, d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, r as OnSettleFailureHook, O as OnVerifyFailureHook, h as PaymentRequiredContext, R as ResourceConfig, l as SettleContext, n as SettleFailureContext, m as SettleResultContext, o as SettlementOverrides, i as VerifyContext, k as VerifyFailureContext, j as VerifyResultContext, g as getFacilitatorResponseError, x as x402ResourceServer } from '../mechanisms-C6YmSXgy.js';
export { C as CompiledRoute, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, p as SETTLEMENT_OVERRIDES_HEADER, S as SettlementFailedResponseBody, U as UnpaidResponseBody, q as checkIfBazaarNeeded, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-CVhfZSvj.js';
import { a as PaymentRequirements, S as SettleResponse } from '../x402Client-DmgwYAFT.js';
export { w as AfterSettleHook, A as AfterVerifyHook, v as BeforeSettleHook, B as BeforeVerifyHook, d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, y as OnSettleFailureHook, z as OnVerifiedPaymentCanceledHook, O as OnVerifyFailureHook, r as PaymentCancellationDispatcher, h as PaymentRequiredContext, R as ResourceConfig, u as ResourceVerifyRespone, C as SchemeEnrichPaymentRequiredResponseHook, E as SchemeEnrichSettlementPayloadHook, G as SchemeEnrichSettlementResponseHook, D as SchemePaymentRequiredContext, l as SettleContext, n as SettleFailureContext, m as SettleResultContext, s as SettlementOverrides, t as SkipHandlerDirective, q as VerifiedPaymentCancelOptions, o as VerifiedPaymentCanceledContext, p as VerifiedPaymentCancellationReason, i as VerifyContext, k as VerifyFailureContext, j as VerifyResultContext, g as getFacilitatorResponseError, x as x402ResourceServer } from '../x402Client-DmgwYAFT.js';
export { C as CompiledRoute, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, p as SETTLEMENT_OVERRIDES_HEADER, S as SettlementFailedResponseBody, U as UnpaidResponseBody, q as checkIfBazaarNeeded, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-D1-CDqp9.js';

@@ -33,2 +33,11 @@ /**

/**
* Ensures scheme 402 enrichment only adds `extra` keys to matching accepts.
*
* @param baseline - Snapshot before the scheme enrich step
* @param current - Live `accepts` entries after scheme enrichment
* @param scheme - Scheme whose hook was invoked
* @param network - Network whose hook was invoked
*/
declare function assertAcceptsAdditiveExtraAfterSchemeEnrich(baseline: PaymentRequirements[], current: PaymentRequirements[], scheme: string, network: string): void;
/**
* Immutable subset of {@link SettleResponse} compared across settlement extension enrich.

@@ -54,3 +63,20 @@ */

declare function assertSettleResponseCoreUnchanged(before: SettleResponseCoreSnapshot, after: SettleResponse, extensionKey: string): void;
/**
* Ensures scheme settlement-payload enrichment only adds server-owned fields.
*
* @param payload - Existing scheme payload before enrichment
* @param enrichment - Fields returned by the scheme enrichment hook
* @param callerLabel - Hook source label used in policy error messages
*/
declare function assertAdditivePayloadEnrichment(payload: Record<string, unknown>, enrichment: Record<string, unknown>, callerLabel: string): void;
/**
* Ensures scheme response enrichment only adds new `extra` fields, including nested fields
* below existing objects.
*
* @param extra - Existing settlement extra fields
* @param enrichment - Fields returned by the scheme response enrichment hook
* @param callerLabel - Hook label used in policy error messages
*/
declare function assertAdditiveSettlementExtra(extra: Record<string, unknown>, enrichment: Record<string, unknown>, callerLabel: string): void;
export { type SettleResponseCoreSnapshot, assertAcceptsAllowlistedAfterExtensionEnrich, assertSettleResponseCoreUnchanged, isVacantStringField, snapshotPaymentRequirementsList, snapshotSettleResponseCore };
export { type SettleResponseCoreSnapshot, assertAcceptsAdditiveExtraAfterSchemeEnrich, assertAcceptsAllowlistedAfterExtensionEnrich, assertAdditivePayloadEnrichment, assertAdditiveSettlementExtra, assertSettleResponseCoreUnchanged, isVacantStringField, snapshotPaymentRequirementsList, snapshotSettleResponseCore };

@@ -1,1 +0,1 @@

export { E as AssetAmount, $ as DeepReadonly, Y as FacilitatorContext, F as FacilitatorExtension, f as FacilitatorResponseError, M as Money, U as MoneyParser, N as Network, P as PaymentPayload, X as PaymentPayloadContext, W as PaymentPayloadResult, w as PaymentPayloadV1, c as PaymentRequired, h as PaymentRequiredContext, v as PaymentRequiredV1, a as PaymentRequirements, u as PaymentRequirementsV1, s as Price, Q as ResourceInfo, Z as ResourceServerExtension, _ as ResourceServerExtensionHooks, t as SchemeNetworkClient, b as SchemeNetworkFacilitator, T as SchemeNetworkServer, l as SettleContext, L as SettleError, n as SettleFailureContext, I as SettleRequest, S as SettleResponse, m as SettleResultContext, J as SupportedResponse, i as VerifyContext, K as VerifyError, k as VerifyFailureContext, G as VerifyRequest, V as VerifyResponse, j as VerifyResultContext, g as getFacilitatorResponseError } from '../mechanisms-C6YmSXgy.js';
export { a9 as AssetAmount, ar as DeepReadonly, ao as FacilitatorContext, F as FacilitatorExtension, f as FacilitatorResponseError, a8 as Money, al as MoneyParser, N as Network, P as PaymentPayload, an as PaymentPayloadContext, am as PaymentPayloadResult, a3 as PaymentPayloadV1, c as PaymentRequired, h as PaymentRequiredContext, a2 as PaymentRequiredV1, a as PaymentRequirements, a1 as PaymentRequirementsV1, I as Price, ag as ResourceInfo, ap as ResourceServerExtension, aq as ResourceServerExtensionHooks, ai as SchemeClientHooks, C as SchemeEnrichPaymentRequiredResponseHook, ah as SchemeNetworkClient, b as SchemeNetworkFacilitator, aj as SchemeNetworkServer, D as SchemePaymentRequiredContext, ak as SchemeServerHooks, l as SettleContext, af as SettleError, n as SettleFailureContext, ab as SettleRequest, S as SettleResponse, m as SettleResultContext, ad as SupportedKind, ac as SupportedResponse, o as VerifiedPaymentCanceledContext, i as VerifyContext, ae as VerifyError, k as VerifyFailureContext, aa as VerifyRequest, V as VerifyResponse, j as VerifyResultContext, g as getFacilitatorResponseError } from '../x402Client-DmgwYAFT.js';

@@ -36,3 +36,3 @@ "use strict";

* @param statusCode - HTTP status code from the facilitator
* @param response - The verify response containing error details
* @param response - The verify response containing failure details
*/

@@ -39,0 +39,0 @@ constructor(statusCode, response) {

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../src/types/index.ts","../../../src/types/facilitator.ts"],"sourcesContent":["export type {\n VerifyRequest,\n VerifyResponse,\n SettleRequest,\n SettleResponse,\n SupportedResponse,\n} from \"./facilitator\";\nexport {\n VerifyError,\n SettleError,\n FacilitatorResponseError,\n getFacilitatorResponseError,\n} from \"./facilitator\";\nexport type {\n PaymentRequirements,\n PaymentPayload,\n PaymentRequired,\n ResourceInfo,\n} from \"./payments\";\nexport type {\n SchemeNetworkClient,\n SchemeNetworkFacilitator,\n SchemeNetworkServer,\n MoneyParser,\n PaymentPayloadResult,\n PaymentPayloadContext,\n FacilitatorContext,\n} from \"./mechanisms\";\nexport type { PaymentRequirementsV1, PaymentRequiredV1, PaymentPayloadV1 } from \"./v1\";\nexport type {\n FacilitatorExtension,\n ResourceServerExtension,\n ResourceServerExtensionHooks,\n PaymentRequiredContext,\n SettleResultContext,\n VerifyContext,\n VerifyResultContext,\n VerifyFailureContext,\n SettleContext,\n SettleFailureContext,\n} from \"./extensions\";\n\nexport type { DeepReadonly } from \"./readonly\";\n\nexport type Network = `${string}:${string}`;\n\nexport type Money = string | number;\nexport type AssetAmount = {\n asset: string;\n amount: string;\n extra?: Record<string, unknown>;\n};\nexport type Price = Money | AssetAmount;\n","import { PaymentPayload, PaymentRequirements } from \"./payments\";\nimport { Network } from \"./\";\n\nexport type VerifyRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type VerifyResponse = {\n isValid: boolean;\n invalidReason?: string;\n invalidMessage?: string;\n payer?: string;\n extensions?: Record<string, unknown>;\n};\n\nexport type SettleRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type SettleResponse = {\n success: boolean;\n errorReason?: string;\n errorMessage?: string;\n payer?: string;\n transaction: string;\n network: Network;\n /** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */\n amount?: string;\n extensions?: Record<string, unknown>;\n};\n\nexport type SupportedKind = {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n};\n\nexport type SupportedResponse = {\n kinds: SupportedKind[];\n extensions: string[];\n signers: Record<string, string[]>; // CAIP family pattern → Signer addresses\n};\n\n/**\n * Error thrown when payment verification fails.\n */\nexport class VerifyError extends Error {\n readonly invalidReason?: string;\n readonly invalidMessage?: string;\n readonly payer?: string;\n readonly statusCode: number;\n\n /**\n * Creates a VerifyError from a failed verification response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The verify response containing error details\n */\n constructor(statusCode: number, response: VerifyResponse) {\n const reason = response.invalidReason || \"unknown reason\";\n const message = response.invalidMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"VerifyError\";\n this.statusCode = statusCode;\n this.invalidReason = response.invalidReason;\n this.invalidMessage = response.invalidMessage;\n this.payer = response.payer;\n }\n}\n\n/**\n * Error thrown when payment settlement fails.\n */\nexport class SettleError extends Error {\n readonly errorReason?: string;\n readonly errorMessage?: string;\n readonly payer?: string;\n readonly transaction: string;\n readonly network: Network;\n readonly statusCode: number;\n\n /**\n * Creates a SettleError from a failed settlement response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The settle response containing error details\n */\n constructor(statusCode: number, response: SettleResponse) {\n const reason = response.errorReason || \"unknown reason\";\n const message = response.errorMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"SettleError\";\n this.statusCode = statusCode;\n this.errorReason = response.errorReason;\n this.errorMessage = response.errorMessage;\n this.payer = response.payer;\n this.transaction = response.transaction;\n this.network = response.network;\n }\n}\n\n/**\n * Error thrown when a facilitator returns malformed success payload data.\n */\nexport class FacilitatorResponseError extends Error {\n /**\n * Creates a FacilitatorResponseError for malformed facilitator responses.\n *\n * @param message - The boundary error message\n */\n constructor(message: string) {\n super(message);\n this.name = \"FacilitatorResponseError\";\n }\n}\n\n/**\n * Walks an error cause chain to find the first facilitator response error.\n *\n * @param error - The thrown value to inspect\n * @returns The nested facilitator response error, if present\n */\nexport function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null {\n let current = error;\n\n while (current instanceof Error) {\n if (current instanceof FacilitatorResponseError) {\n return current;\n }\n current = current.cause;\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmDO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,iBAAiB;AACzC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,gBAAgB,SAAS;AAC9B,SAAK,iBAAiB,SAAS;AAC/B,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAKO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,eAAe;AACvC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,cAAc,SAAS;AAC5B,SAAK,eAAe,SAAS;AAC7B,SAAK,QAAQ,SAAS;AACtB,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,SAAS;AAAA,EAC1B;AACF;AAKO,IAAM,2BAAN,cAAuC,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAQO,SAAS,4BAA4B,OAAiD;AAC3F,MAAI,UAAU;AAEd,SAAO,mBAAmB,OAAO;AAC/B,QAAI,mBAAmB,0BAA0B;AAC/C,aAAO;AAAA,IACT;AACA,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;","names":[]}
{"version":3,"sources":["../../../src/types/index.ts","../../../src/types/facilitator.ts"],"sourcesContent":["export type {\n VerifyRequest,\n VerifyResponse,\n SettleRequest,\n SettleResponse,\n SupportedResponse,\n SupportedKind,\n} from \"./facilitator\";\nexport {\n VerifyError,\n SettleError,\n FacilitatorResponseError,\n getFacilitatorResponseError,\n} from \"./facilitator\";\nexport type {\n PaymentRequirements,\n PaymentPayload,\n PaymentRequired,\n ResourceInfo,\n} from \"./payments\";\nexport type {\n SchemeNetworkClient,\n SchemeClientHooks,\n SchemeNetworkFacilitator,\n SchemeNetworkServer,\n SchemeServerHooks,\n MoneyParser,\n PaymentPayloadResult,\n PaymentPayloadContext,\n FacilitatorContext,\n SchemePaymentRequiredContext,\n SchemeEnrichPaymentRequiredResponseHook,\n} from \"./mechanisms\";\nexport type { PaymentRequirementsV1, PaymentRequiredV1, PaymentPayloadV1 } from \"./v1\";\nexport type {\n FacilitatorExtension,\n ResourceServerExtension,\n ResourceServerExtensionHooks,\n PaymentRequiredContext,\n SettleResultContext,\n VerifyContext,\n VerifyResultContext,\n VerifyFailureContext,\n SettleContext,\n SettleFailureContext,\n VerifiedPaymentCanceledContext,\n} from \"./extensions\";\n\nexport type { DeepReadonly } from \"./readonly\";\n\nexport type Network = `${string}:${string}`;\n\nexport type Money = string | number;\nexport type AssetAmount = {\n asset: string;\n amount: string;\n extra?: Record<string, unknown>;\n};\nexport type Price = Money | AssetAmount;\n","import { PaymentPayload, PaymentRequirements } from \"./payments\";\nimport { Network } from \"./\";\n\nexport type VerifyRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type VerifyResponse = {\n isValid: boolean;\n invalidReason?: string;\n invalidMessage?: string;\n payer?: string;\n extensions?: Record<string, unknown>;\n extra?: Record<string, unknown>;\n};\n\nexport type SettleRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type SettleResponse = {\n success: boolean;\n errorReason?: string;\n errorMessage?: string;\n payer?: string;\n transaction: string;\n network: Network;\n /** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */\n amount?: string;\n extensions?: Record<string, unknown>;\n extra?: Record<string, unknown>;\n};\n\nexport type SupportedKind = {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n};\n\nexport type SupportedResponse = {\n kinds: SupportedKind[];\n extensions: string[];\n signers: Record<string, string[]>; // CAIP family pattern → Signer addresses\n};\n\n/**\n * Error thrown when payment verification fails.\n */\nexport class VerifyError extends Error {\n readonly invalidReason?: string;\n readonly invalidMessage?: string;\n readonly payer?: string;\n readonly statusCode: number;\n\n /**\n * Creates a VerifyError from a failed verification response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The verify response containing failure details\n */\n constructor(statusCode: number, response: VerifyResponse) {\n const reason = response.invalidReason || \"unknown reason\";\n const message = response.invalidMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"VerifyError\";\n this.statusCode = statusCode;\n this.invalidReason = response.invalidReason;\n this.invalidMessage = response.invalidMessage;\n this.payer = response.payer;\n }\n}\n\n/**\n * Error thrown when payment settlement fails.\n */\nexport class SettleError extends Error {\n readonly errorReason?: string;\n readonly errorMessage?: string;\n readonly payer?: string;\n readonly transaction: string;\n readonly network: Network;\n readonly statusCode: number;\n\n /**\n * Creates a SettleError from a failed settlement response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The settle response containing error details\n */\n constructor(statusCode: number, response: SettleResponse) {\n const reason = response.errorReason || \"unknown reason\";\n const message = response.errorMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"SettleError\";\n this.statusCode = statusCode;\n this.errorReason = response.errorReason;\n this.errorMessage = response.errorMessage;\n this.payer = response.payer;\n this.transaction = response.transaction;\n this.network = response.network;\n }\n}\n\n/**\n * Error thrown when a facilitator returns malformed success payload data.\n */\nexport class FacilitatorResponseError extends Error {\n /**\n * Creates a FacilitatorResponseError for malformed facilitator responses.\n *\n * @param message - The boundary error message\n */\n constructor(message: string) {\n super(message);\n this.name = \"FacilitatorResponseError\";\n }\n}\n\n/**\n * Walks an error cause chain to find the first facilitator response error.\n *\n * @param error - The thrown value to inspect\n * @returns The nested facilitator response error, if present\n */\nexport function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null {\n let current = error;\n\n while (current instanceof Error) {\n if (current instanceof FacilitatorResponseError) {\n return current;\n }\n current = current.cause;\n }\n\n return null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqDO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,iBAAiB;AACzC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,gBAAgB,SAAS;AAC9B,SAAK,iBAAiB,SAAS;AAC/B,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAKO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,eAAe;AACvC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,cAAc,SAAS;AAC5B,SAAK,eAAe,SAAS;AAC7B,SAAK,QAAQ,SAAS;AACtB,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,SAAS;AAAA,EAC1B;AACF;AAKO,IAAM,2BAAN,cAAuC,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAQO,SAAS,4BAA4B,OAAiD;AAC3F,MAAI,UAAU;AAEd,SAAO,mBAAmB,OAAO;AAC/B,QAAI,mBAAmB,0BAA0B;AAC/C,aAAO;AAAA,IACT;AACA,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;","names":[]}

@@ -1,1 +0,1 @@

export { w as PaymentPayloadV1, v as PaymentRequiredV1, u as PaymentRequirementsV1, z as SettleRequestV1, C as SettleResponseV1, D as SupportedResponseV1, y as VerifyRequestV1 } from '../../mechanisms-C6YmSXgy.js';
export { a3 as PaymentPayloadV1, a2 as PaymentRequiredV1, a1 as PaymentRequirementsV1, a5 as SettleRequestV1, a6 as SettleResponseV1, a7 as SupportedResponseV1, a4 as VerifyRequestV1 } from '../../x402Client-DmgwYAFT.js';

@@ -1,2 +0,2 @@

import { N as Network } from '../mechanisms-C6YmSXgy.js';
import { N as Network } from '../x402Client-DmgwYAFT.js';

@@ -3,0 +3,0 @@ /**

@@ -1,255 +0,5 @@

import { c as PaymentRequired, a as PaymentRequirements, P as PaymentPayload, N as Network, t as SchemeNetworkClient, S as SettleResponse } from '../mechanisms-C6YmSXgy.mjs';
import { c as PaymentRequired, J as x402Client, P as PaymentPayload, S as SettleResponse } from '../x402Client-DmgwYAFT.mjs';
export { T as AfterPaymentCreationHook, Q as BeforePaymentCreationHook, Z as ClientExtension, U as OnPaymentCreationFailureHook, X as OnPaymentResponseHook, L as PaymentCreatedContext, K as PaymentCreationContext, M as PaymentCreationFailureContext, _ as PaymentPolicy, W as PaymentResponseContext, $ as SchemeRegistration, Y as SelectPaymentRequirements, a0 as x402ClientConfig } from '../x402Client-DmgwYAFT.mjs';
/**
* Client Hook Context Interfaces
*/
interface PaymentCreationContext {
paymentRequired: PaymentRequired;
selectedRequirements: PaymentRequirements;
}
interface PaymentCreatedContext extends PaymentCreationContext {
paymentPayload: PaymentPayload;
}
interface PaymentCreationFailureContext extends PaymentCreationContext {
error: Error;
}
/**
* Client Hook Type Definitions
*/
type BeforePaymentCreationHook = (context: PaymentCreationContext) => Promise<void | {
abort: true;
reason: string;
}>;
type AfterPaymentCreationHook = (context: PaymentCreatedContext) => Promise<void>;
type OnPaymentCreationFailureHook = (context: PaymentCreationFailureContext) => Promise<void | {
recovered: true;
payload: PaymentPayload;
}>;
type SelectPaymentRequirements = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements;
/**
* Extension that can enrich payment payloads on the client side.
*
* Client extensions are invoked after the scheme creates the base payment payload
* but before it is returned. This allows mechanism-specific logic (e.g., EVM EIP-2612
* permit signing) to enrich the payload's extensions data.
*/
interface ClientExtension {
/**
* Unique key identifying this extension (e.g., "eip2612GasSponsoring").
* Must match the extension key used in PaymentRequired.extensions.
*/
key: string;
/**
* Called after payload creation when the extension key is present in
* paymentRequired.extensions. Allows the extension to enrich the payload
* with extension-specific data (e.g., signing an EIP-2612 permit).
*
* @param paymentPayload - The payment payload to enrich
* @param paymentRequired - The original PaymentRequired response
* @returns The enriched payment payload
*/
enrichPaymentPayload?: (paymentPayload: PaymentPayload, paymentRequired: PaymentRequired) => Promise<PaymentPayload>;
}
/**
* A policy function that filters or transforms payment requirements.
* Policies are applied in order before the selector chooses the final option.
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of payment requirements to filter/transform
* @returns Filtered array of payment requirements
*/
type PaymentPolicy = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements[];
/**
* Configuration for registering a payment scheme with a specific network
*/
interface SchemeRegistration {
/**
* The network identifier (e.g., 'eip155:8453', 'solana:mainnet')
*/
network: Network;
/**
* The scheme client implementation for this network
*/
client: SchemeNetworkClient;
/**
* The x402 protocol version to use for this scheme
*
* @default 2
*/
x402Version?: number;
}
/**
* Configuration options for the fetch wrapper
*/
interface x402ClientConfig {
/**
* Array of scheme registrations defining which payment methods are supported
*/
schemes: SchemeRegistration[];
/**
* Policies to apply to the client
*/
policies?: PaymentPolicy[];
/**
* Custom payment requirements selector function
* If not provided, uses the default selector (first available option)
*/
paymentRequirementsSelector?: SelectPaymentRequirements;
}
/**
* Core client for managing x402 payment schemes and creating payment payloads.
*
* Handles registration of payment schemes, policy-based filtering of payment requirements,
* and creation of payment payloads based on server requirements.
*/
declare class x402Client {
private readonly paymentRequirementsSelector;
private readonly registeredClientSchemes;
private readonly policies;
private readonly registeredExtensions;
private beforePaymentCreationHooks;
private afterPaymentCreationHooks;
private onPaymentCreationFailureHooks;
/**
* Creates a new x402Client instance.
*
* @param paymentRequirementsSelector - Function to select payment requirements from available options
*/
constructor(paymentRequirementsSelector?: SelectPaymentRequirements);
/**
* Creates a new x402Client instance from a configuration object.
*
* @param config - The client configuration including schemes, policies, and payment requirements selector
* @returns A configured x402Client instance
*/
static fromConfig(config: x402ClientConfig): x402Client;
/**
* Registers a scheme client for the current x402 version.
*
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
register(network: Network, client: SchemeNetworkClient): x402Client;
/**
* Registers a scheme client for x402 version 1.
*
* @param network - The v1 network identifier (e.g., 'base-sepolia', 'solana-devnet')
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
registerV1(network: string, client: SchemeNetworkClient): x402Client;
/**
* Registers a policy to filter or transform payment requirements.
*
* Policies are applied in order after filtering by registered schemes
* and before the selector chooses the final payment requirement.
*
* @param policy - Function to filter/transform payment requirements
* @returns The x402Client instance for chaining
*
* @example
* ```typescript
* // Prefer cheaper options
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => BigInt(r.value) < BigInt('1000000'))
* );
*
* // Prefer specific networks
* client.registerPolicy((version, reqs) =>
* reqs.filter(r => r.network.startsWith('eip155:'))
* );
* ```
*/
registerPolicy(policy: PaymentPolicy): x402Client;
/**
* Registers a client extension that can enrich payment payloads.
*
* Extensions are invoked after the scheme creates the base payload and the
* payload is wrapped with extensions/resource/accepted data. If the extension's
* key is present in `paymentRequired.extensions`, the extension's
* `enrichPaymentPayload` hook is called to modify the payload.
*
* @param extension - The client extension to register
* @returns The x402Client instance for chaining
*/
registerExtension(extension: ClientExtension): x402Client;
/**
* Register a hook to execute before payment payload creation.
* Can abort creation by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onBeforePaymentCreation(hook: BeforePaymentCreationHook): x402Client;
/**
* Register a hook to execute after successful payment payload creation.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onAfterPaymentCreation(hook: AfterPaymentCreationHook): x402Client;
/**
* Register a hook to execute when payment payload creation fails.
* Can recover from failure by returning { recovered: true, payload: PaymentPayload }
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentCreationFailure(hook: OnPaymentCreationFailureHook): x402Client;
/**
* Creates a payment payload based on a PaymentRequired response.
*
* Automatically extracts x402Version, resource, and extensions from the PaymentRequired
* response and constructs a complete PaymentPayload with the accepted requirements.
*
* @param paymentRequired - The PaymentRequired response from the server
* @returns Promise resolving to the complete payment payload
*/
createPaymentPayload(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
/**
* Merges server-declared extensions with scheme-provided extensions.
* Scheme extensions overlay on top of server extensions at each key,
* preserving server-provided schema while overlaying scheme-provided info.
*
* @param serverExtensions - Extensions declared by the server in the 402 response
* @param schemeExtensions - Extensions provided by the scheme client (e.g. EIP-2612)
* @returns The merged extensions object, or undefined if both inputs are undefined
*/
private mergeExtensions;
/**
* Enriches a payment payload by calling registered extension hooks.
* For each extension key present in the PaymentRequired response,
* invokes the corresponding extension's enrichPaymentPayload callback.
*
* @param paymentPayload - The payment payload to enrich with extension data
* @param paymentRequired - The PaymentRequired response containing extension declarations
* @returns The enriched payment payload with extension data applied
*/
private enrichPaymentPayloadWithExtensions;
/**
* Selects appropriate payment requirements based on registered clients and policies.
*
* Selection process:
* 1. Filter by registered schemes (network + scheme support)
* 2. Apply all registered policies in order
* 3. Use selector to choose final requirement
*
* @param x402Version - The x402 protocol version
* @param paymentRequirements - Array of available payment requirements
* @returns The selected payment requirements
*/
private selectPaymentRequirements;
/**
* Internal method to register a scheme client.
*
* @param x402Version - The x402 protocol version
* @param network - The network to register the client for
* @param client - The scheme network client to register
* @returns The x402Client instance for chaining
*/
private _registerScheme;
}
/**
* Context provided to onPaymentRequired hooks.

@@ -327,4 +77,53 @@ */

createPaymentPayload(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
/**
* Parses response headers into protocol types, fires payment response hooks,
* and returns whether a hook signaled recovery.
*
* Called by transport wrappers (fetch, axios) after the paid request completes.
*
* @param paymentPayload - The payload that was sent with the request
* @param getHeader - Function to retrieve a response header by name
* @param status - The HTTP status code of the response
* @returns Whether a hook recovered and the parsed settle response (if any)
*/
processPaymentResult(paymentPayload: PaymentPayload, getHeader: (name: string) => string | null | undefined, status: number): Promise<{
recovered: boolean;
settleResponse?: SettleResponse;
}>;
/**
* Parses a fetch Response into a discriminated `x402PaymentResult` for app-level convenience.
*
* @param response - The fetch Response to process
* @returns A discriminated union describing the payment outcome
*/
processResponse(response: Response): Promise<x402PaymentResult>;
}
/**
* Discriminated union describing the outcome of a payment-enabled request.
*/
type x402PaymentResult = {
kind: "success";
response: Response;
body: unknown;
settleResponse: SettleResponse;
} | {
kind: "settle_failed";
response: Response;
body: unknown;
settleResponse: SettleResponse;
} | {
kind: "payment_required";
response: Response;
paymentRequired: PaymentRequired;
} | {
kind: "error";
response: Response;
status: number;
body: unknown;
} | {
kind: "passthrough";
response: Response;
body: unknown;
};
export { type AfterPaymentCreationHook, type BeforePaymentCreationHook, type ClientExtension, type OnPaymentCreationFailureHook, type PaymentCreatedContext, type PaymentCreationContext, type PaymentCreationFailureContext, type PaymentPolicy, type PaymentRequiredContext, type PaymentRequiredHook, type SchemeRegistration, type SelectPaymentRequirements, x402Client, type x402ClientConfig, x402HTTPClient };
export { type PaymentRequiredContext, type PaymentRequiredHook, x402Client, x402HTTPClient, type x402PaymentResult };
import {
x402HTTPClient
} from "../chunk-G3XJUKWR.mjs";
import "../chunk-KMQH4MQI.mjs";
} from "../chunk-FTDK7NUZ.mjs";
import "../chunk-FPXAE3OS.mjs";
import {
x402Version
} from "../chunk-VE37GDG2.mjs";
import "../chunk-JUGE6MAI.mjs";
import "../chunk-AGOUMC4P.mjs";
import {

@@ -24,2 +24,3 @@ findByNetworkAndScheme,

this.registeredClientSchemes = /* @__PURE__ */ new Map();
this.schemeClientHookAdapters = /* @__PURE__ */ new Map();
this.policies = [];

@@ -30,2 +31,3 @@ this.registeredExtensions = /* @__PURE__ */ new Map();

this.onPaymentCreationFailureHooks = [];
this.paymentResponseHooks = [];
this.paymentRequirementsSelector = paymentRequirementsSelector || ((x402Version2, accepts) => accepts[0]);

@@ -147,2 +149,33 @@ }

/**
* Register a hook to execute after a paid request completes.
* Can signal recovery by returning { recovered: true }, causing the transport to retry.
*
* @param hook - The hook function to register
* @returns The x402Client instance for chaining
*/
onPaymentResponse(hook) {
this.paymentResponseHooks.push(hook);
return this;
}
/**
* Fires all registered payment response hooks in order.
* Returns `{ recovered: true }` if any hook signals recovery (first wins).
*
* @param ctx - The payment response context
* @returns Recovery signal or undefined
*/
async handlePaymentResponse(ctx) {
for (const hook of this.getLabeledHooks(
"onPaymentResponse",
ctx.paymentPayload.x402Version,
ctx.requirements
)) {
const result = await hook(ctx);
if (result && "recovered" in result && result.recovered) {
return { recovered: true };
}
}
return void 0;
}
/**
* Creates a payment payload based on a PaymentRequired response.

@@ -166,3 +199,7 @@ *

};
for (const hook of this.beforePaymentCreationHooks) {
for (const hook of this.getLabeledHooks(
"beforePaymentCreation",
paymentRequired.x402Version,
requirements
)) {
const result = await hook(context);

@@ -204,3 +241,7 @@ if (result && "abort" in result && result.abort) {

};
for (const hook of this.afterPaymentCreationHooks) {
for (const hook of this.getLabeledHooks(
"afterPaymentCreation",
paymentRequired.x402Version,
requirements
)) {
await hook(createdContext);

@@ -214,3 +255,7 @@ }

};
for (const hook of this.onPaymentCreationFailureHooks) {
for (const hook of this.getLabeledHooks(
"onPaymentCreationFailure",
paymentRequired.x402Version,
requirements
)) {
const result = await hook(failureContext);

@@ -327,7 +372,69 @@ if (result && "recovered" in result && result.recovered) {

const clientByScheme = clientSchemesByNetwork.get(network);
if (!clientByScheme.has(client.scheme)) {
clientByScheme.set(client.scheme, client);
clientByScheme.set(client.scheme, client);
if (!this.schemeClientHookAdapters.has(x402Version2)) {
this.schemeClientHookAdapters.set(x402Version2, /* @__PURE__ */ new Map());
}
const adaptersByNetwork = this.schemeClientHookAdapters.get(x402Version2);
if (!adaptersByNetwork.has(network)) {
adaptersByNetwork.set(network, /* @__PURE__ */ new Map());
}
const adaptersByScheme = adaptersByNetwork.get(network);
const hooks = client.schemeHooks;
if (!hooks) {
adaptersByScheme.delete(client.scheme);
return this;
}
const handles = {};
if (hooks.onBeforePaymentCreation) {
handles.beforePaymentCreation = hooks.onBeforePaymentCreation;
}
if (hooks.onAfterPaymentCreation) {
handles.afterPaymentCreation = hooks.onAfterPaymentCreation;
}
if (hooks.onPaymentCreationFailure) {
handles.onPaymentCreationFailure = hooks.onPaymentCreationFailure;
}
if (hooks.onPaymentResponse) {
handles.onPaymentResponse = hooks.onPaymentResponse;
}
if (Object.keys(handles).length > 0) {
adaptersByScheme.set(client.scheme, handles);
} else {
adaptersByScheme.delete(client.scheme);
}
return this;
}
/**
* Returns manual hooks followed by the hook for the selected scheme, if present.
*
* @param phase - Hook slot to collect
* @param x402Version - Protocol version for the selected requirement
* @param requirements - Selected payment requirement
* @returns Hooks in invocation order
*/
getLabeledHooks(phase, x402Version2, requirements) {
let manual;
switch (phase) {
case "beforePaymentCreation":
manual = this.beforePaymentCreationHooks;
break;
case "afterPaymentCreation":
manual = this.afterPaymentCreationHooks;
break;
case "onPaymentCreationFailure":
manual = this.onPaymentCreationFailureHooks;
break;
case "onPaymentResponse":
manual = this.paymentResponseHooks;
break;
}
const out = [...manual];
const adaptersByNetwork = this.schemeClientHookAdapters.get(x402Version2);
const schemeAdapter = adaptersByNetwork ? findByNetworkAndScheme(adaptersByNetwork, requirements.scheme, requirements.network) : void 0;
const hook = schemeAdapter?.[phase];
if (hook !== void 0) {
out.push(hook);
}
return out;
}
};

@@ -334,0 +441,0 @@ export {

@@ -1,1 +0,1 @@

{"version":3,"sources":["../../../src/client/x402Client.ts"],"sourcesContent":["import { x402Version } from \"..\";\nimport { SchemeNetworkClient } from \"../types/mechanisms\";\nimport { PaymentPayload, PaymentRequirements } from \"../types/payments\";\nimport { Network, PaymentRequired } from \"../types\";\nimport { findByNetworkAndScheme, findSchemesByNetwork } from \"../utils\";\n\n/**\n * Client Hook Context Interfaces\n */\n\nexport interface PaymentCreationContext {\n paymentRequired: PaymentRequired;\n selectedRequirements: PaymentRequirements;\n}\n\nexport interface PaymentCreatedContext extends PaymentCreationContext {\n paymentPayload: PaymentPayload;\n}\n\nexport interface PaymentCreationFailureContext extends PaymentCreationContext {\n error: Error;\n}\n\n/**\n * Client Hook Type Definitions\n */\n\nexport type BeforePaymentCreationHook = (\n context: PaymentCreationContext,\n) => Promise<void | { abort: true; reason: string }>;\n\nexport type AfterPaymentCreationHook = (context: PaymentCreatedContext) => Promise<void>;\n\nexport type OnPaymentCreationFailureHook = (\n context: PaymentCreationFailureContext,\n) => Promise<void | { recovered: true; payload: PaymentPayload }>;\n\nexport type SelectPaymentRequirements = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements;\n\n/**\n * Extension that can enrich payment payloads on the client side.\n *\n * Client extensions are invoked after the scheme creates the base payment payload\n * but before it is returned. This allows mechanism-specific logic (e.g., EVM EIP-2612\n * permit signing) to enrich the payload's extensions data.\n */\nexport interface ClientExtension {\n /**\n * Unique key identifying this extension (e.g., \"eip2612GasSponsoring\").\n * Must match the extension key used in PaymentRequired.extensions.\n */\n key: string;\n\n /**\n * Called after payload creation when the extension key is present in\n * paymentRequired.extensions. Allows the extension to enrich the payload\n * with extension-specific data (e.g., signing an EIP-2612 permit).\n *\n * @param paymentPayload - The payment payload to enrich\n * @param paymentRequired - The original PaymentRequired response\n * @returns The enriched payment payload\n */\n enrichPaymentPayload?: (\n paymentPayload: PaymentPayload,\n paymentRequired: PaymentRequired,\n ) => Promise<PaymentPayload>;\n}\n\n/**\n * A policy function that filters or transforms payment requirements.\n * Policies are applied in order before the selector chooses the final option.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - Array of payment requirements to filter/transform\n * @returns Filtered array of payment requirements\n */\nexport type PaymentPolicy = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements[];\n\n\n/**\n * Configuration for registering a payment scheme with a specific network\n */\nexport interface SchemeRegistration {\n /**\n * The network identifier (e.g., 'eip155:8453', 'solana:mainnet')\n */\n network: Network;\n\n /**\n * The scheme client implementation for this network\n */\n client: SchemeNetworkClient;\n\n /**\n * The x402 protocol version to use for this scheme\n *\n * @default 2\n */\n x402Version?: number;\n}\n\n/**\n * Configuration options for the fetch wrapper\n */\nexport interface x402ClientConfig {\n /**\n * Array of scheme registrations defining which payment methods are supported\n */\n schemes: SchemeRegistration[];\n\n /**\n * Policies to apply to the client\n */\n policies?: PaymentPolicy[];\n\n /**\n * Custom payment requirements selector function\n * If not provided, uses the default selector (first available option)\n */\n paymentRequirementsSelector?: SelectPaymentRequirements;\n}\n\n/**\n * Core client for managing x402 payment schemes and creating payment payloads.\n *\n * Handles registration of payment schemes, policy-based filtering of payment requirements,\n * and creation of payment payloads based on server requirements.\n */\nexport class x402Client {\n private readonly paymentRequirementsSelector: SelectPaymentRequirements;\n private readonly registeredClientSchemes: Map<number, Map<string, Map<string, SchemeNetworkClient>>> = new Map();\n private readonly policies: PaymentPolicy[] = [];\n private readonly registeredExtensions: Map<string, ClientExtension> = new Map();\n\n private beforePaymentCreationHooks: BeforePaymentCreationHook[] = [];\n private afterPaymentCreationHooks: AfterPaymentCreationHook[] = [];\n private onPaymentCreationFailureHooks: OnPaymentCreationFailureHook[] = [];\n\n /**\n * Creates a new x402Client instance.\n *\n * @param paymentRequirementsSelector - Function to select payment requirements from available options\n */\n constructor(paymentRequirementsSelector?: SelectPaymentRequirements) {\n this.paymentRequirementsSelector = paymentRequirementsSelector || ((x402Version, accepts) => accepts[0]);\n }\n\n /**\n * Creates a new x402Client instance from a configuration object.\n *\n * @param config - The client configuration including schemes, policies, and payment requirements selector\n * @returns A configured x402Client instance\n */\n static fromConfig(config: x402ClientConfig): x402Client {\n const client = new x402Client(config.paymentRequirementsSelector);\n config.schemes.forEach(scheme => {\n if (scheme.x402Version === 1) {\n client.registerV1(scheme.network, scheme.client);\n } else {\n client.register(scheme.network, scheme.client);\n }\n });\n config.policies?.forEach(policy => {\n client.registerPolicy(policy);\n });\n return client;\n }\n\n /**\n * Registers a scheme client for the current x402 version.\n *\n * @param network - The network to register the client for\n * @param client - The scheme network client to register\n * @returns The x402Client instance for chaining\n */\n register(network: Network, client: SchemeNetworkClient): x402Client {\n return this._registerScheme(x402Version, network, client);\n }\n\n /**\n * Registers a scheme client for x402 version 1.\n *\n * @param network - The v1 network identifier (e.g., 'base-sepolia', 'solana-devnet')\n * @param client - The scheme network client to register\n * @returns The x402Client instance for chaining\n */\n registerV1(network: string, client: SchemeNetworkClient): x402Client {\n return this._registerScheme(1, network as Network, client);\n }\n\n /**\n * Registers a policy to filter or transform payment requirements.\n *\n * Policies are applied in order after filtering by registered schemes\n * and before the selector chooses the final payment requirement.\n *\n * @param policy - Function to filter/transform payment requirements\n * @returns The x402Client instance for chaining\n *\n * @example\n * ```typescript\n * // Prefer cheaper options\n * client.registerPolicy((version, reqs) =>\n * reqs.filter(r => BigInt(r.value) < BigInt('1000000'))\n * );\n *\n * // Prefer specific networks\n * client.registerPolicy((version, reqs) =>\n * reqs.filter(r => r.network.startsWith('eip155:'))\n * );\n * ```\n */\n registerPolicy(policy: PaymentPolicy): x402Client {\n this.policies.push(policy);\n return this;\n }\n\n /**\n * Registers a client extension that can enrich payment payloads.\n *\n * Extensions are invoked after the scheme creates the base payload and the\n * payload is wrapped with extensions/resource/accepted data. If the extension's\n * key is present in `paymentRequired.extensions`, the extension's\n * `enrichPaymentPayload` hook is called to modify the payload.\n *\n * @param extension - The client extension to register\n * @returns The x402Client instance for chaining\n */\n registerExtension(extension: ClientExtension): x402Client {\n this.registeredExtensions.set(extension.key, extension);\n return this;\n }\n\n /**\n * Register a hook to execute before payment payload creation.\n * Can abort creation by returning { abort: true, reason: string }\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onBeforePaymentCreation(hook: BeforePaymentCreationHook): x402Client {\n this.beforePaymentCreationHooks.push(hook);\n return this;\n }\n\n /**\n * Register a hook to execute after successful payment payload creation.\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onAfterPaymentCreation(hook: AfterPaymentCreationHook): x402Client {\n this.afterPaymentCreationHooks.push(hook);\n return this;\n }\n\n /**\n * Register a hook to execute when payment payload creation fails.\n * Can recover from failure by returning { recovered: true, payload: PaymentPayload }\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onPaymentCreationFailure(hook: OnPaymentCreationFailureHook): x402Client {\n this.onPaymentCreationFailureHooks.push(hook);\n return this;\n }\n\n /**\n * Creates a payment payload based on a PaymentRequired response.\n *\n * Automatically extracts x402Version, resource, and extensions from the PaymentRequired\n * response and constructs a complete PaymentPayload with the accepted requirements.\n *\n * @param paymentRequired - The PaymentRequired response from the server\n * @returns Promise resolving to the complete payment payload\n */\n async createPaymentPayload(\n paymentRequired: PaymentRequired,\n ): Promise<PaymentPayload> {\n const clientSchemesByNetwork = this.registeredClientSchemes.get(paymentRequired.x402Version);\n if (!clientSchemesByNetwork) {\n throw new Error(`No client registered for x402 version: ${paymentRequired.x402Version}`);\n }\n\n const requirements = this.selectPaymentRequirements(paymentRequired.x402Version, paymentRequired.accepts);\n\n const context: PaymentCreationContext = {\n paymentRequired,\n selectedRequirements: requirements,\n };\n\n // Execute beforePaymentCreation hooks\n for (const hook of this.beforePaymentCreationHooks) {\n const result = await hook(context);\n if (result && \"abort\" in result && result.abort) {\n throw new Error(`Payment creation aborted: ${result.reason}`);\n }\n }\n\n try {\n const schemeNetworkClient = findByNetworkAndScheme(clientSchemesByNetwork, requirements.scheme, requirements.network);\n if (!schemeNetworkClient) {\n throw new Error(`No client registered for scheme: ${requirements.scheme} and network: ${requirements.network}`);\n }\n\n const partialPayload = await schemeNetworkClient.createPaymentPayload(\n paymentRequired.x402Version,\n requirements,\n { extensions: paymentRequired.extensions },\n );\n\n let paymentPayload: PaymentPayload;\n if (partialPayload.x402Version == 1) {\n paymentPayload = partialPayload as PaymentPayload;\n } else {\n // Merge server-declared extensions with any scheme-provided extensions.\n // Scheme extensions overlay on top (e.g., EIP-2612 info enriches server declaration).\n const mergedExtensions = this.mergeExtensions(\n paymentRequired.extensions,\n partialPayload.extensions,\n );\n\n paymentPayload = {\n x402Version: partialPayload.x402Version,\n payload: partialPayload.payload,\n extensions: mergedExtensions,\n resource: paymentRequired.resource,\n accepted: requirements,\n };\n }\n\n // Enrich payload via registered client extensions (for non-scheme extensions)\n paymentPayload = await this.enrichPaymentPayloadWithExtensions(paymentPayload, paymentRequired);\n\n // Execute afterPaymentCreation hooks\n const createdContext: PaymentCreatedContext = {\n ...context,\n paymentPayload,\n };\n\n for (const hook of this.afterPaymentCreationHooks) {\n await hook(createdContext);\n }\n\n return paymentPayload;\n } catch (error) {\n const failureContext: PaymentCreationFailureContext = {\n ...context,\n error: error as Error,\n };\n\n // Execute onPaymentCreationFailure hooks\n for (const hook of this.onPaymentCreationFailureHooks) {\n const result = await hook(failureContext);\n if (result && \"recovered\" in result && result.recovered) {\n return result.payload;\n }\n }\n\n throw error;\n }\n }\n\n\n\n /**\n * Merges server-declared extensions with scheme-provided extensions.\n * Scheme extensions overlay on top of server extensions at each key,\n * preserving server-provided schema while overlaying scheme-provided info.\n *\n * @param serverExtensions - Extensions declared by the server in the 402 response\n * @param schemeExtensions - Extensions provided by the scheme client (e.g. EIP-2612)\n * @returns The merged extensions object, or undefined if both inputs are undefined\n */\n private mergeExtensions(\n serverExtensions?: Record<string, unknown>,\n schemeExtensions?: Record<string, unknown>,\n ): Record<string, unknown> | undefined {\n if (!schemeExtensions) return serverExtensions;\n if (!serverExtensions) return schemeExtensions;\n\n const merged = { ...serverExtensions };\n for (const [key, schemeValue] of Object.entries(schemeExtensions)) {\n const serverValue = merged[key];\n if (\n serverValue &&\n typeof serverValue === \"object\" &&\n schemeValue &&\n typeof schemeValue === \"object\"\n ) {\n // Deep merge: scheme info overlays server info, schema preserved\n merged[key] = { ...serverValue as Record<string, unknown>, ...schemeValue as Record<string, unknown> };\n } else {\n merged[key] = schemeValue;\n }\n }\n return merged;\n }\n\n /**\n * Enriches a payment payload by calling registered extension hooks.\n * For each extension key present in the PaymentRequired response,\n * invokes the corresponding extension's enrichPaymentPayload callback.\n *\n * @param paymentPayload - The payment payload to enrich with extension data\n * @param paymentRequired - The PaymentRequired response containing extension declarations\n * @returns The enriched payment payload with extension data applied\n */\n private async enrichPaymentPayloadWithExtensions(\n paymentPayload: PaymentPayload,\n paymentRequired: PaymentRequired,\n ): Promise<PaymentPayload> {\n if (!paymentRequired.extensions || this.registeredExtensions.size === 0) {\n return paymentPayload;\n }\n\n let enriched = paymentPayload;\n for (const [key, extension] of this.registeredExtensions) {\n if (key in paymentRequired.extensions && extension.enrichPaymentPayload) {\n enriched = await extension.enrichPaymentPayload(enriched, paymentRequired);\n }\n }\n\n return enriched;\n }\n\n /**\n * Selects appropriate payment requirements based on registered clients and policies.\n *\n * Selection process:\n * 1. Filter by registered schemes (network + scheme support)\n * 2. Apply all registered policies in order\n * 3. Use selector to choose final requirement\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - Array of available payment requirements\n * @returns The selected payment requirements\n */\n private selectPaymentRequirements(x402Version: number, paymentRequirements: PaymentRequirements[]): PaymentRequirements {\n const clientSchemesByNetwork = this.registeredClientSchemes.get(x402Version);\n if (!clientSchemesByNetwork) {\n throw new Error(`No client registered for x402 version: ${x402Version}`);\n }\n\n // Step 1: Filter by registered schemes\n const supportedPaymentRequirements = paymentRequirements.filter(requirement => {\n let clientSchemes = findSchemesByNetwork(clientSchemesByNetwork, requirement.network);\n if (!clientSchemes) {\n return false;\n }\n\n return clientSchemes.has(requirement.scheme);\n })\n\n if (supportedPaymentRequirements.length === 0) {\n throw new Error(`No network/scheme registered for x402 version: ${x402Version} which comply with the payment requirements. ${JSON.stringify({\n x402Version,\n paymentRequirements,\n x402Versions: Array.from(this.registeredClientSchemes.keys()),\n networks: Array.from(clientSchemesByNetwork.keys()),\n schemes: Array.from(clientSchemesByNetwork.values()).map(schemes => Array.from(schemes.keys())).flat(),\n })}`);\n }\n\n // Step 2: Apply all policies in order\n let filteredRequirements = supportedPaymentRequirements;\n for (const policy of this.policies) {\n filteredRequirements = policy(x402Version, filteredRequirements);\n\n if (filteredRequirements.length === 0) {\n throw new Error(`All payment requirements were filtered out by policies for x402 version: ${x402Version}`);\n }\n }\n\n // Step 3: Use selector to choose final requirement\n return this.paymentRequirementsSelector(x402Version, filteredRequirements);\n }\n\n /**\n * Internal method to register a scheme client.\n *\n * @param x402Version - The x402 protocol version\n * @param network - The network to register the client for\n * @param client - The scheme network client to register\n * @returns The x402Client instance for chaining\n */\n private _registerScheme(x402Version: number, network: Network, client: SchemeNetworkClient): x402Client {\n if (!this.registeredClientSchemes.has(x402Version)) {\n this.registeredClientSchemes.set(x402Version, new Map());\n }\n const clientSchemesByNetwork = this.registeredClientSchemes.get(x402Version)!;\n if (!clientSchemesByNetwork.has(network)) {\n clientSchemesByNetwork.set(network, new Map());\n }\n\n const clientByScheme = clientSchemesByNetwork.get(network)!;\n if (!clientByScheme.has(client.scheme)) {\n clientByScheme.set(client.scheme, client);\n }\n\n return this;\n }\n}\n"],"mappings":"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","names":["x402Version"]}
{"version":3,"sources":["../../../src/client/x402Client.ts"],"sourcesContent":["import { x402Version } from \"..\";\nimport { SchemeNetworkClient } from \"../types/mechanisms\";\nimport { PaymentPayload, PaymentRequirements } from \"../types/payments\";\nimport { Network, PaymentRequired, SettleResponse } from \"../types\";\nimport { findByNetworkAndScheme, findSchemesByNetwork } from \"../utils\";\n\n/**\n * Client Hook Context Interfaces\n */\n\nexport interface PaymentCreationContext {\n paymentRequired: PaymentRequired;\n selectedRequirements: PaymentRequirements;\n}\n\nexport interface PaymentCreatedContext extends PaymentCreationContext {\n paymentPayload: PaymentPayload;\n}\n\nexport interface PaymentCreationFailureContext extends PaymentCreationContext {\n error: Error;\n}\n\n/**\n * Client Hook Type Definitions\n */\n\nexport type BeforePaymentCreationHook = (\n context: PaymentCreationContext,\n) => Promise<void | { abort: true; reason: string }>;\n\nexport type AfterPaymentCreationHook = (context: PaymentCreatedContext) => Promise<void>;\n\nexport type OnPaymentCreationFailureHook = (\n context: PaymentCreationFailureContext,\n) => Promise<void | { recovered: true; payload: PaymentPayload }>;\n\n/**\n * Context provided to payment response hooks after the paid request completes.\n *\n * Discriminate by what's present:\n * - `settleResponse` with `success: true` → settle succeeded\n * - `settleResponse` with `success: false` → settle failed\n * - `paymentRequired` (no `settleResponse`) → verify failed\n * - `error` → transport or parse error\n */\nexport interface PaymentResponseContext {\n paymentPayload: PaymentPayload;\n requirements: PaymentRequirements;\n settleResponse?: SettleResponse;\n paymentRequired?: PaymentRequired;\n error?: Error;\n}\n\n/**\n * Hook fired after a paid request completes.\n * Return `{ recovered: true }` to signal the transport should retry with a fresh payload.\n */\nexport type OnPaymentResponseHook = (\n ctx: PaymentResponseContext,\n) => Promise<void | { recovered: true }>;\n\nexport type SelectPaymentRequirements = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements;\n\ntype ClientHookAdapterHandles = {\n beforePaymentCreation?: BeforePaymentCreationHook;\n afterPaymentCreation?: AfterPaymentCreationHook;\n onPaymentCreationFailure?: OnPaymentCreationFailureHook;\n onPaymentResponse?: OnPaymentResponseHook;\n};\n\ntype ClientHookPhase = keyof ClientHookAdapterHandles;\n\n/**\n * Extension that can enrich payment payloads on the client side.\n *\n * Client extensions are invoked after the scheme creates the base payment payload\n * but before it is returned. This allows mechanism-specific logic (e.g., EVM EIP-2612\n * permit signing) to enrich the payload's extensions data.\n */\nexport interface ClientExtension {\n /**\n * Unique key identifying this extension (e.g., \"eip2612GasSponsoring\").\n * Must match the extension key used in PaymentRequired.extensions.\n */\n key: string;\n\n /**\n * Called after payload creation when the extension key is present in\n * paymentRequired.extensions. Allows the extension to enrich the payload\n * with extension-specific data (e.g., signing an EIP-2612 permit).\n *\n * @param paymentPayload - The payment payload to enrich\n * @param paymentRequired - The original PaymentRequired response\n * @returns The enriched payment payload\n */\n enrichPaymentPayload?: (\n paymentPayload: PaymentPayload,\n paymentRequired: PaymentRequired,\n ) => Promise<PaymentPayload>;\n}\n\n/**\n * A policy function that filters or transforms payment requirements.\n * Policies are applied in order before the selector chooses the final option.\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - Array of payment requirements to filter/transform\n * @returns Filtered array of payment requirements\n */\nexport type PaymentPolicy = (x402Version: number, paymentRequirements: PaymentRequirements[]) => PaymentRequirements[];\n\n\n/**\n * Configuration for registering a payment scheme with a specific network\n */\nexport interface SchemeRegistration {\n /**\n * The network identifier (e.g., 'eip155:8453', 'solana:mainnet')\n */\n network: Network;\n\n /**\n * The scheme client implementation for this network\n */\n client: SchemeNetworkClient;\n\n /**\n * The x402 protocol version to use for this scheme\n *\n * @default 2\n */\n x402Version?: number;\n}\n\n/**\n * Configuration options for the fetch wrapper\n */\nexport interface x402ClientConfig {\n /**\n * Array of scheme registrations defining which payment methods are supported\n */\n schemes: SchemeRegistration[];\n\n /**\n * Policies to apply to the client\n */\n policies?: PaymentPolicy[];\n\n /**\n * Custom payment requirements selector function\n * If not provided, uses the default selector (first available option)\n */\n paymentRequirementsSelector?: SelectPaymentRequirements;\n}\n\n/**\n * Core client for managing x402 payment schemes and creating payment payloads.\n *\n * Handles registration of payment schemes, policy-based filtering of payment requirements,\n * and creation of payment payloads based on server requirements.\n */\nexport class x402Client {\n private readonly paymentRequirementsSelector: SelectPaymentRequirements;\n private readonly registeredClientSchemes: Map<number, Map<string, Map<string, SchemeNetworkClient>>> = new Map();\n private readonly schemeClientHookAdapters: Map<number, Map<string, Map<string, ClientHookAdapterHandles>>> = new Map();\n private readonly policies: PaymentPolicy[] = [];\n private readonly registeredExtensions: Map<string, ClientExtension> = new Map();\n\n private beforePaymentCreationHooks: BeforePaymentCreationHook[] = [];\n private afterPaymentCreationHooks: AfterPaymentCreationHook[] = [];\n private onPaymentCreationFailureHooks: OnPaymentCreationFailureHook[] = [];\n private paymentResponseHooks: OnPaymentResponseHook[] = [];\n\n /**\n * Creates a new x402Client instance.\n *\n * @param paymentRequirementsSelector - Function to select payment requirements from available options\n */\n constructor(paymentRequirementsSelector?: SelectPaymentRequirements) {\n this.paymentRequirementsSelector = paymentRequirementsSelector || ((x402Version, accepts) => accepts[0]);\n }\n\n /**\n * Creates a new x402Client instance from a configuration object.\n *\n * @param config - The client configuration including schemes, policies, and payment requirements selector\n * @returns A configured x402Client instance\n */\n static fromConfig(config: x402ClientConfig): x402Client {\n const client = new x402Client(config.paymentRequirementsSelector);\n config.schemes.forEach(scheme => {\n if (scheme.x402Version === 1) {\n client.registerV1(scheme.network, scheme.client);\n } else {\n client.register(scheme.network, scheme.client);\n }\n });\n config.policies?.forEach(policy => {\n client.registerPolicy(policy);\n });\n return client;\n }\n\n /**\n * Registers a scheme client for the current x402 version.\n *\n * @param network - The network to register the client for\n * @param client - The scheme network client to register\n * @returns The x402Client instance for chaining\n */\n register(network: Network, client: SchemeNetworkClient): x402Client {\n return this._registerScheme(x402Version, network, client);\n }\n\n /**\n * Registers a scheme client for x402 version 1.\n *\n * @param network - The v1 network identifier (e.g., 'base-sepolia', 'solana-devnet')\n * @param client - The scheme network client to register\n * @returns The x402Client instance for chaining\n */\n registerV1(network: string, client: SchemeNetworkClient): x402Client {\n return this._registerScheme(1, network as Network, client);\n }\n\n /**\n * Registers a policy to filter or transform payment requirements.\n *\n * Policies are applied in order after filtering by registered schemes\n * and before the selector chooses the final payment requirement.\n *\n * @param policy - Function to filter/transform payment requirements\n * @returns The x402Client instance for chaining\n *\n * @example\n * ```typescript\n * // Prefer cheaper options\n * client.registerPolicy((version, reqs) =>\n * reqs.filter(r => BigInt(r.value) < BigInt('1000000'))\n * );\n *\n * // Prefer specific networks\n * client.registerPolicy((version, reqs) =>\n * reqs.filter(r => r.network.startsWith('eip155:'))\n * );\n * ```\n */\n registerPolicy(policy: PaymentPolicy): x402Client {\n this.policies.push(policy);\n return this;\n }\n\n /**\n * Registers a client extension that can enrich payment payloads.\n *\n * Extensions are invoked after the scheme creates the base payload and the\n * payload is wrapped with extensions/resource/accepted data. If the extension's\n * key is present in `paymentRequired.extensions`, the extension's\n * `enrichPaymentPayload` hook is called to modify the payload.\n *\n * @param extension - The client extension to register\n * @returns The x402Client instance for chaining\n */\n registerExtension(extension: ClientExtension): x402Client {\n this.registeredExtensions.set(extension.key, extension);\n return this;\n }\n\n /**\n * Register a hook to execute before payment payload creation.\n * Can abort creation by returning { abort: true, reason: string }\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onBeforePaymentCreation(hook: BeforePaymentCreationHook): x402Client {\n this.beforePaymentCreationHooks.push(hook);\n return this;\n }\n\n /**\n * Register a hook to execute after successful payment payload creation.\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onAfterPaymentCreation(hook: AfterPaymentCreationHook): x402Client {\n this.afterPaymentCreationHooks.push(hook);\n return this;\n }\n\n /**\n * Register a hook to execute when payment payload creation fails.\n * Can recover from failure by returning { recovered: true, payload: PaymentPayload }\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onPaymentCreationFailure(hook: OnPaymentCreationFailureHook): x402Client {\n this.onPaymentCreationFailureHooks.push(hook);\n return this;\n }\n\n /**\n * Register a hook to execute after a paid request completes.\n * Can signal recovery by returning { recovered: true }, causing the transport to retry.\n *\n * @param hook - The hook function to register\n * @returns The x402Client instance for chaining\n */\n onPaymentResponse(hook: OnPaymentResponseHook): x402Client {\n this.paymentResponseHooks.push(hook);\n return this;\n }\n\n /**\n * Fires all registered payment response hooks in order.\n * Returns `{ recovered: true }` if any hook signals recovery (first wins).\n *\n * @param ctx - The payment response context\n * @returns Recovery signal or undefined\n */\n async handlePaymentResponse(\n ctx: PaymentResponseContext,\n ): Promise<{ recovered: true } | undefined> {\n for (const hook of this.getLabeledHooks(\n \"onPaymentResponse\",\n ctx.paymentPayload.x402Version,\n ctx.requirements,\n )) {\n const result = await hook(ctx);\n if (result && \"recovered\" in result && result.recovered) {\n return { recovered: true };\n }\n }\n return undefined;\n }\n\n /**\n * Creates a payment payload based on a PaymentRequired response.\n *\n * Automatically extracts x402Version, resource, and extensions from the PaymentRequired\n * response and constructs a complete PaymentPayload with the accepted requirements.\n *\n * @param paymentRequired - The PaymentRequired response from the server\n * @returns Promise resolving to the complete payment payload\n */\n async createPaymentPayload(\n paymentRequired: PaymentRequired,\n ): Promise<PaymentPayload> {\n const clientSchemesByNetwork = this.registeredClientSchemes.get(paymentRequired.x402Version);\n if (!clientSchemesByNetwork) {\n throw new Error(`No client registered for x402 version: ${paymentRequired.x402Version}`);\n }\n\n const requirements = this.selectPaymentRequirements(paymentRequired.x402Version, paymentRequired.accepts);\n\n const context: PaymentCreationContext = {\n paymentRequired,\n selectedRequirements: requirements,\n };\n\n for (const hook of this.getLabeledHooks(\n \"beforePaymentCreation\",\n paymentRequired.x402Version,\n requirements,\n )) {\n const result = await hook(context);\n if (result && \"abort\" in result && result.abort) {\n throw new Error(`Payment creation aborted: ${result.reason}`);\n }\n }\n\n try {\n const schemeNetworkClient = findByNetworkAndScheme(clientSchemesByNetwork, requirements.scheme, requirements.network);\n if (!schemeNetworkClient) {\n throw new Error(`No client registered for scheme: ${requirements.scheme} and network: ${requirements.network}`);\n }\n\n const partialPayload = await schemeNetworkClient.createPaymentPayload(\n paymentRequired.x402Version,\n requirements,\n { extensions: paymentRequired.extensions },\n );\n\n let paymentPayload: PaymentPayload;\n if (partialPayload.x402Version == 1) {\n paymentPayload = partialPayload as PaymentPayload;\n } else {\n // Merge server-declared extensions with any scheme-provided extensions.\n // Scheme extensions overlay on top (e.g., EIP-2612 info enriches server declaration).\n const mergedExtensions = this.mergeExtensions(\n paymentRequired.extensions,\n partialPayload.extensions,\n );\n\n paymentPayload = {\n x402Version: partialPayload.x402Version,\n payload: partialPayload.payload,\n extensions: mergedExtensions,\n resource: paymentRequired.resource,\n accepted: requirements,\n };\n }\n\n // Enrich payload via registered client extensions (for non-scheme extensions)\n paymentPayload = await this.enrichPaymentPayloadWithExtensions(paymentPayload, paymentRequired);\n\n const createdContext: PaymentCreatedContext = {\n ...context,\n paymentPayload,\n };\n\n for (const hook of this.getLabeledHooks(\n \"afterPaymentCreation\",\n paymentRequired.x402Version,\n requirements,\n )) {\n await hook(createdContext);\n }\n\n return paymentPayload;\n } catch (error) {\n const failureContext: PaymentCreationFailureContext = {\n ...context,\n error: error as Error,\n };\n\n for (const hook of this.getLabeledHooks(\n \"onPaymentCreationFailure\",\n paymentRequired.x402Version,\n requirements,\n )) {\n const result = await hook(failureContext);\n if (result && \"recovered\" in result && result.recovered) {\n return result.payload;\n }\n }\n\n throw error;\n }\n }\n\n\n\n /**\n * Merges server-declared extensions with scheme-provided extensions.\n * Scheme extensions overlay on top of server extensions at each key,\n * preserving server-provided schema while overlaying scheme-provided info.\n *\n * @param serverExtensions - Extensions declared by the server in the 402 response\n * @param schemeExtensions - Extensions provided by the scheme client (e.g. EIP-2612)\n * @returns The merged extensions object, or undefined if both inputs are undefined\n */\n private mergeExtensions(\n serverExtensions?: Record<string, unknown>,\n schemeExtensions?: Record<string, unknown>,\n ): Record<string, unknown> | undefined {\n if (!schemeExtensions) return serverExtensions;\n if (!serverExtensions) return schemeExtensions;\n\n const merged = { ...serverExtensions };\n for (const [key, schemeValue] of Object.entries(schemeExtensions)) {\n const serverValue = merged[key];\n if (\n serverValue &&\n typeof serverValue === \"object\" &&\n schemeValue &&\n typeof schemeValue === \"object\"\n ) {\n // Deep merge: scheme info overlays server info, schema preserved\n merged[key] = { ...serverValue as Record<string, unknown>, ...schemeValue as Record<string, unknown> };\n } else {\n merged[key] = schemeValue;\n }\n }\n return merged;\n }\n\n /**\n * Enriches a payment payload by calling registered extension hooks.\n * For each extension key present in the PaymentRequired response,\n * invokes the corresponding extension's enrichPaymentPayload callback.\n *\n * @param paymentPayload - The payment payload to enrich with extension data\n * @param paymentRequired - The PaymentRequired response containing extension declarations\n * @returns The enriched payment payload with extension data applied\n */\n private async enrichPaymentPayloadWithExtensions(\n paymentPayload: PaymentPayload,\n paymentRequired: PaymentRequired,\n ): Promise<PaymentPayload> {\n if (!paymentRequired.extensions || this.registeredExtensions.size === 0) {\n return paymentPayload;\n }\n\n let enriched = paymentPayload;\n for (const [key, extension] of this.registeredExtensions) {\n if (key in paymentRequired.extensions && extension.enrichPaymentPayload) {\n enriched = await extension.enrichPaymentPayload(enriched, paymentRequired);\n }\n }\n\n return enriched;\n }\n\n /**\n * Selects appropriate payment requirements based on registered clients and policies.\n *\n * Selection process:\n * 1. Filter by registered schemes (network + scheme support)\n * 2. Apply all registered policies in order\n * 3. Use selector to choose final requirement\n *\n * @param x402Version - The x402 protocol version\n * @param paymentRequirements - Array of available payment requirements\n * @returns The selected payment requirements\n */\n private selectPaymentRequirements(x402Version: number, paymentRequirements: PaymentRequirements[]): PaymentRequirements {\n const clientSchemesByNetwork = this.registeredClientSchemes.get(x402Version);\n if (!clientSchemesByNetwork) {\n throw new Error(`No client registered for x402 version: ${x402Version}`);\n }\n\n // Step 1: Filter by registered schemes\n const supportedPaymentRequirements = paymentRequirements.filter(requirement => {\n let clientSchemes = findSchemesByNetwork(clientSchemesByNetwork, requirement.network);\n if (!clientSchemes) {\n return false;\n }\n\n return clientSchemes.has(requirement.scheme);\n })\n\n if (supportedPaymentRequirements.length === 0) {\n throw new Error(`No network/scheme registered for x402 version: ${x402Version} which comply with the payment requirements. ${JSON.stringify({\n x402Version,\n paymentRequirements,\n x402Versions: Array.from(this.registeredClientSchemes.keys()),\n networks: Array.from(clientSchemesByNetwork.keys()),\n schemes: Array.from(clientSchemesByNetwork.values()).map(schemes => Array.from(schemes.keys())).flat(),\n })}`);\n }\n\n // Step 2: Apply all policies in order\n let filteredRequirements = supportedPaymentRequirements;\n for (const policy of this.policies) {\n filteredRequirements = policy(x402Version, filteredRequirements);\n\n if (filteredRequirements.length === 0) {\n throw new Error(`All payment requirements were filtered out by policies for x402 version: ${x402Version}`);\n }\n }\n\n // Step 3: Use selector to choose final requirement\n return this.paymentRequirementsSelector(x402Version, filteredRequirements);\n }\n\n /**\n * Internal method to register a scheme client.\n *\n * @param x402Version - The x402 protocol version\n * @param network - The network to register the client for\n * @param client - The scheme network client to register\n * @returns The x402Client instance for chaining\n */\n private _registerScheme(x402Version: number, network: Network, client: SchemeNetworkClient): x402Client {\n if (!this.registeredClientSchemes.has(x402Version)) {\n this.registeredClientSchemes.set(x402Version, new Map());\n }\n const clientSchemesByNetwork = this.registeredClientSchemes.get(x402Version)!;\n if (!clientSchemesByNetwork.has(network)) {\n clientSchemesByNetwork.set(network, new Map());\n }\n\n const clientByScheme = clientSchemesByNetwork.get(network)!;\n clientByScheme.set(client.scheme, client);\n\n if (!this.schemeClientHookAdapters.has(x402Version)) {\n this.schemeClientHookAdapters.set(x402Version, new Map());\n }\n const adaptersByNetwork = this.schemeClientHookAdapters.get(x402Version)!;\n if (!adaptersByNetwork.has(network)) {\n adaptersByNetwork.set(network, new Map());\n }\n\n const adaptersByScheme = adaptersByNetwork.get(network)!;\n const hooks = client.schemeHooks;\n if (!hooks) {\n adaptersByScheme.delete(client.scheme);\n return this;\n }\n\n const handles: ClientHookAdapterHandles = {};\n if (hooks.onBeforePaymentCreation) {\n handles.beforePaymentCreation = hooks.onBeforePaymentCreation;\n }\n if (hooks.onAfterPaymentCreation) {\n handles.afterPaymentCreation = hooks.onAfterPaymentCreation;\n }\n if (hooks.onPaymentCreationFailure) {\n handles.onPaymentCreationFailure = hooks.onPaymentCreationFailure;\n }\n if (hooks.onPaymentResponse) {\n handles.onPaymentResponse = hooks.onPaymentResponse;\n }\n\n if (Object.keys(handles).length > 0) {\n adaptersByScheme.set(client.scheme, handles);\n } else {\n adaptersByScheme.delete(client.scheme);\n }\n\n return this;\n }\n\n /**\n * Returns manual hooks followed by the hook for the selected scheme, if present.\n *\n * @param phase - Hook slot to collect\n * @param x402Version - Protocol version for the selected requirement\n * @param requirements - Selected payment requirement\n * @returns Hooks in invocation order\n */\n private getLabeledHooks<P extends ClientHookPhase>(\n phase: P,\n x402Version: number,\n requirements: PaymentRequirements,\n ): Array<NonNullable<ClientHookAdapterHandles[P]>> {\n let manual: Array<NonNullable<ClientHookAdapterHandles[P]>>;\n switch (phase) {\n case \"beforePaymentCreation\":\n manual = this.beforePaymentCreationHooks as Array<\n NonNullable<ClientHookAdapterHandles[P]>\n >;\n break;\n case \"afterPaymentCreation\":\n manual = this.afterPaymentCreationHooks as Array<\n NonNullable<ClientHookAdapterHandles[P]>\n >;\n break;\n case \"onPaymentCreationFailure\":\n manual = this.onPaymentCreationFailureHooks as Array<\n NonNullable<ClientHookAdapterHandles[P]>\n >;\n break;\n case \"onPaymentResponse\":\n manual = this.paymentResponseHooks as Array<NonNullable<ClientHookAdapterHandles[P]>>;\n break;\n }\n\n const out: Array<NonNullable<ClientHookAdapterHandles[P]>> = [...manual];\n const adaptersByNetwork = this.schemeClientHookAdapters.get(x402Version);\n const schemeAdapter = adaptersByNetwork\n ? findByNetworkAndScheme(adaptersByNetwork, requirements.scheme, requirements.network)\n : undefined;\n const hook = schemeAdapter?.[phase];\n if (hook !== undefined) {\n out.push(hook);\n }\n return out;\n }\n}\n"],"mappings":"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","names":["x402Version"]}

@@ -1,2 +0,2 @@

import { P as PaymentPayload, a as PaymentRequirements, V as VerifyResponse, S as SettleResponse, N as Network, b as SchemeNetworkFacilitator, F as FacilitatorExtension } from '../mechanisms-C6YmSXgy.mjs';
import { P as PaymentPayload, a as PaymentRequirements, V as VerifyResponse, S as SettleResponse, N as Network, b as SchemeNetworkFacilitator, F as FacilitatorExtension } from '../x402Client-DmgwYAFT.mjs';

@@ -3,0 +3,0 @@ /**

@@ -1,4 +0,4 @@

import { P as PaymentPayload, c as PaymentRequired, S as SettleResponse } from '../mechanisms-C6YmSXgy.mjs';
export { d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, g as getFacilitatorResponseError } from '../mechanisms-C6YmSXgy.mjs';
export { C as CompiledRoute, D as DynamicPayTo, h as DynamicPrice, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, f as PaymentOption, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, S as SettlementFailedResponseBody, U as UnpaidResponseBody, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-DozxbWk6.mjs';
import { P as PaymentPayload, c as PaymentRequired, S as SettleResponse } from '../x402Client-DmgwYAFT.mjs';
export { d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, g as getFacilitatorResponseError } from '../x402Client-DmgwYAFT.mjs';
export { C as CompiledRoute, D as DynamicPayTo, h as DynamicPrice, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, f as PaymentOption, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, S as SettlementFailedResponseBody, U as UnpaidResponseBody, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-DdaA7yvX.mjs';
export { PaymentRequiredContext, PaymentRequiredHook, x402HTTPClient } from '../client/index.mjs';

@@ -5,0 +5,0 @@

@@ -12,4 +12,4 @@ import {

x402HTTPResourceServer
} from "../chunk-G3XJUKWR.mjs";
import "../chunk-KMQH4MQI.mjs";
} from "../chunk-FTDK7NUZ.mjs";
import "../chunk-FPXAE3OS.mjs";
import "../chunk-VE37GDG2.mjs";

@@ -19,3 +19,3 @@ import {

getFacilitatorResponseError
} from "../chunk-JUGE6MAI.mjs";
} from "../chunk-AGOUMC4P.mjs";
import "../chunk-4BKQ2IT7.mjs";

@@ -22,0 +22,0 @@ import "../chunk-BJTO5JO5.mjs";

@@ -39,5 +39,2 @@ import { z } from 'zod';

type Network = z.infer<typeof NetworkSchema>;
/**
* ResourceInfo schema for V2 - describes the protected resource.
*/
declare const ResourceInfoSchema: z.ZodObject<{

@@ -47,2 +44,5 @@ url: z.ZodString;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -52,2 +52,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -57,2 +60,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>;

@@ -85,5 +91,5 @@ type ResourceInfo = z.infer<typeof ResourceInfoSchema>;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -98,5 +104,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>;

@@ -132,5 +138,5 @@ type PaymentRequirementsV1 = z.infer<typeof PaymentRequirementsV1Schema>;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -145,5 +151,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>, "many">;

@@ -161,5 +167,5 @@ }, "strip", z.ZodTypeAny, {

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -178,5 +184,5 @@ error?: string | undefined;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -248,2 +254,5 @@ error?: string | undefined;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -253,2 +262,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -258,2 +270,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>;

@@ -291,2 +306,5 @@ accepts: z.ZodArray<z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -310,2 +328,5 @@ x402Version: 2;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -336,2 +357,5 @@ x402Version: 2;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -341,2 +365,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -346,2 +373,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>>;

@@ -392,2 +422,5 @@ accepted: z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -411,2 +444,5 @@ }, {

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -440,5 +476,5 @@ }>;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -453,5 +489,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>, z.ZodObject<{

@@ -511,5 +547,5 @@ scheme: z.ZodString;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}, {

@@ -524,5 +560,5 @@ payTo: string;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}>, "many">;

@@ -540,5 +576,5 @@ }, "strip", z.ZodTypeAny, {

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -557,5 +593,5 @@ error?: string | undefined;

maxTimeoutSeconds: number;
extra?: Record<string, unknown> | null | undefined;
mimeType?: string | undefined;
outputSchema?: Record<string, unknown> | null | undefined;
extra?: Record<string, unknown> | null | undefined;
}[];

@@ -570,2 +606,5 @@ error?: string | undefined;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -575,2 +614,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -580,2 +622,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>;

@@ -613,2 +658,5 @@ accepts: z.ZodArray<z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -632,2 +680,5 @@ x402Version: 2;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
};

@@ -673,2 +724,5 @@ x402Version: 2;

mimeType: z.ZodOptional<z.ZodString>;
serviceName: z.ZodOptional<z.ZodString>;
tags: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
iconUrl: z.ZodOptional<z.ZodString>;
}, "strip", z.ZodTypeAny, {

@@ -678,2 +732,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}, {

@@ -683,2 +740,5 @@ url: string;

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
}>>;

@@ -729,2 +789,5 @@ accepted: z.ZodObject<{

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -748,2 +811,5 @@ }, {

mimeType?: string | undefined;
serviceName?: string | undefined;
tags?: string[] | undefined;
iconUrl?: string | undefined;
} | undefined;

@@ -750,0 +816,0 @@ }>]>;

@@ -34,3 +34,3 @@ import {

z
} from "../chunk-KMQH4MQI.mjs";
} from "../chunk-FPXAE3OS.mjs";
import "../chunk-BJTO5JO5.mjs";

@@ -37,0 +37,0 @@ export {

@@ -1,4 +0,4 @@

import { a as PaymentRequirements, S as SettleResponse } from '../mechanisms-C6YmSXgy.mjs';
export { q as AfterSettleHook, A as AfterVerifyHook, p as BeforeSettleHook, B as BeforeVerifyHook, d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, r as OnSettleFailureHook, O as OnVerifyFailureHook, h as PaymentRequiredContext, R as ResourceConfig, l as SettleContext, n as SettleFailureContext, m as SettleResultContext, o as SettlementOverrides, i as VerifyContext, k as VerifyFailureContext, j as VerifyResultContext, g as getFacilitatorResponseError, x as x402ResourceServer } from '../mechanisms-C6YmSXgy.mjs';
export { C as CompiledRoute, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, p as SETTLEMENT_OVERRIDES_HEADER, S as SettlementFailedResponseBody, U as UnpaidResponseBody, q as checkIfBazaarNeeded, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-DozxbWk6.mjs';
import { a as PaymentRequirements, S as SettleResponse } from '../x402Client-DmgwYAFT.mjs';
export { w as AfterSettleHook, A as AfterVerifyHook, v as BeforeSettleHook, B as BeforeVerifyHook, d as FacilitatorClient, e as FacilitatorConfig, f as FacilitatorResponseError, H as HTTPFacilitatorClient, y as OnSettleFailureHook, z as OnVerifiedPaymentCanceledHook, O as OnVerifyFailureHook, r as PaymentCancellationDispatcher, h as PaymentRequiredContext, R as ResourceConfig, u as ResourceVerifyRespone, C as SchemeEnrichPaymentRequiredResponseHook, E as SchemeEnrichSettlementPayloadHook, G as SchemeEnrichSettlementResponseHook, D as SchemePaymentRequiredContext, l as SettleContext, n as SettleFailureContext, m as SettleResultContext, s as SettlementOverrides, t as SkipHandlerDirective, q as VerifiedPaymentCancelOptions, o as VerifiedPaymentCanceledContext, p as VerifiedPaymentCancellationReason, i as VerifyContext, k as VerifyFailureContext, j as VerifyResultContext, g as getFacilitatorResponseError, x as x402ResourceServer } from '../x402Client-DmgwYAFT.mjs';
export { C as CompiledRoute, H as HTTPAdapter, d as HTTPProcessResult, a as HTTPRequestContext, i as HTTPResponseBody, c as HTTPResponseInstructions, b as HTTPTransportContext, P as PaywallConfig, e as PaywallProvider, l as ProcessSettleFailureResponse, j as ProcessSettleResultResponse, k as ProcessSettleSuccessResponse, o as ProtectedRequestHook, R as RouteConfig, n as RouteConfigurationError, m as RouteValidationError, g as RoutesConfig, p as SETTLEMENT_OVERRIDES_HEADER, S as SettlementFailedResponseBody, U as UnpaidResponseBody, q as checkIfBazaarNeeded, x as x402HTTPResourceServer } from '../x402HTTPResourceServer-DdaA7yvX.mjs';

@@ -33,2 +33,11 @@ /**

/**
* Ensures scheme 402 enrichment only adds `extra` keys to matching accepts.
*
* @param baseline - Snapshot before the scheme enrich step
* @param current - Live `accepts` entries after scheme enrichment
* @param scheme - Scheme whose hook was invoked
* @param network - Network whose hook was invoked
*/
declare function assertAcceptsAdditiveExtraAfterSchemeEnrich(baseline: PaymentRequirements[], current: PaymentRequirements[], scheme: string, network: string): void;
/**
* Immutable subset of {@link SettleResponse} compared across settlement extension enrich.

@@ -54,3 +63,20 @@ */

declare function assertSettleResponseCoreUnchanged(before: SettleResponseCoreSnapshot, after: SettleResponse, extensionKey: string): void;
/**
* Ensures scheme settlement-payload enrichment only adds server-owned fields.
*
* @param payload - Existing scheme payload before enrichment
* @param enrichment - Fields returned by the scheme enrichment hook
* @param callerLabel - Hook source label used in policy error messages
*/
declare function assertAdditivePayloadEnrichment(payload: Record<string, unknown>, enrichment: Record<string, unknown>, callerLabel: string): void;
/**
* Ensures scheme response enrichment only adds new `extra` fields, including nested fields
* below existing objects.
*
* @param extra - Existing settlement extra fields
* @param enrichment - Fields returned by the scheme response enrichment hook
* @param callerLabel - Hook label used in policy error messages
*/
declare function assertAdditiveSettlementExtra(extra: Record<string, unknown>, enrichment: Record<string, unknown>, callerLabel: string): void;
export { type SettleResponseCoreSnapshot, assertAcceptsAllowlistedAfterExtensionEnrich, assertSettleResponseCoreUnchanged, isVacantStringField, snapshotPaymentRequirementsList, snapshotSettleResponseCore };
export { type SettleResponseCoreSnapshot, assertAcceptsAdditiveExtraAfterSchemeEnrich, assertAcceptsAllowlistedAfterExtensionEnrich, assertAdditivePayloadEnrichment, assertAdditiveSettlementExtra, assertSettleResponseCoreUnchanged, isVacantStringField, snapshotPaymentRequirementsList, snapshotSettleResponseCore };

@@ -7,4 +7,4 @@ import {

x402HTTPResourceServer
} from "../chunk-G3XJUKWR.mjs";
import "../chunk-KMQH4MQI.mjs";
} from "../chunk-FTDK7NUZ.mjs";
import "../chunk-FPXAE3OS.mjs";
import {

@@ -17,3 +17,3 @@ x402Version

getFacilitatorResponseError
} from "../chunk-JUGE6MAI.mjs";
} from "../chunk-AGOUMC4P.mjs";
import {

@@ -25,3 +25,3 @@ deepEqual,

// src/server/extensionResponsePolicy.ts
// src/server/hookPolicy.ts
function isVacantStringField(value) {

@@ -78,2 +78,41 @@ return value.trim() === "";

}
function assertAcceptsAdditiveExtraAfterSchemeEnrich(baseline, current, scheme, network) {
if (baseline.length !== current.length) {
throw new Error(
`[x402] scheme "${scheme}" violated accepts mutation policy: accepts length changed (${baseline.length} \u2192 ${current.length})`
);
}
for (let i = 0; i < baseline.length; i++) {
const b = baseline[i];
const c = current[i];
const isMatchingAccept = b.scheme === scheme && b.network === network;
if (b.scheme !== c.scheme || b.network !== c.network) {
throw new Error(
`[x402] scheme "${scheme}" violated accepts mutation policy: scheme/network are immutable (index ${i})`
);
}
if (b.maxTimeoutSeconds !== c.maxTimeoutSeconds || b.payTo !== c.payTo || b.amount !== c.amount || b.asset !== c.asset) {
throw new Error(
`[x402] scheme "${scheme}" violated accepts mutation policy: payment terms are immutable (index ${i})`
);
}
for (const key of Object.keys(b.extra)) {
if (!Object.prototype.hasOwnProperty.call(c.extra, key)) {
throw new Error(
`[x402] scheme "${scheme}" violated accepts mutation policy: extra["${key}"] was removed (index ${i})`
);
}
if (!deepEqual(c.extra[key], b.extra[key])) {
throw new Error(
`[x402] scheme "${scheme}" violated accepts mutation policy: extra["${key}"] may not be changed (index ${i})`
);
}
}
if (!isMatchingAccept && Object.keys(c.extra).length !== Object.keys(b.extra).length) {
throw new Error(
`[x402] scheme "${scheme}" violated accepts mutation policy: only matching accepts may receive new extra fields (index ${i})`
);
}
}
}
function snapshotSettleResponseCore(result) {

@@ -108,2 +147,45 @@ return {

}
function assertAdditivePayloadEnrichment(payload, enrichment, callerLabel) {
for (const key of Object.keys(enrichment)) {
if (!Object.prototype.hasOwnProperty.call(payload, key)) continue;
throw new Error(
`[x402] ${callerLabel} violated settlement payload enrichment policy: "${key}" already exists on the client payload`
);
}
}
function isPlainRecord(value) {
return typeof value === "object" && value !== null && !Array.isArray(value);
}
function assertAdditiveSettlementExtra(extra, enrichment, callerLabel) {
assertAdditiveRecord(extra, enrichment, callerLabel, "extra");
}
function mergeAdditiveSettlementExtra(extra, enrichment) {
return mergeAdditiveRecord(extra, enrichment);
}
function assertAdditiveRecord(target, enrichment, callerLabel, path) {
for (const [key, enrichmentValue] of Object.entries(enrichment)) {
const nextPath = `${path}["${key}"]`;
if (!Object.prototype.hasOwnProperty.call(target, key)) continue;
const targetValue = target[key];
if (isPlainRecord(targetValue) && isPlainRecord(enrichmentValue)) {
assertAdditiveRecord(targetValue, enrichmentValue, callerLabel, nextPath);
continue;
}
throw new Error(
`[x402] ${callerLabel} violated settlement response enrichment policy: ${nextPath} already exists on the settlement result`
);
}
}
function mergeAdditiveRecord(target, enrichment) {
const merged = { ...target };
for (const [key, enrichmentValue] of Object.entries(enrichment)) {
const targetValue = merged[key];
if (isPlainRecord(targetValue) && isPlainRecord(enrichmentValue)) {
merged[key] = mergeAdditiveRecord(targetValue, enrichmentValue);
continue;
}
merged[key] = enrichmentValue;
}
return merged;
}

@@ -134,2 +216,3 @@ // src/server/x402ResourceServer.ts

this.registeredServerSchemes = /* @__PURE__ */ new Map();
this.schemeHookAdapters = /* @__PURE__ */ new Map();
this.supportedResponsesMap = /* @__PURE__ */ new Map();

@@ -145,2 +228,3 @@ this.facilitatorClientsMap = /* @__PURE__ */ new Map();

this.onSettleFailureHooks = [];
this.onVerifiedPaymentCanceledHooks = [];
if (!facilitatorClients) {

@@ -166,5 +250,27 @@ this.facilitatorClients = [new HTTPFacilitatorClient()];

const serverByScheme = this.registeredServerSchemes.get(network);
if (!serverByScheme.has(server.scheme)) {
serverByScheme.set(server.scheme, server);
serverByScheme.set(server.scheme, server);
if (!this.schemeHookAdapters.has(network)) {
this.schemeHookAdapters.set(network, /* @__PURE__ */ new Map());
}
const hooksByScheme = this.schemeHookAdapters.get(network);
const hooks = server.schemeHooks;
if (!hooks) {
hooksByScheme.delete(server.scheme);
return this;
}
const handles = {};
if (hooks.onBeforeVerify) handles.beforeVerify = hooks.onBeforeVerify;
if (hooks.onAfterVerify) handles.afterVerify = hooks.onAfterVerify;
if (hooks.onVerifyFailure) handles.onVerifyFailure = hooks.onVerifyFailure;
if (hooks.onBeforeSettle) handles.beforeSettle = hooks.onBeforeSettle;
if (hooks.onAfterSettle) handles.afterSettle = hooks.onAfterSettle;
if (hooks.onSettleFailure) handles.onSettleFailure = hooks.onSettleFailure;
if (hooks.onVerifiedPaymentCanceled) {
handles.onVerifiedPaymentCanceled = hooks.onVerifiedPaymentCanceled;
}
if (Object.keys(handles).length > 0) {
hooksByScheme.set(server.scheme, handles);
} else {
hooksByScheme.delete(server.scheme);
}
return this;

@@ -232,2 +338,3 @@ }

bindExtensionHookAdapter("onSettleFailure", "onSettleFailure");
bindExtensionHookAdapter("onVerifiedPaymentCanceled", "onVerifiedPaymentCanceled");
if (Object.keys(handles).length > 0) {

@@ -346,2 +453,12 @@ this.extensionHookAdapters.set(extensionKey, handles);

/**
* Register a hook to execute when verified payment work is canceled before settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifiedPaymentCanceled(hook) {
this.onVerifiedPaymentCanceledHooks.push(hook);
return this;
}
/**
* Initialize by fetching supported kinds from all facilitators

@@ -483,6 +600,3 @@ * Creates mappings for supported responses and facilitator clients

baseRequirements,
{
...supportedKind,
x402Version
},
supportedKind,
facilitatorExtensions

@@ -527,5 +641,6 @@ );

* @param transportContext - Optional transport-specific context (e.g., HTTP request, MCP tool context)
* @param paymentPayload - Optional failed payment payload for response-time scheme enrichment
* @returns Payment required response object
*/
async createPaymentRequiredResponse(requirements, resourceInfo, error, extensions, transportContext) {
async createPaymentRequiredResponse(requirements, resourceInfo, error, extensions, transportContext, paymentPayload) {
const acceptsClone = requirements.map((req) => ({

@@ -535,3 +650,4 @@ ...req,

}));
let baselineAccepts = snapshotPaymentRequirementsList(acceptsClone);
let workingAccepts = acceptsClone;
let baselineAccepts = snapshotPaymentRequirementsList(workingAccepts);
let response = {

@@ -541,3 +657,3 @@ x402Version: 2,

resource: resourceInfo,
accepts: acceptsClone
accepts: workingAccepts
};

@@ -547,2 +663,33 @@ if (extensions && Object.keys(extensions).length > 0) {

}
for (let i = 0; i < workingAccepts.length; i++) {
const accept = workingAccepts[i];
const scheme = findByNetworkAndScheme(
this.registeredServerSchemes,
accept.scheme,
accept.network
);
if (!scheme?.enrichPaymentRequiredResponse) {
continue;
}
const context = {
requirements: workingAccepts,
paymentPayload,
resourceInfo,
error,
paymentRequiredResponse: response,
transportContext
};
const enrichedAccepts = await scheme.enrichPaymentRequiredResponse(context);
if (enrichedAccepts !== void 0) {
workingAccepts = enrichedAccepts;
response.accepts = workingAccepts;
}
assertAcceptsAdditiveExtraAfterSchemeEnrich(
baselineAccepts,
response.accepts,
accept.scheme,
accept.network
);
baselineAccepts = snapshotPaymentRequirementsList(response.accepts);
}
if (extensions) {

@@ -554,3 +701,3 @@ for (const [key, declaration] of Object.entries(extensions)) {

const context = {
requirements: acceptsClone,
requirements: workingAccepts,
resourceInfo,

@@ -574,4 +721,4 @@ error,

}
assertAcceptsAllowlistedAfterExtensionEnrich(baselineAccepts, acceptsClone, key);
baselineAccepts = snapshotPaymentRequirementsList(acceptsClone);
assertAcceptsAllowlistedAfterExtensionEnrich(baselineAccepts, workingAccepts, key);
baselineAccepts = snapshotPaymentRequirementsList(workingAccepts);
}

@@ -589,3 +736,4 @@ }

* @param transportContext - Optional transport-specific context (e.g. HTTP, MCP)
* @returns Facilitator verify outcome, or abort/recovery as driven by hooks
* @returns Facilitator verify outcome (optionally carrying a `skipHandler` directive),
* or abort/recovery as driven by hooks
*/

@@ -595,2 +743,6 @@ async verifyPayment(paymentPayload, requirements, declaredExtensions, transportContext) {

const extensionKeysInUse = Object.keys(resolvedDeclaredExtensions);
const matchedScheme = {
network: requirements.network,
scheme: requirements.scheme
};
const context = {

@@ -602,3 +754,7 @@ paymentPayload,

};
for (const { label, hook } of this.getLabeledHooks("beforeVerify", extensionKeysInUse)) {
for (const { label, hook } of this.getLabeledHooks(
"beforeVerify",
extensionKeysInUse,
matchedScheme
)) {
try {

@@ -613,2 +769,10 @@ const result = await hook(context);

}
if (result && "skip" in result && result.skip) {
return this.runAfterVerifyHooks(
result.result,
context,
extensionKeysInUse,
matchedScheme
);
}
} catch (error) {

@@ -643,14 +807,3 @@ this.warnResourceServerHookFailure("beforeVerify", label, error);

}
const resultContext = {
...context,
result: verifyResult
};
for (const { label, hook } of this.getLabeledHooks("afterVerify", extensionKeysInUse)) {
try {
await hook(resultContext);
} catch (error) {
this.warnResourceServerHookFailure("afterVerify", label, error);
}
}
return verifyResult;
return this.runAfterVerifyHooks(verifyResult, context, extensionKeysInUse, matchedScheme);
} catch (error) {

@@ -661,3 +814,7 @@ const failureContext = {

};
for (const { label, hook } of this.getLabeledHooks("onVerifyFailure", extensionKeysInUse)) {
for (const { label, hook } of this.getLabeledHooks(
"onVerifyFailure",
extensionKeysInUse,
matchedScheme
)) {
try {

@@ -676,2 +833,29 @@ const result = await hook(failureContext);

/**
* Create cancellation controls for a verified payment attempt.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context
* @returns Cancellation controls for the verified payment attempt
*/
createPaymentCancellationDispatcher(paymentPayload, requirements, declaredExtensions, transportContext) {
const resolvedDeclaredExtensions = declaredExtensions ?? {};
let cancelPromise;
return {
cancel: (options) => {
if (!cancelPromise) {
cancelPromise = this.dispatchVerifiedPaymentCanceled(
paymentPayload,
requirements,
resolvedDeclaredExtensions,
options,
transportContext
);
}
return cancelPromise;
}
};
}
/**
* Settle a verified payment

@@ -708,3 +892,11 @@ *

};
for (const { label, hook } of this.getLabeledHooks("beforeSettle", extensionKeysInUse)) {
const matchedScheme = {
network: effectiveRequirements.network,
scheme: effectiveRequirements.scheme
};
for (const { label, hook } of this.getLabeledHooks(
"beforeSettle",
extensionKeysInUse,
matchedScheme
)) {
try {

@@ -721,2 +913,28 @@ const result = await hook(context);

}
if (result && "skip" in result && result.skip) {
const settleResult = result.result;
const skipResultContext = {
...context,
result: settleResult,
transportContext
};
for (const { label: label2, hook: hook2 } of this.getLabeledHooks(
"afterSettle",
extensionKeysInUse,
matchedScheme
)) {
try {
await hook2(skipResultContext);
} catch (error) {
this.warnResourceServerHookFailure("afterSettle", label2, error);
}
}
await this.enrichSettlementResponse(
settleResult,
skipResultContext,
resolvedDeclaredExtensions,
matchedScheme
);
return settleResult;
}
} catch (error) {

@@ -730,2 +948,16 @@ if (error instanceof SettleError) {

try {
const scheme = findByNetworkAndScheme(
this.registeredServerSchemes,
matchedScheme.scheme,
matchedScheme.network
);
const payloadEnrichmentHook = scheme?.enrichSettlementPayload;
if (payloadEnrichmentHook) {
const label = `scheme "${matchedScheme.scheme}" enrichSettlementPayload`;
const enrichment = await payloadEnrichmentHook(context);
if (enrichment !== void 0) {
assertAdditivePayloadEnrichment(paymentPayload.payload, enrichment, label);
paymentPayload.payload = { ...paymentPayload.payload, ...enrichment };
}
}
const facilitatorClient = this.getFacilitatorClient(

@@ -759,3 +991,7 @@ paymentPayload.x402Version,

};
for (const { label, hook } of this.getLabeledHooks("afterSettle", extensionKeysInUse)) {
for (const { label, hook } of this.getLabeledHooks(
"afterSettle",
extensionKeysInUse,
matchedScheme
)) {
try {

@@ -767,25 +1003,8 @@ await hook(resultContext);

}
if (Object.keys(resolvedDeclaredExtensions).length > 0) {
const settleCoreSnapshot = snapshotSettleResponseCore(settleResult);
for (const [key, declaration] of Object.entries(resolvedDeclaredExtensions)) {
const extension = this.registeredExtensions.get(key);
if (extension?.enrichSettlementResponse) {
try {
const extensionData = await extension.enrichSettlementResponse(
declaration,
resultContext
);
if (extensionData !== void 0) {
if (!settleResult.extensions) {
settleResult.extensions = {};
}
settleResult.extensions[key] = extensionData;
}
} catch (error) {
this.warnExtensionHookFailure(key, "enrichSettlementResponse", error);
}
assertSettleResponseCoreUnchanged(settleCoreSnapshot, settleResult, key);
}
}
}
await this.enrichSettlementResponse(
settleResult,
resultContext,
resolvedDeclaredExtensions,
matchedScheme
);
return settleResult;

@@ -797,3 +1016,7 @@ } catch (error) {

};
for (const { label, hook } of this.getLabeledHooks("onSettleFailure", extensionKeysInUse)) {
for (const { label, hook } of this.getLabeledHooks(
"onSettleFailure",
extensionKeysInUse,
matchedScheme
)) {
try {

@@ -835,68 +1058,2 @@ const result = await hook(failureContext);

/**
* Process a payment request
*
* @param paymentPayload - Optional payment payload if provided
* @param resourceConfig - Configuration for the protected resource
* @param resourceInfo - Information about the resource being accessed
* @param extensions - Optional extensions to include in the response
* @param transportContext - Optional transport context for extension hooks and enrichment
* @returns Processing result
*/
async processPaymentRequest(paymentPayload, resourceConfig, resourceInfo, extensions, transportContext) {
const requirements = await this.buildPaymentRequirements(resourceConfig);
const resolvedRouteExtensions = extensions ?? {};
if (!paymentPayload) {
return {
success: false,
requiresPayment: await this.createPaymentRequiredResponse(
requirements,
resourceInfo,
"Payment required",
extensions,
transportContext
)
};
}
const paymentRequired = await this.createPaymentRequiredResponse(
requirements,
resourceInfo,
void 0,
extensions,
transportContext
);
const matchingRequirements = this.findMatchingRequirements(
paymentRequired.accepts,
paymentPayload
);
if (!matchingRequirements) {
return {
success: false,
requiresPayment: await this.createPaymentRequiredResponse(
requirements,
resourceInfo,
"No matching payment requirements found",
extensions,
transportContext
)
};
}
const verificationResult = await this.verifyPayment(
paymentPayload,
matchingRequirements,
resolvedRouteExtensions,
transportContext
);
if (!verificationResult.isValid) {
return {
success: false,
error: verificationResult.invalidReason,
verificationResult
};
}
return {
success: true,
verificationResult
};
}
/**
* Logs a warning when a manual or extension adapter lifecycle hook throws.

@@ -924,3 +1081,119 @@ *

/**
* Manual hooks first, then extension adapters for keys in `extensionKeysInUse`.
* Executes after-verify hooks for facilitator and hook-provided verify results.
*
* @param verifyResult - Verify response passed to after-verify hooks.
* @param context - Verify context shared with before-verify hooks.
* @param extensionKeysInUse - Declared extension keys for this request.
* @param matchedScheme - Scheme/network selected for this payment.
* @param matchedScheme.network - Matched payment network.
* @param matchedScheme.scheme - Matched payment scheme.
* @returns Verify response with any in-process skip handler directive.
*/
async runAfterVerifyHooks(verifyResult, context, extensionKeysInUse, matchedScheme) {
const resultContext = {
...context,
result: verifyResult
};
let skipHandler;
for (const { label, hook } of this.getLabeledHooks(
"afterVerify",
extensionKeysInUse,
matchedScheme
)) {
try {
const directive = await hook(resultContext);
if (directive && "skipHandler" in directive && directive.skipHandler) {
skipHandler = directive.response ?? {};
}
} catch (error) {
this.warnResourceServerHookFailure("afterVerify", label, error);
}
}
return skipHandler ? { ...verifyResult, skipHandler } : verifyResult;
}
/**
* Runs response enrichment after settlement lifecycle hooks complete.
*
* @param settleResult - Mutable settlement result being returned to the caller
* @param context - Read-only hook context for enrichment callbacks
* @param declaredExtensions - Extension declarations present on this payment
* @param matchedScheme - Scheme/network selected for this settlement
* @param matchedScheme.network - Matched payment network
* @param matchedScheme.scheme - Matched payment scheme
*/
async enrichSettlementResponse(settleResult, context, declaredExtensions, matchedScheme) {
if (Object.keys(declaredExtensions).length > 0) {
const settleCoreSnapshot = snapshotSettleResponseCore(settleResult);
for (const [key, declaration] of Object.entries(declaredExtensions)) {
const extension = this.registeredExtensions.get(key);
if (!extension?.enrichSettlementResponse) continue;
try {
const extensionData = await extension.enrichSettlementResponse(declaration, context);
if (extensionData !== void 0) {
if (!settleResult.extensions) {
settleResult.extensions = {};
}
settleResult.extensions[key] = extensionData;
}
} catch (error) {
this.warnExtensionHookFailure(key, "enrichSettlementResponse", error);
}
assertSettleResponseCoreUnchanged(settleCoreSnapshot, settleResult, key);
}
}
const scheme = findByNetworkAndScheme(
this.registeredServerSchemes,
matchedScheme.scheme,
matchedScheme.network
);
const hook = scheme?.enrichSettlementResponse;
if (!hook) return;
const label = `scheme "${matchedScheme.scheme}" enrichSettlementResponse`;
try {
const enrichment = await hook(context);
if (enrichment === void 0) return;
assertAdditiveSettlementExtra(settleResult.extra ?? {}, enrichment, label);
settleResult.extra = mergeAdditiveSettlementExtra(settleResult.extra ?? {}, enrichment);
} catch (error) {
this.warnResourceServerHookFailure("enrichSettlementResponse", label, error);
}
}
/**
* Notify hooks that verified work ended before settlement.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param options - Cancellation reason and optional diagnostics
* @param fallbackTransportContext - Optional transport-specific context
*/
async dispatchVerifiedPaymentCanceled(paymentPayload, requirements, declaredExtensions, options, fallbackTransportContext) {
const extensionKeysInUse = Object.keys(declaredExtensions);
const matchedScheme = {
network: requirements.network,
scheme: requirements.scheme
};
const context = {
paymentPayload,
requirements,
declaredExtensions,
transportContext: fallbackTransportContext,
reason: options.reason,
error: options.error,
responseStatus: options.responseStatus
};
for (const { label, hook } of this.getLabeledHooks(
"onVerifiedPaymentCanceled",
extensionKeysInUse,
matchedScheme
)) {
try {
await hook(context);
} catch (error) {
this.warnResourceServerHookFailure("onVerifiedPaymentCanceled", label, error);
}
}
}
/**
* Manual hooks first, then the matched scheme adapter, then extension adapters for keys in use.
* Each entry carries a stable label for logging when a hook throws.

@@ -930,5 +1203,8 @@ *

* @param extensionKeysInUse - Declared extension keys for this request
* @param matchedScheme - Scheme/network selected for this payment
* @param matchedScheme.network - Matched payment network
* @param matchedScheme.scheme - Matched payment scheme
* @returns Hooks in invocation order with source labels
*/
getLabeledHooks(phase, extensionKeysInUse) {
getLabeledHooks(phase, extensionKeysInUse, matchedScheme) {
const manualKey = `${phase}Hooks`;

@@ -940,2 +1216,16 @@ const manual = this[manualKey];

});
if (matchedScheme) {
const schemeHandles = findByNetworkAndScheme(
this.schemeHookAdapters,
matchedScheme.scheme,
matchedScheme.network
);
const hook = schemeHandles?.[phase];
if (hook !== void 0) {
out.push({
label: `scheme "${matchedScheme.scheme}" ${phase}`,
hook
});
}
}
const inUse = new Set(extensionKeysInUse);

@@ -970,3 +1260,6 @@ for (const [extensionKey, adapterHandles] of this.extensionHookAdapters.entries()) {

SETTLEMENT_OVERRIDES_HEADER,
assertAcceptsAdditiveExtraAfterSchemeEnrich,
assertAcceptsAllowlistedAfterExtensionEnrich,
assertAdditivePayloadEnrichment,
assertAdditiveSettlementExtra,
assertSettleResponseCoreUnchanged,

@@ -973,0 +1266,0 @@ checkIfBazaarNeeded,

@@ -1,1 +0,1 @@

export { E as AssetAmount, $ as DeepReadonly, Y as FacilitatorContext, F as FacilitatorExtension, f as FacilitatorResponseError, M as Money, U as MoneyParser, N as Network, P as PaymentPayload, X as PaymentPayloadContext, W as PaymentPayloadResult, w as PaymentPayloadV1, c as PaymentRequired, h as PaymentRequiredContext, v as PaymentRequiredV1, a as PaymentRequirements, u as PaymentRequirementsV1, s as Price, Q as ResourceInfo, Z as ResourceServerExtension, _ as ResourceServerExtensionHooks, t as SchemeNetworkClient, b as SchemeNetworkFacilitator, T as SchemeNetworkServer, l as SettleContext, L as SettleError, n as SettleFailureContext, I as SettleRequest, S as SettleResponse, m as SettleResultContext, J as SupportedResponse, i as VerifyContext, K as VerifyError, k as VerifyFailureContext, G as VerifyRequest, V as VerifyResponse, j as VerifyResultContext, g as getFacilitatorResponseError } from '../mechanisms-C6YmSXgy.mjs';
export { a9 as AssetAmount, ar as DeepReadonly, ao as FacilitatorContext, F as FacilitatorExtension, f as FacilitatorResponseError, a8 as Money, al as MoneyParser, N as Network, P as PaymentPayload, an as PaymentPayloadContext, am as PaymentPayloadResult, a3 as PaymentPayloadV1, c as PaymentRequired, h as PaymentRequiredContext, a2 as PaymentRequiredV1, a as PaymentRequirements, a1 as PaymentRequirementsV1, I as Price, ag as ResourceInfo, ap as ResourceServerExtension, aq as ResourceServerExtensionHooks, ai as SchemeClientHooks, C as SchemeEnrichPaymentRequiredResponseHook, ah as SchemeNetworkClient, b as SchemeNetworkFacilitator, aj as SchemeNetworkServer, D as SchemePaymentRequiredContext, ak as SchemeServerHooks, l as SettleContext, af as SettleError, n as SettleFailureContext, ab as SettleRequest, S as SettleResponse, m as SettleResultContext, ad as SupportedKind, ac as SupportedResponse, o as VerifiedPaymentCanceledContext, i as VerifyContext, ae as VerifyError, k as VerifyFailureContext, aa as VerifyRequest, V as VerifyResponse, j as VerifyResultContext, g as getFacilitatorResponseError } from '../x402Client-DmgwYAFT.mjs';

@@ -6,3 +6,3 @@ import {

getFacilitatorResponseError
} from "../chunk-JUGE6MAI.mjs";
} from "../chunk-AGOUMC4P.mjs";
import "../chunk-BJTO5JO5.mjs";

@@ -9,0 +9,0 @@ export {

@@ -1,1 +0,1 @@

export { w as PaymentPayloadV1, v as PaymentRequiredV1, u as PaymentRequirementsV1, z as SettleRequestV1, C as SettleResponseV1, D as SupportedResponseV1, y as VerifyRequestV1 } from '../../mechanisms-C6YmSXgy.mjs';
export { a3 as PaymentPayloadV1, a2 as PaymentRequiredV1, a1 as PaymentRequirementsV1, a5 as SettleRequestV1, a6 as SettleResponseV1, a7 as SupportedResponseV1, a4 as VerifyRequestV1 } from '../../x402Client-DmgwYAFT.mjs';

@@ -1,2 +0,2 @@

import { N as Network } from '../mechanisms-C6YmSXgy.mjs';
import { N as Network } from '../x402Client-DmgwYAFT.mjs';

@@ -3,0 +3,0 @@ /**

{
"name": "@x402/core",
"version": "2.11.0",
"version": "2.12.0",
"main": "./dist/cjs/index.js",

@@ -23,3 +23,3 @@ "module": "./dist/esm/index.js",

"tsup": "^8.4.0",
"tsx": "^4.19.2",
"tsx": "^4.21.0",
"typescript": "^5.7.3",

@@ -26,0 +26,0 @@ "vite": "^6.2.6",

type PaymentRequirementsV1 = {
scheme: string;
network: Network;
maxAmountRequired: string;
resource: string;
description: string;
mimeType: string;
outputSchema: Record<string, unknown>;
payTo: string;
maxTimeoutSeconds: number;
asset: string;
extra: Record<string, unknown>;
};
type PaymentRequiredV1 = {
x402Version: 1;
error?: string;
accepts: PaymentRequirementsV1[];
};
type PaymentPayloadV1 = {
x402Version: 1;
scheme: string;
network: Network;
payload: Record<string, unknown>;
};
type VerifyRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleResponseV1 = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
};
type SupportedResponseV1 = {
kinds: {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
}[];
};
/**
* Recursive readonly for hook contexts so accidental in-place mutation is visible at compile time.
* (Runtime mutation is still possible via other references; see extension enrich validation.)
*/
type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends object ? {
readonly [K in keyof T]: DeepReadonly<T[K]>;
} : T;
interface FacilitatorConfig {
url?: string;
createAuthHeaders?: () => Promise<{
verify: Record<string, string>;
settle: Record<string, string>;
supported: Record<string, string>;
}>;
}
/**
* Interface for facilitator clients
* Can be implemented for HTTP-based or local facilitators
*/
interface FacilitatorClient {
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
}
/**
* HTTP-based client for interacting with x402 facilitator services
* Handles HTTP communication with facilitator endpoints
*/
declare class HTTPFacilitatorClient implements FacilitatorClient {
readonly url: string;
private readonly _createAuthHeaders?;
/**
* Creates a new HTTPFacilitatorClient instance.
*
* @param config - Configuration options for the facilitator client
*/
constructor(config?: FacilitatorConfig);
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator.
* Retries with exponential backoff on 429 rate limit errors.
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
/**
* 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
*/
createAuthHeaders(path: string): Promise<{
headers: Record<string, string>;
}>;
/**
* 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
*/
private toJsonSafe;
}
/**
* Configuration for a protected resource
* Only contains payment-specific configuration, not resource metadata
*/
interface ResourceConfig {
scheme: string;
/**
* Payment recipient. Use a **vacant** value (`""` or whitespace-only) when an extension must
* fill `payTo` during `enrichPaymentRequiredResponse`; non-vacant values are **immutable** there
* so extensions cannot redirect funds to an arbitrary address.
*/
payTo: string;
price: Price;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Context for `enrichPaymentRequiredResponse`. Extensions may merge extension payload via the
* return value. In-place edits to `paymentRequiredResponse.accepts` are **allowlisted** only
* (see {@link assertAcceptsAllowlistedAfterExtensionEnrich}): `scheme`, `network`, and
* `maxTimeoutSeconds` are immutable; `payTo`, `amount`, and `asset` may change only when the
* baseline value was vacant; `extra` may add keys but must not change or remove baseline keys.
*/
interface PaymentRequiredContext {
requirements: PaymentRequirements[];
resourceInfo: ResourceInfo;
error?: string;
paymentRequiredResponse: PaymentRequired;
transportContext?: unknown;
}
/**
* Verify / settle lifecycle hook context: treat as **read-only** for core protocol fields.
* Control flow uses **abort** / **recover** return values only, not in-place mutation.
*/
interface VerifyContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface VerifyResultContext extends VerifyContext {
result: DeepReadonly<VerifyResponse>;
}
interface VerifyFailureContext extends VerifyContext {
error: Error;
}
interface SettleContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface SettleResultContext extends SettleContext {
result: DeepReadonly<SettleResponse>;
}
interface SettleFailureContext extends SettleContext {
error: Error;
}
type BeforeVerifyHook = (context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
type AfterVerifyHook = (context: VerifyResultContext) => Promise<void>;
type OnVerifyFailureHook = (context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
type BeforeSettleHook = (context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
type AfterSettleHook = (context: SettleResultContext) => Promise<void>;
type OnSettleFailureHook = (context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
/**
* Optional overrides for settlement parameters.
* Used to support partial settlement (e.g., upto scheme billing by actual usage).
*
* Note: Overriding the amount to a value different from the agreed-upon
* `PaymentRequirements.amount` is only valid in schemes that explicitly support
* partial settlement, such as the `upto` scheme. Using this with standard
* x402 schemes (e.g., `exact`) will likely cause settlement verification to fail.
*/
interface SettlementOverrides {
/**
* Amount to settle. Supports three formats:
*
* - **Raw atomic units** — e.g., `"1000"` settles exactly 1000 atomic units.
* - **Percent** — e.g., `"50%"` settles 50% of `PaymentRequirements.amount`.
* Supports up to two decimal places (e.g., `"33.33%"`). The result is floored
* to the nearest atomic unit.
* - **Dollar price** — e.g., `"$0.05"` converts a USD-denominated price to
* atomic units. Decimals are determined from the registered scheme's
* `getAssetDecimals` method, falling back to 6 (standard for USDC stablecoins).
* The result is rounded to the nearest atomic unit.
*
* The resolved amount must be <= the authorized maximum in `PaymentRequirements`.
*
* Note: Setting this to an amount other than `PaymentRequirements.amount` is
* only valid in schemes that support partial settlement, such as `upto`.
*/
amount?: string;
}
/**
* Core x402 protocol server for resource protection
* Transport-agnostic implementation of the x402 payment protocol
*/
declare class x402ResourceServer {
private facilitatorClients;
private registeredServerSchemes;
private supportedResponsesMap;
private facilitatorClientsMap;
private registeredExtensions;
private extensionHookAdapters;
private beforeVerifyHooks;
private afterVerifyHooks;
private onVerifyFailureHooks;
private beforeSettleHooks;
private afterSettleHooks;
private onSettleFailureHooks;
/**
* Creates a new x402ResourceServer instance.
*
* @param facilitatorClients - Optional facilitator client(s) for payment processing
*/
constructor(facilitatorClients?: FacilitatorClient | FacilitatorClient[]);
/**
* Register a scheme/network server implementation.
*
* @param network - The network identifier
* @param server - The scheme/network server implementation
* @returns The x402ResourceServer instance for chaining
*/
register(network: Network, server: SchemeNetworkServer): x402ResourceServer;
/**
* Check if a scheme is registered for a given network.
*
* @param network - The network identifier
* @param scheme - The payment scheme name
* @returns True if the scheme is registered for the network, false otherwise
*/
hasRegisteredScheme(network: Network, scheme: string): boolean;
/**
* Returns the decimal precision for the asset specified in the given payment requirements.
* Looks up the registered scheme for the network and delegates to its getAssetDecimals
* method if available. Falls back to 6 (standard for USDC stablecoins) when the scheme
* does not implement getAssetDecimals or is not registered.
*
* @param requirements - The payment requirements containing scheme, network, and asset
* @returns The number of decimal places for the asset
*/
getAssetDecimalsForRequirements(requirements: PaymentRequirements): number;
/**
* Registers a resource server extension (enrichment and optional verify/settle hooks).
* Re-registering the same key overwrites; omitting `hooks` removes adapter handles for that key.
*
* @param extension - Extension definition including `key` and optional `hooks`
* @returns This server instance for chaining
*/
registerExtension(extension: ResourceServerExtension): this;
/**
* Check if an extension is registered.
*
* @param key - The extension key
* @returns True if the extension is registered
*/
hasExtension(key: string): boolean;
/**
* Get all registered extensions.
*
* @returns Array of registered extensions
*/
getExtensions(): ResourceServerExtension[];
/**
* Enriches declared extensions using registered extension hooks.
*
* @param declaredExtensions - Extensions declared on the route
* @param transportContext - Transport-specific context (HTTP, A2A, MCP, etc.)
* @returns Enriched extensions map
*/
enrichExtensions(declaredExtensions: Record<string, unknown>, transportContext: unknown): Record<string, unknown>;
/**
* Register a hook to execute before payment verification.
* Can abort verification by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeVerify(hook: BeforeVerifyHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment verification.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterVerify(hook: AfterVerifyHook): x402ResourceServer;
/**
* Register a hook to execute when payment verification fails.
* Can recover from failure by returning { recovered: true, result: VerifyResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifyFailure(hook: OnVerifyFailureHook): x402ResourceServer;
/**
* Register a hook to execute before payment settlement.
* Can abort settlement by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeSettle(hook: BeforeSettleHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterSettle(hook: AfterSettleHook): x402ResourceServer;
/**
* Register a hook to execute when payment settlement fails.
* Can recover from failure by returning { recovered: true, result: SettleResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onSettleFailure(hook: OnSettleFailureHook): x402ResourceServer;
/**
* Initialize by fetching supported kinds from all facilitators
* Creates mappings for supported responses and facilitator clients
* Earlier facilitators in the array get precedence
*/
initialize(): Promise<void>;
/**
* Get supported kind for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The supported kind or undefined if not found
*/
getSupportedKind(x402Version: number, network: Network, scheme: string): SupportedKind | undefined;
/**
* Get facilitator extensions for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator extensions or empty array if not found
*/
getFacilitatorExtensions(x402Version: number, network: Network, scheme: string): string[];
/**
* Build payment requirements for a protected resource
*
* @param resourceConfig - Configuration for the protected resource
* @returns Array of payment requirements
*/
buildPaymentRequirements(resourceConfig: ResourceConfig): Promise<PaymentRequirements[]>;
/**
* Build payment requirements from multiple payment options
* This method handles resolving dynamic payTo/price functions and builds requirements for each option
*
* @param paymentOptions - Array of payment options to convert
* @param context - HTTP request context for resolving dynamic functions
* @returns Array of payment requirements (one per option)
*/
buildPaymentRequirementsFromOptions<TContext = unknown>(paymentOptions: Array<{
scheme: string;
payTo: string | ((context: TContext) => string | Promise<string>);
price: Price | ((context: TContext) => Price | Promise<Price>);
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}>, context: TContext): Promise<PaymentRequirements[]>;
/**
* Create a payment required response
*
* @param requirements - Payment requirements
* @param resourceInfo - Resource information
* @param error - Error message
* @param extensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request, MCP tool context)
* @returns Payment required response object
*/
createPaymentRequiredResponse(requirements: PaymentRequirements[], resourceInfo: ResourceInfo, error?: string, extensions?: Record<string, unknown>, transportContext?: unknown): Promise<PaymentRequired>;
/**
* Verifies a payment against requirements, running manual and in-use extension hooks.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context (e.g. HTTP, MCP)
* @returns Facilitator verify outcome, or abort/recovery as driven by hooks
*/
verifyPayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown): Promise<VerifyResponse>;
/**
* Settle a verified payment
*
* @param paymentPayload - The payment payload to settle
* @param requirements - The payment requirements
* @param declaredExtensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request/response, MCP tool context)
* @param settlementOverrides - Optional overrides for settlement parameters (e.g., partial settlement amount)
* @returns Settlement response
*/
settlePayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown, settlementOverrides?: SettlementOverrides): Promise<SettleResponse>;
/**
* Find matching payment requirements for a payment
*
* @param availableRequirements - Array of available payment requirements
* @param paymentPayload - The payment payload
* @returns Matching payment requirements or undefined
*/
findMatchingRequirements(availableRequirements: PaymentRequirements[], paymentPayload: PaymentPayload): PaymentRequirements | undefined;
/**
* Process a payment request
*
* @param paymentPayload - Optional payment payload if provided
* @param resourceConfig - Configuration for the protected resource
* @param resourceInfo - Information about the resource being accessed
* @param extensions - Optional extensions to include in the response
* @param transportContext - Optional transport context for extension hooks and enrichment
* @returns Processing result
*/
processPaymentRequest(paymentPayload: PaymentPayload | null, resourceConfig: ResourceConfig, resourceInfo: ResourceInfo, extensions?: Record<string, unknown>, transportContext?: unknown): Promise<{
success: boolean;
requiresPayment?: PaymentRequired;
verificationResult?: VerifyResponse;
settlementResult?: SettleResponse;
error?: string;
}>;
/**
* Logs a warning when a manual or extension adapter lifecycle hook throws.
*
* @param phase - Lifecycle phase name (e.g. `beforeVerify`)
* @param label - Hook source label from {@link getLabeledHooks} (manual index or extension key)
* @param error - Thrown value or rejection reason
*/
private warnResourceServerHookFailure;
/**
* Logs a warning when a registered extension enrichment hook throws.
*
* @param extensionKey - Registered extension identifier
* @param hookName - Hook method name (e.g. `enrichDeclaration`)
* @param error - Thrown value or rejection reason
*/
private warnExtensionHookFailure;
/**
* Manual hooks first, then extension adapters for keys in `extensionKeysInUse`.
* Each entry carries a stable label for logging when a hook throws.
*
* @param phase - Hook slot (e.g. `beforeVerify`)
* @param extensionKeysInUse - Declared extension keys for this request
* @returns Hooks in invocation order with source labels
*/
private getLabeledHooks;
/**
* Get facilitator client for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator client or undefined if not found
*/
private getFacilitatorClient;
}
interface FacilitatorExtension {
key: string;
}
/**
* Per-extension verify/settle hooks. Contexts are **read-only** for core protocol fields; use
* **abort** / **recover** return values instead of mutating `paymentPayload`, `requirements`, etc.
*/
interface ResourceServerExtensionHooks {
onBeforeVerify?: (declaration: unknown, context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
onAfterVerify?: (declaration: unknown, context: VerifyResultContext) => Promise<void>;
onVerifyFailure?: (declaration: unknown, context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
onBeforeSettle?: (declaration: unknown, context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
onAfterSettle?: (declaration: unknown, context: SettleResultContext) => Promise<void>;
onSettleFailure?: (declaration: unknown, context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
}
interface ResourceServerExtension {
key: string;
enrichDeclaration?: (declaration: unknown, transportContext: unknown) => unknown;
/**
* Return value merges into `extensions[key]`. In-place edits to `accepts` are allowlisted only
* (see server `assertAcceptsAllowlistedAfterExtensionEnrich`): vacant `payTo` / `amount` / `asset`
* may be filled; locked values and `scheme` / `network` / `maxTimeoutSeconds` / baseline `extra`
* entries are immutable.
*/
enrichPaymentRequiredResponse?: (declaration: unknown, context: PaymentRequiredContext) => Promise<unknown>;
/**
* Return value merges into `settleResult.extensions[key]`. Facilitator fields (`success`,
* `transaction`, `network`, etc.) must not be changed; only `extensions` is merged from the hook.
*/
enrichSettlementResponse?: (declaration: unknown, context: SettleResultContext) => Promise<unknown>;
/** Installed on `registerExtension`; runs only when `declaredExtensions[key]` is defined. */
hooks?: ResourceServerExtensionHooks;
}
type Network = `${string}:${string}`;
type Money = string | number;
type AssetAmount = {
asset: string;
amount: string;
extra?: Record<string, unknown>;
};
type Price = Money | AssetAmount;
interface ResourceInfo {
url: string;
description?: string;
mimeType?: string;
}
type PaymentRequirements = {
scheme: string;
network: Network;
asset: string;
amount: string;
payTo: string;
maxTimeoutSeconds: number;
extra: Record<string, unknown>;
};
type PaymentRequired = {
x402Version: number;
error?: string;
resource: ResourceInfo;
accepts: PaymentRequirements[];
extensions?: Record<string, unknown>;
};
type PaymentPayload = {
x402Version: number;
resource?: ResourceInfo;
accepted: PaymentRequirements;
payload: Record<string, unknown>;
extensions?: Record<string, unknown>;
};
type VerifyRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type VerifyResponse = {
isValid: boolean;
invalidReason?: string;
invalidMessage?: string;
payer?: string;
extensions?: Record<string, unknown>;
};
type SettleRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type SettleResponse = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
/** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */
amount?: string;
extensions?: Record<string, unknown>;
};
type SupportedKind = {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
};
type SupportedResponse = {
kinds: SupportedKind[];
extensions: string[];
signers: Record<string, string[]>;
};
/**
* Error thrown when payment verification fails.
*/
declare class VerifyError extends Error {
readonly invalidReason?: string;
readonly invalidMessage?: string;
readonly payer?: string;
readonly statusCode: number;
/**
* 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: number, response: VerifyResponse);
}
/**
* Error thrown when payment settlement fails.
*/
declare class SettleError extends Error {
readonly errorReason?: string;
readonly errorMessage?: string;
readonly payer?: string;
readonly transaction: string;
readonly network: Network;
readonly statusCode: number;
/**
* 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: number, response: SettleResponse);
}
/**
* Error thrown when a facilitator returns malformed success payload data.
*/
declare class FacilitatorResponseError extends Error {
/**
* Creates a FacilitatorResponseError for malformed facilitator responses.
*
* @param message - The boundary error message
*/
constructor(message: string);
}
/**
* Walks an error cause chain to find the first facilitator response error.
*
* @param error - The thrown value to inspect
* @returns The nested facilitator response error, if present
*/
declare function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null;
/**
* Money parser function that converts a numeric amount to an AssetAmount
* Receives the amount as a decimal number (e.g., 1.50 for $1.50)
* Returns null to indicate "cannot handle this amount", causing fallback to next parser
* Always returns a Promise for consistency - use async/await
*
* @param amount - The decimal amount (e.g., 1.50)
* @param network - The network identifier for context
* @returns AssetAmount or null to try next parser
*/
type MoneyParser = (amount: number, network: Network) => Promise<AssetAmount | null>;
/**
* Result of createPaymentPayload - the core payload fields.
* Contains the x402 version, scheme-specific payload data, and optional extension data.
* Schemes may return extensions (e.g., EIP-2612 gas sponsoring) that get merged
* with server-declared extensions in the final PaymentPayload.
*/
type PaymentPayloadResult = Pick<PaymentPayload, "x402Version" | "payload"> & {
extensions?: Record<string, unknown>;
};
/**
* Context passed to scheme's createPaymentPayload for extensions awareness.
* Contains the server-declared extensions from PaymentRequired so the scheme
* can check which extensions are advertised and respond accordingly.
*/
interface PaymentPayloadContext {
extensions?: Record<string, unknown>;
}
interface SchemeNetworkClient {
readonly scheme: string;
createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
}
/**
* Context passed to SchemeNetworkFacilitator.verify/settle, providing
* access to registered facilitator extensions. Mechanism implementations
* use this to retrieve extension-provided capabilities (e.g., a batch signer).
*/
interface FacilitatorContext {
getExtension<T extends FacilitatorExtension = FacilitatorExtension>(key: string): T | undefined;
}
interface SchemeNetworkFacilitator {
readonly scheme: string;
/**
* CAIP family pattern that this facilitator supports.
* Used to group signers by blockchain family in the supported response.
*
* @example
* // EVM facilitators
* readonly caipFamily = "eip155:*";
*
* @example
* // SVM facilitators
* readonly caipFamily = "solana:*";
*/
readonly caipFamily: string;
/**
* Get mechanism-specific extra data needed for the supported kinds endpoint.
* This method is called when building the facilitator's supported response.
*
* @param network - The network identifier for context
* @returns Extra data object or undefined if no extra data is needed
*
* @example
* // EVM schemes return undefined (no extra data needed)
* getExtra(network: Network): undefined {
* return undefined;
* }
*
* @example
* // SVM schemes return feePayer address
* getExtra(network: Network): Record<string, unknown> | undefined {
* return { feePayer: this.signer.address };
* }
*/
getExtra(network: Network): Record<string, unknown> | undefined;
/**
* Get signer addresses used by this facilitator for a given network.
* These are included in the supported response to help clients understand
* which addresses might sign/pay for transactions.
*
* Supports multiple addresses for load balancing, key rotation, and high availability.
*
* @param network - The network identifier
* @returns Array of signer addresses (wallet addresses, fee payer addresses, etc.)
*
* @example
* // EVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*
* @example
* // SVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*/
getSigners(network: string): string[];
verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
}
interface SchemeNetworkServer {
readonly scheme: string;
/**
* Convert a user-friendly price to the scheme's specific amount and asset format
* Always returns a Promise for consistency
*
* @param price - User-friendly price (e.g., "$0.10", "0.10", { amount: "100000", asset: "USDC" })
* @param network - The network identifier for context
* @returns Promise that resolves to the converted amount, asset identifier, and any extra metadata
*
* @example
* // For EVM networks with USDC:
* await parsePrice("$0.10", "eip155:8453") => { amount: "100000", asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
*
* // For custom schemes:
* await parsePrice("10 points", "custom:network") => { amount: "10", asset: "points" }
*/
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
/**
* Optional: Return the decimal precision of the asset for a given network.
* Used by `resolveSettlementOverrideAmount` to convert dollar-format overrides to atomic units.
* Defaults to 6 when not implemented.
*
* @param asset - The asset address or symbol
* @param network - The network identifier
* @returns Number of decimal places for the asset
*/
getAssetDecimals?(asset: string, network: Network): number;
/**
* Build payment requirements for this scheme/network combination
*
* @param paymentRequirements - Base payment requirements with amount/asset already set
* @param supportedKind - The supported kind from facilitator's /supported endpoint
* @param supportedKind.x402Version - The x402 version
* @param supportedKind.scheme - The payment scheme
* @param supportedKind.network - The network identifier
* @param supportedKind.extra - Optional extra metadata
* @param facilitatorExtensions - Extensions supported by the facilitator
* @returns Enhanced payment requirements ready to be sent to clients
*/
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
}, facilitatorExtensions: string[]): Promise<PaymentRequirements>;
}
export { type DeepReadonly as $, type AfterVerifyHook as A, type BeforeVerifyHook as B, type SettleResponseV1 as C, type SupportedResponseV1 as D, type AssetAmount as E, type FacilitatorExtension as F, type VerifyRequest as G, HTTPFacilitatorClient as H, type SettleRequest as I, type SupportedResponse as J, VerifyError as K, SettleError as L, type Money as M, type Network as N, type OnVerifyFailureHook as O, type PaymentPayload as P, type ResourceInfo as Q, type ResourceConfig as R, type SettleResponse as S, type SchemeNetworkServer as T, type MoneyParser as U, type VerifyResponse as V, type PaymentPayloadResult as W, type PaymentPayloadContext as X, type FacilitatorContext as Y, type ResourceServerExtension as Z, type ResourceServerExtensionHooks as _, type PaymentRequirements as a, type SchemeNetworkFacilitator as b, type PaymentRequired as c, type FacilitatorClient as d, type FacilitatorConfig as e, FacilitatorResponseError as f, getFacilitatorResponseError as g, type PaymentRequiredContext as h, type VerifyContext as i, type VerifyResultContext as j, type VerifyFailureContext as k, type SettleContext as l, type SettleResultContext as m, type SettleFailureContext as n, type SettlementOverrides as o, type BeforeSettleHook as p, type AfterSettleHook as q, type OnSettleFailureHook as r, type Price as s, type SchemeNetworkClient as t, type PaymentRequirementsV1 as u, type PaymentRequiredV1 as v, type PaymentPayloadV1 as w, x402ResourceServer as x, type VerifyRequestV1 as y, type SettleRequestV1 as z };
import { x as x402ResourceServer, s as Price, N as Network, S as SettleResponse, c as PaymentRequired, P as PaymentPayload, a as PaymentRequirements, o as SettlementOverrides } from './mechanisms-C6YmSXgy.js';
declare const SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
/**
* Framework-agnostic HTTP adapter interface
* Implementations provide framework-specific HTTP operations
*/
interface HTTPAdapter {
getHeader(name: string): string | undefined;
getMethod(): string;
getPath(): string;
getUrl(): string;
getAcceptHeader(): string;
getUserAgent(): string;
/**
* Get query parameters from the request URL
*
* @returns Record of query parameter key-value pairs
*/
getQueryParams?(): Record<string, string | string[]>;
/**
* Get a specific query parameter by name
*
* @param name - The query parameter name
* @returns The query parameter value(s) or undefined
*/
getQueryParam?(name: string): string | string[] | undefined;
/**
* Get the parsed request body
* Framework adapters should parse JSON/form data appropriately
*
* @returns The parsed request body
*/
getBody?(): unknown;
}
/**
* Paywall configuration for HTML responses
*/
interface PaywallConfig {
appName?: string;
appLogo?: string;
sessionTokenEndpoint?: string;
currentUrl?: string;
testnet?: boolean;
}
/**
* Paywall provider interface for generating HTML
*/
interface PaywallProvider {
generateHtml(paymentRequired: PaymentRequired, config?: PaywallConfig): string;
}
/**
* Dynamic payTo function that receives HTTP request context
*/
type DynamicPayTo = (context: HTTPRequestContext) => string | Promise<string>;
/**
* Dynamic price function that receives HTTP request context
*/
type DynamicPrice = (context: HTTPRequestContext) => Price | Promise<Price>;
/**
* Result of response body callbacks containing content type and body.
*/
interface HTTPResponseBody {
/**
* The content type for the response (e.g., 'application/json', 'text/plain').
*/
contentType: string;
/**
* The response body to include in the 402 response.
*/
body: unknown;
}
/**
* Dynamic function to generate a custom response for unpaid requests.
* Receives the HTTP request context and returns the content type and body to include in the 402 response.
*/
type UnpaidResponseBody = (context: HTTPRequestContext) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* Dynamic function to generate a custom response for settlement failures.
* Receives the HTTP request context and settle failure result, returns the content type and body.
*/
type SettlementFailedResponseBody = (context: HTTPRequestContext, settleResult: Omit<ProcessSettleFailureResponse, "response">) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* A single payment option for a route
* Represents one way a client can pay for access to the resource
*/
interface PaymentOption {
scheme: string;
payTo: string | DynamicPayTo;
price: Price | DynamicPrice;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Route configuration for HTTP endpoints
*
* The 'accepts' field defines payment options for the route.
* Can be a single PaymentOption or an array of PaymentOptions for multiple payment methods.
*/
interface RouteConfig {
accepts: PaymentOption | PaymentOption[];
resource?: string;
description?: string;
mimeType?: string;
customPaywallHtml?: string;
/**
* Optional callback to generate a custom response for unpaid API requests.
* This allows servers to return preview data, error messages, or other content
* when a request lacks payment.
*
* For browser requests (Accept: text/html), the paywall HTML takes precedence.
* This callback is only used for API clients.
*
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @returns An object containing both contentType and body for the 402 response
*/
unpaidResponseBody?: UnpaidResponseBody;
/**
* Optional callback to generate a custom response for settlement failures.
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @param settleResult - The settlement failure result
* @returns An object containing both contentType and body for the 402 response
*/
settlementFailedResponseBody?: SettlementFailedResponseBody;
extensions?: Record<string, unknown>;
}
/**
* Routes configuration - maps path patterns to route configs
*/
type RoutesConfig = Record<string, RouteConfig> | RouteConfig;
/**
* Check if any routes in the configuration declare bazaar extensions.
*
* @param routes - Route configuration
* @returns True if any route has extensions.bazaar defined
*/
declare function checkIfBazaarNeeded(routes: RoutesConfig): boolean;
/**
* Hook that runs on every request to a protected route, before payment processing.
* Can grant access without payment, deny the request, or continue to payment flow.
*
* @returns
* - `void` - Continue to payment processing (default behavior)
* - `{ grantAccess: true }` - Grant access without requiring payment
* - `{ abort: true; reason: string }` - Deny the request (returns 403)
*/
type ProtectedRequestHook = (context: HTTPRequestContext, routeConfig: RouteConfig) => Promise<void | {
grantAccess: true;
} | {
abort: true;
reason: string;
}>;
/**
* Compiled route for efficient matching
*/
interface CompiledRoute {
verb: string;
regex: RegExp;
config: RouteConfig;
pattern: string;
}
/**
* HTTP request context that encapsulates all request data
*/
interface HTTPRequestContext {
adapter: HTTPAdapter;
path: string;
method: string;
paymentHeader?: string;
routePattern?: string;
}
/**
* HTTP transport context contains both request context and optional response data.
*/
interface HTTPTransportContext {
/** The HTTP request context */
request: HTTPRequestContext;
/** The response body buffer */
responseBody?: Buffer;
/** Response headers set by the route handler (used for settlement overrides) */
responseHeaders?: Record<string, string>;
}
/**
* HTTP response instructions for the framework middleware
*/
interface HTTPResponseInstructions {
status: number;
headers: Record<string, string>;
body?: unknown;
isHtml?: boolean;
}
/**
* Result of processing an HTTP request for payment
*/
type HTTPProcessResult = {
type: "no-payment-required";
} | {
type: "payment-verified";
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
declaredExtensions?: Record<string, unknown>;
} | {
type: "payment-error";
response: HTTPResponseInstructions;
};
/**
* Result of processSettlement
*/
type ProcessSettleSuccessResponse = SettleResponse & {
success: true;
headers: Record<string, string>;
requirements: PaymentRequirements;
};
type ProcessSettleFailureResponse = SettleResponse & {
success: false;
errorReason: string;
errorMessage?: string;
headers: Record<string, string>;
response: HTTPResponseInstructions;
};
type ProcessSettleResultResponse = ProcessSettleSuccessResponse | ProcessSettleFailureResponse;
/**
* Represents a validation error for a specific route's payment configuration.
*/
interface RouteValidationError {
/** The route pattern (e.g., "GET /api/weather") */
routePattern: string;
/** The payment scheme that failed validation */
scheme: string;
/** The network that failed validation */
network: Network;
/** The type of validation failure */
reason: "missing_scheme" | "missing_facilitator";
/** Human-readable error message */
message: string;
}
/**
* Error thrown when route configuration validation fails.
*/
declare class RouteConfigurationError extends Error {
/** The validation errors that caused this exception */
readonly errors: RouteValidationError[];
/**
* Creates a new RouteConfigurationError with the given validation errors.
*
* @param errors - The validation errors that caused this exception.
*/
constructor(errors: RouteValidationError[]);
}
/**
* HTTP-enhanced x402 resource server
* Provides framework-agnostic HTTP protocol handling
*/
declare class x402HTTPResourceServer {
private ResourceServer;
private compiledRoutes;
private routesConfig;
private paywallProvider?;
private protectedRequestHooks;
/**
* Creates a new x402HTTPResourceServer instance.
*
* @param ResourceServer - The core x402ResourceServer instance to use
* @param routes - Route configuration for payment-protected endpoints
*/
constructor(ResourceServer: x402ResourceServer, routes: RoutesConfig);
/**
* Get the underlying x402ResourceServer instance.
*
* @returns The underlying x402ResourceServer instance
*/
get server(): x402ResourceServer;
/**
* Get the routes configuration.
*
* @returns The routes configuration
*/
get routes(): 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();
* ```
*/
initialize(): Promise<void>;
/**
* Register a custom paywall provider for generating HTML
*
* @param provider - PaywallProvider instance
* @returns This service instance for chaining
*/
registerPaywallProvider(provider: PaywallProvider): 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: ProtectedRequestHook): 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
*/
processHTTPRequest(context: HTTPRequestContext, paywallConfig?: PaywallConfig): Promise<HTTPProcessResult>;
/**
* 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)
* @param transportContext - Optional HTTP transport context
* @param settlementOverrides - Optional settlement overrides (e.g., partial settlement amount)
* @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
*/
processSettlement(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: HTTPTransportContext, settlementOverrides?: SettlementOverrides): Promise<ProcessSettleResultResponse>;
/**
* 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: HTTPRequestContext): boolean;
/**
* Build HTTPResponseInstructions for settlement failure.
* Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
*
* @param failure - Settlement failure result with headers
* @param transportContext - Optional HTTP transport context for the request
* @returns HTTP response instructions for the 402 settlement failure response
*/
private buildSettlementFailureResponse;
/**
* 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
*/
private normalizePaymentOptions;
/**
* 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)
*/
private validateRouteConfiguration;
/**
* Get route configuration for a request
*
* @param path - Request path
* @param method - HTTP method
* @returns Route configuration and pattern, or undefined if no match
*/
private getRouteConfig;
/**
* Extract payment from HTTP headers (handles v1 and v2)
*
* @param adapter - HTTP adapter
* @returns Decoded payment payload or null
*/
private extractPayment;
/**
* Check if request is from a web browser
*
* @param adapter - HTTP adapter
* @returns True if request appears to be from a browser
*/
private isWebBrowser;
/**
* 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
*/
private createHTTPResponse;
/**
* 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
*/
private createHTTPPaymentRequiredResponse;
/**
* Create settlement response headers
*
* @param settleResponse - Settlement response
* @returns Headers to add to response
*/
private createSettlementHeaders;
/**
* Parse route pattern into verb and regex
*
* @param pattern - Route pattern like "GET /api/*", "/api/[id]", or "/api/:id"
* @returns Parsed pattern with verb and regex
*/
private parseRoutePattern;
/**
* Normalize path for matching
*
* @param path - Raw path from request
* @returns Normalized path
*/
private normalizePath;
/**
* 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
*/
private generatePaywallHTML;
/**
* Extract display amount from payment requirements.
* Uses the registered scheme's decimal precision for the asset, falling back to 6.
*
* @param paymentRequired - The payment required object
* @returns The display amount in decimal format
*/
private getDisplayAmount;
}
export { type CompiledRoute as C, type DynamicPayTo as D, type HTTPAdapter as H, type PaywallConfig as P, type RouteConfig as R, type SettlementFailedResponseBody as S, type UnpaidResponseBody as U, type HTTPRequestContext as a, type HTTPTransportContext as b, type HTTPResponseInstructions as c, type HTTPProcessResult as d, type PaywallProvider as e, type PaymentOption as f, type RoutesConfig as g, type DynamicPrice as h, type HTTPResponseBody as i, type ProcessSettleResultResponse as j, type ProcessSettleSuccessResponse as k, type ProcessSettleFailureResponse as l, type RouteValidationError as m, RouteConfigurationError as n, type ProtectedRequestHook as o, SETTLEMENT_OVERRIDES_HEADER as p, checkIfBazaarNeeded as q, x402HTTPResourceServer as x };
import {
z
} from "./chunk-KMQH4MQI.mjs";
import {
x402Version
} from "./chunk-VE37GDG2.mjs";
import {
FacilitatorResponseError,
SettleError,
VerifyError
} from "./chunk-JUGE6MAI.mjs";
import {
Base64EncodedRegex,
safeBase64Decode,
safeBase64Encode
} from "./chunk-4BKQ2IT7.mjs";
import {
__require
} from "./chunk-BJTO5JO5.mjs";
// src/http/x402HTTPResourceServer.ts
var SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
function checkIfBazaarNeeded(routes) {
if ("accepts" in routes) {
return !!(routes.extensions && "bazaar" in routes.extensions);
}
return Object.values(routes).some((routeConfig) => {
return !!(routeConfig.extensions && "bazaar" in routeConfig.extensions);
});
}
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,
pattern: parsed.path
});
}
}
/**
* 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 method = context.method || context.adapter.getMethod();
context = { ...context, method };
const { adapter, path } = context;
const routeMatch = this.getRouteConfig(path, method);
if (!routeMatch) {
return { type: "no-payment-required" };
}
const { config: routeConfig, pattern: routePattern } = routeMatch;
const enrichedContext = { ...context, routePattern };
for (const hook of this.protectedRequestHooks) {
const result = await hook(enrichedContext, 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 || enrichedContext.adapter.getUrl(),
description: routeConfig.description || "",
mimeType: routeConfig.mimeType || ""
};
let requirements = await this.ResourceServer.buildPaymentRequirementsFromOptions(
paymentOptions,
enrichedContext
);
let extensions = routeConfig.extensions;
if (extensions) {
extensions = this.ResourceServer.enrichExtensions(extensions, enrichedContext);
}
const transportContext = { request: enrichedContext };
const paymentRequired = await this.ResourceServer.createPaymentRequiredResponse(
requirements,
resourceInfo,
!paymentPayload ? "Payment required" : void 0,
extensions,
transportContext
);
if (!paymentPayload) {
const unpaidBody = routeConfig.unpaidResponseBody ? await routeConfig.unpaidResponseBody(enrichedContext) : 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",
extensions ?? {},
transportContext
);
return {
type: "payment-error",
response: this.createHTTPResponse(errorResponse, false, paywallConfig)
};
}
const verifyResult = await this.ResourceServer.verifyPayment(
paymentPayload,
matchingRequirements,
extensions ?? {},
transportContext
);
if (!verifyResult.isValid) {
const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
requirements,
resourceInfo,
verifyResult.invalidReason,
extensions ?? {},
transportContext
);
return {
type: "payment-error",
response: this.createHTTPResponse(errorResponse, false, paywallConfig)
};
}
return {
type: "payment-verified",
paymentPayload,
paymentRequirements: matchingRequirements,
declaredExtensions: extensions ?? {}
};
} catch (error) {
if (error instanceof FacilitatorResponseError) {
throw error;
}
const errorResponse = await this.ResourceServer.createPaymentRequiredResponse(
requirements,
resourceInfo,
error instanceof Error ? error.message : "Payment verification failed",
extensions ?? {},
transportContext
);
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)
* @param transportContext - Optional HTTP transport context
* @param settlementOverrides - Optional settlement overrides (e.g., partial settlement amount)
* @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
*/
async processSettlement(paymentPayload, requirements, declaredExtensions, transportContext, settlementOverrides) {
if (transportContext?.request && !transportContext.request.method) {
transportContext = {
...transportContext,
request: {
...transportContext.request,
method: transportContext.request.adapter.getMethod()
}
};
}
try {
let resolvedOverrides = settlementOverrides;
if (!resolvedOverrides && transportContext?.responseHeaders) {
const overridesKey = SETTLEMENT_OVERRIDES_HEADER.toLowerCase();
const rawValue = Object.entries(transportContext.responseHeaders).find(
([key]) => key.toLowerCase() === overridesKey
)?.[1];
if (rawValue) {
try {
resolvedOverrides = JSON.parse(rawValue);
} catch {
}
}
}
const settleResponse = await this.ResourceServer.settlePayment(
paymentPayload,
requirements,
declaredExtensions,
transportContext,
resolvedOverrides
);
if (!settleResponse.success) {
const failure = {
...settleResponse,
success: false,
errorReason: settleResponse.errorReason || "Settlement failed",
errorMessage: settleResponse.errorMessage || settleResponse.errorReason || "Settlement failed",
headers: this.createSettlementHeaders(settleResponse)
};
const response = await this.buildSettlementFailureResponse(failure, transportContext);
return { ...failure, response };
}
return {
...settleResponse,
success: true,
headers: this.createSettlementHeaders(settleResponse),
requirements
};
} catch (error) {
if (error instanceof FacilitatorResponseError) {
throw error;
}
if (error instanceof SettleError) {
const errorReason2 = error.errorReason || error.message;
const settleResponse2 = {
success: false,
errorReason: errorReason2,
errorMessage: error.errorMessage || errorReason2,
payer: error.payer,
network: error.network,
transaction: error.transaction
};
const failure2 = {
...settleResponse2,
success: false,
errorReason: errorReason2,
headers: this.createSettlementHeaders(settleResponse2)
};
const response2 = await this.buildSettlementFailureResponse(failure2, transportContext);
return { ...failure2, response: response2 };
}
const errorReason = error instanceof Error ? error.message : "Settlement failed";
const settleResponse = {
success: false,
errorReason,
errorMessage: errorReason,
network: requirements.network,
transaction: ""
};
const failure = {
...settleResponse,
success: false,
errorReason,
headers: this.createSettlementHeaders(settleResponse)
};
const response = await this.buildSettlementFailureResponse(failure, transportContext);
return { ...failure, response };
}
}
/**
* 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 method = context.method || context.adapter.getMethod();
return this.getRouteConfig(context.path, method) !== void 0;
}
/**
* Build HTTPResponseInstructions for settlement failure.
* Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
*
* @param failure - Settlement failure result with headers
* @param transportContext - Optional HTTP transport context for the request
* @returns HTTP response instructions for the 402 settlement failure response
*/
async buildSettlementFailureResponse(failure, transportContext) {
const settlementHeaders = failure.headers;
const routeConfig = transportContext ? this.getRouteConfig(transportContext.request.path, transportContext.request.method) : void 0;
const customBody = routeConfig?.config.settlementFailedResponseBody ? await routeConfig.config.settlementFailedResponseBody(transportContext.request, failure) : void 0;
const contentType = customBody ? customBody.contentType : "application/json";
const body = customBody ? customBody.body : {};
return {
status: 402,
headers: {
"Content-Type": contentType,
...settlementHeaders
},
body,
isHtml: contentType.includes("text/html")
};
}
/**
* 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 pathPart = pattern.includes(" ") ? pattern.split(/\s+/)[1] : pattern;
if (pathPart && pathPart.includes("*") && config.extensions && "bazaar" in config.extensions) {
console.warn(
`[x402] Route "${pattern}": Wildcard (*) patterns with bazaar discovery extensions will auto-generate parameter names (var1, var2, ...). Consider using named parameters instead (e.g. /weather/:city) for better discovery metadata.`
);
}
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 and pattern, 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)
);
if (!matchingRoute) return void 0;
return { config: matchingRoute.config, pattern: matchingRoute.pattern };
}
/**
* 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/*", "/api/[id]", 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, "[^/]+").replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "[^/]+").replace(/\//g, "\\/")}$`,
"i"
);
return { verb: verb.toUpperCase(), regex, path };
}
/**
* 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);
const firstAccept = paymentRequired.accepts?.[0];
const decimals = firstAccept && "amount" in firstAccept ? this.ResourceServer.getAssetDecimalsForRequirements(firstAccept) : 6;
const safeDecimals = Math.min(Math.max(decimals, 0), 100);
const displayAmountText = parseFloat(displayAmount.toFixed(safeDecimals)).toString();
const assetLabel = typeof firstAccept?.extra?.name === "string" ? firstAccept.extra.name : firstAccept?.asset ? `...${firstAccept.asset.slice(-6)}` : "Token";
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> ${displayAmountText} ${assetLabel}</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.
* Uses the registered scheme's decimal precision for the asset, falling back to 6.
*
* @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) {
const decimals = this.ResourceServer.getAssetDecimalsForRequirements(firstReq);
return parseFloat(firstReq.amount) / 10 ** decimals;
}
}
return 0;
}
};
// src/http/httpFacilitatorClient.ts
var DEFAULT_FACILITATOR_URL = "https://x402.org/facilitator";
var GET_SUPPORTED_RETRIES = 3;
var GET_SUPPORTED_RETRY_DELAY_MS = 1e3;
var verifyResponseSchema = z.object({
isValid: z.boolean(),
invalidReason: z.string().nullish().transform((v) => v ?? void 0),
invalidMessage: z.string().nullish().transform((v) => v ?? void 0),
payer: z.string().nullish().transform((v) => v ?? void 0),
extensions: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0)
});
var settleResponseSchema = z.object({
success: z.boolean(),
errorReason: z.string().nullish().transform((v) => v ?? void 0),
errorMessage: z.string().nullish().transform((v) => v ?? void 0),
payer: z.string().nullish().transform((v) => v ?? void 0),
transaction: z.string(),
network: z.custom((value) => typeof value === "string"),
extensions: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0)
});
var supportedKindSchema = z.object({
x402Version: z.number(),
scheme: z.string(),
network: z.custom(
(value) => typeof value === "string"
),
extra: z.record(z.string(), z.unknown()).nullish().transform((v) => v ?? void 0)
});
var supportedResponseSchema = z.object({
kinds: z.array(supportedKindSchema),
extensions: z.array(z.string()).default([]),
signers: z.record(z.string(), z.array(z.string())).default({})
});
function responseExcerpt(text, limit = 200) {
const compact = text.trim().replace(/\s+/g, " ");
if (!compact) {
return "<empty response>";
}
if (compact.length <= limit) {
return compact;
}
return `${compact.slice(0, limit - 3)}...`;
}
async function parseSuccessResponse(response, schema, operation) {
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new FacilitatorResponseError(
`Facilitator ${operation} returned invalid JSON: ${responseExcerpt(text)}`
);
}
const parsed = schema.safeParse(data);
if (!parsed.success) {
throw new FacilitatorResponseError(
`Facilitator ${operation} returned invalid data: ${responseExcerpt(text)}`
);
}
return parsed.data;
}
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).replace(/\/+$/, "");
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,
redirect: "follow",
body: JSON.stringify({
x402Version: paymentPayload.x402Version,
paymentPayload: this.toJsonSafe(paymentPayload),
paymentRequirements: this.toJsonSafe(paymentRequirements)
})
});
if (!response.ok) {
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new Error(`Facilitator verify failed (${response.status}): ${responseExcerpt(text)}`);
}
if (typeof data === "object" && data !== null && "isValid" in data) {
throw new VerifyError(response.status, data);
}
throw new Error(
`Facilitator verify failed (${response.status}): ${responseExcerpt(JSON.stringify(data))}`
);
}
return parseSuccessResponse(response, verifyResponseSchema, "verify");
}
/**
* 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,
redirect: "follow",
body: JSON.stringify({
x402Version: paymentPayload.x402Version,
paymentPayload: this.toJsonSafe(paymentPayload),
paymentRequirements: this.toJsonSafe(paymentRequirements)
})
});
if (!response.ok) {
const text = await response.text();
let data;
try {
data = JSON.parse(text);
} catch {
throw new Error(`Facilitator settle failed (${response.status}): ${responseExcerpt(text)}`);
}
if (typeof data === "object" && data !== null && "success" in data) {
throw new SettleError(response.status, data);
}
throw new Error(
`Facilitator settle failed (${response.status}): ${responseExcerpt(JSON.stringify(data))}`
);
}
return parseSuccessResponse(response, settleResponseSchema, "settle");
}
/**
* Get supported payment kinds and extensions from the facilitator.
* Retries with exponential backoff on 429 rate limit errors.
*
* @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 };
}
let lastError = null;
for (let attempt = 0; attempt < GET_SUPPORTED_RETRIES; attempt++) {
const response = await fetch(`${this.url}/supported`, {
method: "GET",
headers,
redirect: "follow"
});
if (response.ok) {
return parseSuccessResponse(response, supportedResponseSchema, "supported");
}
const errorText = await response.text().catch(() => response.statusText);
lastError = new Error(
`Facilitator getSupported failed (${response.status}): ${responseExcerpt(errorText)}`
);
if (response.status === 429 && attempt < GET_SUPPORTED_RETRIES - 1) {
const delay = GET_SUPPORTED_RETRY_DELAY_MS * Math.pow(2, attempt);
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
throw lastError;
}
throw lastError ?? new Error("Facilitator getSupported failed after retries");
}
/**
* 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));
}
export {
SETTLEMENT_OVERRIDES_HEADER,
checkIfBazaarNeeded,
RouteConfigurationError,
x402HTTPResourceServer,
HTTPFacilitatorClient,
encodePaymentSignatureHeader,
decodePaymentSignatureHeader,
encodePaymentRequiredHeader,
decodePaymentRequiredHeader,
encodePaymentResponseHeader,
decodePaymentResponseHeader,
x402HTTPClient
};
//# sourceMappingURL=chunk-G3XJUKWR.mjs.map

Sorry, the diff of this file is too big to display

// 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;
}
};
var FacilitatorResponseError = class extends Error {
/**
* Creates a FacilitatorResponseError for malformed facilitator responses.
*
* @param message - The boundary error message
*/
constructor(message) {
super(message);
this.name = "FacilitatorResponseError";
}
};
function getFacilitatorResponseError(error) {
let current = error;
while (current instanceof Error) {
if (current instanceof FacilitatorResponseError) {
return current;
}
current = current.cause;
}
return null;
}
export {
VerifyError,
SettleError,
FacilitatorResponseError,
getFacilitatorResponseError
};
//# sourceMappingURL=chunk-JUGE6MAI.mjs.map
{"version":3,"sources":["../../src/types/facilitator.ts"],"sourcesContent":["import { PaymentPayload, PaymentRequirements } from \"./payments\";\nimport { Network } from \"./\";\n\nexport type VerifyRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type VerifyResponse = {\n isValid: boolean;\n invalidReason?: string;\n invalidMessage?: string;\n payer?: string;\n extensions?: Record<string, unknown>;\n};\n\nexport type SettleRequest = {\n x402Version: number;\n paymentPayload: PaymentPayload;\n paymentRequirements: PaymentRequirements;\n};\n\nexport type SettleResponse = {\n success: boolean;\n errorReason?: string;\n errorMessage?: string;\n payer?: string;\n transaction: string;\n network: Network;\n /** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */\n amount?: string;\n extensions?: Record<string, unknown>;\n};\n\nexport type SupportedKind = {\n x402Version: number;\n scheme: string;\n network: Network;\n extra?: Record<string, unknown>;\n};\n\nexport type SupportedResponse = {\n kinds: SupportedKind[];\n extensions: string[];\n signers: Record<string, string[]>; // CAIP family pattern → Signer addresses\n};\n\n/**\n * Error thrown when payment verification fails.\n */\nexport class VerifyError extends Error {\n readonly invalidReason?: string;\n readonly invalidMessage?: string;\n readonly payer?: string;\n readonly statusCode: number;\n\n /**\n * Creates a VerifyError from a failed verification response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The verify response containing error details\n */\n constructor(statusCode: number, response: VerifyResponse) {\n const reason = response.invalidReason || \"unknown reason\";\n const message = response.invalidMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"VerifyError\";\n this.statusCode = statusCode;\n this.invalidReason = response.invalidReason;\n this.invalidMessage = response.invalidMessage;\n this.payer = response.payer;\n }\n}\n\n/**\n * Error thrown when payment settlement fails.\n */\nexport class SettleError extends Error {\n readonly errorReason?: string;\n readonly errorMessage?: string;\n readonly payer?: string;\n readonly transaction: string;\n readonly network: Network;\n readonly statusCode: number;\n\n /**\n * Creates a SettleError from a failed settlement response.\n *\n * @param statusCode - HTTP status code from the facilitator\n * @param response - The settle response containing error details\n */\n constructor(statusCode: number, response: SettleResponse) {\n const reason = response.errorReason || \"unknown reason\";\n const message = response.errorMessage;\n super(message ? `${reason}: ${message}` : reason);\n this.name = \"SettleError\";\n this.statusCode = statusCode;\n this.errorReason = response.errorReason;\n this.errorMessage = response.errorMessage;\n this.payer = response.payer;\n this.transaction = response.transaction;\n this.network = response.network;\n }\n}\n\n/**\n * Error thrown when a facilitator returns malformed success payload data.\n */\nexport class FacilitatorResponseError extends Error {\n /**\n * Creates a FacilitatorResponseError for malformed facilitator responses.\n *\n * @param message - The boundary error message\n */\n constructor(message: string) {\n super(message);\n this.name = \"FacilitatorResponseError\";\n }\n}\n\n/**\n * Walks an error cause chain to find the first facilitator response error.\n *\n * @param error - The thrown value to inspect\n * @returns The nested facilitator response error, if present\n */\nexport function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null {\n let current = error;\n\n while (current instanceof Error) {\n if (current instanceof FacilitatorResponseError) {\n return current;\n }\n current = current.cause;\n }\n\n return null;\n}\n"],"mappings":";AAmDO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,iBAAiB;AACzC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,gBAAgB,SAAS;AAC9B,SAAK,iBAAiB,SAAS;AAC/B,SAAK,QAAQ,SAAS;AAAA,EACxB;AACF;AAKO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcrC,YAAY,YAAoB,UAA0B;AACxD,UAAM,SAAS,SAAS,eAAe;AACvC,UAAM,UAAU,SAAS;AACzB,UAAM,UAAU,GAAG,MAAM,KAAK,OAAO,KAAK,MAAM;AAChD,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,cAAc,SAAS;AAC5B,SAAK,eAAe,SAAS;AAC7B,SAAK,QAAQ,SAAS;AACtB,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,SAAS;AAAA,EAC1B;AACF;AAKO,IAAM,2BAAN,cAAuC,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAQO,SAAS,4BAA4B,OAAiD;AAC3F,MAAI,UAAU;AAEd,SAAO,mBAAmB,OAAO;AAC/B,QAAI,mBAAmB,0BAA0B;AAC/C,aAAO;AAAA,IACT;AACA,cAAU,QAAQ;AAAA,EACpB;AAEA,SAAO;AACT;","names":[]}
// src/schemas/index.ts
import { z } from "zod";
import { z as z2 } from "zod";
var NonEmptyString = z.string().min(1);
var Any = z.record(z.unknown());
var OptionalAny = z.record(z.unknown()).optional().nullable();
var NetworkSchemaV1 = NonEmptyString;
var NetworkSchemaV2 = z.string().min(3).refine((val) => val.includes(":"), {
message: "Network must be in CAIP-2 format (e.g., 'eip155:84532')"
});
var NetworkSchema = z.union([NetworkSchemaV1, NetworkSchemaV2]);
var ResourceInfoSchema = z.object({
url: NonEmptyString,
description: z.string().optional(),
mimeType: z.string().optional()
});
var PaymentRequirementsV1Schema = z.object({
scheme: NonEmptyString,
network: NetworkSchemaV1,
maxAmountRequired: NonEmptyString,
resource: NonEmptyString,
// URL string in V1
description: z.string(),
mimeType: z.string().optional(),
outputSchema: Any.optional().nullable(),
payTo: NonEmptyString,
maxTimeoutSeconds: z.number().positive(),
asset: NonEmptyString,
extra: OptionalAny
});
var PaymentRequiredV1Schema = z.object({
x402Version: z.literal(1),
error: z.string().optional(),
accepts: z.array(PaymentRequirementsV1Schema).min(1)
});
var PaymentPayloadV1Schema = z.object({
x402Version: z.literal(1),
scheme: NonEmptyString,
network: NetworkSchemaV1,
payload: Any
});
var PaymentRequirementsV2Schema = z.object({
scheme: NonEmptyString,
network: NetworkSchemaV2,
amount: NonEmptyString,
asset: NonEmptyString,
payTo: NonEmptyString,
maxTimeoutSeconds: z.number().positive(),
extra: OptionalAny
});
var PaymentRequiredV2Schema = z.object({
x402Version: z.literal(2),
error: z.string().optional(),
resource: ResourceInfoSchema,
accepts: z.array(PaymentRequirementsV2Schema).min(1),
extensions: OptionalAny
});
var PaymentPayloadV2Schema = z.object({
x402Version: z.literal(2),
resource: ResourceInfoSchema.optional(),
accepted: PaymentRequirementsV2Schema,
payload: Any,
extensions: OptionalAny
});
var PaymentRequirementsSchema = z.union([
PaymentRequirementsV1Schema,
PaymentRequirementsV2Schema
]);
var PaymentRequiredSchema = z.discriminatedUnion("x402Version", [
PaymentRequiredV1Schema,
PaymentRequiredV2Schema
]);
var PaymentPayloadSchema = z.discriminatedUnion("x402Version", [
PaymentPayloadV1Schema,
PaymentPayloadV2Schema
]);
function parsePaymentRequired(value) {
return PaymentRequiredSchema.safeParse(value);
}
function validatePaymentRequired(value) {
return PaymentRequiredSchema.parse(value);
}
function isPaymentRequired(value) {
return PaymentRequiredSchema.safeParse(value).success;
}
function parsePaymentRequirements(value) {
return PaymentRequirementsSchema.safeParse(value);
}
function validatePaymentRequirements(value) {
return PaymentRequirementsSchema.parse(value);
}
function isPaymentRequirements(value) {
return PaymentRequirementsSchema.safeParse(value).success;
}
function parsePaymentPayload(value) {
return PaymentPayloadSchema.safeParse(value);
}
function validatePaymentPayload(value) {
return PaymentPayloadSchema.parse(value);
}
function isPaymentPayload(value) {
return PaymentPayloadSchema.safeParse(value).success;
}
function isPaymentRequiredV1(value) {
return PaymentRequiredV1Schema.safeParse(value).success;
}
function isPaymentRequiredV2(value) {
return PaymentRequiredV2Schema.safeParse(value).success;
}
function isPaymentRequirementsV1(value) {
return PaymentRequirementsV1Schema.safeParse(value).success;
}
function isPaymentRequirementsV2(value) {
return PaymentRequirementsV2Schema.safeParse(value).success;
}
function isPaymentPayloadV1(value) {
return PaymentPayloadV1Schema.safeParse(value).success;
}
function isPaymentPayloadV2(value) {
return PaymentPayloadV2Schema.safeParse(value).success;
}
export {
NonEmptyString,
Any,
OptionalAny,
NetworkSchemaV1,
NetworkSchemaV2,
NetworkSchema,
ResourceInfoSchema,
PaymentRequirementsV1Schema,
PaymentRequiredV1Schema,
PaymentPayloadV1Schema,
PaymentRequirementsV2Schema,
PaymentRequiredV2Schema,
PaymentPayloadV2Schema,
PaymentRequirementsSchema,
PaymentRequiredSchema,
PaymentPayloadSchema,
parsePaymentRequired,
validatePaymentRequired,
isPaymentRequired,
parsePaymentRequirements,
validatePaymentRequirements,
isPaymentRequirements,
parsePaymentPayload,
validatePaymentPayload,
isPaymentPayload,
isPaymentRequiredV1,
isPaymentRequiredV2,
isPaymentRequirementsV1,
isPaymentRequirementsV2,
isPaymentPayloadV1,
isPaymentPayloadV2,
z2 as z
};
//# sourceMappingURL=chunk-KMQH4MQI.mjs.map
{"version":3,"sources":["../../src/schemas/index.ts"],"sourcesContent":["import { z } from \"zod\";\n\n// ============================================================================\n// Reusable Primitive Schemas\n// ============================================================================\n\n/**\n * Non-empty string schema - a string with at least one character.\n * Used for required string fields that cannot be empty.\n */\nexport const NonEmptyString = z.string().min(1);\nexport type NonEmptyString = z.infer<typeof NonEmptyString>;\n\n/**\n * Any record schema - an object with unknown keys and values.\n * Used for scheme-specific payloads and other extensible objects.\n */\nexport const Any = z.record(z.unknown());\nexport type Any = z.infer<typeof Any>;\n\n/**\n * Optional any record schema - an optional object with unknown keys and values.\n * Used for optional extension fields like `extra` and `extensions`.\n */\nexport const OptionalAny = z.record(z.unknown()).optional().nullable();\nexport type OptionalAny = z.infer<typeof OptionalAny>;\n\n// ============================================================================\n// Network Schemas\n// ============================================================================\n\n/**\n * Network identifier schema for V1 - loose validation.\n * V1 accepts any non-empty string for backwards compatibility.\n */\nexport const NetworkSchemaV1 = NonEmptyString;\nexport type NetworkV1 = z.infer<typeof NetworkSchemaV1>;\n\n/**\n * Network identifier schema for V2 - CAIP-2 format validation.\n * V2 requires minimum length of 3 and a colon separator (e.g., \"eip155:84532\", \"solana:devnet\").\n */\nexport const NetworkSchemaV2 = z\n .string()\n .min(3)\n .refine(val => val.includes(\":\"), {\n message: \"Network must be in CAIP-2 format (e.g., 'eip155:84532')\",\n });\nexport type NetworkV2 = z.infer<typeof NetworkSchemaV2>;\n\n/**\n * Union network schema - accepts either V1 or V2 format.\n */\nexport const NetworkSchema = z.union([NetworkSchemaV1, NetworkSchemaV2]);\nexport type Network = z.infer<typeof NetworkSchema>;\n\n// ============================================================================\n// Shared Schemas\n// ============================================================================\n\n/**\n * ResourceInfo schema for V2 - describes the protected resource.\n */\nexport const ResourceInfoSchema = z.object({\n url: NonEmptyString,\n description: z.string().optional(),\n mimeType: z.string().optional(),\n});\nexport type ResourceInfo = z.infer<typeof ResourceInfoSchema>;\n\n// ============================================================================\n// V1 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V1.\n * V1 includes resource info directly in the requirements object.\n */\nexport const PaymentRequirementsV1Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n maxAmountRequired: NonEmptyString,\n resource: NonEmptyString, // URL string in V1\n description: z.string(),\n mimeType: z.string().optional(),\n outputSchema: Any.optional().nullable(),\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n asset: NonEmptyString,\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV1 = z.infer<typeof PaymentRequirementsV1Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V1.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV1Schema = z.object({\n x402Version: z.literal(1),\n error: z.string().optional(),\n accepts: z.array(PaymentRequirementsV1Schema).min(1),\n});\nexport type PaymentRequiredV1 = z.infer<typeof PaymentRequiredV1Schema>;\n\n/**\n * PaymentPayload schema for V1.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV1Schema = z.object({\n x402Version: z.literal(1),\n scheme: NonEmptyString,\n network: NetworkSchemaV1,\n payload: Any,\n});\nexport type PaymentPayloadV1 = z.infer<typeof PaymentPayloadV1Schema>;\n\n// ============================================================================\n// V2 Schemas\n// ============================================================================\n\n/**\n * PaymentRequirements schema for V2.\n * V2 uses \"amount\" instead of \"maxAmountRequired\" and doesn't include resource info.\n */\nexport const PaymentRequirementsV2Schema = z.object({\n scheme: NonEmptyString,\n network: NetworkSchemaV2,\n amount: NonEmptyString,\n asset: NonEmptyString,\n payTo: NonEmptyString,\n maxTimeoutSeconds: z.number().positive(),\n extra: OptionalAny,\n});\nexport type PaymentRequirementsV2 = z.infer<typeof PaymentRequirementsV2Schema>;\n\n/**\n * PaymentRequired (402 response) schema for V2.\n * Contains payment requirements when a resource requires payment.\n */\nexport const PaymentRequiredV2Schema = z.object({\n x402Version: z.literal(2),\n error: z.string().optional(),\n resource: ResourceInfoSchema,\n accepts: z.array(PaymentRequirementsV2Schema).min(1),\n extensions: OptionalAny,\n});\nexport type PaymentRequiredV2 = z.infer<typeof PaymentRequiredV2Schema>;\n\n/**\n * PaymentPayload schema for V2.\n * Contains the payment data sent by the client.\n */\nexport const PaymentPayloadV2Schema = z.object({\n x402Version: z.literal(2),\n resource: ResourceInfoSchema.optional(),\n accepted: PaymentRequirementsV2Schema,\n payload: Any,\n extensions: OptionalAny,\n});\nexport type PaymentPayloadV2 = z.infer<typeof PaymentPayloadV2Schema>;\n\n// ============================================================================\n// Union Schemas (V1 | V2)\n// ============================================================================\n\n/**\n * PaymentRequirements union schema - accepts either V1 or V2 format.\n * Use this when you need to handle both versions.\n */\nexport const PaymentRequirementsSchema = z.union([\n PaymentRequirementsV1Schema,\n PaymentRequirementsV2Schema,\n]);\nexport type PaymentRequirements = z.infer<typeof PaymentRequirementsSchema>;\n\n/**\n * PaymentRequired union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentRequiredSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentRequiredV1Schema,\n PaymentRequiredV2Schema,\n]);\nexport type PaymentRequired = z.infer<typeof PaymentRequiredSchema>;\n\n/**\n * PaymentPayload union schema - accepts either V1 or V2 format.\n * Uses discriminated union on x402Version for efficient parsing.\n */\nexport const PaymentPayloadSchema = z.discriminatedUnion(\"x402Version\", [\n PaymentPayloadV1Schema,\n PaymentPayloadV2Schema,\n]);\nexport type PaymentPayload = z.infer<typeof PaymentPayloadSchema>;\n\n// ============================================================================\n// Validation Functions\n// ============================================================================\n\n/**\n * Validates a PaymentRequired object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequired(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequired> {\n return PaymentRequiredSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequired object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequired\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequired(value: unknown): PaymentRequired {\n return PaymentRequiredSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequired (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequired\n */\nexport function isPaymentRequired(value: unknown): value is PaymentRequired {\n return PaymentRequiredSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentRequirements object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentRequirements(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentRequirements> {\n return PaymentRequirementsSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentRequirements object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentRequirements\n * @throws ZodError if validation fails\n */\nexport function validatePaymentRequirements(value: unknown): PaymentRequirements {\n return PaymentRequirementsSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentRequirements (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirements\n */\nexport function isPaymentRequirements(value: unknown): value is PaymentRequirements {\n return PaymentRequirementsSchema.safeParse(value).success;\n}\n\n/**\n * Validates a PaymentPayload object (V1 or V2).\n *\n * @param value - The value to validate\n * @returns A result object with success status and data or error\n */\nexport function parsePaymentPayload(\n value: unknown,\n): z.SafeParseReturnType<unknown, PaymentPayload> {\n return PaymentPayloadSchema.safeParse(value);\n}\n\n/**\n * Validates a PaymentPayload object and throws on error.\n *\n * @param value - The value to validate\n * @returns The validated PaymentPayload\n * @throws ZodError if validation fails\n */\nexport function validatePaymentPayload(value: unknown): PaymentPayload {\n return PaymentPayloadSchema.parse(value);\n}\n\n/**\n * Type guard for PaymentPayload (V1 or V2).\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayload\n */\nexport function isPaymentPayload(value: unknown): value is PaymentPayload {\n return PaymentPayloadSchema.safeParse(value).success;\n}\n\n// ============================================================================\n// Version-Specific Type Guards\n// ============================================================================\n\n/**\n * Type guard for PaymentRequiredV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV1\n */\nexport function isPaymentRequiredV1(value: unknown): value is PaymentRequiredV1 {\n return PaymentRequiredV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequiredV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequiredV2\n */\nexport function isPaymentRequiredV2(value: unknown): value is PaymentRequiredV2 {\n return PaymentRequiredV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV1\n */\nexport function isPaymentRequirementsV1(value: unknown): value is PaymentRequirementsV1 {\n return PaymentRequirementsV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentRequirementsV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentRequirementsV2\n */\nexport function isPaymentRequirementsV2(value: unknown): value is PaymentRequirementsV2 {\n return PaymentRequirementsV2Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV1.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV1\n */\nexport function isPaymentPayloadV1(value: unknown): value is PaymentPayloadV1 {\n return PaymentPayloadV1Schema.safeParse(value).success;\n}\n\n/**\n * Type guard for PaymentPayloadV2.\n *\n * @param value - The value to check\n * @returns True if the value is a valid PaymentPayloadV2\n */\nexport function isPaymentPayloadV2(value: unknown): value is PaymentPayloadV2 {\n return PaymentPayloadV2Schema.safeParse(value).success;\n}\n\n// ============================================================================\n// Re-export zod for convenience\n// ============================================================================\n\nexport { z } from \"zod\";\n"],"mappings":"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","names":["z"]}
type PaymentRequirementsV1 = {
scheme: string;
network: Network;
maxAmountRequired: string;
resource: string;
description: string;
mimeType: string;
outputSchema: Record<string, unknown>;
payTo: string;
maxTimeoutSeconds: number;
asset: string;
extra: Record<string, unknown>;
};
type PaymentRequiredV1 = {
x402Version: 1;
error?: string;
accepts: PaymentRequirementsV1[];
};
type PaymentPayloadV1 = {
x402Version: 1;
scheme: string;
network: Network;
payload: Record<string, unknown>;
};
type VerifyRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleRequestV1 = {
x402Version: number;
paymentPayload: PaymentPayloadV1;
paymentRequirements: PaymentRequirementsV1;
};
type SettleResponseV1 = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
};
type SupportedResponseV1 = {
kinds: {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
}[];
};
/**
* Recursive readonly for hook contexts so accidental in-place mutation is visible at compile time.
* (Runtime mutation is still possible via other references; see extension enrich validation.)
*/
type DeepReadonly<T> = T extends (infer U)[] ? ReadonlyArray<DeepReadonly<U>> : T extends object ? {
readonly [K in keyof T]: DeepReadonly<T[K]>;
} : T;
interface FacilitatorConfig {
url?: string;
createAuthHeaders?: () => Promise<{
verify: Record<string, string>;
settle: Record<string, string>;
supported: Record<string, string>;
}>;
}
/**
* Interface for facilitator clients
* Can be implemented for HTTP-based or local facilitators
*/
interface FacilitatorClient {
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
}
/**
* HTTP-based client for interacting with x402 facilitator services
* Handles HTTP communication with facilitator endpoints
*/
declare class HTTPFacilitatorClient implements FacilitatorClient {
readonly url: string;
private readonly _createAuthHeaders?;
/**
* Creates a new HTTPFacilitatorClient instance.
*
* @param config - Configuration options for the facilitator client
*/
constructor(config?: FacilitatorConfig);
/**
* Verify a payment with the facilitator
*
* @param paymentPayload - The payment to verify
* @param paymentRequirements - The requirements to verify against
* @returns Verification response
*/
verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<VerifyResponse>;
/**
* Settle a payment with the facilitator
*
* @param paymentPayload - The payment to settle
* @param paymentRequirements - The requirements for settlement
* @returns Settlement response
*/
settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise<SettleResponse>;
/**
* Get supported payment kinds and extensions from the facilitator.
* Retries with exponential backoff on 429 rate limit errors.
*
* @returns Supported payment kinds and extensions
*/
getSupported(): Promise<SupportedResponse>;
/**
* 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
*/
createAuthHeaders(path: string): Promise<{
headers: Record<string, string>;
}>;
/**
* 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
*/
private toJsonSafe;
}
/**
* Configuration for a protected resource
* Only contains payment-specific configuration, not resource metadata
*/
interface ResourceConfig {
scheme: string;
/**
* Payment recipient. Use a **vacant** value (`""` or whitespace-only) when an extension must
* fill `payTo` during `enrichPaymentRequiredResponse`; non-vacant values are **immutable** there
* so extensions cannot redirect funds to an arbitrary address.
*/
payTo: string;
price: Price;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Context for `enrichPaymentRequiredResponse`. Extensions may merge extension payload via the
* return value. In-place edits to `paymentRequiredResponse.accepts` are **allowlisted** only
* (see {@link assertAcceptsAllowlistedAfterExtensionEnrich}): `scheme`, `network`, and
* `maxTimeoutSeconds` are immutable; `payTo`, `amount`, and `asset` may change only when the
* baseline value was vacant; `extra` may add keys but must not change or remove baseline keys.
*/
interface PaymentRequiredContext {
requirements: PaymentRequirements[];
resourceInfo: ResourceInfo;
error?: string;
paymentRequiredResponse: PaymentRequired;
transportContext?: unknown;
}
/**
* Verify / settle lifecycle hook context: treat as **read-only** for core protocol fields.
* Control flow uses **abort** / **recover** return values only, not in-place mutation.
*/
interface VerifyContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface VerifyResultContext extends VerifyContext {
result: DeepReadonly<VerifyResponse>;
}
interface VerifyFailureContext extends VerifyContext {
error: Error;
}
interface SettleContext {
paymentPayload: DeepReadonly<PaymentPayload>;
requirements: DeepReadonly<PaymentRequirements>;
declaredExtensions: DeepReadonly<Record<string, unknown>>;
transportContext?: unknown;
}
interface SettleResultContext extends SettleContext {
result: DeepReadonly<SettleResponse>;
}
interface SettleFailureContext extends SettleContext {
error: Error;
}
type BeforeVerifyHook = (context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
type AfterVerifyHook = (context: VerifyResultContext) => Promise<void>;
type OnVerifyFailureHook = (context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
type BeforeSettleHook = (context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
type AfterSettleHook = (context: SettleResultContext) => Promise<void>;
type OnSettleFailureHook = (context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
/**
* Optional overrides for settlement parameters.
* Used to support partial settlement (e.g., upto scheme billing by actual usage).
*
* Note: Overriding the amount to a value different from the agreed-upon
* `PaymentRequirements.amount` is only valid in schemes that explicitly support
* partial settlement, such as the `upto` scheme. Using this with standard
* x402 schemes (e.g., `exact`) will likely cause settlement verification to fail.
*/
interface SettlementOverrides {
/**
* Amount to settle. Supports three formats:
*
* - **Raw atomic units** — e.g., `"1000"` settles exactly 1000 atomic units.
* - **Percent** — e.g., `"50%"` settles 50% of `PaymentRequirements.amount`.
* Supports up to two decimal places (e.g., `"33.33%"`). The result is floored
* to the nearest atomic unit.
* - **Dollar price** — e.g., `"$0.05"` converts a USD-denominated price to
* atomic units. Decimals are determined from the registered scheme's
* `getAssetDecimals` method, falling back to 6 (standard for USDC stablecoins).
* The result is rounded to the nearest atomic unit.
*
* The resolved amount must be <= the authorized maximum in `PaymentRequirements`.
*
* Note: Setting this to an amount other than `PaymentRequirements.amount` is
* only valid in schemes that support partial settlement, such as `upto`.
*/
amount?: string;
}
/**
* Core x402 protocol server for resource protection
* Transport-agnostic implementation of the x402 payment protocol
*/
declare class x402ResourceServer {
private facilitatorClients;
private registeredServerSchemes;
private supportedResponsesMap;
private facilitatorClientsMap;
private registeredExtensions;
private extensionHookAdapters;
private beforeVerifyHooks;
private afterVerifyHooks;
private onVerifyFailureHooks;
private beforeSettleHooks;
private afterSettleHooks;
private onSettleFailureHooks;
/**
* Creates a new x402ResourceServer instance.
*
* @param facilitatorClients - Optional facilitator client(s) for payment processing
*/
constructor(facilitatorClients?: FacilitatorClient | FacilitatorClient[]);
/**
* Register a scheme/network server implementation.
*
* @param network - The network identifier
* @param server - The scheme/network server implementation
* @returns The x402ResourceServer instance for chaining
*/
register(network: Network, server: SchemeNetworkServer): x402ResourceServer;
/**
* Check if a scheme is registered for a given network.
*
* @param network - The network identifier
* @param scheme - The payment scheme name
* @returns True if the scheme is registered for the network, false otherwise
*/
hasRegisteredScheme(network: Network, scheme: string): boolean;
/**
* Returns the decimal precision for the asset specified in the given payment requirements.
* Looks up the registered scheme for the network and delegates to its getAssetDecimals
* method if available. Falls back to 6 (standard for USDC stablecoins) when the scheme
* does not implement getAssetDecimals or is not registered.
*
* @param requirements - The payment requirements containing scheme, network, and asset
* @returns The number of decimal places for the asset
*/
getAssetDecimalsForRequirements(requirements: PaymentRequirements): number;
/**
* Registers a resource server extension (enrichment and optional verify/settle hooks).
* Re-registering the same key overwrites; omitting `hooks` removes adapter handles for that key.
*
* @param extension - Extension definition including `key` and optional `hooks`
* @returns This server instance for chaining
*/
registerExtension(extension: ResourceServerExtension): this;
/**
* Check if an extension is registered.
*
* @param key - The extension key
* @returns True if the extension is registered
*/
hasExtension(key: string): boolean;
/**
* Get all registered extensions.
*
* @returns Array of registered extensions
*/
getExtensions(): ResourceServerExtension[];
/**
* Enriches declared extensions using registered extension hooks.
*
* @param declaredExtensions - Extensions declared on the route
* @param transportContext - Transport-specific context (HTTP, A2A, MCP, etc.)
* @returns Enriched extensions map
*/
enrichExtensions(declaredExtensions: Record<string, unknown>, transportContext: unknown): Record<string, unknown>;
/**
* Register a hook to execute before payment verification.
* Can abort verification by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeVerify(hook: BeforeVerifyHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment verification.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterVerify(hook: AfterVerifyHook): x402ResourceServer;
/**
* Register a hook to execute when payment verification fails.
* Can recover from failure by returning { recovered: true, result: VerifyResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onVerifyFailure(hook: OnVerifyFailureHook): x402ResourceServer;
/**
* Register a hook to execute before payment settlement.
* Can abort settlement by returning { abort: true, reason: string }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onBeforeSettle(hook: BeforeSettleHook): x402ResourceServer;
/**
* Register a hook to execute after successful payment settlement.
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onAfterSettle(hook: AfterSettleHook): x402ResourceServer;
/**
* Register a hook to execute when payment settlement fails.
* Can recover from failure by returning { recovered: true, result: SettleResponse }
*
* @param hook - The hook function to register
* @returns The x402ResourceServer instance for chaining
*/
onSettleFailure(hook: OnSettleFailureHook): x402ResourceServer;
/**
* Initialize by fetching supported kinds from all facilitators
* Creates mappings for supported responses and facilitator clients
* Earlier facilitators in the array get precedence
*/
initialize(): Promise<void>;
/**
* Get supported kind for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The supported kind or undefined if not found
*/
getSupportedKind(x402Version: number, network: Network, scheme: string): SupportedKind | undefined;
/**
* Get facilitator extensions for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator extensions or empty array if not found
*/
getFacilitatorExtensions(x402Version: number, network: Network, scheme: string): string[];
/**
* Build payment requirements for a protected resource
*
* @param resourceConfig - Configuration for the protected resource
* @returns Array of payment requirements
*/
buildPaymentRequirements(resourceConfig: ResourceConfig): Promise<PaymentRequirements[]>;
/**
* Build payment requirements from multiple payment options
* This method handles resolving dynamic payTo/price functions and builds requirements for each option
*
* @param paymentOptions - Array of payment options to convert
* @param context - HTTP request context for resolving dynamic functions
* @returns Array of payment requirements (one per option)
*/
buildPaymentRequirementsFromOptions<TContext = unknown>(paymentOptions: Array<{
scheme: string;
payTo: string | ((context: TContext) => string | Promise<string>);
price: Price | ((context: TContext) => Price | Promise<Price>);
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}>, context: TContext): Promise<PaymentRequirements[]>;
/**
* Create a payment required response
*
* @param requirements - Payment requirements
* @param resourceInfo - Resource information
* @param error - Error message
* @param extensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request, MCP tool context)
* @returns Payment required response object
*/
createPaymentRequiredResponse(requirements: PaymentRequirements[], resourceInfo: ResourceInfo, error?: string, extensions?: Record<string, unknown>, transportContext?: unknown): Promise<PaymentRequired>;
/**
* Verifies a payment against requirements, running manual and in-use extension hooks.
*
* @param paymentPayload - Signed payment payload from the client
* @param requirements - Requirements matched to the payload
* @param declaredExtensions - Optional per-extension declarations for the request
* @param transportContext - Optional transport-specific context (e.g. HTTP, MCP)
* @returns Facilitator verify outcome, or abort/recovery as driven by hooks
*/
verifyPayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown): Promise<VerifyResponse>;
/**
* Settle a verified payment
*
* @param paymentPayload - The payment payload to settle
* @param requirements - The payment requirements
* @param declaredExtensions - Optional declared extensions (for per-key enrichment)
* @param transportContext - Optional transport-specific context (e.g., HTTP request/response, MCP tool context)
* @param settlementOverrides - Optional overrides for settlement parameters (e.g., partial settlement amount)
* @returns Settlement response
*/
settlePayment(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: unknown, settlementOverrides?: SettlementOverrides): Promise<SettleResponse>;
/**
* Find matching payment requirements for a payment
*
* @param availableRequirements - Array of available payment requirements
* @param paymentPayload - The payment payload
* @returns Matching payment requirements or undefined
*/
findMatchingRequirements(availableRequirements: PaymentRequirements[], paymentPayload: PaymentPayload): PaymentRequirements | undefined;
/**
* Process a payment request
*
* @param paymentPayload - Optional payment payload if provided
* @param resourceConfig - Configuration for the protected resource
* @param resourceInfo - Information about the resource being accessed
* @param extensions - Optional extensions to include in the response
* @param transportContext - Optional transport context for extension hooks and enrichment
* @returns Processing result
*/
processPaymentRequest(paymentPayload: PaymentPayload | null, resourceConfig: ResourceConfig, resourceInfo: ResourceInfo, extensions?: Record<string, unknown>, transportContext?: unknown): Promise<{
success: boolean;
requiresPayment?: PaymentRequired;
verificationResult?: VerifyResponse;
settlementResult?: SettleResponse;
error?: string;
}>;
/**
* Logs a warning when a manual or extension adapter lifecycle hook throws.
*
* @param phase - Lifecycle phase name (e.g. `beforeVerify`)
* @param label - Hook source label from {@link getLabeledHooks} (manual index or extension key)
* @param error - Thrown value or rejection reason
*/
private warnResourceServerHookFailure;
/**
* Logs a warning when a registered extension enrichment hook throws.
*
* @param extensionKey - Registered extension identifier
* @param hookName - Hook method name (e.g. `enrichDeclaration`)
* @param error - Thrown value or rejection reason
*/
private warnExtensionHookFailure;
/**
* Manual hooks first, then extension adapters for keys in `extensionKeysInUse`.
* Each entry carries a stable label for logging when a hook throws.
*
* @param phase - Hook slot (e.g. `beforeVerify`)
* @param extensionKeysInUse - Declared extension keys for this request
* @returns Hooks in invocation order with source labels
*/
private getLabeledHooks;
/**
* Get facilitator client for a specific version, network, and scheme
*
* @param x402Version - The x402 version
* @param network - The network identifier
* @param scheme - The payment scheme
* @returns The facilitator client or undefined if not found
*/
private getFacilitatorClient;
}
interface FacilitatorExtension {
key: string;
}
/**
* Per-extension verify/settle hooks. Contexts are **read-only** for core protocol fields; use
* **abort** / **recover** return values instead of mutating `paymentPayload`, `requirements`, etc.
*/
interface ResourceServerExtensionHooks {
onBeforeVerify?: (declaration: unknown, context: VerifyContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
onAfterVerify?: (declaration: unknown, context: VerifyResultContext) => Promise<void>;
onVerifyFailure?: (declaration: unknown, context: VerifyFailureContext) => Promise<void | {
recovered: true;
result: VerifyResponse;
}>;
onBeforeSettle?: (declaration: unknown, context: SettleContext) => Promise<void | {
abort: true;
reason: string;
message?: string;
}>;
onAfterSettle?: (declaration: unknown, context: SettleResultContext) => Promise<void>;
onSettleFailure?: (declaration: unknown, context: SettleFailureContext) => Promise<void | {
recovered: true;
result: SettleResponse;
}>;
}
interface ResourceServerExtension {
key: string;
enrichDeclaration?: (declaration: unknown, transportContext: unknown) => unknown;
/**
* Return value merges into `extensions[key]`. In-place edits to `accepts` are allowlisted only
* (see server `assertAcceptsAllowlistedAfterExtensionEnrich`): vacant `payTo` / `amount` / `asset`
* may be filled; locked values and `scheme` / `network` / `maxTimeoutSeconds` / baseline `extra`
* entries are immutable.
*/
enrichPaymentRequiredResponse?: (declaration: unknown, context: PaymentRequiredContext) => Promise<unknown>;
/**
* Return value merges into `settleResult.extensions[key]`. Facilitator fields (`success`,
* `transaction`, `network`, etc.) must not be changed; only `extensions` is merged from the hook.
*/
enrichSettlementResponse?: (declaration: unknown, context: SettleResultContext) => Promise<unknown>;
/** Installed on `registerExtension`; runs only when `declaredExtensions[key]` is defined. */
hooks?: ResourceServerExtensionHooks;
}
type Network = `${string}:${string}`;
type Money = string | number;
type AssetAmount = {
asset: string;
amount: string;
extra?: Record<string, unknown>;
};
type Price = Money | AssetAmount;
interface ResourceInfo {
url: string;
description?: string;
mimeType?: string;
}
type PaymentRequirements = {
scheme: string;
network: Network;
asset: string;
amount: string;
payTo: string;
maxTimeoutSeconds: number;
extra: Record<string, unknown>;
};
type PaymentRequired = {
x402Version: number;
error?: string;
resource: ResourceInfo;
accepts: PaymentRequirements[];
extensions?: Record<string, unknown>;
};
type PaymentPayload = {
x402Version: number;
resource?: ResourceInfo;
accepted: PaymentRequirements;
payload: Record<string, unknown>;
extensions?: Record<string, unknown>;
};
type VerifyRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type VerifyResponse = {
isValid: boolean;
invalidReason?: string;
invalidMessage?: string;
payer?: string;
extensions?: Record<string, unknown>;
};
type SettleRequest = {
x402Version: number;
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
};
type SettleResponse = {
success: boolean;
errorReason?: string;
errorMessage?: string;
payer?: string;
transaction: string;
network: Network;
/** Actual amount settled in atomic token units. Present for schemes like `upto` where settlement amount may differ from the authorized maximum. */
amount?: string;
extensions?: Record<string, unknown>;
};
type SupportedKind = {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
};
type SupportedResponse = {
kinds: SupportedKind[];
extensions: string[];
signers: Record<string, string[]>;
};
/**
* Error thrown when payment verification fails.
*/
declare class VerifyError extends Error {
readonly invalidReason?: string;
readonly invalidMessage?: string;
readonly payer?: string;
readonly statusCode: number;
/**
* 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: number, response: VerifyResponse);
}
/**
* Error thrown when payment settlement fails.
*/
declare class SettleError extends Error {
readonly errorReason?: string;
readonly errorMessage?: string;
readonly payer?: string;
readonly transaction: string;
readonly network: Network;
readonly statusCode: number;
/**
* 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: number, response: SettleResponse);
}
/**
* Error thrown when a facilitator returns malformed success payload data.
*/
declare class FacilitatorResponseError extends Error {
/**
* Creates a FacilitatorResponseError for malformed facilitator responses.
*
* @param message - The boundary error message
*/
constructor(message: string);
}
/**
* Walks an error cause chain to find the first facilitator response error.
*
* @param error - The thrown value to inspect
* @returns The nested facilitator response error, if present
*/
declare function getFacilitatorResponseError(error: unknown): FacilitatorResponseError | null;
/**
* Money parser function that converts a numeric amount to an AssetAmount
* Receives the amount as a decimal number (e.g., 1.50 for $1.50)
* Returns null to indicate "cannot handle this amount", causing fallback to next parser
* Always returns a Promise for consistency - use async/await
*
* @param amount - The decimal amount (e.g., 1.50)
* @param network - The network identifier for context
* @returns AssetAmount or null to try next parser
*/
type MoneyParser = (amount: number, network: Network) => Promise<AssetAmount | null>;
/**
* Result of createPaymentPayload - the core payload fields.
* Contains the x402 version, scheme-specific payload data, and optional extension data.
* Schemes may return extensions (e.g., EIP-2612 gas sponsoring) that get merged
* with server-declared extensions in the final PaymentPayload.
*/
type PaymentPayloadResult = Pick<PaymentPayload, "x402Version" | "payload"> & {
extensions?: Record<string, unknown>;
};
/**
* Context passed to scheme's createPaymentPayload for extensions awareness.
* Contains the server-declared extensions from PaymentRequired so the scheme
* can check which extensions are advertised and respond accordingly.
*/
interface PaymentPayloadContext {
extensions?: Record<string, unknown>;
}
interface SchemeNetworkClient {
readonly scheme: string;
createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements, context?: PaymentPayloadContext): Promise<PaymentPayloadResult>;
}
/**
* Context passed to SchemeNetworkFacilitator.verify/settle, providing
* access to registered facilitator extensions. Mechanism implementations
* use this to retrieve extension-provided capabilities (e.g., a batch signer).
*/
interface FacilitatorContext {
getExtension<T extends FacilitatorExtension = FacilitatorExtension>(key: string): T | undefined;
}
interface SchemeNetworkFacilitator {
readonly scheme: string;
/**
* CAIP family pattern that this facilitator supports.
* Used to group signers by blockchain family in the supported response.
*
* @example
* // EVM facilitators
* readonly caipFamily = "eip155:*";
*
* @example
* // SVM facilitators
* readonly caipFamily = "solana:*";
*/
readonly caipFamily: string;
/**
* Get mechanism-specific extra data needed for the supported kinds endpoint.
* This method is called when building the facilitator's supported response.
*
* @param network - The network identifier for context
* @returns Extra data object or undefined if no extra data is needed
*
* @example
* // EVM schemes return undefined (no extra data needed)
* getExtra(network: Network): undefined {
* return undefined;
* }
*
* @example
* // SVM schemes return feePayer address
* getExtra(network: Network): Record<string, unknown> | undefined {
* return { feePayer: this.signer.address };
* }
*/
getExtra(network: Network): Record<string, unknown> | undefined;
/**
* Get signer addresses used by this facilitator for a given network.
* These are included in the supported response to help clients understand
* which addresses might sign/pay for transactions.
*
* Supports multiple addresses for load balancing, key rotation, and high availability.
*
* @param network - The network identifier
* @returns Array of signer addresses (wallet addresses, fee payer addresses, etc.)
*
* @example
* // EVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*
* @example
* // SVM facilitator
* getSigners(network: string): string[] {
* return [...this.signer.getAddresses()];
* }
*/
getSigners(network: string): string[];
verify(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<VerifyResponse>;
settle(payload: PaymentPayload, requirements: PaymentRequirements, context?: FacilitatorContext): Promise<SettleResponse>;
}
interface SchemeNetworkServer {
readonly scheme: string;
/**
* Convert a user-friendly price to the scheme's specific amount and asset format
* Always returns a Promise for consistency
*
* @param price - User-friendly price (e.g., "$0.10", "0.10", { amount: "100000", asset: "USDC" })
* @param network - The network identifier for context
* @returns Promise that resolves to the converted amount, asset identifier, and any extra metadata
*
* @example
* // For EVM networks with USDC:
* await parsePrice("$0.10", "eip155:8453") => { amount: "100000", asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" }
*
* // For custom schemes:
* await parsePrice("10 points", "custom:network") => { amount: "10", asset: "points" }
*/
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
/**
* Optional: Return the decimal precision of the asset for a given network.
* Used by `resolveSettlementOverrideAmount` to convert dollar-format overrides to atomic units.
* Defaults to 6 when not implemented.
*
* @param asset - The asset address or symbol
* @param network - The network identifier
* @returns Number of decimal places for the asset
*/
getAssetDecimals?(asset: string, network: Network): number;
/**
* Build payment requirements for this scheme/network combination
*
* @param paymentRequirements - Base payment requirements with amount/asset already set
* @param supportedKind - The supported kind from facilitator's /supported endpoint
* @param supportedKind.x402Version - The x402 version
* @param supportedKind.scheme - The payment scheme
* @param supportedKind.network - The network identifier
* @param supportedKind.extra - Optional extra metadata
* @param facilitatorExtensions - Extensions supported by the facilitator
* @returns Enhanced payment requirements ready to be sent to clients
*/
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: {
x402Version: number;
scheme: string;
network: Network;
extra?: Record<string, unknown>;
}, facilitatorExtensions: string[]): Promise<PaymentRequirements>;
}
export { type DeepReadonly as $, type AfterVerifyHook as A, type BeforeVerifyHook as B, type SettleResponseV1 as C, type SupportedResponseV1 as D, type AssetAmount as E, type FacilitatorExtension as F, type VerifyRequest as G, HTTPFacilitatorClient as H, type SettleRequest as I, type SupportedResponse as J, VerifyError as K, SettleError as L, type Money as M, type Network as N, type OnVerifyFailureHook as O, type PaymentPayload as P, type ResourceInfo as Q, type ResourceConfig as R, type SettleResponse as S, type SchemeNetworkServer as T, type MoneyParser as U, type VerifyResponse as V, type PaymentPayloadResult as W, type PaymentPayloadContext as X, type FacilitatorContext as Y, type ResourceServerExtension as Z, type ResourceServerExtensionHooks as _, type PaymentRequirements as a, type SchemeNetworkFacilitator as b, type PaymentRequired as c, type FacilitatorClient as d, type FacilitatorConfig as e, FacilitatorResponseError as f, getFacilitatorResponseError as g, type PaymentRequiredContext as h, type VerifyContext as i, type VerifyResultContext as j, type VerifyFailureContext as k, type SettleContext as l, type SettleResultContext as m, type SettleFailureContext as n, type SettlementOverrides as o, type BeforeSettleHook as p, type AfterSettleHook as q, type OnSettleFailureHook as r, type Price as s, type SchemeNetworkClient as t, type PaymentRequirementsV1 as u, type PaymentRequiredV1 as v, type PaymentPayloadV1 as w, x402ResourceServer as x, type VerifyRequestV1 as y, type SettleRequestV1 as z };
import { x as x402ResourceServer, s as Price, N as Network, S as SettleResponse, c as PaymentRequired, P as PaymentPayload, a as PaymentRequirements, o as SettlementOverrides } from './mechanisms-C6YmSXgy.mjs';
declare const SETTLEMENT_OVERRIDES_HEADER = "Settlement-Overrides";
/**
* Framework-agnostic HTTP adapter interface
* Implementations provide framework-specific HTTP operations
*/
interface HTTPAdapter {
getHeader(name: string): string | undefined;
getMethod(): string;
getPath(): string;
getUrl(): string;
getAcceptHeader(): string;
getUserAgent(): string;
/**
* Get query parameters from the request URL
*
* @returns Record of query parameter key-value pairs
*/
getQueryParams?(): Record<string, string | string[]>;
/**
* Get a specific query parameter by name
*
* @param name - The query parameter name
* @returns The query parameter value(s) or undefined
*/
getQueryParam?(name: string): string | string[] | undefined;
/**
* Get the parsed request body
* Framework adapters should parse JSON/form data appropriately
*
* @returns The parsed request body
*/
getBody?(): unknown;
}
/**
* Paywall configuration for HTML responses
*/
interface PaywallConfig {
appName?: string;
appLogo?: string;
sessionTokenEndpoint?: string;
currentUrl?: string;
testnet?: boolean;
}
/**
* Paywall provider interface for generating HTML
*/
interface PaywallProvider {
generateHtml(paymentRequired: PaymentRequired, config?: PaywallConfig): string;
}
/**
* Dynamic payTo function that receives HTTP request context
*/
type DynamicPayTo = (context: HTTPRequestContext) => string | Promise<string>;
/**
* Dynamic price function that receives HTTP request context
*/
type DynamicPrice = (context: HTTPRequestContext) => Price | Promise<Price>;
/**
* Result of response body callbacks containing content type and body.
*/
interface HTTPResponseBody {
/**
* The content type for the response (e.g., 'application/json', 'text/plain').
*/
contentType: string;
/**
* The response body to include in the 402 response.
*/
body: unknown;
}
/**
* Dynamic function to generate a custom response for unpaid requests.
* Receives the HTTP request context and returns the content type and body to include in the 402 response.
*/
type UnpaidResponseBody = (context: HTTPRequestContext) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* Dynamic function to generate a custom response for settlement failures.
* Receives the HTTP request context and settle failure result, returns the content type and body.
*/
type SettlementFailedResponseBody = (context: HTTPRequestContext, settleResult: Omit<ProcessSettleFailureResponse, "response">) => HTTPResponseBody | Promise<HTTPResponseBody>;
/**
* A single payment option for a route
* Represents one way a client can pay for access to the resource
*/
interface PaymentOption {
scheme: string;
payTo: string | DynamicPayTo;
price: Price | DynamicPrice;
network: Network;
maxTimeoutSeconds?: number;
extra?: Record<string, unknown>;
}
/**
* Route configuration for HTTP endpoints
*
* The 'accepts' field defines payment options for the route.
* Can be a single PaymentOption or an array of PaymentOptions for multiple payment methods.
*/
interface RouteConfig {
accepts: PaymentOption | PaymentOption[];
resource?: string;
description?: string;
mimeType?: string;
customPaywallHtml?: string;
/**
* Optional callback to generate a custom response for unpaid API requests.
* This allows servers to return preview data, error messages, or other content
* when a request lacks payment.
*
* For browser requests (Accept: text/html), the paywall HTML takes precedence.
* This callback is only used for API clients.
*
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @returns An object containing both contentType and body for the 402 response
*/
unpaidResponseBody?: UnpaidResponseBody;
/**
* Optional callback to generate a custom response for settlement failures.
* If not provided, defaults to { contentType: 'application/json', body: {} }.
*
* @param context - The HTTP request context
* @param settleResult - The settlement failure result
* @returns An object containing both contentType and body for the 402 response
*/
settlementFailedResponseBody?: SettlementFailedResponseBody;
extensions?: Record<string, unknown>;
}
/**
* Routes configuration - maps path patterns to route configs
*/
type RoutesConfig = Record<string, RouteConfig> | RouteConfig;
/**
* Check if any routes in the configuration declare bazaar extensions.
*
* @param routes - Route configuration
* @returns True if any route has extensions.bazaar defined
*/
declare function checkIfBazaarNeeded(routes: RoutesConfig): boolean;
/**
* Hook that runs on every request to a protected route, before payment processing.
* Can grant access without payment, deny the request, or continue to payment flow.
*
* @returns
* - `void` - Continue to payment processing (default behavior)
* - `{ grantAccess: true }` - Grant access without requiring payment
* - `{ abort: true; reason: string }` - Deny the request (returns 403)
*/
type ProtectedRequestHook = (context: HTTPRequestContext, routeConfig: RouteConfig) => Promise<void | {
grantAccess: true;
} | {
abort: true;
reason: string;
}>;
/**
* Compiled route for efficient matching
*/
interface CompiledRoute {
verb: string;
regex: RegExp;
config: RouteConfig;
pattern: string;
}
/**
* HTTP request context that encapsulates all request data
*/
interface HTTPRequestContext {
adapter: HTTPAdapter;
path: string;
method: string;
paymentHeader?: string;
routePattern?: string;
}
/**
* HTTP transport context contains both request context and optional response data.
*/
interface HTTPTransportContext {
/** The HTTP request context */
request: HTTPRequestContext;
/** The response body buffer */
responseBody?: Buffer;
/** Response headers set by the route handler (used for settlement overrides) */
responseHeaders?: Record<string, string>;
}
/**
* HTTP response instructions for the framework middleware
*/
interface HTTPResponseInstructions {
status: number;
headers: Record<string, string>;
body?: unknown;
isHtml?: boolean;
}
/**
* Result of processing an HTTP request for payment
*/
type HTTPProcessResult = {
type: "no-payment-required";
} | {
type: "payment-verified";
paymentPayload: PaymentPayload;
paymentRequirements: PaymentRequirements;
declaredExtensions?: Record<string, unknown>;
} | {
type: "payment-error";
response: HTTPResponseInstructions;
};
/**
* Result of processSettlement
*/
type ProcessSettleSuccessResponse = SettleResponse & {
success: true;
headers: Record<string, string>;
requirements: PaymentRequirements;
};
type ProcessSettleFailureResponse = SettleResponse & {
success: false;
errorReason: string;
errorMessage?: string;
headers: Record<string, string>;
response: HTTPResponseInstructions;
};
type ProcessSettleResultResponse = ProcessSettleSuccessResponse | ProcessSettleFailureResponse;
/**
* Represents a validation error for a specific route's payment configuration.
*/
interface RouteValidationError {
/** The route pattern (e.g., "GET /api/weather") */
routePattern: string;
/** The payment scheme that failed validation */
scheme: string;
/** The network that failed validation */
network: Network;
/** The type of validation failure */
reason: "missing_scheme" | "missing_facilitator";
/** Human-readable error message */
message: string;
}
/**
* Error thrown when route configuration validation fails.
*/
declare class RouteConfigurationError extends Error {
/** The validation errors that caused this exception */
readonly errors: RouteValidationError[];
/**
* Creates a new RouteConfigurationError with the given validation errors.
*
* @param errors - The validation errors that caused this exception.
*/
constructor(errors: RouteValidationError[]);
}
/**
* HTTP-enhanced x402 resource server
* Provides framework-agnostic HTTP protocol handling
*/
declare class x402HTTPResourceServer {
private ResourceServer;
private compiledRoutes;
private routesConfig;
private paywallProvider?;
private protectedRequestHooks;
/**
* Creates a new x402HTTPResourceServer instance.
*
* @param ResourceServer - The core x402ResourceServer instance to use
* @param routes - Route configuration for payment-protected endpoints
*/
constructor(ResourceServer: x402ResourceServer, routes: RoutesConfig);
/**
* Get the underlying x402ResourceServer instance.
*
* @returns The underlying x402ResourceServer instance
*/
get server(): x402ResourceServer;
/**
* Get the routes configuration.
*
* @returns The routes configuration
*/
get routes(): 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();
* ```
*/
initialize(): Promise<void>;
/**
* Register a custom paywall provider for generating HTML
*
* @param provider - PaywallProvider instance
* @returns This service instance for chaining
*/
registerPaywallProvider(provider: PaywallProvider): 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: ProtectedRequestHook): 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
*/
processHTTPRequest(context: HTTPRequestContext, paywallConfig?: PaywallConfig): Promise<HTTPProcessResult>;
/**
* 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)
* @param transportContext - Optional HTTP transport context
* @param settlementOverrides - Optional settlement overrides (e.g., partial settlement amount)
* @returns ProcessSettleResultResponse - SettleResponse with headers if success or errorReason if failure
*/
processSettlement(paymentPayload: PaymentPayload, requirements: PaymentRequirements, declaredExtensions?: Record<string, unknown>, transportContext?: HTTPTransportContext, settlementOverrides?: SettlementOverrides): Promise<ProcessSettleResultResponse>;
/**
* 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: HTTPRequestContext): boolean;
/**
* Build HTTPResponseInstructions for settlement failure.
* Uses settlementFailedResponseBody hook if configured, otherwise defaults to empty body.
*
* @param failure - Settlement failure result with headers
* @param transportContext - Optional HTTP transport context for the request
* @returns HTTP response instructions for the 402 settlement failure response
*/
private buildSettlementFailureResponse;
/**
* 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
*/
private normalizePaymentOptions;
/**
* 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)
*/
private validateRouteConfiguration;
/**
* Get route configuration for a request
*
* @param path - Request path
* @param method - HTTP method
* @returns Route configuration and pattern, or undefined if no match
*/
private getRouteConfig;
/**
* Extract payment from HTTP headers (handles v1 and v2)
*
* @param adapter - HTTP adapter
* @returns Decoded payment payload or null
*/
private extractPayment;
/**
* Check if request is from a web browser
*
* @param adapter - HTTP adapter
* @returns True if request appears to be from a browser
*/
private isWebBrowser;
/**
* 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
*/
private createHTTPResponse;
/**
* 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
*/
private createHTTPPaymentRequiredResponse;
/**
* Create settlement response headers
*
* @param settleResponse - Settlement response
* @returns Headers to add to response
*/
private createSettlementHeaders;
/**
* Parse route pattern into verb and regex
*
* @param pattern - Route pattern like "GET /api/*", "/api/[id]", or "/api/:id"
* @returns Parsed pattern with verb and regex
*/
private parseRoutePattern;
/**
* Normalize path for matching
*
* @param path - Raw path from request
* @returns Normalized path
*/
private normalizePath;
/**
* 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
*/
private generatePaywallHTML;
/**
* Extract display amount from payment requirements.
* Uses the registered scheme's decimal precision for the asset, falling back to 6.
*
* @param paymentRequired - The payment required object
* @returns The display amount in decimal format
*/
private getDisplayAmount;
}
export { type CompiledRoute as C, type DynamicPayTo as D, type HTTPAdapter as H, type PaywallConfig as P, type RouteConfig as R, type SettlementFailedResponseBody as S, type UnpaidResponseBody as U, type HTTPRequestContext as a, type HTTPTransportContext as b, type HTTPResponseInstructions as c, type HTTPProcessResult as d, type PaywallProvider as e, type PaymentOption as f, type RoutesConfig as g, type DynamicPrice as h, type HTTPResponseBody as i, type ProcessSettleResultResponse as j, type ProcessSettleSuccessResponse as k, type ProcessSettleFailureResponse as l, type RouteValidationError as m, RouteConfigurationError as n, type ProtectedRequestHook as o, SETTLEMENT_OVERRIDES_HEADER as p, checkIfBazaarNeeded as q, x402HTTPResourceServer as x };

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display