Use this page when you want Nullark inside your own TypeScript app. The SDK validates the runtime, recovery envelope, proof inputs, fee bounds, spent state, and calldata. Your app supplies local proving, current Merkle membership, chain reads, secure recovery storage, and wallet transport.
The npm release is pending. Install the SDK from the Nullark repository or from tarballs built from a reviewed checkout.

Install from source

The SDK is ESM and includes its own TypeScript declarations. snarkjs ships without declarations, so strict TypeScript apps need a small local declaration:
snarkjs.d.ts

Before you create the client

Have these pieces ready: Run proving where the user’s secrets stay under their control. A browser, desktop app, or local Node process can own the prover. A hosted prover callback receives the private witness. @nullark/sdk/node resolves and verifies local proving files. Keep that import in local Node or trusted build tooling. Browser apps use the main @nullark/sdk entry and an app-owned loader that checks downloaded artifact bytes against the runtime hashes before snarkjs receives them.

Create the client

This factory is the complete local-file setup. artifactDir is the directory containing the runtime’s /proving/... paths; in this repository that directory is apps/web/public.

new Nullark(options)

NullarkCurrentRuntime
Runtime used for every check and prepared transaction. Robinhood integrations should pass the explicitly selected runtime instead of relying on a package default.
LocalBundledChildDepositProver
Required by deposits.prepare. It receives the private deposit witness and must return a 256-byte Groth16 proof plus the six matching public inputs.
LocalBundledChildWithdrawalProver
Required by withdrawals.prepare. It receives the private withdrawal witness and must return a 256-byte Groth16 proof plus the nine matching public inputs.
ResolveBundledChildMembership
Required by withdrawals.prepare. Return the selected bundle commitment, leaf index, 20 path elements, and an accepted root from the active pool.
ReadBundledChildNullifierStatus
Required by withdrawals.prepare. Return the current boolean value for the child nullifier from the runtime pool.
RuntimeFeeReadContractClient
Required by withdrawals.prepare. The interface matches getChainId, getBlock, and readContract reads used by a Viem public client.
(length: number) => Uint8Array
Test hook. Production integrations should use the default WebCrypto randomness.
Build this from ordered CommitmentInserted history or a trusted indexer, then confirm the resulting root is accepted by the same pool.
Read nullifiers(bytes32) at runtime.pool. The SDK checks it before and after withdrawal proving.
The SDK pins all fee reads to one block and verifies the chain, block hash, controller, and fee bounds.

Deposit and recovery

deposits.prepare(input)

Creates fresh bundle secrets, encrypts the recovery payload, runs the local deposit prover, validates its output, and returns one unsigned transaction.
string
required
A registered private-note template. one-as-two-halves deposits 1 ETH and creates two 0.5 ETH child notes.
Uint8Array
required
Exactly 32 random bytes. Keep the key with the matching envelope in encrypted user-controlled storage.
DepositTransactionRequest
{ chainId, to, value, data } ready for wallet simulation and submission. value is the deposit amount.
NullarkRecoveryEnvelope
Encrypted recovery payload plus the runtime, pool, commitment, and payload bindings needed for restoration.
V13BundledChildBundle
The in-memory private bundle created for this deposit. Treat it as secret-bearing state.
HexString
Canonical 256-byte Groth16 proof accepted by the SDK.
readonly HexString[]
Six validated public inputs in the runtime’s deposit order.
object
Safe reconciliation fields: chain, pool, commitment, amount, and payload-presence flags. Private keys and note secrets are excluded.
Save the recovery key and envelope before opening the wallet. If the wallet result becomes uncertain, keep the same recovery material and reconcile the original commitment before preparing another deposit. The SDK accepts raw recovery-key bytes. The Transfer Console adds EIP-712 signer verification, wallet-bound key derivation, onchain event scanning, and bearer-note fallback around this primitive. Integrators need those boundaries before presenting wallet recovery.

recovery.restore(input)

Decrypts one saved envelope and returns the original private bundle after checking its runtime, pool, template set, payload hash, and bundle commitment.
NullarkRecoveryEnvelope
required
The exact envelope returned by deposits.prepare.
Uint8Array
required
The matching 32-byte key.
HexString
Commitment used to locate the bundle in pool history.
readonly V13BundledChildNote[]
Child amount, secret, commitment, owner commitment, and nullifier for each private note.
runtime identity
Identity checked again when the bundle is used for withdrawal.

Withdrawal

withdrawals.prepare(input)

Resolves membership, checks spent state and fee state, runs the local withdrawal prover, validates every public input, rechecks mutable chain state, and returns zero-value calldata.
V13BundledChildBundle
required
Bundle returned by recovery.restore or retained from the original deposit preparation.
number
required
Index of an available child note. The example template has child indices 0 and 1.
HexString
required
Nonzero EVM address that receives the public withdrawal.
string
Maximum accepted fee as decimal wei. The active fee becomes the exact bound when omitted.
string
Minimum amount the destination must receive as decimal wei. The current calculated net amount is used when omitted.
{ chainId, to, value: 0n, data }
Unsigned withdrawal transaction. The pool call always carries zero ETH value.
string
Decimal wei values used by the proof and calldata.
HexString
Public withdrawal identity validated against the generated proof.
HexString fields
Canonical proof package already checked against the exact withdrawal intent.

Send the prepared transaction

Both methods return the same wallet-ready shape. Check the wallet chain, preserve to, value, and data, then wait for a receipt from the runtime RPC.
Treat a rejected wallet request as cancelled. When a hash was returned or the transport timed out after signing, look up that hash and the prepared commitment or nullifier before offering a retry.

Common errors

Use Deposit integration for receipt reconciliation, Withdrawal integration for preflight and settlement, and Proving files for artifact handling.