mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Merge branch 'develop' into testing
This commit is contained in:
commit
58b9afff4f
@ -13,19 +13,17 @@ class AddressBookController {
|
||||
* @param {object} opts Overrides the defaults for the initial state of this.store
|
||||
* @property {array} opts.initState initializes the the state of the AddressBookController. Can contain an
|
||||
* addressBook property to initialize the addressBook array
|
||||
* @param {KeyringController} keyringController (Soon to be deprecated) The keyringController used in the current
|
||||
* MetamaskController. Contains the identities used in this AddressBookController.
|
||||
* @property {object} opts.preferencesStore the {@code PreferencesController} store
|
||||
* @property {object} store The the store of the current users address book
|
||||
* @property {array} store.addressBook An array of addresses and nicknames. These are set by the user when sending
|
||||
* to a new address.
|
||||
*
|
||||
*/
|
||||
constructor (opts = {}, keyringController) {
|
||||
const initState = extend({
|
||||
constructor ({initState, preferencesStore}) {
|
||||
this.store = new ObservableStore(extend({
|
||||
addressBook: [],
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
this.keyringController = keyringController
|
||||
}, initState))
|
||||
this._preferencesStore = preferencesStore
|
||||
}
|
||||
|
||||
//
|
||||
@ -62,7 +60,7 @@ class AddressBookController {
|
||||
*/
|
||||
_addToAddressBook (address, name) {
|
||||
const addressBook = this._getAddressBook()
|
||||
const identities = this._getIdentities()
|
||||
const {identities} = this._preferencesStore.getState()
|
||||
|
||||
const addressBookIndex = addressBook.findIndex((element) => { return element.address.toLowerCase() === address.toLowerCase() || element.name === name })
|
||||
const identitiesIndex = Object.keys(identities).findIndex((element) => { return element.toLowerCase() === address.toLowerCase() })
|
||||
@ -95,19 +93,6 @@ class AddressBookController {
|
||||
_getAddressBook () {
|
||||
return this.store.getState().addressBook
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves identities from the keyring controller in order to avoid
|
||||
* duplication
|
||||
*
|
||||
* @deprecated
|
||||
* @returns {array} Returns the identies array from the keyringContoller's state
|
||||
*
|
||||
*/
|
||||
_getIdentities () {
|
||||
return this.keyringController.memStore.getState().identities
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = AddressBookController
|
||||
|
@ -27,6 +27,7 @@ class PreferencesController {
|
||||
useBlockie: false,
|
||||
featureFlags: {},
|
||||
currentLocale: opts.initLangCode,
|
||||
identities: {},
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
}
|
||||
@ -62,6 +63,16 @@ class PreferencesController {
|
||||
this.store.updateState({ currentLocale: key })
|
||||
}
|
||||
|
||||
setAddresses (addresses) {
|
||||
const oldIdentities = this.store.getState().identities
|
||||
const identities = addresses.reduce((ids, address, index) => {
|
||||
const oldId = oldIdentities[address] || {}
|
||||
ids[address] = {name: `Account ${index + 1}`, address, ...oldId}
|
||||
return ids
|
||||
}, {})
|
||||
this.store.updateState({ identities })
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for the `selectedAddress` property
|
||||
*
|
||||
@ -155,6 +166,21 @@ class PreferencesController {
|
||||
return this.store.getState().tokens
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom label for an account
|
||||
* @param {string} account the account to set a label for
|
||||
* @param {string} label the custom label for the account
|
||||
* @return {Promise<string>}
|
||||
*/
|
||||
setAccountLabel (account, label) {
|
||||
const address = normalizeAddress(account)
|
||||
const {identities} = this.store.getState()
|
||||
identities[address] = identities[address] || {}
|
||||
identities[address].name = label
|
||||
this.store.updateState({ identities })
|
||||
return Promise.resolve(label)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an updated rpc list from this.addToFrequentRpcList() and sets the `frequentRpcList` to this update list.
|
||||
*
|
||||
|
@ -144,7 +144,8 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
// address book controller
|
||||
this.addressBookController = new AddressBookController({
|
||||
initState: initState.AddressBookController,
|
||||
}, this.keyringController)
|
||||
preferencesStore: this.preferencesController.store,
|
||||
})
|
||||
|
||||
// tx mgmt
|
||||
this.txController = new TransactionController({
|
||||
@ -363,6 +364,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
addToken: nodeify(preferencesController.addToken, preferencesController),
|
||||
removeToken: nodeify(preferencesController.removeToken, preferencesController),
|
||||
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController),
|
||||
setAccountLabel: nodeify(preferencesController.setAccountLabel, preferencesController),
|
||||
setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController),
|
||||
|
||||
// AddressController
|
||||
@ -373,7 +375,6 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),
|
||||
createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this),
|
||||
addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController),
|
||||
saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController),
|
||||
exportAccount: nodeify(keyringController.exportAccount, keyringController),
|
||||
|
||||
// txController
|
||||
@ -433,7 +434,9 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
} else {
|
||||
vault = await this.keyringController.createNewVaultAndKeychain(password)
|
||||
this.selectFirstIdentity(vault)
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
this.selectFirstIdentity()
|
||||
}
|
||||
release()
|
||||
} catch (err) {
|
||||
@ -453,7 +456,9 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
const release = await this.createVaultMutex.acquire()
|
||||
try {
|
||||
const vault = await this.keyringController.createNewVaultAndRestore(password, seed)
|
||||
this.selectFirstIdentity(vault)
|
||||
const accounts = await this.keyringController.getAccounts()
|
||||
this.preferencesController.setAddresses(accounts)
|
||||
this.selectFirstIdentity()
|
||||
release()
|
||||
return vault
|
||||
} catch (err) {
|
||||
@ -471,12 +476,10 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Retrieves the first Identiy from the passed Vault and selects the related address
|
||||
*
|
||||
* @param {} vault
|
||||
* Sets the first address in the state to the selected address
|
||||
*/
|
||||
selectFirstIdentity (vault) {
|
||||
const { identities } = vault
|
||||
selectFirstIdentity () {
|
||||
const { identities } = this.preferencesController.store.getState()
|
||||
const address = Object.keys(identities)[0]
|
||||
this.preferencesController.setSelectedAddress(address)
|
||||
}
|
||||
@ -502,13 +505,15 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
await this.verifySeedPhrase()
|
||||
|
||||
this.preferencesController.setAddresses(newAccounts)
|
||||
newAccounts.forEach((address) => {
|
||||
if (!oldAccounts.includes(address)) {
|
||||
this.preferencesController.setSelectedAddress(address)
|
||||
}
|
||||
})
|
||||
|
||||
return keyState
|
||||
const {identities} = this.preferencesController.store.getState()
|
||||
return {...keyState, identities}
|
||||
}
|
||||
|
||||
/**
|
||||
|
47
app/scripts/migrations/026.js
Normal file
47
app/scripts/migrations/026.js
Normal file
@ -0,0 +1,47 @@
|
||||
const version = 26
|
||||
|
||||
/*
|
||||
|
||||
This migration moves the identities stored in the KeyringController
|
||||
into the PreferencesController
|
||||
|
||||
*/
|
||||
|
||||
const clone = require('clone')
|
||||
|
||||
module.exports = {
|
||||
version,
|
||||
migrate (originalVersionedData) {
|
||||
const versionedData = clone(originalVersionedData)
|
||||
versionedData.meta.version = version
|
||||
try {
|
||||
const state = versionedData.data
|
||||
versionedData.data = transformState(state)
|
||||
} catch (err) {
|
||||
console.warn(`MetaMask Migration #${version}` + err.stack)
|
||||
return Promise.reject(err)
|
||||
}
|
||||
return Promise.resolve(versionedData)
|
||||
},
|
||||
}
|
||||
|
||||
function transformState (state) {
|
||||
if (!state.KeyringController || !state.PreferencesController) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!state.KeyringController.walletNicknames) {
|
||||
return state
|
||||
}
|
||||
|
||||
state.PreferencesController.identities = Object.keys(state.KeyringController.walletNicknames)
|
||||
.reduce((identities, address) => {
|
||||
identities[address] = {
|
||||
name: state.KeyringController.walletNicknames[address],
|
||||
address,
|
||||
}
|
||||
return identities
|
||||
}, {})
|
||||
delete state.KeyringController.walletNicknames
|
||||
return state
|
||||
}
|
@ -36,4 +36,5 @@ module.exports = [
|
||||
require('./023'),
|
||||
require('./024'),
|
||||
require('./025'),
|
||||
require('./026'),
|
||||
]
|
||||
|
@ -91,7 +91,7 @@ AccountDetailScreen.prototype.render = function () {
|
||||
isEditingLabel: false,
|
||||
},
|
||||
saveText: (text) => {
|
||||
props.dispatch(actions.saveAccountLabel(selected, text))
|
||||
props.dispatch(actions.setAccountLabel(selected, text))
|
||||
},
|
||||
}, [
|
||||
|
||||
|
22
package-lock.json
generated
22
package-lock.json
generated
@ -8054,9 +8054,9 @@
|
||||
}
|
||||
},
|
||||
"eth-keyring-controller": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-2.2.0.tgz",
|
||||
"integrity": "sha512-f/g1ZrxciWJs2aHgpfvYmZ3ImP48GA+pobTU0EFNF/y5Yylf1zQyDw671W5opGpIt5TgV4F9sYXcvyjlgbL0Pg==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-3.1.1.tgz",
|
||||
"integrity": "sha512-Z9HTzrop/V4Ld8Wq7uwetKecfWIyx25/uL8aFoZxV3kegZGoXaWoRmNy+4oW0WNLp4BcJ1lk6QfsGEdlymGjmA==",
|
||||
"requires": {
|
||||
"bip39": "2.4.0",
|
||||
"bluebird": "3.5.1",
|
||||
@ -8064,7 +8064,7 @@
|
||||
"eth-hd-keyring": "1.2.2",
|
||||
"eth-sig-util": "1.4.2",
|
||||
"eth-simple-keyring": "1.2.1",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"loglevel": "1.6.0",
|
||||
"obs-store": "2.4.1",
|
||||
"promise-filter": "1.1.0"
|
||||
@ -8080,9 +8080,9 @@
|
||||
}
|
||||
},
|
||||
"ethereumjs-util": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz",
|
||||
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"create-hash": "1.1.3",
|
||||
@ -8176,16 +8176,16 @@
|
||||
"integrity": "sha1-bXs1LcWppQINYfafryHvsvY2P0U=",
|
||||
"requires": {
|
||||
"eth-sig-util": "1.4.2",
|
||||
"ethereumjs-util": "5.1.5",
|
||||
"ethereumjs-util": "5.2.0",
|
||||
"ethereumjs-wallet": "0.6.0",
|
||||
"events": "1.1.1",
|
||||
"xtend": "4.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethereumjs-util": {
|
||||
"version": "5.1.5",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz",
|
||||
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
|
||||
"integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
|
||||
"requires": {
|
||||
"bn.js": "4.11.8",
|
||||
"create-hash": "1.1.3",
|
||||
|
@ -95,7 +95,7 @@
|
||||
"eth-hd-keyring": "^1.2.1",
|
||||
"eth-json-rpc-filters": "^1.2.6",
|
||||
"eth-json-rpc-infura": "^3.0.0",
|
||||
"eth-keyring-controller": "^2.2.0",
|
||||
"eth-keyring-controller": "^3.1.1",
|
||||
"eth-phishing-detect": "^1.1.4",
|
||||
"eth-query": "^2.1.2",
|
||||
"eth-sig-util": "^1.4.2",
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,35 +0,0 @@
|
||||
// var jsdom = require('mocha-jsdom')
|
||||
var assert = require('assert')
|
||||
var freeze = require('deep-freeze-strict')
|
||||
var path = require('path')
|
||||
|
||||
var actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
|
||||
var reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
|
||||
|
||||
describe('SAVE_ACCOUNT_LABEL', function () {
|
||||
it('updates the state.metamask.identities[:i].name property of the state to the action.value.label', function () {
|
||||
var initialState = {
|
||||
metamask: {
|
||||
identities: {
|
||||
foo: {
|
||||
name: 'bar',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
freeze(initialState)
|
||||
|
||||
const action = {
|
||||
type: actions.SAVE_ACCOUNT_LABEL,
|
||||
value: {
|
||||
account: 'foo',
|
||||
label: 'baz',
|
||||
},
|
||||
}
|
||||
freeze(action)
|
||||
|
||||
var resultingState = reducers(initialState, action)
|
||||
assert.equal(resultingState.metamask.identities.foo.name, action.value.label)
|
||||
})
|
||||
})
|
||||
|
34
test/unit/actions/set_account_label_test.js
Normal file
34
test/unit/actions/set_account_label_test.js
Normal file
@ -0,0 +1,34 @@
|
||||
const assert = require('assert')
|
||||
const freeze = require('deep-freeze-strict')
|
||||
const path = require('path')
|
||||
|
||||
const actions = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'actions.js'))
|
||||
const reducers = require(path.join(__dirname, '..', '..', '..', 'ui', 'app', 'reducers.js'))
|
||||
|
||||
describe('SET_ACCOUNT_LABEL', function () {
|
||||
it('updates the state.metamask.identities[:i].name property of the state to the action.value.label', function () {
|
||||
const initialState = {
|
||||
metamask: {
|
||||
identities: {
|
||||
foo: {
|
||||
name: 'bar',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
freeze(initialState)
|
||||
|
||||
const action = {
|
||||
type: actions.SET_ACCOUNT_LABEL,
|
||||
value: {
|
||||
account: 'foo',
|
||||
label: 'baz',
|
||||
},
|
||||
}
|
||||
freeze(action)
|
||||
|
||||
const resultingState = reducers(initialState, action)
|
||||
assert.equal(resultingState.metamask.identities.foo.name, action.value.label)
|
||||
})
|
||||
})
|
||||
|
@ -1,26 +1,26 @@
|
||||
const assert = require('assert')
|
||||
const AddressBookController = require('../../../../app/scripts/controllers/address-book')
|
||||
|
||||
const mockKeyringController = {
|
||||
memStore: {
|
||||
getState: function () {
|
||||
return {
|
||||
identities: {
|
||||
'0x0aaa': {
|
||||
address: '0x0aaa',
|
||||
name: 'owned',
|
||||
},
|
||||
const stubPreferencesStore = {
|
||||
getState: function () {
|
||||
return {
|
||||
identities: {
|
||||
'0x0aaa': {
|
||||
address: '0x0aaa',
|
||||
name: 'owned',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
describe('address-book-controller', function () {
|
||||
var addressBookController
|
||||
|
||||
beforeEach(function () {
|
||||
addressBookController = new AddressBookController({}, mockKeyringController)
|
||||
addressBookController = new AddressBookController({
|
||||
preferencesStore: stubPreferencesStore,
|
||||
})
|
||||
})
|
||||
|
||||
describe('addres book management', function () {
|
||||
|
@ -4,7 +4,7 @@ const clone = require('clone')
|
||||
const nock = require('nock')
|
||||
const createThoughStream = require('through2').obj
|
||||
const MetaMaskController = require('../../../../app/scripts/metamask-controller')
|
||||
const blacklistJSON = require('../../../stub/blacklist')
|
||||
const blacklistJSON = require('eth-phishing-detect/src/config')
|
||||
const firstTimeState = require('../../../../app/scripts/first-time-state')
|
||||
|
||||
const currentNetworkId = 42
|
||||
@ -118,7 +118,7 @@ describe('MetaMaskController', function () {
|
||||
[TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL },
|
||||
})
|
||||
|
||||
await metamaskController.keyringController.saveAccountLabel(TEST_ADDRESS, 'Account Foo')
|
||||
await metamaskController.preferencesController.setAccountLabel(TEST_ADDRESS, 'Account Foo')
|
||||
assert.deepEqual(metamaskController.getState().identities, {
|
||||
[TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' },
|
||||
})
|
||||
@ -170,14 +170,17 @@ describe('MetaMaskController', function () {
|
||||
beforeEach(function () {
|
||||
address = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc'
|
||||
identities = {
|
||||
identities: {
|
||||
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
|
||||
'address': '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
|
||||
'name': 'Account 1',
|
||||
},
|
||||
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {
|
||||
'address': address,
|
||||
'name': 'Account 1',
|
||||
},
|
||||
'0xc42edfcc21ed14dda456aa0756c153f7985d8813': {
|
||||
'address': '0xc42edfcc21ed14dda456aa0756c153f7985d8813',
|
||||
'name': 'Account 2',
|
||||
},
|
||||
}
|
||||
metamaskController.selectFirstIdentity(identities)
|
||||
metamaskController.preferencesController.store.updateState({ identities })
|
||||
metamaskController.selectFirstIdentity()
|
||||
})
|
||||
|
||||
it('changes preferences controller select address', function () {
|
||||
|
@ -4,16 +4,91 @@ const PreferencesController = require('../../../../app/scripts/controllers/prefe
|
||||
describe('preferences controller', function () {
|
||||
let preferencesController
|
||||
|
||||
before(() => {
|
||||
beforeEach(() => {
|
||||
preferencesController = new PreferencesController()
|
||||
})
|
||||
|
||||
describe('setAddresses', function () {
|
||||
it('should keep a map of addresses to names and addresses in the store', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
'0x7e57e2',
|
||||
])
|
||||
|
||||
const {identities} = preferencesController.store.getState()
|
||||
assert.deepEqual(identities, {
|
||||
'0xda22le': {
|
||||
name: 'Account 1',
|
||||
address: '0xda22le',
|
||||
},
|
||||
'0x7e57e2': {
|
||||
name: 'Account 2',
|
||||
address: '0x7e57e2',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('should replace its list of addresses', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
'0x7e57e2',
|
||||
])
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le77',
|
||||
'0x7e57e277',
|
||||
])
|
||||
|
||||
const {identities} = preferencesController.store.getState()
|
||||
assert.deepEqual(identities, {
|
||||
'0xda22le77': {
|
||||
name: 'Account 1',
|
||||
address: '0xda22le77',
|
||||
},
|
||||
'0x7e57e277': {
|
||||
name: 'Account 2',
|
||||
address: '0x7e57e277',
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('setAccountLabel', function () {
|
||||
it('should update a label for the given account', function () {
|
||||
preferencesController.setAddresses([
|
||||
'0xda22le',
|
||||
'0x7e57e2',
|
||||
])
|
||||
|
||||
assert.deepEqual(preferencesController.store.getState().identities['0xda22le'], {
|
||||
name: 'Account 1',
|
||||
address: '0xda22le',
|
||||
})
|
||||
|
||||
|
||||
preferencesController.setAccountLabel('0xda22le', 'Dazzle')
|
||||
assert.deepEqual(preferencesController.store.getState().identities['0xda22le'], {
|
||||
name: 'Dazzle',
|
||||
address: '0xda22le',
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('getTokens', function () {
|
||||
it('should return an empty list initially', async function () {
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
|
||||
const tokens = preferencesController.getTokens()
|
||||
assert.equal(tokens.length, 0, 'empty list of tokens')
|
||||
})
|
||||
})
|
||||
|
||||
describe('addToken', function () {
|
||||
it('should add that token to its state', async function () {
|
||||
const address = '0xabcdef1234567'
|
||||
const symbol = 'ABBR'
|
||||
const decimals = 5
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
|
||||
const tokens = preferencesController.getTokens()
|
||||
@ -30,6 +105,7 @@ describe('preferences controller', function () {
|
||||
const symbol = 'ABBR'
|
||||
const decimals = 5
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
|
||||
const newDecimals = 6
|
||||
@ -43,6 +119,44 @@ describe('preferences controller', function () {
|
||||
assert.equal(added.symbol, symbol, 'set symbol correctly')
|
||||
assert.equal(added.decimals, newDecimals, 'updated decimals correctly')
|
||||
})
|
||||
|
||||
it('should allow adding tokens to two separate addresses', async function () {
|
||||
const address = '0xabcdef1234567'
|
||||
const symbol = 'ABBR'
|
||||
const decimals = 5
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 1st address')
|
||||
|
||||
await preferencesController.setSelectedAddress('0xda22le')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 2nd address')
|
||||
})
|
||||
})
|
||||
|
||||
describe('removeToken', function () {
|
||||
it('should remove the only token from its state', async function () {
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken('0xa', 'A', 5)
|
||||
await preferencesController.removeToken('0xa')
|
||||
|
||||
const tokens = preferencesController.getTokens()
|
||||
assert.equal(tokens.length, 0, 'one token removed')
|
||||
})
|
||||
|
||||
it('should remove a token from its state', async function () {
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
await preferencesController.removeToken('0xa')
|
||||
|
||||
const tokens = preferencesController.getTokens()
|
||||
assert.equal(tokens.length, 1, 'one token removed')
|
||||
|
||||
const [token1] = tokens
|
||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
41
test/unit/migrations/026-test.js
Normal file
41
test/unit/migrations/026-test.js
Normal file
@ -0,0 +1,41 @@
|
||||
const assert = require('assert')
|
||||
const migration26 = require('../../../app/scripts/migrations/026')
|
||||
const oldStorage = {
|
||||
'meta': {'version': 25},
|
||||
'data': {
|
||||
'PreferencesController': {},
|
||||
'KeyringController': {
|
||||
'walletNicknames': {
|
||||
'0x1e77e2': 'Test Account 1',
|
||||
'0x7e57e2': 'Test Account 2',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
describe('migration #26', () => {
|
||||
it('should move the identities from KeyringController', (done) => {
|
||||
migration26.migrate(oldStorage)
|
||||
.then((newStorage) => {
|
||||
const identities = newStorage.data.PreferencesController.identities
|
||||
assert.deepEqual(identities, {
|
||||
'0x1e77e2': {name: 'Test Account 1', address: '0x1e77e2'},
|
||||
'0x7e57e2': {name: 'Test Account 2', address: '0x7e57e2'},
|
||||
})
|
||||
assert.strictEqual(newStorage.data.KeyringController.walletNicknames, undefined)
|
||||
done()
|
||||
})
|
||||
.catch(done)
|
||||
})
|
||||
|
||||
it('should successfully migrate first time state', (done) => {
|
||||
migration26.migrate({
|
||||
meta: {},
|
||||
data: require('../../../app/scripts/first-time-state'),
|
||||
})
|
||||
.then((migratedData) => {
|
||||
assert.equal(migratedData.meta.version, migration26.version)
|
||||
done()
|
||||
}).catch(done)
|
||||
})
|
||||
})
|
@ -24,7 +24,7 @@ function mapDispatchToProps (dispatch) {
|
||||
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
|
||||
},
|
||||
hideModal: () => dispatch(actions.hideModal()),
|
||||
saveAccountLabel: (address, label) => dispatch(actions.saveAccountLabel(address, label)),
|
||||
setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,8 +124,8 @@ var actions = {
|
||||
SHOW_PRIVATE_KEY: 'SHOW_PRIVATE_KEY',
|
||||
showPrivateKey: showPrivateKey,
|
||||
exportAccountComplete,
|
||||
SAVE_ACCOUNT_LABEL: 'SAVE_ACCOUNT_LABEL',
|
||||
saveAccountLabel: saveAccountLabel,
|
||||
SET_ACCOUNT_LABEL: 'SET_ACCOUNT_LABEL',
|
||||
setAccountLabel,
|
||||
// tx conf screen
|
||||
COMPLETED_TX: 'COMPLETED_TX',
|
||||
TRANSACTION_ERROR: 'TRANSACTION_ERROR',
|
||||
@ -1598,13 +1598,13 @@ function showPrivateKey (key) {
|
||||
}
|
||||
}
|
||||
|
||||
function saveAccountLabel (account, label) {
|
||||
function setAccountLabel (account, label) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
log.debug(`background.saveAccountLabel`)
|
||||
log.debug(`background.setAccountLabel`)
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
background.saveAccountLabel(account, label, (err) => {
|
||||
background.setAccountLabel(account, label, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
|
||||
if (err) {
|
||||
@ -1613,7 +1613,7 @@ function saveAccountLabel (account, label) {
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: actions.SAVE_ACCOUNT_LABEL,
|
||||
type: actions.SET_ACCOUNT_LABEL,
|
||||
value: { account, label },
|
||||
})
|
||||
|
||||
|
@ -25,7 +25,7 @@ function mapDispatchToProps (dispatch) {
|
||||
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
|
||||
},
|
||||
hideModal: () => dispatch(actions.hideModal()),
|
||||
saveAccountLabel: (address, label) => dispatch(actions.saveAccountLabel(address, label)),
|
||||
setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +49,7 @@ AccountDetailsModal.prototype.render = function () {
|
||||
selectedIdentity,
|
||||
network,
|
||||
showExportPrivateKeyModal,
|
||||
saveAccountLabel,
|
||||
setAccountLabel,
|
||||
} = this.props
|
||||
const { name, address } = selectedIdentity
|
||||
|
||||
@ -57,7 +57,7 @@ AccountDetailsModal.prototype.render = function () {
|
||||
h(EditableLabel, {
|
||||
className: 'account-modal__name',
|
||||
defaultValue: name,
|
||||
onSubmit: label => saveAccountLabel(address, label),
|
||||
onSubmit: label => setAccountLabel(address, label),
|
||||
}),
|
||||
|
||||
h(QrView, {
|
||||
|
@ -18,8 +18,8 @@ function mapDispatchToProps (dispatch) {
|
||||
hideModal: () => {
|
||||
dispatch(actions.hideModal())
|
||||
},
|
||||
saveAccountLabel: (account, label) => {
|
||||
dispatch(actions.saveAccountLabel(account, label))
|
||||
setAccountLabel: (account, label) => {
|
||||
dispatch(actions.setAccountLabel(account, label))
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -41,7 +41,7 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(EditAccountNameMod
|
||||
|
||||
|
||||
EditAccountNameModal.prototype.render = function () {
|
||||
const { hideModal, saveAccountLabel, identity } = this.props
|
||||
const { hideModal, setAccountLabel, identity } = this.props
|
||||
|
||||
return h('div', {}, [
|
||||
h('div.flex-column.edit-account-name-modal-content', {
|
||||
@ -69,7 +69,7 @@ EditAccountNameModal.prototype.render = function () {
|
||||
h('button.btn-clear.edit-account-name-modal-save-button.allcaps', {
|
||||
onClick: () => {
|
||||
if (this.state.inputText.length !== 0) {
|
||||
saveAccountLabel(identity.address, this.state.inputText)
|
||||
setAccountLabel(identity.address, this.state.inputText)
|
||||
hideModal()
|
||||
}
|
||||
},
|
||||
|
@ -95,7 +95,7 @@ const mapDispatchToProps = dispatch => {
|
||||
dispatch(actions.addNewAccount())
|
||||
.then((newAccountAddress) => {
|
||||
if (newAccountName) {
|
||||
dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName))
|
||||
dispatch(actions.setAccountLabel(newAccountAddress, newAccountName))
|
||||
}
|
||||
dispatch(actions.hideModal())
|
||||
})
|
||||
|
@ -75,7 +75,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
|
||||
},
|
||||
hideModal: () => dispatch(actions.hideModal()),
|
||||
saveAccountLabel: (address, label) => dispatch(actions.saveAccountLabel(address, label)),
|
||||
setAccountLabel: (address, label) => dispatch(actions.setAccountLabel(address, label)),
|
||||
})
|
||||
|
||||
module.exports = connect(mapStateToProps, mapDispatchToProps)(CreateAccountPage)
|
||||
|
@ -87,7 +87,7 @@ const mapDispatchToProps = dispatch => {
|
||||
return dispatch(actions.addNewAccount())
|
||||
.then(newAccountAddress => {
|
||||
if (newAccountName) {
|
||||
dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName))
|
||||
dispatch(actions.setAccountLabel(newAccountAddress, newAccountName))
|
||||
}
|
||||
})
|
||||
},
|
||||
|
@ -163,7 +163,7 @@ function reduceMetamask (state, action) {
|
||||
selectedTokenAddress: action.value,
|
||||
})
|
||||
|
||||
case actions.SAVE_ACCOUNT_LABEL:
|
||||
case actions.SET_ACCOUNT_LABEL:
|
||||
const account = action.value.account
|
||||
const name = action.value.label
|
||||
const id = {}
|
||||
|
Loading…
Reference in New Issue
Block a user