Context
The wallet app currently fetches balance data for multiple addresses via two qli endpoints. Both are being deprecated and we need an aggregation endpoint to replace them.
The existing RPC live API only supports single-address queries (GET /live/v1/balances/{id}), which forces the wallet to make N requests for N seeds. We need a batch endpoint that accepts multiple identities in a single request.
Reference: The POST /aggregation/v1/getCurrentIpoBids endpoint is already live and follows the same request pattern ({ "identities": [...] }).
Current qli endpoints being replaced
1. CurrentBalance (rich data with transactions)
POST https://api.qubic.li/Wallet/CurrentBalance
Content-Type: application/json
Authorization: Bearer <jwt-token>
["IDENTITY_1", "IDENTITY_2"]
Response (BalanceResponse[]):
[
{
"computorIndex": null,
"isComputor": false,
"publicId": "BZBQFLLBNCXEMGLOBHUVFTLUPLVCPQUASSILFABOFFBCADQSSUPNWLZBQEXK",
"currentEstimatedAmount": 1500000000,
"epochBaseAmount": 1490000000,
"epochChanges": 10000000,
"baseDate": "2026-03-20T00:00:00Z",
"transactions": [
{
"id": "oxjqnfchpjmkkbdgkweonqmpofcuxjsxbbknpebdiiypcflmhfaaxrpgejij",
"sourceId": "BZBQFLLBNCXEMGLOBHUVFTLUPLVCPQUASSILFABOFFBCADQSSUPNWLZBQEXK",
"destId": "EPYWDREDNLHXOFYVGQUKPHJGOMPBSLDDGZDPKVQUMFXAIQYMZGEHPZTAAWON",
"amount": 10000000,
"status": "Success",
"created": "2026-03-22T14:30:00Z",
"stored": "2026-03-22T14:30:01Z",
"staged": "2026-03-22T14:30:02Z",
"broadcasted": "2026-03-22T14:30:03Z",
"confirmed": "2026-03-22T14:30:10Z",
"statusUpdate": "2026-03-22T14:30:10Z",
"targetTick": 22451800,
"isPending": false,
"moneyFlow": true,
"type": 0
}
]
}
]
2. NetworkBalances (simple balance + tick)
POST https://api.qubic.li/Wallet/NetworkBalances
Content-Type: application/json
Authorization: Bearer <jwt-token>
["IDENTITY_1", "IDENTITY_2"]
Response (NetworkBalance[]):
[
{
"publicId": "BZBQFLLBNCXEMGLOBHUVFTLUPLVCPQUASSILFABOFFBCADQSSUPNWLZBQEXK",
"amount": 1500000000,
"tick": 22451873,
"reportingNodes": ["127.0.0.1"]
},
{
"publicId": "EPYWDREDNLHXOFYVGQUKPHJGOMPBSLDDGZDPKVQUMFXAIQYMZGEHPZTAAWON",
"amount": 250000,
"tick": 22451873,
"reportingNodes": ["127.0.0.1"]
}
]
How the wallet displays the QUBIC balance
The balance shown on the dashboard comes from two sources with a fallback logic:
-
Primary source: NetworkBalances — The amount field is stored per seed along with its tick. This is the confirmed on-chain balance and is the value displayed on the dashboard when available (getBalance() reads seed.balance which is set by updateBalance() from NetworkBalances).
-
Fallback: CurrentBalance — If a seed has no balanceTick yet (i.e., NetworkBalances hasn't returned data for it), the wallet falls back to currentEstimatedAmount from CurrentBalance (via getDeprecatedBalance()). This is a transitional fallback for when the seed was just added.
-
Epoch change indicator — The +/- delta shown below the balance is computed as: seed.balance (from NetworkBalances) - epochBaseAmount (from CurrentBalance). This requires data from both endpoints.
From CurrentBalance
| Field |
Used |
How |
publicId |
Yes |
Match response to seed |
currentEstimatedAmount |
Yes |
Fallback balance display when NetworkBalances hasn't returned data yet |
epochBaseAmount |
Yes |
Used to compute epoch change: networkBalance - epochBaseAmount (the +/- indicator on the dashboard) |
transactions[] |
Yes (being removed) |
Currently flattened across all identities and used as the pending/recent transaction list in the balance view. Each transaction includes status tracking (Pending, Success, Failed), and transactions already present in the archiver are de-duplicated client-side. Note: We are refactoring the wallet to replace this with local pending transaction tracking + archiver data, so this field will no longer be needed. See transaction fields below for current structure |
computorIndex |
No |
Not used by the wallet |
isComputor |
No |
Not used by the wallet |
epochChanges |
No |
Not used directly (wallet computes it from balance - epochBaseAmount) |
baseDate |
No |
Not used by the wallet |
From NetworkBalances
| Field |
Used |
How |
publicId |
Yes |
Match response to seed |
amount |
Yes |
Primary balance displayed on the dashboard, stored per seed |
tick |
Yes |
Staleness check: wallet only updates if tick is higher than previously stored tick |
reportingNodes |
No |
Not used by the wallet |
Transaction fields
| Field |
Used |
How |
id |
Yes |
Transaction identifier, explorer links, de-duplication with archiver |
sourceId |
Yes |
Sender identity, displayed in UI |
destId |
Yes |
Receiver identity, displayed in UI, used to detect SC calls |
amount |
Yes |
Transfer amount |
status |
Yes |
"Success", "Failed", or "Pending" — drives the status icon in the balance view |
created |
Yes |
Displayed as transaction date |
targetTick |
Yes |
Displayed, used for repeat-transaction logic and sorting |
isPending |
Yes |
Controls pending indicator in UI |
moneyFlow |
Yes |
Whether money actually moved (confirmed on-chain) |
type |
Yes |
Transaction input type (0 = transfer, 1 = SC call), used for repeat-transaction filtering |
inputHex |
Yes |
Hex-encoded payload for SC calls (used to parse asset transfer details) |
price |
Yes |
IPO bid price (only present for IPO bid transactions) |
quantity |
Yes |
IPO bid quantity (only present for IPO bid transactions) |
stored |
No |
Not used by the wallet |
staged |
No |
Not used by the wallet |
broadcasted |
No |
Not used by the wallet |
confirmed |
No |
Not used by the wallet |
statusUpdate |
No |
Not used by the wallet |
Requirements
- The wallet polls this every ~60 seconds for all seeds (typically 1-10 identities per request)
- The tick-based staleness check is critical: the wallet ignores balance updates where the tick is lower than the last stored tick
- To use the new function available in QUtil to fetch up to 16 identities balance https://github.com/qubic/core/blob/main/src/contracts/QUtil.h#L1585
epochBaseAmount is essential for the epoch change indicator on the dashboard
transactions are currently used for the pending/recent transaction list in the balance view, but we are refactoring to replace this with local pending transaction tracking + archiver data — so this field will no longer be needed by the wallet
- No authentication should be required (public data)
Context
The wallet app currently fetches balance data for multiple addresses via two qli endpoints. Both are being deprecated and we need an aggregation endpoint to replace them.
The existing RPC live API only supports single-address queries (
GET /live/v1/balances/{id}), which forces the wallet to make N requests for N seeds. We need a batch endpoint that accepts multiple identities in a single request.Reference: The
POST /aggregation/v1/getCurrentIpoBidsendpoint is already live and follows the same request pattern ({ "identities": [...] }).Current qli endpoints being replaced
1. CurrentBalance (rich data with transactions)
Response (
BalanceResponse[]):[ { "computorIndex": null, "isComputor": false, "publicId": "BZBQFLLBNCXEMGLOBHUVFTLUPLVCPQUASSILFABOFFBCADQSSUPNWLZBQEXK", "currentEstimatedAmount": 1500000000, "epochBaseAmount": 1490000000, "epochChanges": 10000000, "baseDate": "2026-03-20T00:00:00Z", "transactions": [ { "id": "oxjqnfchpjmkkbdgkweonqmpofcuxjsxbbknpebdiiypcflmhfaaxrpgejij", "sourceId": "BZBQFLLBNCXEMGLOBHUVFTLUPLVCPQUASSILFABOFFBCADQSSUPNWLZBQEXK", "destId": "EPYWDREDNLHXOFYVGQUKPHJGOMPBSLDDGZDPKVQUMFXAIQYMZGEHPZTAAWON", "amount": 10000000, "status": "Success", "created": "2026-03-22T14:30:00Z", "stored": "2026-03-22T14:30:01Z", "staged": "2026-03-22T14:30:02Z", "broadcasted": "2026-03-22T14:30:03Z", "confirmed": "2026-03-22T14:30:10Z", "statusUpdate": "2026-03-22T14:30:10Z", "targetTick": 22451800, "isPending": false, "moneyFlow": true, "type": 0 } ] } ]2. NetworkBalances (simple balance + tick)
Response (
NetworkBalance[]):[ { "publicId": "BZBQFLLBNCXEMGLOBHUVFTLUPLVCPQUASSILFABOFFBCADQSSUPNWLZBQEXK", "amount": 1500000000, "tick": 22451873, "reportingNodes": ["127.0.0.1"] }, { "publicId": "EPYWDREDNLHXOFYVGQUKPHJGOMPBSLDDGZDPKVQUMFXAIQYMZGEHPZTAAWON", "amount": 250000, "tick": 22451873, "reportingNodes": ["127.0.0.1"] } ]How the wallet displays the QUBIC balance
The balance shown on the dashboard comes from two sources with a fallback logic:
Primary source:
NetworkBalances— Theamountfield is stored per seed along with itstick. This is the confirmed on-chain balance and is the value displayed on the dashboard when available (getBalance()readsseed.balancewhich is set byupdateBalance()from NetworkBalances).Fallback:
CurrentBalance— If a seed has nobalanceTickyet (i.e., NetworkBalances hasn't returned data for it), the wallet falls back tocurrentEstimatedAmountfrom CurrentBalance (viagetDeprecatedBalance()). This is a transitional fallback for when the seed was just added.Epoch change indicator — The +/- delta shown below the balance is computed as:
seed.balance (from NetworkBalances) - epochBaseAmount (from CurrentBalance). This requires data from both endpoints.From CurrentBalance
publicIdcurrentEstimatedAmountepochBaseAmountnetworkBalance - epochBaseAmount(the +/- indicator on the dashboard)transactions[]Pending,Success,Failed), and transactions already present in the archiver are de-duplicated client-side. Note: We are refactoring the wallet to replace this with local pending transaction tracking + archiver data, so this field will no longer be needed. See transaction fields below for current structurecomputorIndexisComputorepochChangesbalance - epochBaseAmount)baseDateFrom NetworkBalances
publicIdamounttickreportingNodesTransaction fields
idsourceIddestIdamountstatus"Success","Failed", or"Pending"— drives the status icon in the balance viewcreatedtargetTickisPendingmoneyFlowtypeinputHexpricequantitystoredstagedbroadcastedconfirmedstatusUpdateRequirements
epochBaseAmountis essential for the epoch change indicator on the dashboardtransactionsare currently used for the pending/recent transaction list in the balance view, but we are refactoring to replace this with local pending transaction tracking + archiver data — so this field will no longer be needed by the wallet