Nitso Provider

Root provider for Nitso. Required before using any Nitso component.

Installation

npx shadcn@latest add https://nitso.fun/r/nitso-provider.json
pnpm dlx shadcn@latest add https://nitso.fun/r/nitso-provider.json
yarn dlx shadcn@latest add https://nitso.fun/r/nitso-provider.json
bunx --bun shadcn@latest add https://nitso.fun/r/nitso-provider.json

Install dependencies

npm install @solana/connector @solana/web3.js
pnpm add @solana/connector @solana/web3.js
yarn add @solana/connector @solana/web3.js
bun add @solana/connector @solana/web3.js

Copy the source code

nitso-provider.tsx
import { getDefaultConfig } from "@solana/connector/headless";import { AppProvider } from "@solana/connector/react";import { type ReactNode, useMemo } from "react";interface SolanaCluster {  id: "solana:mainnet" | "solana:devnet" | "solana:testnet" | "solana:localnet";  label: string;  url: string;}interface WalletDisplayConfig {  allowList?: string[];  denyList?: string[];  featured?: string[];}interface SimplifiedWalletConnectConfig {  projectId?: string;  defaultChain?: "solana:mainnet" | "solana:devnet" | "solana:testnet";  relayUrl?: string;}interface NitsoProviderProps {  children: ReactNode;  /** Application name shown in wallet connection prompts */  appName: string;  /**   * Application URL.   * Only needed if you enable walletConnect.   */  appUrl?: string;  /**   * Custom RPC endpoints per cluster.   * Strongly recommended — public endpoints are rate limited.   *   * Define this OUTSIDE your component to keep the reference stable   * and avoid unnecessary re-renders.   *   * @example   * const clusters = [   *   { id: 'solana:mainnet' as const, label: 'Mainnet Beta', url: 'https://mainnet.helius-rpc.com/?api-key=xxx' },   *   { id: 'solana:devnet'  as const, label: 'Devnet',       url: 'https://api.devnet.solana.com' },   *   { id: 'solana:testnet' as const, label: 'Testnet',      url: 'https://api.testnet.solana.com' },   * ];   *   * <NitsoProvider clusters={clusters} ... />   */  clusters?: SolanaCluster[];  /**   * Control which wallets are shown.   * Define OUTSIDE your component to keep the reference stable.   *   * @example   * // Show only specific wallets   * wallets={{ allowList: ['Phantom', 'Solflare'], featured: ['Phantom'] }}   *   * // Hide specific wallets   * wallets={{ denyList: ['WalletConnect'] }}   */  wallets?: WalletDisplayConfig;  /**   * Silently reconnect last wallet on page load.   * @default true   */  autoConnect?: boolean;  /**   * Human-readable names for program IDs.   * Used to enrich transaction history labels.   *   * @example   * programLabels={{   *   'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4': 'Jupiter',   *   'whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc': 'Orca',   * }}   */  programLabels?: Record<string, string>;  /**   * Enable WalletConnect for QR code / deep link connections.   * Disabled by default.   *   * Requires:   *   npm install @walletconnect/universal-provider qrcode.react   *   * Also requires appUrl to be set for WalletConnect metadata.   *   * @example   * walletConnect={{ projectId: process.env.WALLETCONNECT_PROJECT_ID }}     // Next.js   * walletConnect={{ projectId: import.meta.env.VITE_WALLETCONNECT_PROJECT_ID }} // Vite   */  walletConnect?: SimplifiedWalletConnectConfig;}export function NitsoProvider({  children,  appName,  appUrl,  clusters,  wallets,  autoConnect = true,  programLabels,  walletConnect,}: NitsoProviderProps) {  const config = useMemo(    () =>      getDefaultConfig({        appName,        appUrl,        clusters,        wallets,        autoConnect,        programLabels,        walletConnect,      }),    // Primitive values (string, boolean) are safe as deps.    // Object values (clusters, wallets, programLabels)    // must be defined OUTSIDE the component to stay stable.    // eslint-disable-next-line react-hooks/exhaustive-deps    [      appName,      appUrl,      autoConnect,      wallets,      walletConnect,      programLabels,      clusters,    ],  );  return <AppProvider connectorConfig={config}>{children}</AppProvider>;}

Setup

Add NitsoProvider to your root layout. It must wrap all Nitso components.

Add Environment Variables

Public RPC endpoints are rate limited and not suitable for production. Get a dedicated key from Helius, QuickNode, or Alchemy.

.env.local
RPC_MAINNET=https://mainnet.helius-rpc.com/?api-key=your-key
RPC_DEVNET=https://devnet.helius-rpc.com/?api-key=your-key

Create the provider

NitsoProvider uses React hooks internally and requires "use client". To keep your root layout as a Server Component (needed for metadata exports and SEO), create a separate client boundary file:

app/provider.tsx
"use client";

import { NitsoProvider } from "@/components/nitso/nitso-provider";

const clusters = [
  {
    id: "solana:mainnet" as const,
    label: "Mainnet Beta",
    url: process.env.RPC_MAINNET!,
  },
  {
    id: "solana:devnet" as const,
    label: "Devnet",
    url: process.env.RPC_DEVNET!,
  },
  {
    id: "solana:testnet" as const,
    label: "Testnet",
    url: "https://api.testnet.solana.com",
  },
];

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <NitsoProvider appName="My App" clusters={clusters}>
      {children}
    </NitsoProvider>
  );
}

Wrap your root layout

app/layout.tsx
import { Providers } from "./provider";

export const metadata = {
  title: "My App",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Add Environment Variables

Public RPC endpoints are rate limited and not suitable for production. Get a dedicated key from Helius, QuickNode, or Alchemy.

.env
VITE_RPC_MAINNET=https://mainnet.helius-rpc.com/?api-key=your-key
VITE_RPC_DEVNET=https://devnet.helius-rpc.com/?api-key=your-key

Add the provider

src/main.tsx
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { NitsoProvider } from "@/components/nitso/nitso-provider";
import App from "./App";

const clusters = [
  {
    id: "solana:mainnet" as const,
    label: "Mainnet Beta",
    url: import.meta.env.VITE_RPC_MAINNET,
  },
  {
    id: "solana:devnet" as const,
    label: "Devnet",
    url: import.meta.env.VITE_RPC_DEVNET,
  },
  {
    id: "solana:testnet" as const,
    label: "Testnet",
    url: "https://api.testnet.solana.com",
  },
];

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <NitsoProvider appName="My App" clusters={clusters}>
      <App />
    </NitsoProvider>
  </StrictMode>,
);

WalletConnect

Enable QR code and deep link connections by setting walletConnect. This adds a "WalletConnect" option to the wallet modal.

Requires @walletconnect/universal-provider and qrcode.react to be installed:

npm install @walletconnect/universal-provider qrcode.react
pnpm add @walletconnect/universal-provider qrcode.react
yarn add @walletconnect/universal-provider qrcode.react
bun add @walletconnect/universal-provider qrcode.react

Get a project ID from WalletConnect Cloud, then add it to your environment:

.env.local
WALLETCONNECT_PROJECT_ID=your-project-id
app/provider.tsx
<NitsoProvider
  appName="My App"
  appUrl="https://myapp.com"
  clusters={clusters}
  walletConnect={{
    projectId: process.env.WALLETCONNECT_PROJECT_ID!,
  }}
>
  {children}
</NitsoProvider>
.env
VITE_WALLETCONNECT_PROJECT_ID=your-project-id
src/main.tsx
<NitsoProvider
  appName="My App"
  appUrl="https://myapp.com"
  clusters={clusters}
  walletConnect={{
    projectId: import.meta.env.VITE_WALLETCONNECT_PROJECT_ID,
  }}
>
  <App />
</NitsoProvider>

Wallet Filtering

Control which detected wallets appear in the wallet modal.

// Show only specific wallets
const wallets = {
  allowList: ["Phantom", "Solflare", "Backpack"],
  featured: ["Phantom"],
};

// Hide specific wallets
const wallets = {
  denyList: ["WalletConnect"],
};

<NitsoProvider appName="My App" clusters={clusters} wallets={wallets}>
  {children}
</NitsoProvider>;

Matching is case-insensitive. denyList wins over allowList when the same wallet appears in both. featured only reorders — it doesn't filter.

Define wallets outside your component to keep the reference stable and avoid unnecessary re-renders.

Program Labels

Add human-readable names for program IDs to enrich transaction history labels.

<NitsoProvider
  appName="My App"
  clusters={clusters}
  programLabels={{
    JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4: "Jupiter",
    whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc: "Orca",
  }}
>
  {children}
</NitsoProvider>

Props

PropTypeDefaultDescription
appNamestringRequired. Shown in wallet connection prompts
appUrlstringRequired when walletConnect is enabled
clustersSolanaCluster[]Custom RPC endpoints per cluster
walletsWalletDisplayConfigFilter and prioritize detected wallets
autoConnectbooleantrueReconnect last wallet on page load
programLabelsRecord<string, string>Human-readable names for program IDs
walletConnectSimplifiedWalletConnectConfigEnable WalletConnect QR connections

On this page