Skip to content
This repository was archived by the owner on May 24, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
6eaa9e3
WIP - Fixes #293. Shows tx fee estimate and total tx amount. See issu…
ltfschoen Dec 18, 2018
f4d6784
Merge branch 'master' into luke-293-show-tx-fee
ltfschoen Dec 19, 2018
b0ce528
review-fix: Swap order that Amount and Gas Price are shown
ltfschoen Dec 19, 2018
9f3b3c6
review-fix: Rename Gas Price back to Transaction Speed
ltfschoen Dec 19, 2018
ba122f2
review-fix: Combine Tx Fees and Total Amount into a Tx Details component
ltfschoen Dec 19, 2018
c491cba
review-fix: Squeeze calculation into details section and refactor code
ltfschoen Dec 19, 2018
0be070d
refactor: Rename Calculation to Calcs so fits in better
ltfschoen Dec 19, 2018
48136d1
review-fix: Gas Price of 21000 is measured in Wei not Gwei
ltfschoen Dec 20, 2018
eebf01d
review-fix: Remove the division by 10**18 since makes it look too com…
ltfschoen Dec 20, 2018
aa689f4
review-fix: Darken the colour of the Details section placeholder text
ltfschoen Dec 20, 2018
6964453
review-fix: Toggling the Details/Hide buttons no longer makes Send bu…
ltfschoen Dec 20, 2018
18dab6e
merge latest from master and fix merge conflict
ltfschoen Dec 20, 2018
d053f7d
merge latest from master
ltfschoen Dec 25, 2018
d9e6a0a
refactor: Make it gas limit clearer in calcs. Round to 9 decimals to …
ltfschoen Dec 27, 2018
0e86a7a
refactor: Simplify syntax of call to function
ltfschoen Dec 27, 2018
13fd9f6
fix: Fix unresolved promise bug when enter valid amount and recipient…
ltfschoen Dec 27, 2018
2ef7659
review-fix: Reorder tx details and make clearer
ltfschoen Jan 1, 2019
5a631b2
review-fix: Tweak tx details. Convert functions into instance methods.
ltfschoen Jan 1, 2019
6ac70de
review-fix: Refactor into TxDetails component and make text selectable
ltfschoen Jan 1, 2019
7f45a5a
fix: Remvoe useless else
ltfschoen Jan 1, 2019
96b7109
review-fix: Use fromWei to convert to ether values
ltfschoen Jan 2, 2019
01887a3
review-fix: Fix indentation
ltfschoen Jan 2, 2019
e576126
review-fix: Add try/catch and throw error if estimateGas throws. See …
ltfschoen Jan 2, 2019
b3fc6e2
review-fix: Move logic so TxDetails not unnecessarily mounted
ltfschoen Jan 2, 2019
2e4ef04
refactor: Move TxDetails in TxForm folder since only used by that com…
ltfschoen Jan 3, 2019
86d6e19
Merge branch 'master' into luke-293-show-tx-fee
ltfschoen Jan 3, 2019
d370246
review-fix: Replace concat with interpolated strings on new lines
ltfschoen Jan 3, 2019
44fa269
fix: Fix typo
ltfschoen Jan 4, 2019
7a53f64
review-fix: Pass down estimatedTxFee value instead of the function as…
ltfschoen Jan 4, 2019
e7af4eb
review-fix: Remove useless prop that is no longer used
ltfschoen Jan 4, 2019
c331736
review-fix: Change TxDetails text to be full opacity to match normal …
ltfschoen Jan 4, 2019
7af4838
review-fix: Show values that have Wei decimal places. Need remove tra…
ltfschoen Jan 4, 2019
7b79b80
review-fix: Remove trailing zeros from big number decimal values for …
ltfschoen Jan 4, 2019
b73ecab
fix: Do not process removing trailing zeros when more than one decima…
ltfschoen Jan 4, 2019
063215b
merge latest from master
ltfschoen Jan 4, 2019
e5e3a76
refactor: Move autofocus from the Amount to the To input field on TxForm
ltfschoen Jan 4, 2019
2a9403b
review-fix: Hide vertical overflow on body element so scrollbar not f…
ltfschoen Jan 4, 2019
a684de2
review-fix: Remove toFixed(18) so do not need script to remove traili…
ltfschoen Jan 4, 2019
bd56db6
review-fix: TxDetails floats above footer. TxDetails toggle buttons m…
ltfschoen Jan 4, 2019
2d96f28
review-fix: Restore TxDetails between inputs and footer. Move toggle …
ltfschoen Jan 6, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/fether-react/src/Onboarding/Onboarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import termsAndConditions from './termsAndConditions.md';
*/
const reactMarkdownOptions = {
link: props => (
<a href={props.href} target='_blank'>
<a href={props.href} target='_blank' rel='noopener noreferrer'>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice. Not sure this vulnerability concerns us since we're not a website, but anyways, it's a good habit to have. 👍

{props.children}
</a>
)
Expand Down
1 change: 1 addition & 0 deletions packages/fether-react/src/Send/Sent/Sent.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class Sent extends Component {
token.address
)}
target='_blank'
rel='noopener noreferrer'
>
<button className='button -tiny'>See it on BlockScout</button>
</a>
Expand Down
70 changes: 70 additions & 0 deletions packages/fether-react/src/Send/TxForm/TxDetails/TxDetails.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: BSD-3-Clause

import React, { Component } from 'react';
import BigNumber from 'bignumber.js';
import { fromWei, toWei } from '@parity/api/lib/util/wei';

class TxDetails extends Component {
renderCalculation = () => {
const { estimatedTxFee, values } = this.props;

const gasPriceBn = new BigNumber(values.gasPrice.toString());
const gasLimitBn = estimatedTxFee
.div(gasPriceBn)
.div(10 ** 9)
.toFixed(0)
.toString();

return `Estimate amount of gas: ${gasLimitBn}`;
};

renderDetails = () => {
return `${this.renderCalculation()}
${this.renderFee()}
${this.renderTotalAmount()}`;
};

renderFee = () => {
const { estimatedTxFee } = this.props;

return `Fee: ${fromWei(estimatedTxFee, 'ether')
.toFixed(9)
.toString()} ETH (estimate * gas price)`;
};

renderTotalAmount = () => {
const { estimatedTxFee, token, values } = this.props;

return `Total Amount: ${fromWei(
estimatedTxFee.plus(
token.address === 'ETH' ? toWei(values.amount.toString()) : 0
),
'ether'
).toString()} ETH`;
};

render () {
const { showDetails } = this.props;

return (
<div>
<div className='form_field'>
<div hidden={!showDetails}>
<label htmlFor='txDetails'>Transaction Details (Estimate):</label>
<textarea
className='-sm-details'
id='txDetails'
readOnly
value={this.renderDetails()}
/>
</div>
</div>
</div>
);
}
}

export default TxDetails;
8 changes: 8 additions & 0 deletions packages/fether-react/src/Send/TxForm/TxDetails/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: BSD-3-Clause

import TxDetails from './TxDetails';

export default TxDetails;
141 changes: 113 additions & 28 deletions packages/fether-react/src/Send/TxForm/TxForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import TokenBalance from '../../Tokens/TokensList/TokenBalance';
import withAccount from '../../utils/withAccount.js';
import withBalance, { withEthBalance } from '../../utils/withBalance';
import withTokens from '../../utils/withTokens';
import TxDetails from './TxDetails';

const MAX_GAS_PRICE = 40; // In Gwei
const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
Expand All @@ -37,26 +38,32 @@ const MIN_GAS_PRICE = 3; // Safelow gas price from GasStation, in Gwei
@observer
class Send extends Component {
state = {
maxSelected: false
};
handleSubmit = values => {
const { accountAddress, history, sendStore, token } = this.props;

sendStore.setTx(values);
history.push(`/send/${token.address}/from/${accountAddress}/signer`);
maxSelected: false,
showDetails: false
};

decorator = createDecorator({
field: /to|amount/, // when the value of these fields change...
updates: {
// ...set field "gas"
gas: (value, allValues) => {
gas: async (value, allValues) => {
const { parityStore, token } = this.props;
let newGasEstimate = null;

if (this.preValidate(allValues) === true) {
return estimateGas(allValues, token, parityStore.api);
} else {
return null;
try {
newGasEstimate = await estimateGas(
allValues,
token,
parityStore.api
);
} catch (error) {
console.error(error);
throw new Error('Unable to estimate gas');
}
}

return newGasEstimate;
}
}
});
Expand All @@ -78,6 +85,28 @@ class Send extends Component {
return output;
};

estimatedTxFee = values => {
if (
!values.amount ||
!values.gas ||
!values.gasPrice ||
isNaN(values.amount) ||
isNaN(values.gas) ||
isNaN(values.gasPrice)
) {
return null;
}

return values.gas.multipliedBy(toWei(values.gasPrice, 'shannon'));
};

handleSubmit = values => {
const { accountAddress, history, sendStore, token } = this.props;

sendStore.setTx(values);
history.push(`/send/${token.address}/from/${accountAddress}/signer`);
};

recalculateMax = (args, state, { changeValue }) => {
changeValue(state, 'amount', value => {
return this.calculateMax(
Expand All @@ -91,13 +120,37 @@ class Send extends Component {
this.setState({ maxSelected: !this.state.maxSelected });
};

showDetailsAnchor = () => {
return (
<span className='toggle-details'>
<a onClick={this.toggleDetails}>&darr; Details</a>
</span>
);
};

showHideAnchor = () => {
return (
<span className='toggle-details'>
<a onClick={this.toggleDetails}>&uarr; Hide</a>
</span>
);
};

toggleDetails = () => {
const { showDetails } = this.state;

this.setState({ showDetails: !showDetails });
};

render () {
const {
accountAddress,
sendStore: { tx },
token
} = this.props;

const { showDetails } = this.state;

return (
<div>
<Header
Expand Down Expand Up @@ -132,7 +185,17 @@ class Send extends Component {
<form className='send-form' onSubmit={handleSubmit}>
<fieldset className='form_fields'>
<Field
as='textarea'
autoFocus
className='-sm'
label='To'
name='to'
placeholder='0x...'
required
render={FetherForm.Field}
/>

<Field
className='form_field_amount'
formNoValidate
label='Amount'
Expand All @@ -159,16 +222,6 @@ class Send extends Component {
</button>
</Field>

<Field
as='textarea'
className='-sm'
label='To'
name='to'
placeholder='0x...'
required
render={FetherForm.Field}
/>

<Field
centerText={`${values.gasPrice} GWEI`}
className='-range'
Expand All @@ -184,6 +237,19 @@ class Send extends Component {
type='range' // In Gwei
/>

{/* eslint-disable */}
{valid &&
!validating &&
this.estimatedTxFee(values) ? (
<TxDetails
estimatedTxFee={this.estimatedTxFee(values)}
showDetails={showDetails}
token={token}
values={values}
/>
) : null}
{/* eslint-enable */}

<OnChange name='gasPrice'>
{(value, previous) => {
if (this.state.maxSelected) {
Expand All @@ -202,6 +268,17 @@ class Send extends Component {
)}
</fieldset>
<nav className='form-nav'>
{/* eslint-disable */}
{valid &&
!validating &&
this.estimatedTxFee(values) ? (
<div className="form-details-buttons">
{showDetails
? this.showHideAnchor()
: this.showDetailsAnchor()}
</div>
) : null}
{/* eslint-enable */}
<button
disabled={!valid || validating}
className='button'
Expand All @@ -226,6 +303,10 @@ class Send extends Component {
preValidate = values => {
const { balance, token } = this.props;

if (!values) {
return;
}

if (!values.amount) {
return { amount: 'Please enter a valid amount' };
}
Expand Down Expand Up @@ -268,29 +349,33 @@ class Send extends Component {
* the tx.
*/
validateForm = debounce(values => {
if (!values) {
return;
}

try {
const { ethBalance, token } = this.props;

if (!ethBalance) {
throw new Error('No "ethBalance"');
}

const preValidation = this.preValidate(values);

// preValidate return an error if a field isn't valid
if (preValidation !== true) {
return preValidation;
}

// If the gas hasn't been calculated yet, then we don't show any errors,
// just wait a bit more
if (!values.gas) {
if (!this.estimatedTxFee(values)) {
return;
}

if (!ethBalance || isNaN(values.gas)) {
throw new Error('No "ethBalance" or "gas" value.');
}

// Verify that `gas + (eth amount if sending eth) <= ethBalance`
if (
values.gas
.multipliedBy(toWei(values.gasPrice, 'shannon'))
this.estimatedTxFee(values)
.plus(token.address === 'ETH' ? toWei(values.amount) : 0)
.gt(toWei(ethBalance))
) {
Expand Down
12 changes: 12 additions & 0 deletions packages/fether-react/src/assets/sass/components/_form-nav.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.form-nav {
position: relative;
padding-top: 0.5rem;
display: flex;
justify-content: center;
Expand All @@ -10,4 +11,15 @@
&.-space-around {
justify-content: space-around;
}

.form-details-buttons {
position: absolute;
left: 1rem;

.toggle-details > a {
color: $dark-grey;
font-size: 0.8rem;
font-weight: 400;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $chrome: #F5F6F6;
$faint: #ddd;
$black: #222;
$grey: #888;
$dark-grey: #444;

$purple: #330044;
$blue: #160DF6;
Expand Down
1 change: 1 addition & 0 deletions packages/fether-react/src/assets/sass/shared/_basics.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ body {
font-weight: 400;
font-size: ms(0);
line-height: ms(0) * 1.3;
overflow-y: hidden;
}

.hidden {
Expand Down
14 changes: 14 additions & 0 deletions packages/fether-react/src/assets/sass/shared/_form.scss
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@
font-family: $mono;
font-size: ms(-1);

&.-xs-inline {
display: inline-flex;
height: 2.5rem;
}

&.-sm-details {
color: $dark-grey;
font-size: 0.6rem;
width: 100%;
height: 4.75rem;
opacity: 1;
resize: none;
}

&.-sm {
height: 3.5rem;
}
Expand Down