diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js index 74d0e3d7c2b..be4b8d457fb 100644 --- a/app/components/Nav/Main/index.js +++ b/app/components/Nav/Main/index.js @@ -23,7 +23,7 @@ import I18n, { strings } from '../../../../locales/i18n'; import { colors } from '../../../styles/common'; import LockManager from '../../../core/LockManager'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; -import { hexToBN, fromWei, renderFromTokenMinimalUnit } from '../../../util/number'; +import { hexToBN, fromWei } from '../../../util/number'; import { setEtherTransaction, setTransactionObject } from '../../../actions/transaction'; import PersonalSign from '../../UI/PersonalSign'; import TypedSign from '../../UI/TypedSign'; @@ -33,9 +33,12 @@ import Device from '../../../util/device'; import { getMethodData, TOKEN_METHOD_TRANSFER, - decodeTransferData, APPROVE_FUNCTION_SIGNATURE, decodeApproveData, + getTokenValueParam, + getTokenAddressParam, + calcTokenAmount, + getTokenValueParamAsHex, } from '../../../util/transactions'; import { BN } from 'ethereumjs-util'; import Logger from '../../../util/Logger'; @@ -66,6 +69,10 @@ import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics'; import BigNumber from 'bignumber.js'; import { setInfuraAvailabilityBlocked, setInfuraAvailabilityNotBlocked } from '../../../actions/infuraAvailability'; import { toLowerCaseEquals } from '../../../util/general'; +import { ethers } from 'ethers'; +import abi from 'human-standard-token-abi'; + +const hstInterface = new ethers.utils.Interface(abi); const styles = StyleSheet.create({ flex: { @@ -362,13 +369,14 @@ const Main = (props) => { } } - const decodedData = decodeTransferData('transfer', data); - transactionMeta.transaction.value = hexToBN(decodedData[2]); - transactionMeta.transaction.readableValue = renderFromTokenMinimalUnit( - hexToBN(decodedData[2]), - asset.decimals - ); - transactionMeta.transaction.to = decodedData[0]; + const tokenData = hstInterface.parseTransaction({ data }); + const tokenValue = getTokenValueParam(tokenData); + const toAddress = getTokenAddressParam(tokenData); + const tokenAmount = tokenData && calcTokenAmount(tokenValue, asset.decimals).toFixed(); + + transactionMeta.transaction.value = hexToBN(getTokenValueParamAsHex(tokenData)); + transactionMeta.transaction.readableValue = tokenAmount; + transactionMeta.transaction.to = toAddress; setTransactionObject({ type: 'INDIVIDUAL_TOKEN_TRANSACTION', diff --git a/app/components/UI/AccountApproval/index.test.tsx b/app/components/UI/AccountApproval/index.test.tsx index 46d5109dc61..af6cd629816 100644 --- a/app/components/UI/AccountApproval/index.test.tsx +++ b/app/components/UI/AccountApproval/index.test.tsx @@ -10,22 +10,22 @@ const initialState = { engine: { backgroundState: { AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, NetworkController: { provider: { - type: ROPSTEN - } + type: ROPSTEN, + }, }, TokensController: { - tokens: [] + tokens: [], }, PreferencesController: { selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', - identities: { '0xe7E125654064EEa56229f273dA586F10DF96B0a1': { name: 'Account 1' } } - } - } - } + identities: { '0xe7E125654064EEa56229f273dA586F10DF96B0a1': { name: 'Account 1' } }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/AccountInfoCard/index.test.tsx b/app/components/UI/AccountInfoCard/index.test.tsx index afc8bead259..83fe1e2dda5 100644 --- a/app/components/UI/AccountInfoCard/index.test.tsx +++ b/app/components/UI/AccountInfoCard/index.test.tsx @@ -11,28 +11,28 @@ const initialState = { AccountTrackerController: { accounts: { '0x0': { - balance: 200 - } - } + balance: 200, + }, + }, }, PreferencesController: { selectedAddress: '0x0', identities: { address: '0x0', - name: 'Account 1' - } + name: 'Account 1', + }, }, CurrencyRateController: { conversionRate: 10, - currentCurrency: 'inr' + currentCurrency: 'inr', }, NetworkController: { provider: { - ticker: 'eth' - } - } - } - } + ticker: 'eth', + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/AccountList/index.test.tsx b/app/components/UI/AccountList/index.test.tsx index c0f8067a318..97a3b88c04d 100644 --- a/app/components/UI/AccountList/index.test.tsx +++ b/app/components/UI/AccountList/index.test.tsx @@ -11,11 +11,11 @@ const store = mockStore({ backgroundState: { AccountTrackerController: { accounts: { - [address]: { name: 'account 1', address, balance: 0 } - } - } - } - } + [address]: { name: 'account 1', address, balance: 0 }, + }, + }, + }, + }, }); describe('Accounts', () => { diff --git a/app/components/UI/AccountRightButton/index.test.tsx b/app/components/UI/AccountRightButton/index.test.tsx index e298150f154..56e3adb20f3 100644 --- a/app/components/UI/AccountRightButton/index.test.tsx +++ b/app/components/UI/AccountRightButton/index.test.tsx @@ -9,10 +9,10 @@ const store = mockStore({ engine: { backgroundState: { PreferencesController: { - selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1' - } - } - } + selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', + }, + }, + }, }); describe('AccountRightButton', () => { diff --git a/app/components/UI/ApproveTransactionReview/index.test.tsx b/app/components/UI/ApproveTransactionReview/index.test.tsx index a99d2283bc9..fb542938985 100644 --- a/app/components/UI/ApproveTransactionReview/index.test.tsx +++ b/app/components/UI/ApproveTransactionReview/index.test.tsx @@ -9,30 +9,30 @@ const initialState = { engine: { backgroundState: { AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, CurrencyRateController: { - conversionRate: 5 + conversionRate: 5, }, NetworkController: { provider: { ticker: 'ETH', - type: 'ETH' - } + type: 'ETH', + }, }, TokensController: { - tokens: [] - } - } + tokens: [], + }, + }, }, transaction: {}, settings: { - primaryCurrency: 'fiat' + primaryCurrency: 'fiat', }, browser: { activeTab: 1605778647042, - tabs: [{ id: 1605778647042, url: 'https://metamask.github.io/test-dapp/' }] - } + tabs: [{ id: 1605778647042, url: 'https://metamask.github.io/test-dapp/' }], + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/CollectibleContractOverview/index.test.tsx b/app/components/UI/CollectibleContractOverview/index.test.tsx index 5c2d12ea9dc..c2fdb0761ed 100644 --- a/app/components/UI/CollectibleContractOverview/index.test.tsx +++ b/app/components/UI/CollectibleContractOverview/index.test.tsx @@ -9,10 +9,10 @@ const initialState = { engine: { backgroundState: { CollectiblesController: { - collectibles: [] - } - } - } + collectibles: [], + }, + }, + }, }; const store = mockStore(initialState); @@ -26,7 +26,7 @@ describe('CollectibleContractOverview', () => { symbol: 'symbol', description: 'description', address: '0x123', - totalSupply: 1 + totalSupply: 1, }} /> diff --git a/app/components/UI/CollectibleContracts/index.test.tsx b/app/components/UI/CollectibleContracts/index.test.tsx index 68cb77fe807..cec00538e4b 100644 --- a/app/components/UI/CollectibleContracts/index.test.tsx +++ b/app/components/UI/CollectibleContracts/index.test.tsx @@ -7,17 +7,17 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { collectibles: { - favorites: {} + favorites: {}, }, engine: { backgroundState: { NetworkController: { provider: { - chainId: 1 - } + chainId: 1, + }, }, PreferencesController: { - selectedAddress: '0x1' + selectedAddress: '0x1', }, CollectiblesController: { collectibleContracts: [ @@ -27,20 +27,20 @@ const initialState = { address: '0x0', symbol: 'NM', description: 'description', - totalSupply: 10 - } + totalSupply: 10, + }, ], collectibles: [ { address: '0x0', tokenId: 10, name: 'name', - image: 'image' - } - ] - } - } - } + image: 'image', + }, + ], + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/CollectibleModal/index.test.tsx b/app/components/UI/CollectibleModal/index.test.tsx index f606645ec45..ff83fd5d11b 100644 --- a/app/components/UI/CollectibleModal/index.test.tsx +++ b/app/components/UI/CollectibleModal/index.test.tsx @@ -17,8 +17,8 @@ describe('CollectibleModal', () => { route={{ params: { contractName: 'Opensea', - collectible: { name: 'Leopard', tokenId: 6904, address: '0x123' } - } + collectible: { name: 'Leopard', tokenId: 6904, address: '0x123' }, + }, }} /> diff --git a/app/components/UI/CollectibleOverview/index.test.tsx b/app/components/UI/CollectibleOverview/index.test.tsx index ed3c3f50125..69bceb0c19f 100644 --- a/app/components/UI/CollectibleOverview/index.test.tsx +++ b/app/components/UI/CollectibleOverview/index.test.tsx @@ -7,20 +7,20 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { collectibles: { - favorites: {} + favorites: {}, }, engine: { backgroundState: { NetworkController: { provider: { - chainId: 1 - } + chainId: 1, + }, }, PreferencesController: { - selectedAddress: '0x1' - } - } - } + selectedAddress: '0x1', + }, + }, + }, }; const store = mockStore(initialState); @@ -34,7 +34,7 @@ describe('CollectibleOverview', () => { tokenId: 6904, address: '0x06012c8cf97BEaD5deAe237070F9587f8E7A266d', externalLink: 'https://nft.example.com', - tradable: true + tradable: true, }} /> diff --git a/app/components/UI/NetworkList/index.test.tsx b/app/components/UI/NetworkList/index.test.tsx index add87d39512..0a29f9e03e7 100644 --- a/app/components/UI/NetworkList/index.test.tsx +++ b/app/components/UI/NetworkList/index.test.tsx @@ -7,16 +7,16 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { privacy: { - approvedHosts: {} + approvedHosts: {}, }, engine: { backgroundState: { NetworkController: { - provider: { type: 'mainnet', rpcTarget: 'http://10.0.2.2:8545' } + provider: { type: 'mainnet', rpcTarget: 'http://10.0.2.2:8545' }, }, - PreferencesController: { frequentRpcList: ['http://10.0.2.2:8545'] } - } - } + PreferencesController: { frequentRpcList: ['http://10.0.2.2:8545'] }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/OnboardingWizard/Step3/index.test.tsx b/app/components/UI/OnboardingWizard/Step3/index.test.tsx index ffcf9d588b0..824d2f48bdf 100644 --- a/app/components/UI/OnboardingWizard/Step3/index.test.tsx +++ b/app/components/UI/OnboardingWizard/Step3/index.test.tsx @@ -10,22 +10,22 @@ const initialState = { backgroundState: { PreferencesController: { selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', - identities: { '0xe7E125654064EEa56229f273dA586F10DF96B0a1': { name: 'Account 1' } } + identities: { '0xe7E125654064EEa56229f273dA586F10DF96B0a1': { name: 'Account 1' } }, }, AccountTrackerController: { accounts: { '0xe7E125654064EEa56229f273dA586F10DF96B0a1': { name: 'account 1', address: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', - balance: 0 - } - } + balance: 0, + }, + }, }, CurrencyRateController: { - currentCurrecy: 'USD' - } - } - } + currentCurrecy: 'USD', + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/OptinMetrics/index.test.tsx b/app/components/UI/OptinMetrics/index.test.tsx index f6faa22addc..fb61563e327 100644 --- a/app/components/UI/OptinMetrics/index.test.tsx +++ b/app/components/UI/OptinMetrics/index.test.tsx @@ -7,8 +7,8 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { onboarding: { - event: 'event' - } + event: 'event', + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/ReceiveRequest/index.test.tsx b/app/components/UI/ReceiveRequest/index.test.tsx index 58dcbca864a..379ed754856 100644 --- a/app/components/UI/ReceiveRequest/index.test.tsx +++ b/app/components/UI/ReceiveRequest/index.test.tsx @@ -9,15 +9,15 @@ const initialState = { engine: { backgroundState: { PreferencesController: { selectedAddress: '0x' }, - NetworkController: { network: '1' } - } + NetworkController: { network: '1' }, + }, }, modals: { - receiveAsset: {} + receiveAsset: {}, }, user: { - seedphraseBackedUp: true - } + seedphraseBackedUp: true, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/SignatureRequest/index.test.tsx b/app/components/UI/SignatureRequest/index.test.tsx index 3618cd0a6c4..6b7490b78e4 100644 --- a/app/components/UI/SignatureRequest/index.test.tsx +++ b/app/components/UI/SignatureRequest/index.test.tsx @@ -10,19 +10,19 @@ const initialState = { engine: { backgroundState: { AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, PreferencesController: { selectedAddress: '0x2', - identities: { '0x2': { address: '0x2', name: 'Account 1' } } + identities: { '0x2': { address: '0x2', name: 'Account 1' } }, }, NetworkController: { provider: { - type: ROPSTEN - } - } - } - } + type: ROPSTEN, + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TokenImage/index.test.tsx b/app/components/UI/TokenImage/index.test.tsx index b7d42004973..2f0bde6ffa9 100644 --- a/app/components/UI/TokenImage/index.test.tsx +++ b/app/components/UI/TokenImage/index.test.tsx @@ -9,13 +9,13 @@ const initialState = { engine: { backgroundState: { SwapsController: { - tokens: [] - } - } + tokens: [], + }, + }, }, settings: { - primaryCurrency: 'usd' - } + primaryCurrency: 'usd', + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionEditor/index.test.tsx b/app/components/UI/TransactionEditor/index.test.tsx index b9839c24de2..599e09beb34 100644 --- a/app/components/UI/TransactionEditor/index.test.tsx +++ b/app/components/UI/TransactionEditor/index.test.tsx @@ -10,38 +10,38 @@ const initialState = { engine: { backgroundState: { AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, CurrencyRateController: { - conversionRate: 621.92 + conversionRate: 621.92, }, TokenBalancesController: { - contractBalances: { '0x2': new BN(0) } + contractBalances: { '0x2': new BN(0) }, }, PreferencesController: { - selectedAddress: '0x0' + selectedAddress: '0x0', }, TokensController: { - tokens: [] + tokens: [], }, CollectiblesController: { - collectibles: [] + collectibles: [], }, NetworkController: { provider: { type: 'mainnet', - chainId: '1' - } + chainId: '1', + }, }, GasFeeController: { - gasEstimates: {} - } - } + gasEstimates: {}, + }, + }, }, transaction: { value: 0, data: '0x0', gas: 0, gasPrice: 1, from: '0x0', to: '0x1' }, settings: { - primaryCurrency: 'fiat' - } + primaryCurrency: 'fiat', + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx b/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx index 7a0c38259af..0aea02e644c 100644 --- a/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx +++ b/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx @@ -11,19 +11,19 @@ const initialState = { backgroundState: { CurrencyRateController: { conversionRate: 2, - currentCurrency: 'USD' + currentCurrency: 'USD', }, PreferencesController: { - frequentRpcList: [] + frequentRpcList: [], }, NetworkController: { provider: { rpcTarget: '', - type: RPC - } - } - } - } + type: RPC, + }, + }, + }, + }, }; const store = mockStore(initialState); @@ -36,8 +36,8 @@ describe('TransactionDetails', () => { networkID: '1', status: 'confirmed', transaction: { - nonce: '' - } + nonce: '', + }, }} transactionDetails={{ renderFrom: '0x0', @@ -47,7 +47,7 @@ describe('TransactionDetails', () => { renderGas: '21000', renderGasPrice: '2', renderTotalValue: '2 TKN / 0.001 ETH', - renderTotalValueFiat: '' + renderTotalValueFiat: '', }} /> diff --git a/app/components/UI/TransactionElement/index.test.tsx b/app/components/UI/TransactionElement/index.test.tsx index ef9b9fcb9bd..342760be812 100644 --- a/app/components/UI/TransactionElement/index.test.tsx +++ b/app/components/UI/TransactionElement/index.test.tsx @@ -10,29 +10,29 @@ const initialState = { backgroundState: { PreferencesController: { selectedAddress: '0x1', - identities: { '0xbar': { name: 'Account 1', address: '0x0', importTime: Date.now() } } + identities: { '0xbar': { name: 'Account 1', address: '0x0', importTime: Date.now() } }, }, CurrencyRateController: { currentCurrency: 'usd', - conversionRate: 0.1 + conversionRate: 0.1, }, NetworkController: { provider: { ticker: 'ETH', - type: 'mainnet' - } + type: 'mainnet', + }, }, TransactionController: { - swapsTransactions: {} + swapsTransactions: {}, }, SwapsController: { - tokens: [] - } - } + tokens: [], + }, + }, }, settings: { - primaryCurrency: 'ETH' - } + primaryCurrency: 'ETH', + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionReview/TransactionReviewData/index.test.tsx b/app/components/UI/TransactionReview/TransactionReviewData/index.test.tsx index 8b6e86a0891..16b788bb71b 100644 --- a/app/components/UI/TransactionReview/TransactionReviewData/index.test.tsx +++ b/app/components/UI/TransactionReview/TransactionReviewData/index.test.tsx @@ -9,17 +9,17 @@ const initialState = { engine: { backgroundState: { TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CurrencyRateController: { currentCurrency: 'usd', - conversionRate: 0.1 - } - } + conversionRate: 0.1, + }, + }, }, transaction: { transaction: { - data: '' + data: '', }, value: '', from: '0x1', @@ -27,8 +27,8 @@ const initialState = { gasPrice: '', to: '0x2', selectedAsset: undefined, - assetType: undefined - } + assetType: undefined, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionReview/TransactionReviewEIP1559/index.test.tsx b/app/components/UI/TransactionReview/TransactionReviewEIP1559/index.test.tsx index 8c84fae7a66..5741add2e48 100644 --- a/app/components/UI/TransactionReview/TransactionReviewEIP1559/index.test.tsx +++ b/app/components/UI/TransactionReview/TransactionReviewEIP1559/index.test.tsx @@ -10,16 +10,16 @@ const initialState = { backgroundState: { CurrencyRateController: { currentCurrency: 'usd', - conversionRate: 0.1 + conversionRate: 0.1, }, NetworkController: { provider: { ticker: 'ETH', - chainId: '1' - } - } - } - } + chainId: '1', + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionReview/TransactionReviewFeeCard/index.test.tsx b/app/components/UI/TransactionReview/TransactionReviewFeeCard/index.test.tsx index 5b181bbe958..8bfa906b4c2 100644 --- a/app/components/UI/TransactionReview/TransactionReviewFeeCard/index.test.tsx +++ b/app/components/UI/TransactionReview/TransactionReviewFeeCard/index.test.tsx @@ -10,16 +10,16 @@ const initialState = { backgroundState: { CurrencyRateController: { currentCurrency: 'usd', - conversionRate: 0.1 + conversionRate: 0.1, }, NetworkController: { provider: { ticker: 'ETH', - chainId: '1' - } - } - } - } + chainId: '1', + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionReview/TransactionReviewInformation/index.js b/app/components/UI/TransactionReview/TransactionReviewInformation/index.js index 1e572747b26..448198071ef 100644 --- a/app/components/UI/TransactionReview/TransactionReviewInformation/index.js +++ b/app/components/UI/TransactionReview/TransactionReviewInformation/index.js @@ -312,17 +312,6 @@ class TransactionReviewInformation extends PureComponent { contractExchangeRates, } = this.props; - const { totalMinNative, totalMinConversion, totalMaxNative, totalMaxConversion } = calculateAmountsEIP1559({ - value: value && BNToHex(value), - nativeCurrency, - currentCurrency, - conversionRate, - gasFeeMinConversion, - gasFeeMinNative, - gasFeeMaxNative, - gasFeeMaxConversion, - }); - let renderableTotalMinNative, renderableTotalMinConversion, renderableTotalMaxNative, @@ -330,6 +319,18 @@ class TransactionReviewInformation extends PureComponent { const totals = { ETH: () => { + const { totalMinNative, totalMinConversion, totalMaxNative, totalMaxConversion } = + calculateAmountsEIP1559({ + value: value && BNToHex(value), + nativeCurrency, + currentCurrency, + conversionRate, + gasFeeMinConversion, + gasFeeMinNative, + gasFeeMaxNative, + gasFeeMaxConversion, + }); + [ renderableTotalMinNative, renderableTotalMinConversion, @@ -352,6 +353,18 @@ class TransactionReviewInformation extends PureComponent { ]; }, ERC20: () => { + const { totalMinNative, totalMinConversion, totalMaxNative, totalMaxConversion } = + calculateAmountsEIP1559({ + value: '0x0', + nativeCurrency, + currentCurrency, + conversionRate, + gasFeeMinConversion, + gasFeeMinNative, + gasFeeMaxNative, + gasFeeMaxConversion, + }); + const tokenAmount = renderFromTokenMinimalUnit(value, selectedAsset.decimals); const exchangeRate = contractExchangeRates[selectedAsset.address]; const symbol = selectedAsset.symbol; @@ -381,6 +394,18 @@ class TransactionReviewInformation extends PureComponent { ]; }, ERC721: () => { + const { totalMinNative, totalMinConversion, totalMaxNative, totalMaxConversion } = + calculateAmountsEIP1559({ + value: '0x0', + nativeCurrency, + currentCurrency, + conversionRate, + gasFeeMinConversion, + gasFeeMinNative, + gasFeeMaxNative, + gasFeeMaxConversion, + }); + [ renderableTotalMinNative, renderableTotalMinConversion, diff --git a/app/components/UI/TransactionReview/TransactionReviewInformation/index.test.tsx b/app/components/UI/TransactionReview/TransactionReviewInformation/index.test.tsx index 40fc7512f1f..00eb9288dbf 100644 --- a/app/components/UI/TransactionReview/TransactionReviewInformation/index.test.tsx +++ b/app/components/UI/TransactionReview/TransactionReviewInformation/index.test.tsx @@ -9,21 +9,21 @@ const initialState = { engine: { backgroundState: { PreferencesController: { - selectedAddress: '0x2' + selectedAddress: '0x2', }, TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CurrencyRateController: { currentCurrency: 'usd', - conversionRate: 0.1 + conversionRate: 0.1, }, NetworkController: { provider: { - ticker: 'ETH' - } - } - } + ticker: 'ETH', + }, + }, + }, }, transaction: { value: '', @@ -33,11 +33,11 @@ const initialState = { gasPrice: '', to: '0x2', selectedAsset: undefined, - assetType: undefined + assetType: undefined, }, settings: { - primaryCurrency: 'ETH' - } + primaryCurrency: 'ETH', + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionReview/TransactionReviewSummary/index.test.tsx b/app/components/UI/TransactionReview/TransactionReviewSummary/index.test.tsx index 25abeff9112..71897c5e1cc 100644 --- a/app/components/UI/TransactionReview/TransactionReviewSummary/index.test.tsx +++ b/app/components/UI/TransactionReview/TransactionReviewSummary/index.test.tsx @@ -9,24 +9,24 @@ const initialState = { engine: { backgroundState: { TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CurrencyRateController: { currentCurrency: 'usd', - conversionRate: 0.1 + conversionRate: 0.1, }, TokensController: { - tokens: [] + tokens: [], }, NetworkController: { provider: { - ticker: 'ETH' - } - } - } + ticker: 'ETH', + }, + }, + }, }, settings: { - showHexData: true + showHexData: true, }, transaction: { value: '', @@ -36,8 +36,8 @@ const initialState = { gasPrice: '', to: '0x2', selectedAsset: undefined, - assetType: undefined - } + assetType: undefined, + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/TransactionReview/index.test.tsx b/app/components/UI/TransactionReview/index.test.tsx index 9d048eab6cf..c287ccddac4 100644 --- a/app/components/UI/TransactionReview/index.test.tsx +++ b/app/components/UI/TransactionReview/index.test.tsx @@ -10,32 +10,32 @@ const initialState = { engine: { backgroundState: { PreferencesController: { - selectedAddress: '0x2' + selectedAddress: '0x2', }, AccountTrackerController: { - accounts: [] + accounts: [], }, TokensController: { - tokens: [] + tokens: [], }, CurrencyRateController: { - currentCurrency: 'usd' + currentCurrency: 'usd', }, TokenRatesController: { contractExchangeRates: { - '0x': '0.1' - } + '0x': '0.1', + }, }, NetworkController: { provider: { - ticker: 'ETH' - } - } - } + ticker: 'ETH', + }, + }, + }, }, settings: { showHexData: true, - primaryCurrency: 'ETH' + primaryCurrency: 'ETH', }, transaction: { value: '', @@ -45,11 +45,11 @@ const initialState = { gasPrice: '', to: '0x2', selectedAsset: undefined, - assetType: undefined + assetType: undefined, }, browser: { - tabs: [] - } + tabs: [], + }, }; const store = mockStore(initialState); diff --git a/app/components/UI/Transactions/index.test.tsx b/app/components/UI/Transactions/index.test.tsx index 2a54b40313a..e4afd34d8d5 100644 --- a/app/components/UI/Transactions/index.test.tsx +++ b/app/components/UI/Transactions/index.test.tsx @@ -12,34 +12,34 @@ const initialState = { backgroundState: { PreferencesController: { selectedAddress: '0x0', - identities: { '0xbar': { name: 'Account 1', address: '0x0', importTime: Date.now() } } + identities: { '0xbar': { name: 'Account 1', address: '0x0', importTime: Date.now() } }, }, AccountTrackerController: { - accounts: {} + accounts: {}, }, TokensController: { - tokens: [] + tokens: [], }, TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CollectiblesController: { - collectibleContracts: {} + collectibleContracts: {}, }, CurrencyRateController: { currentCurrency: 'USD', - conversionRate: 1 + conversionRate: 1, }, NetworkController: { provider: { - chainId: '1' - } - } - } + chainId: '1', + }, + }, + }, }, privacy: { - thirdPartyApiMode: true - } + thirdPartyApiMode: true, + }, }; const store = mockStore(initialState); @@ -62,10 +62,10 @@ describe('Transactions', () => { gasPrice: '0x37e11d600', nonce: '0x2e', to: '0xe46abaf75cfbff815c0b7ffed6f02b0760ea27f1', - value: '0xfa1c6d5030000' + value: '0xfa1c6d5030000', }, - transactionHash: '0x79ce2d56aaa4735b2bb602ae3a501d9055350a6ec3fb3bd457ba18e8fa4aa2ae' - } + transactionHash: '0x79ce2d56aaa4735b2bb602ae3a501d9055350a6ec3fb3bd457ba18e8fa4aa2ae', + }, ]} loading={false} /> diff --git a/app/components/Views/AccountBackupStep1/index.test.tsx b/app/components/Views/AccountBackupStep1/index.test.tsx index 014aca06306..483624105bc 100644 --- a/app/components/Views/AccountBackupStep1/index.test.tsx +++ b/app/components/Views/AccountBackupStep1/index.test.tsx @@ -10,11 +10,11 @@ const initialState = { backgroundState: { NetworkController: { provider: { - chainId: '1' - } - } - } - } + chainId: '1', + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/AddAsset/index.test.tsx b/app/components/Views/AddAsset/index.test.tsx index 2d717185009..07fd5b5da0d 100644 --- a/app/components/Views/AddAsset/index.test.tsx +++ b/app/components/Views/AddAsset/index.test.tsx @@ -10,11 +10,11 @@ const initialState = { backgroundState: { NetworkController: { provider: { - chainId: '1' - } - } - } - } + chainId: '1', + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Approval/index.test.tsx b/app/components/Views/Approval/index.test.tsx index 80c5c2cabd9..819a0d12b4a 100644 --- a/app/components/Views/Approval/index.test.tsx +++ b/app/components/Views/Approval/index.test.tsx @@ -8,7 +8,7 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { settings: { - showCustomNonce: false + showCustomNonce: false, }, transaction: { value: '', @@ -18,23 +18,23 @@ const initialState = { gasPrice: '', to: '0x2', selectedAsset: { symbol: 'ETH' }, - assetType: undefined + assetType: undefined, }, engine: { backgroundState: { TransactionController: { - transactions: [] + transactions: [], }, AddressBookController: { - addressBook: {} + addressBook: {}, }, NetworkController: { provider: { - type: ROPSTEN - } - } - } - } + type: ROPSTEN, + }, + }, + }, + }, }; const store = mockStore(initialState); const navigation = { state: { params: { address: '0x1' } } } as any; diff --git a/app/components/Views/ApproveView/Approve/index.test.tsx b/app/components/Views/ApproveView/Approve/index.test.tsx index 128a015419a..a5e2f02d024 100644 --- a/app/components/Views/ApproveView/Approve/index.test.tsx +++ b/app/components/Views/ApproveView/Approve/index.test.tsx @@ -9,44 +9,44 @@ const mockStore = configureMockStore(); const initialState = { transaction: {}, settings: { - primaryCurrency: 'Fiat' + primaryCurrency: 'Fiat', }, browser: { activeTab: 1592878266671, - tabs: [{ id: 1592878266671, url: 'https://metamask.github.io/test-dapp/' }] + tabs: [{ id: 1592878266671, url: 'https://metamask.github.io/test-dapp/' }], }, engine: { backgroundState: { AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, NetworkController: { provider: { - ticker: 'ETH' - } + ticker: 'ETH', + }, }, TransactionController: { - transactions: [] + transactions: [], }, CurrencyRateController: { currentCurrency: 'USD', - conversionRate: 100 + conversionRate: 100, }, PreferencesController: { selectedAddress: '0x1', - identities: { '0x1': { name: 'Account 1' } } + identities: { '0x1': { name: 'Account 1' } }, }, TokenBalancesController: { - contractBalances: { '0x2': new BN(0) } + contractBalances: { '0x2': new BN(0) }, }, TokensController: { - tokens: [] + tokens: [], }, GasFeeController: { - gasEstimates: {} - } - } - } + gasEstimates: {}, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/ChoosePassword/index.test.tsx b/app/components/Views/ChoosePassword/index.test.tsx index d8feccb29e0..4de732cd925 100644 --- a/app/components/Views/ChoosePassword/index.test.tsx +++ b/app/components/Views/ChoosePassword/index.test.tsx @@ -11,15 +11,15 @@ const mockStore = configureMockStore(); const initialState = { user: { passwordSet: true, - seedphraseBackedUp: false + seedphraseBackedUp: false, }, engine: { backgroundState: { PreferencesController: { - selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1' - } - } - } + selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/ChoosePasswordSimple/index.test.tsx b/app/components/Views/ChoosePasswordSimple/index.test.tsx index d2fadc02f69..f195311d766 100644 --- a/app/components/Views/ChoosePasswordSimple/index.test.tsx +++ b/app/components/Views/ChoosePasswordSimple/index.test.tsx @@ -10,8 +10,8 @@ const mockStore = configureMockStore(); const initialState = { user: { passwordSet: true, - seedphraseBackedUp: false - } + seedphraseBackedUp: false, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Collectible/index.test.tsx b/app/components/Views/Collectible/index.test.tsx index 41567bee74e..1299cde5c21 100644 --- a/app/components/Views/Collectible/index.test.tsx +++ b/app/components/Views/Collectible/index.test.tsx @@ -9,13 +9,13 @@ const initialState = { engine: { backgroundState: { CollectiblesController: { - collectibles: [{ address: '0x0', name: 'collectible', tokenId: 0, image: 'image' }] - } - } + collectibles: [{ address: '0x0', name: 'collectible', tokenId: 0, image: 'image' }], + }, + }, }, modals: { - collectibleContractModalVisible: false - } + collectibleContractModalVisible: false, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Entry/index.test.tsx b/app/components/Views/Entry/index.test.tsx index 5020a98c5ec..b33dd47463d 100644 --- a/app/components/Views/Entry/index.test.tsx +++ b/app/components/Views/Entry/index.test.tsx @@ -7,13 +7,13 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { user: { - passwordSet: false + passwordSet: false, }, engine: { backgroundState: { - PreferencesController: {} - } - } + PreferencesController: {}, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/ExtensionSync/index.test.tsx b/app/components/Views/ExtensionSync/index.test.tsx deleted file mode 100644 index 96308236cb9..00000000000 --- a/app/components/Views/ExtensionSync/index.test.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import ExtensionSync from './'; -import { Provider } from 'react-redux'; -import createMockStore from 'redux-mock-store'; - -const mockStore = createMockStore(); -const initialState = { - user: { - passwordSet: false, - loadingSet: false, - loadingMsg: '' - }, - engine: { - backgroundState: { - PreferencesController: { - selectedAddress: '' - } - } - } -}; -const store = mockStore(initialState); - -describe('ExtensionSync', () => { - it('should render correctly', () => { - const wrapper = shallow( - - - - ); - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/app/components/Views/ExtensionSync/index.tsx b/app/components/Views/ExtensionSync/index.tsx deleted file mode 100644 index 8986308b5f8..00000000000 --- a/app/components/Views/ExtensionSync/index.tsx +++ /dev/null @@ -1,402 +0,0 @@ -import React, { useEffect, useCallback } from 'react'; -import { View, StyleSheet, Text, Image, InteractionManager, ActivityIndicator } from 'react-native'; -import { colors, fontStyles } from '../../../styles/common'; -import { getOnboardingNavbarOptions } from '../../UI/Navbar'; -import StyledButton from '../../UI/StyledButton'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { Alert } from 'react-native'; -import { strings } from '../../../../locales/i18n'; -import PubNubWrapper from '../../../util/syncWithExtension'; -import { useRef } from 'react'; -import Logger from '../../../util/Logger'; -import AnalyticsV2 from '../../../util/analyticsV2'; -import Analytics from '../../../core/Analytics'; -import DefaultPreference from 'react-native-default-preference'; -import PreventScreenshot from '../../../core/PreventScreenshot'; -import { - EXISTING_USER, - METRICS_OPT_IN, - SEED_PHRASE_HINTS, - BIOMETRY_CHOICE, - BIOMETRY_CHOICE_DISABLED, - NEXT_MAKER_REMINDER, - TRUE, -} from '../../../constants/storage'; -import AsyncStorage from '@react-native-community/async-storage'; -import SecureKeychain from '../../../core/SecureKeychain'; -import Device from '../../../util/device'; -import AppConstants from '../../../core/AppConstants'; -import Engine from '../../../core/Engine'; -import { useDispatch, useSelector } from 'react-redux'; -import { saveOnboardingEvent as saveEvent } from '../../../actions/onboarding'; -import { - loadingSet, - loadingUnset, - seedphraseNotBackedUp as backedUpSeed, - passwordSet as passwordIsSet, -} from '../../../actions/user'; -import { setLockTime as lockTimeSet } from '../../../actions/settings'; -import { BIOMETRY_TYPE } from 'react-native-keychain'; -import scaling from '../../../util/scaling'; - -// TODO: This file needs typings -const ExtensionSync = ({ navigation, route }: any) => { - const pubnubWrapperRef = useRef(null); - const passwordRef = useRef(undefined); - const seedWordsRef = useRef(null); - const importedAccountsRef = useRef(null); - const dataToSyncRef = useRef(null); - - const passwordSet = useSelector((state: any) => state.user.passwordSet); - const selectedAddress = useSelector( - (state: any) => state.engine.backgroundState.PreferencesController.selectedAddress - ); - const loading = useSelector((state: any) => state.user.loadingSet); - const loadingMsg = useSelector((state: any) => state.user.loadingMsg); - - const dispatch = useDispatch(); - const saveOnboardingEvent = (event: any) => dispatch(saveEvent(event)); - const setLoading = (msg: string) => dispatch(loadingSet(msg)); - const unsetLoading = () => dispatch(loadingUnset()); - const passwordHasBeenSet = () => dispatch(passwordIsSet()); - const seedphraseBackedUp = () => dispatch(backedUpSeed()); - const setLockTime = (time: number) => dispatch(lockTimeSet(time)); - - useEffect(() => { - // Set navigation options - navigation.setOptions(getOnboardingNavbarOptions(navigation, route)); - // Unmount - return () => { - pubnubWrapperRef.current?.disconnectWebsockets?.(); - unsetLoading(); - InteractionManager.runAfterInteractions(PreventScreenshot.allow); - }; - }, []); - - // TODO: Don't spread this, break it out and type it - const track = useCallback( - (...eventArgs) => { - InteractionManager.runAfterInteractions(async () => { - if (Analytics.getEnabled()) { - AnalyticsV2.trackEvent(eventArgs[0], eventArgs[1]); - return; - } - const metricsOptIn = await DefaultPreference.get(METRICS_OPT_IN); - if (!metricsOptIn) { - saveOnboardingEvent(eventArgs); - } - }); - }, - [saveOnboardingEvent] - ); - - const finishSync = useCallback( - async (opts) => { - if (opts.biometrics) { - try { - await SecureKeychain.setGenericPassword(opts.password, SecureKeychain.TYPES.BIOMETRICS); - } catch (e) { - await SecureKeychain.resetGenericPassword(); - } - } else { - await SecureKeychain.resetGenericPassword(); - } - - try { - await AsyncStorage.removeItem(NEXT_MAKER_REMINDER); - await Engine.resetState(); - await Engine.sync({ - ...dataToSyncRef.current, - seed: seedWordsRef.current, - importedAccounts: importedAccountsRef.current, - pass: opts.password, - }); - await AsyncStorage.setItem(EXISTING_USER, TRUE); - await AsyncStorage.removeItem(SEED_PHRASE_HINTS); - passwordHasBeenSet(); - setLockTime(AppConstants.DEFAULT_LOCK_TIMEOUT); - seedphraseBackedUp(); - dataToSyncRef.current = null; - track(AnalyticsV2.ANALYTICS_EVENTS.WALLET_SYNC_SUCCESSFUL); - track(AnalyticsV2.ANALYTICS_EVENTS.WALLET_SETUP_COMPLETED, { - wallet_setup_type: 'sync', - new_wallet: false, - }); - - navigation.push('SyncWithExtensionSuccess'); - unsetLoading(); - } catch (e) { - track(AnalyticsV2.ANALYTICS_EVENTS.WALLET_SETUP_FAILURE, { - wallet_setup_type: 'sync', - error_type: e.toString(), - }); - Logger.error(e, 'Sync::disconnect'); - Alert.alert(strings('sync_with_extension.error_title'), strings('sync_with_extension.error_message')); - unsetLoading(); - navigation.goBack(); - } - }, - [unsetLoading, passwordHasBeenSet, setLockTime, seedphraseBackedUp, track] - ); - - const disconnect = useCallback(async () => { - let password: string | undefined; - try { - // If there's a password set, let's keep it - if (passwordSet) { - // This could also come from the previous step if it's a first time user - const credentials = await SecureKeychain.getGenericPassword(); - if (credentials) { - password = credentials.password; - } else { - password = passwordRef.current; - } - // Otherwise use the password from the extension - } else { - password = passwordRef.current; - } - } catch (e) { - password = passwordRef.current; - } - - if (password === passwordRef.current) { - let biometryType: BIOMETRY_TYPE | null | 'biometrics' = await SecureKeychain.getSupportedBiometryType(); - if (biometryType) { - if (Device.isAndroid()) biometryType = 'biometrics'; - Alert.alert( - strings('sync_with_extension.allow_biometrics_title', { biometrics: biometryType }), - strings('sync_with_extension.allow_biometrics_desc', { biometrics: biometryType }), - [ - { - text: strings('sync_with_extension.warning_cancel_button'), - onPress: async () => { - await AsyncStorage.removeItem(BIOMETRY_CHOICE); - await AsyncStorage.setItem(BIOMETRY_CHOICE_DISABLED, TRUE); - finishSync({ biometrics: false, password }); - }, - style: 'cancel', - }, - { - text: strings('sync_with_extension.warning_ok_button'), - onPress: async () => { - await AsyncStorage.setItem(BIOMETRY_CHOICE, biometryType as string); - await AsyncStorage.removeItem(BIOMETRY_CHOICE_DISABLED); - finishSync({ biometrics: true, biometryType, password }); - }, - }, - ], - { cancelable: false } - ); - } else { - finishSync({ biometrics: false, password }); - } - } else { - finishSync({ biometrics: false, password }); - } - }, [finishSync, passwordSet, passwordRef]); - - const initWebsockets = useCallback(() => { - setLoading(strings('sync_with_extension.please_wait')); - - pubnubWrapperRef.current?.addMessageListener?.( - () => { - Alert.alert(strings('sync_with_extension.error_title'), strings('sync_with_extension.error_message')); - track(AnalyticsV2.ANALYTICS_EVENTS.WALLET_SETUP_FAILURE, { - wallet_setup_type: 'sync', - error_type: 'onErrorSync', - }); - unsetLoading(); - return false; - }, - (data: any) => { - // this.incomingDataStr = null; - const { pwd, seed, importedAccounts } = data.udata; - passwordRef.current = pwd; - seedWordsRef.current = seed; - importedAccountsRef.current = importedAccounts; - delete data.udata; - dataToSyncRef.current = { ...data }; - pubnubWrapperRef.current?.endSync?.(disconnect); - } - ); - - pubnubWrapperRef.current?.subscribe?.(); - }, [pubnubWrapperRef, passwordRef, track, unsetLoading, disconnect, setLoading]); - - const startSync = useCallback(async () => { - try { - initWebsockets(); - await pubnubWrapperRef.current?.startSync?.(); - return true; - } catch (e) { - unsetLoading(); - if (e.message === 'Sync::timeout') { - Alert.alert( - strings('sync_with_extension.outdated_qr_code'), - strings('sync_with_extension.outdated_qr_code_desc') - ); - } else { - Alert.alert( - strings('sync_with_extension.something_wrong'), - strings('sync_with_extension.something_wrong_desc') - ); - } - Logger.error(e, { message: 'Sync::startSync', firstAttempt: true }); - track(AnalyticsV2.ANALYTICS_EVENTS.WALLET_SETUP_FAILURE, { - wallet_setup_type: 'sync', - error_type: e.message(), - }); - return false; - } - }, [initWebsockets, pubnubWrapperRef, track, unsetLoading]); - - const onStartScan = useCallback( - async (data) => { - if (data.content && data.content.search('metamask-sync:') !== -1) { - const [channelName, cipherKey] = data.content.replace('metamask-sync:', '').split('|@|'); - pubnubWrapperRef.current = new PubNubWrapper(channelName, cipherKey); - await pubnubWrapperRef.current?.establishConnection?.(selectedAddress); - } else { - Alert.alert( - strings('sync_with_extension.invalid_qr_code'), - strings('sync_with_extension.invalid_qr_code_desc') - ); - } - }, - [selectedAddress] - ); - - const onScanSuccess = useCallback(async (data) => { - if (data.content && data.content.search('metamask-sync:') !== -1) { - await startSync(); - } else { - Alert.alert( - strings('sync_with_extension.invalid_qr_code'), - strings('sync_with_extension.invalid_qr_code_desc') - ); - } - }, []); - - const triggerScan = useCallback(() => { - navigation.push('QRScanner', { - onStartScan, - onScanSuccess, - }); - }, [onStartScan, onScanSuccess]); - - const renderSyncImage = useCallback(() => { - return ; - }, []); - - const renderTitle = useCallback(() => { - return {strings('onboarding.scan_title')}; - }, []); - - const renderSteps = useCallback(() => { - const steps = [1, 2, 3, 4]; - return ( - - {steps.map((stepIndex) => { - const text = `onboarding.scan_step_${stepIndex}`; - return ( - - {`${stepIndex}. ${strings(text)}`} - - ); - })} - - ); - }, []); - - const renderScanButton = useCallback(() => { - return ( - - {strings('onboarding.scan')} - - ); - }, [triggerScan]); - - const renderLoader = useCallback(() => { - return ( - - - - {loadingMsg} - - - ); - }, [loading, loadingMsg]); - - const renderContent = useCallback(() => { - return ( - - - {renderSyncImage()} - {renderTitle()} - {renderSteps()} - - {renderScanButton()} - - ); - }, [renderSyncImage, renderTitle, renderSteps, renderScanButton]); - - return ( - - {loading ? renderLoader() : renderContent()} - - ); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - backgroundColor: colors.white, - paddingHorizontal: 16, - justifyContent: 'space-between', - paddingBottom: 16, - }, - fill: { - flex: 1, - }, - syncImage: { - height: 44, - marginTop: 48, - width: 112, - alignSelf: 'center', - }, - titleLabel: { - textAlign: 'center', - color: colors.black, - fontSize: 24, - fontFamily: fontStyles.bold.fontFamily, - marginTop: 32, - }, - stepsContainer: { - marginTop: 32, - }, - stepLabel: { - color: colors.black, - fontSize: scaling.scale(16), - fontFamily: fontStyles.normal.fontFamily, - marginBottom: 8, - }, - wrapper: { - flex: 1, - alignItems: 'center', - paddingVertical: 30, - }, - loader: { - marginTop: 180, - justifyContent: 'center', - textAlign: 'center', - }, - loadingText: { - marginTop: 30, - fontSize: 14, - textAlign: 'center', - color: colors.fontPrimary, - fontFamily: fontStyles.normal.fontFamily, - }, -}); - -export default ExtensionSync; diff --git a/app/components/Views/ImportFromSeed/index.test.tsx b/app/components/Views/ImportFromSeed/index.test.tsx index 340a4c7822a..8f100755bc0 100644 --- a/app/components/Views/ImportFromSeed/index.test.tsx +++ b/app/components/Views/ImportFromSeed/index.test.tsx @@ -8,8 +8,8 @@ const mockStore = configureMockStore(); const initialState = { user: { passwordSet: true, - seedphraseBackedUp: false - } + seedphraseBackedUp: false, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/LockScreen/index.test.tsx b/app/components/Views/LockScreen/index.test.tsx index b6c8816747f..c6711836e51 100644 --- a/app/components/Views/LockScreen/index.test.tsx +++ b/app/components/Views/LockScreen/index.test.tsx @@ -7,8 +7,8 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { user: { - passwordSet: false - } + passwordSet: false, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Login/index.test.tsx b/app/components/Views/Login/index.test.tsx index 2a22a7f606e..0716dd3bd88 100644 --- a/app/components/Views/Login/index.test.tsx +++ b/app/components/Views/Login/index.test.tsx @@ -10,22 +10,22 @@ const initialState = { engine: { backgroundState: { AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, NetworkController: { provider: { - type: ROPSTEN - } + type: ROPSTEN, + }, }, TokensController: { - tokens: [] + tokens: [], }, - PreferencesController: {} - } + PreferencesController: {}, + }, }, user: { - passwordSet: true - } + passwordSet: true, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/ManualBackupStep2/index.test.tsx b/app/components/Views/ManualBackupStep2/index.test.tsx index 0ed6c8597f0..5f5be7a266b 100644 --- a/app/components/Views/ManualBackupStep2/index.test.tsx +++ b/app/components/Views/ManualBackupStep2/index.test.tsx @@ -8,8 +8,8 @@ const mockStore = configureMockStore(); const initialState = { user: { passwordSet: true, - seedphraseBackedUp: false - } + seedphraseBackedUp: false, + }, }; const store = mockStore(initialState); @@ -32,10 +32,10 @@ describe('ManualBackupStep2', () => { 'business', 'category', 'champion', - 'cinnamon' + 'cinnamon', ], - steps: ['one', 'two', 'three'] - } + steps: ['one', 'two', 'three'], + }, }} /> diff --git a/app/components/Views/OfflineMode/index.test.tsx b/app/components/Views/OfflineMode/index.test.tsx index 7ab74911365..40340f7053e 100644 --- a/app/components/Views/OfflineMode/index.test.tsx +++ b/app/components/Views/OfflineMode/index.test.tsx @@ -7,8 +7,8 @@ import { Provider } from 'react-redux'; const mockStore = configureMockStore(); const initialState = { infuraAvailability: { - isBlocked: false - } + isBlocked: false, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/ResetPassword/index.test.tsx b/app/components/Views/ResetPassword/index.test.tsx index 5fc62257e1b..67df1dadb32 100644 --- a/app/components/Views/ResetPassword/index.test.tsx +++ b/app/components/Views/ResetPassword/index.test.tsx @@ -10,15 +10,15 @@ const mockStore = configureMockStore(); const initialState = { user: { passwordSet: true, - seedphraseBackedUp: false + seedphraseBackedUp: false, }, engine: { backgroundState: { PreferencesController: { - selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1' - } - } - } + selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/RevealPrivateCredential/index.test.tsx b/app/components/Views/RevealPrivateCredential/index.test.tsx index 76b271cbfd6..cca0b7204b9 100644 --- a/app/components/Views/RevealPrivateCredential/index.test.tsx +++ b/app/components/Views/RevealPrivateCredential/index.test.tsx @@ -9,13 +9,13 @@ const initialState = { engine: { backgroundState: { PreferencesController: { - selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1' - } - } + selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1', + }, + }, }, user: { - passwordSet: false - } + passwordSet: false, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/SendFlow/AddressElement/index.test.tsx b/app/components/Views/SendFlow/AddressElement/index.test.tsx index 6c751713684..229faa855cc 100644 --- a/app/components/Views/SendFlow/AddressElement/index.test.tsx +++ b/app/components/Views/SendFlow/AddressElement/index.test.tsx @@ -9,10 +9,10 @@ const initialState = { engine: { backgroundState: { NetworkController: { - network: '1' - } - } - } + network: '1', + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/SendFlow/AddressList/index.test.tsx b/app/components/Views/SendFlow/AddressList/index.test.tsx index 9a1ff08dba7..cfb7dc748c0 100644 --- a/app/components/Views/SendFlow/AddressList/index.test.tsx +++ b/app/components/Views/SendFlow/AddressList/index.test.tsx @@ -12,8 +12,8 @@ const initialState = { NetworkController: { network: '1', provider: { - chainId: '1' - } + chainId: '1', + }, }, AddressBookController: { addressBook: { @@ -22,23 +22,23 @@ const initialState = { chainId: '1', isEns: false, memo: '', - name: 'aa' - } - } + name: 'aa', + }, + }, }, PreferencesController: { identities: { '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b': { address: '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b', - name: 'Account 1' - } - } + name: 'Account 1', + }, + }, }, TransactionController: { - transactions: [] - } - } - } + transactions: [], + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/SendFlow/Amount/index.test.tsx b/app/components/Views/SendFlow/Amount/index.test.tsx index f2eec4ba624..25d27119f34 100644 --- a/app/components/Views/SendFlow/Amount/index.test.tsx +++ b/app/components/Views/SendFlow/Amount/index.test.tsx @@ -12,11 +12,11 @@ const initialState = { network: '1', provider: { ticker: 'ETH', - type: 'mainnet' - } + type: 'mainnet', + }, }, AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, AddressBookController: { addressBook: { @@ -25,45 +25,45 @@ const initialState = { chainId: '1', isEns: false, memo: '', - name: 'aa' - } - } + name: 'aa', + }, + }, }, PreferencesController: { identities: { '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b': { address: '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b', - name: 'Account 1' - } - } + name: 'Account 1', + }, + }, }, TransactionController: { - transactions: [] + transactions: [], }, TokensController: { - tokens: [] + tokens: [], }, CollectiblesController: { - collectibles: {} + collectibles: {}, }, TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CurrencyRateController: { currentCurrency: 'USD', - conversionRate: 1 + conversionRate: 1, }, TokenBalancesController: { - contractBalance: {} - } - } + contractBalance: {}, + }, + }, }, settings: { - primaryCurrency: 'fiat' + primaryCurrency: 'fiat', }, transaction: { - selectedAsset: {} - } + selectedAsset: {}, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/SendFlow/Confirm/index.test.tsx b/app/components/Views/SendFlow/Confirm/index.test.tsx index 50763f56078..22636aaf8ca 100644 --- a/app/components/Views/SendFlow/Confirm/index.test.tsx +++ b/app/components/Views/SendFlow/Confirm/index.test.tsx @@ -12,46 +12,46 @@ const initialState = { network: '1', provider: { ticker: 'ETH', - type: 'mainnet' - } + type: 'mainnet', + }, }, AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, TransactionController: { - transactions: [] + transactions: [], }, TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CurrencyRateController: { currentCurrency: 'USD', - conversionRate: 1 + conversionRate: 1, }, TokenBalancesController: { - contractBalances: {} + contractBalances: {}, }, PreferencesController: { - identities: {} + identities: {}, }, KeyringController: { - keyrings: [{ accounts: ['0x'], type: 'HD Key Tree' }] + keyrings: [{ accounts: ['0x'], type: 'HD Key Tree' }], }, GasFeeController: { - gasEstimates: {} - } - } + gasEstimates: {}, + }, + }, }, settings: { - showHexData: true + showHexData: true, }, transaction: { selectedAsset: {}, transaction: { from: '0x1', - to: '0x2' - } - } + to: '0x2', + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/SendFlow/SendTo/index.test.tsx b/app/components/Views/SendFlow/SendTo/index.test.tsx index cb845681ac9..ba075efdc90 100644 --- a/app/components/Views/SendFlow/SendTo/index.test.tsx +++ b/app/components/Views/SendFlow/SendTo/index.test.tsx @@ -12,11 +12,11 @@ const initialState = { network: '1', provider: { ticker: 'ETH', - type: 'mainnet' - } + type: 'mainnet', + }, }, AccountTrackerController: { - accounts: { '0x2': { balance: '0' } } + accounts: { '0x2': { balance: '0' } }, }, AddressBookController: { addressBook: { @@ -25,44 +25,44 @@ const initialState = { chainId: '1', isEns: false, memo: '', - name: 'aa' - } - } + name: 'aa', + }, + }, }, PreferencesController: { identities: { '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b': { address: '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b', - name: 'Account 1' - } + name: 'Account 1', + }, }, - selectedAddress: '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b' + selectedAddress: '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b', }, TransactionController: { - transactions: [] + transactions: [], }, TokensController: { - tokens: [] + tokens: [], }, TokenRatesController: { - contractExchangeRates: {} + contractExchangeRates: {}, }, CurrencyRateController: { currentCurrency: 'USD', - conversionRate: 1 + conversionRate: 1, }, TokenBalancesController: { - contractBalance: {} + contractBalance: {}, }, - KeyringController: { keyrings: [{ accounts: ['0x'], type: 'HD Key Tree' }] } - } + KeyringController: { keyrings: [{ accounts: ['0x'], type: 'HD Key Tree' }] }, + }, }, settings: { - primaryCurrency: 'fiat' + primaryCurrency: 'fiat', }, transaction: { - selectedAsset: {} - } + selectedAsset: {}, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/AdvancedSettings/index.test.tsx b/app/components/Views/Settings/AdvancedSettings/index.test.tsx index 1595604063c..86854643e66 100644 --- a/app/components/Views/Settings/AdvancedSettings/index.test.tsx +++ b/app/components/Views/Settings/AdvancedSettings/index.test.tsx @@ -10,10 +10,10 @@ const initialState = { engine: { backgroundState: { PreferencesController: { - ipfsGateway: 'https://ipfs.io/ipfs/' - } - } - } + ipfsGateway: 'https://ipfs.io/ipfs/', + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx b/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx index a669a5a3b3b..b87ebb61c5e 100644 --- a/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx +++ b/app/components/Views/Settings/Contacts/ContactForm/index.test.tsx @@ -9,7 +9,7 @@ const initialState = { engine: { backgroundState: { NetworkController: { - network: '1' + network: '1', }, AddressBookController: { addressBook: { @@ -18,20 +18,20 @@ const initialState = { chainId: '1', isEns: false, memo: '', - name: 'aa' - } - } + name: 'aa', + }, + }, }, PreferencesController: { identities: { '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b': { address: '0x51239E13Fe029cD52asA8babEBafb6814bc8Ba4b', - name: 'Account 1' - } - } - } - } - } + name: 'Account 1', + }, + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/Contacts/index.test.tsx b/app/components/Views/Settings/Contacts/index.test.tsx index 9cfb27cb2fa..96a5abc9a42 100644 --- a/app/components/Views/Settings/Contacts/index.test.tsx +++ b/app/components/Views/Settings/Contacts/index.test.tsx @@ -9,7 +9,7 @@ const initialState = { engine: { backgroundState: { NetworkController: { - network: '1' + network: '1', }, AddressBookController: { addressBook: { @@ -18,12 +18,12 @@ const initialState = { chainId: '1', isEns: false, memo: '', - name: 'aa' - } - } - } - } - } + name: 'aa', + }, + }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/ExperimentalSettings/index.test.tsx b/app/components/Views/Settings/ExperimentalSettings/index.test.tsx index ca113e64f55..654947f7554 100644 --- a/app/components/Views/Settings/ExperimentalSettings/index.test.tsx +++ b/app/components/Views/Settings/ExperimentalSettings/index.test.tsx @@ -12,9 +12,9 @@ const initialState = { engine: { backgroundState: { PreferencesController: { selectedAddress: '0x', identities: { '0x': { name: 'Account 1' } } }, - AccountTrackerController: { accounts: {} } - } - } + AccountTrackerController: { accounts: {} }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/GeneralSettings/index.test.tsx b/app/components/Views/Settings/GeneralSettings/index.test.tsx index b7f4c787a42..9d662d191b1 100644 --- a/app/components/Views/Settings/GeneralSettings/index.test.tsx +++ b/app/components/Views/Settings/GeneralSettings/index.test.tsx @@ -14,12 +14,12 @@ const initialState = { CurrencyRateController: { currentCurrency: 'USD' }, NetworkController: { provider: { - type: 'mainnet' - } + type: 'mainnet', + }, }, - PreferencesController: { selectedAddress: '0x0' } - } - } + PreferencesController: { selectedAddress: '0x0' }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.test.tsx b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.test.tsx index a630a8cd240..2e874de527d 100644 --- a/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.test.tsx +++ b/app/components/Views/Settings/NetworksSettings/NetworkSettings/index.test.tsx @@ -9,10 +9,10 @@ const initialState = { engine: { backgroundState: { PreferencesController: { - frequentRpcList: [] - } - } - } + frequentRpcList: [], + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/NetworksSettings/index.test.tsx b/app/components/Views/Settings/NetworksSettings/index.test.tsx index 8dcecab9e9c..52356040924 100644 --- a/app/components/Views/Settings/NetworksSettings/index.test.tsx +++ b/app/components/Views/Settings/NetworksSettings/index.test.tsx @@ -9,14 +9,14 @@ const initialState = { engine: { backgroundState: { NetworkController: { - provider: { type: 'mainnet', rpcTarget: 'http://10.0.2.2:8545' } + provider: { type: 'mainnet', rpcTarget: 'http://10.0.2.2:8545' }, }, - PreferencesController: { frequentRpcList: ['http://10.0.2.2:8545'] } - } + PreferencesController: { frequentRpcList: ['http://10.0.2.2:8545'] }, + }, }, privacy: { - thirdPartyApiMode: true - } + thirdPartyApiMode: true, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/SecuritySettings/index.test.tsx b/app/components/Views/Settings/SecuritySettings/index.test.tsx index 74427292c53..cb7f0c1ff94 100644 --- a/app/components/Views/Settings/SecuritySettings/index.test.tsx +++ b/app/components/Views/Settings/SecuritySettings/index.test.tsx @@ -14,9 +14,9 @@ const initialState = { backgroundState: { PreferencesController: { selectedAddress: '0x', identities: { '0x': { name: 'Account 1' } } }, AccountTrackerController: { accounts: {} }, - KeyringController: { keyrings: [{ accounts: ['0x'], type: 'HD Key Tree' }] } - } - } + KeyringController: { keyrings: [{ accounts: ['0x'], type: 'HD Key Tree' }] }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/Settings/index.test.tsx b/app/components/Views/Settings/index.test.tsx index 81d4fb122ce..9384415462b 100644 --- a/app/components/Views/Settings/index.test.tsx +++ b/app/components/Views/Settings/index.test.tsx @@ -15,12 +15,12 @@ const initialState = { CurrencyRateController: { currentCurrency: 'USD' }, NetworkController: { provider: { - type: 'mainnet' - } + type: 'mainnet', + }, }, - PreferencesController: { selectedAddress: '0x0' } - } - } + PreferencesController: { selectedAddress: '0x0' }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/components/Views/TransactionDirection/index.test.tsx b/app/components/Views/TransactionDirection/index.test.tsx index 72ce39c62b4..154aa28bab0 100644 --- a/app/components/Views/TransactionDirection/index.test.tsx +++ b/app/components/Views/TransactionDirection/index.test.tsx @@ -10,10 +10,10 @@ const initialState = { engine: { backgroundState: { PreferencesController: { - identities: { '0x1': { name: 'Account 1' } } - } - } - } + identities: { '0x1': { name: 'Account 1' } }, + }, + }, + }, }; const store = mockStore(initialState); diff --git a/app/util/transactions/index.js b/app/util/transactions/index.js index 23740a13689..ac51f36d304 100644 --- a/app/util/transactions/index.js +++ b/app/util/transactions/index.js @@ -33,6 +33,8 @@ import { import humanizeDuration from 'humanize-duration'; import Logger from '../../util/Logger'; +import BigNumber from 'bignumber.js'; + const { SAI_ADDRESS } = AppConstants; export const TOKEN_METHOD_TRANSFER = 'transfer'; @@ -1113,3 +1115,56 @@ export function validateTransactionActionBalance(transaction, rate, accounts) { return false; } } + +export function calcTokenAmount(value, decimals) { + const multiplier = Math.pow(10, Number(decimals || 0)); + return new BigNumber(String(value)).div(multiplier); +} + +export function calcTokenValue(value, decimals) { + const multiplier = Math.pow(10, Number(decimals || 0)); + return new BigNumber(String(value)).times(multiplier); +} + +/** + * Attempts to get the address parameter of the given token transaction data + * (i.e. function call) per the Human Standard Token ABI, in the following + * order: + * - The '_to' parameter, if present + * - The first parameter, if present + * + * @param {Object} tokenData - ethers Interface token data. + * @returns {string | undefined} A lowercase address string. + */ +export function getTokenAddressParam(tokenData = {}) { + const value = tokenData?.args?._to || tokenData?.args?.[0]; + return value?.toString().toLowerCase(); +} + +/** + * Gets the '_hex' parameter of the given token transaction data + * (i.e function call) per the Human Standard Token ABI, if present. + * + * @param {Object} tokenData - ethers Interface token data. + * @returns {string | undefined} A hex string value. + */ +export function getTokenValueParamAsHex(tokenData = {}) { + const value = tokenData?.args?._value?._hex || tokenData?.args?.[1]._hex; + return value?.toLowerCase(); +} + +/** + * Gets the '_value' parameter of the given token transaction data + * (i.e function call) per the Human Standard Token ABI, if present. + * + * @param {Object} tokenData - ethers Interface token data. + * @returns {string | undefined} A decimal string value. + */ +export function getTokenValueParam(tokenData = {}) { + return tokenData?.args?._value?.toString(); +} + +export function getTokenValue(tokenParams = []) { + const valueData = tokenParams.find((param) => param.name === '_value'); + return valueData && valueData.value; +} diff --git a/package.json b/package.json index b17e0eaa59b..7c15da9a8e0 100644 --- a/package.json +++ b/package.json @@ -129,6 +129,7 @@ "events": "3.0.0", "fuse.js": "3.4.4", "https-browserify": "0.0.1", + "human-standard-token-abi": "^2.0.0", "humanize-duration": "^3.27.0", "improved-yarn-audit": "^2.3.3", "is-url": "^1.2.4",