
Security News
GPT-6 Astra Attempts Supply Chain Attacks Against Open Source Maintainers in Testing
GPT-6 Astra hits 100% on ExploitBench and finds zero-days autonomously, while independent tests reveal scope violations and monitoring gaps.
@axvn-vn/kit-plugin-rpc
Advanced tools
This package provides plugins that add RPC functionality to your Kit clients.
pnpm install @solana/kit-plugin-rpc
solanaRpc pluginThe solanaRpc plugin sets up a full Solana RPC client in a single call. It installs an RPC connection, RPC Subscriptions, minimum balance computation, transaction planning, and transaction execution on the client.
The client must have a payer set before applying this plugin.
import { createClient } from '@solana/kit';
import { solanaRpc } from '@solana/kit-plugin-rpc';
import { payer } from '@solana/kit-plugin-signer';
const client = createClient()
.use(payer(myPayer))
.use(solanaRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }));
All options are provided via a SolanaRpcConfig object:
rpcUrl (required): URL of the Solana RPC endpoint.rpcSubscriptionsUrl: URL of the RPC Subscriptions endpoint. Defaults to the rpcUrl with the protocol changed from http to ws. As a convenience, the exact strings http://127.0.0.1:8899 and http://localhost:8899 (the canonical local validator RPC endpoints) are rewritten to port 8900. The match is exact-string only — any other host, scheme, or port (including https://localhost:8899 or http://0.0.0.0:8899) is left untouched. Pass rpcSubscriptionsUrl explicitly when your RPC and WebSocket endpoints use different ports.rpcConfig: Optional configuration forwarded to createSolanaRpc.rpcSubscriptionsConfig: Optional configuration forwarded to createSolanaRpcSubscriptions.transactionConfig: Options to configure how transaction messages are created. See the rpcTransactionPlanner options below.maxConcurrency: Maximum number of concurrent transaction executions. Defaults to 10.skipPreflight: Whether to always skip preflight simulation. Defaults to false.rpc: Call any Solana RPC method.rpcSubscriptions: Subscribe to Solana RPC notifications.getMinimumBalance: Compute minimum lamports for rent exemption.planTransaction(s): Plan instructions into transaction messages without executing them.sendTransaction(s): Plan and execute instructions, instruction plans, or transaction messages in one call.transactionPlanner / transactionPlanExecutor (deprecated): Fields kept for backward compatibility. Use planTransaction(s) / sendTransaction(s) instead.solanaMainnetRpc pluginA convenience wrapper around solanaRpc that types the connection as a mainnet URL, preventing accidental use of devnet-only features such as airdrops.
import { createClient } from '@solana/kit';
import { solanaMainnetRpc } from '@solana/kit-plugin-rpc';
import { payer } from '@solana/kit-plugin-signer';
const client = createClient()
.use(payer(myPayer))
.use(solanaMainnetRpc({ rpcUrl: 'https://api.mainnet-beta.solana.com' }));
See solanaRpc for available features.
solanaDevnetRpc pluginA convenience wrapper around solanaRpc that defaults to the public devnet endpoint (https://api.devnet.solana.com) and includes airdrop support for requesting SOL from the faucet.
import { createClient } from '@solana/kit';
import { solanaDevnetRpc } from '@solana/kit-plugin-rpc';
import { payerFromFile } from '@solana/kit-plugin-signer';
const client = createClient().use(payerFromFile('~/.config/solana/id.json')).use(solanaDevnetRpc());
See solanaRpc for available features, plus:
airdrop: Request SOL from the devnet faucet.
await client.airdrop(address('HQVxiMVDoV9jzG4tpoxmDZsNfWvaHXm8DGGv93Gka75v'), lamports(1_000_000_000n));
solanaTestnetRpc pluginA convenience wrapper around solanaRpc that defaults to the public testnet endpoint (https://api.testnet.solana.com) and includes airdrop support for requesting SOL from the faucet.
import { createClient } from '@solana/kit';
import { solanaTestnetRpc } from '@solana/kit-plugin-rpc';
import { payerFromFile } from '@solana/kit-plugin-signer';
const client = createClient().use(payerFromFile('~/.config/solana/id.json')).use(solanaTestnetRpc());
See solanaRpc for available features, plus:
airdrop: Request SOL from the testnet faucet.
await client.airdrop(address('HQVxiMVDoV9jzG4tpoxmDZsNfWvaHXm8DGGv93Gka75v'), lamports(1_000_000_000n));
solanaLocalRpc pluginA convenience wrapper around solanaRpc that defaults to http://127.0.0.1:8899 for the RPC and ws://127.0.0.1:8900 for subscriptions, and includes airdrop support.
import { createClient } from '@solana/kit';
import { solanaLocalRpc } from '@solana/kit-plugin-rpc';
import { payerFromFile } from '@solana/kit-plugin-signer';
const client = createClient().use(payerFromFile('~/.config/solana/id.json')).use(solanaLocalRpc());
See solanaRpc for available features, plus:
airdrop: Request SOL from the local validator faucet.
await client.airdrop(address('HQVxiMVDoV9jzG4tpoxmDZsNfWvaHXm8DGGv93Gka75v'), lamports(1_000_000_000n));
solanaRpcConnection pluginThe solanaRpcConnection plugin creates a Solana RPC and Solana RPC Subscriptions from a cluster URL and installs both on the client.
import { createClient } from '@solana/kit';
import { solanaRpcConnection } from '@solana/kit-plugin-rpc';
const client = createClient().use(solanaRpcConnection({ rpcUrl: 'https://api.mainnet-beta.solana.com' }));
You may wrap your RPC URL using the mainnet, devnet, or testnet helpers from @solana/kit. When you do, the returned RPC API will be adjusted to match the selected cluster since some RPC features are not available on all clusters.
import { mainnet } from '@solana/kit';
const client = createClient().use(solanaRpcConnection({ rpcUrl: mainnet('https://api.mainnet-beta.solana.com') }));
All options are provided via a SolanaRpcConnectionConfig object:
rpcUrl (required): URL of the Solana RPC endpoint.rpcSubscriptionsUrl: URL of the RPC Subscriptions endpoint. Defaults to the rpcUrl with the protocol changed from http to ws. As a convenience, the exact strings http://127.0.0.1:8899 and http://localhost:8899 (the canonical local validator RPC endpoints) are rewritten to port 8900. The match is exact-string only — any other host, scheme, or port (including https://localhost:8899 or http://0.0.0.0:8899) is left untouched. Pass rpcSubscriptionsUrl explicitly when your RPC and WebSocket endpoints use different ports.rpcConfig: Optional configuration forwarded to createSolanaRpc.rpcSubscriptionsConfig: Optional configuration forwarded to createSolanaRpcSubscriptions.rpc: Call any Solana RPC method using type-safe methods.
const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();
rpcSubscriptions: Subscribe to Solana RPC notifications using async iterators.
const slotNotifications = await client.rpcSubscriptions.slotNotifications({ commitment: 'confirmed' }).subscribe();
for await (const slotNotification of slotNotifications) {
console.log('Got a slot notification', slotNotification);
}
rpcAirdrop pluginThis plugin adds an airdrop method to your Kit client that requests SOL airdrops via the RPC and RPC Subscriptions transports.
[!NOTE] Airdrop is only available on test clusters (devnet, testnet) and local validators. Using this plugin with a mainnet RPC will produce a TypeScript error.
The client must have rpc and rpcSubscriptions installed before applying this plugin.
import { createClient } from '@solana/kit';
import { solanaRpcConnection, rpcAirdrop } from '@solana/kit-plugin-rpc';
const client = createClient()
.use(solanaRpcConnection({ rpcUrl: 'http://127.0.0.1:8899' }))
.use(rpcAirdrop());
airdrop: An asynchronous helper function that airdrops a specified amount of lamports to a given address.
await client.airdrop(address('HQVxiMVDoV9jzG4tpoxmDZsNfWvaHXm8DGGv93Gka75v'), lamports(1_000_000_000n));
rpcGetMinimumBalance pluginThis plugin adds a getMinimumBalance method to your Kit client that computes the minimum lamports required for an account with a given data size, using the getMinimumBalanceForRentExemption RPC method.
The client must have rpc installed before applying this plugin.
import { createClient } from '@solana/kit';
import { solanaRpcConnection, rpcGetMinimumBalance } from '@solana/kit-plugin-rpc';
const client = createClient()
.use(solanaRpcConnection({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
.use(rpcGetMinimumBalance());
getMinimumBalance: An asynchronous helper that returns the minimum lamports required for an account with the given data size. By default, the 128-byte account header is included on top of the provided space.
// Minimum balance for an account with 100 bytes of data (plus header).
const balance = await client.getMinimumBalance(100);
// Minimum balance for exactly 100 bytes (without adding the header).
const rawBalance = await client.getMinimumBalance(100, { withoutHeader: true });
rpcTransactionPlanner pluginAdds planTransaction and planTransactions to the client, using a planner that plans instructions into transaction messages with a fee payer, provisory resource limits (a compute unit limit, plus a loaded accounts data size limit for version 1 transactions), and optional priority fees. The fee payer is read from client.payer lazily, at plan time, so a dynamic payer (such as a connected wallet) is always respected.
The client must have a payer set before installing the plugin.
import { createClient } from '@solana/kit';
import { rpcTransactionPlanSendingExecutor, rpcTransactionPlanner, solanaRpcConnection } from '@solana/kit-plugin-rpc';
import { generatedPayer } from '@solana/kit-plugin-signer';
const client = await createClient()
.use(solanaRpcConnection({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
.use(generatedPayer())
.use(rpcTransactionPlanner())
.use(rpcTransactionPlanSendingExecutor());
const transactionPlan = await client.planTransactions(myInstructionPlan);
All options are provided via a TransactionPlannerConfig object. Its shape is discriminated by the transaction version.
For legacy and version 0 transactions:
version: The transaction message version to use. Accepts 0 or 'legacy'. Defaults to 0.microLamportsPerComputeUnit: The priority fee in micro-lamports per compute unit, added as a setComputeUnitPrice instruction. Defaults to no priority fees.estimateResourceLimits: Whether to estimate and set resource limits by simulating before sending. Set to false to skip estimation and reserve no provisory limits, which is useful for transactions close to the message size limit. Defaults to true.Version 1 transactions are defined for forward compatibility but are not yet buildable by @solana/kit; passing version: 1 currently throws. When available, version 1 will accept priorityFeeLamports (a flat total in lamports) instead of microLamportsPerComputeUnit, alongside the shared estimateResourceLimits option.
rpcTransactionPlanSendingExecutor pluginAdds sendTransaction and sendTransactions to the client, using an executor that estimates resource limits, signs, and sends transactions via RPC. Resource limit estimation covers the compute unit limit and, for version 1 transactions, the loaded accounts data size limit.
The client must have rpc and rpcSubscriptions configured, and a transaction planner installed, before installing this plugin — sending plans through the client's planning functions.
import { createClient } from '@solana/kit';
import { rpcTransactionPlanSendingExecutor, rpcTransactionPlanner, solanaRpcConnection } from '@solana/kit-plugin-rpc';
import { generatedPayer } from '@solana/kit-plugin-signer';
const client = await createClient()
.use(solanaRpcConnection({ rpcUrl: 'https://api.mainnet-beta.solana.com' }))
.use(generatedPayer())
.use(rpcTransactionPlanner())
.use(rpcTransactionPlanSendingExecutor());
const transactionPlanResult = await client.sendTransactions(myInstructionPlan);
All options are provided via a RpcTransactionPlanExecutorConfig object:
estimateResourceLimits: Whether to estimate and set resource limits by simulating before sending (default: true). This should match the estimateResourceLimits option on the planner; solanaRpc keeps them in sync automatically.getComputeUnitLimitFromEstimate: A (estimatedComputeUnits: number) => number function that maps the estimated compute unit consumption to the compute unit limit to set, adding headroom for variation between simulation and execution. Defaults to a function that adds a buffer on top of the estimate of at least 300 compute units, or a margin that decays linearly from 10% at low estimates to 2% at 500,000 compute units and above, whichever is greater. The result is always capped at 1,400,000 (the per-transaction maximum).maxConcurrency: Maximum number of concurrent executions (default: 10).skipPreflight: Whether to skip the preflight simulation when sending transactions (default: false).As it works through a transaction, the executor records the planned message (once its blockhash lifetime and resource limits are set), the fully signed transaction, and the signature it was sent under. A successful plan result carries all three on its context, and the exported RpcSendContext type names that shape so you can annotate results yourself.
import { SuccessfulSingleTransactionPlanResult } from '@solana/kit';
import { RpcSendContext } from '@solana/kit-plugin-rpc';
function logSentTransaction(result: SuccessfulSingleTransactionPlanResult<RpcSendContext>) {
console.log(
`Sent ${result.context.signature} using blockhash ${result.context.message.lifetimeConstraint.blockhash}`,
);
}
Because the context is filled in as execution progresses, a transaction that fails or is canceled part way through carries only what was recorded before it stopped. Failed and canceled results therefore type the context as partial — only successful results guarantee every field.
The sendTransaction and sendTransactions functions installed by this plugin propagate this context type, so their results carry a typed RpcSendContext without any annotation needed.
By default, the executor estimates resource limits by simulating the transaction before sending it. This covers the compute unit limit and, for version 1 transactions, the loaded accounts data size limit. When estimation is performed, preflight is skipped to avoid a redundant second simulation. When every applicable resource limit is already explicitly set (no estimation needed), preflight runs as the only simulation.
Setting skipPreflight: true changes the behavior:
getComputeUnitLimitFromEstimate applied) so the transaction still reaches the validator. This is useful for debugging failed transactions in an explorer.| Scenario | skipPreflight: false (default) | skipPreflight: true |
|---|---|---|
| Estimation succeeds | Set limits, skip preflight | Set limits, skip preflight |
| Estimation fails | Throw | Use consumed resources, skip preflight |
| Explicit limits set | Run preflight | Skip preflight |
Set estimateResourceLimits: false to opt out of resource limit estimation entirely. The planner then reserves no provisory resource limits and the executor does not simulate to estimate or inject any; any explicit resource limits already present on the message are preserved. This is useful for transactions close to the message size limit, where adding a compute budget instruction would make an otherwise valid transaction too large.
Note that disabling estimation does not disable preflight. When estimateResourceLimits: false and skipPreflight is left at its default false, the executor still runs a preflight simulation when sending — this becomes the only simulation. To avoid all simulation overhead, set skipPreflight: true as well.
When using solanaRpc, both the planner and executor read estimateResourceLimits from a single place: transactionConfig.
const client = createClient()
.use(payer(myPayer))
.use(
solanaRpc({
rpcUrl: 'https://api.mainnet-beta.solana.com',
skipPreflight: true,
transactionConfig: { estimateResourceLimits: false },
}),
);
Because a transaction can consume slightly more compute units at execution time than during simulation, the executor adds a buffer to the estimated compute unit limit. By default this buffer is the greater of a fixed minimum of 300 compute units and a margin that decays linearly from 10% at low estimates to 2% at 500,000 compute units and above, added on top of the estimate.
Override this by passing a getComputeUnitLimitFromEstimate function that maps the raw estimate to the limit to set. It is applied on both successful estimation and the skipPreflight recovery path. The resulting limit is always capped at 1,400,000, the maximum number of compute units allowed per transaction, including for custom functions.
const client = createClient()
.use(payer(myPayer))
.use(
solanaRpc({
rpcUrl: 'https://api.mainnet-beta.solana.com',
// Add a flat 20% buffer instead of the default curve.
getComputeUnitLimitFromEstimate: estimatedComputeUnits => Math.ceil(estimatedComputeUnits * 1.2),
}),
);
The following plugins are still exported for backward compatibility but are deprecated. Prefer solanaRpcConnection for new code.
rpcConnection(rpc) / rpcSubscriptionsConnection(rpcSubscriptions): Trivial wrappers around extendClient. Inline extendClient({ rpc }) or extendClient({ rpcSubscriptions }) instead, or use solanaRpcConnection when starting from a cluster URL.
solanaRpcSubscriptionsConnection(url, config?): No longer needed because solanaRpcConnection installs both rpc and rpcSubscriptions.
rpcTransactionPlanExecutor(config?): Only sets the deprecated client.transactionPlanExecutor field. Use rpcTransactionPlanSendingExecutor instead, which installs sendTransaction and sendTransactions alongside the executor.
// Before
const client = await createClient()
.use(rpcTransactionPlanner())
.use(rpcTransactionPlanExecutor())
.use(planAndSendTransactions());
// After
const client = await createClient().use(rpcTransactionPlanner()).use(rpcTransactionPlanSendingExecutor());
FAQs
RPC support for Kit clients
We found that @axvn-vn/kit-plugin-rpc 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.

Security News
GPT-6 Astra hits 100% on ExploitBench and finds zero-days autonomously, while independent tests reveal scope violations and monitoring gaps.

Product
Socket can now send alerts and supply chain attack notifications to Microsoft Teams, with filters that route the right updates to each channel.

Security News
pnpm 12 rewrites the package manager in Rust, cutting install times by up to 90% while preserving pnpm 11 workflows and lockfiles.