Overview
After a Stealth Pool Note is written, the SDK publishes an X25519-AES ciphertext on-chain addressed either to the sender (self-burnable) or to the recipient (receiver-burnable). To find your burnable notes, the scanner:- Discovers every active stealth-pool tree.
- Loads scan progress from
client.utxoDataStoreand computes the unscanned ranges. - Fetches the encrypted note data for those ranges from the indexer.
- Tries to decrypt each ciphertext with your X25519 + viewing keys.
- Persists progress.
- Returns the successful decryptions, grouped by
(kind, source).
Usage
Return Value
Example: Run the scanner
Idempotent — call as often as you like
The scanner is idempotent: subsequent calls only fetch and decrypt new leaves since the last call. The cursor lives inclient.utxoDataStore.getScanProgress(treeIndex) / client.utxoDataStore.addScannedRange(treeIndex, start, end). Re-mounting the scanner factory does not reset state.
A typical browser app calls the scanner on every page load and on a 30s timer while the page is open.
How decryption works
The SDK derives your X25519 private key from the master seed, then for each note ciphertext:- Extracts the writer’s ephemeral X25519 public key from the ciphertext header.
- Computes an X25519 ECDH shared secret.
- Derives an AES-GCM key.
- Attempts to decrypt the payload.
- If decryption succeeds, reads the 12-byte domain separator and routes the note into the matching
(kind, source)bucket.
Custom indexer fetchers
If you are running a private indexer mirror, override the data fetchers viadeps:
fetchBatchMerkleProof is a separate dep on the burner — see Burning.)
Error Handling
An empty result (all buckets empty) is not an error — it means no notes addressable by your viewing keys exist in the trees the scanner walked. Errors are reserved for infrastructure failures.