Types
Wallet
The main interface returned by createWallet.
interface Wallet { getBalance(userId: string): Promise<number>; canSpend(userId: string, amount: number): Promise<boolean>; spend( userId: string, amount: number, idempotencyKey: string, options?: { metadata?: string }, ): Promise<void>; topUp( userId: string, amount: number, idempotencyKey: string, options?: { expiresAt?: Date; metadata?: string }, ): Promise<void>; expireTokens(userId: string): Promise<ExpireResult>; getUsageReport( userId: string, dateRange: { from: Date; to: Date }, ): Promise<UsageReport>; getTransactions(userId: string, query?: TransactionQuery): Promise<LedgerEntry[]>; getCheckouts(userId: string, query?: CheckoutQuery): Promise<CheckoutSession[]>;}WalletConfig
interface WalletConfig { storage: StorageAdapter;}LedgerEntry
A single transaction in the append-only ledger.
interface LedgerEntry { id: string; userId: string; /** Positive = credit, negative = debit */ amount: number; idempotencyKey: string; createdAt: Date; /** When this credit expires (credits only) */ expiresAt?: Date; /** Remaining unexpired amount (credits only, decremented on spend) */ remaining?: number; /** When this credit was expired by expireTokens */ expiredAt?: Date; /** Free-form audit metadata */ metadata?: string;}CheckoutSession
A payment session created by the checkout manager.
interface CheckoutSession { id: string; userId: string; amount: number; redirectUrl: string; status: 'pending' | 'paid' | 'failed'; createdAt: Date;}TransactionQuery
Query parameters for getTransactions.
interface TransactionQuery { limit?: number; // 1-100, default 50 offset?: number; // >= 0, default 0 type?: 'credit' | 'debit'; from?: Date; // filter entries created at or after this date to?: Date; // filter entries created before this date}CheckoutQuery
Query parameters for getCheckouts.
interface CheckoutQuery { limit?: number; // 1-100, default 50 offset?: number; // >= 0, default 0 status?: 'pending' | 'paid' | 'failed';}WebhookResult
Returned by handleWebhook.
interface WebhookResult { action: WebhookAction; reason?: WebhookSkipReason;}
type WebhookAction = 'credited' | 'skipped' | 'duplicate';
type WebhookSkipReason = | 'unparseable' | 'non_success_status' | 'session_not_found' | 'already_processed';WebhookStatus
Gateway-agnostic payment status.
type WebhookStatus = 'success' | 'failed' | 'pending' | 'expired';ExpireResult
Returned by wallet.expireTokens.
interface ExpireResult { /** Number of ledger entries that were expired */ expiredCount: number; /** Total token amount that was expired */ expiredAmount: number;}UsageReport
Returned by wallet.getUsageReport.
interface UsageReport { /** Total credits added in the date range */ totalCredits: number; /** Total debits in the date range */ totalDebits: number; /** Net change (credits - debits) */ netChange: number; /** Number of transactions in the date range */ transactionCount: number;}StorageAdapter
Interface for storage backends. Implement this to use a different database.
interface StorageAdapter { getBalance(userId: string): Promise<number>; appendEntry(entry: Omit<LedgerEntry, 'id' | 'createdAt'>): Promise<LedgerEntry>; findEntry(idempotencyKey: string): Promise<LedgerEntry | null>; saveCheckout(session: CheckoutSession): Promise<CheckoutSession>; findCheckout(id: string): Promise<CheckoutSession | null>; updateCheckoutStatus(id: string, status: CheckoutSession['status']): Promise<void>; getTransactions?(userId: string, query?: TransactionQuery): Promise<LedgerEntry[]>; getCheckouts?(userId: string, query?: CheckoutQuery): Promise<CheckoutSession[]>;
/** Expire all credits past their expiresAt for a user. Optional — throws if not implemented. */ expireCredits?(userId: string): Promise<ExpireResult>; /** Return user IDs that have credits past their expiresAt. Optional. */ getUsersWithExpirableCredits?(): Promise<string[]>;}PaymentGatewayAdapter
Interface for payment gateways. Implement this to add a new payment provider.
interface PaymentGatewayAdapter { createCheckout(params: { userId: string; amount: number; successRedirectUrl: string; failureRedirectUrl: string; }): Promise<CheckoutSession>;
verifyWebhook(payload: unknown, signature: string, rawBody?: string | Buffer): Promise<boolean>;
parseWebhookPayload(payload: unknown): { orderId: string; status: WebhookStatus; grossAmount: number; } | null;
/** Optional — poll gateway for payment status */ getPaymentStatus?(id: string): Promise<WebhookStatus>;}