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

Feature: transfer approval #995

Merged
merged 2 commits into from
Aug 14, 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
7 changes: 5 additions & 2 deletions app/actions/transaction/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
}

Expand Down
62 changes: 45 additions & 17 deletions app/components/Nav/Main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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: {
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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');
}
};
Expand Down Expand Up @@ -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(
Expand Down
16 changes: 11 additions & 5 deletions app/components/Views/Approval/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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') {
Expand Down Expand Up @@ -255,8 +262,7 @@ const mapStateToProps = state => ({
});

const mapDispatchToProps = dispatch => ({
newTransaction: () => dispatch(newTransaction()),
setTransactionObject: transaction => dispatch(setTransactionObject(transaction))
newTransaction: () => dispatch(newTransaction())
});

export default connect(
Expand Down
6 changes: 0 additions & 6 deletions app/components/Views/BrowserTab/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -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))
});
Expand Down
6 changes: 5 additions & 1 deletion app/reducers/transaction/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion app/util/transactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -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': {
Expand Down