All routes below require authentication and use the shared application envelope. A ledger row is an indexed movement, not native transaction finality.
| Method | Path | Result |
|---|---|---|
| GET | /api/ledger/player/{player_id}/page/{page} |
Existing Alpha transfer history |
| GET | /api/ledger/player/{player_id}/count |
Count with the same ownership/action filters |
| GET | /api/ledger/{tx_id} |
One ledger row by its numeric row ID, or null |
| GET | /api/ledger/player/{player_id}/transfer-source |
Exact sent leg matched to verified inclusion coordinates |
| GET | /api/ledger/list/all/page/{page} |
All ledger actions/denominations |
| GET | /api/ledger/list/player/{player_id}/page/{page} |
All movements at addresses currently owned by a player |
| GET | /api/ledger/list/address/{address}/page/{page} |
All movements at one literal address |
| GET | /api/ledger/stats |
30-day action/denomination volume; see analytics |
The existing history page and count select positive ualpha sent/received rows.
They use structs.asset_owner: vault and currently approved retained addresses belong
to the player; guild vaults remain guild assets. Counts and pages share that policy.
This is current-owner attribution, not a historical ownership snapshot at each event.
Pages are flat arrays ordered by time DESC, id DESC, with 100 rows per page.
Count returns data: {"count": ...}. Despite the route parameter name tx_id,
GET /api/ledger/{tx_id} looks up ledger.id, not a chain hash. Detail resolves
counterparty_player_id and counterparty_username through current ownership,
including a recipient’s vault.
Rows retain address, counterparty, denom, action, direction, time,
chain_id, tx_index, msg_index, event_index, and exact string id, amount_p
and block_height. amount is a display value; amount_p is the raw denomination
amount. Preserve complete denominations, including dotted synthetic or slash-bearing
names. Never tokenize them to recover an integer or assume every asset uses Alpha’s
six decimal places.
The bespoke history/count/detail methods read data and inventory readiness metadata
inside one consistent SQL snapshot. Inspect meta.data_ready and the specific
response boundary; a later /api/block cannot certify earlier history.
After verifying the original signed transaction’s committed code-0 result, request:
GET /api/ledger/player/{player_id}/transfer-source
Supply these URL-encoded query parameters; unknown parameters are rejected:
| Parameter | Contract |
|---|---|
chain_id |
structstestnet-111 in this integration |
block_height |
Positive exact decimal, within PostgreSQL signed bigint |
tx_index |
Exact nonnegative transaction index |
block_time |
Verified UTC block timestamp, ...Z, with up to 9 fractional digits |
address, counterparty |
Exact source/destination addresses from the committed message |
denom |
ualpha for this endpoint |
amount_p |
Positive exact raw coin amount |
msg_index, event_index |
Optional disambiguators; message index may be -1 |
The timestamp is truncated to microseconds to match the writer’s PostgreSQL encoding.
The query matches source time, chain, height/index, exact amount/denomination,
source/destination, sent/debit and current player ownership. It does not scan
history for a similar amount or guess a transaction hash.
The envelope may be successful while matching is incomplete. Check
meta.transfer_source.ready and required_height; reasons are
indexed_state_unavailable, not_indexed, not_found or ambiguous. Only exactly
one matching row is returned as ready. Missing/ambiguous history never authorizes a
replacement payment. Keep the original journal and reconcile it independently.
/list/ avoids collision with the single-row path. Catalogs include all actions and
denominations, default to 100 rows, accept a limit clamped to 1–10000 and order newest
first. Ledger catalogs do not support updated_since, after_id or since_seq.
Optional include_total=1 / include_meta=1 reads those values with the same page
snapshot, but its height-only stamp is not full transaction-readiness evidence.
Source-aware row idempotency uses (time, chain_id, tx_index, msg_index, event_index,
denom). One native transaction can emit several rows and several denominations;
legacy rows can lack source coordinates. Display row IDs and source-event coordinates
serve different purposes.
Synthetic ualpha.infused / ualpha.defusing current balances come from complete
native/stored claims, not the sum of historical ledger movements. Slashing, retained
stake and held unbonding make a historical sum unsuitable as current spendability.
Statistics are volume summaries and do not authorize transfers.
Verified against webapp 43bc1086 (LedgerManager, TransferSourceQuery and
TableReadManager), structs-pg 400e1c1 ownership/readiness/ledger identity, and the
recorded confirmed-transfer, ambiguity and exact-source integration fixtures.