From 0d3a4767c779f646eee521efcfa7d1402fa88e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20Mi=C3=B1o?= Date: Mon, 5 Aug 2019 13:10:42 -0400 Subject: [PATCH] Bugfix: android tx list crashes (#973) * check for tx to before lowercase * small refactor * cleaner code * cleaner code * text transfoirm * snaps --- app/components/UI/EthereumAddress/index.js | 13 ++- .../TransferElement/index.js | 2 +- .../__snapshots__/index.test.js.snap | 1 + app/components/UI/TransactionElement/index.js | 101 ++++++++++-------- app/components/UI/Transactions/index.js | 2 +- app/components/Views/Asset/index.js | 4 +- app/components/Views/PaymentChannel/index.js | 2 +- app/util/address.js | 4 +- 8 files changed, 73 insertions(+), 56 deletions(-) diff --git a/app/components/UI/EthereumAddress/index.js b/app/components/UI/EthereumAddress/index.js index 672414746c3..73ee010c965 100644 --- a/app/components/UI/EthereumAddress/index.js +++ b/app/components/UI/EthereumAddress/index.js @@ -7,6 +7,7 @@ import networkMap from 'ethjs-ens/lib/network-map.json'; import Engine from '../../../core/Engine'; import { renderShortAddress, renderFullAddress } from '../../../util/address'; import Logger from '../../../util/Logger'; +import { isValidAddress } from 'ethereumjs-util'; /** * View that renders an ethereum address @@ -45,12 +46,14 @@ class EthereumAddress extends PureComponent { } formatAddress(rawAddress, type) { - let formattedAddress; + let formattedAddress = rawAddress; - if (type && type === 'short') { - formattedAddress = renderShortAddress(rawAddress); - } else { - formattedAddress = renderFullAddress(rawAddress); + if (isValidAddress(rawAddress)) { + if (type && type === 'short') { + formattedAddress = renderShortAddress(rawAddress); + } else { + formattedAddress = renderFullAddress(rawAddress); + } } return formattedAddress; } diff --git a/app/components/UI/TransactionElement/TransferElement/index.js b/app/components/UI/TransactionElement/TransferElement/index.js index eea46dc5a27..23e5ce19dcb 100644 --- a/app/components/UI/TransactionElement/TransferElement/index.js +++ b/app/components/UI/TransactionElement/TransferElement/index.js @@ -246,7 +246,7 @@ export default class TransferElement extends PureComponent { let [transactionElement, transactionDetails] = this.state.isCollectible ? this.getCollectibleTransfer(totalGas) : this.getTokenTransfer(totalGas); - transactionElement = { ...transactionElement, ...{ addressTo } }; + transactionElement = { ...transactionElement, renderTo: addressTo }; transactionDetails = { ...transactionDetails, ...{ diff --git a/app/components/UI/TransactionElement/__snapshots__/index.test.js.snap b/app/components/UI/TransactionElement/__snapshots__/index.test.js.snap index 8d074008131..b4bc8150482 100644 --- a/app/components/UI/TransactionElement/__snapshots__/index.test.js.snap +++ b/app/components/UI/TransactionElement/__snapshots__/index.test.js.snap @@ -89,6 +89,7 @@ exports[`TransactionElement should render correctly 1`] = ` "paddingHorizontal": 5, "paddingVertical": 3, "textAlign": "center", + "textTransform": "uppercase", "width": 75, }, null, diff --git a/app/components/UI/TransactionElement/index.js b/app/components/UI/TransactionElement/index.js index c1852733216..f5aad9f836c 100644 --- a/app/components/UI/TransactionElement/index.js +++ b/app/components/UI/TransactionElement/index.js @@ -61,6 +61,7 @@ const styles = StyleSheet.create({ fontSize: 9, letterSpacing: 0.5, width: 75, + textTransform: 'uppercase', ...fontStyles.bold }, amount: { @@ -254,8 +255,8 @@ class TransactionElement extends PureComponent { renderTxElementImage = transactionElement => { const { - addressTo, - addressFrom, + renderTo, + renderFrom, actionKey, contractDeployment = false, paymentChannelTransaction @@ -263,7 +264,6 @@ class TransactionElement extends PureComponent { const { tx: { networkID } } = this.props; - const checksumAddress = toChecksumAddress(addressTo); let logo; if (contractDeployment) { @@ -273,12 +273,12 @@ class TransactionElement extends PureComponent { ); } else if (actionKey === strings('transactions.smart_contract_interaction')) { - if (checksumAddress in contractMap) { - logo = contractMap[checksumAddress].logo; + if (renderTo in contractMap) { + logo = contractMap[renderTo].logo; } return ( @@ -299,7 +299,7 @@ class TransactionElement extends PureComponent { ); } - const isWithdraw = addressFrom === CONTRACTS[networkID]; + const isWithdraw = renderFrom === CONTRACTS[networkID]; if (isWithdraw) { return ( @@ -313,7 +313,7 @@ class TransactionElement extends PureComponent { ); } } - return ; + return ; }; /** @@ -325,11 +325,10 @@ class TransactionElement extends PureComponent { const { tx: { status } } = this.props; - const { addressTo, actionKey, value, fiatValue = false } = transactionElement; - const checksumAddress = toChecksumAddress(addressTo); + const { renderTo, actionKey, value, fiatValue = false } = transactionElement; let symbol; - if (checksumAddress in contractMap) { - symbol = contractMap[checksumAddress].symbol; + if (renderTo in contractMap) { + symbol = contractMap[renderTo].symbol; } return ( @@ -340,7 +339,7 @@ class TransactionElement extends PureComponent { {symbol ? symbol + ' ' + actionKey : actionKey} - {status.toUpperCase()} + {status} {value} @@ -351,7 +350,7 @@ class TransactionElement extends PureComponent { ); }; - renderTransferFromElement = () => { + decodeTransferFromTx = () => { const { tx: { transaction: { gas, gasPrice, data, to }, @@ -375,9 +374,12 @@ class TransactionElement extends PureComponent { ? strings('unit.token_id') + tokenId + ' ' + collectible.symbol : strings('unit.token_id') + tokenId; + const renderFrom = renderFullAddress(addressFrom); + const renderTo = renderFullAddress(addressTo); + const transactionDetails = { - renderFrom: renderFullAddress(addressFrom), - renderTo: renderFullAddress(addressTo), + renderFrom, + renderTo, transactionHash, renderValue: renderCollectible, renderGas: parseInt(gas, 16).toString(), @@ -394,8 +396,8 @@ class TransactionElement extends PureComponent { }; const transactionElement = { - addressTo, - addressFrom, + renderTo, + renderFrom, actionKey, value: `${strings('unit.token_id')}${tokenId}`, fiatValue: collectible ? collectible.symbol : undefined @@ -404,7 +406,7 @@ class TransactionElement extends PureComponent { return [transactionElement, transactionDetails]; }; - renderConfirmElement = () => { + decodeConfirmTx = () => { const { tx: { transaction: { value, gas, gasPrice, from, to }, @@ -417,27 +419,30 @@ class TransactionElement extends PureComponent { const { actionKey } = this.state; const totalEth = hexToBN(value); const renderTotalEth = renderFromWei(totalEth) + ' ' + ticker; - const renderTotalEthFiat = weiToFiat(totalEth, conversionRate, currentCurrency.toUpperCase()); + const renderTotalEthFiat = weiToFiat(totalEth, conversionRate, currentCurrency); const gasBN = hexToBN(gas); const gasPriceBN = hexToBN(gasPrice); const totalGas = isBN(gasBN) && isBN(gasPriceBN) ? gasBN.mul(gasPriceBN) : toBN('0x0'); const totalValue = isBN(totalEth) ? totalEth.add(totalGas) : totalGas; + const renderFrom = renderFullAddress(from); + const renderTo = renderFullAddress(to); + const transactionDetails = { - renderFrom: from ? renderFullAddress(from) : strings('transactions.tx_details_not_available'), - renderTo: to ? renderFullAddress(to) : strings('transactions.tx_details_not_available'), + renderFrom, + renderTo, transactionHash, renderValue: renderFromWei(value) + ' ' + ticker, renderGas: parseInt(gas, 16).toString(), renderGasPrice: renderToGwei(gasPrice), renderTotalValue: renderFromWei(totalValue) + ' ' + ticker, - renderTotalValueFiat: weiToFiat(totalValue, conversionRate, currentCurrency.toUpperCase()) + renderTotalValueFiat: weiToFiat(totalValue, conversionRate, currentCurrency) }; const transactionElement = { - addressTo: to, - addressFrom: from, + renderTo, + renderFrom, actionKey, value: renderTotalEth, fiatValue: renderTotalEthFiat @@ -446,10 +451,10 @@ class TransactionElement extends PureComponent { return [transactionElement, transactionDetails]; }; - renderDeploymentElement = () => { + decodeDeploymentTx = () => { const { tx: { - transaction: { value, gas, gasPrice, to, from }, + transaction: { value, gas, gasPrice, from }, transactionHash }, conversionRate, @@ -462,32 +467,35 @@ class TransactionElement extends PureComponent { const totalGas = isBN(gasBN) && isBN(gasPriceBN) ? gasBN.mul(gasPriceBN) : toBN('0x0'); const renderTotalEth = renderFromWei(totalGas) + ' ' + ticker; - const renderTotalEthFiat = weiToFiat(totalGas, conversionRate, currentCurrency.toUpperCase()); + const renderTotalEthFiat = weiToFiat(totalGas, conversionRate, currentCurrency); const totalEth = isBN(value) ? value.add(totalGas) : totalGas; + const renderFrom = renderFullAddress(from); + const renderTo = strings('transactions.to_contract'); + const transactionElement = { - addressTo: to, - addressFrom: from, + renderTo, + renderFrom, actionKey, value: renderTotalEth, fiatValue: renderTotalEthFiat, contractDeployment: true }; const transactionDetails = { - renderFrom: renderFullAddress(from), - renderTo: strings('transactions.to_contract'), + renderFrom, + renderTo, transactionHash, renderValue: renderFromWei(value) + ' ' + ticker, renderGas: parseInt(gas, 16).toString(), renderGasPrice: renderToGwei(gasPrice), renderTotalValue: renderFromWei(totalEth) + ' ' + ticker, - renderTotalValueFiat: weiToFiat(totalEth, conversionRate, currentCurrency.toUpperCase()) + renderTotalValueFiat: weiToFiat(totalEth, conversionRate, currentCurrency) }; return [transactionElement, transactionDetails]; }; - renderPaymentChannelTx = () => { + decodePaymentChannelTx = () => { const { tx: { networkID, @@ -502,16 +510,19 @@ class TransactionElement extends PureComponent { const contract = CONTRACTS[networkID]; const isDeposit = contract && to.toLowerCase() === contract.toLowerCase(); const totalEth = hexToBN(value); - const totalEthFiat = weiToFiat(totalEth, conversionRate, currentCurrency.toUpperCase()); + const totalEthFiat = weiToFiat(totalEth, conversionRate, currentCurrency); const readableTotalEth = renderFromWei(totalEth); const renderTotalEth = readableTotalEth + ' ' + (isDeposit ? strings('unit.eth') : strings('unit.dai')); const renderTotalEthFiat = isDeposit ? totalEthFiat : balanceToFiat(parseFloat(readableTotalEth), conversionRate, exchangeRate, currentCurrency); + const renderFrom = renderFullAddress(from); + const renderTo = renderFullAddress(to); + const transactionDetails = { - renderFrom: renderFullAddress(from), - renderTo: renderFullAddress(to), + renderFrom, + renderTo, transactionHash, renderGas: gas ? parseInt(gas, 16).toString() : strings('transactions.tx_details_not_available'), renderGasPrice: gasPrice ? renderToGwei(gasPrice) : strings('transactions.tx_details_not_available'), @@ -521,8 +532,8 @@ class TransactionElement extends PureComponent { }; const transactionElement = { - addressTo: to, - addressFrom: from, + renderFrom, + renderTo, actionKey, value: renderTotalEth, fiatValue: renderTotalEthFiat, @@ -565,23 +576,23 @@ class TransactionElement extends PureComponent { ); } if (paymentChannelTransaction) { - [transactionElement, transactionDetails] = this.renderPaymentChannelTx(); + [transactionElement, transactionDetails] = this.decodePaymentChannelTx(); } else { switch (actionKey) { case strings('transactions.sent_collectible'): - [transactionElement, transactionDetails] = this.renderTransferFromElement(totalGas); + [transactionElement, transactionDetails] = this.decodeTransferFromTx(totalGas); break; case strings('transactions.contract_deploy'): - [transactionElement, transactionDetails] = this.renderDeploymentElement(totalGas); + [transactionElement, transactionDetails] = this.decodeDeploymentTx(totalGas); break; default: - [transactionElement, transactionDetails] = this.renderConfirmElement(totalGas); + [transactionElement, transactionDetails] = this.decodeConfirmTx(totalGas); } } return ( diff --git a/app/components/UI/Transactions/index.js b/app/components/UI/Transactions/index.js index da93239da0f..d78742c4d11 100644 --- a/app/components/UI/Transactions/index.js +++ b/app/components/UI/Transactions/index.js @@ -229,7 +229,7 @@ class Transactions extends PureComponent { contractExchangeRates={this.props.contractExchangeRates} exchangeRate={this.props.exchangeRate} conversionRate={this.props.conversionRate} - currentCurrency={this.props.currentCurrency} + currentCurrency={this.props.currentCurrency.toUpperCase()} showAlert={this.props.showAlert} navigation={this.props.navigation} /> diff --git a/app/components/Views/Asset/index.js b/app/components/Views/Asset/index.js index dc7e9070a3a..21a86ff6daf 100644 --- a/app/components/Views/Asset/index.js +++ b/app/components/Views/Asset/index.js @@ -127,8 +127,8 @@ class Asset extends PureComponent { if (symbol.toUpperCase() !== 'ETH' && tokenAddress !== '') { txs = txs.filter( tx => - tx.transaction.from.toLowerCase() === tokenAddress.toLowerCase() || - tx.transaction.to.toLowerCase() === tokenAddress.toLowerCase() + (tx.transaction.from && tx.transaction.from.toLowerCase()) === tokenAddress.toLowerCase() || + (tx.transaction.to && tx.transaction.to.toLowerCase()) === tokenAddress.toLowerCase() ); } diff --git a/app/components/Views/PaymentChannel/index.js b/app/components/Views/PaymentChannel/index.js index 94c3ccbeb10..0239dd77816 100644 --- a/app/components/Views/PaymentChannel/index.js +++ b/app/components/Views/PaymentChannel/index.js @@ -407,7 +407,7 @@ class PaymentChannel extends PureComponent { internalTransactions.forEach(tx => { if ( Networks[provider.type].networkId.toString() === tx.networkID && - tx.transaction.to.toLowerCase() === selectedAddress.toLowerCase() + (tx.transaction.to && tx.transaction.to.toLowerCase()) === selectedAddress.toLowerCase() ) { parsedTransactions.push({ ...tx, diff --git a/app/util/address.js b/app/util/address.js index 647cc9fbe27..15bad54b4f0 100644 --- a/app/util/address.js +++ b/app/util/address.js @@ -1,6 +1,8 @@ import { toChecksumAddress } from 'ethereumjs-util'; import Engine from '../core/Engine'; import AppConstants from '../core/AppConstants'; +import { strings } from '../../locales/i18n'; + /** * Returns full checksummed address * @@ -8,7 +10,7 @@ import AppConstants from '../core/AppConstants'; * @returns {String} - String corresponding to full checksummed address */ export function renderFullAddress(address) { - return toChecksumAddress(address); + return address ? toChecksumAddress(address) : strings('transactions.tx_details_not_available'); } /**