Skip to content
Testnet only: a reference implementation, not a production service.Tokens and bank transfers here are simulated and have no value.

Finality and reconciliation

A transfer isn't final when it is submitted; it becomes final when a ledger closes with it inside. This page explains that boundary, and how the issuer notices when the chain and the ledger disagree.

When a transfer is final

A transfer is final, and credited, on the first closed ledger that contains its transaction. Until that ledger closes, the transaction is only submitted; it can still expire and be rebuilt.

Each signed envelope moves through its own small state machine: built → signed → submitted → included or expired. A retry resubmits the same signed envelope until it is included or expires; nothing is rebuilt early.

After max_time passes, a lookup by hash decides the outcome: included if the transaction is on chain, or expired if it isn't found and the latest ledger's close time is past max_time. Only a confirmed expired allows a rebuild with a new sequence number.

Time bounds

An envelope is built with min_time = now − 30 s and max_time = now + 60 s, a 90-second window that never exceeds the signer's 120-second limit.

The network checks those bounds against the ledger close time, which trails wall-clock time by a few seconds. That is why min_time = now is rejected as tx_too_early; the shared helper pads the start backwards so a fresh envelope is still valid when it reaches a ledger.

Watching the chain

The watcher polls the Platform asset's contract events from a stored cursor. Each event is inserted once, keyed by the RPC event id, so a replay changes nothing. A to_muxed_id in an event is matched to an open redeem; one that names a deposit route goes to suspense in Phase 1.

The watcher also stores the network passphrase and the last ledger close time. If the sequence goes backwards or the passphrase changes, it halts, pauses minting and raises a reset alert. Account changes that don't appear as events are caught by comparing account snapshots on each poll. That comparison does not yet cover signers or thresholds.

Reconciliation

Reconciliation compares what the ledger says with what the chain and the rails say. It runs every five minutes and on demand:

CheckOn break
On-chain supply against supply_expectedSev-1, pause mints
supply_expected plus in-flight against reservesSev-1, pause mints
Ledger customer fiat against the rail balanceWarning, tracked as in-transit
Reserve source freshnessWarning

A break that pauses mints waits for an operator to resume them, with a reason on the audit log.

Endpoints

Edit on GitHub