Skip to content
Last updated

Tokens and balances

Anyone can deploy a token contract, and any contract can send something to your address. Vilna keeps token balances according to its verified list and your project's trust choices. The default notification filter uses those marks too, alongside the selected address's own actions. This page explains the two marks, what they switch on, how to read the catalog and how to add a contract of your own.

is_verified - the shared list is_trusted - your project's pick Balances follow the marks The noise filter uses marks

Why tokens need a mark

A catalog entry with status: supported means Vilna resolved the contract's name, symbol and decimals and can follow its transfers. It says nothing about whether the token is legitimate. Airdropped tokens with a familiar name, look-alike contracts and plain spam all resolve just fine. If every resolved token drove balances and alerts, a stranger could make your integration react by sending you anything.

So a token carries two independent marks:

  • is_verified - Vilna's shared list, the same for every project. It is maintained by hand for one exact contract on one exact chain. A name, a symbol or heavy transfer volume never earns it.
  • is_trusted - your project's own selection, set with one call and revoked with another.

Either mark is enough. The native coin of every network (ETH, BNB, BTC, TRX) is always in scope without a mark.

What the marks switch on

Balances. Vilna keeps balances for the native coins and for every token in your project's scope: verified ones and the ones you trusted. Reading a balance, or seeing a token move through your address, does not widen that scope. A token outside it has no balance rows at all.

Notifications. Every subscription carries is_noise_filtered, on by default. With it on, a notice fires only when one of the selected addresses supplies its own reason: it acted itself (as sender, caller, creator or owner), in which case the tokens involved do not matter and unfamiliar ones simply appear in the payload; or a native coin, a verified token or a trusted token moved on that address. Another address's action, trust or fee never qualifies yours. With the filter off, any activity that touches a selected address notifies, unfamiliar tokens included; that grants no trust and starts no balances. The events guide covers the filter in full.

Solana networks resolve tokens for the catalog and stop there: no balances and no notifications, whatever the marks say.

Reading the catalog

GET /tokens lists the catalog. scope decides how much of it you see:

Use scope=project for native, verified and trusted assets in your project, or scope=all (the default) for the full catalog. Narrow the results by chain_gid, search or a token tag through tag_id. A search match does not grant trust. The operation above provides the CatalogAsset schema, complete filters, limits and request examples.

A supported entry has resolved metadata; pending means the identity is known but not fully resolved; unsupported means the chain cannot serve it. Name, symbol and decimals are guaranteed for supported entries and may be partially known earlier.

There is no server-side filter for verified tokens alone. To list them, request scope=project and keep the entries whose is_verified is true, or filter the full catalog on that field.

Use decimals for the exact gid, not a symbol shared across contracts or chains. Keep base-unit strings exact with BigInt or an exact decimal library; converting them to Number can lose units. Authenticated invoice amounts are raw strings, unlike the structured transaction amounts. The invoice guide explains invoice amount representation.

For example, one token with decimals: 6 has this transaction amount:

{ "base": "1000000", "formatted": "1.0" }

Adding a token

Two calls. The first puts the contract in the catalog and resolves its metadata from the chain; the second marks it trusted for your project.

POST /tokens/{chain_gid}/{asset_path} with no body. The response carries the entry with status: supported; a contract that resolves as pending or unsupported answers 422 instead. A token already in the catalog comes back as 200.

POST /tokens/{chain_gid}/{asset_path}/actions/trust adds it to your project's selection. 404 means the token is not in the catalog yet; 422 means it is there but not supported.

Use a project key with api:asset:write for mutations and api:asset:read for catalog reads. Registration and trust are separate intents with separate Idempotency-Key values; save each key and the original inputs before sending. The operation pages above provide schemas and request examples.

After a lost response, retry with the same key and original parameters. Untrust is a separate intent and needs its own key. If replay is unavailable, reconcile catalog and trust state instead of automatically replacing the key. See Idempotency.

From that moment the token counts for your subscriptions, and balances for every address in the project, current and future, are initialized in the background. Nothing is sent for transactions that happened before: trusting a token creates no notification backlog.

POST /tokens/{chain_gid}/{asset_path}/actions/untrust removes your selection and answers 204. If no other mark keeps the token in scope, its balances stop and it drops out of your scope=project reads; it stays in the full catalog (scope=all). Trusting it again starts the balances from scratch rather than resuming the old ones.

The asset_path is the part of the CAIP-19 id after the chain:

Assetchain_gidasset_path
ETHeip155:1slip44:60
USDT on Ethereumeip155:1erc20:0xdAC17F958D2ee523a2206206994597C13D831ec7
USDT on Trontron:728126428trc20:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t

Token tags

A token tag is a named group of tokens inside a project, managed under GET /token-tags. Tags do not change trust; they exist so that GET /tokens?tag_id=… can return one group at a time, such as the stablecoins you accept.