Skip to main content

NoteManager

The NoteManager is the local index of your notes: what you have, each note's status, and the discovery cursor. It is held in the session's storage adapter, which you configure. Storage is not configured by default, so without a persistentStorage config the index lives in memory only and is lost on reload.

Note status states

INACTIVE A draft or unclaimed note the session is aware of but cannot yet spend. The typical case is a recipient-side draft generated as part of a send, before the corresponding commitment lands on-chain or is imported.
PENDING The note exists locally but isn't spendable yet: a deposit is awaiting ASP attestation, and a transact output is awaiting chain confirmation.
ACTIVE The note is attested and confirmed, so it is spendable.
SPENT The nullifier has been published on-chain, and the note can't be re-spent.
REJECTED The ASP explicitly refused the deposit's label. The note is recoverable via ragequit.
EXITED The note has been ragequit and the public exit completed.

Status transition matrix

The legal transitions are:

FromToTrigger
INACTIVEPENDINGcommitment observed on-chain
INACTIVEEXITEDragequit
PENDINGACTIVEattestation lands
PENDINGACTIVEdiscoverable-mode re-decryption
PENDINGREJECTEDattestation refuses
PENDINGEXITEDragequit
ACTIVESPENTtransact submission lands
ACTIVEEXITEDragequit
ACTIVEREJECTEDlabel revoked on the ASP after activation
REJECTEDEXITEDragequit

Illegal transitions throw InvalidStatusTransitionError. State can still drift if note updates aren't persisted before reload. The most common symptom is re-running discovery flipping SPENT back to ACTIVE. If you see balances refuse to decrease across a page reload, call session.discoverNotes(), which flushes the NoteManager internally. See Failure modes.

Persistence

Choose one of these adapters through persistentStorage. None is selected by default, so until you set one the NoteManager keeps its index in memory only.

{type: "local", prefix} Browser localStorage, used only when you select this type. The default prefix is then privacy-pool, and the cursor and note state persist under keys carrying that prefix.
{type: "file", dirPath, filename?} Node disk persistence, with JSON files per account.
{type: "memory"} An in-process Map, for tests and one-shot scripts.

Cursor

The NoteManager keeps a sync cursor (the last-synced block number). Subsequent discoverNotes() calls start from the cursor instead of from genesis, which keeps steady-state syncs fast. Clearing the cursor forces a full rescan, which can be slow on a cold start.

Direct access

Usually you go through session.exportAccount(). The NoteManager isn't a public API of the session, but imports and mutations happen through these session methods:

  • importReceivedNote(note): adds a note manually.
  • discoverNotes(): reconciles from the chain.
  • exportAccount(): takes a snapshot.