/**
 * NeuroCoin ledger and per-window consumption tracking for borrowed traffic.
 *
 * Two jobs, deliberately in one module because they settle from the same event:
 *
 * 1. **Coins.** A grant with a coin entitlement spends against a balance. The
 *    balance itself lives on the grant (one source of truth); this module holds
 *    the entries and drives the deduction.
 * 2. **Window buckets.** How much of an account's 5h/7d window a grant has taken,
 *    keyed by that window's reset timestamp so the counter starts fresh when the
 *    window does. This is what makes a slice ceiling mean "a fifth of *this*
 *    window" rather than "a fifth, once, forever".
 *
 * **Why hold-then-settle.** Real usage is only known when the response finishes
 * — for a stream, at `message_delta`. A balance checked at admission and
 * deducted at completion lets N concurrent streams each pass the same check and
 * overspend by N-1 requests. So admission opens a *hold* for an estimate, the
 * available balance is `balance - Σ open holds`, and settlement replaces the
 * hold with the real figure. A crash loses in-flight holds, which is the safe
 * direction: the balance is only ever reduced by traffic that actually happened.
 *
 * @module proxy/shareLedger
 */
import type { ProxyShareGrant, ProxyShareGrantUsageSummary, ProxyShareHold, ProxySharePoolUsage, ProxyShareSettlement, ProxyShareUsage, ProxyShareWindowObservation } from "../types/index.js";
/** Normalized tokens per coin. */
export declare const TOKENS_PER_COIN = 1000;
export declare function initShareLedger(ledgerFilePath: string): void;
export declare function modelCoinWeight(model: string | undefined): number;
/** Convert real usage into coins. Pure — the pricing table is the whole story. */
export declare function usageToCoins(usage: ProxyShareUsage, model: string | undefined): number;
/**
 * What to hold at admission, before anything is known about the response.
 *
 * Intentionally rough: the hold exists to stop concurrent streams from each
 * spending the last coin, not to predict the bill. Settlement replaces it with
 * the real figure moments later.
 */
export declare function estimateHoldCoins(model: string | undefined, maxTokens: number | undefined): number;
/** Coins currently held against a grant by in-flight requests. */
export declare function heldCoins(grantId: string): number;
/**
 * Balance a new request may draw on: the stored balance minus what in-flight
 * requests have already claimed.
 */
export declare function availableCoins(grant: ProxyShareGrant): number;
export declare function openShareHold(grantId: string, coins: number, now?: number): ProxyShareHold;
/** Drop a hold without spending it — the request never reached the upstream. */
export declare function releaseShareHold(holdId: string | undefined): void;
/**
 * Record how much of an account's windows a borrowed request consumed.
 *
 * Never throws: a bookkeeping failure must not turn a response the borrower has
 * already received into an error.
 */
export declare function recordShareWindowDelta(observation: ProxyShareWindowObservation): Promise<void>;
/**
 * Charge a finished borrowed request against its grant and close the hold.
 *
 * Never throws, for the same reason as above.
 */
export declare function settleShareUsage(settlement: ProxyShareSettlement): Promise<number>;
/**
 * What a grant has taken from one account's current windows.
 *
 * Buckets whose reset timestamp no longer matches the account's are reported as
 * zero: they describe a window that has since rolled over.
 */
export declare function readShareWindowUsage(grantId: string, accountKey: string, currentSessionResetAt: number | null, currentWeeklyResetAt: number | null): Promise<{
    sessionFraction: number;
    weeklyFraction: number;
}>;
/**
 * What a grant has taken from the pool as a whole, normalised to one window.
 *
 * Summing the per-account fractions and dividing by the account count is what
 * makes a ceiling mean the same thing on a one-account pool and a ten-account
 * one. Without the division, `--max-slice 20` would silently grant 20% of every
 * credential — 200% of a single window's worth across ten accounts.
 *
 * Buckets whose reset timestamp no longer matches contribute zero: they
 * describe a window that has since rolled over.
 */
export declare function readSharePoolWindowUsage(grantId: string, accounts: ReadonlyArray<{
    accountKey: string;
    sessionResetAt: number | null;
    weeklyResetAt: number | null;
}>): Promise<ProxySharePoolUsage>;
/** Per-grant rollup across accounts, for `share status`. */
export declare function summarizeGrantUsage(grantId: string): Promise<ProxyShareGrantUsageSummary>;
/**
 * Apply a standing allowance for every period that has elapsed.
 *
 * Called opportunistically at admission — there is no timer, so a node that is
 * off across one or more refill boundaries pays them on its next borrowed
 * request. Paying only the newest period would quietly turn "100 a week" into
 * "100 whenever you next happen to ask", which is not what the operator wrote.
 *
 * `lastAt` advances by whole periods rather than to `now`, so the schedule stays
 * anchored to when the grant was issued instead of drifting later with every
 * catch-up. It advances past the periods the cap refused to pay as well — see
 * {@link MAX_REFILL_CATCHUP_PERIODS}.
 */
export declare function applyRefillIfDue(grant: ProxyShareGrant, now?: number): Promise<ProxyShareGrant>;
/** Drop all ledger state. Test isolation only. */
export declare function resetShareLedgerForTests(): void;
