Skip to content

Add RpcSendable / RpcSubscribable duck-types and loosen reactive-store config#1708

Open
mcintyre94 wants to merge 1 commit into
graphite-base/1708from
rpc/sendable-subscribable
Open

Add RpcSendable / RpcSubscribable duck-types and loosen reactive-store config#1708
mcintyre94 wants to merge 1 commit into
graphite-base/1708from
rpc/sendable-subscribable

Conversation

@mcintyre94
Copy link
Copy Markdown
Member

@mcintyre94 mcintyre94 commented May 27, 2026

Problem

createReactiveStoreWithInitialValueAndSlotTracking currently takes as input a PendingRpcRequest and a PendingRpcSubscriptionsRequest. These types are a bit more restrictive than they need to be, and particularly now include a reactiveStore() function that createReactiveStoreWithInitialValueAndSlotTracking does not need.

Summary of Changes

Add new types:

  • RpcSendable: just requires the .send() function from PendingRpcRequest
  • RpcSubscribable: just requires the .subscribe() function from PendingRpcSubscriptionsRequest

This is similar to the ReactiveActionSource and ReactiveStreamSource types which only include the .reactiveStore() functions. They are introduced for the same reason, to make it easier for plugins etc to create instances of these types.

createReactiveStoreWithInitialValueAndSlotTracking and createAsyncGeneratorWithInitialValueAndSlotTracking now take RpcSendable and RpcSubscribable inputs, making them more flexible.

PendingRpcRequest and PendingRpcSubscriptionsRequest are still valid inputs as they satisfy these new types.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 27, 2026

🦋 Changeset detected

Latest commit: 0153a07

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

This PR includes changesets to release 47 packages
Name Type
@solana/rpc-spec Minor
@solana/rpc-subscriptions-spec Minor
@solana/kit Minor
@solana/accounts Minor
@solana/plugin-interfaces Minor
@solana/rpc-api Minor
@solana/rpc-transport-http Minor
@solana/rpc Minor
@solana/sysvars Minor
@solana/rpc-subscriptions-api Minor
@solana/rpc-subscriptions-channel-websocket Minor
@solana/rpc-subscriptions Minor
@solana/react Minor
@solana/program-client-core Minor
@solana/rpc-graphql Minor
@solana/transaction-confirmation 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/fixed-points 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/plugin-core Minor
@solana/programs Minor
@solana/promises Minor
@solana/rpc-parsed-types Minor
@solana/rpc-spec-types Minor
@solana/rpc-transformers Minor
@solana/rpc-types Minor
@solana/signers Minor
@solana/subscribable Minor
@solana/transaction-messages Minor
@solana/transactions Minor
@solana/wallet-account-signer 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

mcintyre94 commented May 27, 2026

@bundlemon
Copy link
Copy Markdown

bundlemon Bot commented May 27, 2026

BundleMon

Files updated (25)
Status Path Size Limits
react/dist/index.browser.mjs
4.51KB (+1.42KB +45.72%) -
react/dist/index.native.mjs
4.51KB (+1.42KB +45.74%) -
react/dist/index.node.mjs
4.51KB (+1.42KB +45.75%) -
subscribable/dist/index.node.mjs
2.82KB (+144B +5.25%) -
subscribable/dist/index.browser.mjs
2.74KB (+142B +5.32%) -
subscribable/dist/index.native.mjs
2.75KB (+142B +5.31%) -
rpc-types/dist/index.browser.mjs
1.9KB (+102B +5.53%) -
rpc-types/dist/index.native.mjs
1.9KB (+101B +5.48%) -
rpc-types/dist/index.node.mjs
1.9KB (+101B +5.48%) -
wallet-account-signer/dist/index.browser.mjs
17.57KB (+45B +0.25%) -
wallet-account-signer/dist/index.native.mjs
17.57KB (+45B +0.25%) -
wallet-account-signer/dist/index.node.mjs
17.59KB (+44B +0.24%) -
errors/dist/index.browser.mjs
20.76KB (+36B +0.17%) -
errors/dist/index.native.mjs
20.76KB (+35B +0.16%) -
errors/dist/index.node.mjs
20.78KB (+35B +0.16%) -
rpc-subscriptions-spec/dist/index.browser.mjs
2.19KB (-13B -0.58%) -
rpc-subscriptions-spec/dist/index.native.mjs
2.19KB (-13B -0.58%) -
rpc-subscriptions-spec/dist/index.node.mjs
2.23KB (-13B -0.56%) -
rpc-spec/dist/index.browser.mjs
898B (-20B -2.18%) -
rpc-spec/dist/index.native.mjs
897B (-21B -2.29%) -
rpc-spec/dist/index.node.mjs
896B (-21B -2.29%) -
@solana/kit production bundle
kit/dist/index.production.min.js
52.49KB (-130B -0.24%) -
kit/dist/index.node.mjs
4.13KB (-352B -7.69%) -
kit/dist/index.browser.mjs
4.13KB (-353B -7.71%) -
kit/dist/index.native.mjs
4.13KB (-353B -7.71%) -
Unchanged files (122)
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 -
transaction-messages/dist/index.browser.mjs
11.32KB -
transaction-messages/dist/index.native.mjs
11.32KB -
transaction-messages/dist/index.node.mjs
11.32KB -
instruction-plans/dist/index.browser.mjs
6.58KB -
instruction-plans/dist/index.native.mjs
6.58KB -
instruction-plans/dist/index.node.mjs
6.58KB -
fixed-points/dist/index.browser.mjs
5.08KB -
fixed-points/dist/index.native.mjs
5.07KB -
fixed-points/dist/index.node.mjs
5.07KB -
codecs-data-structures/dist/index.browser.mjs
5.04KB -
codecs-data-structures/dist/index.native.mjs
5.03KB -
codecs-data-structures/dist/index.node.mjs
5.03KB -
offchain-messages/dist/index.browser.mjs
4.89KB -
offchain-messages/dist/index.native.mjs
4.89KB -
offchain-messages/dist/index.node.mjs
4.89KB -
transactions/dist/index.browser.mjs
4.07KB -
transactions/dist/index.native.mjs
4.07KB -
transactions/dist/index.node.mjs
4.07KB -
codecs-core/dist/index.browser.mjs
3.62KB -
codecs-core/dist/index.native.mjs
3.62KB -
codecs-core/dist/index.node.mjs
3.62KB -
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 -
signers/dist/index.browser.mjs
3.26KB -
signers/dist/index.native.mjs
3.26KB -
signers/dist/index.node.mjs
3.26KB -
rpc-transformers/dist/index.browser.mjs
3.16KB -
rpc-transformers/dist/index.native.mjs
3.16KB -
rpc-transformers/dist/index.node.mjs
3.16KB -
keys/dist/index.node.mjs
3.06KB -
addresses/dist/index.browser.mjs
2.93KB -
addresses/dist/index.native.mjs
2.92KB -
addresses/dist/index.node.mjs
2.92KB -
keys/dist/index.browser.mjs
2.85KB -
keys/dist/index.native.mjs
2.85KB -
codecs-strings/dist/index.browser.mjs
2.55KB -
codecs-strings/dist/index.node.mjs
2.51KB -
codecs-strings/dist/index.native.mjs
2.47KB -
transaction-confirmation/dist/index.node.mjs
2.42KB -
transaction-confirmation/dist/index.native.mj
s
2.37KB -
sysvars/dist/index.browser.mjs
2.37KB -
sysvars/dist/index.native.mjs
2.37KB -
transaction-confirmation/dist/index.browser.m
js
2.37KB -
sysvars/dist/index.node.mjs
2.37KB -
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 -
rpc-transport-http/dist/index.node.mjs
1.72KB -
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 -
program-client-core/dist/index.browser.mjs
1.21KB -
program-client-core/dist/index.native.mjs
1.21KB -
program-client-core/dist/index.node.mjs
1.21KB -
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.17KB -
accounts/dist/index.native.mjs
1.17KB -
accounts/dist/index.node.mjs
1.16KB -
rpc-api/dist/index.browser.mjs
998B -
rpc-api/dist/index.native.mjs
997B -
rpc-api/dist/index.node.mjs
995B -
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
871B -
rpc-subscriptions-api/dist/index.browser.mjs
870B -
rpc-subscriptions-api/dist/index.node.mjs
870B -
promises/dist/index.native.mjs
841B -
promises/dist/index.node.mjs
840B -
promises/dist/index.browser.mjs
839B -
plugin-core/dist/index.browser.mjs
820B -
plugin-core/dist/index.native.mjs
819B -
plugin-core/dist/index.node.mjs
817B -
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 -
fs-impl/dist/index.browser.mjs
245B -
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
145B -
codecs/dist/index.native.mjs
144B -
codecs/dist/index.node.mjs
142B -
event-target-impl/dist/index.browser.mjs
133B -
ws-impl/dist/index.node.mjs
131B -
text-encoding-impl/dist/index.browser.mjs
122B -
fs-impl/dist/index.node.mjs
120B -
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 +3.94KB +0.75%

Final result: ✅

View report in BundleMon website ➡️


Current branch size history | Target branch size history

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

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

@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from c71602b to 4399c85 Compare May 27, 2026 16:08
@mcintyre94
Copy link
Copy Markdown
Member Author

@trevor-cortex

Copy link
Copy Markdown

@trevor-cortex trevor-cortex left a comment

Choose a reason for hiding this comment

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

LGTM (commenting because I can't formally approve without explicit repo access).

Summary

Adds two structural duck-types — RpcSendable<TResponse> (just send(options?)) in @solana/rpc-spec and RpcSubscribable<TNotification> (just subscribe(options)) in @solana/rpc-subscriptions-spec — and uses them to loosen the rpcRequest / rpcSubscriptionRequest fields on the configs for createReactiveStoreWithInitialValueAndSlotTracking and createAsyncGeneratorWithInitialValueAndSlotTracking. Both primitives only ever call .send() / .subscribe() on those inputs, so the narrower types are sufficient and existing callers continue to work because PendingRpcRequest / PendingRpcSubscriptionsRequest structurally satisfy the new types.

Mirrors the prior-art pattern from ReactiveActionSource / ReactiveStreamSource, and makes life easier for plugin authors / test mocks that don't want to fabricate a full { reactiveStore, send } object.

What I verified

  • The new RpcSendable.send signature is identical to PendingRpcRequest.send (send(options?: RpcSendOptions): Promise<TResponse>), and RpcSubscribable.subscribe is identical to PendingRpcSubscriptionsRequest.subscribe (subscribe(options: RpcSubscribeOptions): Promise<AsyncIterable<TNotification>>) — so structural compatibility actually holds and existing call sites compile unchanged.
  • The new types flow through to @solana/kit via the existing export * chains (rpc-specrpckit, rpc-subscriptions-specrpc-subscriptionskit), matching the changeset's documented import type { RpcSendable, RpcSubscribable } from '@solana/kit' example.
  • Both implementation files only consume .send() / .subscribe() on these inputs, so loosening the type is purely additive at runtime.
  • Docblock copy on the two config fields was updated from "A pending RPC request" → "A one-shot RPC request" / "An RPC subscription request", which more accurately describes the looser contract.

Changeset

minor across @solana/rpc-spec, @solana/rpc-subscriptions-spec, and @solana/kit looks right — purely additive new exports plus a contravariant input loosening, no breaking change. Fixed-version lockstep handles the umbrella @solana/rpc / @solana/rpc-subscriptions packages automatically.

Notes for subsequent reviewers

  • Worth a quick sanity check that no downstream consumer is relying on the specific PendingRpcRequest / PendingRpcSubscriptionsRequest shape on the config (e.g. calling .reactiveStore() on the passed-in object). A grep over rpcRequest.reactiveStore / rpcSubscriptionRequest.reactiveStore in this repo and kit-plugins should be enough.
  • No tests changed. Given this is type-only and the structural relationship is mechanically obvious, that's fine — but if there's a __typetests__ directory for these primitives, a one-liner asserting that a Pending*Request is assignable to the new config (and that a bare { send } / { subscribe } object also is) would lock in the contract cheaply.

@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 4399c85 to d303d3d Compare May 27, 2026 16:43
@mcintyre94 mcintyre94 marked this pull request as ready for review May 27, 2026 16:58
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from d303d3d to eb7e142 Compare May 28, 2026 10:03
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch 2 times, most recently from b81de7d to f0abc4e Compare May 28, 2026 10:06
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from eb7e142 to 0153a07 Compare May 28, 2026 10:06
…store config

Add `RpcSendable<T>` to `@solana/rpc-spec` and `RpcSubscribable<T>` to `@solana/rpc-subscriptions-spec` — structural duck-types covering just `send({ abortSignal })` and `subscribe({ abortSignal })` respectively. Both are intentionally narrower than the concrete `PendingRpcRequest<T>` / `PendingRpcSubscriptionsRequest<T>`, which also expose `reactiveStore()`. Use them at consumer boundaries to accept request-like objects without forcing producers to implement the full store-bearing shape.

Loosens the `rpcRequest` and `rpcSubscriptionRequest` fields on `CreateReactiveStoreWithInitialValueAndSlotTrackingConfig` (exported) and the internal config for `createAsyncGeneratorWithInitialValueAndSlotTracking` to use the new types. Both primitives only ever call `.send()` and `.subscribe()` on their inputs, so the previous `Pending*Request` constraint was over-tight — existing callers passing concrete `rpc.getAccountInfo(addr)` / `rpcSubscriptions.accountNotifications(addr)` results still satisfy the loosened types structurally.

Motivation: plugin-authored wrappers (caching layers, request batchers, request dedup) and test mocks no longer need to stub out an unused `reactiveStore()` method just to satisfy the type. Parallels the existing `ReactiveStreamSource<T>` / `ReactiveActionSource<T>` duck-types in `@solana/subscribable` — same pattern, applied to the producer side of one-shot and subscription requests.
@mcintyre94 mcintyre94 force-pushed the rpc/sendable-subscribable branch from 0153a07 to e40f088 Compare May 28, 2026 10:13
@mcintyre94 mcintyre94 force-pushed the react/depend-on-kit branch from f0abc4e to 5dc6620 Compare May 28, 2026 10:13
@mcintyre94 mcintyre94 changed the base branch from react/depend-on-kit to graphite-base/1708 May 28, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants