Skip to content

Batch QUBIC Balances Endpoint #4

@sallymoc

Description

@sallymoc

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:

  1. 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).

  2. 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.

  3. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    🔖 Ready

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions