Skip to content

Instantly share code, notes, and snippets.

@dmurawsky
Created June 25, 2025 16:36
Show Gist options
  • Select an option

  • Save dmurawsky/b41a1400f675d765981511d691fb4b75 to your computer and use it in GitHub Desktop.

Select an option

Save dmurawsky/b41a1400f675d765981511d691fb4b75 to your computer and use it in GitHub Desktop.
A ledger system for event sourcing in TypeScript
export type TimeLedgerItem = {
amountPerMs: number;
/** The timestamp of when the ledger item was ended */
endedAt?: number;
};
export type SumLedgerItem = {
/** If the resource has been stored, this will tell you where */
storageMapContentPath?: string;
amount: number;
};
/** Type guard for checking if a ledger item is a TimeLedgerItem */
export const isTimeLedgerItem = (item: TimeLedgerItem | SumLedgerItem): item is TimeLedgerItem => "amountPerMs" in item;
export function ledgerAccumulator(currentTimestamp: number) {
return (acc: number, [timestamp, ledgerItem]: [string, TimeLedgerItem | SumLedgerItem]) => {
let amount = 0;
if (isTimeLedgerItem(ledgerItem)) {
amount =
ledgerItem.amountPerMs *
// endedAt could be in the future because we calculate it based on capacity
// so we use the current time if enededAt is in the future
((ledgerItem.endedAt ? Math.min(Date.now(), ledgerItem.endedAt) : currentTimestamp) - Number(timestamp));
} else {
amount = ledgerItem.amount;
}
return acc + amount;
};
}
export function getLedgerTotal(ledger: Record<string, TimeLedgerItem | SumLedgerItem>, currentTimestamp = Date.now()) {
return Object.entries(ledger).reduce(ledgerAccumulator(currentTimestamp), 0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment