Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/strong-bananas-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solana/kit-plugin-rpc': minor
---

Add granular `rpcConnection`, `rpcSubscriptionsConnection`, `solanaRpcConnection`, and `solanaRpcSubscriptionsConnection` plugins. Deprecate `rpc` and `localhostRpc` in favor of the new granular alternatives.
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,19 @@ None of the ready-to-use clients fit your needs? No worries! You can **build you

```ts
import { createClient } from '@solana/kit';
import { rpc, rpcAirdrop, rpcTransactionPlanner, rpcTransactionPlanExecutor } from '@solana/kit-plugin-rpc';
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() // An empty client with a `use` method to install plugins.
.use(rpc('https://api.devnet.solana.com')) // Adds `client.rpc` and `client.rpcSubscriptions`.
.use(solanaRpcConnection('https://api.devnet.solana.com')) // Adds `client.rpc`.
.use(solanaRpcSubscriptionsConnection('wss://api.devnet.solana.com')) // Adds `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`.
Expand All @@ -119,12 +126,12 @@ _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`](./packages/kit-plugin-rpc) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-rpc.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-rpc) | Connect to Solana clusters | `rpc`, `localhostRpc`, `rpcAirdrop`, `rpcGetMinimumBalance`, `rpcTransactionPlanner`, `rpcTransactionPlanExecutor` |
| [`@solana/kit-plugin-payer`](./packages/kit-plugin-payer) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-payer.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-payer) | Manage transaction fee payers | `payer`, `payerFromFile`, `generatedPayer`, `generatedPayerWithSol` |
| [`@solana/kit-plugin-litesvm`](./packages/kit-plugin-litesvm) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-litesvm.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-litesvm) | LiteSVM support | `litesvm`, `litesvmAirdrop`, `litesvmGetMinimumBalance`, `litesvmTransactionPlanner`, `litesvmTransactionPlanExecutor` |
| [`@solana/kit-plugin-instruction-plan`](./packages/kit-plugin-instruction-plan) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-instruction-plan.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-instruction-plan) | Transaction planning and execution | `transactionPlanner`, `transactionPlanExecutor`, `planAndSendTransactions` |
| Package | Version | Description | Plugins |
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`@solana/kit-plugin-rpc`](./packages/kit-plugin-rpc) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-rpc.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-rpc) | Connect to Solana clusters | `rpcConnection`, `rpcSubscriptionsConnection`, `solanaRpcConnection`, `solanaRpcSubscriptionsConnection`, `rpcAirdrop`, `rpcGetMinimumBalance`, `rpcTransactionPlanner`, `rpcTransactionPlanExecutor` |
| [`@solana/kit-plugin-payer`](./packages/kit-plugin-payer) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-payer.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-payer) | Manage transaction fee payers | `payer`, `payerFromFile`, `generatedPayer`, `generatedPayerWithSol` |
| [`@solana/kit-plugin-litesvm`](./packages/kit-plugin-litesvm) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-litesvm.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-litesvm) | LiteSVM support | `litesvm`, `litesvmAirdrop`, `litesvmGetMinimumBalance`, `litesvmTransactionPlanner`, `litesvmTransactionPlanExecutor` |
| [`@solana/kit-plugin-instruction-plan`](./packages/kit-plugin-instruction-plan) | [![npm](https://img.shields.io/npm/v/@solana/kit-plugin-instruction-plan.svg?style=flat)](https://www.npmjs.com/package/@solana/kit-plugin-instruction-plan) | Transaction planning and execution | `transactionPlanner`, `transactionPlanExecutor`, `planAndSendTransactions` |

## Community Plugins

Expand Down
12 changes: 8 additions & 4 deletions packages/kit-plugin-payer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,14 @@ Note that this plugin requires an airdrop plugin to be installed on the client b

```ts
import { createClient } from '@solana/kit';
import { localhostRpc, rpcAirdrop } from '@solana/kit-plugin-rpc';
import { solanaRpcConnection, solanaRpcSubscriptionsConnection, rpcAirdrop } from '@solana/kit-plugin-rpc';
import { generatedPayerWithSol } from '@solana/kit-plugin-payer';

const client = await createClient()
.use(localhostRpc()) // or .use(litesvm()).use(litesvmAirdrop())
.use(solanaRpcConnection('http://127.0.0.1:8899'))
.use(solanaRpcSubscriptionsConnection('ws://127.0.0.1:8900'))
.use(rpcAirdrop())
// or .use(litesvm()).use(litesvmAirdrop())
.use(generatedPayerWithSol(lamports(10_000_000_000n))); // 10 SOL
```

Expand All @@ -90,16 +92,18 @@ When no explicit payer is given, this plugin requires an airdrop plugin to be in

```ts
import { createClient } from '@solana/kit';
import { localhostRpc, rpcAirdrop } from '@solana/kit-plugin-rpc';
import { solanaRpcConnection, solanaRpcSubscriptionsConnection, rpcAirdrop } from '@solana/kit-plugin-rpc';
import { payerOrGeneratedPayer } from '@solana/kit-plugin-payer';

// With an explicit payer — no airdrop needed.
const client = await createClient().use(payerOrGeneratedPayer(mySigner));

// Without a payer — generates one and airdrops 100 SOL.
const client = await createClient()
.use(localhostRpc()) // or .use(litesvm()).use(litesvmAirdrop())
.use(solanaRpcConnection('http://127.0.0.1:8899'))
.use(solanaRpcSubscriptionsConnection('ws://127.0.0.1:8900'))
.use(rpcAirdrop())
// or .use(litesvm()).use(litesvmAirdrop())
.use(payerOrGeneratedPayer(undefined));
```

Expand Down
5 changes: 3 additions & 2 deletions packages/kit-plugin-payer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,16 @@ export function payerFromFile(path: string) {
* @example
* ```ts
* import { createClient } from '@solana/kit';
* import { localhostRpc, rpcAirdrop } from '@solana/kit-plugin-rpc';
* import { solanaRpcConnection, solanaRpcSubscriptionsConnection, rpcAirdrop } from '@solana/kit-plugin-rpc';
* import { payerOrGeneratedPayer } from '@solana/kit-plugin-payer';
*
* // With an explicit payer.
* const client = await createClient().use(payerOrGeneratedPayer(mySigner));
*
* // Without a payer — generates one and airdrops 100 SOL.
* const client = await createClient()
* .use(localhostRpc())
* .use(solanaRpcConnection('http://127.0.0.1:8899'))
* .use(solanaRpcSubscriptionsConnection('ws://127.0.0.1:8900'))
* .use(rpcAirdrop())
* .use(payerOrGeneratedPayer(undefined));
* ```
Expand Down
121 changes: 84 additions & 37 deletions packages/kit-plugin-rpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,70 @@ This package provides plugins that add RPC functionality to your Kit clients.
pnpm install @solana/kit-plugin-rpc
```

## `rpc` plugin
## `rpcConnection` plugin

The RPC plugin adds `rpc` and `rpcSubscriptions` objects to your Kit client, allowing you to call RPC methods and subscribe to RPC notifications.
The `rpcConnection` plugin sets a provided `Rpc` instance on the client. This is the generic variant that works with any RPC API.

### Installation

To use the `rpc` plugin, you must provide the URL of your desired Solana RPC endpoint.
```ts
import { createClient, createSolanaRpc } from '@solana/kit';
import { rpcConnection } from '@solana/kit-plugin-rpc';

const myRpc = createSolanaRpc('https://api.mainnet-beta.solana.com');
const client = createClient().use(rpcConnection(myRpc));
```

### Features

- `rpc`: Call any RPC method using type-safe methods.
```ts
const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();
```

## `rpcSubscriptionsConnection` plugin

The `rpcSubscriptionsConnection` plugin sets a provided `RpcSubscriptions` instance on the client. This is the generic variant that works with any RPC Subscriptions API.

### Installation

```ts
import { createClient } from '@solana/kit';
import { rpc } from '@solana/kit-plugin-rpc';
import { createClient, createSolanaRpcSubscriptions } from '@solana/kit';
import { rpcSubscriptionsConnection } from '@solana/kit-plugin-rpc';

const client = createClient().use(rpc('https://api.mainnet-beta.solana.com'));
const myRpcSubscriptions = createSolanaRpcSubscriptions('wss://api.mainnet-beta.solana.com');
const client = createClient().use(rpcSubscriptionsConnection(myRpcSubscriptions));
```

Note that 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.
### Features

- `rpcSubscriptions`: Subscribe to RPC notifications using async iterators.
```ts
const slotNotifications = await client.rpcSubscriptions.slotNotifications({ commitment: 'confirmed' }).subscribe();
for await (const slotNotification of slotNotifications) {
console.log('Got a slot notification', slotNotification);
}
```

## `solanaRpcConnection` plugin

The `solanaRpcConnection` plugin creates a Solana RPC from a cluster URL and sets it on the client.

### Installation

```ts
import { mainnet } from '@solana/kit';
import { createClient } from '@solana/kit';
import { solanaRpcConnection } from '@solana/kit-plugin-rpc';

const client = createClient().use(rpc(mainnet('https://api.mainnet-beta.solana.com')));
const client = createClient().use(solanaRpcConnection('https://api.mainnet-beta.solana.com'));
```

By default, the WebSocket URL is derived from the RPC's HTTP URL but you may configure it explicitly using the second parameter. This config object can also be used to customize other aspects of RPC Subscriptions behavior.
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.

```ts
const client = createClient().use(
rpc('https://my-rpc-url.com', {
url: 'wss://my-rpc-ws-url.com',
minChannels: 5,
maxSubscriptionsPerChannel: 50,
}),
);
import { mainnet } from '@solana/kit';

const client = createClient().use(solanaRpcConnection(mainnet('https://api.mainnet-beta.solana.com')));
```

### Features
Expand All @@ -56,30 +87,29 @@ const client = createClient().use(
```ts
const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();
```
- `rpcSubscriptions`: Subscribe to Solana RPC notifications using async iterators.
```ts
const slotNotifications = await client.rpcSubscriptions.slotNotifications({ commitment: 'confirmed' }).subscribe();
for await (const slotNotification of slotNotifications) {
console.log('Got a slot notification', slotNotification);
}
```

## `localhostRpc` plugin
## `solanaRpcSubscriptionsConnection` plugin

This plugin is an alias for the `rpc` plugin pre-configured to connect to a local Solana validator.
The `solanaRpcSubscriptionsConnection` plugin creates Solana RPC Subscriptions from a cluster URL and sets them on the client.

### Installation

```ts
import { createClient } from '@solana/kit';
import { localhostRpc } from '@solana/kit-plugin-rpc';
import { solanaRpcSubscriptionsConnection } from '@solana/kit-plugin-rpc';

const client = createClient().use(localhostRpc());
const client = createClient().use(solanaRpcSubscriptionsConnection('wss://api.mainnet-beta.solana.com'));
```

### Features

_See the `rpc` plugin for available features_.
- `rpcSubscriptions`: Subscribe to Solana RPC notifications using async iterators.
```ts
const slotNotifications = await client.rpcSubscriptions.slotNotifications({ commitment: 'confirmed' }).subscribe();
for await (const slotNotification of slotNotifications) {
console.log('Got a slot notification', slotNotification);
}
```

## `rpcAirdrop` plugin

Expand All @@ -94,9 +124,12 @@ The client must have `rpc` and `rpcSubscriptions` installed before applying this

```ts
import { createClient } from '@solana/kit';
import { localhostRpc, rpcAirdrop } from '@solana/kit-plugin-rpc';
import { solanaRpcConnection, solanaRpcSubscriptionsConnection, rpcAirdrop } from '@solana/kit-plugin-rpc';

const client = createClient().use(localhostRpc()).use(rpcAirdrop());
const client = createClient()
.use(solanaRpcConnection('http://127.0.0.1:8899'))
.use(solanaRpcSubscriptionsConnection('ws://127.0.0.1:8900'))
.use(rpcAirdrop());
```

### Features
Expand All @@ -116,9 +149,11 @@ The client must have `rpc` installed before applying this plugin.

```ts
import { createClient } from '@solana/kit';
import { rpc, rpcGetMinimumBalance } from '@solana/kit-plugin-rpc';
import { solanaRpcConnection, rpcGetMinimumBalance } from '@solana/kit-plugin-rpc';

const client = createClient().use(rpc('https://api.mainnet-beta.solana.com')).use(rpcGetMinimumBalance());
const client = createClient()
.use(solanaRpcConnection('https://api.mainnet-beta.solana.com'))
.use(rpcGetMinimumBalance());
```

### Features
Expand All @@ -143,11 +178,17 @@ This plugin requires a payer to be set on the client or passed as an option.

```ts
import { createClient } from '@solana/kit';
import { rpc, rpcTransactionPlanner, rpcTransactionPlanExecutor } from '@solana/kit-plugin-rpc';
import {
solanaRpcConnection,
solanaRpcSubscriptionsConnection,
rpcTransactionPlanner,
rpcTransactionPlanExecutor,
} from '@solana/kit-plugin-rpc';
import { generatedPayer } from '@solana/kit-plugin-payer';

const client = await createClient()
.use(rpc('https://api.mainnet-beta.solana.com'))
.use(solanaRpcConnection('https://api.mainnet-beta.solana.com'))
.use(solanaRpcSubscriptionsConnection('wss://api.mainnet-beta.solana.com'))
.use(generatedPayer())
.use(rpcTransactionPlanner())
.use(rpcTransactionPlanExecutor());
Expand Down Expand Up @@ -175,11 +216,17 @@ This plugin requires `rpc` and `rpcSubscriptions` to be configured on the client

```ts
import { createClient } from '@solana/kit';
import { rpc, rpcTransactionPlanner, rpcTransactionPlanExecutor } from '@solana/kit-plugin-rpc';
import {
solanaRpcConnection,
solanaRpcSubscriptionsConnection,
rpcTransactionPlanner,
rpcTransactionPlanExecutor,
} from '@solana/kit-plugin-rpc';
import { generatedPayer } from '@solana/kit-plugin-payer';

const client = await createClient()
.use(rpc('https://api.mainnet-beta.solana.com'))
.use(solanaRpcConnection('https://api.mainnet-beta.solana.com'))
.use(solanaRpcSubscriptionsConnection('wss://api.mainnet-beta.solana.com'))
.use(generatedPayer())
.use(rpcTransactionPlanner())
.use(rpcTransactionPlanExecutor());
Expand Down
13 changes: 7 additions & 6 deletions packages/kit-plugin-rpc/src/airdrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,25 @@ type RpcClient = {
* RPC and RPC Subscriptions transports.
*
* The client must already have `rpc` and `rpcSubscriptions` installed
* (e.g. via the {@link rpc} or {@link localhostRpc} plugins). A
* TypeScript error is raised when a mainnet RPC is used because
* (e.g. via {@link solanaRpcConnection} and {@link solanaRpcSubscriptionsConnection}).
* A TypeScript error is raised when a mainnet RPC is used because
* airdrop methods are not available on mainnet.
*
* @example
* ```ts
* import { createClient } from '@solana/kit';
* import { localhostRpc, rpcAirdrop } from '@solana/kit-plugin-rpc';
* import { solanaRpcConnection, solanaRpcSubscriptionsConnection, rpcAirdrop } from '@solana/kit-plugin-rpc';
*
* const client = createClient()
* .use(localhostRpc())
* .use(solanaRpcConnection('http://127.0.0.1:8899'))
* .use(solanaRpcSubscriptionsConnection('ws://127.0.0.1:8900'))
* .use(rpcAirdrop());
*
* await client.airdrop(myAddress, lamports(1_000_000_000n));
* ```
*
* @see {@link rpc}
* @see {@link localhostRpc}
* @see {@link solanaRpcConnection}
* @see {@link solanaRpcSubscriptionsConnection}
*/
export function rpcAirdrop() {
return <T extends RpcClient>(client: T) => {
Expand Down
10 changes: 4 additions & 6 deletions packages/kit-plugin-rpc/src/get-minimum-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,21 @@ import {
* A plugin that adds a `getMinimumBalance` method to the client using
* the `getMinimumBalanceForRentExemption` RPC method.
*
* The client must already have `rpc` installed (e.g. via the {@link rpc}
* or {@link localhostRpc} plugins).
* The client must already have `rpc` installed (e.g. via {@link solanaRpcConnection}).
*
* @example
* ```ts
* import { createClient } from '@solana/kit';
* import { rpc, rpcGetMinimumBalance } from '@solana/kit-plugin-rpc';
* import { solanaRpcConnection, rpcGetMinimumBalance } from '@solana/kit-plugin-rpc';
*
* const client = createClient()
* .use(rpc('https://api.mainnet-beta.solana.com'))
* .use(solanaRpcConnection('https://api.mainnet-beta.solana.com'))
* .use(rpcGetMinimumBalance());
*
* const balance = await client.getMinimumBalance(100);
* ```
*
* @see {@link rpc}
* @see {@link localhostRpc}
* @see {@link solanaRpcConnection}
*/
export function rpcGetMinimumBalance() {
return <T extends ClientWithRpc<GetMinimumBalanceForRentExemptionApi>>(client: T) => {
Expand Down
1 change: 1 addition & 0 deletions packages/kit-plugin-rpc/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './airdrop';
export * from './get-minimum-balance';
export * from './rpc';
export * from './solana-rpc';
export * from './transaction-plan-executor';
export * from './transaction-planner';
Loading
Loading