import type { SignedVoucher } from '../../shared/session-types.js'; import type { ChannelState } from './store.js'; /** * Reasons a voucher can be rejected. Stable string tags so the caller * can map to HTTP statuses / log levels without parsing free text. */ export type VoucherRejectReason = 'below-min-delta' | 'channel-close-pending' | 'channel-sealed' | 'cumulative-not-monotonic' | 'exceeds-deposit' | 'expired' | 'expires-within-settlement-window' | 'invalid-cumulative' | 'invalid-signature'; /** Verification outcome: the voucher advanced the channel watermark. */ export interface VoucherVerifyAccepted { /** New cumulative watermark to persist. */ readonly newCumulative: bigint; /** Expiry of the now-highest voucher (i64 seconds). */ readonly newExpiresAt: bigint; /** Signature to persist as `highestVoucherSignature`. */ readonly newSignature: string; readonly status: 'accepted'; } /** Verification outcome: an already-accepted voucher was re-submitted (idempotent). */ export interface VoucherVerifyReplayed { /** Existing watermark, returned for caller convenience. */ readonly newCumulative: bigint; readonly status: 'replayed'; } /** Verification outcome: the voucher was rejected. See {@link VoucherRejectReason}. */ export interface VoucherVerifyRejected { /** Human-readable detail. Safe to log; not stable. */ readonly detail: string; readonly reason: VoucherRejectReason; readonly status: 'rejected'; } /** Union of the three voucher verification outcomes. */ export type VoucherVerifyResult = VoucherVerifyAccepted | VoucherVerifyRejected | VoucherVerifyReplayed; /** Arguments to {@link verifyVoucherForChannel}. */ export interface VerifyVoucherArgs { /** * Authoritative deposit cap. Passed in (rather than read off `state`) * because some callers carry an updated cap after a recent top-up * that hasn't yet been written back into the store. */ readonly deposit: bigint; /** Optional minimum delta from the previous cumulative. */ readonly minVoucherDelta?: bigint | undefined; /** * Unix seconds, defaults to `Math.floor(Date.now() / 1000)`. Exposed * for tests and for callers that already have a clock. */ readonly nowSeconds?: bigint | undefined; /** * Forced-close grace period of the channel, in seconds (the on-chain * `gracePeriod` captured at open). When set, a *non-zero* voucher * `expiresAt` must outlast the settlement window — i.e. it must still * be valid `settlementWindow` seconds from now, so the merchant can * land an async settle_and_seal before the voucher expires. * A voucher with `expiresAt == 0` never expires and is unaffected. * Defaults to 0 (window check disabled — only `expiresAt <= now` is * rejected for non-zero expiries). */ readonly settlementWindow?: bigint | undefined; /** Voucher being submitted. */ readonly signed: SignedVoucher; /** Channel snapshot — typically read just before calling. */ readonly state: ChannelState; } /** * Verify a voucher against a channel snapshot. * * Returns a verdict; the caller is responsible for persisting any * accepted delta via `store.updateChannel`. The verifier is pure — * no store, network, or clock side effects (clock is injectable). * * Mirrors `SessionServer::verify_voucher` in Rust. Expiry is checked * here rather than inside the signature helper (Rust intermixes the * two; we keep them separate so callers can override `nowSeconds`). */ export declare function verifyVoucherForChannel(args: VerifyVoucherArgs): Promise; //# sourceMappingURL=voucher.d.ts.map