Skip to content
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

Bugfix: cancel and speedup insufficient funds #1252

Merged
merged 6 commits into from
Jan 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 6 additions & 5 deletions app/components/UI/ActionModal/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ exports[`ActionModal should render correctly 1`] = `
<View
style={
Object {
"alignSelf": "center",
"backgroundColor": "#FFFFFF",
"borderRadius": 10,
"height": 300,
"width": "90%",
}
}
>
<View
style={
Object {
"flex": 1,
"alignItems": "center",
"flexDirection": "row",
"minHeight": 250,
}
}
/>
Expand Down Expand Up @@ -103,7 +103,7 @@ exports[`ActionModal should render correctly 1`] = `
testID=""
type="neutral"
>
CANCEL
Cancel
</StyledButton>
<StyledButton
containerStyle={
Expand All @@ -116,6 +116,7 @@ exports[`ActionModal should render correctly 1`] = `
},
]
}
disabled={false}
disabledContainerStyle={
Object {
"opacity": 0.6,
Expand All @@ -129,7 +130,7 @@ exports[`ActionModal should render correctly 1`] = `
testID=""
type="warning"
>
CONFIRM
Confirm
</StyledButton>
</View>
</View>
Expand Down
33 changes: 22 additions & 11 deletions app/components/UI/ActionModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { StyleSheet, View } from 'react-native';
import Modal from 'react-native-modal';
import { colors, baseStyles } from '../../../styles/common';
import { colors } from '../../../styles/common';
import StyledButton from '../StyledButton';
import { strings } from '../../../../locales/i18n';

const styles = StyleSheet.create({
modal: {
Expand All @@ -15,10 +16,8 @@ const styles = StyleSheet.create({
justifyContent: 'center',
alignItems: 'center'
},
modalText: {
alignSelf: 'center',
modalContainer: {
width: '90%',
height: 300,
backgroundColor: colors.white,
borderRadius: 10
},
Expand All @@ -29,6 +28,11 @@ const styles = StyleSheet.create({
flexDirection: 'row',
padding: 16
},
childrenContainer: {
minHeight: 250,
flexDirection: 'row',
alignItems: 'center'
},
button: {
flex: 1
},
Expand All @@ -49,6 +53,7 @@ export default function ActionModal({
cancelText,
children,
confirmText,
confirmDisabled,
cancelButtonMode,
confirmButtonMode,
onCancelPress,
Expand All @@ -66,24 +71,25 @@ export default function ActionModal({
swipeDirection={'down'}
>
<View style={styles.modalView}>
<View style={styles.modalText}>
<View style={baseStyles.flexGrow}>{children}</View>
<View style={styles.modalContainer}>
<View style={styles.childrenContainer}>{children}</View>
<View style={styles.actionContainer}>
<StyledButton
testID={cancelTestID}
type={cancelButtonMode}
onPress={onCancelPress}
containerStyle={[styles.button, styles.cancel]}
>
{cancelText.toUpperCase()}
{cancelText}
</StyledButton>
<StyledButton
testID={confirmTestID}
type={confirmButtonMode}
onPress={onConfirmPress}
containerStyle={[styles.button, styles.confirm]}
disabled={confirmDisabled}
>
{confirmText.toUpperCase()}
{confirmText}
</StyledButton>
</View>
</View>
Expand All @@ -97,8 +103,9 @@ ActionModal.defaultProps = {
confirmButtonMode: 'warning',
confirmTestID: '',
cancelTestID: '',
cancelText: 'CANCEL',
confirmText: 'CONFIRM'
cancelText: strings('action_view.cancel'),
confirmText: strings('action_view.confirm'),
confirmDisabled: false
};

ActionModal.propTypes = {
Expand All @@ -121,11 +128,15 @@ ActionModal.propTypes = {
/**
* Type of button to show as the cancel button
*/
cancelButtonMode: PropTypes.oneOf(['cancel', 'neutral', 'confirm']),
cancelButtonMode: PropTypes.oneOf(['cancel', 'neutral', 'confirm', 'normal']),
/**
* Type of button to show as the confirm button
*/
confirmButtonMode: PropTypes.oneOf(['normal', 'confirm', 'warning']),
/**
* Whether confirm button is disabled
*/
confirmDisabled: PropTypes.bool,
/**
* Text to show in the confirm button
*/
Expand Down
4 changes: 2 additions & 2 deletions app/components/UI/TransactionElement/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -608,14 +608,14 @@ class TransactionElement extends PureComponent {
const { tx } = this.props;
const existingGasPrice = tx.transaction ? tx.transaction.gasPrice : '0x0';
const existingGasPriceDecimal = parseInt(existingGasPrice === undefined ? '0x0' : existingGasPrice, 16);
this.mounted && this.props.onCancelAction(true, existingGasPriceDecimal, this.props.tx.id);
this.mounted && this.props.onCancelAction(true, existingGasPriceDecimal, this.props.tx);
};

showSpeedUpModal = () => {
const { tx } = this.props;
const existingGasPrice = tx.transaction ? tx.transaction.gasPrice : '0x0';
const existingGasPriceDecimal = parseInt(existingGasPrice === undefined ? '0x0' : existingGasPrice, 16);
this.mounted && this.props.onSpeedUpAction(true, existingGasPriceDecimal, this.props.tx.id);
this.mounted && this.props.onSpeedUpAction(true, existingGasPriceDecimal, this.props.tx);
};

hideSpeedUpModal = () => {
Expand Down
71 changes: 62 additions & 9 deletions app/components/UI/Transactions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import TransactionsNotificationManager from '../../../core/TransactionsNotificat
import ActionModal from '../ActionModal';
import { CANCEL_RATE, SPEED_UP_RATE } from 'gaba';
import { renderFromWei } from '../../../util/number';
import { safeToChecksumAddress } from '../../../util/address';
import { hexToBN } from 'gaba/dist/util';
import { BN } from 'ethereumjs-util';

const styles = StyleSheet.create({
wrapper: {
Expand Down Expand Up @@ -54,7 +57,8 @@ const styles = StyleSheet.create({
modalText: {
...fontStyles.normal,
fontSize: 14,
textAlign: 'center'
textAlign: 'center',
paddingVertical: 8
},
modalTitle: {
...fontStyles.bold,
Expand All @@ -64,7 +68,8 @@ const styles = StyleSheet.create({
gasTitle: {
...fontStyles.bold,
fontSize: 16,
textAlign: 'center'
textAlign: 'center',
marginVertical: 8
},
cancelFeeWrapper: {
backgroundColor: colors.grey000,
Expand All @@ -75,6 +80,13 @@ const styles = StyleSheet.create({
...fontStyles.bold,
fontSize: 24,
textAlign: 'center'
},
warningText: {
...fontStyles.normal,
fontSize: 12,
color: colors.red,
paddingVertical: 8,
textAlign: 'center'
}
});

Expand All @@ -85,6 +97,10 @@ const ROW_HEIGHT = (Platform.OS === 'ios' ? 95 : 100) + StyleSheet.hairlineWidth
*/
class Transactions extends PureComponent {
static propTypes = {
/**
* Map of accounts to information objects including balances
*/
accounts: PropTypes.object,
/**
* Object containing token exchange rates in the format address => exchangeRate
*/
Expand Down Expand Up @@ -161,7 +177,9 @@ class Transactions extends PureComponent {
ready: false,
refreshing: false,
cancelIsOpen: false,
speedUpIsOpen: false
cancelConfirmDisabled: false,
speedUpIsOpen: false,
speedUpConfirmDisabled: false
};

existingGasPriceDecimal = null;
Expand Down Expand Up @@ -265,10 +283,32 @@ class Transactions extends PureComponent {

blockExplorer = () => hasBlockExplorer(this.props.networkType);

onSpeedUpAction = (speedUpAction, existingGasPriceDecimal, speedUpTxId) => {
validateBalance = (tx, rate) => {
const { accounts } = this.props;
try {
const checksummedFrom = safeToChecksumAddress(tx.transaction.from);
const balance = accounts[checksummedFrom].balance;
return hexToBN(balance).lt(
hexToBN(tx.transaction.gasPrice)
.mul(new BN(rate * 10))
.mul(new BN(10))
.mul(hexToBN(tx.transaction.gas))
.add(hexToBN(tx.transaction.value))
);
} catch (e) {
return false;
}
};

onSpeedUpAction = (speedUpAction, existingGasPriceDecimal, tx) => {
this.setState({ speedUpIsOpen: speedUpAction });
this.existingGasPriceDecimal = existingGasPriceDecimal;
this.speedUpTxId = speedUpTxId;
this.speedUpTxId = tx.id;
if (this.validateBalance(tx, SPEED_UP_RATE)) {
this.setState({ speedUpIsOpen: speedUpAction, speedUpConfirmDisabled: true });
} else {
this.setState({ speedUpIsOpen: speedUpAction, speedUpConfirmDisabled: false });
}
};

onSpeedUpCompleted = () => {
Expand All @@ -277,12 +317,15 @@ class Transactions extends PureComponent {
this.speedUpTxId = null;
};

onCancelAction = (cancelAction, existingGasPriceDecimal, cancelTxId) => {
this.setState({ cancelIsOpen: cancelAction });
onCancelAction = (cancelAction, existingGasPriceDecimal, tx) => {
this.existingGasPriceDecimal = existingGasPriceDecimal;
this.cancelTxId = cancelTxId;
this.cancelTxId = tx.id;
if (this.validateBalance(tx, SPEED_UP_RATE)) {
this.setState({ cancelIsOpen: cancelAction, cancelConfirmDisabled: true });
} else {
this.setState({ cancelIsOpen: cancelAction, cancelConfirmDisabled: false });
}
};

onCancelCompleted = () => {
this.setState({ cancelIsOpen: false });
this.existingGasPriceDecimal = null;
Expand Down Expand Up @@ -342,6 +385,7 @@ class Transactions extends PureComponent {
}

const { submittedTransactions, confirmedTransactions, header } = this.props;
const { cancelConfirmDisabled, speedUpConfirmDisabled } = this.state;
const transactions =
submittedTransactions && submittedTransactions.length
? submittedTransactions.concat(confirmedTransactions)
Expand Down Expand Up @@ -369,6 +413,7 @@ class Transactions extends PureComponent {
onCancelPress={this.onCancelCompleted}
onRequestClose={this.onCancelCompleted}
onConfirmPress={this.cancelTransaction}
confirmDisabled={cancelConfirmDisabled}
>
<View style={styles.modalView}>
<Text style={styles.modalTitle}>{strings('transaction.cancel_tx_title')}</Text>
Expand All @@ -381,6 +426,9 @@ class Transactions extends PureComponent {
</Text>
</View>
<Text style={styles.modalText}>{strings('transaction.cancel_tx_message')}</Text>
{cancelConfirmDisabled && (
<Text style={styles.warningText}>{strings('transaction.insufficient')}</Text>
)}
</View>
</ActionModal>

Expand All @@ -391,6 +439,7 @@ class Transactions extends PureComponent {
onCancelPress={this.onSpeedUpCompleted}
onRequestClose={this.onSpeedUpCompleted}
onConfirmPress={this.speedUpTransaction}
confirmDisabled={speedUpConfirmDisabled}
>
<View style={styles.modalView}>
<Text style={styles.modalTitle}>{strings('transaction.speedup_tx_title')}</Text>
Expand All @@ -403,6 +452,9 @@ class Transactions extends PureComponent {
</Text>
</View>
<Text style={styles.modalText}>{strings('transaction.speedup_tx_message')}</Text>
{speedUpConfirmDisabled && (
<Text style={styles.warningText}>{strings('transaction.insufficient')}</Text>
)}
</View>
</ActionModal>
</View>
Expand All @@ -411,6 +463,7 @@ class Transactions extends PureComponent {
}

const mapStateToProps = state => ({
accounts: state.engine.backgroundState.AccountTrackerController.accounts,
tokens: state.engine.backgroundState.AssetsController.tokens.reduce((tokens, token) => {
tokens[token.address] = token;
return tokens;
Expand Down
3 changes: 3 additions & 0 deletions app/components/UI/Transactions/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ describe('Transactions', () => {
const initialState = {
engine: {
backgroundState: {
AccountTrackerController: {
accounts: {}
},
AssetsController: {
tokens: []
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
cancelTestID=""
cancelText="NEVERMIND"
confirmButtonMode="warning"
confirmDisabled={false}
confirmTestID=""
confirmText="RESET"
modalVisible={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ exports[`SecuritySettings should render correctly 1`] = `
cancelTestID=""
cancelText="NEVERMIND"
confirmButtonMode="warning"
confirmDisabled={false}
confirmTestID=""
confirmText="CLEAR"
modalVisible={false}
Expand Down Expand Up @@ -522,6 +523,7 @@ exports[`SecuritySettings should render correctly 1`] = `
cancelTestID=""
cancelText="NEVERMIND"
confirmButtonMode="warning"
confirmDisabled={false}
confirmTestID=""
confirmText="CLEAR"
modalVisible={false}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"ethjs-unit": "0.1.6",
"events": "3.0.0",
"fuse.js": "3.4.4",
"gaba": "1.9.0",
"gaba": "1.9.2",
"https-browserify": "0.0.1",
"lottie-react-native": "git+ssh://git@github.com/brunobar79/lottie-react-native.git#7ce6a78ac4ac7b9891bc513cb3f12f8b9c9d9106",
"multihashes": "0.4.14",
Expand Down
2 changes: 1 addition & 1 deletion scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ buildAndroid(){

buildIosSimulator(){
prebuild_ios
react-native run-ios --simulator "iPhone 11 Pro (13.2)"
react-native run-ios --simulator "iPhone 11 Pro (13.3)"
}

buildIosDevice(){
Expand Down
Loading