
Security News
Federal Audit Finds NIST Wasted Funds With No Plan to Clear NVD Backlog
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.
@solana/client
Advanced tools
Framework-agnostic Solana client orchestration layer powering higher-level experiences
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.
npm install @solana/client
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: { /* ... */ } });
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());
}
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();
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();
const signature = await client.actions.requestAirdrop(address, 1_000_000_000n); // 1 SOL
console.log(signature.toString());
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());
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 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,
});
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]);
const nonce = await client.actions.fetchNonceAccount(
toAddress("NonceAccountAddress111111111111111111111111"),
);
console.log(`Nonce: ${nonce.blockhash}`);
console.log(`Authority: ${nonce.authority}`);
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());
const watcher = client.watchers.watchSignature(
{ signature, commitment: "confirmed" },
(notification) => console.log("Signature update:", notification),
);
// Later…
watcher.abort();
Pass a cluster moniker to auto-resolve RPC + WebSocket URLs. Monikers map to:
mainnet / mainnet-beta → https://api.mainnet-beta.solana.comtestnet → https://api.testnet.solana.comdevnet (default) → https://api.devnet.solana.comlocalnet / localhost → http://127.0.0.1:8899WebSocket 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:
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.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"),
});
autoDiscover() picks up Wallet Standard injectables; use filterByNames() to filter by name, or compose phantom(), solflare(), backpack(), etc. when you need explicit control.createStore to createClient for custom persistence or server-side stores. serializeSolanaState / deserializeSolanaState help save and restore cluster + wallet metadata.fetchAccount, fetchBalance, fetchLookupTable, fetchLookupTables, fetchNonceAccount, setCluster, requestAirdrop, sendTransaction, and wallet connect/disconnect keep the store in sync.watchAccount, watchBalance, and watchSignature stream updates into the store and return an abort() handle for cleanup.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.pnpm build – compile JS and type definitionspnpm test:typecheck – strict type-checkingpnpm lint / pnpm format – Biome-powered linting and formattingexamples/vite-react (run with pnpm install && pnpm dev).examples/nextjs.src/actions.ts, src/watchers, and src/features/* for helper internals.FAQs
Framework-agnostic Solana client orchestration layer powering higher-level experiences
The npm package @solana/client receives a total of 2,902 weekly downloads. As such, @solana/client popularity was classified as popular.
We found that @solana/client demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Federal audit finds NIST lacked a plan to clear the NVD backlog, wasted funds on duplicate work, and delayed use of CISA data.

Research
/Security News
A mini Shai-Hulud campaign compromised Red Hat Cloud Services npm packages to steal developer and CI/CD secrets during installation.

Research
/Security News
The North Korean malware loader hides in a Packagist-listed package and its GitHub branch to fetch and execute remote code in a likely Contagious Interview-style lure.