npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@umbra-privacy/nimbus-solana-web

v0.4.0

Published

The Solana SDK for browsers with every dependency filled: load it for a cluster from its bundled preset, open a session for the connected wallet, and run the flows, with crypto in WASM, IndexedDB storage, the prover's WASM, the service clients and @solana

Readme

@umbra-privacy/nimbus-solana-web

Private balances and payments for Solana web apps. Users deposit from their wallet, pay other users and withdraw to a Solana address. The SDK builds proofs, stores and syncs private balances, and submits payments, all in the browser. Spending keys stay on the user's device.

Pre-release (0.x): every API, type and behaviour is subject to change at any time, as and when the Nimbus Privacy team (built by Umbra Privacy) decides or requires.

Install

pnpm add @umbra-privacy/nimbus-solana-web @solana/kit
# or
npm install @umbra-privacy/nimbus-solana-web @solana/kit
# or
yarn add @umbra-privacy/nimbus-solana-web @solana/kit

Every SDK function takes mints and wallets as a kit Address. Make one with address from @solana/kit.

The SDK runs in the browser only. Load it from code that runs in the browser, not in a server render.

Setup

1. Serve the SDK's files

The package ships WebAssembly and a worker script. Your app serves them from its own site. Copy them into your static folder after every install:

{
    "scripts": {
        "postinstall": "nimbus-solana-web copy-assets public/nimbus"
    }
}

Keep that folder out of git. Pass its URL to loadNimbusSdk as assetsBaseUrl, ending with /. The SDK checks every file's SHA-256 before it runs it.

2. Turn on cross-origin isolation

By default, proofs use shared memory. Browsers allow it only on pages served with these two headers:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Send both with every page that loads the SDK. Install and set up shows the config for Next.js, Vite, Vercel and Cloudflare. If a wallet breaks under them, load the SDK on that page with proving: { threading: "workers" }, which proves more slowly and needs neither header.

3. Get a mainnet gateway token

Nimbus's services on mainnet sit behind a gateway. It accepts only requests that carry a token issued for your app. To get one, email [email protected] or reach out to any Umbra team member.

Pass it to openNimbusSession as gatewayToken. Without it, a session still opens and reads balances. Registration and every payment fail with reason unauthorized.

Example

Alice connects her wallet, registers, deposits 25 USDC and reads her private balance. This runs on mainnet and moves real USDC.

import { address } from "@solana/kit";
import {
    createDepositContext,
    createRegistrationContext,
    deposit,
    listWallets,
    loadNimbusSdk,
    openNimbusSession,
    openWalletConnection,
    readBalances,
    register,
    syncNoteStore,
} from "@umbra-privacy/nimbus-solana-web";

const usdc = address("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");

// Load the SDK once per page.
const sdk = await loadNimbusSdk(
    { cluster: "mainnet" },
    { assetsBaseUrl: "/nimbus/" },
);

// Connect a wallet.
const [wallet] = listWallets(sdk);
if (wallet === undefined) throw new Error("Install a Solana wallet first.");
const connection = await openWalletConnection(sdk, { wallet });
if (connection.kind !== "connected") throw new Error("Not connected.");
const { signer, transactionVersion } = connection.connected;

// Open Alice's private account. Her wallet signs one message; no money moves.
const opened = await openNimbusSession(
    sdk,
    { connectedWallet: signer },
    { gatewayToken: "your-gateway-token" },
);
if (opened.kind === "declined") throw new Error("Alice declined to sign.");
const { session } = opened;

// Register her, once, before her first deposit.
if (session.registration.kind === "unregistered") {
    const registration = await register(
        await createRegistrationContext(session),
        {},
        { transactionVersion },
    );
    const registered =
        registration.kind === "complete" ||
        (registration.kind === "submitted" &&
            registration.submission.submission.kind === "landed");
    if (!registered) throw new Error("The registration did not land.");
}

// Deposit 25 USDC. USDC has 6 decimals. The protocol fee comes out of it.
const deposited = await deposit(
    await createDepositContext(session),
    { mint: usdc, amount: 25_000_000n, recipient: session.walletAddress },
    { transactionVersion },
);
if (
    deposited.kind !== "submitted" ||
    deposited.submission.submission.kind !== "landed"
) {
    throw new Error("The deposit did not land.");
}

// Sync with Solana, then read her private balance.
await syncNoteStore(session, {});
const balances = await readBalances(session, {});
for (const row of balances) {
    if (row.mint === usdc) console.log(row.state, row.total);
}

A new deposit can read as pending for a moment, until Solana confirms it. Then it reads as available.

Private Send (transfer) and withdraw follow the same pattern. A relayer submits them, so the wallet signs nothing and pays no network fee. The quickstart walks through both and handles every result.

What's public and what's private

  • Deposits publish the funding wallet, token and amount, but not whose private balance receives them.
  • Withdrawals publish the destination, token and amount, but not which private balance paid.
  • Private Send does not publish the sender, recipient, payment token or amount. The relayer transaction and any paid tip remain public.

Read the privacy boundaries before you launch.

Links

  • Documentation: https://sdk.nimbusprivacy.xyz
  • Protocol documentation: https://docs.nimbusprivacy.xyz

License

Apache-2.0


Nimbus Privacy (built by Umbra Privacy)