Every amount, fiat and crypto
NUMERIC(38,0)
Integers all the way down, at every layer including this page
Per movement of money
2 rows
Double entry and append only, so a balance is a sum I can rebuild
A quote stays good for
15 minutes
Locked when the payment is created, so the price cannot move
Before a webhook dead letters
7 attempts
Backing off from ten seconds to six hours, then it waits for a replay
How a payment works
Four steps, from the till to the merchant's balance.
A shop asks for 10.50 GEL
One POST with an idempotency key. A retry returns the first response instead of charging twice.
Oathgate quotes and locks
Converts at the live rate, holds it for 15 minutes, and derives an address used by this payment alone.
The chain is watched
Every transaction to that address is recorded, so the exact amount received is known, including a customer who sends too little or too much.
The merchant is credited
At the confirmation threshold the balance moves and a signed webhook goes out, so the shop can mark the order paid without asking.
The threshold is 1 confirmation. A confirmation is not a second opinion, it is a price: reversing the payment now means rebuilding that many blocks faster than everybody else together, and that is already far more than a coffee is worth stealing. Six blocks on a ten minute chain is an hour of a customer standing at a counter.
The parts that are hard to get right
A payment gateway is not a CRUD app with a status column. These are the pieces that decide whether it can be trusted with money.
Double entry, append only
Every movement is two rows that sum to zero, and the balance is a projection I can rebuild from them at any time. Undoing a reorg writes a compensating pair rather than deleting history.
Correct under concurrency
Settlement takes a row lock on the balance inside the transaction. A test fires fifty simultaneous confirmations at one payment and asserts exactly one ledger pair exists.
No float touches money
Fiat is integer minor units, crypto is integer base units, both NUMERIC(38,0) in Postgres. Even this dashboard formats amounts by shifting digits rather than dividing.
Events survive a crash
The event row is written in the same transaction as the ledger, then relayed separately. A process dying between commit and publish cannot lose a merchant notification.
Watch one settle, end to end
Create a payment, pay it, and watch the status move while the ledger entries appear and the webhook fires. Then reverse it and watch the compensating pair get written.
