> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nullark.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Nullark SDK API reference

Use Nullark client methods, adapter contracts, prepared results, and starter setup helpers without guessing their shapes.

Reference for integration path proven by current `@nullark/sdk` source and package-pinned starter. Start with [complete SDK integration](/developers/sdk/quickstart.md) when you want runnable order.

## `Nullark`

Create one client with one runtime and one matching set of adapters.

```ts
import { Nullark } from "@nullark/sdk";

const nullark = new Nullark({
  runtime,
  localDepositProver,
  localWithdrawalProver,
  readDeposits,
  resolveMembership,
  isNullifierSpent,
  runtimeFeeReadClient
});
```

Client exposes runtime as `nullark.runtime` and five public operations:

| Operation | Purpose |
| --- | --- |
| `nullark.recovery.createKey()` | Create recovery key |
| `nullark.deposits.prepare(input)` | Prepare recoverable deposit and unsigned request |
| `nullark.recovery.restore(input)` | Restore private bundle from key and envelope |
| `nullark.balances.get(input)` | Recover matching deposits and total available notes |
| `nullark.withdrawals.prepare(input)` | Prepare bounded withdrawal and unsigned request |

### Constructor options

| Option | Used by | Value expected |
| --- | --- | --- |
| `runtime` | All operations | Runtime object; defaults to `getCurrentRuntime()` |
| `localDepositProver` | `deposits.prepare` | Callback returning `proof` and `publicInputs` |
| `localWithdrawalProver` | `withdrawals.prepare` | Callback returning `proof` and `publicInputs` |
| `readDeposits` | `balances.get` | Deposit events plus reader source identity |
| `resolveMembership` | `withdrawals.prepare` | Bundle commitment, leaf index, path elements, and root |
| `isNullifierSpent` | Balance and withdrawal | Reader source identity plus boolean `spent` |
| `runtimeFeeReadClient` | `withdrawals.prepare` | Chain ID, block snapshot, and pool fee reads |
| `randomBytes` | Recovery, deposit, withdrawal | Optional byte source; SDK uses WebCrypto when omitted |

Missing operation-specific adapter rejects that operation before transaction preparation finishes.

## `recovery.createKey`

```ts
const recoveryKey = nullark.recovery.createKey();
```

No input. Returns new `Uint8Array` containing exactly 32 bytes. When `randomBytes` is set, callback must return requested byte count.

Keep returned bytes with recovery envelope created by `deposits.prepare`.

## `deposits.prepare`

```ts
const deposit = await nullark.deposits.prepare({
  templateId: "one-as-two-halves",
  recoveryKey
});
```

### Input

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `templateId` | `string` | Yes | Template registered by active runtime |
| `recoveryKey` | `Uint8Array` | Yes | Recovery key containing 32 bytes |

Method creates private bundle, encrypts recovery envelope, builds proof binding, calls `localDepositProver`, validates returned proof data, then builds unsigned transaction.

### Result

| Field | Meaning |
| --- | --- |
| `transaction.chainId` | Runtime chain ID |
| `transaction.to` | Runtime pool address |
| `transaction.value` | Deposit amount as `bigint` |
| `transaction.data` | Encoded deposit call |
| `proof` | Proof bytes returned by local prover after SDK checks |
| `publicInputs` | Public inputs checked against deposit binding |
| `binding` | Commitment, amount, encrypted payload, hashes, inputs, and prover witness |
| `recovery.bundle` | Private bundle used by withdrawal preparation |
| `recovery.envelope` | Encrypted recovery data stored with recovery key |
| `publicEvidence` | Chain, pool, commitment, amount, and flags showing private keys and note secrets are absent |

Keep `binding`, `recovery.bundle`, key, and witness data inside trusted client. Wallet receives `transaction` after recovery backup passes restore roundtrip.

Preparation rejects missing prover, unknown template, invalid recovery key, malformed prover result, or proof data that fails binding checks.

## `recovery.restore`

```ts
const bundle = await nullark.recovery.restore({
  recoveryKey,
  envelope
});
```

### Input

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `recoveryKey` | `Uint8Array` | Yes | Same 32 bytes saved for deposit |
| `envelope` | `NullarkRecoveryEnvelope` | Yes | Encrypted envelope returned by deposit preparation |

Method checks envelope against active runtime, opens it with recovery key, verifies recovered bundle commitment, then returns bundle accepted by `withdrawals.prepare`.

Wrong key, changed envelope, or runtime mismatch rejects restore.

## `balances.get`

```ts
const balance = await nullark.balances.get({ recoveryKey });
```

### Input

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `recoveryKey` | `Uint8Array` | Yes | Key used by deposits you want to find |

Method calls `readDeposits`, tries matching encrypted events locally, calls `isNullifierSpent` for each recovered note, and sums notes still available.

### Result

| Field | Type | Meaning |
| --- | --- | --- |
| `availableBalanceWei` | `string` | Sum of available recovered notes in decimal wei |
| `deposits` | `array` | Deposits opened by recovery key |
| `deposits[].event` | `object` | Commitment, amount, and encrypted payload supplied by reader |
| `deposits[].bundle` | `object` | Restored bundle accepted by withdrawal preparation |
| `deposits[].notes` | `array` | Nonzero child notes found in bundle |
| `deposits[].notes[].childIndex` | `number` | Index passed to withdrawal preparation |
| `deposits[].notes[].amountWei` | `string` | Note amount in decimal wei |
| `deposits[].notes[].commitment` | hex string | Child commitment |
| `deposits[].notes[].nullifier` | hex string | Value used by spent-state reader |
| `deposits[].notes[].status` | `"available" \| "spent"` | Current reader result |

Spent notes stay in `notes` with status `"spent"`; available balance excludes their amounts. Unrelated encrypted events stay out of `deposits`.

Call requires both `readDeposits` and `isNullifierSpent`. Malformed events, duplicate commitments, malformed status, or reader-source mismatch reject whole read.

## `withdrawals.prepare`

```ts
const withdrawal = await nullark.withdrawals.prepare({
  bundle,
  childIndex,
  destination,
  maxFeeWei,
  minNetAmountWei
});
```

### Input

| Field | Type | Required | Meaning |
| --- | --- | --- | --- |
| `bundle` | restored bundle | Yes | Bundle returned by recovery or balance read |
| `childIndex` | `number` | Yes | Available nonzero note selected by user |
| `destination` | `HexString` | Yes | Nonzero recipient address |
| `maxFeeWei` | decimal `string` | No | Highest fee accepted by user |
| `minNetAmountWei` | decimal `string` | No | Lowest recipient amount accepted by user |

When fee bounds are omitted, method uses fee and net amount read during preparation as exact bounds.

Preparation checks bundle/runtime match, resolves membership, checks selected note, reads fee, checks user bounds, calls local prover, validates proof intent, reads fee again, checks selected note again, then builds unsigned transaction.

### Result

| Field | Meaning |
| --- | --- |
| `transaction` | Unsigned `{ chainId, to, value, data }`; `value` is `0n` |
| `proof` | Checked withdrawal proof bytes |
| `publicInputs` | Checked withdrawal inputs |
| `encryptedPayload` | Cover payload included with call |
| `nullifier` | Selected note identifier used for spent check |
| `root` | Membership root used by proof |
| `destination` | Normalized recipient address |
| `grossAmountWei` | Selected note amount |
| `feeWei` | Fee used by proof |
| `netAmountWei` | Recipient amount |
| `maxFeeWei` | Applied fee ceiling |
| `minNetAmountWei` | Applied recipient floor |

Preparation rejects spent note, missing adapter, invalid destination, invalid decimal bound, fee above ceiling, net amount below floor, fee change during proving, or prover result that fails proof checks.

## Adapter contracts

All chain readers stay tied to `nullark.runtime`.

### Reader source

`readDeposits` and `isNullifierSpent` return same source fields with their data:

```ts
type NullarkReaderSource = {
  chainId: number;
  pool: HexString;
  runtimeId: string;
  runtimeIdHash: HexString;
  templateSetHash: HexString;
};
```

SDK checks every field against active runtime.

### Adapter shapes

| Adapter | Receives | Returns |
| --- | --- | --- |
| `readDeposits` | `{ runtime }` | `{ source, events }`, each event containing `commitment`, `amountWei`, `encryptedPayload` |
| `resolveMembership` | `{ runtime, bundle, childIndex }` | `{ bundleCommitment, leafIndex, pathElements, root }` |
| `isNullifierSpent` | `{ runtime, nullifier }` | `{ source, spent }` |
| `runtimeFeeReadClient.getChainId` | No input | Chain ID |
| `runtimeFeeReadClient.getBlock` | Optional block number | Block number and hash |
| `runtimeFeeReadClient.readContract` | Address, ABI, function name, optional block | Pool fee value |
| `localDepositProver` | `{ runtime, bundle, recoverableDeposit, binding }` | `{ proof, publicInputs }` |
| `localWithdrawalProver` | `{ runtime, witnessBundle }` | `{ proof, publicInputs }` |

## Starter setup helpers

These exports wire proving path used by starter:

| Import | Export | Use |
| --- | --- | --- |
| `@nullark/sdk` | `getCurrentRuntime` | Read bundled runtime object |
| `@nullark/sdk` | `generateBundledChildDepositGroth16Proof` | Run deposit proof through supplied prover runner |
| `@nullark/sdk` | `generateWithdrawalGroth16Proof` | Run withdrawal proof through supplied prover runner |
| `@nullark/sdk/node` | `resolveProverArtifacts` | Resolve runtime file paths into local paths or HTTPS URLs |
| `@nullark/sdk/node` | `verifyLocalProverArtifacts` | Check local file hashes and record bindings |

`@nullark/sdk/node` reads local files with Node APIs. Keep that entry in Node code. Main `@nullark/sdk` entry carries client, methods, types, proof helpers, and runtime helpers.

## Common stops

| Stop | Check |
| --- | --- |
| Deposit prover missing | Pass `localDepositProver` when creating client |
| Balance reader missing | Pass both `readDeposits` and `isNullifierSpent` |
| Withdrawal adapter missing | Pass membership, spent-state, fee, and withdrawal-prover adapters |
| Reader source mismatch | Point every reader at same runtime and pool |
| Recovery restore failed | Use untouched envelope with matching 32-byte key |
| Note already spent | Refresh `balances.get` and choose available note |
| Fee changed during proof | Run `withdrawals.prepare` again with user-approved bounds |

Submission status stays app-owned. Use starter-backed [errors and status](/developers/sdk/errors.md) flow before any retry.
