-
Notifications
You must be signed in to change notification settings - Fork 5.4k
fix: hwb 76 fix incorrect transaction approved events log when user reject in hardware wallet #38089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix: hwb 76 fix incorrect transaction approved events log when user reject in hardware wallet #38089
Conversation
…nts-for-hardware-wallet
…lets - Updated the transaction controller to properly handle transaction approval and rejection events, particularly for hardware wallets. - Added logic to differentiate between failed and rejected transactions, ensuring that the appropriate event handlers are invoked based on the transaction status. - revert the createRPCMethodTrackingMiddleware.js back to main version. This change aims to provide a more robust user experience when interacting with hardware wallets during transaction confirmations.
…ing middleware - Adjusted the indentation of the error message status assignment in the createRPCMethodTrackingMiddleware.js file to improve code readability and maintain consistency with surrounding code structure.
|
CLA Signature Action: Thank you for your submission, we really appreciate it. We ask that you all read and sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just by adding a comment to this pull request with this exact sentence:
By commenting with the above message you are agreeing to the terms of the CLA. Your account will be recorded as agreeing to our CLA so you don't need to sign it again for future contributions to this repository. 1 out of 2 committers have signed the CLA. |
✨ Files requiring CODEOWNER review ✨✅ @MetaMask/confirmations (1 files, +19 -1)
|
app/scripts/controller-init/confirmations/transaction-controller-init.ts
Outdated
Show resolved
Hide resolved
app/scripts/controller-init/confirmations/transaction-controller-init.ts
Outdated
Show resolved
Hide resolved
Builds ready [65e499e]
UI Startup Metrics (1153 ± 94 ms)
📊 Page Load Benchmark ResultsCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
…nts-for-hardware-wallet
app/scripts/controller-init/confirmations/transaction-controller-init.ts
Show resolved
Hide resolved
Builds ready [717b815]
UI Startup Metrics (1350 ± 137 ms)
📊 Page Load Benchmark ResultsCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
…ad handling Updated the transaction controller listener to destructure `transactionMeta` from the payload directly, improving code clarity. This change ensures that the handling of transaction approval and rejection remains consistent while reducing redundancy in the function calls.
Builds ready [c937ecc]
UI Startup Metrics (1356 ± 137 ms)
📊 Page Load Benchmark ResultsCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
…nts-for-hardware-wallet
app/scripts/controller-init/confirmations/transaction-controller-init.ts
Show resolved
Hide resolved
Builds ready [8d60926]
UI Startup Metrics (1324 ± 135 ms)
📊 Page Load Benchmark ResultsCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
…s for hardware wallets Updated comments in the transaction controller to better explain the handling of rejected transactions when using hardware wallets. This addresses the issue where the transaction controller erroneously triggers a transactionApproved event after a user rejects a transaction on their device, clarifying the expected behavior for both Ledger and Trezor devices.
Co-authored-by: leo.wang <[email protected]>
|
Cursor Agent can help with this pull request. Just |
Builds ready [75a67d4]
UI Startup Metrics (1301 ± 132 ms)
📊 Page Load Benchmark ResultsCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
|
I have read the CLA Document and I hereby sign the CLA |
…nts-for-hardware-wallet
Builds ready [e5715b5]
UI Startup Metrics (1225 ± 109 ms)
📊 Page Load Benchmark ResultsCurrent Commit: 📄 Localhost MetaMask Test DappSamples: 100 Summary
📈 Detailed Results
Bundle size diffs [🚨 Warning! Bundle size has increased!]
|
|
I have read the CLA Document and I hereby sign the CLA. |
|
| // after user reject the transaction in devices. So we need to handle the transaction rejected here. | ||
| // ledger will make status as failed, and trezor will make status as rejected. | ||
| if ( | ||
| transactionMeta.status === TransactionStatus.failed || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still shouldn't be possible and I worry we're not treating the root cause.
If a transaction is unapproved, it should become only approved or rejected, does this suggest we're changing the status to failed somewhere when we should instead just be rejecting with a custom hardware wallet specific error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just debugged and this seems like an edge case we need to fix @matthewwalsh0, I think there is a race condition when hardware wallet rejects but this event cant catch up.
We can fix race condition later - but an easy fix will be status check and early return in handleTransactionApproved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This event should only fire once the approval promise is resolved.
So we should have as long as we want to reject, but is there a bad code path that is failing instead and rejecting also?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have missing check - when user rejects on hardware wallet:
-
It comes at this spot and fails transaction
https://github.com/MetaMask/core/blob/main/packages/transaction-controller/src/TransactionController.ts#L3325 -
But the result of
#approveTransactionis not handled here
https://github.com/MetaMask/core/blob/main/packages/transaction-controller/src/TransactionController.ts#L3088
We are not checkingapprovalResultto beApprovalState.NotApprovedhence it proceeds and publish:transactionApproved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi, @matthewwalsh0 and @OGPoyraz yea, you last comments is exactly what i found out before, actually i have another PR MetaMask/core#7214. which do the same fix to this issue, (if we keep that one, this PR is not required, event will be checked.), sorry i dont hve time and keep that PR sitting there too long.
My another fix in Transaction controller, basically i didnt check ApprovalState.NotApproved, but instead, i still check updatedTransactionMeta to see whether publish transaction failed event.
yea, i agree that fixing transaction-controller should be better fix then putting code in mobile level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks both, this makes sense now.
So the root issue is nothing to do with rejection, but if any keyring throws during signing, we change the status to failed internally, but continue to publish the approved event higher up the stack as no exception is thrown.
I agree we should fix in the original controller PR by checking ApprovalState result before publishing.
| const { transactionMeta } = payload; | ||
| if (!transactionMeta) { | ||
| await handleTransactionApproved(transactionMetricsRequest, payload); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I follow this check. Why we are triggering handler if there is no transactionMeta? Can you elaborate what case this is fixing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| await handleTransactionRejected(transactionMetricsRequest, payload); | ||
| } else { | ||
| await handleTransactionApproved(transactionMetricsRequest, payload); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than handling it here - can we carry this implementation into handleTransactionApproved handler. This file just supposed to connect handlers ideally we don't implement any logic here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here.
| transactionMeta.status === TransactionStatus.failed || | ||
| transactionMeta.status === TransactionStatus.rejected | ||
| ) { | ||
| await handleTransactionRejected(transactionMetricsRequest, payload); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly as it's commented above - this handler is getting triggered when rejected from device. But I can also see handleTransactionFailed is getting triggered afterwards. So triggering here once again will duplicate the events.
Rather than trying to trigger handleTransactionRejected or handleTransactionFailed what we need to do is just check transactionMeta if there is an error and status is not "approved" then we just interrupt.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
Description
This PR fix incorrect transaction approved events log when user reject in hardware wallet, which relative to #18361
Basically this pr override the transactionApproved listener in
Transaction-controller-init.tsand check the transactionMetadata return, if the metadata status isfailedorrejected, then we should logtransaction rejectedevent instead, which mean user reject in hardware wallet side which cause the transaction rejected.This PR fix the incorrect
Changelog
CHANGELOG entry: Override Transaction Approved event listener to handle hardware wallet user rejected event.
Related issues
Fixes: #18361
https://consensyssoftware.atlassian.net/browse/HWB-76
Manual testing steps
Screenshots/Recordings
Before
After
Pre-merge author checklist
Pre-merge reviewer checklist
Note
Updates the transactionApproved listener to call rejected handling when the transaction status is failed or rejected (hardware wallet user rejection), otherwise proceed with approved; adds TransactionStatus import.
app/scripts/controller-init/confirmations/transaction-controller-init.ts):TransactionController:transactionApprovedsubscription to:handleTransactionRejectedwhentransactionMeta.statusisTransactionStatus.failedorTransactionStatus.rejected.handleTransactionApprovedwhen status is not failed/rejected or whentransactionMetais absent.TransactionStatusfrom@metamask/transaction-controller.Written by Cursor Bugbot for commit e5715b5. This will update automatically on new commits. Configure here.