The Quantus browser extension (quantus/extension#14) is gaining a read-only wormhole balance. A wormhole address's System.Account balance is everything it ever received: an exit credits the exit account and records a nullifier, and nothing debits the wormhole address. What is still spendable is the deposits whose nullifier N(secret, transfer_count) has not been used. So a wallet needs, for each of its wormhole addresses, every Wormhole::NativeTransferred to it: transfer_count to compute the nullifier, amount to add up, and leaf_index for a later proof.
The chain has no reverse index from recipient to leaves (ZkTree::Leaves is keyed by leaf index). The mobile wallet asks Quantus's Subsquid (sqm.quantus.com), which tells Quantus which addresses belong to one person. This observer already stores every one of those events in chain_event, with the recipient in accounts[] under a GIN index. What's missing is a way to ask for them by recipient:
/v1/chains/{chain}/events/Wormhole/NativeTransferred pages through every deposit on the chain.
/v1/chains/{chain}/accounts/{address} returns one address at a time, mixed with all its other activity, newest first. A miner's reward address has tens of thousands of deposits interleaved with MinerRewarded.
What
GET /v1/chains/{chain}/wormhole/deposits?to=<addr>,<addr>,…&after=<height>:<event_index>&limit=<n>
to: up to 100 addresses, SS58 or 0x hex. A malformed one is a 400 that names it.
Deposits oldest first, so a client can cache what it has and resume from a cursor, with next set when there are more.
Each deposit: to (hex) and its SS58, amount as a decimal string (it is a u128), transfer_count, leaf_index, height, event_index, at.
The response carries indexed_from / indexed_to. A testnet still backfilling has a partial answer, and a client must be able to say so instead of showing a low balance as if it were complete. Clients can cross-check the count against the chain's Wormhole::TransferCount.
CORS: any origin, GET only, on this route alone. Browser-extension origins can't go on an allowlist, because Chrome's id depends on the install and Firefox's is a random per-install uuid. The data is public chain data and the route is read-only. The site's own allowlist is unchanged.
Not in scope
Nullifiers. Checking whether a deposit is spent means computing its nullifier from the secret. Sending nullifiers anywhere, even to our own infra, would let the recipient pair a deposit with its exit, so the client checks them against the chain itself.
## Why
The Quantus browser extension (quantus/extension#14) is gaining a read-only wormhole balance. A wormhole address's `System.Account` balance is **everything it ever received**: an exit credits the exit account and records a nullifier, and nothing debits the wormhole address. What is still spendable is the deposits whose nullifier `N(secret, transfer_count)` has not been used. So a wallet needs, for each of its wormhole addresses, every `Wormhole::NativeTransferred` to it: `transfer_count` to compute the nullifier, `amount` to add up, and `leaf_index` for a later proof.
The chain has no reverse index from recipient to leaves (`ZkTree::Leaves` is keyed by leaf index). The mobile wallet asks Quantus's Subsquid (`sqm.quantus.com`), which tells Quantus which addresses belong to one person. This observer already stores every one of those events in `chain_event`, with the recipient in `accounts[]` under a GIN index. What's missing is a way to ask for them by recipient:
- `/v1/chains/{chain}/events/Wormhole/NativeTransferred` pages through every deposit on the chain.
- `/v1/chains/{chain}/accounts/{address}` returns one address at a time, mixed with all its other activity, newest first. A miner's reward address has tens of thousands of deposits interleaved with `MinerRewarded`.
## What
`GET /v1/chains/{chain}/wormhole/deposits?to=<addr>,<addr>,…&after=<height>:<event_index>&limit=<n>`
- `to`: up to 100 addresses, SS58 or 0x hex. A malformed one is a 400 that names it.
- Deposits oldest first, so a client can cache what it has and resume from a cursor, with `next` set when there are more.
- Each deposit: `to` (hex) and its SS58, `amount` as a decimal string (it is a u128), `transfer_count`, `leaf_index`, `height`, `event_index`, `at`.
- The response carries `indexed_from` / `indexed_to`. A testnet still backfilling has a partial answer, and a client must be able to say so instead of showing a low balance as if it were complete. Clients can cross-check the count against the chain's `Wormhole::TransferCount`.
- **CORS: any origin, GET only, on this route alone.** Browser-extension origins can't go on an allowlist, because Chrome's id depends on the install and Firefox's is a random per-install uuid. The data is public chain data and the route is read-only. The site's own allowlist is unchanged.
## Not in scope
- **Nullifiers.** Checking whether a deposit is spent means computing its nullifier from the secret. Sending nullifiers anywhere, even to our own infra, would let the recipient pair a deposit with its exit, so the client checks them against the chain itself.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Why
The Quantus browser extension (quantus/extension#14) is gaining a read-only wormhole balance. A wormhole address's
System.Accountbalance is everything it ever received: an exit credits the exit account and records a nullifier, and nothing debits the wormhole address. What is still spendable is the deposits whose nullifierN(secret, transfer_count)has not been used. So a wallet needs, for each of its wormhole addresses, everyWormhole::NativeTransferredto it:transfer_countto compute the nullifier,amountto add up, andleaf_indexfor a later proof.The chain has no reverse index from recipient to leaves (
ZkTree::Leavesis keyed by leaf index). The mobile wallet asks Quantus's Subsquid (sqm.quantus.com), which tells Quantus which addresses belong to one person. This observer already stores every one of those events inchain_event, with the recipient inaccounts[]under a GIN index. What's missing is a way to ask for them by recipient:/v1/chains/{chain}/events/Wormhole/NativeTransferredpages through every deposit on the chain./v1/chains/{chain}/accounts/{address}returns one address at a time, mixed with all its other activity, newest first. A miner's reward address has tens of thousands of deposits interleaved withMinerRewarded.What
GET /v1/chains/{chain}/wormhole/deposits?to=<addr>,<addr>,…&after=<height>:<event_index>&limit=<n>to: up to 100 addresses, SS58 or 0x hex. A malformed one is a 400 that names it.nextset when there are more.to(hex) and its SS58,amountas a decimal string (it is a u128),transfer_count,leaf_index,height,event_index,at.indexed_from/indexed_to. A testnet still backfilling has a partial answer, and a client must be able to say so instead of showing a low balance as if it were complete. Clients can cross-check the count against the chain'sWormhole::TransferCount.Not in scope