Skip to main content

Note scanning & wallet reconstruction

Because Mersennet never stores a plaintext balance for you, your wallet rebuilds private state locally. It scans the encrypted notes it is allowed to decrypt, drops the ones it has already spent, and sums what remains. There is no central indexer of your funds.

The scan-and-reconstruct workflowโ€‹

flowchart TD
Fetch["Fetch encrypted notes (prime_viewNotes / prime_getShieldedNotes)"] --> Decrypt["Decrypt with viewing material"]
Decrypt --> Derive["Derive each note's nullifier"]
Derive --> Filter["Drop notes whose nullifier is in the spent set"]
Filter --> Sum["Sum remaining notes per asset"]
Sum --> Balance["Reconstructed balances"]
  1. Fetch the encrypted notes the wallet (or a grantee) is authorized to see.
  2. Decrypt each note with the owner's or grantee's viewing material.
  3. Derive nullifiers for the decrypted notes.
  4. Filter out spent notes by checking each nullifier against the on-chain spent-nullifier set.
  5. Sum the unspent notes per asset to get the current balance.

SDK primitivesโ€‹

The TypeScript SDK ships the full pipeline so a wallet does not implement crypto by hand:

HelperPurpose
scanGrantedNotesDecrypt the notes a viewing grant authorizes.
defaultNullifierDeriverDerive a note's nullifier deterministically.
reconstructPortfolioSum unspent notes into per-asset balances.
scanAndReconstructBalancesEnd-to-end: scan, derive, filter spent, and reconstruct in one call.
import { scanAndReconstructBalances } from '@prime-chain/sdk';

const portfolio = await scanAndReconstructBalances({
encryptedNotes, // from prime_viewNotes / prime_getShieldedNotes
viewingMaterial, // owner or grantee material
spentNullifiers, // from the chain's nullifier set
});

console.log(portfolio.balances); // per-asset totals, spent notes excluded

Why nullifiers matter hereโ€‹

A note you received may already have been spent. The only way to know โ€” without a trusted server tracking your account โ€” is to derive each note's nullifier and check it against the public spent-nullifier set. Notes whose nullifier is present are excluded from the balance. This is the same primitive that prevents double-spends in shielded accounts, reused on the read path.

Positions and open ordersโ€‹

Trading state is reconstructed the same way, over the wallet's local order and fill records:

  • reconstructPositions โ€” net positions per market.
  • reconstructOpenOrders โ€” resting open orders per market.

These power both your own wallet view and grant-gated selective disclosure reads. See the Shielded SDK for the complete API.