> 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.

# Wallets (/helpers/wallets)

The SDK finds wallets through the [Wallet Standard](https://github.com/wallet-standard/wallet-standard),
which every major Solana browser wallet supports. You need no wallet adapter library.

In this guide, Alice picks her wallet from a list, connects it, and gets the signer her session
needs.

## List the wallets

`listWallets` returns the installed wallets that can do everything the SDK asks. Each one must
connect, sign messages and sign transactions on the SDK's cluster. Any other wallet is left out.

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

for (const wallet of listWallets(sdk)) {
  console.log(wallet.name, wallet.icon);
}
```

Each entry is a Wallet Standard `Wallet`. Show its `name` and `icon` in your wallet picker.

## Follow wallets that load late

A browser extension can register its wallet after your page loads. `followWallets` calls you with
the new list each time a wallet registers or unregisters. It returns a function that stops
following.

In React, a hook keeps the list current:

```tsx
import { followWallets, listWallets } from "@umbra/nimbus-solana-web";
import { useEffect, useState } from "react";

export function useWallets(sdk: NimbusSdk): readonly Wallet[] {
  const [wallets, setWallets] = useState(() => listWallets(sdk));
  useEffect(() => followWallets(sdk, { onChange: setWallets }), [sdk]);
  return wallets;
}
```

The stop function is the effect's cleanup. The hook stops following when the component unmounts.

## Connect one

When Alice picks a wallet, call `openWalletConnection`. Her wallet shows its connection prompt,
unless your page is already connected.

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

const connection = await openWalletConnection(sdk, { wallet });

switch (connection.kind) {
  case "connected": {
    const { signer, transactionVersion } = connection.connected;
    console.log(signer.account.address, transactionVersion);
    break;
  }
  case "no-account":
    console.log(`${wallet.name} has no account on this network.`);
    break;
  case "declined":
    console.log("You declined to connect.");
    break;
}
```

| `kind`       | What happened                                                     | What to do                                                        |
| ------------ | ----------------------------------------------------------------- | ----------------------------------------------------------------- |
| `connected`  | The wallet connected. `connected.signer` is what a session takes. | [Open a session](https://sdk.nimbusprivacy.xyz/helpers/sessions). |
| `no-account` | The wallet connected but has no account on this cluster.          | Ask Alice to add one, or pick another wallet.                     |
| `declined`   | Alice refused to connect.                                         | Let her try again.                                                |

A wallet that fails while connecting throws a `NimbusSdkError` with reason `wallet-unsupported`.
Ask Alice to pick another wallet.

## Version 0 and version 1 wallets

`connected.transactionVersion` is the newest transaction version the wallet signs. It is `1` for
most wallets, and `0` for older ones.

It matters only for the payments Alice's own wallet signs: [registration](https://sdk.nimbusprivacy.xyz/registration),
[deposit](https://sdk.nimbusprivacy.xyz/deposit) and a deposit refund. Pass it to each as the `transactionVersion` option. The
default is `1`, which a version 0 wallet cannot sign.

At version 0, a deposit takes two transactions, so Alice approves twice.
[Wallets that sign only version 0](https://sdk.nimbusprivacy.xyz/deposit#wallets-that-sign-only-version-0) explains why.

A [Private Send](https://sdk.nimbusprivacy.xyz/transfer) or a [withdrawal](https://sdk.nimbusprivacy.xyz/withdraw) is sent by a relayer. Alice's wallet never
signs it, so those take no version.

## Bring your own signer

A session takes any `WalletStandardSigner`. That is an account and two functions, shaped like the
Wallet Standard's `solana:signMessage` and `solana:signTransaction`. Build one when your app already
connects wallets through another library, or uses an embedded wallet.

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

const signer: WalletStandardSigner = {
  account: {
    address: accountAddress,
    publicKey: accountPublicKey,
    chains: ["solana:mainnet"],
    features: ["solana:signMessage", "solana:signTransaction"],
  },
  signMessage: async (...inputs) =>
    Promise.all(
      inputs.map(async ({ message }) => ({
        signedMessage: message,
        signature: await signBytes(message),
      })),
    ),
  signTransaction: async (...inputs) =>
    Promise.all(
      inputs.map(async ({ transaction }) => ({
        signedTransaction: await signWireTransaction(transaction),
      })),
    ),
};
```

The SDK holds your signer to the same rules as a wallet:

- **The account** lists the cluster's chain, `solana:mainnet`. Its address is the base58 form of
  its 32-byte public key.
- **`signMessage`** signs the bytes exactly as given, and returns them as `signedMessage`. A signer
  that wraps or prefixes the message is refused as `wallet-unsupported`.
- **`signTransaction`** returns the whole signed transaction. If it changes the transaction, the
  payment throws a `NimbusSolanaFlowError` with reason `transaction-altered`. Nothing is sent.
- **When the user refuses**, reject with an error whose `code` is `4001`. A message that says
  rejected, declined, denied or cancelled works too. The SDK then answers `declined` instead of
  throwing.

## Next

- [Sessions](https://sdk.nimbusprivacy.xyz/helpers/sessions): Open the user's private account with the signer.
- [Registration](https://sdk.nimbusprivacy.xyz/registration): Register the wallet before its first deposit.
- [Deposit](https://sdk.nimbusprivacy.xyz/deposit): Move tokens from the wallet into a private balance.
- [API reference](https://sdk.nimbusprivacy.xyz/reference/wallets): listWallets, followWallets and openWalletConnection.


Last updated 21 October 2026
