Skip to content

anza-xyz/kit-plugins

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

195 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kit Plugins

ci

A library for Solana Kit that helps you build composable Solana clients with a modular plugin system.

Features

  • All-in-one bundle plugins for production, local development, and local testing.
  • Modular plugin system to compose custom clients by combining granular 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.

Quick Start

Production

Use the solanaRpc bundle plugin to set up a full Solana RPC client with transaction planning and execution.

pnpm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-payer
import { createClient } from '@solana/kit';
import { solanaRpc } from '@solana/kit-plugin-rpc';
import { payer } from '@solana/kit-plugin-payer';

const client = createClient()
    .use(payer(myProductionSigner))
    .use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }));

await client.sendTransaction([myInstruction]);

For mainnet type safety (preventing accidental use of devnet-only features like airdrops), use solanaMainnetRpc instead.

See all features and configuration options.

Local Development

Use solanaLocalRpc which defaults to http://127.0.0.1:8899 and includes airdrop support.

pnpm install @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-payer
import { createClient } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { payerFromFile } from '@solana/kit-plugin-payer';

const client = createClient().use(payerFromFile('~/.config/solana/id.json')).use(solanaLocalRpc());

await client.sendTransaction([myInstruction]);

For devnet, use solanaDevnetRpc which defaults to https://api.devnet.solana.com and also includes airdrop support.

See all features and configuration options.

Local Testing with LiteSVM

Use the litesvm bundle plugin for fast local blockchain simulation without a network connection.

pnpm install @solana/kit @solana/kit-plugin-litesvm @solana/kit-plugin-payer
import { createClient, lamports } from '@solana/kit';
import { litesvm } from '@solana/kit-plugin-litesvm';
import { generatedPayer } from '@solana/kit-plugin-payer';

const client = await createClient().use(generatedPayer()).use(litesvm());

// Fund the payer
await client.airdrop(client.payer.address, lamports(10_000_000_000n));

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

Compose Granular Plugins

The bundle plugins above are built from smaller, granular plugins. You can compose these granular plugins directly to build a custom setup tailored to your needs.

import { createClient } from '@solana/kit';
import {
    solanaRpcConnection,
    solanaRpcSubscriptionsConnection,
    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 createClient()
    .use(payerFromFile('path/to/keypair.json')) // Adds `client.payer` using a local keypair file.
    .use(solanaRpcConnection('https://api.devnet.solana.com')) // Adds `client.rpc`.
    .use(solanaRpcSubscriptionsConnection('wss://api.devnet.solana.com')) // Adds `client.rpcSubscriptions`.
    .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 core plugin interfaces 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.

Available Plugins

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 npm Connect to Solana clusters solanaRpc, solanaMainnetRpc, solanaDevnetRpc, solanaLocalRpc, rpcConnection, rpcSubscriptionsConnection, solanaRpcConnection, solanaRpcSubscriptionsConnection, rpcAirdrop, rpcGetMinimumBalance, rpcTransactionPlanner, rpcTransactionPlanExecutor
@solana/kit-plugin-payer npm Manage transaction fee payers payer, payerFromFile, generatedPayer, generatedPayerWithSol
@solana/kit-plugin-litesvm npm LiteSVM support litesvm, litesvmConnection, litesvmAirdrop, litesvmGetMinimumBalance, litesvmTransactionPlanner, litesvmTransactionPlanExecutor
@solana/kit-plugin-instruction-plan npm Transaction planning and execution transactionPlanner, transactionPlanExecutor, planAndSendTransactions

Community Plugins

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!

Create Your Own Plugins

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 });
}

createClient().use(apple()).use(appleTart()); // Ok
createClient().use(appleTart()); // TypeScript error

Plugins 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 createClient().use(magicFruit()).use(apple());

About

Plugins and presets to extend your Kit clients.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors