mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
Use combineReducers for rootReducer (#7964)
This commit is contained in:
parent
7e04be9b58
commit
dea8f0f24d
@ -43,7 +43,9 @@ async function start () {
|
||||
// provide app state to append to error logs
|
||||
function getState () {
|
||||
// get app state
|
||||
const state = window.getCleanAppState()
|
||||
const state = window.getCleanAppState
|
||||
? window.getCleanAppState()
|
||||
: {}
|
||||
// remove unnecessary data
|
||||
delete state.localeMessages
|
||||
delete state.metamask.recentBlocks
|
||||
|
@ -13,11 +13,13 @@
|
||||
import log from 'loglevel'
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import { createStore, applyMiddleware } from 'redux'
|
||||
import thunkMiddleware from 'redux-thunk'
|
||||
import * as qs from 'qs'
|
||||
import Selector from './selector'
|
||||
import * as actions from '../ui/app/store/actions'
|
||||
import Root from '../ui/app/pages'
|
||||
import configureStore from '../ui/app/store/store'
|
||||
import rootReducer from '../ui/app/ducks'
|
||||
import MetamaskController from '../app/scripts/metamask-controller'
|
||||
import firstTimeState from '../app/scripts/first-time-state'
|
||||
import ExtensionPlatform from '../app/scripts/platforms/extension'
|
||||
@ -92,7 +94,14 @@ function modifyBackgroundConnection (backgroundConnectionModifier) {
|
||||
}
|
||||
|
||||
// parse opts
|
||||
const store = configureStore(firstState)
|
||||
const store = createStore(
|
||||
(state, action) =>
|
||||
(action.type === 'GLOBAL_FORCE_UPDATE'
|
||||
? action.value
|
||||
: rootReducer(state, action)),
|
||||
firstState,
|
||||
applyMiddleware(thunkMiddleware),
|
||||
)
|
||||
|
||||
// start app
|
||||
startApp()
|
||||
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"delegateCallCode": "0x606060405260e060020a60003504637bd703e8811461003157806390b98a111461005c578063f8b2cb4f1461008e575b005b6100b4600435600073f28c53067227848f8145355c455da5cfdd20e3136396e4ee3d6100da84610095565b6100c660043560243533600160a060020a03166000908152602081905260408120548290101561011f57506000610189565b6100b46004355b600160a060020a0381166000908152602081905260409020545b919050565b60408051918252519081900360200190f35b604080519115158252519081900360200190f35b60026040518360e060020a02815260040180838152602001828152602001925050506020604051808303818660325a03f4156100025750506040515191506100af9050565b33600160a060020a0390811660008181526020818152604080832080548890039055938716808352918490208054870190558351868152935191937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929081900390910190a35060015b9291505056"
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
const fakeWallet = {
|
||||
privKey: '0x123456788890abcdef',
|
||||
address: '0xfedcba0987654321',
|
||||
}
|
||||
const type = 'Simple Key Pair'
|
||||
|
||||
export default class MockSimpleKeychain {
|
||||
|
||||
static type () {
|
||||
return type
|
||||
}
|
||||
|
||||
constructor (opts) {
|
||||
this.type = type
|
||||
this.opts = opts || {}
|
||||
this.wallets = []
|
||||
}
|
||||
|
||||
serialize () {
|
||||
return [ fakeWallet.privKey ]
|
||||
}
|
||||
|
||||
deserialize (data) {
|
||||
if (!Array.isArray(data)) {
|
||||
throw new Error('Simple keychain deserialize requires a privKey array.')
|
||||
}
|
||||
this.wallets = [ fakeWallet ]
|
||||
}
|
||||
|
||||
addAccounts (n = 1) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
this.wallets.push(fakeWallet)
|
||||
}
|
||||
}
|
||||
|
||||
getAccounts () {
|
||||
return this.wallets.map(w => w.address)
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
import { applyMiddleware, createStore } from 'redux'
|
||||
import thunkMiddleware from 'redux-thunk'
|
||||
|
||||
const rootReducer = function () {}
|
||||
|
||||
export default configureStore
|
||||
|
||||
const createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore)
|
||||
|
||||
function configureStore (initialState) {
|
||||
return createStoreWithMiddleware(rootReducer, initialState)
|
||||
}
|
@ -10,9 +10,6 @@ describe('tx confirmation screen', function () {
|
||||
const txId = 1457634084250832
|
||||
const initialState = {
|
||||
appState: {
|
||||
currentView: {
|
||||
name: 'confTx',
|
||||
},
|
||||
},
|
||||
metamask: {
|
||||
unapprovedTxs: {
|
||||
@ -43,14 +40,12 @@ describe('tx confirmation screen', function () {
|
||||
done()
|
||||
})
|
||||
|
||||
it('creates COMPLETED_TX with the cancelled transaction ID', function (done) {
|
||||
store.dispatch(actions.cancelTx({ id: txId }))
|
||||
.then(() => {
|
||||
const storeActions = store.getActions()
|
||||
const completedTxAction = storeActions.find(({ type }) => type === actions.actionConstants.COMPLETED_TX)
|
||||
assert.equal(completedTxAction.value, txId)
|
||||
done()
|
||||
})
|
||||
it('creates COMPLETED_TX with the cancelled transaction ID', async function () {
|
||||
await store.dispatch(actions.cancelTx({ id: txId }))
|
||||
const storeActions = store.getActions()
|
||||
const completedTxAction = storeActions.find(({ type }) => type === actions.actionConstants.COMPLETED_TX)
|
||||
const { id } = completedTxAction.value
|
||||
assert.equal(id, txId)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1,9 +1,4 @@
|
||||
/* eslint-disable */
|
||||
// Used to inspect long objects
|
||||
// util.inspect({JSON}, false, null))
|
||||
// const util = require('util')
|
||||
import assert from 'assert'
|
||||
|
||||
import sinon from 'sinon'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import nock from 'nock'
|
||||
@ -14,14 +9,13 @@ import EthQuery from 'eth-query'
|
||||
import Eth from 'ethjs'
|
||||
import KeyringController from 'eth-keyring-controller'
|
||||
import { createTestProviderTools } from '../../../stub/provider'
|
||||
const provider = createTestProviderTools({ scaffold: {}}).provider
|
||||
|
||||
import enLocale from '../../../../app/_locales/en/messages.json'
|
||||
import * as actions from '../../../../ui/app/store/actions'
|
||||
import MetaMaskController from '../../../../app/scripts/metamask-controller'
|
||||
import firstTimeState from '../../localhostState'
|
||||
import devState from '../../../data/2-state.json'
|
||||
|
||||
const provider = createTestProviderTools({ scaffold: {} }).provider
|
||||
const middleware = [thunk]
|
||||
const mockStore = configureStore(middleware)
|
||||
|
||||
@ -133,9 +127,9 @@ describe('Actions', () => {
|
||||
await store.dispatch(actions.tryUnlockMetamask('test'))
|
||||
assert.fail('Should have thrown error')
|
||||
} catch (_) {
|
||||
const actions = store.getActions()
|
||||
const warning = actions.filter(action => action.type === 'DISPLAY_WARNING')
|
||||
const unlockFailed = actions.filter(action => action.type === 'UNLOCK_FAILED')
|
||||
const actions1 = store.getActions()
|
||||
const warning = actions1.filter(action => action.type === 'DISPLAY_WARNING')
|
||||
const unlockFailed = actions1.filter(action => action.type === 'UNLOCK_FAILED')
|
||||
assert.deepEqual(warning, displayWarningError)
|
||||
assert.deepEqual(unlockFailed, unlockFailedError)
|
||||
}
|
||||
@ -450,7 +444,7 @@ describe('Actions', () => {
|
||||
{ type: 'DISPLAY_WARNING', value: 'error' },
|
||||
]
|
||||
|
||||
checkHardwareStatusSpy.callsFake((deviceName, hdPath, callback) => {
|
||||
checkHardwareStatusSpy.callsFake((_, __, callback) => {
|
||||
callback(new Error('error'))
|
||||
})
|
||||
|
||||
@ -492,7 +486,7 @@ describe('Actions', () => {
|
||||
{ type: 'DISPLAY_WARNING', value: 'error' },
|
||||
]
|
||||
|
||||
forgetDeviceSpy.callsFake((deviceName, callback) => {
|
||||
forgetDeviceSpy.callsFake((_, callback) => {
|
||||
callback(new Error('error'))
|
||||
})
|
||||
|
||||
@ -534,7 +528,7 @@ describe('Actions', () => {
|
||||
{ type: 'DISPLAY_WARNING', value: 'error' },
|
||||
]
|
||||
|
||||
connectHardwareSpy.callsFake((deviceName, page, hdPath, callback) => {
|
||||
connectHardwareSpy.callsFake((_, __, ___, callback) => {
|
||||
callback(new Error('error'))
|
||||
})
|
||||
|
||||
@ -568,7 +562,7 @@ describe('Actions', () => {
|
||||
|
||||
})
|
||||
|
||||
it('shows loading indicator and displays error', async() => {
|
||||
it('shows loading indicator and displays error', async () => {
|
||||
const store = mockStore()
|
||||
|
||||
const expectedActions = [
|
||||
@ -576,7 +570,7 @@ describe('Actions', () => {
|
||||
{ type: 'DISPLAY_WARNING', value: 'error' },
|
||||
]
|
||||
|
||||
unlockHardwareWalletAccountSpy.callsFake((deviceName, page, hdPath, callback) => {
|
||||
unlockHardwareWalletAccountSpy.callsFake((_, __, ___, callback) => {
|
||||
callback(new Error('error'))
|
||||
})
|
||||
|
||||
@ -646,7 +640,9 @@ describe('Actions', () => {
|
||||
})
|
||||
|
||||
it('calls signMsg in background', () => {
|
||||
const store = mockStore()
|
||||
const store = mockStore({
|
||||
metamask: {},
|
||||
})
|
||||
|
||||
signMessageSpy = sinon.spy(background, 'signMessage')
|
||||
store.dispatch(actions.signMsg(msgParams))
|
||||
@ -655,7 +651,9 @@ describe('Actions', () => {
|
||||
})
|
||||
|
||||
it('errors when signMessage in background throws', async () => {
|
||||
const store = mockStore()
|
||||
const store = mockStore({
|
||||
metamask: {},
|
||||
})
|
||||
const expectedActions = [
|
||||
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
|
||||
{ type: 'UPDATE_METAMASK_STATE', value: undefined },
|
||||
@ -700,7 +698,9 @@ describe('Actions', () => {
|
||||
})
|
||||
|
||||
it('calls signPersonalMessage', () => {
|
||||
const store = mockStore()
|
||||
const store = mockStore({
|
||||
metamask: {},
|
||||
})
|
||||
|
||||
signPersonalMessageSpy = sinon.spy(background, 'signPersonalMessage')
|
||||
|
||||
@ -741,19 +741,19 @@ describe('Actions', () => {
|
||||
data: JSON.stringify({
|
||||
'types': {
|
||||
'EIP712Domain': [
|
||||
{'name': 'name', 'type': 'string'},
|
||||
{'name': 'version', 'type': 'string'},
|
||||
{'name': 'chainId', 'type': 'uint256'},
|
||||
{'name': 'verifyingContract', 'type': 'address'},
|
||||
{ 'name': 'name', 'type': 'string' },
|
||||
{ 'name': 'version', 'type': 'string' },
|
||||
{ 'name': 'chainId', 'type': 'uint256' },
|
||||
{ 'name': 'verifyingContract', 'type': 'address' },
|
||||
],
|
||||
'Person': [
|
||||
{'name': 'name', 'type': 'string'},
|
||||
{'name': 'wallet', 'type': 'address'},
|
||||
{ 'name': 'name', 'type': 'string' },
|
||||
{ 'name': 'wallet', 'type': 'address' },
|
||||
],
|
||||
'Mail': [
|
||||
{'name': 'from', 'type': 'Person'},
|
||||
{'name': 'to', 'type': 'Person'},
|
||||
{'name': 'contents', 'type': 'string'},
|
||||
{ 'name': 'from', 'type': 'Person' },
|
||||
{ 'name': 'to', 'type': 'Person' },
|
||||
{ 'name': 'contents', 'type': 'string' },
|
||||
],
|
||||
},
|
||||
'primaryType': 'Mail',
|
||||
@ -952,7 +952,7 @@ describe('Actions', () => {
|
||||
|
||||
const txData = { id: '1', status: 'unapproved', metamaskNetworkId: currentNetworkId, txParams: txParams }
|
||||
|
||||
beforeEach( async () => {
|
||||
beforeEach(async () => {
|
||||
await metamaskController.txController.txStateManager.addTx(txData)
|
||||
})
|
||||
|
||||
@ -976,7 +976,7 @@ describe('Actions', () => {
|
||||
const store = mockStore()
|
||||
|
||||
updateTransactionSpy = sinon.stub(background, 'updateTransaction')
|
||||
updateTransactionSpy.callsFake((res, callback) => {
|
||||
updateTransactionSpy.callsFake((_, callback) => {
|
||||
callback(new Error('error'))
|
||||
})
|
||||
|
||||
@ -1347,7 +1347,7 @@ describe('Actions', () => {
|
||||
nock('https://shapeshift.io')
|
||||
.defaultReplyHeaders({ 'access-control-allow-origin': '*' })
|
||||
.get('/marketinfo/btc_eth')
|
||||
.reply(200, {pair: 'BTC_ETH', rate: 25.68289016, minerFee: 0.00176, limit: 0.67748474, minimum: 0.00013569, maxLimit: 0.67758573})
|
||||
.reply(200, { pair: 'BTC_ETH', rate: 25.68289016, minerFee: 0.00176, limit: 0.67748474, minimum: 0.00013569, maxLimit: 0.67758573 })
|
||||
|
||||
nock('https://shapeshift.io')
|
||||
.defaultReplyHeaders({ 'access-control-allow-origin': '*' })
|
||||
@ -1515,7 +1515,7 @@ describe('Actions', () => {
|
||||
|
||||
const expectedActions = [
|
||||
{ type: 'SHOW_LOADING_INDICATION', value: undefined },
|
||||
{ type: 'SET_CURRENT_LOCALE', value: { locale: 'en', messages: enLocale }},
|
||||
{ type: 'SET_CURRENT_LOCALE', value: { locale: 'en', messages: enLocale } },
|
||||
{ type: 'HIDE_LOADING_INDICATION' },
|
||||
]
|
||||
|
||||
|
@ -7,13 +7,11 @@ const actions = actionConstants
|
||||
describe('App State', () => {
|
||||
|
||||
const metamaskState = {
|
||||
metamask: {
|
||||
selectedAddress: '0xAddress',
|
||||
identities: {
|
||||
'0xAddress': {
|
||||
name: 'account 1',
|
||||
address: '0xAddress',
|
||||
},
|
||||
selectedAddress: '0xAddress',
|
||||
identities: {
|
||||
'0xAddress': {
|
||||
name: 'account 1',
|
||||
address: '0xAddress',
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -24,7 +22,7 @@ describe('App State', () => {
|
||||
assert(initState)
|
||||
})
|
||||
|
||||
it('sets networkd dropdown to true', () => {
|
||||
it('sets networkDropdownOpen dropdown to true', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.NETWORK_DROPDOWN_OPEN,
|
||||
})
|
||||
@ -32,7 +30,7 @@ describe('App State', () => {
|
||||
assert.equal(state.networkDropdownOpen, true)
|
||||
})
|
||||
|
||||
it('sets networkd dropdown to false', () => {
|
||||
it('sets networkDropdownOpen dropdown to false', () => {
|
||||
const dropdown = { networkDropdowopen: true }
|
||||
const state = { ...metamaskState, ...dropdown }
|
||||
const newState = reduceApp(state, {
|
||||
@ -129,7 +127,7 @@ describe('App State', () => {
|
||||
assert.equal(newState.modal.modalState.name, null)
|
||||
})
|
||||
|
||||
it('tansitions forwards', () => {
|
||||
it('transitions forwards', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.TRANSITION_FORWARD,
|
||||
})
|
||||
@ -137,22 +135,11 @@ describe('App State', () => {
|
||||
assert.equal(state.transForward, true)
|
||||
})
|
||||
|
||||
it('sets forgot password', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.FORGOT_PASSWORD,
|
||||
value: true,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'restoreVault')
|
||||
})
|
||||
|
||||
it('shows send token page', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.SHOW_SEND_TOKEN_PAGE,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'sendToken')
|
||||
assert.equal(state.currentView.context, '0xAddress')
|
||||
assert.equal(state.transForward, true)
|
||||
assert.equal(state.warning, null)
|
||||
})
|
||||
@ -173,8 +160,6 @@ describe('App State', () => {
|
||||
type: actions.LOCK_METAMASK,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'accountDetail')
|
||||
assert.equal(state.currentView.context, '0xAddress')
|
||||
assert.equal(state.transForward, false)
|
||||
assert.equal(state.warning, null)
|
||||
})
|
||||
@ -184,7 +169,6 @@ describe('App State', () => {
|
||||
type: actions.GO_HOME,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'accountDetail')
|
||||
assert.equal(state.accountDetail.subview, 'transactions')
|
||||
assert.equal(state.accountDetail.accountExport, 'none')
|
||||
assert.equal(state.accountDetail.privateKey, '')
|
||||
@ -199,8 +183,6 @@ describe('App State', () => {
|
||||
value: 'context address',
|
||||
})
|
||||
assert.equal(state.forgottenPassword, null) // default
|
||||
assert.equal(state.currentView.name, 'accountDetail')
|
||||
assert.equal(state.currentView.context, 'context address')
|
||||
assert.equal(state.accountDetail.subview, 'transactions') // default
|
||||
assert.equal(state.accountDetail.accountExport, 'none') // default
|
||||
assert.equal(state.accountDetail.privateKey, '') // default
|
||||
@ -213,7 +195,6 @@ describe('App State', () => {
|
||||
type: actions.SHOW_ACCOUNTS_PAGE,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'accounts')
|
||||
assert.equal(state.transForward, true)
|
||||
assert.equal(state.isLoading, false)
|
||||
assert.equal(state.warning, null)
|
||||
@ -232,17 +213,14 @@ describe('App State', () => {
|
||||
},
|
||||
},
|
||||
}
|
||||
const oldState = {
|
||||
metamask: { ...metamaskState.metamask, ...txs },
|
||||
}
|
||||
const oldState = { ...metamaskState, ...txs }
|
||||
const state = reduceApp(oldState, {
|
||||
type: actions.SHOW_CONF_TX_PAGE,
|
||||
id: 2,
|
||||
transForward: false,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'confTx')
|
||||
assert.equal(state.currentView.context, 1)
|
||||
assert.equal(state.txId, 2)
|
||||
assert.equal(state.transForward, false)
|
||||
assert.equal(state.warning, null)
|
||||
assert.equal(state.isLoading, false)
|
||||
@ -261,17 +239,16 @@ describe('App State', () => {
|
||||
},
|
||||
}
|
||||
|
||||
const oldState = {
|
||||
metamask: { ...metamaskState, ...txs },
|
||||
}
|
||||
const oldState = { ...metamaskState, ...txs }
|
||||
|
||||
const state = reduceApp(oldState, {
|
||||
type: actions.COMPLETED_TX,
|
||||
value: 1,
|
||||
value: {
|
||||
id: 1,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'confTx')
|
||||
assert.equal(state.currentView.context, 0)
|
||||
assert.equal(state.txId, null)
|
||||
assert.equal(state.transForward, false)
|
||||
assert.equal(state.warning, null)
|
||||
})
|
||||
@ -279,25 +256,17 @@ describe('App State', () => {
|
||||
it('returns to account detail page when no unconf actions completed tx', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.COMPLETED_TX,
|
||||
value: {
|
||||
unconfirmedActionsCount: 0,
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'accountDetail')
|
||||
assert.equal(state.currentView.context, '0xAddress')
|
||||
assert.equal(state.transForward, false)
|
||||
assert.equal(state.warning, null)
|
||||
assert.equal(state.accountDetail.subview, 'transactions')
|
||||
|
||||
})
|
||||
|
||||
it('sets error message in confTx view', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.TRANSACTION_ERROR,
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'confTx')
|
||||
assert.equal(state.currentView.errorMessage, 'There was a problem submitting this transaction.')
|
||||
})
|
||||
|
||||
it('sets default warning when unlock fails', () => {
|
||||
const state = reduceApp(metamaskState, {
|
||||
type: actions.UNLOCK_FAILED,
|
||||
@ -423,13 +392,11 @@ describe('App State', () => {
|
||||
}
|
||||
|
||||
const appState = {
|
||||
appState: {
|
||||
buyView: {
|
||||
buyAddress: '0xAddress',
|
||||
amount: '12.00',
|
||||
formView: {
|
||||
coinOptions,
|
||||
},
|
||||
buyView: {
|
||||
buyAddress: '0xAddress',
|
||||
amount: '12.00',
|
||||
formView: {
|
||||
coinOptions,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -477,10 +444,8 @@ describe('App State', () => {
|
||||
|
||||
it('shows qr view', () => {
|
||||
const appState = {
|
||||
appState: {
|
||||
currentView: {
|
||||
context: 'accounts',
|
||||
},
|
||||
currentView: {
|
||||
context: 'accounts',
|
||||
},
|
||||
}
|
||||
|
||||
@ -493,8 +458,6 @@ describe('App State', () => {
|
||||
},
|
||||
})
|
||||
|
||||
assert.equal(state.currentView.name, 'qr')
|
||||
assert.equal(state.currentView.context, 'accounts')
|
||||
assert.equal(state.transForward, true)
|
||||
assert.equal(state.Qr.message, 'message')
|
||||
assert.equal(state.Qr.data, 'data')
|
||||
|
@ -1,13 +1,11 @@
|
||||
import assert from 'assert'
|
||||
import reduceMetamask from '../../../../../ui/app/ducks/metamask/metamask'
|
||||
import { actionConstants } from '../../../../../ui/app/store/actions'
|
||||
|
||||
const actions = actionConstants
|
||||
import { actionConstants as actions } from '../../../../../ui/app/store/actions'
|
||||
|
||||
describe('MetaMask Reducers', () => {
|
||||
|
||||
it('init state', () => {
|
||||
const initState = reduceMetamask({ metamask: {} }, {})
|
||||
const initState = reduceMetamask(undefined, {})
|
||||
assert(initState)
|
||||
})
|
||||
|
||||
@ -24,11 +22,9 @@ describe('MetaMask Reducers', () => {
|
||||
|
||||
it('locks MetaMask', () => {
|
||||
const unlockMetaMaskState = {
|
||||
metamask: {
|
||||
isUnlocked: true,
|
||||
isInitialzed: false,
|
||||
selectedAddress: 'test address',
|
||||
},
|
||||
isUnlocked: true,
|
||||
isInitialzed: false,
|
||||
selectedAddress: 'test address',
|
||||
}
|
||||
const lockMetaMask = reduceMetamask(unlockMetaMaskState, {
|
||||
type: actions.LOCK_METAMASK,
|
||||
@ -55,70 +51,6 @@ describe('MetaMask Reducers', () => {
|
||||
assert.equal(state.provider.type, 'provider type')
|
||||
})
|
||||
|
||||
describe('CompletedTx', () => {
|
||||
const oldState = {
|
||||
metamask: {
|
||||
unapprovedTxs: {
|
||||
1: {
|
||||
id: 1,
|
||||
time: 1538495996507,
|
||||
status: 'unapproved',
|
||||
metamaskNetworkId: 4,
|
||||
loadingDefaults: false,
|
||||
txParams: {
|
||||
from: '0xAddress',
|
||||
to: '0xAddress2',
|
||||
value: '0x16345785d8a0000',
|
||||
gas: '0x5208',
|
||||
gasPrice: '0x3b9aca00',
|
||||
},
|
||||
type: 'standard',
|
||||
},
|
||||
2: {
|
||||
test: 'Should persist',
|
||||
},
|
||||
},
|
||||
unapprovedMsgs: {
|
||||
1: {
|
||||
id: 2,
|
||||
msgParams: {
|
||||
from: '0xAddress',
|
||||
data: '0xData',
|
||||
origin: 'test origin',
|
||||
},
|
||||
time: 1538498521717,
|
||||
status: 'unapproved',
|
||||
type: 'eth_sign',
|
||||
},
|
||||
2: {
|
||||
test: 'Should Persist',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
it('removes tx from new state if completed in action.', () => {
|
||||
|
||||
const state = reduceMetamask(oldState, {
|
||||
type: actions.COMPLETED_TX,
|
||||
id: 1,
|
||||
})
|
||||
|
||||
assert.equal(Object.keys(state.unapprovedTxs).length, 1)
|
||||
assert.equal(state.unapprovedTxs[2].test, 'Should persist')
|
||||
})
|
||||
|
||||
it('removes msg from new state if completed id in action', () => {
|
||||
const state = reduceMetamask(oldState, {
|
||||
type: actions.COMPLETED_TX,
|
||||
id: 1,
|
||||
})
|
||||
|
||||
assert.equal(Object.keys(state.unapprovedMsgs).length, 1)
|
||||
assert.equal(state.unapprovedTxs[2].test, 'Should persist')
|
||||
})
|
||||
})
|
||||
|
||||
it('shows account detail', () => {
|
||||
|
||||
const state = reduceMetamask({}, {
|
||||
@ -342,14 +274,12 @@ describe('MetaMask Reducers', () => {
|
||||
|
||||
it('updates value of tx by id', () => {
|
||||
const oldState = {
|
||||
metamask: {
|
||||
selectedAddressTxList: [
|
||||
{
|
||||
id: 1,
|
||||
txParams: 'foo',
|
||||
},
|
||||
],
|
||||
},
|
||||
selectedAddressTxList: [
|
||||
{
|
||||
id: 1,
|
||||
txParams: 'foo',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
const state = reduceMetamask(oldState, {
|
||||
|
@ -1,33 +1,9 @@
|
||||
import txHelper from '../../../lib/tx-helper'
|
||||
import log from 'loglevel'
|
||||
import { actionConstants } from '../../store/actions'
|
||||
|
||||
const actions = actionConstants
|
||||
import { actionConstants as actions } from '../../store/actions'
|
||||
|
||||
// Actions
|
||||
const SET_THREEBOX_LAST_UPDATED = 'metamask/app/SET_THREEBOX_LAST_UPDATED'
|
||||
|
||||
export default function reduceApp (state, action) {
|
||||
log.debug('App Reducer got ' + action.type)
|
||||
// clone and defaults
|
||||
const selectedAddress = state.metamask.selectedAddress
|
||||
const hasUnconfActions = checkUnconfActions(state)
|
||||
let name = 'accounts'
|
||||
if (selectedAddress) {
|
||||
name = 'accountDetail'
|
||||
}
|
||||
|
||||
if (hasUnconfActions) {
|
||||
log.debug('pending txs detected, defaulting to conf-tx view.')
|
||||
name = 'confTx'
|
||||
}
|
||||
|
||||
const defaultView = {
|
||||
name,
|
||||
detailView: null,
|
||||
context: selectedAddress,
|
||||
}
|
||||
|
||||
export default function reduceApp (state = {}, action) {
|
||||
// default state
|
||||
const appState = Object.assign({
|
||||
shouldClose: false,
|
||||
@ -52,7 +28,6 @@ export default function reduceApp (state, action) {
|
||||
alertMessage: null,
|
||||
qrCodeData: null,
|
||||
networkDropdownOpen: false,
|
||||
currentView: defaultView,
|
||||
accountDetail: {
|
||||
subview: 'transactions',
|
||||
},
|
||||
@ -79,7 +54,7 @@ export default function reduceApp (state, action) {
|
||||
requestAccountTabs: {},
|
||||
openMetaMaskTabs: {},
|
||||
currentWindowTab: {},
|
||||
}, state.appState)
|
||||
}, state)
|
||||
|
||||
switch (action.type) {
|
||||
// dropdown methods
|
||||
@ -157,7 +132,7 @@ export default function reduceApp (state, action) {
|
||||
return {
|
||||
...appState,
|
||||
modal: Object.assign(
|
||||
state.appState.modal,
|
||||
appState.modal,
|
||||
{ open: false },
|
||||
{ modalState: { name: null, props: {} } },
|
||||
{ previousModalState: appState.modal.modalState },
|
||||
@ -172,26 +147,14 @@ export default function reduceApp (state, action) {
|
||||
}
|
||||
|
||||
case actions.FORGOT_PASSWORD:
|
||||
const newState = {
|
||||
return {
|
||||
...appState,
|
||||
forgottenPassword: action.value,
|
||||
}
|
||||
|
||||
if (action.value) {
|
||||
newState.currentView = {
|
||||
name: 'restoreVault',
|
||||
}
|
||||
}
|
||||
|
||||
return newState
|
||||
|
||||
case actions.SHOW_SEND_TOKEN_PAGE:
|
||||
return {
|
||||
...appState,
|
||||
currentView: {
|
||||
name: 'sendToken',
|
||||
context: appState.currentView.context,
|
||||
},
|
||||
transForward: true,
|
||||
warning: null,
|
||||
}
|
||||
@ -211,7 +174,6 @@ export default function reduceApp (state, action) {
|
||||
case actions.LOCK_METAMASK:
|
||||
return {
|
||||
...appState,
|
||||
currentView: defaultView,
|
||||
transForward: false,
|
||||
warning: null,
|
||||
}
|
||||
@ -221,10 +183,6 @@ export default function reduceApp (state, action) {
|
||||
case actions.GO_HOME:
|
||||
return {
|
||||
...appState,
|
||||
currentView: {
|
||||
...appState.currentView,
|
||||
name: 'accountDetail',
|
||||
},
|
||||
accountDetail: {
|
||||
subview: 'transactions',
|
||||
accountExport: 'none',
|
||||
@ -238,10 +196,6 @@ export default function reduceApp (state, action) {
|
||||
return {
|
||||
...appState,
|
||||
forgottenPassword: appState.forgottenPassword ? !appState.forgottenPassword : null,
|
||||
currentView: {
|
||||
name: 'accountDetail',
|
||||
context: action.value,
|
||||
},
|
||||
accountDetail: {
|
||||
subview: 'transactions',
|
||||
accountExport: 'none',
|
||||
@ -253,9 +207,6 @@ export default function reduceApp (state, action) {
|
||||
case actions.SHOW_ACCOUNTS_PAGE:
|
||||
return {
|
||||
...appState,
|
||||
currentView: {
|
||||
name: 'accounts',
|
||||
},
|
||||
transForward: true,
|
||||
isLoading: false,
|
||||
warning: null,
|
||||
@ -266,44 +217,28 @@ export default function reduceApp (state, action) {
|
||||
case actions.SHOW_CONF_TX_PAGE:
|
||||
return {
|
||||
...appState,
|
||||
currentView: {
|
||||
name: 'confTx',
|
||||
context: action.id ? indexForPending(state, action.id) : 0,
|
||||
},
|
||||
txId: action.id,
|
||||
transForward: action.transForward,
|
||||
warning: null,
|
||||
isLoading: false,
|
||||
}
|
||||
|
||||
case actions.COMPLETED_TX:
|
||||
log.debug('reducing COMPLETED_TX for tx ' + action.value)
|
||||
const otherUnconfActions = getUnconfActionList(state)
|
||||
.filter(tx => tx.id !== action.value)
|
||||
const hasOtherUnconfActions = otherUnconfActions.length > 0
|
||||
|
||||
if (hasOtherUnconfActions) {
|
||||
log.debug('reducer detected txs - rendering confTx view')
|
||||
if (action.value.unconfirmedActionsCount > 0) {
|
||||
return {
|
||||
...appState,
|
||||
transForward: false,
|
||||
currentView: {
|
||||
name: 'confTx',
|
||||
context: 0,
|
||||
},
|
||||
txId: null,
|
||||
warning: null,
|
||||
}
|
||||
} else {
|
||||
log.debug('attempting to close popup')
|
||||
return {
|
||||
...appState,
|
||||
// indicate notification should close
|
||||
shouldClose: true,
|
||||
transForward: false,
|
||||
warning: null,
|
||||
currentView: {
|
||||
name: 'accountDetail',
|
||||
context: state.metamask.selectedAddress,
|
||||
},
|
||||
txId: null,
|
||||
accountDetail: {
|
||||
subview: 'transactions',
|
||||
},
|
||||
@ -313,10 +248,6 @@ export default function reduceApp (state, action) {
|
||||
case actions.TRANSACTION_ERROR:
|
||||
return {
|
||||
...appState,
|
||||
currentView: {
|
||||
name: 'confTx',
|
||||
errorMessage: 'There was a problem submitting this transaction.',
|
||||
},
|
||||
}
|
||||
|
||||
case actions.UNLOCK_FAILED:
|
||||
@ -421,10 +352,6 @@ export default function reduceApp (state, action) {
|
||||
case actions.SHOW_QR_VIEW:
|
||||
return {
|
||||
...appState,
|
||||
currentView: {
|
||||
name: 'qr',
|
||||
context: appState.currentView.context,
|
||||
},
|
||||
transForward: true,
|
||||
Qr: {
|
||||
message: action.value.message,
|
||||
@ -525,25 +452,3 @@ export function setThreeBoxLastUpdated (lastUpdated) {
|
||||
value: lastUpdated,
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
function checkUnconfActions (state) {
|
||||
const unconfActionList = getUnconfActionList(state)
|
||||
const hasUnconfActions = unconfActionList.length > 0
|
||||
return hasUnconfActions
|
||||
}
|
||||
|
||||
function getUnconfActionList (state) {
|
||||
const { unapprovedTxs, unapprovedMsgs,
|
||||
unapprovedPersonalMsgs, unapprovedTypedMessages, network } = state.metamask
|
||||
|
||||
const unconfActionList = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network)
|
||||
return unconfActionList
|
||||
}
|
||||
|
||||
function indexForPending (state, txId) {
|
||||
const unconfTxList = getUnconfActionList(state)
|
||||
const match = unconfTxList.find((tx) => tx.id === txId)
|
||||
const index = unconfTxList.indexOf(match)
|
||||
return index
|
||||
}
|
||||
|
@ -66,102 +66,102 @@ const initState = {
|
||||
}
|
||||
|
||||
// Reducer
|
||||
export default function reducer ({ confirmTransaction: confirmState = initState }, action = {}) {
|
||||
export default function reducer (state = initState, action = {}) {
|
||||
switch (action.type) {
|
||||
case UPDATE_TX_DATA:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
txData: {
|
||||
...action.payload,
|
||||
},
|
||||
}
|
||||
case CLEAR_TX_DATA:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
txData: {},
|
||||
}
|
||||
case UPDATE_TOKEN_DATA:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
tokenData: {
|
||||
...action.payload,
|
||||
},
|
||||
}
|
||||
case CLEAR_TOKEN_DATA:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
tokenData: {},
|
||||
}
|
||||
case UPDATE_METHOD_DATA:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
methodData: {
|
||||
...action.payload,
|
||||
},
|
||||
}
|
||||
case CLEAR_METHOD_DATA:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
methodData: {},
|
||||
}
|
||||
case UPDATE_TRANSACTION_AMOUNTS:
|
||||
const { fiatTransactionAmount, ethTransactionAmount, hexTransactionAmount } = action.payload
|
||||
return {
|
||||
...confirmState,
|
||||
fiatTransactionAmount: fiatTransactionAmount || confirmState.fiatTransactionAmount,
|
||||
ethTransactionAmount: ethTransactionAmount || confirmState.ethTransactionAmount,
|
||||
hexTransactionAmount: hexTransactionAmount || confirmState.hexTransactionAmount,
|
||||
...state,
|
||||
fiatTransactionAmount: fiatTransactionAmount || state.fiatTransactionAmount,
|
||||
ethTransactionAmount: ethTransactionAmount || state.ethTransactionAmount,
|
||||
hexTransactionAmount: hexTransactionAmount || state.hexTransactionAmount,
|
||||
}
|
||||
case UPDATE_TRANSACTION_FEES:
|
||||
const { fiatTransactionFee, ethTransactionFee, hexTransactionFee } = action.payload
|
||||
return {
|
||||
...confirmState,
|
||||
fiatTransactionFee: fiatTransactionFee || confirmState.fiatTransactionFee,
|
||||
ethTransactionFee: ethTransactionFee || confirmState.ethTransactionFee,
|
||||
hexTransactionFee: hexTransactionFee || confirmState.hexTransactionFee,
|
||||
...state,
|
||||
fiatTransactionFee: fiatTransactionFee || state.fiatTransactionFee,
|
||||
ethTransactionFee: ethTransactionFee || state.ethTransactionFee,
|
||||
hexTransactionFee: hexTransactionFee || state.hexTransactionFee,
|
||||
}
|
||||
case UPDATE_TRANSACTION_TOTALS:
|
||||
const { fiatTransactionTotal, ethTransactionTotal, hexTransactionTotal } = action.payload
|
||||
return {
|
||||
...confirmState,
|
||||
fiatTransactionTotal: fiatTransactionTotal || confirmState.fiatTransactionTotal,
|
||||
ethTransactionTotal: ethTransactionTotal || confirmState.ethTransactionTotal,
|
||||
hexTransactionTotal: hexTransactionTotal || confirmState.hexTransactionTotal,
|
||||
...state,
|
||||
fiatTransactionTotal: fiatTransactionTotal || state.fiatTransactionTotal,
|
||||
ethTransactionTotal: ethTransactionTotal || state.ethTransactionTotal,
|
||||
hexTransactionTotal: hexTransactionTotal || state.hexTransactionTotal,
|
||||
}
|
||||
case UPDATE_TOKEN_PROPS:
|
||||
const { tokenSymbol = '', tokenDecimals = '' } = action.payload
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
tokenProps: {
|
||||
...confirmState.tokenProps,
|
||||
...state.tokenProps,
|
||||
tokenSymbol,
|
||||
tokenDecimals,
|
||||
},
|
||||
}
|
||||
case UPDATE_NONCE:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
nonce: action.payload,
|
||||
}
|
||||
case UPDATE_TO_SMART_CONTRACT:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
toSmartContract: action.payload,
|
||||
}
|
||||
case FETCH_DATA_START:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
fetchingData: true,
|
||||
}
|
||||
case FETCH_DATA_END:
|
||||
return {
|
||||
...confirmState,
|
||||
...state,
|
||||
fetchingData: false,
|
||||
}
|
||||
case CLEAR_CONFIRM_TRANSACTION:
|
||||
return initState
|
||||
default:
|
||||
return confirmState
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,40 +46,35 @@ const CLEAR_CONFIRM_TRANSACTION = 'metamask/confirm-transaction/CLEAR_CONFIRM_TR
|
||||
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',
|
||||
hexTransactionAmount: '',
|
||||
hexTransactionFee: '0x1319718a5000',
|
||||
hexTransactionTotal: '',
|
||||
nonce: '0x0',
|
||||
toSmartContract: false,
|
||||
fetchingData: false,
|
||||
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',
|
||||
hexTransactionAmount: '',
|
||||
hexTransactionFee: '0x1319718a5000',
|
||||
hexTransactionTotal: '',
|
||||
nonce: '0x0',
|
||||
toSmartContract: false,
|
||||
fetchingData: false,
|
||||
}
|
||||
|
||||
it('should initialize state', () => {
|
||||
assert.deepEqual(
|
||||
ConfirmTransactionReducer({}),
|
||||
initialState
|
||||
)
|
||||
assert.deepEqual(ConfirmTransactionReducer(undefined, {}), initialState)
|
||||
})
|
||||
|
||||
it('should return state unchanged if it does not match a dispatched actions type', () => {
|
||||
@ -88,7 +83,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
type: 'someOtherAction',
|
||||
value: 'someValue',
|
||||
}),
|
||||
{ ...mockState.confirmTransaction },
|
||||
{ ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -101,9 +96,9 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
txData: {
|
||||
...mockState.confirmTransaction.txData,
|
||||
...mockState.txData,
|
||||
id: 2,
|
||||
},
|
||||
}
|
||||
@ -116,7 +111,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
type: CLEAR_TX_DATA,
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
txData: {},
|
||||
}
|
||||
)
|
||||
@ -131,9 +126,9 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
tokenData: {
|
||||
...mockState.confirmTransaction.tokenData,
|
||||
...mockState.tokenData,
|
||||
name: 'defToken',
|
||||
},
|
||||
}
|
||||
@ -146,7 +141,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
type: CLEAR_TOKEN_DATA,
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
tokenData: {},
|
||||
}
|
||||
)
|
||||
@ -161,9 +156,9 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
methodData: {
|
||||
...mockState.confirmTransaction.methodData,
|
||||
...mockState.methodData,
|
||||
name: 'transferFrom',
|
||||
},
|
||||
}
|
||||
@ -176,7 +171,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
type: CLEAR_METHOD_DATA,
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
methodData: {},
|
||||
}
|
||||
)
|
||||
@ -193,7 +188,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
fiatTransactionAmount: '123.45',
|
||||
ethTransactionAmount: '.5',
|
||||
hexTransactionAmount: '0x1',
|
||||
@ -212,7 +207,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
fiatTransactionFee: '123.45',
|
||||
ethTransactionFee: '.5',
|
||||
hexTransactionFee: '0x1',
|
||||
@ -231,7 +226,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
fiatTransactionTotal: '123.45',
|
||||
ethTransactionTotal: '.5',
|
||||
hexTransactionTotal: '0x1',
|
||||
@ -249,7 +244,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
},
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
tokenProps: {
|
||||
tokenSymbol: 'DEF',
|
||||
tokenDecimals: '1',
|
||||
@ -265,7 +260,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
payload: '0x1',
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
nonce: '0x1',
|
||||
}
|
||||
)
|
||||
@ -278,7 +273,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
payload: true,
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
toSmartContract: true,
|
||||
}
|
||||
)
|
||||
@ -290,7 +285,7 @@ describe('Confirm Transaction Duck', () => {
|
||||
type: FETCH_DATA_START,
|
||||
}),
|
||||
{
|
||||
...mockState.confirmTransaction,
|
||||
...mockState,
|
||||
fetchingData: true,
|
||||
}
|
||||
)
|
||||
@ -298,24 +293,13 @@ describe('Confirm Transaction Duck', () => {
|
||||
|
||||
it('should set fetchingData to false when receiving a FETCH_DATA_END action', () => {
|
||||
assert.deepEqual(
|
||||
ConfirmTransactionReducer({ confirmTransaction: { fetchingData: true } }, {
|
||||
type: FETCH_DATA_END,
|
||||
}),
|
||||
{
|
||||
fetchingData: false,
|
||||
}
|
||||
ConfirmTransactionReducer({ fetchingData: true }, { type: FETCH_DATA_END }),
|
||||
{ fetchingData: false },
|
||||
)
|
||||
})
|
||||
|
||||
it('should clear confirmTransaction when receiving a FETCH_DATA_END action', () => {
|
||||
assert.deepEqual(
|
||||
ConfirmTransactionReducer(mockState, {
|
||||
type: CLEAR_CONFIRM_TRANSACTION,
|
||||
}),
|
||||
{
|
||||
...initialState,
|
||||
}
|
||||
)
|
||||
assert.deepEqual(ConfirmTransactionReducer(mockState, { type: CLEAR_CONFIRM_TRANSACTION }), initialState)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -93,9 +93,7 @@ describe('Gas Duck', () => {
|
||||
})
|
||||
|
||||
const mockState = {
|
||||
gas: {
|
||||
mockProp: 123,
|
||||
},
|
||||
mockProp: 123,
|
||||
}
|
||||
const initState = {
|
||||
customData: {
|
||||
@ -140,10 +138,7 @@ describe('Gas Duck', () => {
|
||||
|
||||
describe('GasReducer()', () => {
|
||||
it('should initialize state', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer({}),
|
||||
initState
|
||||
)
|
||||
assert.deepEqual(GasReducer(undefined, {}), initState)
|
||||
})
|
||||
|
||||
it('should return state unchanged if it does not match a dispatched actions type', () => {
|
||||
@ -152,58 +147,45 @@ describe('Gas Duck', () => {
|
||||
type: 'someOtherAction',
|
||||
value: 'someValue',
|
||||
}),
|
||||
Object.assign({}, mockState.gas)
|
||||
mockState,
|
||||
)
|
||||
})
|
||||
|
||||
it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer(mockState, {
|
||||
type: BASIC_GAS_ESTIMATE_LOADING_STARTED,
|
||||
}),
|
||||
Object.assign({ basicEstimateIsLoading: true }, mockState.gas)
|
||||
GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }),
|
||||
{ basicEstimateIsLoading: true, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer(mockState, {
|
||||
type: BASIC_GAS_ESTIMATE_LOADING_FINISHED,
|
||||
}),
|
||||
Object.assign({ basicEstimateIsLoading: false }, mockState.gas)
|
||||
GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }),
|
||||
{ basicEstimateIsLoading: false, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should set gasEstimatesLoading to true when receiving a GAS_ESTIMATE_LOADING_STARTED action', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer(mockState, {
|
||||
type: GAS_ESTIMATE_LOADING_STARTED,
|
||||
}),
|
||||
Object.assign({ gasEstimatesLoading: true }, mockState.gas)
|
||||
GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_STARTED }),
|
||||
{ gasEstimatesLoading: true, ...mockState }
|
||||
)
|
||||
})
|
||||
|
||||
it('should set gasEstimatesLoading to false when receiving a GAS_ESTIMATE_LOADING_FINISHED action', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer(mockState, {
|
||||
type: GAS_ESTIMATE_LOADING_FINISHED,
|
||||
}),
|
||||
Object.assign({ gasEstimatesLoading: false }, mockState.gas)
|
||||
GasReducer(mockState, { type: GAS_ESTIMATE_LOADING_FINISHED }),
|
||||
{ gasEstimatesLoading: false, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should return a new object (and not just modify the existing state object)', () => {
|
||||
assert.deepEqual(GasReducer(mockState), mockState.gas)
|
||||
assert.notEqual(GasReducer(mockState), mockState.gas)
|
||||
})
|
||||
|
||||
it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer(mockState, {
|
||||
type: SET_BASIC_GAS_ESTIMATE_DATA,
|
||||
value: { someProp: 'someData123' },
|
||||
}),
|
||||
Object.assign({ basicEstimates: { someProp: 'someData123' } }, mockState.gas)
|
||||
{ basicEstimates: { someProp: 'someData123' }, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -213,7 +195,7 @@ describe('Gas Duck', () => {
|
||||
type: SET_PRICE_AND_TIME_ESTIMATES,
|
||||
value: { someProp: 'someData123' },
|
||||
}),
|
||||
Object.assign({ priceAndTimeEstimates: { someProp: 'someData123' } }, mockState.gas)
|
||||
{ priceAndTimeEstimates: { someProp: 'someData123' }, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -223,7 +205,7 @@ describe('Gas Duck', () => {
|
||||
type: SET_CUSTOM_GAS_PRICE,
|
||||
value: 4321,
|
||||
}),
|
||||
Object.assign({ customData: { price: 4321 } }, mockState.gas)
|
||||
{ customData: { price: 4321 }, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -233,7 +215,7 @@ describe('Gas Duck', () => {
|
||||
type: SET_CUSTOM_GAS_LIMIT,
|
||||
value: 9876,
|
||||
}),
|
||||
Object.assign({ customData: { limit: 9876 } }, mockState.gas)
|
||||
{ customData: { limit: 9876 }, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -243,7 +225,7 @@ describe('Gas Duck', () => {
|
||||
type: SET_CUSTOM_GAS_TOTAL,
|
||||
value: 10000,
|
||||
}),
|
||||
Object.assign({ customData: { total: 10000 } }, mockState.gas)
|
||||
{ customData: { total: 10000 }, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -253,7 +235,7 @@ describe('Gas Duck', () => {
|
||||
type: SET_API_ESTIMATES_LAST_RETRIEVED,
|
||||
value: 1500000000000,
|
||||
}),
|
||||
Object.assign({ priceAndTimeEstimatesLastRetrieved: 1500000000000 }, mockState.gas)
|
||||
{ priceAndTimeEstimatesLastRetrieved: 1500000000000, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -263,7 +245,7 @@ describe('Gas Duck', () => {
|
||||
type: SET_BASIC_API_ESTIMATES_LAST_RETRIEVED,
|
||||
value: 1700000000000,
|
||||
}),
|
||||
Object.assign({ basicPriceAndTimeEstimatesLastRetrieved: 1700000000000 }, mockState.gas)
|
||||
{ basicPriceAndTimeEstimatesLastRetrieved: 1700000000000, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -273,35 +255,27 @@ describe('Gas Duck', () => {
|
||||
type: SET_CUSTOM_GAS_ERRORS,
|
||||
value: { someError: 'error_error' },
|
||||
}),
|
||||
Object.assign({ errors: { someError: 'error_error' } }, mockState.gas)
|
||||
{ errors: { someError: 'error_error' }, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should return the initial state in response to a RESET_CUSTOM_GAS_STATE action', () => {
|
||||
assert.deepEqual(
|
||||
GasReducer(mockState, {
|
||||
type: RESET_CUSTOM_GAS_STATE,
|
||||
}),
|
||||
Object.assign({}, initState)
|
||||
GasReducer(mockState, { type: RESET_CUSTOM_GAS_STATE }),
|
||||
initState,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('basicGasEstimatesLoadingStarted', () => {
|
||||
it('should create the correct action', () => {
|
||||
assert.deepEqual(
|
||||
basicGasEstimatesLoadingStarted(),
|
||||
{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED }
|
||||
)
|
||||
assert.deepEqual(basicGasEstimatesLoadingStarted(), { type: BASIC_GAS_ESTIMATE_LOADING_STARTED })
|
||||
})
|
||||
})
|
||||
|
||||
describe('basicGasEstimatesLoadingFinished', () => {
|
||||
it('should create the correct action', () => {
|
||||
assert.deepEqual(
|
||||
basicGasEstimatesLoadingFinished(),
|
||||
{ type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }
|
||||
)
|
||||
assert.deepEqual(basicGasEstimatesLoadingFinished(), { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED })
|
||||
})
|
||||
})
|
||||
|
||||
@ -309,11 +283,9 @@ describe('Gas Duck', () => {
|
||||
it('should call fetch with the expected params', async () => {
|
||||
const mockDistpatch = sinon.spy()
|
||||
|
||||
await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: Object.assign(
|
||||
{},
|
||||
initState,
|
||||
{ basicPriceAEstimatesLastRetrieved: 1000000 }
|
||||
) }))
|
||||
await fetchBasicGasEstimates()(mockDistpatch, () => ({
|
||||
gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 },
|
||||
}))
|
||||
assert.deepEqual(
|
||||
mockDistpatch.getCall(0).args,
|
||||
[{ type: BASIC_GAS_ESTIMATE_LOADING_STARTED } ]
|
||||
|
@ -28,7 +28,6 @@ const SET_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_API_ESTIMATES_LAST_RE
|
||||
const SET_BASIC_API_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_API_ESTIMATES_LAST_RETRIEVED'
|
||||
const SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED = 'metamask/gas/SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED'
|
||||
|
||||
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
|
||||
const initState = {
|
||||
customData: {
|
||||
price: null,
|
||||
@ -57,96 +56,94 @@ const initState = {
|
||||
}
|
||||
|
||||
// Reducer
|
||||
export default function reducer ({ gas: gasState = initState }, action = {}) {
|
||||
const newState = clone(gasState)
|
||||
|
||||
export default function reducer (state = initState, action) {
|
||||
switch (action.type) {
|
||||
case BASIC_GAS_ESTIMATE_LOADING_STARTED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
basicEstimateIsLoading: true,
|
||||
}
|
||||
case BASIC_GAS_ESTIMATE_LOADING_FINISHED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
basicEstimateIsLoading: false,
|
||||
}
|
||||
case GAS_ESTIMATE_LOADING_STARTED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
gasEstimatesLoading: true,
|
||||
}
|
||||
case GAS_ESTIMATE_LOADING_FINISHED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
gasEstimatesLoading: false,
|
||||
}
|
||||
case SET_BASIC_GAS_ESTIMATE_DATA:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
basicEstimates: action.value,
|
||||
}
|
||||
case SET_CUSTOM_GAS_PRICE:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
customData: {
|
||||
...newState.customData,
|
||||
...state.customData,
|
||||
price: action.value,
|
||||
},
|
||||
}
|
||||
case SET_CUSTOM_GAS_LIMIT:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
customData: {
|
||||
...newState.customData,
|
||||
...state.customData,
|
||||
limit: action.value,
|
||||
},
|
||||
}
|
||||
case SET_CUSTOM_GAS_TOTAL:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
customData: {
|
||||
...newState.customData,
|
||||
...state.customData,
|
||||
total: action.value,
|
||||
},
|
||||
}
|
||||
case SET_PRICE_AND_TIME_ESTIMATES:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
priceAndTimeEstimates: action.value,
|
||||
}
|
||||
case SET_CUSTOM_GAS_ERRORS:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
errors: {
|
||||
...newState.errors,
|
||||
...state.errors,
|
||||
...action.value,
|
||||
},
|
||||
}
|
||||
case SET_API_ESTIMATES_LAST_RETRIEVED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
priceAndTimeEstimatesLastRetrieved: action.value,
|
||||
}
|
||||
case SET_BASIC_API_ESTIMATES_LAST_RETRIEVED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
basicPriceAndTimeEstimatesLastRetrieved: action.value,
|
||||
}
|
||||
case SET_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
basicPriceEstimatesLastRetrieved: action.value,
|
||||
}
|
||||
case RESET_CUSTOM_DATA:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
customData: clone(initState.customData),
|
||||
}
|
||||
case RESET_CUSTOM_GAS_STATE:
|
||||
return clone(initState)
|
||||
default:
|
||||
return newState
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,90 +1,17 @@
|
||||
import { cloneDeep } from 'lodash'
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
import { combineReducers } from 'redux'
|
||||
import metamaskReducer from './metamask/metamask'
|
||||
import localeMessagesReducer from './locale/locale'
|
||||
import sendReducer from './send/send.duck'
|
||||
import appStateReducer from './app/app'
|
||||
import confirmTransactionReducer from './confirm-transaction/confirm-transaction.duck'
|
||||
import gasReducer from './gas/gas.duck'
|
||||
|
||||
//
|
||||
// Sub-Reducers take in the complete state and return their sub-state
|
||||
//
|
||||
import reduceMetamask from './metamask/metamask'
|
||||
|
||||
import reduceLocale from './locale/locale'
|
||||
import reduceSend from './send/send.duck'
|
||||
import reduceApp from './app/app'
|
||||
import reduceConfirmTransaction from './confirm-transaction/confirm-transaction.duck'
|
||||
import reduceGas from './gas/gas.duck'
|
||||
|
||||
window.METAMASK_CACHED_LOG_STATE = null
|
||||
|
||||
export default rootReducer
|
||||
|
||||
function rootReducer (state, action) {
|
||||
// clone
|
||||
state = { ...state }
|
||||
|
||||
if (action.type === 'GLOBAL_FORCE_UPDATE') {
|
||||
return action.value
|
||||
}
|
||||
|
||||
//
|
||||
// MetaMask
|
||||
//
|
||||
|
||||
state.metamask = reduceMetamask(state, action)
|
||||
|
||||
//
|
||||
// AppState
|
||||
//
|
||||
|
||||
state.appState = reduceApp(state, action)
|
||||
|
||||
//
|
||||
// LocaleMessages
|
||||
//
|
||||
|
||||
state.localeMessages = reduceLocale(state, action)
|
||||
|
||||
//
|
||||
// Send
|
||||
//
|
||||
|
||||
state.send = reduceSend(state, action)
|
||||
|
||||
state.confirmTransaction = reduceConfirmTransaction(state, action)
|
||||
|
||||
state.gas = reduceGas(state, action)
|
||||
|
||||
window.METAMASK_CACHED_LOG_STATE = state
|
||||
return state
|
||||
}
|
||||
|
||||
window.getCleanAppState = function () {
|
||||
const state = cloneDeep(window.METAMASK_CACHED_LOG_STATE)
|
||||
// append additional information
|
||||
state.version = global.platform.getVersion()
|
||||
state.browser = window.navigator.userAgent
|
||||
return state
|
||||
}
|
||||
|
||||
window.logStateString = function (cb) {
|
||||
const state = window.getCleanAppState()
|
||||
global.platform.getPlatformInfo((err, platform) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
state.platform = platform
|
||||
const stateString = JSON.stringify(state, null, 2)
|
||||
cb(null, stateString)
|
||||
})
|
||||
}
|
||||
|
||||
window.logState = function (toClipboard) {
|
||||
return window.logStateString((err, result) => {
|
||||
if (err) {
|
||||
console.error(err.message)
|
||||
} else if (toClipboard) {
|
||||
copyToClipboard(result)
|
||||
console.log('State log copied')
|
||||
} else {
|
||||
console.log(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
export default combineReducers({
|
||||
activeTab: (s) => (s === undefined ? null : s),
|
||||
metamask: metamaskReducer,
|
||||
appState: appStateReducer,
|
||||
send: sendReducer,
|
||||
confirmTransaction: confirmTransactionReducer,
|
||||
gas: gasReducer,
|
||||
localeMessages: localeMessagesReducer,
|
||||
})
|
||||
|
@ -1,17 +1,13 @@
|
||||
import { actionConstants } from '../../store/actions'
|
||||
|
||||
export default reduceMetamask
|
||||
|
||||
function reduceMetamask (state, action) {
|
||||
const localeMessagesState = { ...state.localeMessages }
|
||||
|
||||
switch (action.type) {
|
||||
export default function reduceLocaleMessages (state = {}, { type, value }) {
|
||||
switch (type) {
|
||||
case actionConstants.SET_CURRENT_LOCALE:
|
||||
return {
|
||||
...localeMessagesState,
|
||||
current: action.value.messages,
|
||||
...state,
|
||||
current: value.messages,
|
||||
}
|
||||
default:
|
||||
return localeMessagesState
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,8 @@
|
||||
import { actionConstants } from '../../store/actions'
|
||||
import { actionConstants as actions } from '../../store/actions'
|
||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
||||
import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums'
|
||||
|
||||
const actions = actionConstants
|
||||
|
||||
export default reduceMetamask
|
||||
|
||||
function reduceMetamask (state, action) {
|
||||
let newState
|
||||
|
||||
// clone + defaults
|
||||
export default function reduceMetamask (state = {}, action) {
|
||||
const metamaskState = Object.assign({
|
||||
isInitialized: false,
|
||||
isUnlocked: false,
|
||||
@ -59,7 +52,7 @@ function reduceMetamask (state, action) {
|
||||
participateInMetaMetrics: null,
|
||||
metaMetricsSendCount: 0,
|
||||
nextNonce: null,
|
||||
}, state.metamask)
|
||||
}, state)
|
||||
|
||||
switch (action.type) {
|
||||
|
||||
@ -97,25 +90,6 @@ function reduceMetamask (state, action) {
|
||||
},
|
||||
}
|
||||
|
||||
case actions.COMPLETED_TX:
|
||||
const stringId = String(action.id)
|
||||
newState = {
|
||||
...metamaskState,
|
||||
unapprovedTxs: {},
|
||||
unapprovedMsgs: {},
|
||||
}
|
||||
for (const id in metamaskState.unapprovedTxs) {
|
||||
if (id !== stringId) {
|
||||
newState.unapprovedTxs[id] = metamaskState.unapprovedTxs[id]
|
||||
}
|
||||
}
|
||||
for (const id in metamaskState.unapprovedMsgs) {
|
||||
if (id !== stringId) {
|
||||
newState.unapprovedMsgs[id] = metamaskState.unapprovedMsgs[id]
|
||||
}
|
||||
}
|
||||
return newState
|
||||
|
||||
case actions.SHOW_ACCOUNT_DETAIL:
|
||||
return {
|
||||
...metamaskState,
|
||||
@ -124,8 +98,8 @@ function reduceMetamask (state, action) {
|
||||
selectedAddress: action.value,
|
||||
}
|
||||
|
||||
case actions.SET_SELECTED_TOKEN:
|
||||
newState = {
|
||||
case actions.SET_SELECTED_TOKEN: {
|
||||
const newState = {
|
||||
...metamaskState,
|
||||
selectedTokenAddress: action.value,
|
||||
}
|
||||
@ -148,6 +122,7 @@ function reduceMetamask (state, action) {
|
||||
|
||||
newState.send = newSend
|
||||
return newState
|
||||
}
|
||||
|
||||
case actions.SET_ACCOUNT_LABEL:
|
||||
const account = action.value.account
|
||||
@ -411,6 +386,5 @@ function reduceMetamask (state, action) {
|
||||
|
||||
default:
|
||||
return metamaskState
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,7 @@ import SendReducer, {
|
||||
|
||||
describe('Send Duck', () => {
|
||||
const mockState = {
|
||||
send: {
|
||||
mockProp: 123,
|
||||
},
|
||||
mockProp: 123,
|
||||
}
|
||||
const initState = {
|
||||
toDropdownOpen: false,
|
||||
@ -28,10 +26,7 @@ describe('Send Duck', () => {
|
||||
|
||||
describe('SendReducer()', () => {
|
||||
it('should initialize state', () => {
|
||||
assert.deepEqual(
|
||||
SendReducer({}),
|
||||
initState
|
||||
)
|
||||
assert.deepEqual(SendReducer(undefined, {}), initState)
|
||||
})
|
||||
|
||||
it('should return state unchanged if it does not match a dispatched actions type', () => {
|
||||
@ -40,22 +35,16 @@ describe('Send Duck', () => {
|
||||
type: 'someOtherAction',
|
||||
value: 'someValue',
|
||||
}),
|
||||
Object.assign({}, mockState.send)
|
||||
mockState,
|
||||
)
|
||||
})
|
||||
|
||||
it('should return a new object (and not just modify the existing state object)', () => {
|
||||
assert.deepEqual(SendReducer(mockState), mockState.send)
|
||||
assert.notEqual(SendReducer(mockState), mockState.send)
|
||||
})
|
||||
|
||||
|
||||
it('should set toDropdownOpen to true when receiving a OPEN_TO_DROPDOWN action', () => {
|
||||
assert.deepEqual(
|
||||
SendReducer(mockState, {
|
||||
type: OPEN_TO_DROPDOWN,
|
||||
}),
|
||||
Object.assign({ toDropdownOpen: true }, mockState.send)
|
||||
{ toDropdownOpen: true, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
@ -64,47 +53,43 @@ describe('Send Duck', () => {
|
||||
SendReducer(mockState, {
|
||||
type: CLOSE_TO_DROPDOWN,
|
||||
}),
|
||||
Object.assign({ toDropdownOpen: false }, mockState.send)
|
||||
{ toDropdownOpen: false, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should set gasButtonGroupShown to true when receiving a SHOW_GAS_BUTTON_GROUP action', () => {
|
||||
assert.deepEqual(
|
||||
SendReducer(Object.assign({}, mockState, { gasButtonGroupShown: false }), {
|
||||
type: SHOW_GAS_BUTTON_GROUP,
|
||||
}),
|
||||
Object.assign({ gasButtonGroupShown: true }, mockState.send)
|
||||
SendReducer({ ...mockState, gasButtonGroupShown: false }, { type: SHOW_GAS_BUTTON_GROUP }),
|
||||
{ gasButtonGroupShown: true, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should set gasButtonGroupShown to false when receiving a HIDE_GAS_BUTTON_GROUP action', () => {
|
||||
assert.deepEqual(
|
||||
SendReducer(mockState, {
|
||||
type: HIDE_GAS_BUTTON_GROUP,
|
||||
}),
|
||||
Object.assign({ gasButtonGroupShown: false }, mockState.send)
|
||||
SendReducer(mockState, { type: HIDE_GAS_BUTTON_GROUP }),
|
||||
{ gasButtonGroupShown: false, ...mockState },
|
||||
)
|
||||
})
|
||||
|
||||
it('should extend send.errors with the value of a UPDATE_SEND_ERRORS action', () => {
|
||||
const modifiedMockState = Object.assign({}, mockState, {
|
||||
send: {
|
||||
errors: {
|
||||
someError: false,
|
||||
},
|
||||
const modifiedMockState = {
|
||||
...mockState,
|
||||
errors: {
|
||||
someError: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
assert.deepEqual(
|
||||
SendReducer(modifiedMockState, {
|
||||
type: UPDATE_SEND_ERRORS,
|
||||
value: { someOtherError: true },
|
||||
}),
|
||||
Object.assign({}, modifiedMockState.send, {
|
||||
{
|
||||
...modifiedMockState,
|
||||
errors: {
|
||||
someError: false,
|
||||
someOtherError: true,
|
||||
},
|
||||
})
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
@ -113,44 +98,28 @@ describe('Send Duck', () => {
|
||||
SendReducer(mockState, {
|
||||
type: RESET_SEND_STATE,
|
||||
}),
|
||||
Object.assign({}, initState)
|
||||
initState,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('openToDropdown', () => {
|
||||
assert.deepEqual(
|
||||
openToDropdown(),
|
||||
{ type: OPEN_TO_DROPDOWN }
|
||||
)
|
||||
assert.deepEqual(openToDropdown(), { type: OPEN_TO_DROPDOWN })
|
||||
})
|
||||
|
||||
describe('closeToDropdown', () => {
|
||||
assert.deepEqual(
|
||||
closeToDropdown(),
|
||||
{ type: CLOSE_TO_DROPDOWN }
|
||||
)
|
||||
assert.deepEqual(closeToDropdown(), { type: CLOSE_TO_DROPDOWN })
|
||||
})
|
||||
|
||||
describe('showGasButtonGroup', () => {
|
||||
assert.deepEqual(
|
||||
showGasButtonGroup(),
|
||||
{ type: SHOW_GAS_BUTTON_GROUP }
|
||||
)
|
||||
assert.deepEqual(showGasButtonGroup(), { type: SHOW_GAS_BUTTON_GROUP })
|
||||
})
|
||||
|
||||
describe('hideGasButtonGroup', () => {
|
||||
assert.deepEqual(
|
||||
hideGasButtonGroup(),
|
||||
{ type: HIDE_GAS_BUTTON_GROUP }
|
||||
)
|
||||
assert.deepEqual(hideGasButtonGroup(), { type: HIDE_GAS_BUTTON_GROUP })
|
||||
})
|
||||
|
||||
describe('updateSendErrors', () => {
|
||||
assert.deepEqual(
|
||||
updateSendErrors('mockErrorObject'),
|
||||
{ type: UPDATE_SEND_ERRORS, value: 'mockErrorObject' }
|
||||
)
|
||||
assert.deepEqual(updateSendErrors('mockErrorObject'), { type: UPDATE_SEND_ERRORS, value: 'mockErrorObject' })
|
||||
})
|
||||
|
||||
})
|
||||
|
@ -6,7 +6,6 @@ const RESET_SEND_STATE = 'metamask/send/RESET_SEND_STATE'
|
||||
const SHOW_GAS_BUTTON_GROUP = 'metamask/send/SHOW_GAS_BUTTON_GROUP'
|
||||
const HIDE_GAS_BUTTON_GROUP = 'metamask/send/HIDE_GAS_BUTTON_GROUP'
|
||||
|
||||
// TODO: determine if this approach to initState is consistent with conventional ducks pattern
|
||||
const initState = {
|
||||
toDropdownOpen: false,
|
||||
gasButtonGroupShown: true,
|
||||
@ -14,42 +13,40 @@ const initState = {
|
||||
}
|
||||
|
||||
// Reducer
|
||||
export default function reducer ({ send: sendState = initState }, action = {}) {
|
||||
const newState = { ...sendState }
|
||||
|
||||
export default function reducer (state = initState, action) {
|
||||
switch (action.type) {
|
||||
case OPEN_TO_DROPDOWN:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
toDropdownOpen: true,
|
||||
}
|
||||
case CLOSE_TO_DROPDOWN:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
toDropdownOpen: false,
|
||||
}
|
||||
case UPDATE_SEND_ERRORS:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
errors: {
|
||||
...newState.errors,
|
||||
...state.errors,
|
||||
...action.value,
|
||||
},
|
||||
}
|
||||
case SHOW_GAS_BUTTON_GROUP:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
gasButtonGroupShown: true,
|
||||
}
|
||||
case HIDE_GAS_BUTTON_GROUP:
|
||||
return {
|
||||
...newState,
|
||||
...state,
|
||||
gasButtonGroupShown: false,
|
||||
}
|
||||
case RESET_SEND_STATE:
|
||||
return { ...initState }
|
||||
default:
|
||||
return newState
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,15 @@ import Loading from '../../components/ui/loading-screen'
|
||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'
|
||||
|
||||
function mapStateToProps (state) {
|
||||
const { metamask } = state
|
||||
const { metamask, appState } = state
|
||||
const {
|
||||
unapprovedMsgCount,
|
||||
unapprovedPersonalMsgCount,
|
||||
unapprovedTypedMessagesCount,
|
||||
} = metamask
|
||||
const {
|
||||
txId,
|
||||
} = appState
|
||||
|
||||
return {
|
||||
identities: state.metamask.identities,
|
||||
@ -26,7 +29,7 @@ function mapStateToProps (state) {
|
||||
unapprovedMsgs: state.metamask.unapprovedMsgs,
|
||||
unapprovedPersonalMsgs: state.metamask.unapprovedPersonalMsgs,
|
||||
unapprovedTypedMessages: state.metamask.unapprovedTypedMessages,
|
||||
index: state.appState.currentView.context,
|
||||
index: txId,
|
||||
warning: state.appState.warning,
|
||||
network: state.metamask.network,
|
||||
provider: state.metamask.provider,
|
||||
|
@ -13,6 +13,7 @@ import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../app/scripts/lib/enums'
|
||||
import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util'
|
||||
import { setCustomGasLimit } from '../ducks/gas/gas.duck'
|
||||
import WebcamUtils from '../../lib/webcam-utils'
|
||||
import txHelper from '../../lib/tx-helper'
|
||||
|
||||
export const actionConstants = {
|
||||
GO_HOME: 'GO_HOME',
|
||||
@ -678,7 +679,7 @@ export function signTx (txData) {
|
||||
return dispatch(displayWarning(err.message))
|
||||
}
|
||||
})
|
||||
dispatch(showConfTxPage({}))
|
||||
dispatch(showConfTxPage())
|
||||
}
|
||||
}
|
||||
|
||||
@ -858,7 +859,7 @@ export function signTokenTx (tokenAddress, toAddress, amount, txData) {
|
||||
dispatch(hideLoadingIndication())
|
||||
dispatch(displayWarning(err.message))
|
||||
})
|
||||
dispatch(showConfTxPage({}))
|
||||
dispatch(showConfTxPage())
|
||||
}
|
||||
}
|
||||
|
||||
@ -877,9 +878,7 @@ const updateMetamaskStateFromBackground = () => {
|
||||
}
|
||||
|
||||
export function updateTransaction (txData) {
|
||||
log.info('actions: updateTx: ' + JSON.stringify(txData))
|
||||
return dispatch => {
|
||||
log.debug(`actions calling background.updateTx`)
|
||||
dispatch(showLoadingIndication())
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -906,9 +905,7 @@ export function updateTransaction (txData) {
|
||||
}
|
||||
|
||||
export function updateAndApproveTx (txData) {
|
||||
log.info('actions: updateAndApproveTx: ' + JSON.stringify(txData))
|
||||
return (dispatch) => {
|
||||
log.debug(`actions calling background.updateAndApproveTx`)
|
||||
dispatch(showLoadingIndication())
|
||||
return new Promise((resolve, reject) => {
|
||||
background.updateAndApproveTransaction(txData, err => {
|
||||
@ -944,9 +941,24 @@ export function updateAndApproveTx (txData) {
|
||||
}
|
||||
|
||||
export function completedTx (id) {
|
||||
return {
|
||||
type: actionConstants.COMPLETED_TX,
|
||||
value: id,
|
||||
return (dispatch, getState) => {
|
||||
const state = getState()
|
||||
const {
|
||||
unapprovedTxs,
|
||||
unapprovedMsgs,
|
||||
unapprovedPersonalMsgs,
|
||||
unapprovedTypedMessages,
|
||||
network,
|
||||
} = state.metamask
|
||||
const unconfirmedActions = txHelper(unapprovedTxs, unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, network)
|
||||
const otherUnconfirmedActions = unconfirmedActions.filter(tx => tx.id !== id)
|
||||
dispatch({
|
||||
type: actionConstants.COMPLETED_TX,
|
||||
value: {
|
||||
id,
|
||||
unconfirmedActionsCount: otherUnconfirmedActions.length,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -969,7 +981,6 @@ export function cancelMsg (msgData) {
|
||||
return (dispatch) => {
|
||||
dispatch(showLoadingIndication())
|
||||
return new Promise((resolve, reject) => {
|
||||
log.debug(`background.cancelMessage`)
|
||||
background.cancelMessage(msgData.id, (err, newState) => {
|
||||
dispatch(updateMetamaskState(newState))
|
||||
dispatch(hideLoadingIndication())
|
||||
@ -1033,7 +1044,6 @@ export function cancelTypedMsg (msgData) {
|
||||
|
||||
export function cancelTx (txData) {
|
||||
return (dispatch) => {
|
||||
log.debug(`background.cancelTransaction`)
|
||||
dispatch(showLoadingIndication())
|
||||
return new Promise((resolve, reject) => {
|
||||
background.cancelTransaction(txData.id, err => {
|
||||
@ -1252,7 +1262,7 @@ export function showAccountsPage () {
|
||||
}
|
||||
}
|
||||
|
||||
export function showConfTxPage ({ transForward = true, id }) {
|
||||
export function showConfTxPage ({ transForward = true, id } = {}) {
|
||||
return {
|
||||
type: actionConstants.SHOW_CONF_TX_PAGE,
|
||||
transForward,
|
||||
|
46
ui/index.js
46
ui/index.js
@ -1,3 +1,6 @@
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
import log from 'loglevel'
|
||||
import { clone } from 'lodash'
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
import Root from './app/pages'
|
||||
@ -6,13 +9,10 @@ import configureStore from './app/store/store'
|
||||
import txHelper from './lib/tx-helper'
|
||||
import { fetchLocale } from './app/helpers/utils/i18n-helper'
|
||||
import switchDirection from './app/helpers/utils/switch-direction'
|
||||
import log from 'loglevel'
|
||||
|
||||
export default launchMetamaskUi
|
||||
|
||||
log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn')
|
||||
|
||||
function launchMetamaskUi (opts, cb) {
|
||||
export default function launchMetamaskUi (opts, cb) {
|
||||
const { backgroundConnection } = opts
|
||||
actions._setBackgroundConnection(backgroundConnection)
|
||||
// check if we are unlocked first
|
||||
@ -22,6 +22,7 @@ function launchMetamaskUi (opts, cb) {
|
||||
}
|
||||
startApp(metamaskState, backgroundConnection, opts)
|
||||
.then((store) => {
|
||||
setupDebuggingHelpers(store)
|
||||
cb(null, store)
|
||||
})
|
||||
})
|
||||
@ -55,9 +56,6 @@ async function startApp (metamaskState, backgroundConnection, opts) {
|
||||
current: currentLocaleMessages,
|
||||
en: enLocaleMessages,
|
||||
},
|
||||
|
||||
// Which blockchain we are using:
|
||||
networkVersion: opts.networkVersion,
|
||||
})
|
||||
|
||||
// if unconfirmed txs, start on txConf page
|
||||
@ -104,3 +102,37 @@ async function startApp (metamaskState, backgroundConnection, opts) {
|
||||
|
||||
return store
|
||||
}
|
||||
|
||||
function setupDebuggingHelpers (store) {
|
||||
window.getCleanAppState = function () {
|
||||
const state = clone(store.getState())
|
||||
state.version = global.platform.getVersion()
|
||||
state.browser = window.navigator.userAgent
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
window.logStateString = function (cb) {
|
||||
const state = window.getCleanAppState()
|
||||
global.platform.getPlatformInfo((err, platform) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
state.platform = platform
|
||||
const stateString = JSON.stringify(state, null, 2)
|
||||
cb(null, stateString)
|
||||
})
|
||||
}
|
||||
|
||||
window.logState = function (toClipboard) {
|
||||
return window.logStateString((err, result) => {
|
||||
if (err) {
|
||||
console.error(err.message)
|
||||
} else if (toClipboard) {
|
||||
copyToClipboard(result)
|
||||
console.log('State log copied')
|
||||
} else {
|
||||
console.log(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user