From 2ed5bafa119015049443f17bc2972c4aadab22d9 Mon Sep 17 00:00:00 2001 From: Brad Decker Date: Wed, 10 Mar 2021 14:16:44 -0600 Subject: [PATCH] remove transactionCategory in favor of more types (#10615) * remove transactionCategory in favor of more types * remove reference to STANDARD in stubs --- .../controllers/incoming-transactions.js | 4 +- app/scripts/controllers/transactions/index.js | 58 +++++--- app/scripts/migrations/053.js | 46 ++++++ app/scripts/migrations/index.js | 1 + shared/constants/transaction.js | 71 ++++----- test/data/transaction-data.json | 34 ++--- .../controllers/incoming-transactions.test.js | 12 +- test/unit/app/controllers/network/stubs.js | 7 +- .../transactions/tx-controller.test.js | 51 ++++--- test/unit/migrations/053.test.js | 136 ++++++++++++++++++ .../transaction-breakdown.container.js | 5 +- ...transaction-list-item-details.component.js | 5 +- .../transaction-list.component.js | 12 +- ui/app/ducks/swaps/swaps.js | 6 +- ui/app/helpers/constants/transactions.js | 8 +- ui/app/helpers/utils/transactions.util.js | 41 +++--- .../helpers/utils/transactions.util.test.js | 4 +- ui/app/hooks/tests/useTokenData.test.js | 8 +- .../tests/useTransactionDisplayData.test.js | 4 +- ui/app/hooks/useSwappedTokenValue.js | 10 +- ui/app/hooks/useTransactionDisplayData.js | 44 +++--- .../confirm-approve/confirm-approve.util.js | 4 +- .../confirm-transaction-base.component.js | 20 +-- .../confirm-transaction-base.container.js | 9 +- .../confirm-transaction-switch.component.js | 16 +-- .../confirm-transaction.container.js | 4 +- .../tests/confirm-transaction.test.js | 4 +- ui/app/selectors/transactions.js | 9 +- 28 files changed, 389 insertions(+), 244 deletions(-) create mode 100644 app/scripts/migrations/053.js create mode 100644 test/unit/migrations/053.test.js diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index b6227d984..632bd96a4 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -6,7 +6,7 @@ import { bnToHex } from '../lib/util'; import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_STATUSES, } from '../../../shared/constants/transaction'; import { @@ -296,7 +296,7 @@ export default class IncomingTransactionsController { value: bnToHex(new BN(txMeta.value)), }, hash: txMeta.hash, - transactionCategory: TRANSACTION_CATEGORIES.INCOMING, + type: TRANSACTION_TYPES.INCOMING, }; } } diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index f153558d3..d6bfe48c3 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -19,7 +19,6 @@ import { import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'; import { getSwapsTokensReceivedFromTxMeta } from '../../../../ui/app/pages/swaps/swaps.util'; import { - TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../../shared/constants/transaction'; @@ -235,11 +234,10 @@ export default class TransactionController extends EventEmitter { `generateTxMeta` adds the default txMeta properties to the passed object. These include the tx's `id`. As we use the id for determining order of txes in the tx-state-manager, it is necessary to call the asynchronous - method `this._determineTransactionCategory` after `generateTxMeta`. + method `this._determineTransactionType` after `generateTxMeta`. */ let txMeta = this.txStateManager.generateTxMeta({ txParams: normalizedTxParams, - type: TRANSACTION_TYPES.STANDARD, }); if (origin === 'metamask') { @@ -265,11 +263,10 @@ export default class TransactionController extends EventEmitter { txMeta.origin = origin; - const { - transactionCategory, - getCodeResponse, - } = await this._determineTransactionCategory(txParams); - txMeta.transactionCategory = transactionCategory; + const { type, getCodeResponse } = await this._determineTransactionType( + txParams, + ); + txMeta.type = type; // ensure value txMeta.txParams.value = txMeta.txParams.value @@ -347,7 +344,7 @@ export default class TransactionController extends EventEmitter { return {}; } else if ( txMeta.txParams.to && - txMeta.transactionCategory === TRANSACTION_CATEGORIES.SENT_ETHER + txMeta.type === TRANSACTION_TYPES.SENT_ETHER ) { // if there's data in the params, but there's no contract code, it's not a valid transaction if (txMeta.txParams.data) { @@ -581,7 +578,7 @@ export default class TransactionController extends EventEmitter { async publishTransaction(txId, rawTx) { const txMeta = this.txStateManager.getTx(txId); txMeta.rawTx = rawTx; - if (txMeta.transactionCategory === TRANSACTION_CATEGORIES.SWAP) { + if (txMeta.type === TRANSACTION_TYPES.SWAP) { const preTxBalance = await this.query.getBalance(txMeta.txParams.from); txMeta.preTxBalance = preTxBalance.toString(16); } @@ -637,7 +634,7 @@ export default class TransactionController extends EventEmitter { 'transactions#confirmTransaction - add txReceipt', ); - if (txMeta.transactionCategory === TRANSACTION_CATEGORIES.SWAP) { + if (txMeta.type === TRANSACTION_TYPES.SWAP) { const postTxBalance = await this.query.getBalance(txMeta.txParams.from); const latestTxMeta = this.txStateManager.getTx(txId); @@ -812,10 +809,27 @@ export default class TransactionController extends EventEmitter { } /** - Returns a "type" for a transaction out of the following list: simpleSend, tokenTransfer, tokenApprove, - contractDeployment, contractMethodCall - */ - async _determineTransactionCategory(txParams) { + * @typedef { 'transfer' | 'approve' | 'transferfrom' | 'contractInteraction'| 'sentEther' } InferrableTransactionTypes + */ + + /** + * @typedef {Object} InferTransactionTypeResult + * @property {InferrableTransactionTypes} type - The type of transaction + * @property {string} getCodeResponse - The contract code, in hex format if + * it exists. '0x0' or '0x' are also indicators of non-existent contract + * code + */ + + /** + * Determines the type of the transaction by analyzing the txParams. + * This method will return one of the types defined in shared/constants/transactions + * It will never return TRANSACTION_TYPE_CANCEL or TRANSACTION_TYPE_RETRY as these + * represent specific events that we control from the extension and are added manually + * at transaction creation. + * @param {Object} txParams - Parameters for the transaction + * @returns {InferTransactionTypeResult} + */ + async _determineTransactionType(txParams) { const { data, to } = txParams; let name; try { @@ -825,16 +839,16 @@ export default class TransactionController extends EventEmitter { } const tokenMethodName = [ - TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, - TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, - TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM, + TRANSACTION_TYPES.TOKEN_METHOD_APPROVE, + TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, + TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM, ].find((methodName) => methodName === name && name.toLowerCase()); let result; if (data && tokenMethodName) { result = tokenMethodName; } else if (data && !to) { - result = TRANSACTION_CATEGORIES.DEPLOY_CONTRACT; + result = TRANSACTION_TYPES.DEPLOY_CONTRACT; } let code; @@ -849,11 +863,11 @@ export default class TransactionController extends EventEmitter { const codeIsEmpty = !code || code === '0x' || code === '0x0'; result = codeIsEmpty - ? TRANSACTION_CATEGORIES.SENT_ETHER - : TRANSACTION_CATEGORIES.CONTRACT_INTERACTION; + ? TRANSACTION_TYPES.SENT_ETHER + : TRANSACTION_TYPES.CONTRACT_INTERACTION; } - return { transactionCategory: result, getCodeResponse: code }; + return { type: result, getCodeResponse: code }; } /** diff --git a/app/scripts/migrations/053.js b/app/scripts/migrations/053.js new file mode 100644 index 000000000..f9d4dc55c --- /dev/null +++ b/app/scripts/migrations/053.js @@ -0,0 +1,46 @@ +import { cloneDeep } from 'lodash'; +import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; + +const version = 53; + +/** + * Deprecate transactionCategory and consolidate on 'type' + */ +export default { + version, + async migrate(originalVersionedData) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; + }, +}; + +function transformState(state) { + const transactions = state?.TransactionController?.transactions; + const incomingTransactions = + state?.IncomingTransactionsController?.incomingTransactions; + if (Array.isArray(transactions)) { + transactions.forEach((transaction) => { + if ( + transaction.type !== TRANSACTION_TYPES.RETRY && + transaction.type !== TRANSACTION_TYPES.CANCEL + ) { + transaction.type = transaction.transactionCategory; + } + delete transaction.transactionCategory; + }); + } + if (incomingTransactions) { + const incomingTransactionsEntries = Object.entries(incomingTransactions); + incomingTransactionsEntries.forEach(([key, transaction]) => { + delete transaction.transactionCategory; + state.IncomingTransactionsController.incomingTransactions[key] = { + ...transaction, + type: TRANSACTION_TYPES.INCOMING, + }; + }); + } + return state; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index b4368c1b5..b30410202 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -57,6 +57,7 @@ const migrations = [ require('./050').default, require('./051').default, require('./052').default, + require('./053').default, ]; export default migrations; diff --git a/shared/constants/transaction.js b/shared/constants/transaction.js index 833463a60..87c33ebca 100644 --- a/shared/constants/transaction.js +++ b/shared/constants/transaction.js @@ -1,8 +1,26 @@ /** * Transaction Type is a MetaMask construct used internally * @typedef {Object} TransactionTypes - * @property {'standard'} STANDARD - A standard transaction, usually the first with - * a given nonce + * @property {'transfer'} TOKEN_METHOD_TRANSFER - A token transaction where the user + * is sending tokens that they own to another address + * @property {'transferfrom'} TOKEN_METHOD_TRANSFER_FROM - A token transaction + * transferring tokens from an account that the sender has an allowance of. + * For more information on allowances, see the approve type. + * @property {'approve'} TOKEN_METHOD_APPROVE - A token transaction requesting an + * allowance of the token to spend on behalf of the user + * @property {'incoming'} INCOMING - An incoming (deposit) transaction + * @property {'sentEther'} SENT_ETHER - A transaction sending ether to a recipient + * @property {'contractInteraction'} CONTRACT_INTERACTION - A transaction that is + * interacting with a smart contract's methods that we have not treated as a special + * case, such as approve, transfer, and transferfrom + * @property {'contractDeployment'} DEPLOY_CONTRACT - A transaction that deployed + * a smart contract + * @property {'swap'} SWAP - A transaction swapping one token for another through + * MetaMask Swaps + * @property {'swapApproval'} SWAP_APPROVAL - Similar to the approve type, a swap + * approval is a special case of ERC20 approve method that requests an allowance of + * the token to spend on behalf of the user for the MetaMask Swaps contract. The first + * swap for any token will have an accompanying swapApproval transaction. * @property {'cancel'} CANCEL - A transaction submitted with the same nonce as a * previous transaction, a higher gas price and a zeroed out send amount. Useful * for users who accidentally send to erroneous addresses or if they send too much. @@ -16,9 +34,17 @@ * @type {TransactionTypes} */ export const TRANSACTION_TYPES = { - STANDARD: 'standard', CANCEL: 'cancel', RETRY: 'retry', + TOKEN_METHOD_TRANSFER: 'transfer', + TOKEN_METHOD_TRANSFER_FROM: 'transferfrom', + TOKEN_METHOD_APPROVE: 'approve', + INCOMING: 'incoming', + SENT_ETHER: 'sentEther', + CONTRACT_INTERACTION: 'contractInteraction', + DEPLOY_CONTRACT: 'contractDeployment', + SWAP: 'swap', + SWAP_APPROVAL: 'swapApproval', }; /** @@ -53,45 +79,6 @@ export const TRANSACTION_STATUSES = { CONFIRMED: 'confirmed', }; -/** - * @typedef {Object} TransactionCategories - * @property {'transfer'} TOKEN_METHOD_TRANSFER - A token transaction where the user - * is sending tokens that they own to another address - * @property {'transferfrom'} TOKEN_METHOD_TRANSFER_FROM - A token transaction - * transferring tokens from an account that the sender has an allowance of. - * For more information on allowances, see the approve category. - * @property {'approve'} TOKEN_METHOD_APPROVE - A token transaction requesting an - * allowance of the token to spend on behalf of the user - * @property {'incoming'} INCOMING - An incoming (deposit) transaction - * @property {'sentEther'} SENT_ETHER - A transaction sending ether to a recipient - * @property {'contractInteraction'} CONTRACT_INTERACTION - A transaction that is - * interacting with a smart contract's methods that we have not treated as a special - * case, such as approve, transfer, and transferfrom - * @property {'contractDeployment'} DEPLOY_CONTRACT - A transaction that deployed - * a smart contract - * @property {'swap'} SWAP - A transaction swapping one token for another through - * MetaMask Swaps - * @property {'swapApproval'} SWAP_APPROVAL - Similar to the approve category, a swap - * approval is a special case of ERC20 approve method that requests an allowance of - * the token to spend on behalf of the user for the MetaMask Swaps contract. The first - * swap for any token will have an accompanying swapApproval transaction. - */ - -/** - * @type {TransactionCategories} - */ -export const TRANSACTION_CATEGORIES = { - TOKEN_METHOD_TRANSFER: 'transfer', - TOKEN_METHOD_TRANSFER_FROM: 'transferfrom', - TOKEN_METHOD_APPROVE: 'approve', - INCOMING: 'incoming', - SENT_ETHER: 'sentEther', - CONTRACT_INTERACTION: 'contractInteraction', - DEPLOY_CONTRACT: 'contractDeployment', - SWAP: 'swap', - SWAP_APPROVAL: 'swapApproval', -}; - /** * Transaction Group Status is a MetaMask construct to track the status of groups * of transactions. diff --git a/test/data/transaction-data.json b/test/data/transaction-data.json index e5ae1f5b8..37e7659dd 100644 --- a/test/data/transaction-data.json +++ b/test/data/transaction-data.json @@ -15,9 +15,8 @@ "gas": "0x5208", "gasPrice": "0x2540be400" }, - "type": "standard", "origin": "metamask", - "transactionCategory": "sentEther", + "type": "sentEther", "nonceDetails": { "params": { "highestLocallyConfirmed": 12, @@ -76,9 +75,8 @@ "gas": "0x5208", "gasPrice": "0x2540be400" }, - "type": "standard", "origin": "metamask", - "transactionCategory": "sentEther", + "type": "sentEther", "nonceDetails": { "params": { "highestLocallyConfirmed": 12, @@ -142,9 +140,8 @@ "gas": "0x5208", "gasPrice": "0x2540be400" }, - "type": "standard", "origin": "metamask", - "transactionCategory": "sentEther", + "type": "sentEther", "nonceDetails": { "params": { "highestLocallyConfirmed": 0, @@ -203,9 +200,8 @@ "gas": "0x5208", "gasPrice": "0x2540be400" }, - "type": "standard", "origin": "metamask", - "transactionCategory": "sentEther", + "type": "sentEther", "nonceDetails": { "params": { "highestLocallyConfirmed": 0, @@ -269,9 +265,8 @@ "gas": "0x5208", "gasPrice": "0x306dc4200" }, - "type": "standard", "origin": "metamask", - "transactionCategory": "sentEther", + "type": "sentEther", "nonceDetails": { "params": { "highestLocallyConfirmed": 0, @@ -331,9 +326,8 @@ "gas": "0x5208", "gasPrice": "0x306dc4200" }, - "type": "standard", "origin": "metamask", - "transactionCategory": "sentEther", + "type": "sentEther", "nonceDetails": { "params": { "highestLocallyConfirmed": 0, @@ -398,7 +392,7 @@ "value": "0x1043561a882930000" }, "hash": "0x5ca26d1cdcabef1ac2ad5b2b38604c9ced65d143efc7525f848c46f28e0e4116", - "transactionCategory": "incoming" + "type": "incoming" }, "primaryTransaction": { "blockNumber": "6477257", @@ -415,7 +409,7 @@ "value": "0x1043561a882930000" }, "hash": "0x5ca26d1cdcabef1ac2ad5b2b38604c9ced65d143efc7525f848c46f28e0e4116", - "transactionCategory": "incoming" + "type": "incoming" }, "hasRetried": false, "hasCancelled": false @@ -436,7 +430,7 @@ "value": "0x0" }, "hash": "0xa42b2b433e5bd2616b52e30792aedb6a3c374a752a95d43d99e2a8b143937889", - "transactionCategory": "incoming" + "type": "incoming" }, "primaryTransaction": { "blockNumber": "6454493", @@ -453,7 +447,7 @@ "value": "0x0" }, "hash": "0xa42b2b433e5bd2616b52e30792aedb6a3c374a752a95d43d99e2a8b143937889", - "transactionCategory": "incoming" + "type": "incoming" }, "hasRetried": false, "hasCancelled": false @@ -474,7 +468,7 @@ "value": "0xde0b6b3a7640000" }, "hash": "0xbcb195f393f4468945b4045cd41bcdbc2f19ad75ae92a32cf153a3004e42009a", - "transactionCategory": "incoming" + "type": "incoming" }, "primaryTransaction": { "blockNumber": "6195526", @@ -491,7 +485,7 @@ "value": "0xde0b6b3a7640000" }, "hash": "0xbcb195f393f4468945b4045cd41bcdbc2f19ad75ae92a32cf153a3004e42009a", - "transactionCategory": "incoming" + "type": "incoming" }, "hasRetried": false, "hasCancelled": false @@ -514,7 +508,7 @@ "hash": "0xbcb195f393f4468945b4045cd41bcdbc2f19ad75ae92a32cf153a3004e42009a", "destinationTokenSymbol": "ABC", "sourceTokenSymbol": "ETH", - "transactionCategory": "swap" + "type": "swap" }, "primaryTransaction": { "blockNumber": "6195527", @@ -531,7 +525,7 @@ "value": "0xde0b6b3a7640000" }, "hash": "0xbcb195f393f4468945b4045cd41bcdbc2f19ad75ae92a32cf153a3004e42009a", - "transactionCategory": "swap", + "type": "swap", "destinationTokenSymbol": "ABC", "destinationTokenAddress": "0xabca64466f257793eaa52fcfff5066894b76a149", "sourceTokenSymbol": "ETH" diff --git a/test/unit/app/controllers/incoming-transactions.test.js b/test/unit/app/controllers/incoming-transactions.test.js index d476d18cb..af59bdd92 100644 --- a/test/unit/app/controllers/incoming-transactions.test.js +++ b/test/unit/app/controllers/incoming-transactions.test.js @@ -16,7 +16,7 @@ import { ROPSTEN_NETWORK_ID, } from '../../../../shared/constants/network'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network'; @@ -276,7 +276,7 @@ describe('IncomingTransactionsController', function () { chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 16000000000000000, - transactionCategory: TRANSACTION_CATEGORIES.INCOMING, + type: TRANSACTION_TYPES.INCOMING, txParams: { from: '0xfake', gas: '0x0', @@ -620,7 +620,7 @@ describe('IncomingTransactionsController', function () { chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 16000000000000000, - transactionCategory: TRANSACTION_CATEGORIES.INCOMING, + type: TRANSACTION_TYPES.INCOMING, txParams: { from: '0xfake', gas: '0x0', @@ -775,7 +775,7 @@ describe('IncomingTransactionsController', function () { chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 16000000000000000, - transactionCategory: TRANSACTION_CATEGORIES.INCOMING, + type: TRANSACTION_TYPES.INCOMING, txParams: { from: '0xfake', gas: '0x0', @@ -1362,7 +1362,7 @@ describe('IncomingTransactionsController', function () { value: '0xf', }, hash: '0xg', - transactionCategory: TRANSACTION_CATEGORIES.INCOMING, + type: TRANSACTION_TYPES.INCOMING, }); }); @@ -1408,7 +1408,7 @@ describe('IncomingTransactionsController', function () { value: '0xf', }, hash: '0xg', - transactionCategory: TRANSACTION_CATEGORIES.INCOMING, + type: TRANSACTION_TYPES.INCOMING, }); }); }); diff --git a/test/unit/app/controllers/network/stubs.js b/test/unit/app/controllers/network/stubs.js index 421e125a8..4021bcddd 100644 --- a/test/unit/app/controllers/network/stubs.js +++ b/test/unit/app/controllers/network/stubs.js @@ -1,5 +1,4 @@ import { - TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../../../shared/constants/transaction'; @@ -14,7 +13,7 @@ export const txMetaStub = { metamaskNetworkId: '4', status: TRANSACTION_STATUSES.UNAPPROVED, time: 1572395156620, - transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, + type: TRANSACTION_TYPES.SENT_ETHER, txParams: { from: '0xf231d46dd78806e1dd93442cf33c7671f8538748', gas: '0x5208', @@ -22,7 +21,6 @@ export const txMetaStub = { to: '0xf231d46dd78806e1dd93442cf33c7671f8538748', value: '0x0', }, - type: TRANSACTION_TYPES.STANDARD, }, [ { @@ -196,7 +194,7 @@ export const txMetaStub = { status: TRANSACTION_STATUSES.SUBMITTED, submittedTime: 1572395158570, time: 1572395156620, - transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, + type: TRANSACTION_TYPES.SENT_ETHER, txParams: { from: '0xf231d46dd78806e1dd93442cf33c7671f8538748', gas: '0x5208', @@ -205,6 +203,5 @@ export const txMetaStub = { to: '0xf231d46dd78806e1dd93442cf33c7671f8538748', value: '0x0', }, - type: TRANSACTION_TYPES.STANDARD, v: '0x2c', }; diff --git a/test/unit/app/controllers/transactions/tx-controller.test.js b/test/unit/app/controllers/transactions/tx-controller.test.js index 2dacf3c6a..e6119a948 100644 --- a/test/unit/app/controllers/transactions/tx-controller.test.js +++ b/test/unit/app/controllers/transactions/tx-controller.test.js @@ -11,7 +11,6 @@ import { getTestAccounts, } from '../../../../stub/provider'; import { - TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../../../shared/constants/transaction'; @@ -776,76 +775,76 @@ describe('Transaction Controller', function () { }); }); - describe('#_determineTransactionCategory', function () { - it('should return a simple send transactionCategory when to is truthy but data is falsy', async function () { - const result = await txController._determineTransactionCategory({ + describe('#_determineTransactionType', function () { + it('should return a simple send type when to is truthy but data is falsy', async function () { + const result = await txController._determineTransactionType({ to: '0xabc', data: '', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, + type: TRANSACTION_TYPES.SENT_ETHER, getCodeResponse: null, }); }); - it('should return a token transfer transactionCategory when data is for the respective method call', async function () { - const result = await txController._determineTransactionCategory({ + it('should return a token transfer type when data is for the respective method call', async function () { + const result = await txController._determineTransactionType({ to: '0xabc', data: '0xa9059cbb0000000000000000000000002f318C334780961FB129D2a6c30D0763d9a5C970000000000000000000000000000000000000000000000000000000000000000a', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, + type: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, getCodeResponse: undefined, }); }); - it('should return a token approve transactionCategory when data is for the respective method call', async function () { - const result = await txController._determineTransactionCategory({ + it('should return a token approve type when data is for the respective method call', async function () { + const result = await txController._determineTransactionType({ to: '0xabc', data: '0x095ea7b30000000000000000000000002f318C334780961FB129D2a6c30D0763d9a5C9700000000000000000000000000000000000000000000000000000000000000005', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, + type: TRANSACTION_TYPES.TOKEN_METHOD_APPROVE, getCodeResponse: undefined, }); }); - it('should return a contract deployment transactionCategory when to is falsy and there is data', async function () { - const result = await txController._determineTransactionCategory({ + it('should return a contract deployment type when to is falsy and there is data', async function () { + const result = await txController._determineTransactionType({ to: '', data: '0xabd', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.DEPLOY_CONTRACT, + type: TRANSACTION_TYPES.DEPLOY_CONTRACT, getCodeResponse: undefined, }); }); - it('should return a simple send transactionCategory with a 0x getCodeResponse when there is data and but the to address is not a contract address', async function () { - const result = await txController._determineTransactionCategory({ + it('should return a simple send type with a 0x getCodeResponse when there is data and but the to address is not a contract address', async function () { + const result = await txController._determineTransactionType({ to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', data: '0xabd', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, + type: TRANSACTION_TYPES.SENT_ETHER, getCodeResponse: '0x', }); }); - it('should return a simple send transactionCategory with a null getCodeResponse when to is truthy and there is data and but getCode returns an error', async function () { - const result = await txController._determineTransactionCategory({ + it('should return a simple send type with a null getCodeResponse when to is truthy and there is data and but getCode returns an error', async function () { + const result = await txController._determineTransactionType({ to: '0xabc', data: '0xabd', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.SENT_ETHER, + type: TRANSACTION_TYPES.SENT_ETHER, getCodeResponse: null, }); }); - it('should return a contract interaction transactionCategory with the correct getCodeResponse when to is truthy and there is data and it is not a token transaction', async function () { + it('should return a contract interaction type with the correct getCodeResponse when to is truthy and there is data and it is not a token transaction', async function () { const _providerResultStub = { // 1 gwei eth_gasPrice: '0x0de0b6b3a7640000', @@ -875,17 +874,17 @@ describe('Transaction Controller', function () { }), getParticipateInMetrics: () => false, }); - const result = await _txController._determineTransactionCategory({ + const result = await _txController._determineTransactionType({ to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', data: 'abd', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, + type: TRANSACTION_TYPES.CONTRACT_INTERACTION, getCodeResponse: '0x0a', }); }); - it('should return a contract interaction transactionCategory with the correct getCodeResponse when to is a contract address and data is falsy', async function () { + it('should return a contract interaction type with the correct getCodeResponse when to is a contract address and data is falsy', async function () { const _providerResultStub = { // 1 gwei eth_gasPrice: '0x0de0b6b3a7640000', @@ -915,12 +914,12 @@ describe('Transaction Controller', function () { }), getParticipateInMetrics: () => false, }); - const result = await _txController._determineTransactionCategory({ + const result = await _txController._determineTransactionType({ to: '0x9e673399f795D01116e9A8B2dD2F156705131ee9', data: '', }); assert.deepEqual(result, { - transactionCategory: TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, + type: TRANSACTION_TYPES.CONTRACT_INTERACTION, getCodeResponse: '0x0a', }); }); diff --git a/test/unit/migrations/053.test.js b/test/unit/migrations/053.test.js new file mode 100644 index 000000000..92d3055bc --- /dev/null +++ b/test/unit/migrations/053.test.js @@ -0,0 +1,136 @@ +import { strict as assert } from 'assert'; +import migration53 from '../../../app/scripts/migrations/053'; +import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; + +describe('migration #53', function () { + it('should update the version metadata', async function () { + const oldStorage = { + meta: { + version: 52, + }, + data: {}, + }; + + const newStorage = await migration53.migrate(oldStorage); + assert.deepEqual(newStorage.meta, { + version: 53, + }); + }); + + it('should update type of standard transactions', async function () { + const oldStorage = { + meta: {}, + data: { + TransactionController: { + transactions: [ + { + type: TRANSACTION_TYPES.CANCEL, + transactionCategory: TRANSACTION_TYPES.SENT_ETHER, + txParams: { foo: 'bar' }, + }, + { + type: 'standard', + transactionCategory: TRANSACTION_TYPES.SENT_ETHER, + txParams: { foo: 'bar' }, + }, + { + type: 'standard', + transactionCategory: TRANSACTION_TYPES.CONTRACT_INTERACTION, + txParams: { foo: 'bar' }, + }, + { + type: TRANSACTION_TYPES.RETRY, + transactionCategory: TRANSACTION_TYPES.SENT_ETHER, + txParams: { foo: 'bar' }, + }, + ], + }, + IncomingTransactionsController: { + incomingTransactions: { + test: { + transactionCategory: 'incoming', + txParams: { + foo: 'bar', + }, + }, + }, + }, + foo: 'bar', + }, + }; + + const newStorage = await migration53.migrate(oldStorage); + assert.deepEqual(newStorage.data, { + TransactionController: { + transactions: [ + { type: TRANSACTION_TYPES.CANCEL, txParams: { foo: 'bar' } }, + { type: TRANSACTION_TYPES.SENT_ETHER, txParams: { foo: 'bar' } }, + { + type: TRANSACTION_TYPES.CONTRACT_INTERACTION, + txParams: { foo: 'bar' }, + }, + { type: TRANSACTION_TYPES.RETRY, txParams: { foo: 'bar' } }, + ], + }, + IncomingTransactionsController: { + incomingTransactions: { + test: { + type: 'incoming', + txParams: { + foo: 'bar', + }, + }, + }, + }, + foo: 'bar', + }); + }); + + it('should do nothing if transactions state does not exist', async function () { + const oldStorage = { + meta: {}, + data: { + TransactionController: { + bar: 'baz', + }, + IncomingTransactionsController: { + foo: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration53.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); + + it('should do nothing if transactions state is empty', async function () { + const oldStorage = { + meta: {}, + data: { + TransactionController: { + transactions: [], + bar: 'baz', + }, + IncomingTransactionsController: { + incomingTransactions: {}, + baz: 'bar', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration53.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); + + it('should do nothing if state is empty', async function () { + const oldStorage = { + meta: {}, + data: {}, + }; + + const newStorage = await migration53.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); +}); diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js index 1ab3b4818..d8f39cdd7 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js +++ b/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js @@ -6,19 +6,16 @@ import { } from '../../../selectors'; import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util'; import { sumHexes } from '../../../helpers/utils/transactions.util'; -import { TRANSACTION_CATEGORIES } from '../../../../../shared/constants/transaction'; import TransactionBreakdown from './transaction-breakdown.component'; const mapStateToProps = (state, ownProps) => { - const { transaction, transactionCategory } = ownProps; + const { transaction, isTokenApprove } = ownProps; const { txParams: { gas, gasPrice, value } = {}, txReceipt: { gasUsed } = {}, } = transaction; const { showFiatInTestnets } = getPreferences(state); const isMainnet = getIsMainnet(state); - const isTokenApprove = - transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE; const gasLimit = typeof gasUsed === 'string' ? gasUsed : gas; diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index 3c93ff921..c1256d7cb 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -10,6 +10,7 @@ import Tooltip from '../../ui/tooltip'; import Copy from '../../ui/icon/copy-icon.component'; import Popover from '../../ui/popover'; import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils'; +import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction'; export default class TransactionListItemDetails extends PureComponent { static contextTypes = { @@ -156,7 +157,7 @@ export default class TransactionListItemDetails extends PureComponent { } = this.props; const { primaryTransaction: transaction, - initialTransaction: { transactionCategory }, + initialTransaction: { type }, } = transactionGroup; const { hash } = transaction; @@ -255,7 +256,7 @@ export default class TransactionListItemDetails extends PureComponent {
{ }; const tokenTransactionFilter = ({ - initialTransaction: { - transactionCategory, - destinationTokenSymbol, - sourceTokenSymbol, - }, + initialTransaction: { type, destinationTokenSymbol, sourceTokenSymbol }, }) => { - if (TOKEN_CATEGORY_HASH[transactionCategory]) { + if (TOKEN_CATEGORY_HASH[type]) { return false; - } else if (transactionCategory === TRANSACTION_CATEGORIES.SWAP) { + } else if (type === TRANSACTION_TYPES.SWAP) { return destinationTokenSymbol === 'ETH' || sourceTokenSymbol === 'ETH'; } return true; diff --git a/ui/app/ducks/swaps/swaps.js b/ui/app/ducks/swaps/swaps.js index 50dd03bd4..8fbc372f5 100644 --- a/ui/app/ducks/swaps/swaps.js +++ b/ui/app/ducks/swaps/swaps.js @@ -57,7 +57,7 @@ import { SWAP_FAILED_ERROR, SWAPS_FETCH_ORDER_CONFLICT, } from '../../helpers/constants/swaps'; -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; const GAS_PRICES_LOADING_STATES = { INITIAL: 'INITIAL', @@ -671,7 +671,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { updateTransaction( { ...approveTxMeta, - transactionCategory: TRANSACTION_CATEGORIES.SWAP_APPROVAL, + type: TRANSACTION_TYPES.SWAP_APPROVAL, sourceTokenSymbol: sourceTokenInfo.symbol, }, true, @@ -712,7 +712,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { ...tradeTxMeta, sourceTokenSymbol: sourceTokenInfo.symbol, destinationTokenSymbol: destinationTokenInfo.symbol, - transactionCategory: TRANSACTION_CATEGORIES.SWAP, + type: TRANSACTION_TYPES.SWAP, destinationTokenDecimals: destinationTokenInfo.decimals, destinationTokenAddress: destinationTokenInfo.address, swapMetaData, diff --git a/ui/app/helpers/constants/transactions.js b/ui/app/helpers/constants/transactions.js index f349b3ae6..288d497e2 100644 --- a/ui/app/helpers/constants/transactions.js +++ b/ui/app/helpers/constants/transactions.js @@ -1,5 +1,5 @@ import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; @@ -15,7 +15,7 @@ export const PRIORITY_STATUS_HASH = { }; export const TOKEN_CATEGORY_HASH = { - [TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE]: true, - [TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER]: true, - [TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM]: true, + [TRANSACTION_TYPES.TOKEN_METHOD_APPROVE]: true, + [TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER]: true, + [TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM]: true, }; diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index ad2af9162..99ce94fe5 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -5,10 +5,9 @@ import log from 'loglevel'; import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, - TRANSACTION_TYPES, } from '../../../../shared/constants/transaction'; import fetchWithCache from './fetch-with-cache'; @@ -112,15 +111,15 @@ export function getFourBytePrefix(data = '') { /** * Given an transaction category, returns a boolean which indicates whether the transaction is calling an erc20 token method * - * @param {string} transactionCategory - The category of transaction being evaluated + * @param {TRANSACTION_TYPES[keyof TRANSACTION_TYPES]} type - The type of transaction being evaluated * @returns {boolean} whether the transaction is calling an erc20 token method */ -export function isTokenMethodAction(transactionCategory) { +export function isTokenMethodAction(type) { return [ - TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, - TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, - TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM, - ].includes(transactionCategory); + TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, + TRANSACTION_TYPES.TOKEN_METHOD_APPROVE, + TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM, + ].includes(type); } export function getLatestSubmittedTxWithNonce( @@ -197,39 +196,37 @@ export function getStatusKey(transaction) { * * This will throw an error if the transaction category is unrecognized and no default is provided. * @param {function} t - The translation function - * @param {TRANSACTION_CATEGORIES[keyof TRANSACTION_CATEGORIES]} transactionCategory - The transaction category constant + * @param {TRANSACTION_TYPES[keyof TRANSACTION_TYPES]} type - The transaction type constant * @returns {string} The transaction category title */ -export function getTransactionCategoryTitle(t, transactionCategory) { - switch (transactionCategory) { - case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER: { +export function getTransactionTypeTitle(t, type) { + switch (type) { + case TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER: { return t('transfer'); } - case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM: { + case TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM: { return t('transferFrom'); } - case TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE: { + case TRANSACTION_TYPES.TOKEN_METHOD_APPROVE: { return t('approve'); } - case TRANSACTION_CATEGORIES.SENT_ETHER: { + case TRANSACTION_TYPES.SENT_ETHER: { return t('sentEther'); } - case TRANSACTION_CATEGORIES.CONTRACT_INTERACTION: { + case TRANSACTION_TYPES.CONTRACT_INTERACTION: { return t('contractInteraction'); } - case TRANSACTION_CATEGORIES.DEPLOY_CONTRACT: { + case TRANSACTION_TYPES.DEPLOY_CONTRACT: { return t('contractDeployment'); } - case TRANSACTION_CATEGORIES.SWAP: { + case TRANSACTION_TYPES.SWAP: { return t('swap'); } - case TRANSACTION_CATEGORIES.SWAP_APPROVAL: { + case TRANSACTION_TYPES.SWAP_APPROVAL: { return t('swapApproval'); } default: { - throw new Error( - `Unrecognized transaction category: ${transactionCategory}`, - ); + throw new Error(`Unrecognized transaction type: ${type}`); } } } diff --git a/ui/app/helpers/utils/transactions.util.test.js b/ui/app/helpers/utils/transactions.util.test.js index 386edd6f8..9bd410cdb 100644 --- a/ui/app/helpers/utils/transactions.util.test.js +++ b/ui/app/helpers/utils/transactions.util.test.js @@ -1,6 +1,6 @@ import assert from 'assert'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; @@ -14,7 +14,7 @@ describe('Transactions utils', function () { ); assert.ok(tokenData); const { name, args } = tokenData; - assert.strictEqual(name, TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER); + assert.strictEqual(name, TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER); const to = args._to; const value = args._value.toString(); assert.strictEqual(to, '0x50A9D56C2B8BA9A5c7f2C08C3d26E0499F23a706'); diff --git a/ui/app/hooks/tests/useTokenData.test.js b/ui/app/hooks/tests/useTokenData.test.js index 593176105..24fbed5af 100644 --- a/ui/app/hooks/tests/useTokenData.test.js +++ b/ui/app/hooks/tests/useTokenData.test.js @@ -2,14 +2,14 @@ import assert from 'assert'; import { ethers } from 'ethers'; import { renderHook } from '@testing-library/react-hooks'; import { useTokenData } from '../useTokenData'; -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; const tests = [ { data: '0xa9059cbb000000000000000000000000ffe5bc4e8f1f969934d773fa67da095d2e491a970000000000000000000000000000000000000000000000000000000000003a98', tokenData: { - name: TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, + name: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, args: [ '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', ethers.BigNumber.from(15000), @@ -20,7 +20,7 @@ const tests = [ data: '0xa9059cbb000000000000000000000000ffe5bc4e8f1f969934d773fa67da095d2e491a9700000000000000000000000000000000000000000000000000000000000061a8', tokenData: { - name: TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, + name: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, args: [ '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', ethers.BigNumber.from(25000), @@ -31,7 +31,7 @@ const tests = [ data: '0xa9059cbb000000000000000000000000ffe5bc4e8f1f969934d773fa67da095d2e491a970000000000000000000000000000000000000000000000000000000000002710', tokenData: { - name: TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, + name: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, args: [ '0xffe5bc4e8f1f969934d773fa67da095d2e491a97', ethers.BigNumber.from(10000), diff --git a/ui/app/hooks/tests/useTransactionDisplayData.test.js b/ui/app/hooks/tests/useTransactionDisplayData.test.js index 96a24c08b..13079628e 100644 --- a/ui/app/hooks/tests/useTransactionDisplayData.test.js +++ b/ui/app/hooks/tests/useTransactionDisplayData.test.js @@ -19,7 +19,7 @@ import { getMessage } from '../../helpers/utils/i18n-helper'; import messages from '../../../../app/_locales/en/messages.json'; import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../helpers/constants/routes'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; @@ -106,7 +106,7 @@ const expectedResults = [ }, { title: 'Swap ETH to ABC', - category: TRANSACTION_CATEGORIES.SWAP, + category: TRANSACTION_TYPES.SWAP, subtitle: '', subtitleContainsOrigin: false, date: 'May 12, 2020', diff --git a/ui/app/hooks/useSwappedTokenValue.js b/ui/app/hooks/useSwappedTokenValue.js index f48e3de69..64d51fe8a 100644 --- a/ui/app/hooks/useSwappedTokenValue.js +++ b/ui/app/hooks/useSwappedTokenValue.js @@ -1,4 +1,4 @@ -import { TRANSACTION_CATEGORIES } from '../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; import { ETH_SWAPS_TOKEN_OBJECT } from '../helpers/constants/swaps'; import { getSwapsTokensReceivedFromTxMeta } from '../pages/swaps/swaps.util'; import { useTokenFiatAmount } from './useTokenFiatAmount'; @@ -25,7 +25,7 @@ import { useTokenFiatAmount } from './useTokenFiatAmount'; export function useSwappedTokenValue(transactionGroup, currentAsset) { const { symbol, decimals, address } = currentAsset; const { primaryTransaction, initialTransaction } = transactionGroup; - const { transactionCategory } = initialTransaction; + const { type } = initialTransaction; const { from: senderAddress } = initialTransaction.txParams || {}; const isViewingReceivedTokenFromSwap = @@ -34,8 +34,7 @@ export function useSwappedTokenValue(transactionGroup, currentAsset) { primaryTransaction.destinationTokenSymbol === 'ETH'); const swapTokenValue = - transactionCategory === TRANSACTION_CATEGORIES.SWAP && - isViewingReceivedTokenFromSwap + type === TRANSACTION_TYPES.SWAP && isViewingReceivedTokenFromSwap ? getSwapsTokensReceivedFromTxMeta( primaryTransaction.destinationTokenSymbol, initialTransaction, @@ -43,8 +42,7 @@ export function useSwappedTokenValue(transactionGroup, currentAsset) { senderAddress, decimals, ) - : transactionCategory === TRANSACTION_CATEGORIES.SWAP && - primaryTransaction.swapTokenValue; + : type === TRANSACTION_TYPES.SWAP && primaryTransaction.swapTokenValue; const isNegative = typeof swapTokenValue === 'string' diff --git a/ui/app/hooks/useTransactionDisplayData.js b/ui/app/hooks/useTransactionDisplayData.js index 18b0e7c39..370516170 100644 --- a/ui/app/hooks/useTransactionDisplayData.js +++ b/ui/app/hooks/useTransactionDisplayData.js @@ -2,7 +2,7 @@ import { useSelector } from 'react-redux'; import { getKnownMethodData } from '../selectors/selectors'; import { getStatusKey, - getTransactionCategoryTitle, + getTransactionTypeTitle, } from '../helpers/utils/transactions.util'; import { camelCaseToCapitalize } from '../helpers/utils/common.util'; import { PRIMARY, SECONDARY } from '../helpers/constants/common'; @@ -18,7 +18,7 @@ import { } from '../helpers/constants/transactions'; import { getTokens } from '../ducks/metamask/metamask'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, } from '../../../shared/constants/transaction'; @@ -62,7 +62,7 @@ export function useTransactionDisplayData(transactionGroup) { const t = useI18nContext(); const { initialTransaction, primaryTransaction } = transactionGroup; // initialTransaction contains the data we need to derive the primary purpose of this transaction group - const { transactionCategory } = initialTransaction; + const { type } = initialTransaction; const { from: senderAddress, to } = initialTransaction.txParams || {}; @@ -85,7 +85,7 @@ export function useTransactionDisplayData(transactionGroup) { // This value is used to determine whether we should look inside txParams.data // to pull out and render token related information - const isTokenCategory = TOKEN_CATEGORY_HASH[transactionCategory]; + const isTokenCategory = TOKEN_CATEGORY_HASH[type]; // these values are always instantiated because they are either // used by or returned from hooks. Hooks must be called at the top level, @@ -145,12 +145,12 @@ export function useTransactionDisplayData(transactionGroup) { // 6. Swap // 7. Swap Approval - if (transactionCategory === null || transactionCategory === undefined) { + if (type === null || type === undefined) { category = TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST; title = t('signatureRequest'); subtitle = origin; subtitleContainsOrigin = true; - } else if (transactionCategory === TRANSACTION_CATEGORIES.SWAP) { + } else if (type === TRANSACTION_TYPES.SWAP) { category = TRANSACTION_GROUP_CATEGORIES.SWAP; title = t('swapTokenToToken', [ initialTransaction.sourceTokenSymbol, @@ -170,48 +170,43 @@ export function useTransactionDisplayData(transactionGroup) { } else { prefix = '-'; } - } else if (transactionCategory === TRANSACTION_CATEGORIES.SWAP_APPROVAL) { + } else if (type === TRANSACTION_TYPES.SWAP_APPROVAL) { category = TRANSACTION_GROUP_CATEGORIES.APPROVAL; title = t('swapApproval', [primaryTransaction.sourceTokenSymbol]); subtitle = origin; subtitleContainsOrigin = true; primarySuffix = primaryTransaction.sourceTokenSymbol; - } else if ( - transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE - ) { + } else if (type === TRANSACTION_TYPES.TOKEN_METHOD_APPROVE) { category = TRANSACTION_GROUP_CATEGORIES.APPROVAL; prefix = ''; title = t('approveSpendLimit', [token?.symbol || t('token')]); subtitle = origin; subtitleContainsOrigin = true; } else if ( - transactionCategory === TRANSACTION_CATEGORIES.DEPLOY_CONTRACT || - transactionCategory === TRANSACTION_CATEGORIES.CONTRACT_INTERACTION + type === TRANSACTION_TYPES.DEPLOY_CONTRACT || + type === TRANSACTION_TYPES.CONTRACT_INTERACTION ) { category = TRANSACTION_GROUP_CATEGORIES.INTERACTION; - const transactionCategoryTitle = getTransactionCategoryTitle( - t, - transactionCategory, - ); + const transactionTypeTitle = getTransactionTypeTitle(t, type); title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || - transactionCategoryTitle; + transactionTypeTitle; subtitle = origin; subtitleContainsOrigin = true; - } else if (transactionCategory === TRANSACTION_CATEGORIES.INCOMING) { + } else if (type === TRANSACTION_TYPES.INCOMING) { category = TRANSACTION_GROUP_CATEGORIES.RECEIVE; title = t('receive'); prefix = ''; subtitle = t('fromAddress', [shortenAddress(senderAddress)]); } else if ( - transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM || - transactionCategory === TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER + type === TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM || + type === TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER ) { category = TRANSACTION_GROUP_CATEGORIES.SEND; title = t('sendSpecifiedTokens', [token?.symbol || t('token')]); recipientAddress = getTokenAddressParam(tokenData); subtitle = t('toAddress', [shortenAddress(recipientAddress)]); - } else if (transactionCategory === TRANSACTION_CATEGORIES.SENT_ETHER) { + } else if (type === TRANSACTION_TYPES.SENT_ETHER) { category = TRANSACTION_GROUP_CATEGORIES.SEND; title = t('sendETH'); subtitle = t('toAddress', [shortenAddress(recipientAddress)]); @@ -241,15 +236,12 @@ export function useTransactionDisplayData(transactionGroup) { subtitle, subtitleContainsOrigin, primaryCurrency: - transactionCategory === TRANSACTION_CATEGORIES.SWAP && isPending - ? '' - : primaryCurrency, + type === TRANSACTION_TYPES.SWAP && isPending ? '' : primaryCurrency, senderAddress, recipientAddress, secondaryCurrency: (isTokenCategory && !tokenFiatAmount) || - (transactionCategory === TRANSACTION_CATEGORIES.SWAP && - !swapTokenFiatAmount) + (type === TRANSACTION_TYPES.SWAP && !swapTokenFiatAmount) ? undefined : secondaryCurrency, displayedStatusKey, diff --git a/ui/app/pages/confirm-approve/confirm-approve.util.js b/ui/app/pages/confirm-approve/confirm-approve.util.js index e724ba58e..3345b0966 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.util.js +++ b/ui/app/pages/confirm-approve/confirm-approve.util.js @@ -1,4 +1,4 @@ -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; import { decimalToHex } from '../../helpers/utils/conversions.util'; import { calcTokenValue, @@ -14,7 +14,7 @@ export function getCustomTxParamsData( if (!tokenData) { throw new Error('Invalid data'); - } else if (tokenData.name !== TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE) { + } else if (tokenData.name !== TRANSACTION_TYPES.TOKEN_METHOD_APPROVE) { throw new Error( `Invalid data; should be 'approve' method, but instead is '${tokenData.name}'`, ); diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index d1b702df9..65af5c890 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -19,10 +19,10 @@ import { hexToDecimal } from '../../helpers/utils/conversions.util'; import AdvancedGasInputs from '../../components/app/gas-customization/advanced-gas-inputs'; import TextField from '../../components/ui/text-field'; import { - TRANSACTION_CATEGORIES, + TRANSACTION_TYPES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; -import { getTransactionCategoryTitle } from '../../helpers/utils/transactions.util'; +import { getTransactionTypeTitle } from '../../helpers/utils/transactions.util'; export default class ConfirmTransactionBase extends Component { static contextTypes = { @@ -87,7 +87,7 @@ export default class ConfirmTransactionBase extends Component { advancedInlineGasShown: PropTypes.bool, insufficientBalance: PropTypes.bool, hideFiatConversion: PropTypes.bool, - transactionCategory: PropTypes.string, + type: PropTypes.string, getNextNonce: PropTypes.func, nextNonce: PropTypes.number, tryReverseResolveAddress: PropTypes.func.isRequired, @@ -218,7 +218,7 @@ export default class ConfirmTransactionBase extends Component { functionType: actionKey || getMethodName(methodData.name) || - TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, + TRANSACTION_TYPES.CONTRACT_INTERACTION, origin, }, }); @@ -395,7 +395,7 @@ export default class ConfirmTransactionBase extends Component { functionType: actionKey || getMethodName(methodData.name) || - TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, + TRANSACTION_TYPES.CONTRACT_INTERACTION, origin, }, }); @@ -450,7 +450,7 @@ export default class ConfirmTransactionBase extends Component { functionType: actionKey || getMethodName(methodData.name) || - TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, + TRANSACTION_TYPES.CONTRACT_INTERACTION, origin, }, }); @@ -500,7 +500,7 @@ export default class ConfirmTransactionBase extends Component { functionType: actionKey || getMethodName(methodData.name) || - TRANSACTION_CATEGORIES.CONTRACT_INTERACTION, + TRANSACTION_TYPES.CONTRACT_INTERACTION, origin, }, }); @@ -667,7 +667,7 @@ export default class ConfirmTransactionBase extends Component { customNonceValue, assetImage, unapprovedTxCount, - transactionCategory, + type, hideSenderToRecipient, showAccountInHeader, txData, @@ -690,8 +690,8 @@ export default class ConfirmTransactionBase extends Component { let functionType = getMethodName(name); if (!functionType) { - if (transactionCategory) { - functionType = getTransactionCategoryTitle(t, transactionCategory); + if (type) { + functionType = getTransactionTypeTitle(t, type); } else { functionType = t('contractInteraction'); } diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 69c8fa0d9..cb5332a22 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -81,12 +81,7 @@ const mapStateToProps = (state, ownProps) => { provider: { chainId }, } = metamask; const { tokenData, txData, tokenProps, nonce } = confirmTransaction; - const { - txParams = {}, - lastGasPrice, - id: transactionId, - transactionCategory, - } = txData; + const { txParams = {}, lastGasPrice, id: transactionId, type } = txData; const transaction = Object.values(unapprovedTxs).find( ({ id }) => id === (transactionId || Number(paramsTransactionId)), @@ -189,7 +184,7 @@ const mapStateToProps = (state, ownProps) => { hideSubtitle: !isMainnet && !showFiatInTestnets, hideFiatConversion: !isMainnet && !showFiatInTestnets, metaMetricsSendCount, - transactionCategory, + type, nextNonce, mostRecentOverviewPage: getMostRecentOverviewPage(state), isMainnet, diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js index 18969e233..83aa7cdbc 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js +++ b/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js @@ -15,7 +15,7 @@ import { ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, } from '../../helpers/constants/routes'; import { MESSAGE_TYPE } from '../../../../shared/constants/app'; -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; export default class ConfirmTransactionSwitch extends Component { static propTypes = { @@ -24,29 +24,29 @@ export default class ConfirmTransactionSwitch extends Component { redirectToTransaction() { const { txData } = this.props; - const { id, txParams: { data } = {}, transactionCategory } = txData; + const { id, txParams: { data } = {}, type } = txData; - if (transactionCategory === TRANSACTION_CATEGORIES.DEPLOY_CONTRACT) { + if (type === TRANSACTION_TYPES.DEPLOY_CONTRACT) { const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_DEPLOY_CONTRACT_PATH}`; return ; } - if (transactionCategory === TRANSACTION_CATEGORIES.SENT_ETHER) { + if (type === TRANSACTION_TYPES.SENT_ETHER) { const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_ETHER_PATH}`; return ; } if (data) { - switch (transactionCategory) { - case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER: { + switch (type) { + case TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER: { const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_SEND_TOKEN_PATH}`; return ; } - case TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE: { + case TRANSACTION_TYPES.TOKEN_METHOD_APPROVE: { const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_APPROVE_PATH}`; return ; } - case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM: { + case TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM: { const pathname = `${CONFIRM_TRANSACTION_ROUTE}/${id}${CONFIRM_TRANSFER_FROM_PATH}`; return ; } diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/app/pages/confirm-transaction/confirm-transaction.container.js index d07665256..68ee7c3ed 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/app/pages/confirm-transaction/confirm-transaction.container.js @@ -27,7 +27,7 @@ const mapStateToProps = (state, ownProps) => { const transaction = totalUnconfirmed ? unapprovedTxs[id] || unconfirmedTransactions[0] : {}; - const { id: transactionId, transactionCategory } = transaction; + const { id: transactionId, type } = transaction; return { totalUnapprovedCount: totalUnconfirmed, @@ -38,7 +38,7 @@ const mapStateToProps = (state, ownProps) => { paramsTransactionId: id && String(id), transactionId: transactionId && String(transactionId), transaction, - isTokenMethodAction: isTokenMethodAction(transactionCategory), + isTokenMethodAction: isTokenMethodAction(type), }; }; diff --git a/ui/app/selectors/tests/confirm-transaction.test.js b/ui/app/selectors/tests/confirm-transaction.test.js index 8f36689cb..647318a9d 100644 --- a/ui/app/selectors/tests/confirm-transaction.test.js +++ b/ui/app/selectors/tests/confirm-transaction.test.js @@ -4,7 +4,7 @@ import { KOVAN_NETWORK_ID, MAINNET_CHAIN_ID, } from '../../../../shared/constants/network'; -import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; import { unconfirmedTransactionsCountSelector, sendTokenTokenAmountAndToAddressSelector, @@ -52,7 +52,7 @@ describe('Confirm Transaction Selector', function () { const state = { confirmTransaction: { tokenData: { - name: TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER, + name: TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER, args: getEthersArrayLikeFromObj({ _to: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', _value: { toString: () => '1' }, diff --git a/ui/app/selectors/transactions.js b/ui/app/selectors/transactions.js index 3fdcbfe41..dd418c655 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/app/selectors/transactions.js @@ -6,7 +6,6 @@ import { import { hexToDecimal } from '../helpers/utils/conversions.util'; import txHelper from '../../lib/tx-helper'; import { - TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../shared/constants/transaction'; @@ -229,13 +228,9 @@ export const nonceSortedTransactionsSelector = createSelector( status, type, time: txTime, - transactionCategory, } = transaction; - if ( - typeof nonce === 'undefined' || - transactionCategory === TRANSACTION_CATEGORIES.INCOMING - ) { + if (typeof nonce === 'undefined' || type === TRANSACTION_TYPES.INCOMING) { const transactionGroup = { transactions: [transaction], initialTransaction: transaction, @@ -244,7 +239,7 @@ export const nonceSortedTransactionsSelector = createSelector( hasCancelled: false, }; - if (transactionCategory === TRANSACTION_CATEGORIES.INCOMING) { + if (type === TRANSACTION_TYPES.INCOMING) { incomingTransactionGroups.push(transactionGroup); } else { insertTransactionGroupByTime(