Update the example app to use transaction plan/send - #1872
Conversation
|
BundleMonUnchanged files (150)
No change in files bundle size Final result: ✅ View report in BundleMon website ➡️ |
trevor-cortex
left a comment
There was a problem hiding this comment.
Summary
Refactors the three transfer panels in the react-app example to use the new client-level planTransaction / useSendTransaction helpers instead of hand-rolling transaction messages, and bumps @solana/kit-plugin-rpc from 0.13.0 → 0.15.0 to pick up the improved CU calculation. Net result is a substantial simplification: SolanaSignAndSendTransactionFeaturePanel loses ~44 lines, and SolanaSignTransactionFeaturePanel / SolanaPartialSignTransactionFeaturePanel each drop the pipe(...) + blockhash-fetch boilerplate. assertCanSignAndSendTransactions and its now-unused imports are removed from walletCapability.ts, and the surrounding ErrorBoundary around the sign-and-send panel is dropped in root.tsx.
Example-app-only, private package — no changeset needed.
Things to watch out for
1. Behavioral change in sign-and-send: source is now client.payer instead of the connected wallet's signer. These should be equivalent here, because walletSigner({ chain }) is registered before solanaRpc(...) in ClientProvider.tsx and sets client.payer from the connected wallet — but it's worth double-checking that the panel behaves the same when there are multiple connected wallets or when the connected account is changed mid-session. If client.payer ever diverges from "the currently selected wallet signer" in this app, the transfer's source would silently follow client.payer rather than the account the user thinks they're operating from.
2. Removed capability guard for sign-and-send. The old code called assertCanSignAndSendTransactions(signer) at render time inside an ErrorBoundary with FeatureNotSupportedCallout, so an account that doesn't expose solana:signAndSendTransaction got a nice "not supported" UI. With this PR, the panel is unconditionally rendered and any incompatibility only surfaces at dispatch time via useSendTransaction's error field (which routes to ErrorDialog). That's a minor UX regression for accounts on the connected wallet that only support signTransaction — worth confirming whether useSendTransaction (or client.sendTransaction under the hood) picks a compatible signer automatically, or whether this now fails at click-time for those accounts. If it does fail at click time, consider keeping a lightweight capability check so the button is disabled rather than throwing after the user tries.
3. Partial-sign panel: fee-payer swap after planning. In SolanaPartialSignTransactionFeaturePanel, client.planTransaction(...) runs with the wallet as the implicit payer (via client.payer), then setTransactionMessageFeePayerSigner(feePayerSigner, planned) swaps the fee payer to the mock server signer. This works, and the comment on the line is helpful, but note that the plugin-rpc 0.15 CU calculation is done against the wallet-as-payer rather than the actual mock fee payer. In practice the CU estimate should be identical for a simple SOL transfer, but if this pattern is ever copied for a transaction where the fee payer materially changes account access (e.g. affects which accounts are writable), the estimate could drift. Not a blocker for the example — flagging for future readers.
Notes for subsequent reviewers
- Verify with Callum whether
useSendTransactiongracefully handles the case where the connected wallet account cannot sign-and-send (point 2 above). If it doesn't, either theErrorBoundary/capability guard should stay, or the submit button should be disabled based on the connected account's capabilities. - The lockfile change is just the
kit-plugin-rpcbump;@solana/kit-plugin-instruction-planis still pinned to0.13.0as a transitive — nothing to do, but worth eyeballing that this is intentional and not a version-skew concern for the plugin-rpc author. - The formatting change in
root.tsxaround theErrorBoundaryforBalanceis cosmetic (line wrap) and unrelated to the feature work — fine to keep.
|
Documentation Preview: https://kit-docs-lmgobhspe-anza-tech.vercel.app |
2066a9f to
eecae8b
Compare
921ceb8 to
220e70c
Compare
|
Added back the capability check and |
| const message = await pipe( | ||
| planned, | ||
| // Set the lifetime to the latest blockhash | ||
| tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), | ||
| // Estimate and set the resource limits for the transaction | ||
| async tx => await estimateAndSetResourceLimits(tx, { abortSignal: signal }), | ||
| ); | ||
| const transaction = await signTransactionMessageWithSigners(message); | ||
| assertIsSendableTransaction(transaction); |
There was a problem hiding this comment.
Highlighting this, I think this may be an API gap
We refactor to use client.planTransaction which I think is much better, but our default transaction planner intentionally does not set the lifetime nor the CUs, both of which are left to the default transaction executor. See https://github.com/anza-xyz/kit-plugins/blob/497b55fcdd7c1df905083e7eda160e06b220d555/packages/kit-plugin-rpc/src/transaction-plan-executor.ts#L143
This means that the app needs to handle adding the blockhash, and setting CUs. The default executor now has a quite sophisticated approach to CUs, but I don't think an app can easily use it outside of the executor.
My instinct here is that it may make sense to split out a client.signTransaction from client.sendTransaction. This would return a fully signed transaction that is ready to send but has not been sent.
The default implementation of this in our solanaRpc plugin would be the current default executor, except without the call to sendAndConfirm, it'd just return the transaction after signing it.
This panel would then collapse to simply client.signTransaction(transferInstruction) here, and then whatever send logic the app chooses to use as the second part. This would also be a clean migration from the wallet-adapter signTransaction API.
This needs a bit more design thought, so leaving as-is in this PR - this demonstrates the small amount of transaction logic an app will currently still need for the sign-then-send flow.
220e70c to
5135262
Compare
5135262 to
d61fd65
Compare
eecae8b to
8da5a8a
Compare
Merge activity
|
8da5a8a to
eb09af5
Compare
d61fd65 to
585e985
Compare
585e985 to
c490db6
Compare
|
🔎💬 Inkeep AI search and chat service is syncing content for source 'Solana Kit Docs' |

This PR updates the react example app to use our transaction plan/send functions, instead of hand-crafting transactions. Note that in a previous PR I added
solanaRpcto the client, so it already has transaction plan/send functions available.useSendTransactionclient.planTransactionto construct their transaction