/** * @pwngh/economy-lab * * Copyright (c) Preston Neal * * This source code is licensed under the MIT license found in the * LICENSE.md file in the root directory of this source tree. * * @license MIT */ import type { Amount } from '../money.js'; import type { AccountRef } from '../accounts.js'; import type { Transaction } from '../contract.js'; import type { Checkpoint, Digest, InboxMessage, Leg, Logger, Meter, OutboxMessage, Posting, PromoGrant, Saga, Subscription } from '../ports.js'; import type { Clock } from '../ports.js'; /** * The shared field vocabulary for opening either SQL engine; each engine entry exports its * `EngineOpenOptions` alias with `TPool` bound to that driver's typed pool, and implements its * subset (`postgresStore` opens by `url`, `mysqlStore` takes a pre-built `pool`). Open-path * schema policy is `assert` (require the schema_meta stamp to match) or `skip` (break-glass); * applying or migrating a schema is a separate operator job, never an open option. */ export type EngineOpenShape = { readonly url?: string; readonly pool?: TPool; readonly poolMax?: number | null; readonly connectionTimeoutMillis?: number; /** Frozen at store construction; changing it means a rebuild over the same database. */ readonly velocityWindowMs: number; readonly digest: Digest; readonly clock: Clock; readonly meter?: Meter; readonly logger?: Logger; readonly schema?: 'assert' | 'skip'; /** Postgres test isolation; created at open, dropped on close. */ readonly schemaName?: string; }; /** * Returns a SHA-256 digest backed by Web Crypto, which is available on every JS runtime. The same * bytes hash to the same digest on every runtime, so the chain head an engine writes is * reproducible everywhere. * * @see {@link https://economy-lab-docs.pages.dev/economy/ports/storage/ Storage} for how engines plug into the ledger. */ export declare function defaultDigest(): Digest; export declare const CHAIN_FORK_INDEX = "chain_links_account_prev_uq"; export declare const CHAIN_CONTINUITY_MARKER = "chain continuity"; export declare function readMinor(value: unknown): bigint; export declare function distinctAccounts(legs: ReadonlyArray): AccountRef[]; export declare function sortByAccountId(rows: Array>): void; export type Link = { account: AccountRef; prevHash: string; hash: string; }; export declare function chainLinksFor(digest: Digest, posting: Posting, heads: Map): Promise>; export declare function isSeededSystemAccount(account: AccountRef): boolean; export declare class KnownAccounts { private readonly entries; private readonly capacity; constructor(capacity?: number); has(account: string): boolean; add(account: string): void; } export declare class StagedAccounts { private accounts; add(account: string): void; mark(): number; rollbackTo(mark: number): void; promoteInto(known: KnownAccounts): void; } export declare class TxHeads { private readonly map; private journal; get(account: string): string | undefined; has(account: string): boolean; set(account: string, hash: string): void; mark(): number; rollbackTo(mark: number): void; } export declare function advanceCapturedHeads(heads: TxHeads | undefined, transactions: ReadonlyArray): void; type Attempt = () => Promise; export type IsTransientConflict = (error: unknown) => boolean; export type RetryEvent = { type: 'retry'; attempt: number; error: unknown; } | { type: 'recovered'; attempts: number; } | { type: 'exhausted'; attempts: number; error: unknown; }; export type RetryObserver = (event: RetryEvent) => void; export declare function setRetryObserver(observer: RetryObserver | null): RetryObserver | null; /** * Builds the production retry observer from a store's optional meter and logger, or undefined when * neither is wired. Each transient conflict and each exhausted budget counts as `engine.retry` * (tagged with the outcome), a commit the budget rescued counts as `engine.retry.recovered`, and an * exhausted budget also logs `engine.retry.exhausted` before the error reaches the caller. */ export declare function retryTelemetry(runtime: { meter?: Meter; logger?: Logger; }, engine: 'postgres' | 'mysql'): RetryObserver | undefined; type RetryOptions = { maxAttempts?: number; observer?: RetryObserver; }; export declare function withTransientRetry(attempt: Attempt, isTransientConflict: IsTransientConflict, options?: RetryOptions): Promise; /** * Runs the vendored money install, retrying a lost concurrent-install race: the install is * idempotent, so the loser just runs it again. Any other failure propagates on the first throw. */ export declare function installMoneyRetrying(install: () => Promise): Promise; export declare function rowToSaga(row: Record): Saga; export declare function rowToSubscription(row: Record): Subscription; export declare function rowToCheckpoint(row: Record): Checkpoint; export declare function parseJson(value: unknown): unknown; export declare function rowToOutbox(row: Record): OutboxMessage; export declare function rowToInbox(row: Record): InboxMessage; export declare function rowToPromoGrant(row: Record): PromoGrant; export declare function naturalDelta(account: AccountRef, row: Record): Amount; export {};