The Wallet SDK
@orbinum/wallet-sdk is the custody half of Orbinum's TypeScript surface. It owns everything
that derives or handles a spending key: key derivation, the encrypted vault, note construction,
chain rescan, coin selection, and proof generation.
It is not publicly published. This page describes what it does and where its boundary sits; it is not an API reference, and none of it is installable from the public registry.
Orbinum's TypeScript code was once a single SDK holding both chain access and key handling. That shape has a specific problem: a spending key reachable from a package anyone can install is an attack surface. Closing it is the reason the code was divided.
The rule that decides which side a given piece of code lands on:
If it can touch a spending key, it is not in the public package.
Everything else — chain access, addresses, encoding, note types, payment slips, disclosure keys,
precompiles — lives in @orbinum/protocol, which holds no keys and which
anyone can install.
Where the boundary falls
The two packages divide the same subject matter by a single question: does this code need to know what the wallet owns?
@orbinum/protocol | @orbinum/wallet-sdk | |
|---|---|---|
| Repository | orbinum/ts-protocol — public | orbinum/wallet-sdk — private |
| License | MIT | UNLICENSED |
| Registry access | public | restricted |
| Holds spending keys | never | always |
| Audience | any dapp, script, or automation | Orbinum's own wallet clients, and negotiated integrations |
Stated as a single sentence: @orbinum/protocol describes and observes the protocol; the wallet
SDK participates in it as an owner of funds. The public package knows what a note looks like;
this one is the only side that can open, own, or spend one.
The division is drawn at a real security property rather than by convenience, which is why some subjects are split across both packages:
| Subject | Public half | Custody half |
|---|---|---|
| Encrypted memo | the 180-byte wire format | sealing and opening it |
| Merkle forest | leaf-index validation, tree identification, capacity | choosing which of your own notes to spend |
| Note disclosure | verifying a disclosure key | generating one from a note you hold |
| Proofs | submitting one in an extrinsic | assembling the witness and producing it |
Dependency direction is strictly one-way: the wallet SDK depends on @orbinum/protocol, and the
public package has no knowledge of this one.
Capability map
Three layers sit on top of @orbinum/protocol. Capability areas and their responsibilities:
| Area | Responsibility |
|---|---|
crypto | Stealth address derivation and note blinding — primitives that consume or produce spend-power material |
protocol/keys | The private identity and the key hierarchy derived from it |
protocol/note | A note's off-chain lifecycle: building one, opening a received one, disclosing it |
protocol/eph | Deterministic ephemeral keys, which make note discovery a hash lookup rather than per-candidate curve work |
protocol/memo | Sealing a note's plaintext to a recipient, and opening it |
protocol/spend | Coin selection — choosing which of the wallet's notes pay a given amount |
protocol/proving | Witness assembly and proof generation for the spending circuits |
protocol/circuit-version | Pinning a proof to the circuit version its note was created under |
wallet/vault | The wallet's notes, encrypted at rest and kept in step with the chain |
wallet/scanner | Note discovery: walking the commitment feed, recovering owned notes, resolving which are spent |
wallet/ops | The user-facing operations — shield, transfer, unshield, fee claim |
wallet/identity | Who the user is on this device, and how that survives between launches |
wallet/worker | The trial-decryption kernel and worker pool, so scanning does not block the UI thread |
wallet/provenance | The wallet's private history of its own notes |
adapters/indexeddb | Browser persistence for the vault, secrets, and device keys |
Entry points
| Import | For |
|---|---|
@orbinum/wallet-sdk | The main custody surface |
@orbinum/wallet-sdk/worker | The decrypt kernel, for a Web Worker |
@orbinum/wallet-sdk/proving | Registers the bundled prover |
@orbinum/wallet-sdk/storage/indexeddb | Browser storage adapters |
The root entry re-exports all of @orbinum/protocol, so a first-party host imports one package
rather than two.
What it is not
This is a headless custody library. It contains no UI layer, no account abstraction, and no social recovery. Those are the host application's concern.
Privacy addresses
A privacy address is the public half of an identity — the part a recipient shares so a sender can pay them. The format is public, since any sender must be able to parse one, even though the code that emits it is not.
orbpriv3:{ownerPk}:{viewingPublicKey}:{checksum}
A sender uses the two halves to embed ownerPk in the note commitment and to encrypt the memo to
viewingPublicKey by ECDH. The trailing checksum makes a corrupted paste fail to decode rather
than pay into a note nobody can spend.
Only the viewing public key travels in an address. Holding someone's address does not let you decrypt their notes.
Only orbpriv3 is ever emitted. Decoding still accepts orbpriv1 and orbpriv2, because
paying an address works regardless of which scheme derived it — an address is just an owner key
plus a viewing key. orbpriv3 and orbpriv2 carry a verified checksum; orbpriv1 predates it and
is validated field-by-field instead.
Circuit versions
A note carries the circuit version it was created under, and its proof must verify against that
version's verification key — not merely the currently active one. Resolving that pairing is
custody-side because it pulls in the prover; the public package deliberately stops at exposing the
verifier's registry (client.zkVerifier), which reports circuit versions and verification-key
hashes.
The resolver fails closed: an unsupported version, or a verification key that does not match, is an error rather than a proof that will be rejected on-chain. See On-Chain Verification.
Access
There is no self-serve path to this package. It is not on the public registry, and the repository is private.
- First-party clients — the Orbinum app and wallet consume it directly.
- Partner integrations — a negotiated grant, requiring membership in the Orbinum npm organization and access to the private repository.
If you are building a dapp, you do not need this package. The supported path is
@orbinum/protocol: talk to the chain, compose a
payment slip, and hand it to an Orbinum wallet, which performs
the custody. A program that custodies its own seed is a wallet rather than a consumer of the public
SDK, and belongs on this side of the boundary.