import type { Client } from "../kernel.js";
import { Run402Error, type NextAction } from "../errors.js";
export declare const DEFAULT_PAYMENT_MAX_USD_MICROS = 100000;
export declare const X402_COMMERCE_RESULT_SCHEMA_VERSION: "x402-commerce-result.v1";
export declare const X402_PAYMENT_POLICY_ERROR_CODES: readonly ["MERCHANT_RECEIPT_REQUIRED", "MERCHANT_RECEIPT_UNAVAILABLE"];
export declare const X402_GATEWAY_AVAILABILITY_ERROR_CODE: "MERCHANT_EVIDENCE_UNAVAILABLE";
export declare const X402_MUTATION_STATES: readonly ["not_started", "committed", "unknown"];
export declare const X402_RECOVERY_ACTIONS: readonly ["retry", "reconcile_payment"];
export interface PayFetchOptions {
    /** Maximum atomic USD units this call may authorize. Defaults to 100,000 ($0.10). */
    maxUsdMicros?: number;
    /** Forwarded as `Idempotency-Key` for key-deduplicated paid HTTP surfaces. */
    idempotencyKey?: string;
    /**
     * Require a verified wallet-rooted merchant offer before authorizing
     * payment and a matching verified receipt after settlement.
     */
    requireReceipt?: boolean;
    /**
     * Lightning only: refuse an `lnbtc` payment whose invoice plus routing
     * headroom exceeds this many sats. Absent, the rail's per-call ceiling applies.
     */
    maxSats?: number;
    /**
     * Lightning only: pay the `lnbtc` entry with this Nostr Wallet Connect
     * pairing instead of the configured wallet, on whichever network its node
     * is on. A bearer secret: the CLI reads it from a file or stdin, and the MCP
     * sandbox refuses it (`SECRET_REQUIRES_CLI`).
     */
    lightningPairing?: string;
}
export declare const X402_EVIDENCE_STATUSES: readonly ["verified", "absent", "invalid", "untrusted", "unavailable"];
export type PaymentEvidenceStatus = (typeof X402_EVIDENCE_STATUSES)[number];
export interface PaymentNextAction extends NextAction {
    type: "retry" | "reconcile_payment";
    why: string;
    request?: "repeat_identical";
    reusePayer?: true;
    reuseIdempotencyKey?: true;
}
export interface PaymentRawEvidence {
    offer: unknown | null;
    merchantReceipt: unknown | null;
    signerAuthorization: unknown | null;
    /** MPP only: the seller's decoded `Payment-Receipt` (`{ method, reference, status, timestamp }`). */
    protocolReceipt?: unknown | null;
}
/** The payment protocol that paid, and its scheme or method. */
export type PaymentProtocol = "x402" | "mpp";
export interface PaymentReceipt {
    protocol: PaymentProtocol;
    /** x402 scheme (`exact`) or MPP method (`tempo`). */
    method: "exact" | "tempo";
    network: string;
    paymentId: string | null;
    amountUsdMicros: number;
    /** Lightning only: the invoice amount in millisatoshis (the USD amount is the seller's, not reported). */
    amountMsat?: number;
    asset: string;
    payer: string | null;
    payTo: string;
    transaction: string;
    resourceUrl: string;
    settlement: {
        status: PaymentEvidenceStatus;
    };
    fundsMoved: PaymentFundsMoved;
    deduplicated: boolean;
    delivery: {
        status: "fulfilled" | "failed" | "unknown";
        replay: boolean;
    };
    offer: {
        status: PaymentEvidenceStatus;
        resourceUrl: string | null;
        validUntil: string | null;
    };
    merchantReceipt: {
        status: PaymentEvidenceStatus;
        claim: "service_delivered" | null;
        issuedAt: string | null;
    };
    signerRelationship: {
        kind: "direct" | "delegated" | "unverified" | null;
        merchantRoot: string | null;
        signer: string | null;
        authorizationExpiresAt: string | null;
    };
    policy: {
        requireReceipt: boolean;
        status: "satisfied" | "unsatisfied" | "not_required";
    };
    evidence: PaymentRawEvidence;
}
export type PayFetchOutcome = "not_required" | "settled" | "already_settled";
export interface PayFetchResult {
    /** The upstream response. The SDK never consumes its body. */
    response: Response;
    /** On-chain receipt, or null when no payment was needed / no transaction reference is available. */
    payment: PaymentReceipt | null;
    outcome: PayFetchOutcome;
    /** True for a re-presented proof or a key-deduplicated upstream result. */
    replay: boolean;
    /** Stable Run402 tenant-payment identity when the target supplied one. */
    paymentId?: string | null;
    /** Whether this HTTP request reused an existing Run402 payment identity. */
    deduplicated?: boolean | null;
    /** Funds movement initiated by this HTTP attempt, when declared by Run402. */
    fundsMoved?: PaymentFundsMoved | null;
    /** Tenant delivery state for this attempt. */
    delivery?: "first" | "replay" | "none" | null;
    /** Confirmed settlement time supplied by Run402. */
    settledAt?: string | null;
    /** Durable intent state when the request is a status-bearing replay. */
    intentState?: string | null;
    /** Canonical recovery actions. Never recommends a second payment. */
    nextActions?: PaymentNextAction[];
}
export declare function payFetchResultToJson(result: PayFetchResult, body: unknown): Record<string, unknown>;
export type PaymentFundsMoved = boolean | "unknown";
export type PaymentBuyerErrorCode = "PAYMENT_EXCEEDS_MAX" | "PAYMENT_WALLET_UNFUNDED" | "PAYMENT_DEPENDENCY_MISSING" | "PAYMENT_NETWORK_UNSUPPORTED" | "PAYMENT_INTENT_PENDING" | "PAYMENT_DESTINATION_DRAINING" | "PAYMENT_INTENT_DESTINATION_CHANGED" | "PAYMENT_INTENT_FENCE_EXPIRED" | "PAYMENT_AUTHORIZATION_LIFETIME_EXCEEDED" | "PAYMENT_CALLER_IDENTITY_NOT_ACTIVE" | "IDEMPOTENCY_KEY_REUSED" | "IDEMPOTENCY_KEY_INVALID" | "IDEMPOTENCY_KEY_PAYER_REQUIRED" | "PAYMENT_SETTLEMENT_FAILED" | "MERCHANT_RECEIPT_REQUIRED" | "MERCHANT_RECEIPT_UNAVAILABLE";
export interface PayResponseMetadata {
    paymentId: string | null;
    deduplicated: boolean | null;
    fundsMoved: PaymentFundsMoved | null;
    delivery: "first" | "replay" | "none" | null;
    settledAt: string | null;
    intentState: string | null;
}
/** Structured local failure from {@link Pay.fetch}. */
export declare class PaymentBuyerError extends Run402Error {
    readonly kind: "payment_buyer_error";
    readonly code: PaymentBuyerErrorCode;
    readonly fundsMoved: PaymentFundsMoved;
    readonly paymentId: string | null;
    readonly intentState: string | null;
    readonly delivery: "first" | "replay" | "none" | null;
    readonly deduplicated: boolean | null;
    readonly settledAt: string | null;
    readonly cause?: unknown;
    constructor(init: {
        code: PaymentBuyerErrorCode;
        message: string;
        fundsMoved: PaymentFundsMoved;
        details?: Record<string, unknown>;
        nextActions: NextAction[];
        retryable?: boolean;
        safeToRetry?: boolean;
        cause?: unknown;
        status?: number | null;
        body?: Record<string, unknown>;
    });
    toJSON(): Record<string, unknown>;
}
/**
 * A receipt policy failed after a paid response was received. The original
 * response and commerce result remain available for reconciliation.
 */
export declare class PaymentPolicyError extends PaymentBuyerError {
    readonly response: Response;
    readonly result: PayFetchResult;
    readonly mutationState: "not_started" | "committed" | "unknown";
    readonly safeToRetry: boolean;
    readonly nextActions: PaymentNextAction[];
    constructor(init: {
        response: Response;
        result: PayFetchResult;
        message: string;
        fundsMoved: PaymentFundsMoved;
        mutationState: "not_started" | "committed" | "unknown";
        safeToRetry: boolean;
        nextActions: PaymentNextAction[];
    });
}
export declare function isPaymentBuyerError(error: unknown): error is PaymentBuyerError;
export declare function isPaymentPolicyError(error: unknown): error is PaymentPolicyError;
export type PayExecutor = (url: string, init: RequestInit | undefined, options: Required<Pick<PayFetchOptions, "maxUsdMicros" | "requireReceipt">> & Pick<PayFetchOptions, "idempotencyKey" | "maxSats" | "lightningPairing">) => Promise<PayFetchResult>;
/** Arbitrary-URL buyer namespace. Node supplies the x402 executor; isomorphic callers may inject one. */
export declare class Pay {
    private readonly client;
    private readonly executor?;
    constructor(client: Client, executor?: PayExecutor | undefined);
    fetch(url: string | URL, init?: RequestInit, options?: PayFetchOptions): Promise<PayFetchResult>;
}
export declare function merchantReceiptRequiredError(details?: Record<string, unknown>): PaymentBuyerError;
export declare function paymentExceedsMaxError(challengedAmountUsdMicros: number, maxUsdMicros: number): PaymentBuyerError;
export declare function walletUnavailableError(details?: Record<string, unknown>): PaymentBuyerError;
/**
 * The paid stack is an OPTIONAL peer set, so a consumer can legitimately be
 * unable to pay while holding a perfectly funded wallet. Reporting that as
 * PAYMENT_WALLET_UNFUNDED sends the caller to fund an already-funded wallet —
 * an unattended agent then loops between `init` (reports funded) and the
 * payment (reports unfunded). The remedy is an install, so say so.
 */
export declare function paidStackUnavailableError(missingPackages: readonly string[], details?: Record<string, unknown>): PaymentBuyerError;
export declare function responseSignalsReplay(response: Response, inspect: boolean): Promise<boolean>;
/** Parse platform-owned payment response headers without consuming the response body. */
export declare function payResponseMetadata(response: Response): PayResponseMetadata;
export declare const RUN402_PENDING_CLASSIFIER_VERSION = 1;
/** Exact DNS-label classifier for Run402-owned tenant and deployment hosts. */
export declare function isTrustedRun402PaymentUrl(input: string | URL, options?: {
    allowTestLocalhost?: boolean;
}): boolean;
/**
 * Trust a pending result only at the complete signed-response boundary. The
 * caller supplies `paymentBearing` and `redirectsDisabled` from its executor;
 * shape alone is intentionally insufficient for arbitrary/custom domains.
 */
export declare function isTrustedRun402PendingResponse(input: {
    requestUrl: string;
    response: Response;
    envelope: Record<string, unknown> | null;
    paymentBearing: boolean;
    redirectsDisabled: boolean;
    allowTestLocalhost?: boolean;
}): boolean;
export declare function readPaymentErrorEnvelope(response: Response): Promise<Record<string, unknown> | null>;
export declare function gatewayPaymentBuyerError(response: Response, envelope: Record<string, unknown>): PaymentBuyerError | null;
//# sourceMappingURL=pay.d.ts.map