Skip to content

Add @solana/plugin-core package#1113

Merged
lorisleiva merged 1 commit into
mainfrom
12-15-add_solana_client_package
Dec 17, 2025
Merged

Add @solana/plugin-core package#1113
lorisleiva merged 1 commit into
mainfrom
12-15-add_solana_client_package

Conversation

@lorisleiva
Copy link
Copy Markdown
Member

@lorisleiva lorisleiva commented Dec 15, 2025

This PR introduces a new @solana/plugin-core package to the monorepo that provides core utilities for creating modular Kit clients through a plugin architecture.

It defines the following types and functions:

  • ClientPlugin: Defines a plugin. A function that extends a client by returning a new one. For instance, <T extends object>(client: T) => ({ ...client, rpc: createSolanaRpc("http://127.0.0.1:8899") }).
  • Client: Defines a client object. Any object that contains a use function for applying plugins.
  • AsyncClient: Defines the promise of a client. It also contains a use function for chaining async plugins without having to await them each time.
  • createEmptyClient(): Function that returns an empty Client. Can be used as the starting point for creating custom clients.

To best illustrate this PR, let's explore some custom plugins and use them all at the end.

RPC plugin

Given an RPC endpoint, provides the rpc and rpcSubscriptions properties to the client.

export function rpc<TClusterUrl extends ClusterUrl>(url: TClusterUrl, subscriptionsUrl?: TClusterUrl) {
    const rpc = createSolanaRpc(url);
    const rpcSubscriptions = createSolanaRpcSubscriptions(subscriptionsUrl ?? url.replace(/^http/, 'ws'));
    return <T extends object>(client: T) => ({ ...client, rpc, rpcSubscriptions });
}

Localhost plugin

An RPC plugin specifically for local environments. Since we are using a localnet, we also offer a airdrop function on the client that can be used later on by other plugins.

export type AirdropFunction = (address: Address, amount: Lamports) => Promise<void>;

export function localhostRpc() {
    const rpcPlugin = rpc('http://127.0.0.1:8899', 'ws://127.0.0.1:8900');
    return <T extends object>(client: T) => {
        const clientWithRpc = rpcPlugin<T>(client);
        const airdropInternal = airdropFactory(clientWithRpc);
        const airdrop: AirdropFunction = async (address, amount) => {
            await airdropInternal({ commitment: 'confirmed', lamports: amount, recipientAddress: address });
        };
        return { ...clientWithRpc, airdrop };
    };
}

Generated payer plugin (async)

A plugin that generates a new keypair signer and assigns it to the payer property of the client.

export function generatedPayer() {
    return async <T extends object>(client: T) => ({ ...client, payer: await generateKeyPairSigner() });
}

Generated payer with SOL plugin (async)

Same as the previous plugin but here we require an airdrop function on the client to also start the generated payer with some initial funds.

export function generatedPayerWithSol(amount: Lamports) {
    const generatedPayerPlugin = generatedPayer();
    return async <T extends { airdrop: AirdropFunction }>(client: T) => {
        const extendedClient = await generatedPayerPlugin<T>(client);
        if (!extendedClient.airdrop) {
            throw new Error('generatedPayerWithSol requires an airdrop function on the client');
        }
        await extendedClient.airdrop(extendedClient.payer.address, amount);
        return extendedClient;
    };
}

Plugin usage

Finally, here's how we can create a localhost client that has all the features offered by the above plugins.

const client = await createClient()
    .use(localhostRpc())
    .use(generatedPayerWithSol(lamports(10_000_000_000n))); // 10 SOL

// client.payer.address
// client.rpc.getBalance(...)
// client.rpcSubscriptions.accountNotifications(...)
// client.airdrop(...)

This is a small subset of features we can wrap in plugins to illustrate this PR. Some more can be found in this proof-of-concept repo.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Dec 15, 2025

🦋 Changeset detected

Latest commit: 33da353

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 43 packages
Name Type
@solana/plugin-core Minor
@solana/kit Minor
@solana/accounts Minor
@solana/addresses Minor
@solana/assertions Minor
@solana/codecs-core Minor
@solana/codecs-data-structures Minor
@solana/codecs-numbers Minor
@solana/codecs-strings Minor
@solana/codecs Minor
@solana/compat Minor
@solana/errors Minor
@solana/fast-stable-stringify Minor
@solana/functional Minor
@solana/instruction-plans Minor
@solana/instructions Minor
@solana/keys Minor
@solana/nominal-types Minor
@solana/offchain-messages Minor
@solana/options Minor
@solana/programs Minor
@solana/promises Minor
@solana/react Minor
@solana/rpc-api Minor
@solana/rpc-graphql Minor
@solana/rpc-parsed-types Minor
@solana/rpc-spec-types Minor
@solana/rpc-spec Minor
@solana/rpc-subscriptions-api Minor
@solana/rpc-subscriptions-channel-websocket Minor
@solana/rpc-subscriptions-spec Minor
@solana/rpc-subscriptions Minor
@solana/rpc-transformers Minor
@solana/rpc-transport-http Minor
@solana/rpc-types Minor
@solana/rpc Minor
@solana/signers Minor
@solana/subscribable Minor
@solana/sysvars Minor
@solana/transaction-confirmation Minor
@solana/transaction-messages Minor
@solana/transactions Minor
@solana/webcrypto-ed25519-polyfill Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@lorisleiva lorisleiva force-pushed the 12-15-add_solana_client_package branch from d490e96 to 28ff0d6 Compare December 15, 2025 16:41
@bundlemon
Copy link
Copy Markdown

bundlemon Bot commented Dec 15, 2025

BundleMon

Files added (3)
Status Path Size Limits
plugin-core/dist/index.browser.mjs
+328B -
plugin-core/dist/index.native.mjs
+326B -
plugin-core/dist/index.node.mjs
+324B -
Files updated (1)
Status Path Size Limits
@solana/kit production bundle
kit/dist/index.production.min.js
39.19KB (+132B +0.33%) -
Unchanged files (132)
Status Path Size Limits
rpc-graphql/dist/index.browser.mjs
18.82KB -
rpc-graphql/dist/index.native.mjs
18.81KB -
rpc-graphql/dist/index.node.mjs
18.81KB -
errors/dist/index.node.mjs
17.07KB -
errors/dist/index.browser.mjs
17.04KB -
errors/dist/index.native.mjs
17.04KB -
transaction-messages/dist/index.browser.mjs
7.29KB -
transaction-messages/dist/index.native.mjs
7.29KB -
transaction-messages/dist/index.node.mjs
7.29KB -
offchain-messages/dist/index.browser.mjs
4.89KB -
offchain-messages/dist/index.native.mjs
4.89KB -
offchain-messages/dist/index.node.mjs
4.89KB -
codecs-data-structures/dist/index.browser.mjs
4.69KB -
codecs-data-structures/dist/index.native.mjs
4.69KB -
codecs-data-structures/dist/index.node.mjs
4.69KB -
instruction-plans/dist/index.browser.mjs
3.71KB -
instruction-plans/dist/index.native.mjs
3.71KB -
instruction-plans/dist/index.node.mjs
3.71KB -
codecs-core/dist/index.browser.mjs
3.61KB -
codecs-core/dist/index.native.mjs
3.61KB -
codecs-core/dist/index.node.mjs
3.61KB -
webcrypto-ed25519-polyfill/dist/index.node.mj
s
3.61KB -
webcrypto-ed25519-polyfill/dist/index.browser
.mjs
3.59KB -
webcrypto-ed25519-polyfill/dist/index.native.
mjs
3.57KB -
rpc-subscriptions/dist/index.browser.mjs
3.37KB -
rpc-subscriptions/dist/index.node.mjs
3.34KB -
rpc-subscriptions/dist/index.native.mjs
3.31KB -
rpc-transformers/dist/index.browser.mjs
2.93KB -
rpc-transformers/dist/index.native.mjs
2.93KB -
rpc-transformers/dist/index.node.mjs
2.93KB -
addresses/dist/index.browser.mjs
2.93KB -
addresses/dist/index.native.mjs
2.92KB -
addresses/dist/index.node.mjs
2.92KB -
signers/dist/index.browser.mjs
2.9KB -
signers/dist/index.native.mjs
2.9KB -
signers/dist/index.node.mjs
2.9KB -
transactions/dist/index.browser.mjs
2.87KB -
transactions/dist/index.native.mjs
2.86KB -
transactions/dist/index.node.mjs
2.86KB -
codecs-strings/dist/index.browser.mjs
2.53KB -
codecs-strings/dist/index.node.mjs
2.49KB -
codecs-strings/dist/index.native.mjs
2.45KB -
transaction-confirmation/dist/index.node.mjs
2.41KB -
transaction-confirmation/dist/index.native.mj
s
2.36KB -
transaction-confirmation/dist/index.browser.m
js
2.35KB -
sysvars/dist/index.browser.mjs
2.35KB -
sysvars/dist/index.native.mjs
2.34KB -
sysvars/dist/index.node.mjs
2.34KB -
react/dist/index.browser.mjs
2.31KB -
react/dist/index.native.mjs
2.31KB -
react/dist/index.node.mjs
2.31KB -
rpc-subscriptions-spec/dist/index.node.mjs
2.18KB -
rpc-subscriptions-spec/dist/index.native.mjs
2.13KB -
rpc-subscriptions-spec/dist/index.browser.mjs
2.13KB -
keys/dist/index.browser.mjs
2.1KB -
keys/dist/index.native.mjs
2.1KB -
keys/dist/index.node.mjs
2.1KB -
rpc/dist/index.node.mjs
1.95KB -
codecs-numbers/dist/index.browser.mjs
1.95KB -
codecs-numbers/dist/index.native.mjs
1.95KB -
codecs-numbers/dist/index.node.mjs
1.94KB -
rpc-transport-http/dist/index.browser.mjs
1.91KB -
rpc-transport-http/dist/index.native.mjs
1.9KB -
rpc/dist/index.native.mjs
1.81KB -
rpc/dist/index.browser.mjs
1.8KB -
subscribable/dist/index.node.mjs
1.8KB -
subscribable/dist/index.native.mjs
1.75KB -
subscribable/dist/index.browser.mjs
1.74KB -
rpc-transport-http/dist/index.node.mjs
1.72KB -
kit/dist/index.browser.mjs
1.69KB -
kit/dist/index.native.mjs
1.69KB -
kit/dist/index.node.mjs
1.69KB -
rpc-types/dist/index.browser.mjs
1.53KB -
rpc-types/dist/index.native.mjs
1.53KB -
rpc-types/dist/index.node.mjs
1.53KB -
rpc-subscriptions-channel-websocket/dist/inde
x.node.mjs
1.33KB -
rpc-subscriptions-channel-websocket/dist/inde
x.native.mjs
1.27KB -
rpc-subscriptions-channel-websocket/dist/inde
x.browser.mjs
1.26KB -
options/dist/index.browser.mjs
1.18KB -
options/dist/index.native.mjs
1.18KB -
options/dist/index.node.mjs
1.17KB -
accounts/dist/index.browser.mjs
1.13KB -
accounts/dist/index.native.mjs
1.12KB -
accounts/dist/index.node.mjs
1.12KB -
rpc-api/dist/index.browser.mjs
976B -
rpc-api/dist/index.native.mjs
975B -
rpc-api/dist/index.node.mjs
973B -
compat/dist/index.browser.mjs
969B -
compat/dist/index.native.mjs
968B -
compat/dist/index.node.mjs
966B -
rpc-spec-types/dist/index.browser.mjs
962B -
rpc-spec-types/dist/index.native.mjs
961B -
rpc-spec-types/dist/index.node.mjs
959B -
rpc-subscriptions-api/dist/index.native.mjs
870B -
rpc-subscriptions-api/dist/index.node.mjs
869B -
rpc-subscriptions-api/dist/index.browser.mjs
868B -
rpc-spec/dist/index.browser.mjs
852B -
rpc-spec/dist/index.native.mjs
851B -
rpc-spec/dist/index.node.mjs
850B -
promises/dist/index.browser.mjs
799B -
promises/dist/index.native.mjs
798B -
promises/dist/index.node.mjs
797B -
assertions/dist/index.browser.mjs
783B -
instructions/dist/index.browser.mjs
771B -
instructions/dist/index.native.mjs
770B -
instructions/dist/index.node.mjs
768B -
fast-stable-stringify/dist/index.browser.mjs
726B -
fast-stable-stringify/dist/index.native.mjs
725B -
assertions/dist/index.native.mjs
724B -
fast-stable-stringify/dist/index.node.mjs
724B -
assertions/dist/index.node.mjs
723B -
programs/dist/index.browser.mjs
329B -
programs/dist/index.native.mjs
327B -
programs/dist/index.node.mjs
325B -
event-target-impl/dist/index.node.mjs
230B -
functional/dist/index.browser.mjs
154B -
functional/dist/index.native.mjs
152B -
text-encoding-impl/dist/index.native.mjs
152B -
functional/dist/index.node.mjs
151B -
codecs/dist/index.browser.mjs
137B -
codecs/dist/index.native.mjs
136B -
codecs/dist/index.node.mjs
134B -
event-target-impl/dist/index.browser.mjs
133B -
ws-impl/dist/index.node.mjs
131B -
text-encoding-impl/dist/index.browser.mjs
122B -
text-encoding-impl/dist/index.node.mjs
119B -
ws-impl/dist/index.browser.mjs
113B -
crypto-impl/dist/index.node.mjs
111B -
crypto-impl/dist/index.browser.mjs
109B -
rpc-parsed-types/dist/index.browser.mjs
66B -
rpc-parsed-types/dist/index.native.mjs
65B -
rpc-parsed-types/dist/index.node.mjs
63B -

Total files change +1.11KB +0.29%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@lorisleiva lorisleiva force-pushed the 12-15-add_solana_client_package branch from 28ff0d6 to c486e07 Compare December 15, 2025 16:45
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Dec 15, 2025

Documentation Preview: https://kit-docs-32a7da1wh-anza-tech.vercel.app

@lorisleiva lorisleiva force-pushed the 12-15-add_solana_client_package branch 3 times, most recently from 94d1504 to 10f2441 Compare December 15, 2025 18:42
@lorisleiva lorisleiva marked this pull request as ready for review December 15, 2025 18:43
Copy link
Copy Markdown
Member

@mcintyre94 mcintyre94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, especially the tests!

I think this is the exact right boundary for the piece that should be in the library

@GuiBibeau
Copy link
Copy Markdown

Just surfacing a slack thread to avoid merging this before we figure out naming:

We currently deploy to NPM @solana/client from https://github.com/solana-foundation/framework-kit/tree/main/packages/client.

@lorisleiva lorisleiva force-pushed the 12-15-add_solana_client_package branch from 10f2441 to 8af12bb Compare December 17, 2025 10:28
@lorisleiva lorisleiva force-pushed the 12-15-add_solana_client_package branch from 8af12bb to 33da353 Compare December 17, 2025 10:31
@lorisleiva lorisleiva changed the title Add @solana/client package Add @solana/plugin-core package Dec 17, 2025
@lorisleiva
Copy link
Copy Markdown
Member Author

Thanks @GuiBibeau! As discussed on Slack, I updated the package name based on the naming convention we agreed on (see below).

# In "anza-xyz/kit" repo.
@solana/plugin-core

# In "anza-xyz/kit-plugins" repo.
@solana/kit-plugins # The package re-exporting plugins and client factories.
@solana/kit-plugin-rpc
@solana/kit-plugin-litesvm
@solana/kit-plugin-payer
@solana/kit-plugin-instruction-plans
@solana/kit-plugin-*

# In program client repos.
@solana-program/token # contains token plugin.
@solana-program/stake # contains stake plugin.
# etc.

@lorisleiva lorisleiva merged commit b1937c7 into main Dec 17, 2025
14 checks passed
@lorisleiva lorisleiva deleted the 12-15-add_solana_client_package branch December 17, 2025 11:48
@github-actions
Copy link
Copy Markdown
Contributor

🔎💬 Inkeep AI search and chat service is syncing content for source 'Solana Kit Docs'

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jan 1, 2026

Because there has been no activity on this PR for 14 days since it was merged, it has been automatically locked. Please open a new issue if it requires a follow up.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jan 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants