@solana/kit
v6.10.0 (2026-06-16)
Minor Changes
-
[
@solana/errors,@solana/kit,@solana/subscribable] #1552c318d7fThanks @mcintyre94! - Addretry()andgetUnifiedState()toReactiveStore. The newgetUnifiedState()returns a discriminated{ data, error, status }snapshot with stable identity, so stores can be passed directly touseSyncExternalStorewithout an intermediate wrapper.getState()andgetError()remain on the type but are now@deprecatedin favour of the unified snapshot.A new
createReactiveStoreFromDataPublisherFactoryfunction is also introduced. It accepts acreateDataPublisher: () => Promise<DataPublisher>factory rather than a ready-made publisher, which lets the store reconnect viaretry()after an error. The existingcreateReactiveStoreFromDataPublisheris now@deprecated; callingretry()on a store it produced throws a newSolanaErrorwith codeSOLANA_ERROR__SUBSCRIBABLE__RETRY_NOT_SUPPORTED.createReactiveStoreWithInitialValueAndSlotTracking(from@solana/kit) now supportsretry(), which re-sends the RPC request and re-subscribes to the subscription with a fresh abort signal while preserving the last known slot and value. -
[
@solana/errors,@solana/kit] #1654460557bThanks @mcintyre94! - AddedestimateResourceLimitsFactory,estimateAndSetResourceLimitsFactory, andfillTransactionMessageProvisoryResourceLimitsto@solana/kit. These mirror the existing compute-unit estimators but additionally estimate and set the loaded accounts data size limit, which is required for version 1 transactions. Both limits are derived from a single simulation call.Two new error codes were added to
@solana/errors:SOLANA_ERROR__TRANSACTION__FAILED_TO_ESTIMATE_LOADED_ACCOUNTS_DATA_SIZE_LIMIT(thrown when an RPC fails to return aloadedAccountsDataSizevalue while estimating a version 1 transaction) andSOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_RESOURCE_LIMITS(the resource-limits counterpart ofSOLANA_ERROR__TRANSACTION__FAILED_WHEN_SIMULATING_TO_ESTIMATE_COMPUTE_LIMIT).Migration
The compute-unit-only helpers are still exported but are now deprecated. The new helpers handle every transaction version: for legacy and version 0 messages they behave the same as the old ones (only the compute unit limit is set); for version 1 messages they additionally set the loaded accounts data size limit, which is required for v1.
estimateComputeUnitLimitFactory→estimateResourceLimitsFactoryThe new estimator returns an object instead of a
number. DestructurecomputeUnitLimitfrom the result:// Before const estimateComputeUnitLimit = estimateComputeUnitLimitFactory({ rpc }); const units = await estimateComputeUnitLimit(transactionMessage); // After const estimateResourceLimits = estimateResourceLimitsFactory({ rpc }); const { computeUnitLimit } = await estimateResourceLimits(transactionMessage); // If provided by the RPC, `loadedAccountsDataSizeLimit` is also returned
estimateAndSetComputeUnitLimitFactory→estimateAndSetResourceLimitsFactoryThe new helper accepts the multi-resource estimator and returns a function with the same shape as before — it takes a transaction message and returns the same message with resource limits set. No call-site change beyond the factory swap:
// Before const estimator = estimateComputeUnitLimitFactory({ rpc }); const estimateAndSet = estimateAndSetComputeUnitLimitFactory(estimator); // After const estimator = estimateResourceLimitsFactory({ rpc }); const estimateAndSet = estimateAndSetResourceLimitsFactory(estimator);
Behavior note: the new helper re-estimates the compute unit limit when it is unset, set to the provisory value of
0, or set to the runtime max of1_400_000(same as before). For the loaded accounts data size limit on v1 messages it only re-estimates when unset or set to the provisory0; an explicit value — including the runtime max of 64 MiB — is left untouched, since callers who set it explicitly are signaling a deliberate choice.fillTransactionMessageProvisoryComputeUnitLimit→fillTransactionMessageProvisoryResourceLimitsThe signature is unchanged. For v1 messages, the new helper additionally reserves a provisory
0for the loaded accounts data size limit when none is set. For legacy and v0 messages, the behavior is unchanged and the function only reserves space for the CU limit.// Before const reserved = fillTransactionMessageProvisoryComputeUnitLimit(transactionMessage); // After const reserved = fillTransactionMessageProvisoryResourceLimits(transactionMessage);
-
[
@solana/errors] #174640e0848Thanks @mcintyre94! - Add theSOLANA_ERROR__WALLET__ACCOUNT_NOT_AVAILABLEerror code, thrown when a selected account is not available in the connected wallet. Its context carries the requestedaddressand thewalletName. -
[
@solana/errors,@solana/kit,@solana/rpc-subscriptions-spec,@solana/subscribable] #155447a785bThanks @mcintyre94! - RenameReactiveStore<T>toReactiveStreamStore<T>. The old name remains exported as a deprecated alias and will be removed in a future major release. -
[
@solana/kit,@solana/rpc-spec] #15555e1644dThanks @mcintyre94! - Add areactiveStore()method toPendingRpcRequest. It fires the request on construction and synchronously returns aReactiveActionStorethat holds the request'sidle/running/success/errorlifecycle state. Compatible withuseSyncExternalStore, Svelte stores, and other reactive primitives. Calldispatch()to re-fire the request (e.g. after an error), orreset()to abort the in-flight call and return to idle.const store = rpc.getAccountInfo(address).reactiveStore(); const state = useSyncExternalStore(store.subscribe, store.getState); if (state.status === 'error') return <ErrorMessage error={state.error} onRetry={store.dispatch} />; if (state.status === 'running' && !state.data) return <Spinner />; return <View data={state.data!} />;
-
[
@solana/kit,@solana/rpc-subscriptions-spec] #155315b610dThanks @mcintyre94! - Add areactiveStore()method toPendingRpcSubscriptionsRequest. Unlikereactive(), this variant returns aReactiveStoresynchronously and supportsretry()to reconnect after an error.reactive()is now@deprecatedin favour ofreactiveStore().const store = rpc.accountNotifications(address).reactiveStore({ abortSignal }); const state = useSyncExternalStore(store.subscribe, store.getUnifiedState); if (state.status === 'error') return <ErrorMessage error={state.error} onRetry={store.retry} />;
-
[
@solana/kit,@solana/subscribable] #1606da868aaThanks @mcintyre94! - Add framework-agnostic source duck-types for reactive bindings.@solana/subscribablenow exports two new types:ReactiveStreamSource<T>— anything with areactiveStore({ abortSignal })method that returns aReactiveStreamStore<T>.PendingRpcSubscriptionsRequest<T>satisfies this by design.ReactiveActionSource<T>— anything with a zero-argumentreactiveStore()method that returns aReactiveActionStore<[], T>.PendingRpcRequest<T>satisfies this by design.
These let reactive-framework bindings consume a single duck-type instead of naming concrete producer types — and let plugin authors expose their own pending-request objects to those bindings without modification.
Both source types live in
@solana/subscribableand are not re-exported from@solana/kit, matching the existing convention for their parentReactiveStreamStore/ReactiveActionStoretypes — anyone consuming a source duck-type is already in the reactive-primitives layer and will already be importing the related store types from the same package.@solana/kitnow publicly exports the previously-privateCreateReactiveStoreWithInitialValueAndSlotTrackingConfigtype so non-React consumers (e.g. plugins) can declare function return shapes based on it without taking a dependency on@solana/react. -
[
@solana/rpc-api] #16600d5aa7fThanks @kh0ra! - Add the optionaltransactionIndexfield to each element of thegetSignaturesForAddressresponse. Agave 4.0 (anza-xyz/agave#9683) included the 0 based transaction index inside the block alongside each returned signature. The field is omitted by older RPC servers, so the new property is optional and existing call sites continue to compile without modification. -
[
@solana/rpc-api] #1658d655befThanks @mcintyre94! - Added theclientIdfield to thegetClusterNodesresponse type, exposing the name of the validator client software advertised by each node. Also marked thetpuandtpuForwardsfields as@deprecatedin favor of their QUIC equivalents (tpuQuicandtpuForwardsQuic); validators may report the UDP fields asnull. -
[
@solana/rpc-types] #165993191afThanks @kh0ra! -Base58EncodedBytes,Base64EncodedBytes, andBase64EncodedZStdCompressedBytesare no longer uniquely branded. They are now plainEncodedString<...>aliases over their respective encoding tags. As a result, any value that already carries the matching encoding tag (such asAddress,Signature, orBlockhashfor base 58) can be used whereverBase58EncodedBytesis expected. For example, anAddressmay now be passed directly as thebytesof amemcmpfilter ingetProgramAccounts. The runtime representation is unchanged and existing call sites continue to compile without modification. -
[
@solana/subscribable] #155082a1ac5Thanks @mcintyre94! - AddedcreateReactiveActionStore— a framework-agnostic state machine that wraps an async function and exposes a{ dispatch, dispatchAsync, getState, subscribe, reset }contract compatible withuseSyncExternalStore, Svelte stores, Vue'sshallowRef, and similar reactive primitives.dispatchis synchronous and fire-and-forget (safe from UI event handlers);dispatchAsyncreturns a promise that resolves to the wrapped function's result and rejects on failure or supersede — useisAbortErrorfrom@solana/promisesto filter aborts. Each call creates a freshAbortControllerand aborts the previous one, so rapid successive dispatches only produce one final state transition — the outcome of the most recent call.
Patch Changes
-
[
@solana/errors] #16816b499eeThanks @brooksprumo! - Add FILTER_TRANSACTION_NOT_FOUND error -
[
@solana/errors] #167974b8d3dThanks @brooksprumo! - Add NO_SLOT_HISTORY error -
[
@solana/offchain-messages] #17416c2c903Thanks @ChargingFoxSec! - Include the v0 preamble bytes when enforcing the 1232-byte limit for hardware-wallet-signable offchain messages. -
[
@solana/plugin-core] #164609e7796Thanks @lorisleiva! - Flatten the inferred return type ofextendClientandwithCleanupso that chained.use()calls on aClientno longer produce deeply nestedOmit<Omit<Omit<...>>>types in editor tooltips and error messages. The inferred shape now displays as a single flat object literal at every step of the chain, while optional (?) andreadonlymodifiers, symbol keys, and override semantics are preserved exactly as before. Also exports the newExtendedClient<TClient, TAdditions>helper type for plugin authors who write their own merging helpers and want the same flattening guarantee. -
[
@solana/rpc-transport-http] #1700bb67860Thanks @pgtls! - Stop sending a manualContent-Lengthheader from the HTTP transport. The value came frombody.length— the JavaScript string's UTF-16 code-unit count — which is smaller than the body's actual UTF-8 byte length whenever the payload contains non-ASCII characters. For such payloads the server would respect the header, read only that many bytes off the socket, and stall waiting for a request that the client believed it had already finished sending. The symptom is a hung request rather than a thrown error, and it has been latent since the line was introduced; recent undici versions surface it more readily. The fix is to letfetchderiveContent-Lengthfrom the body itself, which it always did anyway. The transport's TypeScript surface and dev-mode runtime check continue to disallowContent-Lengthas a caller-supplied header. -
[
@solana/transaction-confirmation] #1640953eed6Thanks @kh0ra! - Fix an abort listener leak ingetTimeoutPromise. The listener registered on the caller'sAbortSignalwas never removed after the promise settled, which caused listeners to accumulate when the same signal was reused across multiple calls.getTimeoutPromisenow registers the listener with the auto-cleanupsignaloption already used by the other strategies in this package and releases it in afinallyblock.