Skip to content

Commit

Permalink
fix: eth token transaction list
Browse files Browse the repository at this point in the history
  • Loading branch information
kilmas committed Sep 28, 2020
1 parent 4bd269f commit 0ec9c0a
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 58 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,8 @@ android {
applicationId "com.qhwallet"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 41
versionName "1.0.39"
versionCode 42
versionName "1.0.40"
multiDexEnabled true
missingDimensionStrategy 'react-native-camera', 'general'
}
Expand Down
12 changes: 6 additions & 6 deletions ios/QHWallet.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -804,7 +804,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 81;
CURRENT_PROJECT_VERSION = 82;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = C35A7P8ZWU;
HEADER_SEARCH_PATHS = (
Expand All @@ -813,7 +813,7 @@
);
INFOPLIST_FILE = QHWallet/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.52;
MARKETING_VERSION = 1.0.53;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
Expand All @@ -833,15 +833,15 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 81;
CURRENT_PROJECT_VERSION = 82;
DEVELOPMENT_TEAM = C35A7P8ZWU;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-customized-image-picker/ios/**",
);
INFOPLIST_FILE = QHWallet/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.52;
MARKETING_VERSION = 1.0.53;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
Expand Down Expand Up @@ -907,15 +907,15 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 81;
CURRENT_PROJECT_VERSION = 82;
DEVELOPMENT_TEAM = C35A7P8ZWU;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/react-native-customized-image-picker/ios/**",
);
INFOPLIST_FILE = QHWallet/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.0.52;
MARKETING_VERSION = 1.0.53;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
Expand Down
4 changes: 3 additions & 1 deletion src/components/UI/Tokens/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Alert, Image, TouchableOpacity, StyleSheet, Text, View } from 'react-native';
import { BigNumber } from "bignumber.js";
import { List, Icon, ActionSheet } from '@ant-design/react-native';
import { inject, observer } from 'mobx-react';
import TokenImage from '../TokenImage';
Expand Down Expand Up @@ -138,9 +139,10 @@ class Tokens extends React.Component {
const itemAddress = safeToChecksumAddress(asset.address);
const logo = asset.logo || ((contractMap[itemAddress] && contractMap[itemAddress].logo) || undefined);
const exchangeRate = itemAddress in tokenExchangeRates ? tokenExchangeRates[itemAddress] : undefined;

const balance =
asset.balance ||
(itemAddress in tokenBalances ? renderFromTokenMinimalUnit(tokenBalances[itemAddress], asset.decimals) : 0);
(itemAddress in tokenBalances ? renderFromTokenMinimalUnit(new BigNumber(tokenBalances[itemAddress]), asset.decimals) : 0);
const balanceFiat = asset.balanceFiat || balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency);
const balanceValue = `${balance} ${asset.symbol}`;

Expand Down
104 changes: 102 additions & 2 deletions src/components/UI/TransactionElement/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import contractMap from 'eth-contract-metadata';
import { toChecksumAddress } from 'web3-utils';
import { renderFullAddress, safeToChecksumAddress } from '../../../utils/address';
import { TRANSACTION_TYPES } from "../../../utils/transactions";
import { decodeTransferData, isCollectibleAddress, getTicker, getActionKey } from '../../../utils/transactions';
import AppConstants from '../../../modules/metamask/core/AppConstants';
import { strings } from '../../../locales/i18n';
Expand Down Expand Up @@ -232,6 +234,102 @@ function getCollectibleTransfer(args) {
return [transactionElement, transactionDetails];
}

function decodeIncomingTransfer(args) {
const {
tx: {
transaction: { to, from, value },
transferInformation: { symbol, decimals, contractAddress },
transactionHash
},
conversionRate,
currentCurrency,
contractExchangeRates,
totalGas,
actionKey,
primaryCurrency,
selectedAddress
} = args;

const amount = toBN(value);
const token = { symbol, decimals, address: contractAddress };

const renderTokenAmount = token
? `${renderFromTokenMinimalUnit(amount, token.decimals)} ${token.symbol}`
: undefined;
const exchangeRate = token ? contractExchangeRates[toChecksumAddress(token.address)] : undefined;

let renderTokenFiatAmount, renderTokenFiatNumber;
if (exchangeRate) {
renderTokenFiatAmount = balanceToFiat(
fromTokenMinimalUnit(amount, token.decimals) || 0,
conversionRate,
exchangeRate,
currentCurrency
);
renderTokenFiatNumber = balanceToFiatNumber(
fromTokenMinimalUnit(amount, token.decimals) || 0,
conversionRate,
exchangeRate
);
}

const renderToken = token
? `${renderFromTokenMinimalUnit(amount, token.decimals)} ${token.symbol}`
: strings('transaction.value_not_available');
const totalFiatNumber = renderTokenFiatNumber
? weiToFiatNumber(totalGas, conversionRate) + renderTokenFiatNumber
: weiToFiatNumber(totalGas, conversionRate);

const ticker = getTicker(args.ticker);

const { SENT_TOKEN, RECEIVED_TOKEN } = TRANSACTION_TYPES;
const transactionType = renderFullAddress(from) === selectedAddress ? SENT_TOKEN : RECEIVED_TOKEN;

let transactionDetails = {
renderTotalGas: `${renderFromWei(totalGas)} ${ticker}`,
renderValue: renderToken,
renderFrom: renderFullAddress(from),
renderTo: renderFullAddress(to),
transactionHash,
transactionType
};
if (primaryCurrency === 'ETH') {
transactionDetails = {
...transactionDetails,
summaryAmount: renderToken,
summaryFee: `${renderFromWei(totalGas)} ${ticker}`,
summaryTotalAmount: `${renderToken} ${strings('unit.divisor')} ${renderFromWei(totalGas)} ${ticker}`,
summarySecondaryTotalAmount: totalFiatNumber
? `${addCurrencySymbol(totalFiatNumber, currentCurrency)}`
: undefined
};
} else {
transactionDetails = {
...transactionDetails,
summaryAmount: renderTokenFiatAmount
? `${renderTokenFiatAmount}`
: `${addCurrencySymbol(0, currentCurrency)}`,
summaryFee: weiToFiat(totalGas, conversionRate, currentCurrency),
summaryTotalAmount: totalFiatNumber ? `${addCurrencySymbol(totalFiatNumber, currentCurrency)}` : undefined,
summarySecondaryTotalAmount: `${renderToken} ${strings('unit.divisor')} ${renderFromWei(
totalGas
)} ${ticker}`
};
}

const transactionElement = {
actionKey,
renderFrom: renderFullAddress(from),
renderTo: renderFullAddress(to),
value: !renderTokenAmount ? strings('transaction.value_not_available') : renderTokenAmount,
fiatValue: renderTokenFiatAmount ? `${renderTokenFiatAmount}` : renderTokenFiatAmount,
isIncomingTransfer: true,
transactionType
};

return [transactionElement, transactionDetails];
}

async function decodeTransferTx(args) {
const {
tx: {
Expand Down Expand Up @@ -478,15 +576,17 @@ function decodeConfirmTx(args, paymentChannelTransaction) {
export default async function decodeTransaction(args) {
const {
tx,
tx: { paymentChannelTransaction },
tx: { paymentChannelTransaction, isTransfer },
selectedAddress,
ticker
} = args;
const actionKey = tx.actionKey || (await getActionKey(tx, selectedAddress, ticker, paymentChannelTransaction));
let transactionElement, transactionDetails;
if (paymentChannelTransaction) {
[transactionElement, transactionDetails] = decodePaymentChannelTx({ ...args, actionKey });
} else {
} else if (isTransfer) {
[transactionElement, transactionDetails] = decodeIncomingTransfer({ ...args, actionKey });
} else {
switch (actionKey) {
case strings('transactions.sent_tokens'):
[transactionElement, transactionDetails] = await decodeTransferTx({ ...args, actionKey });
Expand Down
58 changes: 34 additions & 24 deletions src/pages/Asset/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,31 +111,40 @@ class Asset extends React.Component {
didTxStatusesChange = newTxsPending => this.txsPending.length !== newTxsPending.length;

ethFilter = tx => {
const { selectedAddress, networkType } = this.props;
const networkId = Networks[networkType].networkId;
const {
transaction: { from, to }
} = tx;
return (
(safeToChecksumAddress(from) === selectedAddress || safeToChecksumAddress(to) === selectedAddress) &&
((networkId && networkId.toString() === tx.networkID) ||
(networkType === 'rpc' && !isKnownNetwork(tx.networkID))) &&
tx.status !== 'unapproved'
);
const { selectedAddress, networkType } = this.props;
const networkId = Networks[networkType].networkId;
const {
transaction: { from, to },
isTransfer,
transferInformation
} = tx;
if (isTransfer)
return this.props.tokens.find(
({ address }) => address.toLowerCase() === transferInformation.contractAddress.toLowerCase()
);
return (
(safeToChecksumAddress(from) === selectedAddress || safeToChecksumAddress(to) === selectedAddress) &&
((networkId && networkId.toString() === tx.networkID) ||
(networkType === 'rpc' && !isKnownNetwork(tx.networkID))) &&
tx.status !== 'unapproved'
);
};

noEthFilter = tx => {
const { networkType } = this.props;
const networkId = Networks[networkType].networkId;
const {
transaction: { to, from }
} = tx;
return (
(from & (from.toLowerCase() === this.navAddress) || (to && to.toLowerCase() === this.navAddress)) &&
((networkId && networkId.toString() === tx.networkID) ||
(networkType === 'rpc' && !isKnownNetwork(tx.networkID))) &&
tx.status !== 'unapproved'
);
const { networkType } = this.props;
const networkId = Networks[networkType].networkId;
const {
transaction: { to, from },
isTransfer,
transferInformation
} = tx;
if (isTransfer) return this.navAddress === transferInformation.contractAddress.toLowerCase();
return (
(from & (from.toLowerCase() === this.navAddress) || (to && to.toLowerCase() === this.navAddress)) &&
((networkId && networkId.toString() === tx.networkID) ||
(networkType === 'rpc' && !isKnownNetwork(tx.networkID))) &&
tx.status !== 'unapproved'
);
};

normalizeTransactions() {
Expand Down Expand Up @@ -274,7 +283,8 @@ export default inject(({ store: state }) => ({
currentCurrency: state.engine.backgroundState.CurrencyRateController.currentCurrency,
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
networkType: state.engine.backgroundState.NetworkController.provider.type,
transactions: state.engine.backgroundState.TransactionController.transactions

transactions: state.engine.backgroundState.TransactionController.transactions,
tokens: state.engine.backgroundState.AssetsController.tokens,

}))(observer(Asset))

1 change: 0 additions & 1 deletion src/pages/BrowserTab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,6 @@ export class BrowserTab extends React.Component {
if (pwd === password) {
const tronTeb = Tronweb.instance
const resp = await tronTeb.trx.sign(transaction)
console.log(resp)
Toast.success('sign success')
currentWebview.postMessage(JSON.stringify({ key: data.key, tronWeb, data: resp }))
} else {
Expand Down
73 changes: 51 additions & 22 deletions src/utils/transactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { util } from '@metamask/controllers';
import Engine from '../modules/metamask/core/Engine';
import { safeToChecksumAddress } from './address';
import { strings } from '../locales/i18n';
import AppConstants from '../modules/metamask/core/AppConstants'

export const TOKEN_METHOD_TRANSFER = 'transfer';
export const TOKEN_METHOD_APPROVE = 'approve';
Expand All @@ -27,6 +28,8 @@ export const APPROVE_FUNCTION_SIGNATURE = '0x095ea7b3';
export const CONNEXT_DEPOSIT = '0xea682e37';
export const CONTRACT_CREATION_SIGNATURE = '0x60a060405260046060527f48302e31';


const { SAI_ADDRESS } = AppConstants
/**
* Utility class with the single responsibility
* of caching CollectibleAddresses
Expand Down Expand Up @@ -60,6 +63,21 @@ const actionKeys = {
[CONNEXT_DEPOSIT_ACTION_KEY]: strings('transactions.instant_payment_deposit')
};

export const TRANSACTION_TYPES = {
PAYMENT_CHANNEL_DEPOSIT: 'payment_channel_deposit',
PAYMENT_CHANNEL_WITHDRAW: 'payment_channel_withdraw',
PAYMENT_CHANNEL_SENT: 'payment_channel_sent',
PAYMENT_CHANNEL_RECEIVED: 'payment_channel_received',
SENT: 'transaction_sent',
SENT_TOKEN: 'transaction_sent_token',
SENT_COLLECTIBLE: 'transaction_sent_collectible',
RECEIVED: 'transaction_received',
RECEIVED_TOKEN: 'transaction_received_token',
RECEIVED_COLLECTIBLE: 'transaction_received_collectible',
SITE_INTERACTION: 'transaction_site_interaction',
APPROVE: 'transaction_approve'
};

/**
* Generates transfer data for specified method
*
Expand Down Expand Up @@ -264,28 +282,39 @@ export async function getTransactionActionKey(transaction) {
* @returns {string} - Transaction type message
*/
export async function getActionKey(tx, selectedAddress, ticker, paymentChannelTransaction) {
const actionKey = await getTransactionActionKey(tx);
if (actionKey === SEND_ETHER_ACTION_KEY) {
ticker = paymentChannelTransaction ? strings('unit.sai') : ticker;
const incoming = safeToChecksumAddress(tx.transaction.to) === selectedAddress;
const selfSent = incoming && safeToChecksumAddress(tx.transaction.from) === selectedAddress;
return incoming
? selfSent
? ticker
? strings('transactions.self_sent_unit', { unit: ticker })
: strings('transactions.self_sent_ether')
: ticker
? strings('transactions.received_unit', { unit: ticker })
: strings('transactions.received_ether')
: ticker
? strings('transactions.sent_unit', { unit: ticker })
: strings('transactions.sent_ether');
}
const transactionActionKey = actionKeys[actionKey];
if (transactionActionKey) {
return transactionActionKey;
}
return actionKey;
if (tx.isTransfer) {
const selfSent = safeToChecksumAddress(tx.transaction.from) === selectedAddress;
const translationKey = selfSent ? 'transactions.self_sent_unit' : 'transactions.received_unit';
// Third party sending wrong token symbol
if (tx.transferInformation.contractAddress === SAI_ADDRESS.toLowerCase()) tx.transferInformation.symbol = 'SAI';
return strings(translationKey, { unit: tx.transferInformation.symbol });
}

const actionKey = await getTransactionActionKey(tx);

if (actionKey === SEND_ETHER_ACTION_KEY) {
ticker = paymentChannelTransaction ? strings('unit.sai') : ticker;
const incoming = safeToChecksumAddress(tx.transaction.to) === selectedAddress;
const selfSent = incoming && safeToChecksumAddress(tx.transaction.from) === selectedAddress;
return incoming
? selfSent
? ticker
? strings('transactions.self_sent_unit', { unit: ticker })
: strings('transactions.self_sent_ether')
: ticker
? strings('transactions.received_unit', { unit: ticker })
: strings('transactions.received_ether')
: ticker
? strings('transactions.sent_unit', { unit: ticker })
: strings('transactions.sent_ether');
}
const transactionActionKey = actionKeys[actionKey];

if (transactionActionKey) {
return transactionActionKey;
}

return actionKey;
}

/**
Expand Down

0 comments on commit 0ec9c0a

Please sign in to comment.