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
| className='button' | ||
| > | ||
| {validating | ||
| {validating || !this.isEstimatedTxFee(values) |
There was a problem hiding this comment.
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.
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.
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...' };
// }
| // 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.
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.
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.
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.
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.
Agreed, yes only difference is that the popup will appear about the Amount field
There was a problem hiding this comment.
@Tbaut I've pushed a commit that adopts the workaround that you mentioned of showing the errors on the amount field instead
amaury1093
left a comment
There was a problem hiding this comment.
Looks good to me overall
| values.gas && | ||
| values.gasPrice && | ||
| !isNaN(values.amount) && | ||
| !isNaN(values.gas) && |
There was a problem hiding this comment.
Just seeing this. values.gas is a BigNumber, so isNaN(values.gas) is always true?
There was a problem hiding this comment.
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
| return preValidation; | ||
| } | ||
|
|
||
| if (values.gas && values.gas.toString() === '-1') { |
There was a problem hiding this comment.
I'd say values.gas && values.gas.eq(-1) looks slightly better :)
|
@amaurymartiny I've pushed commits that address your review comments |


Update TxForm.js to add
isEstimatingTxFeewith simple boolean return value so we can check if all values includinggasare available without actually having to calculate if we don't need to.Update TxForm.js to display and disable the "Checking..." button if the
isEstimatingTxFeereturns false (i.e.gasstill 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
gashas 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.txcontains agasproperty that's undefined.So we needed to prevent the user from being able to click "Scan" before the
gasproperty has been determined.We do this by disabling the button and displaying "Checking..." until
isEstimatingTxFeereturns true, and only then do we display "Scan" and enable the button