Check a record on Stellar
Read an institution's latest coverage record straight from its registry with the Stellar CLI or the SDK, and tell covered from stale.
Any institution's record can be read straight from Stellar, with no Solva account and no request to the institution. A read is a simulated contract call. It costs nothing and writes nothing to the ledger.
Before you start
You need:
- the registry contract id (see Find a record),
- the Stellar CLI, or Node.js for the SDK,
- for the CLI, any funded Testnet key. The CLI needs an account to simulate a call, even a read.
To create and fund a key on Testnet:
stellar keys generate reader --network testnet --fundRead the latest record with the Stellar CLI
Call get_latest_proof
This reads the latest record from the Solstice Exchange example registry:
stellar contract invoke \
--id CDSQ35U2Y3VC44PJC6RRUJVCES2DLBWELDN32AIAEY4J35H4WBEKEUQW \
--network testnet \
--source-account reader \
-- get_latest_proofRead the result
The CLI notes that the call was simulated as read-only, then prints the record on one line. Formatted, it reads:
{
"l": "9000000",
"r": "16000000",
"root_h": "0c5c65b8b72f420da5a035470aa35ce6bce46a8309bd605cb10b9392d82c922e",
"timestamp": 1793803080
}The values above are the real output on 4 November 2026. Your output shows whatever the registry holds when you run the call.
What each field means
| Field | Meaning |
|---|---|
r | Reserves, the total of the reserve figures, in the asset's smallest unit. |
l | What is owed, the total of every customer balance in the committed list, in the same unit. |
root_h | The commitment root, which a holder checks their balance against. |
timestamp | The close time of the ledger that wrote the record, in Unix seconds (UTC). It comes from the Stellar network, not from the institution. |
Amounts are whole numbers in the asset's smallest unit, never fractions. The Kestrel Anchor and Solstice Exchange registries count US dollars in cents, so 16000000 is 160,000.00 and 9000000 is 90,000.00. Harbor Wallet's registry counts USDC in its seven-decimal unit, so 200000000 is 20 USDC. The timestamp 1793803080 is 14:38:00 UTC on 4 November 2026.
Coverage here is 16,000,000 divided by 9,000,000, or 177.77 percent, cut off at two decimal places.
The registry writes a record only after the proof behind it passes every check on chain, including that reserves are at least what is owed, so every value you read has already been checked. For what a record proves and does not prove, see What a record shows.
Tell covered, short and stale
Public record pages Coming soon show an asset in one of three statuses. The registry stores no status, so from the registry alone you work them out as follows.
| Status | What you see in the registry |
|---|---|
| Covered | A record whose timestamp falls inside the expected window. Its r is always at least its l. |
| Short | No new record. A cycle with reserves below what is owed is refused, so nothing is written. |
| Stale | No new record inside the expected window. The latest timestamp keeps getting older. |
Set the expected window from the institution's schedule, such as a day for daily cycles or an hour for hourly ones. Subtract the record's timestamp from the current time. If the gap is longer than the window you accept, treat coverage as unknown.
From the contract alone, a short day and a missed day look the same, because in both the latest record gets older. Treat both as not covered for that day. Public record pages show short with the size of the gap, taken from the refused cycle.
Read the latest record with the SDK
The TypeScript SDK reads the same contract. getOnChainLatestProof calls get_latest_proof on the registry and returns the record with amounts as decimal strings.
The SDK lives in the Solva repository as @solva/sdk-ts, with @stellar/stellar-sdk version 16 as a peer dependency. The published npm package Coming soon carries the same calls.
import { Solva } from "@solva/sdk-ts";
const solva = new Solva({
network: "testnet",
tenant: "22222222-2222-2222-2222-222222222222",
endpoints: { contractId: "CDSQ35U2Y3VC44PJC6RRUJVCES2DLBWELDN32AIAEY4J35H4WBEKEUQW" },
});
const record = await solva.getOnChainLatestProof();
console.log(record);tenant is the institution's id in Solva. When you set contractId, the SDK reads the contract directly and makes no call to Solva's API. On testnet, the SDK reads through https://soroban-testnet.stellar.org.
The result:
{
"rootHash": "0c5c65b8b72f420da5a035470aa35ce6bce46a8309bd605cb10b9392d82c922e",
"reservesTotal": "16000000",
"liabilitiesTotal": "9000000",
"timestamp": 1793803080
}These are the contract's fields under clearer names. Read the amounts with BigInt, never as floating-point numbers, so large balances stay exact. If the read fails, the SDK throws a ChainError.
Check a past record
Each record has a proof id, starting at 1 and rising by one with each record. get_proof returns the record with that id:
stellar contract invoke \
--id CDSQ35U2Y3VC44PJC6RRUJVCES2DLBWELDN32AIAEY4J35H4WBEKEUQW \
--network testnet \
--source-account reader \
-- get_proof --id 1{
"l": "9000000",
"r": "16000000",
"root_h": "0c5c65b8b72f420da5a035470aa35ce6bce46a8309bd605cb10b9392d82c922e",
"timestamp": 1783031356
}get_latest_proof does not return the proof id. The latest id is the highest id that get_proof answers. To pull every record in order, see For auditors.
When a read fails
A registry answers with a contract error number when it cannot return a record.
| Error | Name | What it means for a reader |
|---|---|---|
| 5 | ProofNotFound | No record has that id. From get_latest_proof, the registry has no record yet. |
| 2 | NotInitialized | The contract was never set up as a registry. |
The CLI shows the error in the simulation output:
error: transaction simulation failed: HostError: Error(Contract, #5)The registry keeps each record readable for up to 30 days ahead, and a read renews that when fewer than 7 days remain. A record that nobody reads for longer can be archived by the network. A read of an archived record fails until someone restores the entry.
Next: Check a balance was counted.