A plugin library for Solana Kit that provides ready-to-use clients for your Solana applications!
- ✨ Ready-to-use clients for production, local development, and local testing.
- ✨ Modular plugin system to build custom clients by combining individual plugins.
- ✨ Default transaction planning and execution logic built-in, just call
client.sendTransaction(myInstructions). - ✨ Various useful plugins for RPC connectivity, payer management, SOL airdrops, LiteSVM support and more.
Choose from the following three ready-to-use clients!
Pre-configured client for production use with real Solana clusters.
pnpm install @solana/kit @solana/kit-client-rpcimport { generateKeyPairSigner } from '@solana/kit';
import { createClient } from '@solana/kit-client-rpc';
const payer = await generateKeyPairSigner();
const client = createClient({ payer, url: 'https://api.devnet.solana.com' });
// Send transactions
await client.sendTransaction([myInstruction]);See all features and configuration options.
Pre-configured client for localhost development with automatic payer funding.
pnpm install @solana/kit @solana/kit-client-rpcimport { createLocalClient } from '@solana/kit-client-rpc';
import { lamports } from '@solana/kit';
const client = await createLocalClient();
// Payer is auto-generated and funded with SOL
console.log('Payer address:', client.payer.address);
await client.sendTransaction([myInstruction]);See all features and configuration options.
Pre-configured client using LiteSVM for testing without an RPC connection.
pnpm install @solana/kit @solana/kit-client-litesvmimport { createClient } from '@solana/kit-client-litesvm';
const client = await createClient();
// Set up test environment
client.svm.setAccount(myTestAccount);
client.svm.addProgramFromFile(myProgramAddress, 'program.so');
// Execute transactions locally
await client.sendTransaction([myInstruction]);See all features and configuration options.
None of the ready-to-use clients fit your needs? No worries! You can build your own custom clients by combining individual plugins like so.
import { createEmptyClient } from '@solana/kit';
import { rpc, rpcAirdrop, rpcTransactionPlanner, rpcTransactionPlanExecutor } from '@solana/kit-plugin-rpc';
import { payerFromFile } from '@solana/kit-plugin-payer';
import { planAndSendTransactions } from '@solana/kit-plugin-instruction-plan';
const client = await createEmptyClient() // An empty client with a `use` method to install plugins.
.use(rpc('https://api.devnet.solana.com')) // Adds `client.rpc` and `client.rpcSubscriptions`.
.use(payerFromFile('path/to/keypair.json')) // Adds `client.payer` using a local keypair file.
.use(rpcAirdrop()) // Adds `client.airdrop` to request SOL from faucets.
.use(rpcTransactionPlanner()) // Adds `client.transactionPlanner`.
.use(rpcTransactionPlanExecutor()) // Adds `client.transactionPlanExecutor`.
.use(planAndSendTransactions()); // Adds `client.planTransaction(s)` and `client.sendTransaction(s)`.Note that since plugins are defined in @solana/kit itself, you're not limited to the plugins in this repo! You can use community plugins or even create your own.
| Package | Version | Description | Exports |
|---|---|---|---|
@solana/kit-client-rpc |
Pre-configured RPC client | createClient, createLocalClient |
|
@solana/kit-client-litesvm |
Pre-configured LiteSVM client | createClient |
Do you know any? Please open a PR to add them here!
This repo provides the following individual plugin packages. You can learn more about each package by following the links to their READMEs below.
| Package | Version | Description | Plugins |
|---|---|---|---|
@solana/kit-plugin-rpc |
Connect to Solana clusters | rpc, localhostRpc, rpcAirdrop, rpcTransactionPlanner, rpcTransactionPlanExecutor |
|
@solana/kit-plugin-payer |
Manage transaction fee payers | payer, payerFromFile, generatedPayer, generatedPayerWithSol |
|
@solana/kit-plugin-litesvm |
LiteSVM support | litesvm, litesvmAirdrop, litesvmTransactionPlanner, litesvmTransactionPlanExecutor |
|
@solana/kit-plugin-instruction-plan |
Transaction planning and execution | transactionPlanner, transactionPlanExecutor, planAndSendTransactions |
| Package | Description | Plugins | Maintainers |
|---|---|---|---|
airdrop-token (unpublished) |
Create token mints, ATAs, and mint tokens for testing | airdropToken, testTokenPlugin |
@amilz |
local-validator (unpublished) |
Solana test validator lifecycle management (start, stop, restart) | localValidatorPlugin |
@amilz |
transaction-builder (unpublished) |
Transaction builder for constructing, signing, and sending transactions | transactionBuilderPlugin |
@amilz |
Do you know any? Please open a PR to add them here!
A plugin is defined in @solana/kit as a function that takes a client object and returns a new one (or a promise that resolves to a new one).
export type ClientPlugin<TInput extends object, TOutput extends Promise<object> | object> = (input: TInput) => TOutput;This means you can create plugins that extend clients like so:
function apple() {
return <T extends object>(client: T) => ({ ...client, fruit: 'apple' as const });
}While this works, it is recommended to use the extendClient utility from @solana/kit instead. Unlike a plain object spread, extendClient preserves property descriptors (such as getter functions and symbol-keyed properties) from the original client.
import { extendClient } from '@solana/kit';
function apple() {
return <T extends object>(client: T) => extendClient(client, { fruit: 'apple' as const });
}You may also add requirements to your plugins to ensure that other plugins have been installed beforehand. For instance, in the example below, the appleTart plugin requires that the apple plugin has already been installed on the client.
function appleTart() {
return <T extends { fruit: 'apple' }>(client: T) => extendClient(client, { dessert: 'appleTart' as const });
}
createEmptyClient().use(apple()).use(appleTart()); // Ok
createEmptyClient().use(appleTart()); // TypeScript errorPlugins can also be asynchronous if required and return promises that resolve to clients.
function magicFruit() {
return async <T extends object>(client: T) => {
const fruit = await fetchSomeMagicFruit();
return extendClient(client, { fruit });
};
}The use function on the client takes care of awaiting asynchronous plugins automatically, so you can use them seamlessly alongside synchronous ones and simply await the final client when required.
const client = await createEmptyClient().use(magicFruit()).use(apple());