Ledger
Interactive tools for exploring payment processing and reconciliation logic. All data is generated locally — no external APIs, no real transactions.
Next.js · TypeScript · React · Client-side Data Generation
Context
In payment operations, data rarely lines up cleanly. Provider records and internal ledgers drift apart — through timing differences, failed writes, rounding errors, or currency handling edge cases. Reconciliation is the process of finding and resolving those gaps before they become financial discrepancies.
These tools make that process concrete. The Transaction Timeline surfaces patterns across a simulated 30-day window. The Reconciliation Explorer runs a configurable matching algorithm across provider and ledger datasets, classifying every discrepancy by type. Both are fully interactive and run entirely in the browser.
How Reconciliation Works
The matching algorithm works by iterating over provider transactions and attempting to find a corresponding ledger entry by transaction ID. When a match is found, it checks two configurable conditions: whether the amounts are within a defined tolerance (defaulting to one cent), and whether currencies match. A match that fails either condition is classified as a mismatch rather than silently dropped.
Mismatches fall into four categories: missing from the ledger entirely, present in the ledger but absent from the provider feed, amount discrepancy within the same record, and currency mismatch. Each is surfaced separately because the remediation path differs — a missing ledger entry requires a write, an extra entry requires investigation, and an amount mismatch may indicate a fee was applied mid-transit.
for (const provider of providerTransactions) {
for (const ledger of ledgerEntries) {
if (usedLedgerIds.has(ledger.transactionId)) continue;
if (provider.id === ledger.transactionId) {
const amountDiff = Math.abs(provider.amount - ledger.amount);
const amountMatches = amountDiff <= options.amountTolerance;
const currencyMatches =
!options.currencyMatchRequired ||
provider.currency === ledger.currency;
if (amountMatches && currencyMatches) {
matches.push({ provider, ledger });
usedLedgerIds.add(ledger.transactionId);
matched = true;
break;
} else {
// ID matches but data doesn't — classify the mismatch type
mismatches.push({
type: !amountMatches ? "amount_mismatch" : "currency_mismatch",
providerTransaction: provider,
ledgerEntry: ledger,
details: `...`,
});
}
}
}
}Explore
Two tools, fully interactive. Data is freshly generated on each load.
Transaction Timeline
Explore and filter simulated transaction data across a 30-day window.
Showing 50 of 50 transactions
Kroger
Jul 15, 2026, 01:32 PM
$9454.15
Amazon
Jul 15, 2026, 11:39 AM
$6986.22
Lowe's
Jul 15, 2026, 05:29 AM
$370.20
Starbucks
Jul 14, 2026, 11:42 AM
$7546.86
Starbucks
Jul 14, 2026, 05:13 AM
$6586.06
Amazon
Jul 13, 2026, 12:02 PM
$10009.72
Amazon
Jul 13, 2026, 04:42 AM
$2905.56
Starbucks
Jul 13, 2026, 02:31 AM
$4946.47
Walmart
Jul 12, 2026, 02:16 PM
$2266.39
Costco
Jul 12, 2026, 10:24 AM
$1436.63
Costco
Jul 11, 2026, 11:11 PM
$1812.72
Costco
Jul 11, 2026, 09:00 AM
$3066.82
Home Depot
Jul 11, 2026, 06:17 AM
$364.31
Lowe's
Jul 11, 2026, 05:11 AM
$7292.69
Kroger
Jul 10, 2026, 07:04 PM
$8850.29
Target
Jul 10, 2026, 04:08 PM
$4345.60
Walgreens
Jul 9, 2026, 07:11 PM
$8613.50
Target
Jul 9, 2026, 05:53 PM
$2458.75
Costco
Jul 9, 2026, 10:06 AM
$4445.23
Costco
Jul 8, 2026, 07:46 PM
$597.88
Walgreens
Jul 8, 2026, 04:44 AM
$3748.23
Target
Jul 7, 2026, 04:24 PM
$4503.79
Target
Jul 6, 2026, 09:55 PM
$1469.52
Lowe's
Jul 6, 2026, 04:46 AM
$1728.07
Kroger
Jul 5, 2026, 03:29 AM
$5281.65
Amazon
Jul 4, 2026, 03:21 PM
$5608.85
Walgreens
Jul 3, 2026, 03:48 PM
$6872.24
Costco
Jul 2, 2026, 07:21 PM
$921.59
Kroger
Jun 30, 2026, 10:34 AM
$8706.79
Walgreens
Jun 29, 2026, 07:59 AM
$7973.56
Kroger
Jun 29, 2026, 05:24 AM
$7018.37
Home Depot
Jun 28, 2026, 02:28 AM
$7814.01
Best Buy
Jun 27, 2026, 12:52 AM
$2119.30
Kroger
Jun 26, 2026, 12:30 PM
$7602.99
Walgreens
Jun 26, 2026, 01:09 AM
$2544.54
Amazon
Jun 25, 2026, 05:58 PM
$726.79
Target
Jun 23, 2026, 07:53 PM
$6561.00
Lowe's
Jun 23, 2026, 03:29 AM
$5651.89
Kroger
Jun 22, 2026, 03:41 AM
$5127.47
Best Buy
Jun 22, 2026, 01:48 AM
$6910.62
Kroger
Jun 20, 2026, 01:13 AM
$533.70
Amazon
Jun 20, 2026, 01:10 AM
$1383.00
Target
Jun 20, 2026, 12:26 AM
$1443.30
Best Buy
Jun 19, 2026, 07:45 PM
$7007.91
Walgreens
Jun 19, 2026, 12:01 AM
$3685.20
Costco
Jun 18, 2026, 11:39 AM
$587.96
Amazon
Jun 17, 2026, 11:56 PM
$1020.23
Kroger
Jun 17, 2026, 05:46 PM
$6480.77
Starbucks
Jun 17, 2026, 07:20 AM
$2804.02
CVS
Jun 16, 2026, 09:01 PM
$3167.57
Reconciliation Explorer
Compare provider transaction data with internal ledger entries. Identifies matches and mismatches using configurable tolerance rules.
Provider Transactions
30
Ledger Entries
30
Matched
0
Mismatches
60
Missing in Ledger
30
Extra in Ledger
30
Mismatches
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Provider Transaction
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Ledger Entry
Reflections
The most useful design decision here was separating mismatch types rather than collapsing them into a single "error" state. In practice, a missing ledger entry, an amount discrepancy, and a currency mismatch each require a different remediation path — and surfacing them as distinct categories makes the tool actionable rather than just diagnostic.
A production version of this would replace the client-side mock data with a Postgres-backed event log, stream reconciliation results via Server-Sent Events as records are processed, and integrate with provider webhooks to trigger reconciliation runs automatically on settlement. The matching logic itself — the tolerance rules, the classification taxonomy — would remain largely the same.