-
Notifications
You must be signed in to change notification settings - Fork 33
fix: Fixes #361. Restrict user from clicking "Scan" to process tx before gas is calculated #386
fix: Fixes #361. Restrict user from clicking "Scan" to process tx before gas is calculated #386
Conversation
…ore gas is calculated * Add `isEstimatingTxFee` so we can check if all values including `gas` are available without actually having to calculate the tx fee and incorporate into estimateTxFee method * Display and disable the "Checking..." button if the `isEstimatingTxFee` returns false (i.e. `gas` still undefined) * Note: The bug associated with #361 appears to be Parity Signer-specific. If the user can click "Scan" before the `gas` has been calculated, then when it tries to go to the paritytech/fether/packages/fether-react/src/Send/TxQrCode/TxQrCode.js, where it calls `getRlp()` to get the value for the rlp prop of the QrSigner component, which calls `transactionToRlp(this.tx)` to get the RLP of the unsigned tx that is provided as an argument paritytech/fether/packages/fether-react/src/stores/sendStore.js, it crashes if `this.tx` contains a `gas` property that's undefined. So we need to prevent the user from being able to click "Scan" before the `gas` property has been determined. We do this by disabling the button and displaying "Checking..." until `isEstimatingTxFee` returns true, and only then do we display "Scan" and enable the button
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.
className='button' | ||
> | ||
{validating | ||
{validating || !this.isEstimatedTxFee(values) |
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 makes the button appear as "Checking..." when Fether isn't actually checking anything (e.g when no field is filled). This is confusing Ux-wise I think.
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.
Let's keep the validation logic inside validate()
// If the gas hasn't been calculated yet, then we don't show any errors,
// just wait a bit more
if (!this.isEstimatedTxFee(values)) {
return {gasPrice: "Estimating gas..."};
}
does the trick for me
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'm not sure why, but it only displays the validation popup "Estimating gas..." (shown below) if you've changed the slider value of the "Transaction Speed". If you only entered a recipient address and an amount then it doesn't show it.
i.e. try changing the code temporarily to the following so it should shows that validation error as soon as there is an amount and recipient, but after entering a recipient address and an amount it still doesn't appear. It'll only appear after you also change the "Transaction Speed".
// if (!this.isEstimatedTxFee(values)) {
return { gasPrice: 'Estimating gas...' };
// }
@@ -396,7 +407,7 @@ class TxForm extends Component { | |||
|
|||
// If the gas hasn't been calculated yet, then we don't show any errors, | |||
// just wait a bit more | |||
if (!this.estimatedTxFee(values)) { | |||
if (!this.isEstimatedTxFee(values)) { |
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.
replace with
// If the gas hasn't been calculated yet, then we don't show any errors,
// just wait a bit more
if (!this.isEstimatedTxFee(values)) {
return {gasPrice: "Estimating gas..."};
}
if the gas wasn't estimated yet, then the form isn't valid
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.
the only con is that this will show up as a disabled "Send" button rather than a "Verifying" button (while the gas is being estimated), but since this is for a short amount of time I think it's ok
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.
Yeah I think that's fine as a workaround for now, we can see later if that's a problem on mainnet later.
I've pushed changes addressing your review comments. Although I need help trying to figure out #386 (comment) |
I can't reproduce (with Signer account), can you walk me through the steps to reproduce? |
|
if (!this.estimatedTxFee(values)) { | ||
return; | ||
if (!this.isEstimatedTxFee(values)) { | ||
return { gasPrice: 'Estimating gas...' }; |
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.
Got it, this seems to be how the validate
props of final-form works, it would only display an error once the fields has actually been modified (makes sense).
A simple workaround would be to show the error on the amount
field, (that users must fill). I think this is fine because the gas estimation isn't particularly related to the gas price.
return { gasPrice: 'Estimating gas...' }; | |
return { amount: 'Estimating gas...' }; |
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.
Agreed, yes only difference is that the popup will appear about the Amount field
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.
@Tbaut I've pushed a commit that adopts the workaround that you mentioned of showing the errors on the amount
field instead
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.
Looks good to me overall
values.gas && | ||
values.gasPrice && | ||
!isNaN(values.amount) && | ||
!isNaN(values.gas) && |
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.
Just seeing this. values.gas
is a BigNumber, so isNaN(values.gas) is always true?
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.
We need values.gas
to be defined and !isNaN(values.gas)
to be true
for it to estimate the gas
When the Account page is loaded:
values.gas
is undefined
!isNaN(values.gas)
is false
!values.gas.isNaN()
is undefined
So it doesn't estimate the gas
After entering just Recipient address or just an Amount:
values.gas
is null
!isNaN(values.gas)
is true
!values.gas.isNaN()
is null
So it doesn't estimate the gas
After entering BOTH a Recipient address and an Amount:
values.gas
is BigNumber
(i.e. 21000)
!isNaN(values.gas)
is true
!values.gas.isNaN()
is true
So it DOES estimate the gas
==============
So it's better to use the .isNaN()
method provided for BigNumber values
@@ -394,10 +402,14 @@ class TxForm extends Component { | |||
return preValidation; | |||
} | |||
|
|||
if (values.gas && values.gas.toString() === '-1') { |
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'd say values.gas && values.gas.eq(-1)
looks slightly better :)
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.
Agreed
@amaurymartiny I've pushed commits that address your review comments |
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.
👍
Update TxForm.js to add
isEstimatingTxFee
with simple boolean return value so we can check if all values includinggas
are available without actually having to calculate if we don't need to.Update TxForm.js to display and disable the "Checking..." button if the
isEstimatingTxFee
returns false (i.e.gas
still undefined)Update TxDetails.js adding additional early exits if prop values are undefined. Note that these changes do not appear to have been the cause of the bug, but just doing extra due diligence
Note: The bug associated appears to be Parity Signer-specific. If the user was allowed to click "Scan" before the
gas
has been calculated (i.e. because we weren't disabling the "Scan" button on the form, and the "Scan" button would become enabled before the gas had finished being calculated, so if the user clicked "Scan" too quickly after it became enabled it would trigger the error), then when it tries to go to the paritytech/fether/packages/fether-react/src/Send/TxQrCode/TxQrCode.js, where it callsgetRlp()
to get the value for the rlp prop of the QrSigner component, which callstransactionToRlp(this.tx)
to get the RLP of the unsigned tx that is provided as an argument paritytech/fether/packages/fether-react/src/stores/sendStore.js, it crashes ifthis.tx
contains agas
property that's undefined.So we needed to prevent the user from being able to click "Scan" before the
gas
property has been determined.We do this by disabling the button and displaying "Checking..." until
isEstimatingTxFee
returns true, and only then do we display "Scan" and enable the button