> For AI agents: the documentation index is at https://sdk.nimbusprivacy.xyz/llms.txt, and every page is available as Markdown at its URL with .md appended.

# Load the SDK (/helpers/load)

`loadNimbusSdk` is the first call your app makes. It reads the settings the SDK ships for mainnet,
checks the browser, and loads the SDK's WebAssembly. Every other function takes the
`NimbusSdk` it returns, directly or through a session.

Load it once per page. One SDK serves any number of sessions, and it holds no keys.

## Load it

```ts
import { loadNimbusSdk } from "@umbra/nimbus-solana-web";

const sdk = await loadNimbusSdk(
  { cluster: "mainnet" },
  { assetsBaseUrl: "/nimbus/" },
);
```

`assetsBaseUrl` is the directory your app serves the SDK's files from, ending with `/`.
[Serve the SDK's files](https://sdk.nimbusprivacy.xyz/getting-started/setup#serve-the-sdks-files) shows how to put them there.

Loading asks no wallet for anything. It fetches only the SDK's WebAssembly. Nimbus's services are
first reached when a session opens or a payment runs.

## The mainnet preset

The SDK ships a preset for mainnet. It holds the programs, the tokens, every service endpoint and
the proving keys, the large files each proof is built from. So your app passes only
`assetsBaseUrl`.

These are the mainnet preset's endpoints, read from the SDK when this site was built:

| Option                     | mainnet preset                                                                                                                                                                                                                                                                                                                                                                                                                              | Gateway |
| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
| `endpoints.rpc`            | [https://api.mainnet-beta.solana.com](https://api.mainnet-beta.solana.com)                                                                                                                                                                                                                                                                                                                                                                  | No      |
| `endpoints.indexer`        | [https://data.api-v2.umbraprivacy.com](https://data.api-v2.umbraprivacy.com)                                                                                                                                                                                                                                                                                                                                                                | No      |
| `endpoints.context`        | [https://context.api-v2.umbraprivacy.com](https://context.api-v2.umbraprivacy.com)                                                                                                                                                                                                                                                                                                                                                          | No      |
| `endpoints.guardians`      | 1: [https://gateway.api-v2.umbraprivacy.com/guardian-share-node-relay-1](https://gateway.api-v2.umbraprivacy.com/guardian-share-node-relay-1), 2: [https://gateway.api-v2.umbraprivacy.com/guardian-share-node-relay-2](https://gateway.api-v2.umbraprivacy.com/guardian-share-node-relay-2), 3: [https://gateway.api-v2.umbraprivacy.com/guardian-share-node-relay-3](https://gateway.api-v2.umbraprivacy.com/guardian-share-node-relay-3) | Yes     |
| `endpoints.screeners`      | 0: [https://gateway.api-v2.umbraprivacy.com/screener](https://gateway.api-v2.umbraprivacy.com/screener)                                                                                                                                                                                                                                                                                                                                     | Yes     |
| `endpoints.dataEndorsers`  | 0: [https://gateway.api-v2.umbraprivacy.com/data-endorser](https://gateway.api-v2.umbraprivacy.com/data-endorser)                                                                                                                                                                                                                                                                                                                           | Yes     |
| `endpoints.feeEnclave`     | [https://gateway.api-v2.umbraprivacy.com/fee-enclave](https://gateway.api-v2.umbraprivacy.com/fee-enclave)                                                                                                                                                                                                                                                                                                                                  | Yes     |
| `endpoints.relayer`        | [https://gateway.api-v2.umbraprivacy.com/relayer](https://gateway.api-v2.umbraprivacy.com/relayer)                                                                                                                                                                                                                                                                                                                                          | Yes     |
| `endpoints.coordinator`    | [https://gateway.api-v2.umbraprivacy.com/process-coordinator](https://gateway.api-v2.umbraprivacy.com/process-coordinator)                                                                                                                                                                                                                                                                                                                  | Yes     |
| `endpoints.primitivesWasm` | Your app supplies it                                                                                                                                                                                                                                                                                                                                                                                                                        | No      |
| `provingKeys`              | [https://assets.api-v2.umbraprivacy.com/zk/](https://assets.api-v2.umbraprivacy.com/zk/)                                                                                                                                                                                                                                                                                                                                                    | No      |

`primitivesWasm` comes from `assetsBaseUrl`, so you rarely pass it yourself.

## Replace an endpoint

Pass `endpoints` to replace any of the preset's, one at a time. The rest keep their preset values.
The most common case is your own Solana RPC:

```ts
import { loadNimbusSdk } from "@umbra/nimbus-solana-web";

const sdk = await loadNimbusSdk(
  { cluster: "mainnet" },
  {
    assetsBaseUrl: "/nimbus/",
    endpoints: { rpc: "https://rpc.example.com" },
  },
);
```

The example app does the same when its settings name an RPC.

[Endpoints](https://sdk.nimbusprivacy.xyz/production/endpoints) shows how to point the SDK at services you run yourself.

If you replace an endpoint the gateway fronts, your replacement receives the session's gateway
token. Point it only at a host you trust.

## What your app reads from it

Treat every field of the SDK as read-only. These are the ones an app usually reads:

| Field                       | What it holds                                                                                                 |
| --------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `cluster`                   | The cluster you loaded, `"mainnet"`.                                                                          |
| `deployment.chain`          | The chain wallets sign for, such as `solana:mainnet`.                                                         |
| `mints`                     | The tokens the preset lists, with their decimals. See [Tokens](https://sdk.nimbusprivacy.xyz/helpers/tokens). |
| `settings.endpoints`        | Every endpoint, after your replacements.                                                                      |
| `settings.gatewayEndpoints` | The services the gateway fronts, each with its URL. The gateway token goes only to these.                     |
| `settings.assetPinning`     | `"pinned"` when the SDK checks its own files before running them, `"unpinned"` when it does not.              |

### Refuse an unpinned build

A packed copy of the package, the kind a registry serves, is always `pinned`. A copy built from
source can be `unpinned`, and then runs its files unchecked. Refuse to go on in production if you
see it:

```ts
if (sdk.settings.assetPinning !== "pinned") {
  throw new Error("This build runs the SDK's files unchecked.");
}
```

## What it checks

Before it returns, `loadNimbusSdk` makes sure the SDK can run safely on this page. Each failed check
throws a `NimbusSdkError`:

| What it checks                                                                     | Reason when it fails       | How to fix it                                                                                               |
| ---------------------------------------------------------------------------------- | -------------------------- | ----------------------------------------------------------------------------------------------------------- |
| Every endpoint and the proving keys are set, and `assetsBaseUrl` ends with `/`     | `misconfigured`            | Pass what the message names.                                                                                |
| The browser has `fetch`, Web Crypto, IndexedDB, Web Locks, storage and WebAssembly | `unsupported-browser`      | Ask the user for a current browser.                                                                         |
| The page is cross-origin isolated                                                  | `unsupported-browser`      | [Send the two headers](https://sdk.nimbusprivacy.xyz/getting-started/setup#turn-on-cross-origin-isolation). |
| The WebAssembly file can be fetched                                                | `service-unavailable`      | Check `assetsBaseUrl` and that the files are served.                                                        |
| The file's SHA-256 is the one the package pins                                     | `dependency-nonconforming` | Serve the files that shipped with this copy of the package.                                                 |
| The WebAssembly gives the right answers to its known-answer self-tests             | `dependency-nonconforming` | The same.                                                                                                   |
| The file is WebAssembly at all                                                     | `unreadable`               | Check that `assetsBaseUrl` names the right directory.                                                       |
| The browser opens the SDK's cache in IndexedDB                                     | `unsupported-browser`      | Some private windows refuse it.                                                                             |

The prover worker is checked the same way when the first proof starts. Its script, and each file it
loads, must match the SHA-256 the package pins.

Turn each reason into a message your user can act on:

```ts
import { isNimbusSdkError } from "@umbra/nimbus-solana-web";

function describeLoadFailure(thrown: unknown): string {
  if (!isNimbusSdkError(thrown)) return "The private balance could not load.";
  switch (thrown.reason) {
    case "unsupported-browser":
      return "This browser cannot run private payments. Try a current Chrome, Firefox or Safari.";
    case "service-unavailable":
      return "The app's files could not be fetched. Try again.";
    case "misconfigured":
    case "dependency-nonconforming":
    case "unreadable":
      return "This app is set up wrongly. Please tell its developers.";
    case "wallet-unsupported":
    case "unauthorized":
    case "recipient-unregistered":
    case "account-unregistered":
      return "The private balance could not load.";
  }
}
```

Log `thrown.message` as well. It names the endpoint, file or browser feature at fault.

## Next

- [Wallets](https://sdk.nimbusprivacy.xyz/helpers/wallets): List the user's wallets and connect one.
- [Set up your app](https://sdk.nimbusprivacy.xyz/getting-started/setup): Serve the SDK's files and turn on cross-origin isolation.
- [Endpoints](https://sdk.nimbusprivacy.xyz/production/endpoints): The mainnet endpoints, and services of your own.
- [API reference](https://sdk.nimbusprivacy.xyz/reference/load): loadNimbusSdk: its signature, options and errors.


Last updated 21 October 2026
