aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/ducks
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/ducks')
-rw-r--r--ui/app/ducks/confirm-transaction.duck.js386
-rw-r--r--ui/app/ducks/send.duck.js7
-rw-r--r--ui/app/ducks/tests/confirm-transaction.duck.test.js675
-rw-r--r--ui/app/ducks/tests/send-duck.test.js10
4 files changed, 1078 insertions, 0 deletions
diff --git a/ui/app/ducks/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction.duck.js
new file mode 100644
index 000000000..1885e12d1
--- /dev/null
+++ b/ui/app/ducks/confirm-transaction.duck.js
@@ -0,0 +1,386 @@
+import {
+ conversionRateSelector,
+ currentCurrencySelector,
+ unconfirmedTransactionsHashSelector,
+} from '../selectors/confirm-transaction'
+
+import {
+ getTokenData,
+ getMethodData,
+ getTransactionAmount,
+ getTransactionFee,
+ getHexGasTotal,
+ addFiat,
+ addEth,
+ increaseLastGasPrice,
+ hexGreaterThan,
+} from '../helpers/confirm-transaction/util'
+
+import { getSymbolAndDecimals } from '../token-util'
+import { conversionUtil } from '../conversion-util'
+
+// Actions
+const createActionType = action => `metamask/confirm-transaction/${action}`
+
+const UPDATE_TX_DATA = createActionType('UPDATE_TX_DATA')
+const CLEAR_TX_DATA = createActionType('CLEAR_TX_DATA')
+const UPDATE_TOKEN_DATA = createActionType('UPDATE_TOKEN_DATA')
+const CLEAR_TOKEN_DATA = createActionType('CLEAR_TOKEN_DATA')
+const UPDATE_METHOD_DATA = createActionType('UPDATE_METHOD_DATA')
+const CLEAR_METHOD_DATA = createActionType('CLEAR_METHOD_DATA')
+const CLEAR_CONFIRM_TRANSACTION = createActionType('CLEAR_CONFIRM_TRANSACTION')
+const UPDATE_TRANSACTION_AMOUNTS = createActionType('UPDATE_TRANSACTION_AMOUNTS')
+const UPDATE_TRANSACTION_FEES = createActionType('UPDATE_TRANSACTION_FEES')
+const UPDATE_TRANSACTION_TOTALS = createActionType('UPDATE_TRANSACTION_TOTALS')
+const UPDATE_HEX_GAS_TOTAL = createActionType('UPDATE_HEX_GAS_TOTAL')
+const UPDATE_TOKEN_PROPS = createActionType('UPDATE_TOKEN_PROPS')
+const UPDATE_NONCE = createActionType('UPDATE_NONCE')
+const FETCH_METHOD_DATA_START = createActionType('FETCH_METHOD_DATA_START')
+const FETCH_METHOD_DATA_END = createActionType('FETCH_METHOD_DATA_END')
+
+// Initial state
+const initState = {
+ txData: {},
+ tokenData: {},
+ methodData: {},
+ tokenProps: {
+ tokenDecimals: '',
+ tokenSymbol: '',
+ },
+ fiatTransactionAmount: '',
+ fiatTransactionFee: '',
+ fiatTransactionTotal: '',
+ ethTransactionAmount: '',
+ ethTransactionFee: '',
+ ethTransactionTotal: '',
+ hexGasTotal: '',
+ nonce: '',
+ fetchingMethodData: false,
+}
+
+// Reducer
+export default function reducer ({ confirmTransaction: confirmState = initState }, action = {}) {
+ switch (action.type) {
+ case UPDATE_TX_DATA:
+ return {
+ ...confirmState,
+ txData: {
+ ...action.payload,
+ },
+ }
+ case CLEAR_TX_DATA:
+ return {
+ ...confirmState,
+ txData: {},
+ }
+ case UPDATE_TOKEN_DATA:
+ return {
+ ...confirmState,
+ tokenData: {
+ ...action.payload,
+ },
+ }
+ case CLEAR_TOKEN_DATA:
+ return {
+ ...confirmState,
+ tokenData: {},
+ }
+ case UPDATE_METHOD_DATA:
+ return {
+ ...confirmState,
+ methodData: {
+ ...action.payload,
+ },
+ }
+ case CLEAR_METHOD_DATA:
+ return {
+ ...confirmState,
+ methodData: {},
+ }
+ case UPDATE_TRANSACTION_AMOUNTS:
+ const { fiatTransactionAmount, ethTransactionAmount } = action.payload
+ return {
+ ...confirmState,
+ fiatTransactionAmount: fiatTransactionAmount || confirmState.fiatTransactionAmount,
+ ethTransactionAmount: ethTransactionAmount || confirmState.ethTransactionAmount,
+ }
+ case UPDATE_TRANSACTION_FEES:
+ const { fiatTransactionFee, ethTransactionFee } = action.payload
+ return {
+ ...confirmState,
+ fiatTransactionFee: fiatTransactionFee || confirmState.fiatTransactionFee,
+ ethTransactionFee: ethTransactionFee || confirmState.ethTransactionFee,
+ }
+ case UPDATE_TRANSACTION_TOTALS:
+ const { fiatTransactionTotal, ethTransactionTotal } = action.payload
+ return {
+ ...confirmState,
+ fiatTransactionTotal: fiatTransactionTotal || confirmState.fiatTransactionTotal,
+ ethTransactionTotal: ethTransactionTotal || confirmState.ethTransactionTotal,
+ }
+ case UPDATE_HEX_GAS_TOTAL:
+ return {
+ ...confirmState,
+ hexGasTotal: action.payload,
+ }
+ case UPDATE_TOKEN_PROPS:
+ const { tokenSymbol = '', tokenDecimals = '' } = action.payload
+ return {
+ ...confirmState,
+ tokenProps: {
+ ...confirmState.tokenProps,
+ tokenSymbol,
+ tokenDecimals,
+ },
+ }
+ case UPDATE_NONCE:
+ return {
+ ...confirmState,
+ nonce: action.payload,
+ }
+ case FETCH_METHOD_DATA_START:
+ return {
+ ...confirmState,
+ fetchingMethodData: true,
+ }
+ case FETCH_METHOD_DATA_END:
+ return {
+ ...confirmState,
+ fetchingMethodData: false,
+ }
+ case CLEAR_CONFIRM_TRANSACTION:
+ return initState
+ default:
+ return confirmState
+ }
+}
+
+// Action Creators
+export function updateTxData (txData) {
+ return {
+ type: UPDATE_TX_DATA,
+ payload: txData,
+ }
+}
+
+export function clearTxData () {
+ return {
+ type: CLEAR_TX_DATA,
+ }
+}
+
+export function updateTokenData (tokenData) {
+ return {
+ type: UPDATE_TOKEN_DATA,
+ payload: tokenData,
+ }
+}
+
+export function clearTokenData () {
+ return {
+ type: CLEAR_TOKEN_DATA,
+ }
+}
+
+export function updateMethodData (methodData) {
+ return {
+ type: UPDATE_METHOD_DATA,
+ payload: methodData,
+ }
+}
+
+export function clearMethodData () {
+ return {
+ type: CLEAR_METHOD_DATA,
+ }
+}
+
+export function updateTransactionAmounts (amounts) {
+ return {
+ type: UPDATE_TRANSACTION_AMOUNTS,
+ payload: amounts,
+ }
+}
+
+export function updateTransactionFees (fees) {
+ return {
+ type: UPDATE_TRANSACTION_FEES,
+ payload: fees,
+ }
+}
+
+export function updateTransactionTotals (totals) {
+ return {
+ type: UPDATE_TRANSACTION_TOTALS,
+ payload: totals,
+ }
+}
+
+export function updateHexGasTotal (hexGasTotal) {
+ return {
+ type: UPDATE_HEX_GAS_TOTAL,
+ payload: hexGasTotal,
+ }
+}
+
+export function updateTokenProps (tokenProps) {
+ return {
+ type: UPDATE_TOKEN_PROPS,
+ payload: tokenProps,
+ }
+}
+
+export function updateNonce (nonce) {
+ return {
+ type: UPDATE_NONCE,
+ payload: nonce,
+ }
+}
+
+export function setFetchingMethodData (isFetching) {
+ return {
+ type: isFetching ? FETCH_METHOD_DATA_START : FETCH_METHOD_DATA_END,
+ }
+}
+
+export function updateGasAndCalculate ({ gasLimit, gasPrice }) {
+ return (dispatch, getState) => {
+ const { confirmTransaction: { txData } } = getState()
+ const newTxData = {
+ ...txData,
+ txParams: {
+ ...txData.txParams,
+ gas: gasLimit,
+ gasPrice,
+ },
+ }
+
+ dispatch(updateTxDataAndCalculate(newTxData))
+ }
+}
+
+function increaseFromLastGasPrice (txData) {
+ const { lastGasPrice, txParams: { gasPrice: previousGasPrice } = {} } = txData
+
+ // Set the minimum to a 10% increase from the lastGasPrice.
+ const minimumGasPrice = increaseLastGasPrice(lastGasPrice)
+ const gasPriceBelowMinimum = hexGreaterThan(minimumGasPrice, previousGasPrice)
+ const gasPrice = (!previousGasPrice || gasPriceBelowMinimum) ? minimumGasPrice : previousGasPrice
+
+ return {
+ ...txData,
+ txParams: {
+ ...txData.txParams,
+ gasPrice,
+ },
+ }
+}
+
+export function updateTxDataAndCalculate (txData) {
+ return (dispatch, getState) => {
+ const state = getState()
+ const currentCurrency = currentCurrencySelector(state)
+ const conversionRate = conversionRateSelector(state)
+
+ dispatch(updateTxData(txData))
+
+ const { txParams: { value, gas: gasLimit = '0x0', gasPrice = '0x0' } = {} } = txData
+
+ const fiatTransactionAmount = getTransactionAmount({
+ value, toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2,
+ })
+ const ethTransactionAmount = getTransactionAmount({
+ value, toCurrency: 'ETH', conversionRate, numberOfDecimals: 6,
+ })
+
+ dispatch(updateTransactionAmounts({ fiatTransactionAmount, ethTransactionAmount }))
+
+ const hexGasTotal = getHexGasTotal({ gasLimit, gasPrice })
+
+ dispatch(updateHexGasTotal(hexGasTotal))
+
+ const fiatTransactionFee = getTransactionFee({
+ value: hexGasTotal,
+ toCurrency: currentCurrency,
+ numberOfDecimals: 2,
+ conversionRate,
+ })
+ const ethTransactionFee = getTransactionFee({
+ value: hexGasTotal,
+ toCurrency: 'ETH',
+ numberOfDecimals: 6,
+ conversionRate,
+ })
+
+ dispatch(updateTransactionFees({ fiatTransactionFee, ethTransactionFee }))
+
+ const fiatTransactionTotal = addFiat(fiatTransactionFee, fiatTransactionAmount)
+ const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount)
+
+ dispatch(updateTransactionTotals({ fiatTransactionTotal, ethTransactionTotal }))
+ }
+}
+
+export function setTransactionToConfirm (transactionId) {
+ return async (dispatch, getState) => {
+ const state = getState()
+ const unconfirmedTransactionsHash = unconfirmedTransactionsHashSelector(state)
+ const transaction = unconfirmedTransactionsHash[transactionId]
+
+ if (!transaction) {
+ console.error(`Transaction with id ${transactionId} not found`)
+ return
+ }
+
+ if (transaction.txParams) {
+ const { lastGasPrice } = transaction
+ const txData = lastGasPrice ? increaseFromLastGasPrice(transaction) : transaction
+ dispatch(updateTxDataAndCalculate(txData))
+
+ const { txParams } = transaction
+
+ if (txParams.data) {
+ const { tokens: existingTokens } = state
+ const { data, to: tokenAddress } = txParams
+
+ try {
+ dispatch(setFetchingMethodData(true))
+ const methodData = await getMethodData(data)
+ dispatch(updateMethodData(methodData))
+ dispatch(setFetchingMethodData(false))
+ } catch (error) {
+ dispatch(updateMethodData({}))
+ dispatch(setFetchingMethodData(false))
+ }
+
+ const tokenData = getTokenData(data)
+ dispatch(updateTokenData(tokenData))
+
+ try {
+ const tokenSymbolData = await getSymbolAndDecimals(tokenAddress, existingTokens) || {}
+ const { symbol: tokenSymbol = '', decimals: tokenDecimals = '' } = tokenSymbolData
+ dispatch(updateTokenProps({ tokenSymbol, tokenDecimals }))
+ } catch (error) {
+ dispatch(updateTokenProps({ tokenSymbol: '', tokenDecimals: '' }))
+ }
+ }
+
+ if (txParams.nonce) {
+ const nonce = conversionUtil(txParams.nonce, {
+ fromNumericBase: 'hex',
+ toNumericBase: 'dec',
+ })
+
+ dispatch(updateNonce(nonce))
+ }
+ } else {
+ dispatch(updateTxData(transaction))
+ }
+ }
+}
+
+export function clearConfirmTransaction () {
+ return {
+ type: CLEAR_CONFIRM_TRANSACTION,
+ }
+}
diff --git a/ui/app/ducks/send.duck.js b/ui/app/ducks/send.duck.js
index 055cc05c1..db01bbaa9 100644
--- a/ui/app/ducks/send.duck.js
+++ b/ui/app/ducks/send.duck.js
@@ -6,6 +6,7 @@ const CLOSE_FROM_DROPDOWN = 'metamask/send/CLOSE_FROM_DROPDOWN'
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
+const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
const initState = {
@@ -42,6 +43,8 @@ export default function reducer ({ send: sendState = initState }, action = {}) {
...action.value,
},
})
+ case RESET_SEND_STATE:
+ return extend({}, initState)
default:
return newState
}
@@ -70,3 +73,7 @@ export function updateSendErrors (errorObject) {
value: errorObject,
}
}
+
+export function resetSendState () {
+ return { type: RESET_SEND_STATE }
+}
diff --git a/ui/app/ducks/tests/confirm-transaction.duck.test.js b/ui/app/ducks/tests/confirm-transaction.duck.test.js
new file mode 100644
index 000000000..111674e33
--- /dev/null
+++ b/ui/app/ducks/tests/confirm-transaction.duck.test.js
@@ -0,0 +1,675 @@
+import assert from 'assert'
+import configureMockStore from 'redux-mock-store'
+import thunk from 'redux-thunk'
+
+import ConfirmTransactionReducer, * as actions from '../confirm-transaction.duck.js'
+
+const initialState = {
+ txData: {},
+ tokenData: {},
+ methodData: {},
+ tokenProps: {
+ tokenDecimals: '',
+ tokenSymbol: '',
+ },
+ fiatTransactionAmount: '',
+ fiatTransactionFee: '',
+ fiatTransactionTotal: '',
+ ethTransactionAmount: '',
+ ethTransactionFee: '',
+ ethTransactionTotal: '',
+ hexGasTotal: '',
+ nonce: '',
+ fetchingMethodData: false,
+}
+
+const UPDATE_TX_DATA = 'metamask/confirm-transaction/UPDATE_TX_DATA'
+const CLEAR_TX_DATA = 'metamask/confirm-transaction/CLEAR_TX_DATA'
+const UPDATE_TOKEN_DATA = 'metamask/confirm-transaction/UPDATE_TOKEN_DATA'
+const CLEAR_TOKEN_DATA = 'metamask/confirm-transaction/CLEAR_TOKEN_DATA'
+const UPDATE_METHOD_DATA = 'metamask/confirm-transaction/UPDATE_METHOD_DATA'
+const CLEAR_METHOD_DATA = 'metamask/confirm-transaction/CLEAR_METHOD_DATA'
+const UPDATE_TRANSACTION_AMOUNTS = 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS'
+const UPDATE_TRANSACTION_FEES = 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES'
+const UPDATE_TRANSACTION_TOTALS = 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS'
+const UPDATE_HEX_GAS_TOTAL = 'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL'
+const UPDATE_TOKEN_PROPS = 'metamask/confirm-transaction/UPDATE_TOKEN_PROPS'
+const UPDATE_NONCE = 'metamask/confirm-transaction/UPDATE_NONCE'
+const FETCH_METHOD_DATA_START = 'metamask/confirm-transaction/FETCH_METHOD_DATA_START'
+const FETCH_METHOD_DATA_END = 'metamask/confirm-transaction/FETCH_METHOD_DATA_END'
+const CLEAR_CONFIRM_TRANSACTION = 'metamask/confirm-transaction/CLEAR_CONFIRM_TRANSACTION'
+
+describe('Confirm Transaction Duck', () => {
+ describe('State changes', () => {
+ const mockState = {
+ confirmTransaction: {
+ txData: {
+ id: 1,
+ },
+ tokenData: {
+ name: 'abcToken',
+ },
+ methodData: {
+ name: 'approve',
+ },
+ tokenProps: {
+ tokenDecimals: '3',
+ tokenSymbol: 'ABC',
+ },
+ fiatTransactionAmount: '469.26',
+ fiatTransactionFee: '0.01',
+ fiatTransactionTotal: '1.000021',
+ ethTransactionAmount: '1',
+ ethTransactionFee: '0.000021',
+ ethTransactionTotal: '469.27',
+ hexGasTotal: '0x1319718a5000',
+ nonce: '0x0',
+ fetchingMethodData: false,
+ },
+ }
+
+ it('should initialize state', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer({}),
+ initialState
+ )
+ })
+
+ it('should return state unchanged if it does not match a dispatched actions type', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: 'someOtherAction',
+ value: 'someValue',
+ }),
+ { ...mockState.confirmTransaction },
+ )
+ })
+
+ it('should set txData when receiving a UPDATE_TX_DATA action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_TX_DATA,
+ payload: {
+ id: 2,
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ txData: {
+ ...mockState.confirmTransaction.txData,
+ id: 2,
+ },
+ }
+ )
+ })
+
+ it('should clear txData when receiving a CLEAR_TX_DATA action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: CLEAR_TX_DATA,
+ }),
+ {
+ ...mockState.confirmTransaction,
+ txData: {},
+ }
+ )
+ })
+
+ it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_TOKEN_DATA,
+ payload: {
+ name: 'defToken',
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ tokenData: {
+ ...mockState.confirmTransaction.tokenData,
+ name: 'defToken',
+ },
+ }
+ )
+ })
+
+ it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: CLEAR_TOKEN_DATA,
+ }),
+ {
+ ...mockState.confirmTransaction,
+ tokenData: {},
+ }
+ )
+ })
+
+ it('should set methodData when receiving a UPDATE_METHOD_DATA action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_METHOD_DATA,
+ payload: {
+ name: 'transferFrom',
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ methodData: {
+ ...mockState.confirmTransaction.methodData,
+ name: 'transferFrom',
+ },
+ }
+ )
+ })
+
+ it('should clear methodData when receiving a CLEAR_METHOD_DATA action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: CLEAR_METHOD_DATA,
+ }),
+ {
+ ...mockState.confirmTransaction,
+ methodData: {},
+ }
+ )
+ })
+
+ it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_TRANSACTION_AMOUNTS,
+ payload: {
+ fiatTransactionAmount: '123.45',
+ ethTransactionAmount: '.5',
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ fiatTransactionAmount: '123.45',
+ ethTransactionAmount: '.5',
+ }
+ )
+ })
+
+ it('should update transaction fees when receiving an UPDATE_TRANSACTION_FEES action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_TRANSACTION_FEES,
+ payload: {
+ fiatTransactionFee: '123.45',
+ ethTransactionFee: '.5',
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ fiatTransactionFee: '123.45',
+ ethTransactionFee: '.5',
+ }
+ )
+ })
+
+ it('should update transaction totals when receiving an UPDATE_TRANSACTION_TOTALS action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_TRANSACTION_TOTALS,
+ payload: {
+ fiatTransactionTotal: '123.45',
+ ethTransactionTotal: '.5',
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ fiatTransactionTotal: '123.45',
+ ethTransactionTotal: '.5',
+ }
+ )
+ })
+
+ it('should update hexGasTotal when receiving an UPDATE_HEX_GAS_TOTAL action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_HEX_GAS_TOTAL,
+ payload: '0x0',
+ }),
+ {
+ ...mockState.confirmTransaction,
+ hexGasTotal: '0x0',
+ }
+ )
+ })
+
+ it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_TOKEN_PROPS,
+ payload: {
+ tokenSymbol: 'DEF',
+ tokenDecimals: '1',
+ },
+ }),
+ {
+ ...mockState.confirmTransaction,
+ tokenProps: {
+ tokenSymbol: 'DEF',
+ tokenDecimals: '1',
+ },
+ }
+ )
+ })
+
+ it('should update nonce when receiving an UPDATE_NONCE action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: UPDATE_NONCE,
+ payload: '0x1',
+ }),
+ {
+ ...mockState.confirmTransaction,
+ nonce: '0x1',
+ }
+ )
+ })
+
+ it('should set fetchingMethodData to true when receiving a FETCH_METHOD_DATA_START action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: FETCH_METHOD_DATA_START,
+ }),
+ {
+ ...mockState.confirmTransaction,
+ fetchingMethodData: true,
+ }
+ )
+ })
+
+ it('should set fetchingMethodData to false when receiving a FETCH_METHOD_DATA_END action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer({ confirmTransaction: { fetchingMethodData: true } }, {
+ type: FETCH_METHOD_DATA_END,
+ }),
+ {
+ fetchingMethodData: false,
+ }
+ )
+ })
+
+ it('should clear confirmTransaction when receiving a FETCH_METHOD_DATA_END action', () => {
+ assert.deepEqual(
+ ConfirmTransactionReducer(mockState, {
+ type: CLEAR_CONFIRM_TRANSACTION,
+ }),
+ {
+ ...initialState,
+ }
+ )
+ })
+ })
+
+ describe('Single actions', () => {
+ it('should create an action to update txData', () => {
+ const txData = { test: 123 }
+ const expectedAction = {
+ type: UPDATE_TX_DATA,
+ payload: txData,
+ }
+
+ assert.deepEqual(
+ actions.updateTxData(txData),
+ expectedAction
+ )
+ })
+
+ it('should create an action to clear txData', () => {
+ const expectedAction = {
+ type: CLEAR_TX_DATA,
+ }
+
+ assert.deepEqual(
+ actions.clearTxData(),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update tokenData', () => {
+ const tokenData = { test: 123 }
+ const expectedAction = {
+ type: UPDATE_TOKEN_DATA,
+ payload: tokenData,
+ }
+
+ assert.deepEqual(
+ actions.updateTokenData(tokenData),
+ expectedAction
+ )
+ })
+
+ it('should create an action to clear tokenData', () => {
+ const expectedAction = {
+ type: CLEAR_TOKEN_DATA,
+ }
+
+ assert.deepEqual(
+ actions.clearTokenData(),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update methodData', () => {
+ const methodData = { test: 123 }
+ const expectedAction = {
+ type: UPDATE_METHOD_DATA,
+ payload: methodData,
+ }
+
+ assert.deepEqual(
+ actions.updateMethodData(methodData),
+ expectedAction
+ )
+ })
+
+ it('should create an action to clear methodData', () => {
+ const expectedAction = {
+ type: CLEAR_METHOD_DATA,
+ }
+
+ assert.deepEqual(
+ actions.clearMethodData(),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update transaction amounts', () => {
+ const transactionAmounts = { test: 123 }
+ const expectedAction = {
+ type: UPDATE_TRANSACTION_AMOUNTS,
+ payload: transactionAmounts,
+ }
+
+ assert.deepEqual(
+ actions.updateTransactionAmounts(transactionAmounts),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update transaction fees', () => {
+ const transactionFees = { test: 123 }
+ const expectedAction = {
+ type: UPDATE_TRANSACTION_FEES,
+ payload: transactionFees,
+ }
+
+ assert.deepEqual(
+ actions.updateTransactionFees(transactionFees),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update transaction totals', () => {
+ const transactionTotals = { test: 123 }
+ const expectedAction = {
+ type: UPDATE_TRANSACTION_TOTALS,
+ payload: transactionTotals,
+ }
+
+ assert.deepEqual(
+ actions.updateTransactionTotals(transactionTotals),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update hexGasTotal', () => {
+ const hexGasTotal = '0x0'
+ const expectedAction = {
+ type: UPDATE_HEX_GAS_TOTAL,
+ payload: hexGasTotal,
+ }
+
+ assert.deepEqual(
+ actions.updateHexGasTotal(hexGasTotal),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update tokenProps', () => {
+ const tokenProps = {
+ tokenDecimals: '1',
+ tokenSymbol: 'abc',
+ }
+ const expectedAction = {
+ type: UPDATE_TOKEN_PROPS,
+ payload: tokenProps,
+ }
+
+ assert.deepEqual(
+ actions.updateTokenProps(tokenProps),
+ expectedAction
+ )
+ })
+
+ it('should create an action to update nonce', () => {
+ const nonce = '0x1'
+ const expectedAction = {
+ type: UPDATE_NONCE,
+ payload: nonce,
+ }
+
+ assert.deepEqual(
+ actions.updateNonce(nonce),
+ expectedAction
+ )
+ })
+
+ it('should create an action to set fetchingMethodData to true', () => {
+ const expectedAction = {
+ type: FETCH_METHOD_DATA_START,
+ }
+
+ assert.deepEqual(
+ actions.setFetchingMethodData(true),
+ expectedAction
+ )
+ })
+
+ it('should create an action to set fetchingMethodData to false', () => {
+ const expectedAction = {
+ type: FETCH_METHOD_DATA_END,
+ }
+
+ assert.deepEqual(
+ actions.setFetchingMethodData(false),
+ expectedAction
+ )
+ })
+
+ it('should create an action to clear confirmTransaction', () => {
+ const expectedAction = {
+ type: CLEAR_CONFIRM_TRANSACTION,
+ }
+
+ assert.deepEqual(
+ actions.clearConfirmTransaction(),
+ expectedAction
+ )
+ })
+ })
+
+ describe('Thunk actions', done => {
+ it('updates txData and gas on an existing transaction in confirmTransaction', () => {
+ const mockState = {
+ metamask: {
+ conversionRate: 468.58,
+ currentCurrency: 'usd',
+ },
+ confirmTransaction: {
+ ethTransactionAmount: '1',
+ ethTransactionFee: '0.000021',
+ ethTransactionTotal: '1.000021',
+ fetchingMethodData: false,
+ fiatTransactionAmount: '469.26',
+ fiatTransactionFee: '0.01',
+ fiatTransactionTotal: '469.27',
+ hexGasTotal: '0x1319718a5000',
+ methodData: {},
+ nonce: '',
+ tokenData: {},
+ tokenProps: {
+ tokenDecimals: '',
+ tokenSymbol: '',
+ },
+ txData: {
+ estimatedGas: '0x5208',
+ gasLimitSpecified: false,
+ gasPriceSpecified: false,
+ history: [],
+ id: 2603411941761054,
+ loadingDefaults: false,
+ metamaskNetworkId: '3',
+ origin: 'faucet.metamask.io',
+ simpleSend: true,
+ status: 'unapproved',
+ time: 1530838113716,
+ },
+ },
+ }
+
+ const middlewares = [thunk]
+ const mockStore = configureMockStore(middlewares)
+ const store = mockStore(mockState)
+ const expectedActions = [
+ 'metamask/confirm-transaction/UPDATE_TX_DATA',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
+ 'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
+ ]
+
+ store.dispatch(actions.updateGasAndCalculate({ gasLimit: '0x2', gasPrice: '0x25' }))
+
+ const storeActions = store.getActions()
+ assert.equal(storeActions.length, expectedActions.length)
+ storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index]))
+ })
+
+ it('updates txData and updates gas values in confirmTransaction', () => {
+ const txData = {
+ estimatedGas: '0x5208',
+ gasLimitSpecified: false,
+ gasPriceSpecified: false,
+ history: [],
+ id: 2603411941761054,
+ loadingDefaults: false,
+ metamaskNetworkId: '3',
+ origin: 'faucet.metamask.io',
+ simpleSend: true,
+ status: 'unapproved',
+ time: 1530838113716,
+ txParams: {
+ from: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6',
+ gas: '0x33450',
+ gasPrice: '0x2540be400',
+ to: '0x81b7e08f65bdf5648606c89998a9cc8164397647',
+ value: '0xde0b6b3a7640000',
+ },
+ }
+ const mockState = {
+ metamask: {
+ conversionRate: 468.58,
+ currentCurrency: 'usd',
+ },
+ confirmTransaction: {
+ ethTransactionAmount: '1',
+ ethTransactionFee: '0.000021',
+ ethTransactionTotal: '1.000021',
+ fetchingMethodData: false,
+ fiatTransactionAmount: '469.26',
+ fiatTransactionFee: '0.01',
+ fiatTransactionTotal: '469.27',
+ hexGasTotal: '0x1319718a5000',
+ methodData: {},
+ nonce: '',
+ tokenData: {},
+ tokenProps: {
+ tokenDecimals: '',
+ tokenSymbol: '',
+ },
+ txData: {
+ ...txData,
+ txParams: {
+ ...txData.txParams,
+ },
+ },
+ },
+ }
+
+ const middlewares = [thunk]
+ const mockStore = configureMockStore(middlewares)
+ const store = mockStore(mockState)
+ const expectedActions = [
+ 'metamask/confirm-transaction/UPDATE_TX_DATA',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
+ 'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
+ ]
+
+ store.dispatch(actions.updateTxDataAndCalculate(txData))
+
+ const storeActions = store.getActions()
+ assert.equal(storeActions.length, expectedActions.length)
+ storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index]))
+ })
+
+ it('updates confirmTransaction transaction', done => {
+ const mockState = {
+ metamask: {
+ conversionRate: 468.58,
+ currentCurrency: 'usd',
+ network: '3',
+ unapprovedTxs: {
+ 2603411941761054: {
+ estimatedGas: '0x5208',
+ gasLimitSpecified: false,
+ gasPriceSpecified: false,
+ history: [],
+ id: 2603411941761054,
+ loadingDefaults: false,
+ metamaskNetworkId: '3',
+ origin: 'faucet.metamask.io',
+ simpleSend: true,
+ status: 'unapproved',
+ time: 1530838113716,
+ txParams: {
+ from: '0xc5ae6383e126f901dcb06131d97a88745bfa88d6',
+ gas: '0x33450',
+ gasPrice: '0x2540be400',
+ to: '0x81b7e08f65bdf5648606c89998a9cc8164397647',
+ value: '0xde0b6b3a7640000',
+ },
+ },
+ },
+ },
+ confirmTransaction: {},
+ }
+
+ const middlewares = [thunk]
+ const mockStore = configureMockStore(middlewares)
+ const store = mockStore(mockState)
+ const expectedActions = [
+ 'metamask/confirm-transaction/UPDATE_TX_DATA',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS',
+ 'metamask/confirm-transaction/UPDATE_HEX_GAS_TOTAL',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES',
+ 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS',
+ ]
+
+ store.dispatch(actions.setTransactionToConfirm(2603411941761054))
+ .then(() => {
+ const storeActions = store.getActions()
+ assert.equal(storeActions.length, expectedActions.length)
+ storeActions.forEach((action, index) => assert.equal(action.type, expectedActions[index]))
+ done()
+ })
+ })
+ })
+})
diff --git a/ui/app/ducks/tests/send-duck.test.js b/ui/app/ducks/tests/send-duck.test.js
index c06cf55d2..c101132d9 100644
--- a/ui/app/ducks/tests/send-duck.test.js
+++ b/ui/app/ducks/tests/send-duck.test.js
@@ -24,6 +24,7 @@ describe('Send Duck', () => {
const OPEN_TO_DROPDOWN = 'metamask/send/OPEN_TO_DROPDOWN'
const CLOSE_TO_DROPDOWN = 'metamask/send/CLOSE_TO_DROPDOWN'
const UPDATE_SEND_ERRORS = 'metamask/send/UPDATE_SEND_ERRORS'
+ const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
describe('SendReducer()', () => {
it('should initialize state', () => {
@@ -105,6 +106,15 @@ describe('Send Duck', () => {
})
)
})
+
+ it('should return the initial state in response to a RESET_SEND_STATE action', () => {
+ assert.deepEqual(
+ SendReducer(mockState, {
+ type: RESET_SEND_STATE,
+ }),
+ Object.assign({}, initState)
+ )
+ })
})
describe('openFromDropdown', () => {