diff --git a/app/actions/transaction/index.js b/app/actions/transaction/index.js index dc897049fbb..495d24488aa 100644 --- a/app/actions/transaction/index.js +++ b/app/actions/transaction/index.js @@ -45,10 +45,13 @@ export function setTokensTransaction(asset) { /** * Enable Ether only to send in a transaction + * + * @param {object} transaction - Transaction additional object */ -export function setEtherTransaction() { +export function setEtherTransaction(transaction) { return { - type: 'SET_ETHER_TRANSACTION' + type: 'SET_ETHER_TRANSACTION', + transaction }; } diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js index e8feaa2cf20..3a6f0799dfd 100644 --- a/app/components/Nav/Main/index.js +++ b/app/components/Nav/Main/index.js @@ -65,8 +65,8 @@ import I18n, { strings } from '../../../../locales/i18n'; import { colors } from '../../../styles/common'; import LockManager from '../../../core/LockManager'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; -import { hexToBN, fromWei } from '../../../util/number'; -import { setTransactionObject } from '../../../actions/transaction'; +import { hexToBN, fromWei, renderFromTokenMinimalUnit } from '../../../util/number'; +import { setEtherTransaction, setTransactionObject } from '../../../actions/transaction'; import PersonalSign from '../../UI/PersonalSign'; import TypedSign from '../../UI/TypedSign'; import Modal from 'react-native-modal'; @@ -77,10 +77,11 @@ import PaymentChannelApproval from '../../UI/PaymentChannelApproval'; import PaymentChannelDeposit from '../../Views/PaymentChannel/PaymentChannelDeposit'; import PaymentChannelSend from '../../Views/PaymentChannel/PaymentChannelSend'; import Networks from '../../../util/networks'; -import { CONNEXT_DEPOSIT } from '../../../util/transactions'; +import { CONNEXT_DEPOSIT, getMethodData, TOKEN_METHOD_TRANSFER, decodeTransferData } from '../../../util/transactions'; import { toChecksumAddress, isValidAddress } from 'ethereumjs-util'; import { isENS } from '../../../util/address'; import Logger from '../../../util/Logger'; +import contractMap from 'eth-contract-metadata'; const styles = StyleSheet.create({ flex: { @@ -337,6 +338,10 @@ class Main extends PureComponent { * Flag that determines if payment channels are enabled */ paymentChannelsEnabled: PropTypes.bool, + /** + * Action that sets an ETH transaction + */ + setEtherTransaction: PropTypes.func, /** * Action that sets a transaction */ @@ -635,22 +640,44 @@ class Main extends PureComponent { await this.paymentChannelDepositSign(transactionMeta); } else { const { - transaction: { value, gas, gasPrice } + transaction: { value, gas, gasPrice, data, to } } = transactionMeta; - transactionMeta.transaction.value = hexToBN(value); - transactionMeta.transaction.readableValue = fromWei(transactionMeta.transaction.value); + transactionMeta.transaction.gas = hexToBN(gas); transactionMeta.transaction.gasPrice = hexToBN(gasPrice); - this.props.setTransactionObject({ - ...{ - symbol: 'ETH', - type: 'ETHER_TRANSACTION', - assetType: 'ETH', - selectedAsset: { isETH: true, symbol: 'ETH' }, - id: transactionMeta.id - }, - ...transactionMeta.transaction - }); + + if ( + value === '0x0' && + data !== '0x' && + to && + contractMap[toChecksumAddress(to)] && + (await getMethodData(data)).name === TOKEN_METHOD_TRANSFER + ) { + const decodedData = decodeTransferData('transfer', data); + const asset = contractMap[toChecksumAddress(to)]; + + transactionMeta.transaction.value = hexToBN(decodedData[2]); + transactionMeta.transaction.readableValue = renderFromTokenMinimalUnit( + hexToBN(decodedData[2]), + asset.decimals + ); + transactionMeta.transaction.to = decodedData[0]; + + this.props.setTransactionObject({ + type: 'INDIVIDUAL_TOKEN_TRANSACTION', + selectedAsset: asset, + id: transactionMeta.id, + ...transactionMeta.transaction + }); + } else { + transactionMeta.transaction.value = hexToBN(value); + transactionMeta.transaction.readableValue = fromWei(transactionMeta.transaction.value); + + this.props.setEtherTransaction({ + id: transactionMeta.id, + ...transactionMeta.transaction + }); + } this.props.navigation.push('ApprovalView'); } }; @@ -888,7 +915,8 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - setTransactionObject: asset => dispatch(setTransactionObject(asset)) + setEtherTransaction: transaction => dispatch(setEtherTransaction(transaction)), + setTransactionObject: transaction => dispatch(setTransactionObject(transaction)) }); export default connect( diff --git a/app/components/Views/Approval/index.js b/app/components/Views/Approval/index.js index 76f06d64154..95301650c46 100644 --- a/app/components/Views/Approval/index.js +++ b/app/components/Views/Approval/index.js @@ -6,7 +6,7 @@ import TransactionEditor from '../../UI/TransactionEditor'; import { BNToHex, hexToBN } from '../../../util/number'; import { getTransactionOptionsTitle } from '../../UI/Navbar'; import { colors } from '../../../styles/common'; -import { newTransaction, setTransactionObject } from '../../../actions/transaction'; +import { newTransaction } from '../../../actions/transaction'; import { connect } from 'react-redux'; import { toChecksumAddress } from 'ethereumjs-util'; import TransactionsNotificationManager from '../../../core/TransactionsNotificationManager'; @@ -149,10 +149,17 @@ class Approval extends PureComponent { */ onConfirm = async () => { const { TransactionController } = Engine.context; - const { transactions } = this.props; + const { + transactions, + transaction: { assetType, selectedAsset } + } = this.props; let { transaction } = this.props; try { - transaction = this.prepareTransaction(transaction); + if (assetType === 'ETH') { + transaction = this.prepareTransaction(transaction); + } else { + transaction = this.prepareAssetTransaction(transaction, selectedAsset); + } TransactionController.hub.once(`${transaction.id}:finished`, transactionMeta => { if (transactionMeta.status === 'submitted') { @@ -255,8 +262,7 @@ const mapStateToProps = state => ({ }); const mapDispatchToProps = dispatch => ({ - newTransaction: () => dispatch(newTransaction()), - setTransactionObject: transaction => dispatch(setTransactionObject(transaction)) + newTransaction: () => dispatch(newTransaction()) }); export default connect( diff --git a/app/components/Views/BrowserTab/index.js b/app/components/Views/BrowserTab/index.js index 72b941003b5..e4a375880aa 100644 --- a/app/components/Views/BrowserTab/index.js +++ b/app/components/Views/BrowserTab/index.js @@ -44,7 +44,6 @@ import WebviewError from '../../UI/WebviewError'; import { approveHost } from '../../../actions/privacy'; import { addBookmark, removeBookmark } from '../../../actions/bookmarks'; import { addToHistory, addToWhitelist } from '../../../actions/browser'; -import { setTransactionObject } from '../../../actions/transaction'; import DeviceSize from '../../../util/DeviceSize'; import AppConstants from '../../../core/AppConstants'; import SearchApi from 'react-native-search-api'; @@ -320,10 +319,6 @@ export class BrowserTab extends PureComponent { * String representing the current search engine */ searchEngine: PropTypes.string, - /** - * Action that sets a transaction - */ - setTransactionObject: PropTypes.func, /** * Function to store the a page in the browser history */ @@ -1743,7 +1738,6 @@ const mapDispatchToProps = dispatch => ({ removeBookmark: bookmark => dispatch(removeBookmark(bookmark)), addToBrowserHistory: ({ url, name }) => dispatch(addToHistory({ url, name })), addToWhitelist: url => dispatch(addToWhitelist(url)), - setTransactionObject: asset => dispatch(setTransactionObject(asset)), toggleNetworkModal: () => dispatch(toggleNetworkModal()), setOnboardingWizardStep: step => dispatch(setOnboardingWizardStep(step)) }); diff --git a/app/reducers/transaction/index.js b/app/reducers/transaction/index.js index df7a18809b5..7b9e2c0aa71 100644 --- a/app/reducers/transaction/index.js +++ b/app/reducers/transaction/index.js @@ -86,7 +86,11 @@ const transactionReducer = (state = initialState, action) => { case 'SET_ETHER_TRANSACTION': return { ...state, - type: 'ETHER_TRANSACTION' + symbol: 'ETH', + assetType: 'ETH', + selectedAsset: { isETH: true, symbol: 'ETH' }, + type: 'ETHER_TRANSACTION', + ...action.transaction }; case 'SET_INDIVIDUAL_TOKEN_TRANSACTION': return { diff --git a/app/util/transactions.js b/app/util/transactions.js index 24cd05b6dbe..ea27c31db57 100644 --- a/app/util/transactions.js +++ b/app/util/transactions.js @@ -114,7 +114,8 @@ export function decodeTransferData(type, data) { const bufferEncodedAddress = rawEncode(['address'], [addHexPrefix(encodedAddress)]); return [ addHexPrefix(rawDecode(['address'], bufferEncodedAddress)[0]), - parseInt(encodedAmount, 16).toString() + parseInt(encodedAmount, 16).toString(), + encodedAmount ]; } case 'transferFrom': {