Merge pull request #4034 from whymarrh/account-nicknames

Move account names out of KeyringController
feature/default_network_editable
kumavis 7 years ago committed by GitHub
commit 08d95bbafa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 27
      app/scripts/controllers/address-book.js
  2. 30
      app/scripts/controllers/preferences.js
  3. 25
      app/scripts/metamask-controller.js
  4. 47
      app/scripts/migrations/026.js
  5. 1
      app/scripts/migrations/index.js
  6. 2
      old-ui/app/account-detail.js
  7. 22
      package-lock.json
  8. 2
      package.json
  9. 35
      test/unit/actions/save_account_label_test.js
  10. 34
      test/unit/actions/set_account_label_test.js
  11. 26
      test/unit/address-book-controller.js
  12. 2
      test/unit/metamask-controller-test.js
  13. 41
      test/unit/migrations/026-test.js
  14. 116
      test/unit/preferences-controller-test.js
  15. 2
      ui/app/accounts/new-account/index.js
  16. 12
      ui/app/actions.js
  17. 6
      ui/app/components/modals/account-details-modal.js
  18. 8
      ui/app/components/modals/edit-account-name-modal.js
  19. 2
      ui/app/components/modals/new-account-modal.js
  20. 2
      ui/app/components/pages/create-account/index.js
  21. 2
      ui/app/components/pages/create-account/new-account.js
  22. 2
      ui/app/reducers/metamask.js

@ -13,19 +13,17 @@ class AddressBookController {
* @param {object} opts Overrides the defaults for the initial state of this.store * @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 * @property {array} opts.initState initializes the the state of the AddressBookController. Can contain an
* addressBook property to initialize the addressBook array * addressBook property to initialize the addressBook array
* @param {KeyringController} keyringController (Soon to be deprecated) The keyringController used in the current * @property {object} opts.preferencesStore the {@code PreferencesController} store
* MetamaskController. Contains the identities used in this AddressBookController.
* @property {object} store The the store of the current users address book * @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 * @property {array} store.addressBook An array of addresses and nicknames. These are set by the user when sending
* to a new address. * to a new address.
* *
*/ */
constructor (opts = {}, keyringController) { constructor ({initState, preferencesStore}) {
const initState = extend({ this.store = new ObservableStore(extend({
addressBook: [], addressBook: [],
}, opts.initState) }, initState))
this.store = new ObservableStore(initState) this._preferencesStore = preferencesStore
this.keyringController = keyringController
} }
// //
@ -62,7 +60,7 @@ class AddressBookController {
*/ */
_addToAddressBook (address, name) { _addToAddressBook (address, name) {
const addressBook = this._getAddressBook() 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 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() }) const identitiesIndex = Object.keys(identities).findIndex((element) => { return element.toLowerCase() === address.toLowerCase() })
@ -95,19 +93,6 @@ class AddressBookController {
_getAddressBook () { _getAddressBook () {
return this.store.getState().addressBook 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 module.exports = AddressBookController

@ -27,6 +27,7 @@ class PreferencesController {
useBlockie: false, useBlockie: false,
featureFlags: {}, featureFlags: {},
currentLocale: opts.initLangCode, currentLocale: opts.initLangCode,
identities: {},
}, opts.initState) }, opts.initState)
this.store = new ObservableStore(initState) this.store = new ObservableStore(initState)
} }
@ -62,6 +63,16 @@ class PreferencesController {
this.store.updateState({ currentLocale: key }) 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 * Setter for the `selectedAddress` property
* *
@ -155,6 +166,21 @@ class PreferencesController {
return this.store.getState().tokens 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. * Gets an updated rpc list from this.addToFrequentRpcList() and sets the `frequentRpcList` to this update list.
* *
@ -189,8 +215,8 @@ class PreferencesController {
* The returned list will have a max length of 2. If the _url currently exists it the list, it will be moved to the * The returned list will have a max length of 2. If the _url currently exists it the list, it will be moved to the
* end of the list. The current list is modified and returned as a promise. * end of the list. The current list is modified and returned as a promise.
* *
* @param {string} _url The rpc url to add to the frequentRpcList. * @param {string} _url The rpc url to add to the frequentRpcList.
* @returns {Promise<array>} The updated frequentRpcList. * @returns {Promise<array>} The updated frequentRpcList.
* *
*/ */
addToFrequentRpcList (_url) { addToFrequentRpcList (_url) {

@ -144,7 +144,8 @@ module.exports = class MetamaskController extends EventEmitter {
// address book controller // address book controller
this.addressBookController = new AddressBookController({ this.addressBookController = new AddressBookController({
initState: initState.AddressBookController, initState: initState.AddressBookController,
}, this.keyringController) preferencesStore: this.preferencesController.store,
})
// tx mgmt // tx mgmt
this.txController = new TransactionController({ this.txController = new TransactionController({
@ -363,6 +364,7 @@ module.exports = class MetamaskController extends EventEmitter {
addToken: nodeify(preferencesController.addToken, preferencesController), addToken: nodeify(preferencesController.addToken, preferencesController),
removeToken: nodeify(preferencesController.removeToken, preferencesController), removeToken: nodeify(preferencesController.removeToken, preferencesController),
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController), setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab, preferencesController),
setAccountLabel: nodeify(preferencesController.setAccountLabel, preferencesController),
setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController), setFeatureFlag: nodeify(preferencesController.setFeatureFlag, preferencesController),
// AddressController // AddressController
@ -373,7 +375,6 @@ module.exports = class MetamaskController extends EventEmitter {
createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this), createNewVaultAndKeychain: nodeify(this.createNewVaultAndKeychain, this),
createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this), createNewVaultAndRestore: nodeify(this.createNewVaultAndRestore, this),
addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController), addNewKeyring: nodeify(keyringController.addNewKeyring, keyringController),
saveAccountLabel: nodeify(keyringController.saveAccountLabel, keyringController),
exportAccount: nodeify(keyringController.exportAccount, keyringController), exportAccount: nodeify(keyringController.exportAccount, keyringController),
// txController // txController
@ -433,7 +434,9 @@ module.exports = class MetamaskController extends EventEmitter {
} else { } else {
vault = await this.keyringController.createNewVaultAndKeychain(password) vault = await this.keyringController.createNewVaultAndKeychain(password)
this.selectFirstIdentity(vault) const accounts = await this.keyringController.getAccounts()
this.preferencesController.setAddresses(accounts)
this.selectFirstIdentity()
} }
release() release()
} catch (err) { } catch (err) {
@ -453,7 +456,9 @@ module.exports = class MetamaskController extends EventEmitter {
const release = await this.createVaultMutex.acquire() const release = await this.createVaultMutex.acquire()
try { try {
const vault = await this.keyringController.createNewVaultAndRestore(password, seed) const vault = await this.keyringController.createNewVaultAndRestore(password, seed)
this.selectFirstIdentity(vault) const accounts = await this.keyringController.getAccounts()
this.preferencesController.setAddresses(accounts)
this.selectFirstIdentity()
release() release()
return vault return vault
} catch (err) { } 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 * Sets the first address in the state to the selected address
*
* @param {} vault
*/ */
selectFirstIdentity (vault) { selectFirstIdentity () {
const { identities } = vault const { identities } = this.preferencesController.store.getState()
const address = Object.keys(identities)[0] const address = Object.keys(identities)[0]
this.preferencesController.setSelectedAddress(address) this.preferencesController.setSelectedAddress(address)
} }
@ -502,13 +505,15 @@ module.exports = class MetamaskController extends EventEmitter {
await this.verifySeedPhrase() await this.verifySeedPhrase()
this.preferencesController.setAddresses(newAccounts)
newAccounts.forEach((address) => { newAccounts.forEach((address) => {
if (!oldAccounts.includes(address)) { if (!oldAccounts.includes(address)) {
this.preferencesController.setSelectedAddress(address) this.preferencesController.setSelectedAddress(address)
} }
}) })
return keyState const {identities} = this.preferencesController.store.getState()
return {...keyState, identities}
} }
/** /**

@ -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('./023'),
require('./024'), require('./024'),
require('./025'), require('./025'),
require('./026'),
] ]

@ -91,7 +91,7 @@ AccountDetailScreen.prototype.render = function () {
isEditingLabel: false, isEditingLabel: false,
}, },
saveText: (text) => { saveText: (text) => {
props.dispatch(actions.saveAccountLabel(selected, text)) props.dispatch(actions.setAccountLabel(selected, text))
}, },
}, [ }, [

22
package-lock.json generated

@ -8054,9 +8054,9 @@
} }
}, },
"eth-keyring-controller": { "eth-keyring-controller": {
"version": "2.2.0", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-2.2.0.tgz", "resolved": "https://registry.npmjs.org/eth-keyring-controller/-/eth-keyring-controller-3.1.1.tgz",
"integrity": "sha512-f/g1ZrxciWJs2aHgpfvYmZ3ImP48GA+pobTU0EFNF/y5Yylf1zQyDw671W5opGpIt5TgV4F9sYXcvyjlgbL0Pg==", "integrity": "sha512-Z9HTzrop/V4Ld8Wq7uwetKecfWIyx25/uL8aFoZxV3kegZGoXaWoRmNy+4oW0WNLp4BcJ1lk6QfsGEdlymGjmA==",
"requires": { "requires": {
"bip39": "2.4.0", "bip39": "2.4.0",
"bluebird": "3.5.1", "bluebird": "3.5.1",
@ -8064,7 +8064,7 @@
"eth-hd-keyring": "1.2.2", "eth-hd-keyring": "1.2.2",
"eth-sig-util": "1.4.2", "eth-sig-util": "1.4.2",
"eth-simple-keyring": "1.2.1", "eth-simple-keyring": "1.2.1",
"ethereumjs-util": "5.1.5", "ethereumjs-util": "5.2.0",
"loglevel": "1.6.0", "loglevel": "1.6.0",
"obs-store": "2.4.1", "obs-store": "2.4.1",
"promise-filter": "1.1.0" "promise-filter": "1.1.0"
@ -8080,9 +8080,9 @@
} }
}, },
"ethereumjs-util": { "ethereumjs-util": {
"version": "5.1.5", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==", "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
"requires": { "requires": {
"bn.js": "4.11.8", "bn.js": "4.11.8",
"create-hash": "1.1.3", "create-hash": "1.1.3",
@ -8176,16 +8176,16 @@
"integrity": "sha1-bXs1LcWppQINYfafryHvsvY2P0U=", "integrity": "sha1-bXs1LcWppQINYfafryHvsvY2P0U=",
"requires": { "requires": {
"eth-sig-util": "1.4.2", "eth-sig-util": "1.4.2",
"ethereumjs-util": "5.1.5", "ethereumjs-util": "5.2.0",
"ethereumjs-wallet": "0.6.0", "ethereumjs-wallet": "0.6.0",
"events": "1.1.1", "events": "1.1.1",
"xtend": "4.0.1" "xtend": "4.0.1"
}, },
"dependencies": { "dependencies": {
"ethereumjs-util": { "ethereumjs-util": {
"version": "5.1.5", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.1.5.tgz", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz",
"integrity": "sha512-xPaSEATYJpMTCGowIt0oMZwFP4R1bxd6QsWgkcDvFL0JtXsr39p32WEcD14RscCjfP41YXZPCVWA4yAg0nrJmw==", "integrity": "sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA==",
"requires": { "requires": {
"bn.js": "4.11.8", "bn.js": "4.11.8",
"create-hash": "1.1.3", "create-hash": "1.1.3",

@ -95,7 +95,7 @@
"eth-hd-keyring": "^1.2.1", "eth-hd-keyring": "^1.2.1",
"eth-json-rpc-filters": "^1.2.6", "eth-json-rpc-filters": "^1.2.6",
"eth-json-rpc-infura": "^3.0.0", "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-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2", "eth-query": "^2.1.2",
"eth-sig-util": "^1.4.2", "eth-sig-util": "^1.4.2",

@ -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)
})
})

@ -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 assert = require('assert')
const AddressBookController = require('../../app/scripts/controllers/address-book') const AddressBookController = require('../../app/scripts/controllers/address-book')
const mockKeyringController = { const stubPreferencesStore = {
memStore: { getState: function () {
getState: function () { return {
return { identities: {
identities: { '0x0aaa': {
'0x0aaa': { address: '0x0aaa',
address: '0x0aaa', name: 'owned',
name: 'owned',
},
}, },
} },
}, }
}, },
} };
describe('address-book-controller', function () { describe('address-book-controller', function () {
var addressBookController var addressBookController
beforeEach(function () { beforeEach(function () {
addressBookController = new AddressBookController({}, mockKeyringController) addressBookController = new AddressBookController({
preferencesStore: stubPreferencesStore,
})
}) })
describe('addres book management', function () { describe('addres book management', function () {

@ -106,7 +106,7 @@ describe('MetaMaskController', function () {
[TEST_ADDRESS]: { address: TEST_ADDRESS, name: DEFAULT_LABEL }, [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, { assert.deepEqual(metamaskController.getState().identities, {
[TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' }, [TEST_ADDRESS]: { address: TEST_ADDRESS, name: 'Account Foo' },
}) })

@ -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)
})
})

@ -4,16 +4,91 @@ const PreferencesController = require('../../app/scripts/controllers/preferences
describe('preferences controller', function () { describe('preferences controller', function () {
let preferencesController let preferencesController
before(() => { beforeEach(() => {
preferencesController = new PreferencesController() 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 () { describe('addToken', function () {
it('should add that token to its state', async function () { it('should add that token to its state', async function () {
const address = '0xabcdef1234567' const address = '0xabcdef1234567'
const symbol = 'ABBR' const symbol = 'ABBR'
const decimals = 5 const decimals = 5
await preferencesController.setSelectedAddress('0x7e57e2')
await preferencesController.addToken(address, symbol, decimals) await preferencesController.addToken(address, symbol, decimals)
const tokens = preferencesController.getTokens() const tokens = preferencesController.getTokens()
@ -30,6 +105,7 @@ describe('preferences controller', function () {
const symbol = 'ABBR' const symbol = 'ABBR'
const decimals = 5 const decimals = 5
await preferencesController.setSelectedAddress('0x7e57e2')
await preferencesController.addToken(address, symbol, decimals) await preferencesController.addToken(address, symbol, decimals)
const newDecimals = 6 const newDecimals = 6
@ -43,6 +119,44 @@ describe('preferences controller', function () {
assert.equal(added.symbol, symbol, 'set symbol correctly') assert.equal(added.symbol, symbol, 'set symbol correctly')
assert.equal(added.decimals, newDecimals, 'updated decimals 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})
})
}) })
}) })

@ -24,7 +24,7 @@ function mapDispatchToProps (dispatch) {
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
}, },
hideModal: () => dispatch(actions.hideModal()), 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', SHOW_PRIVATE_KEY: 'SHOW_PRIVATE_KEY',
showPrivateKey: showPrivateKey, showPrivateKey: showPrivateKey,
exportAccountComplete, exportAccountComplete,
SAVE_ACCOUNT_LABEL: 'SAVE_ACCOUNT_LABEL', SET_ACCOUNT_LABEL: 'SET_ACCOUNT_LABEL',
saveAccountLabel: saveAccountLabel, setAccountLabel,
// tx conf screen // tx conf screen
COMPLETED_TX: 'COMPLETED_TX', COMPLETED_TX: 'COMPLETED_TX',
TRANSACTION_ERROR: 'TRANSACTION_ERROR', TRANSACTION_ERROR: 'TRANSACTION_ERROR',
@ -1598,13 +1598,13 @@ function showPrivateKey (key) {
} }
} }
function saveAccountLabel (account, label) { function setAccountLabel (account, label) {
return (dispatch) => { return (dispatch) => {
dispatch(actions.showLoadingIndication()) dispatch(actions.showLoadingIndication())
log.debug(`background.saveAccountLabel`) log.debug(`background.setAccountLabel`)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
background.saveAccountLabel(account, label, (err) => { background.setAccountLabel(account, label, (err) => {
dispatch(actions.hideLoadingIndication()) dispatch(actions.hideLoadingIndication())
if (err) { if (err) {
@ -1613,7 +1613,7 @@ function saveAccountLabel (account, label) {
} }
dispatch({ dispatch({
type: actions.SAVE_ACCOUNT_LABEL, type: actions.SET_ACCOUNT_LABEL,
value: { account, label }, value: { account, label },
}) })

@ -25,7 +25,7 @@ function mapDispatchToProps (dispatch) {
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
}, },
hideModal: () => dispatch(actions.hideModal()), 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, selectedIdentity,
network, network,
showExportPrivateKeyModal, showExportPrivateKeyModal,
saveAccountLabel, setAccountLabel,
} = this.props } = this.props
const { name, address } = selectedIdentity const { name, address } = selectedIdentity
@ -57,7 +57,7 @@ AccountDetailsModal.prototype.render = function () {
h(EditableLabel, { h(EditableLabel, {
className: 'account-modal__name', className: 'account-modal__name',
defaultValue: name, defaultValue: name,
onSubmit: label => saveAccountLabel(address, label), onSubmit: label => setAccountLabel(address, label),
}), }),
h(QrView, { h(QrView, {

@ -18,8 +18,8 @@ function mapDispatchToProps (dispatch) {
hideModal: () => { hideModal: () => {
dispatch(actions.hideModal()) dispatch(actions.hideModal())
}, },
saveAccountLabel: (account, label) => { setAccountLabel: (account, label) => {
dispatch(actions.saveAccountLabel(account, label)) dispatch(actions.setAccountLabel(account, label))
}, },
} }
} }
@ -41,7 +41,7 @@ module.exports = connect(mapStateToProps, mapDispatchToProps)(EditAccountNameMod
EditAccountNameModal.prototype.render = function () { EditAccountNameModal.prototype.render = function () {
const { hideModal, saveAccountLabel, identity } = this.props const { hideModal, setAccountLabel, identity } = this.props
return h('div', {}, [ return h('div', {}, [
h('div.flex-column.edit-account-name-modal-content', { 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', { h('button.btn-clear.edit-account-name-modal-save-button.allcaps', {
onClick: () => { onClick: () => {
if (this.state.inputText.length !== 0) { if (this.state.inputText.length !== 0) {
saveAccountLabel(identity.address, this.state.inputText) setAccountLabel(identity.address, this.state.inputText)
hideModal() hideModal()
} }
}, },

@ -95,7 +95,7 @@ const mapDispatchToProps = dispatch => {
dispatch(actions.addNewAccount()) dispatch(actions.addNewAccount())
.then((newAccountAddress) => { .then((newAccountAddress) => {
if (newAccountName) { if (newAccountName) {
dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName)) dispatch(actions.setAccountLabel(newAccountAddress, newAccountName))
} }
dispatch(actions.hideModal()) dispatch(actions.hideModal())
}) })

@ -75,7 +75,7 @@ const mapDispatchToProps = dispatch => ({
dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' })) dispatch(actions.showModal({ name: 'EXPORT_PRIVATE_KEY' }))
}, },
hideModal: () => dispatch(actions.hideModal()), 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) module.exports = connect(mapStateToProps, mapDispatchToProps)(CreateAccountPage)

@ -87,7 +87,7 @@ const mapDispatchToProps = dispatch => {
return dispatch(actions.addNewAccount()) return dispatch(actions.addNewAccount())
.then(newAccountAddress => { .then(newAccountAddress => {
if (newAccountName) { if (newAccountName) {
dispatch(actions.saveAccountLabel(newAccountAddress, newAccountName)) dispatch(actions.setAccountLabel(newAccountAddress, newAccountName))
} }
}) })
}, },

@ -163,7 +163,7 @@ function reduceMetamask (state, action) {
selectedTokenAddress: action.value, selectedTokenAddress: action.value,
}) })
case actions.SAVE_ACCOUNT_LABEL: case actions.SET_ACCOUNT_LABEL:
const account = action.value.account const account = action.value.account
const name = action.value.label const name = action.value.label
const id = {} const id = {}

Loading…
Cancel
Save