fix(solana-wallet-snap): solana dapp transactions expiry check - #183
fix(solana-wallet-snap): solana dapp transactions expiry check#183taran-a wants to merge 4 commits into
Conversation
15ceaab to
baaec6b
Compare
1495a1c to
1dda959
Compare
baaec6b to
c5441ea
Compare
There was a problem hiding this comment.
Pull request overview
Adds Solana transaction blockhash expiry handling for dapp confirmations and refreshes blockhashes for MetaMask-originated transactions.
Changes:
- Detects expired blockhashes and displays localized errors.
- Preserves dapp transaction bytes while refreshing MetaMask transaction blockhashes.
- Updates tests, localization, manifest, changelog, and lint suppressions.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Summary |
|---|---|
packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest.tsx |
Displays alerts and disables confirmation for scan errors. |
packages/solana-wallet-snap/src/features/confirmation/components/TransactionAlert/getErrorMessage.ts |
Maps expired-blockhash errors to localized text. |
packages/solana-wallet-snap/src/core/services/wallet/WalletService.ts |
Forwards transaction source to the signer. |
packages/solana-wallet-snap/src/core/services/wallet/WalletService.test.ts |
Tests source forwarding. |
packages/solana-wallet-snap/src/core/services/transaction-scan/isTransactionBlockhashExpired.ts |
Adds expiry detection. Critical (4): misspelled codec import fails compilation. Critical (1): verification failures fail open. Nit (3): add valid, expired, and durable-nonce coverage. |
packages/solana-wallet-snap/src/core/services/transaction-scan/isTransactionBlockhashExpired.test.ts |
Critical (4): misspelled codec reference causes the test to fail compilation. |
packages/solana-wallet-snap/src/core/services/transaction-scan/buildExpiredScanResult.ts |
Defines the expired transaction scan result. |
packages/solana-wallet-snap/src/core/services/signer/Signer.ts |
Preserves dapp bytes and refreshes MetaMask transaction blockhashes. |
packages/solana-wallet-snap/src/core/services/signer/Signer.test.ts |
Tests signing behavior. |
packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.tsx |
Applies expiry checks during refresh. Moderate (4): initial confirmation can bypass revalidation. |
packages/solana-wallet-snap/src/core/handlers/onCronjob/backgroundEvents/refreshConfirmationEstimation.test.tsx |
Tests refresh behavior. Nit (3): use type-only imports for JSON-RPC types. |
packages/solana-wallet-snap/snap.manifest.json |
Updates the bundle checksum. |
packages/solana-wallet-snap/messages.json |
Adds the expired-blockhash message key. |
packages/solana-wallet-snap/locales/en.json |
Adds the English localization. |
packages/solana-wallet-snap/CHANGELOG.md |
Documents the behavior changes. |
eslint-suppressions.json |
Removes an obsolete suppression. |
Suppressed comments (2)
packages/solana-wallet-snap/src/core/services/transaction-scan/isTransactionBlockhashExpired.test.ts:28
- The only test exercises the decoder-rejection fallback. It does not verify the core
isBlockhashValidpath for an expired or valid recent blockhash, the compiled-message conversion branch, or the durable-lifetime behavior, so an inverted result or broken RPC call would still pass. Add focused cases for those branches.
it('tracks a failure and treats the transaction as not expired', async () => {
packages/solana-wallet-snap/src/features/confirmation/views/ConfirmTransactionRequest/ConfirmTransactionRequest.tsx:34
- The new
shouldShowAlertbehavior is not covered by the confirmation component tests: they do not render an ERROR scan withuseSecurityAlertsdisabled. Add an assertion that an expired/error scan still shows the alert and disables confirmation, since this is the UI behavior that makes the new scan result visible to users.
const shouldShowAlert = context.preferences.useSecurityAlerts || isScanError;
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| : isTransactionBlockhashExpired( | ||
| interfaceContext.transaction, | ||
| connection.getRpc(interfaceContext.scope), | ||
| ), |
There was a problem hiding this comment.
It is highly unlikely a Dapp would send already expired transaction.
| } catch (error) { | ||
| logger.warn({ error }, 'Could not check transaction blockhash lifetime'); | ||
| await trackError(error); | ||
| return false; |
There was a problem hiding this comment.
I am not sure if we should block confirmation just because we can't check if transaction is expired. It might be rpc doesn't answer, etc... We track error and let user proceed the confirmation
There was a problem hiding this comment.
@tomstuart123 feedback would be great on this case.
There was a problem hiding this comment.
Hi @taran-a this makes sense. However, when you say We track error and let user proceed the confirmation what will the user see if the RPC doesn't answer for example? Any warning message?
There was a problem hiding this comment.
@tomstuart123 no actually, we do not show any warning. It might be that this error has no any effect on the transaction. Do you think we should show warning if we are not able to check the trx expiry?
e738de0 to
29e1ac0
Compare
|
Just a nit, there is the |
29e1ac0 to
b2ac2dd
Compare
Explanation
Adds expiry check to the confirmations screen (dapp trx)
Use fresh blockhash for MM transaction (send trx)
References
Checklist