Skip to main content

Build an Asset Dashboard (NAV, Supply, Balance, Holders)

In this section, you'll build an asset dashboard that will show live metrics for an asset (fungible marker or non-fungible scope), incl.:

  • Latest NAV and NAV events
  • Total supply (denom) and holders
  • Balances (by address)
  • Transfer activity (paged; great for tables/audit)

Replace in all snippets:

  • {denom} → your token denom (e.g., ntesting)
  • {address} → a Bech32 address (tp1… testnet / pb1… mainnet)
  • {SCOPE_ID} → scope identifier (bech32 scope address or UUID)

Markers (Fungible)

List markers (optional overview)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/all"

Marker details (state, permissions, etc.)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/detail/\{denom\}"

Tip: For the convenience view you can also use: GET "$PROV_REST_BASE/marker/{denom}"

Total supply (by denom)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/supply/by_denom?denom=\{denom\}"

Holders (addresses)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/holding/\{denom\}"

(Alternate view via bank module)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/denom_owners/\{denom\}"

For large supplies, prefer Token Holders (Plus) with pagination.cursor for infinite-scroll tables.

Combining data for advanced metrics

To compute advanced metrics like "% of supply per address" or to identify restricted holders, you can combine data from multiple endpoints:

  1. Fetch Holders: Use the Query_Holding or Query_DenomOwners API to get a list of addresses holding the token. Example:
Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/holding/\{denom\}"

2. Fetch Balances: Use the Query_AllBalances or Query_SpendableBalanceByDenom API to get the balance of each holder.

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/balances/\{address\}"

3. Combine data:

For each holder, calculate their percentage of the total supply: % of Supply = (Holder's Balance / Total Supply) * 100

Use the Query_SupplyOfQuery API to fetch the total supply:

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/supply/by_denom?denom=\{denom\}"

4. Identify restricted holders (if applicable):

If the marker enforces attributes, use the Query_Holding API to identify restricted holders based on their attributes.

Example workflow:

  • Fetch all holders using Query_Holding.
  • For each holder, fetch their balance using Query_AllBalances.
  • Fetch the total supply using Query_SupplyOfQuery.
  • Calculate the percentage of supply for each holder and flag restricted holders if necessary.

Token holders

Plus; cursor-paged with amounts

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_PLUS_BASE/v1/asset/holders/\{denom\}"

Denom metadata (name/symbol/units)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/denoms_metadata/\{denom\}"
Code snippet
# Module view
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/marker/v1/netassetvalues/\{denom\}"

Tip: There's also a convenience path: GET "$PROV_REST_BASE/marker/{denom}/nav"

For the headline card use: GET /v1/asset/nav-events/latest?denom={denom}; for the chart use: GET /v1/asset/nav-events?denom={denom} with cursor pagination.

Plus view

Filterable, cursor-paged events:

Code snippet
# All NAV events for a denom (add ?startTime=...&endTime=... as needed)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_PLUS_BASE/v1/asset/nav-events?denom=\{denom\}"

# Latest NAV snapshot (e.g., for "headline" card)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_PLUS_BASE/v1/asset/nav-events/latest?denom=\{denom\}"

SPEC FOR ALL NAV EVENTS→

SPEC FOR LATEST NAV →

Scopes (Non-Fungible)

Scope details (base view)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/metadata/scope/\{SCOPE_ID\}"

Ownership & Value ownership (counts & lists)

Code snippet
# Scopes owned by an address (appears in owners list)
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/metadata/v1/ownership/\{address\}"

# Scopes where address is the value_owner_address
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/metadata/v1/valueownership/\{address\}"

SPEC OWNED BY ADDRESS →

SPEC ADDRESS IS VALUE_OWNER_ADDRESS→

Scope NAV (time-series)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/provenance/metadata/v1/netassetvalues/\{SCOPE_ID\}"

Cross-asset widgets (Balances & Transfers)

Balances (for any address)

Code snippet
# All balances for an address
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/balances/\{address\}"
Code snippet
# Spendable balance for a denom
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_REST_BASE/cosmos/bank/v1beta1/spendable_balances/\{address\}/by_denom?denom=\{denom\}"

For balances: Consider also showing the Plus aggregate for balances when you want price/fiat fields and first/last touch metadata:

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_PLUS_BASE/v1/addresses/\{address\}/balance/details"

Transfer activity (paged; ideal for tables)

Code snippet
curl -s -H "Authorization: Bearer $PROV_API_TOKEN" \
"$PROV_PLUS_BASE/v1/asset/transfer-events?recipient=\{address\}&denom=\{denom\}"
# Add ?sender=..., ?before=..., ?after=..., ?limit=... as needed for pagination

Notes & tips

  • Pick one base per widget: use the marker module view for supply/holders/state and the convenience /marker/{denom} or /marker/{denom}/nav when you need a single-object fetch. Keep your UI code consistent.
  • Pagination & caching: transfer-events is cursor-paged; cache your last cursor and poll incrementally for live tables. Addresses for holder rows: combine holders + balances to compute % of supply per address and to flag restricted holders if your marker enforces attributes.

Common Error tips

  • 0 holders returned? You may be querying bank owners for a restricted marker—use marker holding instead.
  • NAV empty on module path? If you publish NAV via Plus only, read /v1/asset/nav-events / /latest.