Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

fix: Fixes #361. Restrict user from clicking "Scan" to process tx before gas is calculated #386

Merged
merged 13 commits into from
Feb 11, 2019

Conversation

ltfschoen
Copy link
Contributor

@ltfschoen ltfschoen commented Jan 22, 2019

  • Update TxForm.js to add isEstimatingTxFee with simple boolean return value so we can check if all values including gas 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 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 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

…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
Copy link
Collaborator

@Tbaut Tbaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small comments.
I had an annoying bug, it's maybe not related (Kovan is quite ill at the moment, the node doesn't stay in sync), still if we could handle such events it's be nice, but that's prob. for a dedicated issue.
image

className='button'
>
{validating
{validating || !this.isEstimatedTxFee(values)
Copy link
Collaborator

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.

Copy link
Contributor

@axelchalon axelchalon Jan 23, 2019

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

Copy link
Contributor Author

@ltfschoen ltfschoen Jan 23, 2019

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...' };
      // }

screen shot 2019-01-24 at 8 16 03 am

@@ -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)) {
Copy link
Contributor

@axelchalon axelchalon Jan 23, 2019

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

Copy link
Contributor

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

Copy link
Collaborator

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.

@axelchalon
Copy link
Contributor

#361 (comment)

@ltfschoen
Copy link
Contributor Author

I've pushed changes addressing your review comments. Although I need help trying to figure out #386 (comment)

@Tbaut
Copy link
Collaborator

Tbaut commented Jan 24, 2019

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?

@ltfschoen
Copy link
Contributor Author

ltfschoen commented Jan 24, 2019

@Tbaut

  1. Comment out just the if statement so it runs return { gasPrice: 'Estimating gas...' }; (to simulate a situation when it's estimating gas and should show the validation popup with the message 'Estimating gas...' when both a valid recipient and amount are entered:
      // if (!this.isEstimatedTxFee(values)) {
        return { gasPrice: 'Estimating gas...' };
      // }
  1. Go to the Send Ether page to send a transaction
  2. Enter a valid recipient and a valid amount
  3. Expect to see a popup validation error stating 'Estimating gas...' above the Transaction Speed slider, however it doesn't appear as expected
  4. Change the value of the "Transaction Speed" by sliding it
  5. Observe the popup validation error stating 'Estimating gas...' appear above the Transaction Speed slider

if (!this.estimatedTxFee(values)) {
return;
if (!this.isEstimatedTxFee(values)) {
return { gasPrice: 'Estimating gas...' };
Copy link
Collaborator

@Tbaut Tbaut Jan 24, 2019

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.

Suggested change
return { gasPrice: 'Estimating gas...' };
return { amount: 'Estimating gas...' };

Copy link
Contributor Author

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

Copy link
Contributor Author

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

Copy link
Collaborator

@amaury1093 amaury1093 left a 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) &&
Copy link
Collaborator

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?

Copy link
Contributor Author

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') {
Copy link
Collaborator

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 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed

@ltfschoen
Copy link
Contributor Author

@amaurymartiny I've pushed commits that address your review comments

Copy link
Collaborator

@Tbaut Tbaut left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@amaury1093 amaury1093 merged commit 0dd96a7 into master Feb 11, 2019
@amaury1093 amaury1093 deleted the luke-361-prevent-scan-before-gas-calculated branch February 11, 2019 09:53
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants