Summary
The client store has a transactions field (Record<string, TransactionRecord>) and client.actions.sendTransaction() correctly writes to it (sending → confirmed/failed).
However, the React hooks — useSolTransfer, useSendTransaction, and useTransactionPool — bypass this entirely. They call client.transaction.send() / client.transaction.prepareAndSend() (the helper layer), which goes directly to runtime.rpc.sendTransaction() without updating the store.
This means third-party tools that subscribe to the store for transaction lifecycle events (analytics SDKs, devtools, logging) cannot observe transactions sent through the React hooks. The state.transactions field effectively only works if consumers call client.actions.sendTransaction() directly, which most React apps won't do since the hooks provide a much better DX.
The same gap exists for signatures — signMessage and signTransaction are fire-and-forget calls on the wallet session with no store representation. A state.signatures field (or reuse of state.transactions with a different type) would enable observability for these operations too.
Problem to solve
see above
Proposed solution
Have the transaction helpers (or the hooks themselves) write to state.transactions when sending, matching what actions.sendTransaction() already does. This would make all transaction paths — whether through hooks or actions — observable via store subscription.
For signatures, consider adding a state.signatures field that tracks signMessage/signTransaction lifecycle (requested → confirmed/rejected), similar to how state.wallet tracks connection lifecycle.
Alternatives considered
The alternative to store subscription is proxying/wrapping wallet methods — intercepting sendTransaction, signMessage, and signTransaction on the wallet session to observe calls as they pass through. This works (it's what the old @solana/wallet-adapter ecosystem required), but has significant drawbacks:
- Trust boundary concern. Wrapping wallet methods is structurally a man-in-the-middle pattern. Even when the wrapper is purely observational (pass-through, no mutation), it sits in a position where it could tamper with transactions. Security-conscious teams and auditors flag this, and it undermines the trust model that framework-kit's clean architecture provides.
- Fragility. The old wallet-adapter's StandardWalletAdapter._reset() method would overwrite wrapped methods on every connect/disconnect/feature-change, requiring re-wrapping hacks and race condition workarounds.
- Coupling. Wrapping ties integrations to the internal shape of wallet session objects, which can break across versions.
Store-level observability avoids all of these problems. The subscription is read-only, doesn't touch the wallet stack, and is stable across wallet implementations.
Additional context
The store subscription model is the clean, non-invasive way for third-party integrations to observe wallet activity. Without it, integrations either need to wrap wallet methods (which is a trust boundary concern for security-conscious teams) or require app developers to manually instrument every transaction and signature call. Centralizing this in the store would benefit the entire ecosystem — analytics, monitoring, debugging tools, and devtools could all subscribe without touching the wallet stack.
Summary
The client store has a transactions field (Record<string, TransactionRecord>) and client.actions.sendTransaction() correctly writes to it (sending → confirmed/failed).
However, the React hooks — useSolTransfer, useSendTransaction, and useTransactionPool — bypass this entirely. They call client.transaction.send() / client.transaction.prepareAndSend() (the helper layer), which goes directly to runtime.rpc.sendTransaction() without updating the store.
This means third-party tools that subscribe to the store for transaction lifecycle events (analytics SDKs, devtools, logging) cannot observe transactions sent through the React hooks. The state.transactions field effectively only works if consumers call client.actions.sendTransaction() directly, which most React apps won't do since the hooks provide a much better DX.
The same gap exists for signatures — signMessage and signTransaction are fire-and-forget calls on the wallet session with no store representation. A state.signatures field (or reuse of state.transactions with a different type) would enable observability for these operations too.
Problem to solve
see above
Proposed solution
Have the transaction helpers (or the hooks themselves) write to state.transactions when sending, matching what actions.sendTransaction() already does. This would make all transaction paths — whether through hooks or actions — observable via store subscription.
For signatures, consider adding a state.signatures field that tracks signMessage/signTransaction lifecycle (requested → confirmed/rejected), similar to how state.wallet tracks connection lifecycle.
Alternatives considered
The alternative to store subscription is proxying/wrapping wallet methods — intercepting sendTransaction, signMessage, and signTransaction on the wallet session to observe calls as they pass through. This works (it's what the old @solana/wallet-adapter ecosystem required), but has significant drawbacks:
Store-level observability avoids all of these problems. The subscription is read-only, doesn't touch the wallet stack, and is stable across wallet implementations.
Additional context
The store subscription model is the clean, non-invasive way for third-party integrations to observe wallet activity. Without it, integrations either need to wrap wallet methods (which is a trust boundary concern for security-conscious teams) or require app developers to manually instrument every transaction and signature call. Centralizing this in the store would benefit the entire ecosystem — analytics, monitoring, debugging tools, and devtools could all subscribe without touching the wallet stack.