/** * DataStore — local JSON store at ~/.fourmm/data/. * * Responsibilities: * - Persist token metadata, pool info, transaction history, holdings, balances * - Atomic writes (write .tmp, rename) to avoid half-written files * - Memory cache per key with TTL (default 30s) * * What it does NOT do: * - Cross-process locking. CLI is single-process; parallel invocations * can race on writes. If Week 3 Router daemons need parallel writes we * add a lockfile then. * - Pretty printing control / schema migration (we'll version if needed). * * Public surface is a class with a singleton accessor so tests can inject * a fresh instance. Paths come from datastore/paths.ts which reads HOME * lazily, so redirecting HOME per test works. */ import { MemoryCache } from './cache.js'; import type { BalancesFile, BnbPriceFile, HoldingsFile, PoolInfoFile, TokenInfoFile, TransactionRecord, TransactionsFile, WalletBalance, WalletHolding } from './types.js'; import type { Address } from 'viem'; export * from './types.js'; export { MemoryCache } from './cache.js'; export declare class DataStore { readonly cache: MemoryCache; constructor(ttlMs?: number); getTokenInfo(ca: Address): TokenInfoFile | null; saveTokenInfo(info: TokenInfoFile): void; getPoolInfo(ca: Address): PoolInfoFile | null; savePoolInfo(info: PoolInfoFile): void; getTransactions(ca: Address, groupId: number): TransactionsFile | null; /** * Append a transaction to the group's history, deduped by txHash. * Always reads fresh from disk (no cache) to avoid losing a concurrent append. */ appendTransaction(ca: Address, groupId: number, tx: TransactionRecord): void; getHoldings(ca: Address, groupId: number): HoldingsFile | null; /** * Upsert a single wallet's holding. * Merges with existing (by walletAddress); creates the file if missing. */ updateHolding(ca: Address, groupId: number, wallet: Address, patch: Partial): void; getBalances(ca: Address, groupId: number): BalancesFile | null; /** * Partial upsert of a single wallet's balance. * * IMPORTANT: patch semantics — any field you DON'T pass keeps its previous * value. This avoids the bug where a BNB-only refresh would clobber a * stored tokenBalance. `updatedAt` is always bumped to now. * * If the wallet has no existing row, missing fields default to 0. */ updateBalance(ca: Address, groupId: number, walletAddress: Address, patch: Partial>): void; /** * Batch variant: apply a list of patches in one file write. * Each patch must include `walletAddress` so we know which row to merge. */ updateBalancesBatch(ca: Address, groupId: number, patches: Array<{ walletAddress: Address; } & Partial>>): void; getBnbPrice(): BnbPriceFile | null; saveBnbPrice(priceUsd: number): void; /** * List all token CA directories we have data for. * * Excludes `NATIVE_BNB` (the sentinel CA used for BNB transfer history) so * callers iterating "for each known token" don't hit version=0 reverts on * the zero address. */ listTokens(): Address[]; /** * List the groups that have native BNB transfer history. * Separate from `listTokens` so downstream monitor/PnL code can treat * BNB history distinctly from token holdings. */ listNativeBnbGroups(): number[]; listGroups(ca: Address): number[]; /** Ensure the group directory exists (useful before running a session) */ ensureGroupDir(ca: Address, groupId: number): void; } /** Get the global DataStore. Tests that need isolation should use `new DataStore()`. */ export declare function getDataStore(): DataStore; /** Reset the singleton (test helper) */ export declare function resetDataStore(): void; //# sourceMappingURL=index.d.ts.map