import { Address, Hex, PublicClient, WalletClient } from 'viem'; /** CAIP-2 network identifier (e.g. "eip155:11155111" for Sepolia) */ type NetworkId = `eip155:${number}` | `solana:${string}`; /** Resource description in 402 response */ type ResourceInfo = { url: string; description?: string; mimeType?: string; }; /** * Payment requirements — one option in the `accepts` array. * Matches @x402/core PaymentRequirements. */ type PaymentRequirements = { scheme: 'exact' | 'upto'; network: NetworkId; asset: Address; amount: string; payTo: Address; maxTimeoutSeconds: number; extra: { name: string; version: string; /** * Settlement scheme the facilitator should use (DVT#130 schema). When omitted the * facilitator defaults by asset (`asset ∈ X402_SUPPORTED_ASSETS ? "direct" : "eip-3009"`). */ settlement?: 'direct' | 'eip-3009'; /** Fee ceiling (atomic units, stringified uint256). Default: the payment amount. */ maxFee?: string; /** * Salt for the eip-3009 derived nonce `keccak256(abi.encode(payTo, maxFee, salt))` * (recipient-binding C-03 fix). Default: `authorization.nonce`. */ salt?: Hex; }; }; /** * 402 response body / PAYMENT-REQUIRED header. * Server sends this to indicate payment is needed. */ type PaymentRequired = { x402Version: 2; error?: string; resource: ResourceInfo; accepts: PaymentRequirements[]; extensions?: Record; }; /** * EIP-3009 TransferWithAuthorization parameters. */ type EIP3009Authorization = { from: Address; to: Address; value: string; validAfter: string; validBefore: string; nonce: Hex; }; /** * Client payment payload — PAYMENT-SIGNATURE header. * Client sends this on retry request. */ type PaymentPayload = { x402Version: 2; resource?: ResourceInfo; accepted: PaymentRequirements; payload: { signature: Hex; authorization: EIP3009Authorization; }; extensions?: Record; }; /** * Settlement response — PAYMENT-RESPONSE header. * Server returns after facilitator settles. */ type SettleResponse = { success: boolean; transaction?: string; network?: NetworkId; payer?: Address; errorReason?: string; extensions?: Record; }; /** * Facilitator verify response. */ type VerifyResponse = { isValid: boolean; invalidReason?: string; payer?: Address; }; /** * Facilitator supported kinds response. */ type FacilitatorSupported = { kinds: Array<{ x402Version: number; scheme: string; network: string; extra?: Record; }>; extensions: string[]; }; /** Direct settlement (for xPNTs and pre-approved tokens, bypasses EIP-3009) */ type DirectPaymentPayload = { x402Version: 2; scheme: 'direct'; from: Address; to: Address; asset: Address; amount: string; nonce: Hex; }; /** Payment creation parameters (high-level SDK input) */ type X402PaymentParams = { from: Address; to: Address; asset: Address; amount: bigint; validAfter?: bigint; validBefore?: bigint; nonce?: Hex; /** * Settlement path (DVT#130). `"direct"` → sign an X402PaymentAuthorization (xPNTs); * `"eip-3009"` → sign a ReceiveWithAuthorization with the recipient-bound derived nonce (USDC). * Default: `"eip-3009"` (the x402 v2 default) unless the client/asset implies direct. */ settlement?: 'direct' | 'eip-3009'; /** Fee ceiling (atomic units). Default: `amount`. */ maxFee?: bigint; /** Salt for the eip-3009 derived nonce. Default: a fresh random 32-byte value. */ salt?: Hex; }; /** Facilitator client configuration */ type FacilitatorConfig = { url: string; /** * Per-request auth headers (stateless, no prior round-trip). Receives the endpoint + the exact * raw request body so it can sign it (e.g. the §4 HMAC over `${timestamp}.${rawBody}`). Use * {@link createX402AuthHeaders} for the DVT facilitator's HMAC scheme. Return `{}` for no auth. */ createAuthHeaders?: (ctx: { endpoint: 'verify' | 'settle' | 'supported'; body: string; }) => Promise> | Record; }; type X402ClientConfig = { publicClient: PublicClient; walletClient: WalletClient; superPaymasterAddress: Address; chainId: number; /** * The deployed `X402Facilitator` contract — the EIP-712 `verifyingContract` for the direct-path * `X402PaymentAuthorization` AND the on-chain recipient for the eip-3009 path. Defaults to * `DEFAULT_X402_FACILITATORS[chainId].contract`. */ facilitatorContract?: Address; /** Facilitator endpoint (default: self-facilitated via SuperPaymaster) */ facilitator?: FacilitatorConfig; /** EIP-712 domain for asset token (defaults: USDC / version "2") */ tokenName?: string; tokenVersion?: string; /** Payment policy: max amount per request (in atomic units) */ maxAmountPerRequest?: bigint; }; declare class X402Client { private readonly actions; private readonly config; private readonly facilitatorClient?; constructor(config: X402ClientConfig); /** Resolve the deployed X402Facilitator contract (config override → DEFAULT_X402_FACILITATORS). */ private facilitatorContract; /** * Create a signed payment payload, aligned with the deployed `X402Facilitator` (DVT#130). * Two settlement paths: * - `"direct"` (xPNTs): payer signs an `X402PaymentAuthorization` (EIP-712 over the facilitator), * settled via `settleX402PaymentDirect(..., signature)`. * - `"eip-3009"` (USDC, default): payer signs a `ReceiveWithAuthorization` over the TOKEN, with * recipient = the facilitator and a DERIVED nonce `keccak256(abi.encode(payTo,maxFee,salt))` * that binds the final recipient (C-03). The facilitator submits `settleX402Payment`. * Returns a base64-encoded PaymentPayload ready for the PAYMENT-SIGNATURE header. */ createPayment(params: X402PaymentParams): Promise<{ payload: PaymentPayload; encoded: string; nonce: Hex; }>; /** * Settle payment on-chain via SuperPaymaster (self-facilitated). * Uses EIP-3009 transferWithAuthorization path. */ settleOnChain(params: { from: Address; to: Address; asset: Address; amount: bigint; validAfter: bigint; validBefore: bigint; nonce: Hex; signature: Hex; }): Promise; /** * Settle payment on-chain via direct transfer (for xPNTs and pre-approved tokens). */ settleDirectOnChain(params: { from: Address; to: Address; asset: Address; amount: bigint; nonce: Hex; }): Promise; /** * Get facilitator fee quote from on-chain contract. */ getQuote(): Promise<{ feeBPS: bigint; }>; /** * Check if a nonce has been used. */ checkNonce(nonce: Hex): Promise; /** * Merge the settlement `extra` (`settlement`/`maxFee`/`salt`) from the signed payload into the * requirements the facilitator actually reads. In the `x402Fetch` path the server's 402 is a bare * requirements object (no settlement fields), so the facilitator can't pick the path/fee/salt unless * we carry them across from `payload.accepted.extra`. Defaults the whole requirements to * `payload.accepted` when none is supplied. */ private requirementsForFacilitator; /** * Verify a payment via the external facilitator (`POST /x402/verify`). `requirements` defaults to * the signed `payload.accepted` (which carries the settlement `extra`). */ verifyViaFacilitator(payload: PaymentPayload, requirements?: PaymentRequirements): Promise; /** * Settle via external facilitator (`POST /x402/settle`). `requirements` defaults to the signed * `payload.accepted`, so the settlement `extra` (settlement/maxFee/salt) always reaches the facilitator. */ settleViaFacilitator(payload: PaymentPayload, requirements?: PaymentRequirements): Promise; /** * x402-aware fetch wrapper. * Automatically handles 402 → sign → retry flow per x402 v2 spec. * * Pattern from: @x402/fetch wrapFetchWithPayment * * Flow: * 1. Make initial request * 2. If 402, extract PaymentRequired from PAYMENT-REQUIRED header * 3. Select best payment option (applies policy: max amount check) * 4. Sign EIP-3009 authorization * 5. Retry with PAYMENT-SIGNATURE header */ x402Fetch(url: string, init?: RequestInit): Promise; } /** * HTTP Facilitator Client — standard x402 v2 facilitator API. * Compatible with Coinbase hosted facilitator and self-hosted instances. * * Ref: coinbase/x402 HTTPFacilitatorClient pattern */ declare class FacilitatorClient { private readonly url; private readonly createAuthHeaders; constructor(config: FacilitatorConfig); /** Headers for a request, signing the EXACT `body` bytes (so the §4 HMAC matches what's sent). */ private getHeaders; /** * POST /verify — validate payment signature off-chain (~100ms). */ verify(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise; /** * POST /settle — execute on-chain settlement (~2s on Base). */ settle(paymentPayload: PaymentPayload, paymentRequirements: PaymentRequirements): Promise; /** * GET /supported — query facilitator capabilities. */ supported(): Promise; } /** EIP-712 type for the direct-settlement payer authorization (X402Facilitator domain). */ declare const X402_PAYMENT_AUTHORIZATION_TYPES: { readonly X402PaymentAuthorization: readonly [{ readonly name: "from"; readonly type: "address"; }, { readonly name: "to"; readonly type: "address"; }, { readonly name: "asset"; readonly type: "address"; }, { readonly name: "amount"; readonly type: "uint256"; }, { readonly name: "maxFee"; readonly type: "uint256"; }, { readonly name: "validBefore"; readonly type: "uint256"; }, { readonly name: "nonce"; readonly type: "bytes32"; }]; }; /** * Derived EIP-3009 nonce for the USDC settle path — MUST equal the contract's * `keccak256(abi.encode(to, maxFee, salt))` (`X402Facilitator.settleX402Payment`), where * `to` is the FINAL recipient (payTo). Binding the recipient into the nonce is the C-03 fix * (a facilitator can't redirect the payout without invalidating the signature). */ declare function deriveEip3009Nonce(payTo: Address, maxFee: bigint, salt: Hex): Hex; /** * Sign the direct-path `X402PaymentAuthorization` (EIP-712). Domain is the FACILITATOR * contract — `{ name: "X402Facilitator", version: "1", chainId, verifyingContract: facilitator }` * (matches `X402Facilitator._x402DomainSeparator()`; verified on-chain via settleX402PaymentDirect). * EOA or AirAccount passkey (ERC-1271) — the contract uses `SignatureCheckerLib.isValidSignatureNow`. */ declare function signX402PaymentAuthorization(walletClient: WalletClient, params: { from: Address; to: Address; asset: Address; amount: bigint; maxFee: bigint; validBefore: bigint; nonce: Hex; chainId: number; facilitator: Address; }): Promise; /** * Default x402 facilitator registry (mirrors `@aastar/core` `DEFAULT_DVT_NODES`). * * `contract` is the deployed `X402Facilitator` (used as the EIP-712 `verifyingContract` for the * direct-path `X402PaymentAuthorization`, and as the on-chain recipient for the eip-3009 path). * `urls` are the hosted facilitator HTTP services (`/x402/{verify,settle,supported}`) — these are * operated by DVT nodes (migration tracked in YetAnotherAA-Validator#130) and are filled in once * dvt1/2/3 deploy the `x402-facilitator` module. A developer can always override via * `new X402Client({ facilitator: { url } })`. */ interface X402FacilitatorEnv { chainId: number; /** Deployed X402Facilitator contract (EIP-712 domain verifyingContract + eip-3009 recipient). */ contract: Address; /** Hosted facilitator service base URLs (each appends `/x402/...`). Empty until DVT deploys. */ urls: string[]; } declare const DEFAULT_X402_FACILITATORS: Readonly>; /** The deployed X402Facilitator contract for a chain (throws if unknown — callers must pass one). */ declare function getX402FacilitatorContract(chainId: number): Address; /** Hosted facilitator service URLs for a chain (empty until DVT deploys the module). */ declare function getX402FacilitatorUrls(chainId: number): string[]; /** HMAC-SHA256(secret, message) as lowercase hex, via Web Crypto (Node 18+ / browser). */ declare function hmacSha256Hex(secret: string, message: string): Promise; /** * Build a `FacilitatorConfig.createAuthHeaders` for the DVT facilitator's optional stateless-HMAC * gate (x402-facilitator spec §4). Only emits headers for `POST /x402/settle` (the only guarded * endpoint); other endpoints get no auth headers. Use ONLY when the target node runs with * `X402_AUTH_ENABLED=true` and shares `X402_AUTH_SECRET`: * * X-X402-Timestamp: * X-X402-Auth: hex HMAC-SHA256(secret, `${timestamp}.${rawBody}`) * * The node accepts iff `|now − timestamp| ≤ X402_AUTH_TTL_MS` and the HMAC matches over the raw body. * * @param secret the shared `X402_AUTH_SECRET`. * @param opts.now injectable clock (ms) for tests; defaults to `Date.now`. */ declare function createX402AuthHeaders(secret: string, opts?: { now?: () => number; }): NonNullable; declare const EIP3009_TYPES: { readonly TransferWithAuthorization: readonly [{ readonly name: "from"; readonly type: "address"; }, { readonly name: "to"; readonly type: "address"; }, { readonly name: "value"; readonly type: "uint256"; }, { readonly name: "validAfter"; readonly type: "uint256"; }, { readonly name: "validBefore"; readonly type: "uint256"; }, { readonly name: "nonce"; readonly type: "bytes32"; }]; readonly ReceiveWithAuthorization: readonly [{ readonly name: "from"; readonly type: "address"; }, { readonly name: "to"; readonly type: "address"; }, { readonly name: "value"; readonly type: "uint256"; }, { readonly name: "validAfter"; readonly type: "uint256"; }, { readonly name: "validBefore"; readonly type: "uint256"; }, { readonly name: "nonce"; readonly type: "bytes32"; }]; readonly CancelAuthorization: readonly [{ readonly name: "authorizer"; readonly type: "address"; }, { readonly name: "nonce"; readonly type: "bytes32"; }]; }; declare function getEIP3009Domain(tokenName: string, tokenVersion: string, chainId: number, verifyingContract: Address): { name: string; version: string; chainId: number; verifyingContract: `0x${string}`; }; declare function generateNonce(): Hex; declare const GTOKEN_EIP712_DOMAIN: { readonly name: "GToken"; readonly version: "1"; }; declare function signTransferWithAuthorization(walletClient: WalletClient, params: { from: Address; to: Address; value: bigint; validAfter: bigint; validBefore: bigint; nonce: Hex; tokenName: string; tokenVersion: string; chainId: number; verifyingContract: Address; }): Promise; /** * Sign a TransferWithAuthorization for GTokenAuthorization (EIP-3009). * GToken-specific wrapper: enforces MAX_AUTH_VALIDITY = 300s before signing. * Use this instead of the generic signTransferWithAuthorization when the * verifying contract is GTokenAuthorization. */ declare function signGTokenTransferWithAuthorization(walletClient: WalletClient, params: { from: Address; to: Address; value: bigint; validAfter: bigint; validBefore: bigint; nonce: Hex; tokenName: string; tokenVersion: string; chainId: number; verifyingContract: Address; }): Promise; /** * Sign a ReceiveWithAuthorization for GTokenAuthorization (EIP-3009). * The signed `to` address must be the one submitting the transaction on-chain. * Note: `xPNTsToken` is NOT included in the signature (it's a relay-supplied hint for RC-2). */ declare function signReceiveWithAuthorization(walletClient: WalletClient, params: { from: Address; to: Address; value: bigint; validAfter: bigint; validBefore: bigint; nonce: Hex; tokenName: string; tokenVersion: string; chainId: number; verifyingContract: Address; }): Promise; /** * Sign a CancelAuthorization for GTokenAuthorization (EIP-3009). * Must be signed by the original `authorizer` address. */ declare function signCancelAuthorization(walletClient: WalletClient, params: { authorizer: Address; nonce: Hex; tokenName: string; tokenVersion: string; chainId: number; verifyingContract: Address; }): Promise; /** v2 header names (standard) */ declare const HEADER_PAYMENT_REQUIRED = "PAYMENT-REQUIRED"; declare const HEADER_PAYMENT_SIGNATURE = "PAYMENT-SIGNATURE"; declare const HEADER_PAYMENT_RESPONSE = "PAYMENT-RESPONSE"; /** v1 header names (backward compat) */ declare const HEADER_V1_PAYMENT = "X-PAYMENT"; declare const HEADER_V1_PAYMENT_RESPONSE = "X-PAYMENT-RESPONSE"; declare function encodePaymentRequired(req: PaymentRequired): string; declare function decodePaymentRequired(encoded: string): PaymentRequired; declare function encodePaymentPayload(payload: PaymentPayload): string; declare function decodePaymentPayload(encoded: string): PaymentPayload; declare function encodeSettleResponse(resp: SettleResponse): string; declare function decodeSettleResponse(encoded: string): SettleResponse; /** * Extract PaymentRequired from a 402 Response. * Tries v2 header first, falls back to v1. */ declare function extractPaymentRequired(response: Response): PaymentRequired | null; /** * Extract SettleResponse from a successful response. */ declare function extractSettleResponse(response: Response): SettleResponse | null; export { DEFAULT_X402_FACILITATORS, type DirectPaymentPayload, type EIP3009Authorization, EIP3009_TYPES, FacilitatorClient, type FacilitatorConfig, type FacilitatorSupported, GTOKEN_EIP712_DOMAIN, HEADER_PAYMENT_REQUIRED, HEADER_PAYMENT_RESPONSE, HEADER_PAYMENT_SIGNATURE, HEADER_V1_PAYMENT, HEADER_V1_PAYMENT_RESPONSE, type NetworkId, type PaymentPayload, type PaymentRequired, type PaymentRequirements, type ResourceInfo, type SettleResponse, type VerifyResponse, X402Client, type X402ClientConfig, type X402FacilitatorEnv, type X402PaymentParams, X402_PAYMENT_AUTHORIZATION_TYPES, createX402AuthHeaders, decodePaymentPayload, decodePaymentRequired, decodeSettleResponse, deriveEip3009Nonce, encodePaymentPayload, encodePaymentRequired, encodeSettleResponse, extractPaymentRequired, extractSettleResponse, generateNonce, getEIP3009Domain, getX402FacilitatorContract, getX402FacilitatorUrls, hmacSha256Hex, signCancelAuthorization, signGTokenTransferWithAuthorization, signReceiveWithAuthorization, signTransferWithAuthorization, signX402PaymentAuthorization };