/** * FacilitatorHandler implementation for x402/Faremeter compatibility * Handles nano-session payment verification and settlement */ import type { PaymentRequirements, PaymentPayload } from '@nanosession/core'; import type { NanoRpcClient } from '@nanosession/rpc'; import type { SpentSetStorage } from './spent-set.js'; /** * Interface for session storage */ export interface SessionRegistry { get(sessionId: string): PaymentRequirements | undefined; set(sessionId: string, requirements: PaymentRequirements): void; delete(sessionId: string): void; has(sessionId: string): boolean; } /** * Configuration options for the handler */ export interface HandlerOptions { /** Nano RPC client instance */ rpcClient: NanoRpcClient; /** Optional spent set storage (defaults to in-memory) */ spentSet?: SpentSetStorage; /** Optional session storage (defaults to in-memory Map) */ sessionRegistry?: SessionRegistry; /** Optional tag modulus override (defaults to TAG_MODULUS) */ tagModulus?: number; /** Optional tag multiplier override (defaults to TAG_MULTIPLIER) */ tagMultiplier?: string | bigint; /** Seed for generating receive blocks in Track 2 (nanoSignature) */ seed?: string; /** Account index for the Facilitator's wallet. Defaults to 0. */ accountIndex?: number; /** Track 2 Receive Mode. Defaults to 'sync'. */ receiveMode?: 'sync' | 'async'; } /** * Supported payment scheme information */ export interface SupportedScheme { /** x402 protocol version */ x402Version: 2; /** Payment scheme identifier */ scheme: string; /** Network identifier (CAIP-2 format) */ network: string; } /** * Result of payment verification */ export interface VerifyResult { /** Whether the payment is valid */ isValid: boolean; /** Error message if verification failed */ error?: string; /** The transaction hash if verified */ blockHash?: string; } /** * Result of payment settlement */ export interface SettleResult { /** Whether settlement succeeded */ success: boolean; /** Transaction hash if successful */ transactionHash?: string; /** Error message if settlement failed */ error?: string; } /** * NanoSession Facilitator Handler * Implements x402/Faremeter FacilitatorHandler interface * * SECURITY: This handler maintains a session registry to prevent session spoofing attacks. * Only session IDs issued via getRequirements() are considered valid. */ export declare class NanoSessionFacilitatorHandler { private rpcClient; private spentSet; /** * Session registry - maps sessionId to the PaymentRequirements that were issued. * This prevents attackers from submitting payments with forged session IDs. * See: AGENTS.md § Security-First Protocol Development */ private sessionRegistry; private activeSessionAmounts; private tagModulus; private tagMultiplier; private seed?; private accountIndex; private receiveMode; constructor(options: HandlerOptions); private static resolveTagModulus; private static resolveTagMultiplier; private releaseSession; private isAmountInUse; /** * Returns the list of payment schemes supported by this facilitator. * @returns Array of supported protocol versions, schemes, and networks */ getSupported(): SupportedScheme[]; /** * Generates new payment requirements for a session. * Internally generates a unique session ID and reserved payment tag. * * @param args Configuration for the requirements * @returns Standard x402 PaymentRequirements object */ getRequirements(args: { /** Resource amount in raw, before the tag amount is added */ resourceAmountRaw: string; /** Destination account address */ payTo: string; /** How long before session expires */ maxTimeoutSeconds?: number; /** Optional deterministic tag value */ tag?: number; /** Optional deterministic tag amount in raw */ tagAmountRaw?: string; /** Optional tag modulus override */ tagModulus?: number; /** Optional tag multiplier override */ tagMultiplier?: string | bigint; }): PaymentRequirements; /** * Generates payment requirements for the nanoSignature (stateless) variant. * No session ID, no tag — the amount is the clean resource price. * Returns a SEPARATE PaymentRequirements from getRequirements(). * * A Facilitator advertising both variants should include BOTH in the accepts array: * ```ts * const accepts = [ * facilitator.getRequirements({ resourceAmountRaw, payTo }), * facilitator.getSignatureRequirements({ amount: resourceAmountRaw, payTo, url }) * ]; * ``` */ getSignatureRequirements(args: { /** Amount in raw (clean resource price) */ amount: string; /** Destination account address */ payTo: string; /** How long before this requirement expires (default: 600s) */ maxTimeoutSeconds?: number; /** The canonical URL for signature binding (required for replay protection) */ url: string; /** Template for the message the client must sign (default: "block_hash+url") */ messageToSign?: string; }): PaymentRequirements; /** * Retrieves previously generated requirements for a session. * @param sessionId Hexadecimal session identifier * @returns The stored requirements, or undefined if not found or expired */ getStoredRequirements(sessionId: string): PaymentRequirements | undefined; /** * Re-registers a session from externally-supplied requirements. * Used for recovery when the in-memory registry is lost (e.g. server restart) * but the client still holds the original 402 requirements. * * @WARNING: This skips session ID verification. Ensure you trust the * requirements if you use this to recover state. * * @param sessionId Hexadecimal session identifier * @param requirements The requirements to register */ registerSessionFromRequirements(sessionId: string, requirements: PaymentRequirements): void; /** * Verifies that a payment proof (block hash) satisfies the given requirements. * Performs cryptographic validation, session checks, and amount verification. * * @param requirements The requirements the payment must satisfy * @param payload The payment response containing the proof (hash) * @returns Verification result with validity status and optional error */ handleVerify(requirements: PaymentRequirements, payload: PaymentPayload, context?: unknown): Promise; /** * Verifies and finalizes a payment (settlement). * Unlike verify, this marks the proof as spent to prevent double-spending. * * @param requirements The requirements the payment must satisfy * @param payload The payment response containing the proof (hash) * @returns Settlement result with success status */ handleSettle(requirements: PaymentRequirements, payload: PaymentPayload, context?: unknown): Promise; /** * Verifies a nanoSignature (stateless) payment proof. * Checks: signature validity, block confirmation, receivability, destination, amount. * Does NOT broadcast receive block — that happens in handleSettle. */ private verifyNanoSignature; private settleReceiveBlock; private queueReceiveBlock; private generateWork; private waitForConfirmation; } //# sourceMappingURL=handler.d.ts.map