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: android tx list crashes #973

Merged
merged 6 commits into from
Aug 5, 2019
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
13 changes: 8 additions & 5 deletions app/components/UI/EthereumAddress/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
...{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ exports[`TransactionElement should render correctly 1`] = `
"paddingHorizontal": 5,
"paddingVertical": 3,
"textAlign": "center",
"textTransform": "uppercase",
"width": 75,
},
null,
Expand Down
101 changes: 56 additions & 45 deletions app/components/UI/TransactionElement/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const styles = StyleSheet.create({
fontSize: 9,
letterSpacing: 0.5,
width: 75,
textTransform: 'uppercase',
...fontStyles.bold
},
amount: {
Expand Down Expand Up @@ -254,16 +255,15 @@ class TransactionElement extends PureComponent {

renderTxElementImage = transactionElement => {
const {
addressTo,
addressFrom,
renderTo,
renderFrom,
actionKey,
contractDeployment = false,
paymentChannelTransaction
} = transactionElement;
const {
tx: { networkID }
} = this.props;
const checksumAddress = toChecksumAddress(addressTo);
let logo;

if (contractDeployment) {
Expand All @@ -273,20 +273,20 @@ class TransactionElement extends PureComponent {
</FadeIn>
);
} 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 (
<TokenImage
asset={{ address: addressTo, logo }}
asset={{ address: renderTo, logo }}
containerStyle={styles.tokenImageStyle}
iconStyle={styles.tokenImageStyle}
logoDefined
/>
);
} else if (paymentChannelTransaction) {
const contract = CONTRACTS[networkID];
const isDeposit = contract && addressTo.toLowerCase() === contract.toLowerCase();
const isDeposit = contract && renderTo.toLowerCase() === contract.toLowerCase();
if (isDeposit) {
return (
<FadeIn style={styles.paymentChannelTransactionIconWrapper}>
Expand All @@ -299,7 +299,7 @@ class TransactionElement extends PureComponent {
</FadeIn>
);
}
const isWithdraw = addressFrom === CONTRACTS[networkID];
const isWithdraw = renderFrom === CONTRACTS[networkID];
if (isWithdraw) {
return (
<FadeIn style={styles.paymentChannelTransactionIconWrapper}>
Expand All @@ -313,7 +313,7 @@ class TransactionElement extends PureComponent {
);
}
}
return <Identicon address={addressTo} diameter={24} />;
return <Identicon address={renderTo} diameter={24} />;
};

/**
Expand All @@ -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 (
<View style={styles.rowOnly}>
Expand All @@ -340,7 +339,7 @@ class TransactionElement extends PureComponent {
<Text numberOfLines={1} style={styles.address}>
{symbol ? symbol + ' ' + actionKey : actionKey}
</Text>
<Text style={[styles.status, this.getStatusStyle(status)]}>{status.toUpperCase()}</Text>
<Text style={[styles.status, this.getStatusStyle(status)]}>{status}</Text>
</View>
<View style={styles.amounts}>
<Text style={styles.amount}>{value}</Text>
Expand All @@ -351,7 +350,7 @@ class TransactionElement extends PureComponent {
);
};

renderTransferFromElement = () => {
decodeTransferFromTx = () => {
const {
tx: {
transaction: { gas, gasPrice, data, to },
Expand All @@ -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(),
Expand All @@ -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
Expand All @@ -404,7 +406,7 @@ class TransactionElement extends PureComponent {
return [transactionElement, transactionDetails];
};

renderConfirmElement = () => {
decodeConfirmTx = () => {
const {
tx: {
transaction: { value, gas, gasPrice, from, to },
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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'),
Expand All @@ -521,8 +532,8 @@ class TransactionElement extends PureComponent {
};

const transactionElement = {
addressTo: to,
addressFrom: from,
renderFrom,
renderTo,
actionKey,
value: renderTotalEth,
fiatValue: renderTotalEthFiat,
Expand Down Expand Up @@ -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 (
<TouchableHighlight
style={styles.row}
onPress={this.onPressItem} // eslint-disable-line react/jsx-no-bind
onPress={this.onPressItem}
underlayColor={colors.grey000}
activeOpacity={1}
>
Expand Down
2 changes: 1 addition & 1 deletion app/components/UI/Transactions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}
/>
Expand Down
4 changes: 2 additions & 2 deletions app/components/Views/Asset/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()
);
}

Expand Down
2 changes: 1 addition & 1 deletion app/components/Views/PaymentChannel/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion app/util/address.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { toChecksumAddress } from 'ethereumjs-util';
import Engine from '../core/Engine';
import AppConstants from '../core/AppConstants';
import { strings } from '../../locales/i18n';

/**
* Returns full checksummed address
*
* @param {String} address - String corresponding to an address
* @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');
}

/**
Expand Down