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

@solana/client

v1.7.0

Published

Framework-agnostic Solana client orchestration layer powering higher-level experiences

Readme

@solana/client

Framework-agnostic building blocks for Solana RPC, subscriptions, wallets, and transactions. Works in any runtime (React, Svelte, API routes, workers, etc.).

Status: Experimental – expect rapid iteration.

Install

npm install @solana/client

ConnectorKit (optional)

ConnectorKit integration is available as a stable, opt-in entrypoint: @solana/client/connectorkit.

This requires installing @solana/connector (an optional peer dependency of @solana/client):

npm install @solana/connector
import { connectorKit } from "@solana/client/connectorkit";

const walletConnectors = connectorKit({ defaultConfig: { /* ... */ } });

Quickstart

  1. Choose Wallet Standard connectors (auto-discovery is the fastest way to start).
  2. Create a Solana client.
  3. Call actions, watchers, and helpers anywhere in your app (React, APIs, workers, etc.).
import { autoDiscover, createClient } from "@solana/client";

const client = createClient({
  endpoint: "https://api.devnet.solana.com",
  websocketEndpoint: "wss://api.devnet.solana.com",
  walletConnectors: autoDiscover(),
});

// Connect Wallet Standard apps via their connector ids.
// Recommended: use canonical ids like "wallet-standard:phantom" (aliases like "phantom" also work).
await client.actions.connectWallet("wallet-standard:phantom");

// Fetch an account once.
const wallet = client.store.getState().wallet;
if (wallet.status === "connected") {
  const account = await client.actions.fetchAccount(wallet.session.account.address);
  console.log(account.lamports?.toString());
}

Common Solana flows (copy/paste)

Connect, disconnect, and inspect wallet state

const connectors = client.connectors.all; // Wallet Standard-aware connectors

await client.actions.connectWallet(connectors[0].id);

const wallet = client.store.getState().wallet;
if (wallet.status === "connected") {
  console.log(wallet.session.account.address.toString());
}

await client.actions.disconnectWallet();

Fetch and watch lamports

import { toAddress } from "@solana/client";

const address = toAddress("Fg6PaFpoGXkYsidMpWFKfwtz6DhFVyG4dL1x8kj7ZJup");

const lamports = await client.actions.fetchBalance(address);
console.log(`Lamports: ${lamports.toString()}`);

const watcher = client.watchers.watchBalance({ address }, (nextLamports) => {
  console.log("Updated balance:", nextLamports.toString());
});

// Later…
watcher.abort();

Request an airdrop (devnet/testnet)

const signature = await client.actions.requestAirdrop(address, 1_000_000_000n); // 1 SOL
console.log(signature.toString());

Send SOL

const wallet = client.store.getState().wallet;
if (wallet.status !== "connected") throw new Error("Connect wallet first");

const signature = await client.solTransfer.sendTransfer({
  amount: 100_000_000n, // 0.1 SOL
  authority: wallet.session, // Wallet Standard session
  destination: "Ff34MXWdgNsEJ1kJFj9cXmrEe7y2P93b95mGu5CJjBQJ",
});
console.log(signature.toString());

SPL token balance + transfer

const wallet = client.store.getState().wallet;
if (wallet.status !== "connected") throw new Error("Connect wallet first");

const usdc = client.splToken({ mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" }); // USDC

const balance = await usdc.fetchBalance(wallet.session.account.address);
console.log(`Balance: ${balance.uiAmount}`);

const signature = await usdc.sendTransfer({
  amount: 1n,
  authority: wallet.session,
  destinationOwner: "Ff34MXWdgNsEJ1kJFj9cXmrEe7y2P93b95mGu5CJjBQJ",
});
console.log(signature.toString());

Token 2022 support

Token 2022 mints are supported via the tokenProgram option:

// Auto-detect Token or Token 2022 (recommended)
const token = client.splToken({
  mint: "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo", // PYUSD
  tokenProgram: "auto",
});

// Or explicitly specify Token 2022 program
import { TOKEN_2022_PROGRAM_ADDRESS } from "@solana/client";

const token2022 = client.splToken({
  mint: mintAddress,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS,
});

// Balance and transfers work the same way
const balance = await token.fetchBalance(wallet.session.account.address);
const signature = await token.sendTransfer({
  amount: 10,
  authority: wallet.session,
  destinationOwner: recipientAddress,
});

Fetch address lookup tables

import { toAddress } from "@solana/client";

// Single lookup table
const lut = await client.actions.fetchLookupTable(
  toAddress("AddressLookupTab1e1111111111111111111111111"),
);
console.log(`Addresses in LUT: ${lut.addresses.length}`);

// Multiple lookup tables
const luts = await client.actions.fetchLookupTables([lutAddress1, lutAddress2]);

Fetch nonce accounts

const nonce = await client.actions.fetchNonceAccount(
  toAddress("NonceAccountAddress111111111111111111111111"),
);
console.log(`Nonce: ${nonce.blockhash}`);
console.log(`Authority: ${nonce.authority}`);

Build and send arbitrary transactions

import { getTransferSolInstruction } from "@solana-program/system";

const wallet = client.store.getState().wallet;
if (wallet.status !== "connected") throw new Error("Connect wallet first");

const prepared = await client.transaction.prepare({
  authority: wallet.session,
  instructions: [
    getTransferSolInstruction({
      destination: "Ff34MXWdgNsEJ1kJFj9cXmrEe7y2P93b95mGu5CJjBQJ",
      lamports: 10_000n,
      source: wallet.session.account.address,
    }),
  ],
  version: "auto", // defaults to 0 when lookups exist, otherwise 'legacy'
});

// Inspect or serialize first.
const wire = await client.transaction.toWire(prepared);

// Submit.
const signature = await client.transaction.send(prepared);
console.log(signature.toString());

Watch signature confirmations

const watcher = client.watchers.watchSignature(
  { signature, commitment: "confirmed" },
  (notification) => console.log("Signature update:", notification),
);

// Later…
watcher.abort();

Cluster monikers and endpoints

Pass a cluster moniker to auto-resolve RPC + WebSocket URLs. Monikers map to:

  • mainnet / mainnet-betahttps://api.mainnet-beta.solana.com
  • testnethttps://api.testnet.solana.com
  • devnet (default) → https://api.devnet.solana.com
  • localnet / localhosthttp://127.0.0.1:8899

WebSocket URLs are inferred (wss:// or ws://) when not supplied. Override with endpoint/rpc or websocket/websocketEndpoint when you need a custom host.

import { autoDiscover, createClient } from "@solana/client";

const client = createClient({
  cluster: "mainnet", // or 'devnet' | 'testnet' | 'localnet' | 'localhost'
  walletConnectors: autoDiscover(),
});

Custom endpoint with inferred WebSocket:

const client = createClient({
  endpoint: "http://127.0.0.1:8899", // websocket inferred as ws://127.0.0.1:8900
});

Use resolveCluster directly when you need the resolved URLs without creating a client:

import { resolveCluster } from "@solana/client";

const resolved = resolveCluster({ moniker: "testnet" });
console.log(resolved.endpoint, resolved.websocketEndpoint);

Notes:

  • Default moniker is devnet when nothing is provided; moniker becomes custom when you pass a raw endpoint.
  • createClient, createDefaultClient (resolveClientConfig), and SolanaProvider all use resolveCluster under the hood, so the moniker/endpoint behavior is consistent across entrypoints.

Wallet connector filtering

Use filterByNames with autoDiscover() to filter wallets by name without wallet-specific code:

import { autoDiscover, filterByNames } from "@solana/client";

// Only show Phantom and Solflare
const connectors = autoDiscover({
  filter: filterByNames("phantom", "solflare"),
});

const client = createClient({
  cluster: "devnet",
  walletConnectors: connectors,
});

This approach follows Wallet Standard's wallet-agnostic discovery pattern while still allowing you to curate which wallets appear in your app.

You can also write custom filter functions:

const connectors = autoDiscover({
  filter: (wallet) => wallet.name.toLowerCase().includes("phantom"),
});

Notes and defaults

  • Wallet connectors: autoDiscover() picks up Wallet Standard injectables; use filterByNames() to filter by name, or compose phantom(), solflare(), backpack(), etc. when you need explicit control.
  • Store: built on Zustand; pass createStore to createClient for custom persistence or server-side stores. serializeSolanaState / deserializeSolanaState help save and restore cluster + wallet metadata.
  • Actions: fetchAccount, fetchBalance, fetchLookupTable, fetchLookupTables, fetchNonceAccount, setCluster, requestAirdrop, sendTransaction, and wallet connect/disconnect keep the store in sync.
  • Watchers: watchAccount, watchBalance, and watchSignature stream updates into the store and return an abort() handle for cleanup.
  • Helpers: solTransfer, splToken, and transaction cover common transfers plus low-level prepare/sign/toWire flows. Transaction versions default to 0 when any instruction references address lookup tables, otherwise legacy; override with version when needed.

Scripts

  • pnpm build – compile JS and type definitions
  • pnpm test:typecheck – strict type-checking
  • pnpm lint / pnpm format – Biome-powered linting and formatting

More resources

  • Documentation — full guides and API reference
  • Playground: examples/vite-react (run with pnpm install && pnpm dev).
  • Next.js reference app: examples/nextjs.
  • Client APIs live in src/actions.ts, src/watchers, and src/features/* for helper internals.