mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Merge pull request #4884 from MetaMask/TokensPerAccountBasis
Tokens per account & network basis
This commit is contained in:
commit
e9f74f005d
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
|
- [#4884](https://github.com/MetaMask/metamask-extension/pull/4884): Allow to have tokens per account and network.
|
||||||
|
|
||||||
## 4.9.0 Tue Aug 07 2018
|
## 4.9.0 Tue Aug 07 2018
|
||||||
|
|
||||||
- Add new tokens auto detection
|
- Add new tokens auto detection
|
||||||
|
@ -85,7 +85,7 @@ class DetectTokensController {
|
|||||||
set preferences (preferences) {
|
set preferences (preferences) {
|
||||||
if (!preferences) { return }
|
if (!preferences) { return }
|
||||||
this._preferences = preferences
|
this._preferences = preferences
|
||||||
preferences.store.subscribe(({ tokens }) => { this.tokenAddresses = tokens.map((obj) => { return obj.address }) })
|
preferences.store.subscribe(({ tokens = [] }) => { this.tokenAddresses = tokens.map((obj) => { return obj.address }) })
|
||||||
preferences.store.subscribe(({ selectedAddress }) => {
|
preferences.store.subscribe(({ selectedAddress }) => {
|
||||||
if (this.selectedAddress !== selectedAddress) {
|
if (this.selectedAddress !== selectedAddress) {
|
||||||
this.selectedAddress = selectedAddress
|
this.selectedAddress = selectedAddress
|
||||||
|
@ -13,6 +13,7 @@ class PreferencesController {
|
|||||||
* @property {array} store.frequentRpcList A list of custom rpcs to provide the user
|
* @property {array} store.frequentRpcList A list of custom rpcs to provide the user
|
||||||
* @property {string} store.currentAccountTab Indicates the selected tab in the ui
|
* @property {string} store.currentAccountTab Indicates the selected tab in the ui
|
||||||
* @property {array} store.tokens The tokens the user wants display in their token lists
|
* @property {array} store.tokens The tokens the user wants display in their token lists
|
||||||
|
* @property {object} store.accountTokens The tokens stored per account and then per network type
|
||||||
* @property {boolean} store.useBlockie The users preference for blockie identicons within the UI
|
* @property {boolean} store.useBlockie The users preference for blockie identicons within the UI
|
||||||
* @property {object} store.featureFlags A key-boolean map, where keys refer to features and booleans to whether the
|
* @property {object} store.featureFlags A key-boolean map, where keys refer to features and booleans to whether the
|
||||||
* user wishes to see that feature
|
* user wishes to see that feature
|
||||||
@ -24,6 +25,7 @@ class PreferencesController {
|
|||||||
const initState = extend({
|
const initState = extend({
|
||||||
frequentRpcList: [],
|
frequentRpcList: [],
|
||||||
currentAccountTab: 'history',
|
currentAccountTab: 'history',
|
||||||
|
accountTokens: {},
|
||||||
tokens: [],
|
tokens: [],
|
||||||
useBlockie: false,
|
useBlockie: false,
|
||||||
featureFlags: {},
|
featureFlags: {},
|
||||||
@ -33,8 +35,9 @@ class PreferencesController {
|
|||||||
}, opts.initState)
|
}, opts.initState)
|
||||||
|
|
||||||
this.diagnostics = opts.diagnostics
|
this.diagnostics = opts.diagnostics
|
||||||
|
this.network = opts.network
|
||||||
this.store = new ObservableStore(initState)
|
this.store = new ObservableStore(initState)
|
||||||
|
this._subscribeProviderType()
|
||||||
}
|
}
|
||||||
// PUBLIC METHODS
|
// PUBLIC METHODS
|
||||||
|
|
||||||
@ -77,12 +80,19 @@ class PreferencesController {
|
|||||||
*/
|
*/
|
||||||
setAddresses (addresses) {
|
setAddresses (addresses) {
|
||||||
const oldIdentities = this.store.getState().identities
|
const oldIdentities = this.store.getState().identities
|
||||||
|
const oldAccountTokens = this.store.getState().accountTokens
|
||||||
|
|
||||||
const identities = addresses.reduce((ids, address, index) => {
|
const identities = addresses.reduce((ids, address, index) => {
|
||||||
const oldId = oldIdentities[address] || {}
|
const oldId = oldIdentities[address] || {}
|
||||||
ids[address] = {name: `Account ${index + 1}`, address, ...oldId}
|
ids[address] = {name: `Account ${index + 1}`, address, ...oldId}
|
||||||
return ids
|
return ids
|
||||||
}, {})
|
}, {})
|
||||||
this.store.updateState({ identities })
|
const accountTokens = addresses.reduce((tokens, address) => {
|
||||||
|
const oldTokens = oldAccountTokens[address] || {}
|
||||||
|
tokens[address] = oldTokens
|
||||||
|
return tokens
|
||||||
|
}, {})
|
||||||
|
this.store.updateState({ identities, accountTokens })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,11 +103,13 @@ class PreferencesController {
|
|||||||
*/
|
*/
|
||||||
removeAddress (address) {
|
removeAddress (address) {
|
||||||
const identities = this.store.getState().identities
|
const identities = this.store.getState().identities
|
||||||
|
const accountTokens = this.store.getState().accountTokens
|
||||||
if (!identities[address]) {
|
if (!identities[address]) {
|
||||||
throw new Error(`${address} can't be deleted cause it was not found`)
|
throw new Error(`${address} can't be deleted cause it was not found`)
|
||||||
}
|
}
|
||||||
delete identities[address]
|
delete identities[address]
|
||||||
this.store.updateState({ identities })
|
delete accountTokens[address]
|
||||||
|
this.store.updateState({ identities, accountTokens })
|
||||||
|
|
||||||
// If the selected account is no longer valid,
|
// If the selected account is no longer valid,
|
||||||
// select an arbitrary other account:
|
// select an arbitrary other account:
|
||||||
@ -117,14 +129,17 @@ class PreferencesController {
|
|||||||
*/
|
*/
|
||||||
addAddresses (addresses) {
|
addAddresses (addresses) {
|
||||||
const identities = this.store.getState().identities
|
const identities = this.store.getState().identities
|
||||||
|
const accountTokens = this.store.getState().accountTokens
|
||||||
addresses.forEach((address) => {
|
addresses.forEach((address) => {
|
||||||
// skip if already exists
|
// skip if already exists
|
||||||
if (identities[address]) return
|
if (identities[address]) return
|
||||||
// add missing identity
|
// add missing identity
|
||||||
const identityCount = Object.keys(identities).length
|
const identityCount = Object.keys(identities).length
|
||||||
|
|
||||||
|
accountTokens[address] = {}
|
||||||
identities[address] = { name: `Account ${identityCount + 1}`, address }
|
identities[address] = { name: `Account ${identityCount + 1}`, address }
|
||||||
})
|
})
|
||||||
this.store.updateState({ identities })
|
this.store.updateState({ identities, accountTokens })
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -175,15 +190,15 @@ class PreferencesController {
|
|||||||
* Setter for the `selectedAddress` property
|
* Setter for the `selectedAddress` property
|
||||||
*
|
*
|
||||||
* @param {string} _address A new hex address for an account
|
* @param {string} _address A new hex address for an account
|
||||||
* @returns {Promise<void>} Promise resolves with undefined
|
* @returns {Promise<void>} Promise resolves with tokens
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
setSelectedAddress (_address) {
|
setSelectedAddress (_address) {
|
||||||
return new Promise((resolve, reject) => {
|
const address = normalizeAddress(_address)
|
||||||
const address = normalizeAddress(_address)
|
this._updateTokens(address)
|
||||||
this.store.updateState({ selectedAddress: address })
|
this.store.updateState({ selectedAddress: address })
|
||||||
resolve()
|
const tokens = this.store.getState().tokens
|
||||||
})
|
return Promise.resolve(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -232,9 +247,7 @@ class PreferencesController {
|
|||||||
} else {
|
} else {
|
||||||
tokens.push(newEntry)
|
tokens.push(newEntry)
|
||||||
}
|
}
|
||||||
|
this._updateAccountTokens(tokens)
|
||||||
this.store.updateState({ tokens })
|
|
||||||
|
|
||||||
return Promise.resolve(tokens)
|
return Promise.resolve(tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,10 +260,8 @@ class PreferencesController {
|
|||||||
*/
|
*/
|
||||||
removeToken (rawAddress) {
|
removeToken (rawAddress) {
|
||||||
const tokens = this.store.getState().tokens
|
const tokens = this.store.getState().tokens
|
||||||
|
|
||||||
const updatedTokens = tokens.filter(token => token.address !== rawAddress)
|
const updatedTokens = tokens.filter(token => token.address !== rawAddress)
|
||||||
|
this._updateAccountTokens(updatedTokens)
|
||||||
this.store.updateState({ tokens: updatedTokens })
|
|
||||||
return Promise.resolve(updatedTokens)
|
return Promise.resolve(updatedTokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +387,57 @@ class PreferencesController {
|
|||||||
//
|
//
|
||||||
// PRIVATE METHODS
|
// PRIVATE METHODS
|
||||||
//
|
//
|
||||||
|
/**
|
||||||
|
* Subscription to network provider type.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_subscribeProviderType () {
|
||||||
|
this.network.providerStore.subscribe(() => {
|
||||||
|
const { tokens } = this._getTokenRelatedStates()
|
||||||
|
this.store.updateState({ tokens })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates `accountTokens` and `tokens` of current account and network according to it.
|
||||||
|
*
|
||||||
|
* @param {array} tokens Array of tokens to be updated.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_updateAccountTokens (tokens) {
|
||||||
|
const { accountTokens, providerType, selectedAddress } = this._getTokenRelatedStates()
|
||||||
|
accountTokens[selectedAddress][providerType] = tokens
|
||||||
|
this.store.updateState({ accountTokens, tokens })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates `tokens` of current account and network.
|
||||||
|
*
|
||||||
|
* @param {string} selectedAddress Account address to be updated with.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_updateTokens (selectedAddress) {
|
||||||
|
const { tokens } = this._getTokenRelatedStates(selectedAddress)
|
||||||
|
this.store.updateState({ tokens })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A getter for `tokens` and `accountTokens` related states.
|
||||||
|
*
|
||||||
|
* @param {string} selectedAddress A new hex address for an account
|
||||||
|
* @returns {Object.<array, object, string, string>} States to interact with tokens in `accountTokens`
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
_getTokenRelatedStates (selectedAddress) {
|
||||||
|
const accountTokens = this.store.getState().accountTokens
|
||||||
|
if (!selectedAddress) selectedAddress = this.store.getState().selectedAddress
|
||||||
|
const providerType = this.network.providerStore.getState().type
|
||||||
|
if (!(selectedAddress in accountTokens)) accountTokens[selectedAddress] = {}
|
||||||
|
if (!(providerType in accountTokens[selectedAddress])) accountTokens[selectedAddress][providerType] = []
|
||||||
|
const tokens = accountTokens[selectedAddress][providerType]
|
||||||
|
return { tokens, accountTokens, providerType, selectedAddress }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = PreferencesController
|
module.exports = PreferencesController
|
||||||
|
@ -87,6 +87,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
this.preferencesController = new PreferencesController({
|
this.preferencesController = new PreferencesController({
|
||||||
initState: initState.PreferencesController,
|
initState: initState.PreferencesController,
|
||||||
initLangCode: opts.initLangCode,
|
initLangCode: opts.initLangCode,
|
||||||
|
network: this.networkController,
|
||||||
})
|
})
|
||||||
|
|
||||||
// currency controller
|
// currency controller
|
||||||
@ -1436,7 +1437,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A method for activating the retrieval of price data and auto detect tokens,
|
* A method for activating the retrieval of price data,
|
||||||
* which should only be fetched when the UI is visible.
|
* which should only be fetched when the UI is visible.
|
||||||
* @private
|
* @private
|
||||||
* @param {boolean} active - True if price data should be getting fetched.
|
* @param {boolean} active - True if price data should be getting fetched.
|
||||||
|
40
app/scripts/migrations/028.js
Normal file
40
app/scripts/migrations/028.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// next version number
|
||||||
|
const version = 28
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
normalizes txParams on unconfirmed txs
|
||||||
|
|
||||||
|
*/
|
||||||
|
const clone = require('clone')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
version,
|
||||||
|
|
||||||
|
migrate: async function (originalVersionedData) {
|
||||||
|
const versionedData = clone(originalVersionedData)
|
||||||
|
versionedData.meta.version = version
|
||||||
|
const state = versionedData.data
|
||||||
|
const newState = transformState(state)
|
||||||
|
versionedData.data = newState
|
||||||
|
return versionedData
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function transformState (state) {
|
||||||
|
const newState = state
|
||||||
|
|
||||||
|
if (newState.PreferencesController) {
|
||||||
|
if (newState.PreferencesController.tokens) {
|
||||||
|
const identities = newState.TransactionController.identities
|
||||||
|
const tokens = newState.PreferencesController.tokens
|
||||||
|
newState.PreferencesController.accountTokens = {}
|
||||||
|
for (const identity in identities) {
|
||||||
|
newState.PreferencesController.accountTokens[identity] = {'mainnet': tokens}
|
||||||
|
}
|
||||||
|
newState.PreferencesController.tokens = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState
|
||||||
|
}
|
@ -38,4 +38,5 @@ module.exports = [
|
|||||||
require('./025'),
|
require('./025'),
|
||||||
require('./026'),
|
require('./026'),
|
||||||
require('./027'),
|
require('./027'),
|
||||||
|
require('./028'),
|
||||||
]
|
]
|
||||||
|
@ -7,10 +7,11 @@ const PreferencesController = require('../../../../app/scripts/controllers/prefe
|
|||||||
|
|
||||||
describe('DetectTokensController', () => {
|
describe('DetectTokensController', () => {
|
||||||
const sandbox = sinon.createSandbox()
|
const sandbox = sinon.createSandbox()
|
||||||
let clock
|
let clock, keyringMemStore, network, preferences
|
||||||
let keyringMemStore
|
beforeEach(async () => {
|
||||||
before(async () => {
|
|
||||||
keyringMemStore = new ObservableStore({ isUnlocked: false})
|
keyringMemStore = new ObservableStore({ isUnlocked: false})
|
||||||
|
network = new NetworkController({ provider: { type: 'mainnet' }})
|
||||||
|
preferences = new PreferencesController({ network })
|
||||||
})
|
})
|
||||||
after(() => {
|
after(() => {
|
||||||
sandbox.restore()
|
sandbox.restore()
|
||||||
@ -25,9 +26,7 @@ describe('DetectTokensController', () => {
|
|||||||
|
|
||||||
it('should be called on every polling period', async () => {
|
it('should be called on every polling period', async () => {
|
||||||
clock = sandbox.useFakeTimers()
|
clock = sandbox.useFakeTimers()
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('mainnet')
|
network.setProviderType('mainnet')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
controller.isUnlocked = true
|
controller.isUnlocked = true
|
||||||
@ -45,9 +44,7 @@ describe('DetectTokensController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not check tokens while in test network', async () => {
|
it('should not check tokens while in test network', async () => {
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('rinkeby')
|
network.setProviderType('rinkeby')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
controller.isUnlocked = true
|
controller.isUnlocked = true
|
||||||
@ -61,9 +58,7 @@ describe('DetectTokensController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should only check and add tokens while in main network', async () => {
|
it('should only check and add tokens while in main network', async () => {
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('mainnet')
|
network.setProviderType('mainnet')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
controller.isUnlocked = true
|
controller.isUnlocked = true
|
||||||
@ -80,9 +75,7 @@ describe('DetectTokensController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not detect same token while in main network', async () => {
|
it('should not detect same token while in main network', async () => {
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('mainnet')
|
network.setProviderType('mainnet')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)
|
preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
@ -100,9 +93,7 @@ describe('DetectTokensController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger detect new tokens when change address', async () => {
|
it('should trigger detect new tokens when change address', async () => {
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('mainnet')
|
network.setProviderType('mainnet')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
controller.isUnlocked = true
|
controller.isUnlocked = true
|
||||||
@ -112,9 +103,7 @@ describe('DetectTokensController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger detect new tokens when submit password', async () => {
|
it('should trigger detect new tokens when submit password', async () => {
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('mainnet')
|
network.setProviderType('mainnet')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
controller.selectedAddress = '0x0'
|
controller.selectedAddress = '0x0'
|
||||||
@ -124,9 +113,7 @@ describe('DetectTokensController', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should not trigger detect new tokens when not open or not unlocked', async () => {
|
it('should not trigger detect new tokens when not open or not unlocked', async () => {
|
||||||
const network = new NetworkController()
|
|
||||||
network.setProviderType('mainnet')
|
network.setProviderType('mainnet')
|
||||||
const preferences = new PreferencesController()
|
|
||||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||||
controller.isOpen = true
|
controller.isOpen = true
|
||||||
controller.isUnlocked = false
|
controller.isUnlocked = false
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
const assert = require('assert')
|
const assert = require('assert')
|
||||||
|
const ObservableStore = require('obs-store')
|
||||||
const PreferencesController = require('../../../../app/scripts/controllers/preferences')
|
const PreferencesController = require('../../../../app/scripts/controllers/preferences')
|
||||||
|
|
||||||
describe('preferences controller', function () {
|
describe('preferences controller', function () {
|
||||||
let preferencesController
|
let preferencesController
|
||||||
|
let network
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
preferencesController = new PreferencesController()
|
network = {providerStore: new ObservableStore({ type: 'mainnet' })}
|
||||||
|
preferencesController = new PreferencesController({ network })
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('setAddresses', function () {
|
describe('setAddresses', function () {
|
||||||
@ -28,6 +31,20 @@ describe('preferences controller', function () {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should create account tokens for each account in the store', function () {
|
||||||
|
preferencesController.setAddresses([
|
||||||
|
'0xda22le',
|
||||||
|
'0x7e57e2',
|
||||||
|
])
|
||||||
|
|
||||||
|
const accountTokens = preferencesController.store.getState().accountTokens
|
||||||
|
|
||||||
|
assert.deepEqual(accountTokens, {
|
||||||
|
'0xda22le': {},
|
||||||
|
'0x7e57e2': {},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('should replace its list of addresses', function () {
|
it('should replace its list of addresses', function () {
|
||||||
preferencesController.setAddresses([
|
preferencesController.setAddresses([
|
||||||
'0xda22le',
|
'0xda22le',
|
||||||
@ -64,6 +81,17 @@ describe('preferences controller', function () {
|
|||||||
assert.equal(preferencesController.store.getState().identities['0xda22le'], undefined)
|
assert.equal(preferencesController.store.getState().identities['0xda22le'], undefined)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should remove an address from state and respective tokens', function () {
|
||||||
|
preferencesController.setAddresses([
|
||||||
|
'0xda22le',
|
||||||
|
'0x7e57e2',
|
||||||
|
])
|
||||||
|
|
||||||
|
preferencesController.removeAddress('0xda22le')
|
||||||
|
|
||||||
|
assert.equal(preferencesController.store.getState().accountTokens['0xda22le'], undefined)
|
||||||
|
})
|
||||||
|
|
||||||
it('should switch accounts if the selected address is removed', function () {
|
it('should switch accounts if the selected address is removed', function () {
|
||||||
preferencesController.setAddresses([
|
preferencesController.setAddresses([
|
||||||
'0xda22le',
|
'0xda22le',
|
||||||
@ -158,6 +186,42 @@ describe('preferences controller', function () {
|
|||||||
await preferencesController.addToken(address, symbol, decimals)
|
await preferencesController.addToken(address, symbol, decimals)
|
||||||
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 2nd address')
|
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 2nd address')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should add token per account', async function () {
|
||||||
|
const addressFirst = '0xabcdef1234567'
|
||||||
|
const addressSecond = '0xabcdef1234568'
|
||||||
|
const symbolFirst = 'ABBR'
|
||||||
|
const symbolSecond = 'ABBB'
|
||||||
|
const decimals = 5
|
||||||
|
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
await preferencesController.addToken(addressFirst, symbolFirst, decimals)
|
||||||
|
const tokensFirstAddress = preferencesController.getTokens()
|
||||||
|
|
||||||
|
await preferencesController.setSelectedAddress('0xda22le')
|
||||||
|
await preferencesController.addToken(addressSecond, symbolSecond, decimals)
|
||||||
|
const tokensSeconAddress = preferencesController.getTokens()
|
||||||
|
|
||||||
|
assert.notEqual(tokensFirstAddress, tokensSeconAddress, 'add different tokens for two account and tokens are equal')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should add token per network', async function () {
|
||||||
|
const addressFirst = '0xabcdef1234567'
|
||||||
|
const addressSecond = '0xabcdef1234568'
|
||||||
|
const symbolFirst = 'ABBR'
|
||||||
|
const symbolSecond = 'ABBB'
|
||||||
|
const decimals = 5
|
||||||
|
|
||||||
|
network.providerStore.updateState({ type: 'mainnet' })
|
||||||
|
await preferencesController.addToken(addressFirst, symbolFirst, decimals)
|
||||||
|
const tokensFirstAddress = preferencesController.getTokens()
|
||||||
|
|
||||||
|
network.providerStore.updateState({ type: 'rinkeby' })
|
||||||
|
await preferencesController.addToken(addressSecond, symbolSecond, decimals)
|
||||||
|
const tokensSeconAddress = preferencesController.getTokens()
|
||||||
|
|
||||||
|
assert.notEqual(tokensFirstAddress, tokensSeconAddress, 'add different tokens for two networks and tokens are equal')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('removeToken', function () {
|
describe('removeToken', function () {
|
||||||
@ -182,6 +246,98 @@ describe('preferences controller', function () {
|
|||||||
const [token1] = tokens
|
const [token1] = tokens
|
||||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should remove a token from its state on corresponding address', async function () {
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
await preferencesController.addToken('0xa', 'A', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'B', 5)
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||||
|
await preferencesController.addToken('0xa', 'A', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'B', 5)
|
||||||
|
const initialTokensSecond = preferencesController.getTokens()
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
await preferencesController.removeToken('0xa')
|
||||||
|
|
||||||
|
const tokensFirst = preferencesController.getTokens()
|
||||||
|
assert.equal(tokensFirst.length, 1, 'one token removed in account')
|
||||||
|
|
||||||
|
const [token1] = tokensFirst
|
||||||
|
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||||
|
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||||
|
const tokensSecond = preferencesController.getTokens()
|
||||||
|
assert.deepEqual(tokensSecond, initialTokensSecond, 'token deleted for account')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should remove a token from its state on corresponding network', async function () {
|
||||||
|
network.providerStore.updateState({ type: 'mainnet' })
|
||||||
|
await preferencesController.addToken('0xa', 'A', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'B', 5)
|
||||||
|
network.providerStore.updateState({ type: 'rinkeby' })
|
||||||
|
await preferencesController.addToken('0xa', 'A', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'B', 5)
|
||||||
|
const initialTokensSecond = preferencesController.getTokens()
|
||||||
|
network.providerStore.updateState({ type: 'mainnet' })
|
||||||
|
await preferencesController.removeToken('0xa')
|
||||||
|
|
||||||
|
const tokensFirst = preferencesController.getTokens()
|
||||||
|
assert.equal(tokensFirst.length, 1, 'one token removed in network')
|
||||||
|
|
||||||
|
const [token1] = tokensFirst
|
||||||
|
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||||
|
|
||||||
|
network.providerStore.updateState({ type: 'rinkeby' })
|
||||||
|
const tokensSecond = preferencesController.getTokens()
|
||||||
|
assert.deepEqual(tokensSecond, initialTokensSecond, 'token deleted for network')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('on setSelectedAddress', function () {
|
||||||
|
it('should update tokens from its state on corresponding address', async function () {
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
await preferencesController.addToken('0xa', 'A', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'B', 5)
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||||
|
await preferencesController.addToken('0xa', 'C', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'D', 5)
|
||||||
|
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
const initialTokensFirst = preferencesController.getTokens()
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||||
|
const initialTokensSecond = preferencesController.getTokens()
|
||||||
|
|
||||||
|
assert.notDeepEqual(initialTokensFirst, initialTokensSecond, 'tokens not equal for different accounts and tokens')
|
||||||
|
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||||
|
const tokensFirst = preferencesController.getTokens()
|
||||||
|
await preferencesController.setSelectedAddress('0x7e57e3')
|
||||||
|
const tokensSecond = preferencesController.getTokens()
|
||||||
|
|
||||||
|
assert.deepEqual(tokensFirst, initialTokensFirst, 'tokens equal for same account')
|
||||||
|
assert.deepEqual(tokensSecond, initialTokensSecond, 'tokens equal for same account')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('on updateStateNetworkType', function () {
|
||||||
|
it('should remove a token from its state on corresponding network', async function () {
|
||||||
|
network.providerStore.updateState({ type: 'mainnet' })
|
||||||
|
await preferencesController.addToken('0xa', 'A', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'B', 5)
|
||||||
|
const initialTokensFirst = preferencesController.getTokens()
|
||||||
|
network.providerStore.updateState({ type: 'rinkeby' })
|
||||||
|
await preferencesController.addToken('0xa', 'C', 4)
|
||||||
|
await preferencesController.addToken('0xb', 'D', 5)
|
||||||
|
const initialTokensSecond = preferencesController.getTokens()
|
||||||
|
|
||||||
|
assert.notDeepEqual(initialTokensFirst, initialTokensSecond, 'tokens not equal for different networks and tokens')
|
||||||
|
|
||||||
|
network.providerStore.updateState({ type: 'mainnet' })
|
||||||
|
const tokensFirst = preferencesController.getTokens()
|
||||||
|
network.providerStore.updateState({ type: 'rinkeby' })
|
||||||
|
const tokensSecond = preferencesController.getTokens()
|
||||||
|
assert.deepEqual(tokensFirst, initialTokensFirst, 'tokens equal for same network')
|
||||||
|
assert.deepEqual(tokensSecond, initialTokensSecond, 'tokens equal for same network')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1483,11 +1483,12 @@ function showAccountDetail (address) {
|
|||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
dispatch(actions.showLoadingIndication())
|
dispatch(actions.showLoadingIndication())
|
||||||
log.debug(`background.setSelectedAddress`)
|
log.debug(`background.setSelectedAddress`)
|
||||||
background.setSelectedAddress(address, (err) => {
|
background.setSelectedAddress(address, (err, tokens) => {
|
||||||
dispatch(actions.hideLoadingIndication())
|
dispatch(actions.hideLoadingIndication())
|
||||||
if (err) {
|
if (err) {
|
||||||
return dispatch(actions.displayWarning(err.message))
|
return dispatch(actions.displayWarning(err.message))
|
||||||
}
|
}
|
||||||
|
dispatch(updateTokens(tokens))
|
||||||
dispatch({
|
dispatch({
|
||||||
type: actions.SHOW_ACCOUNT_DETAIL,
|
type: actions.SHOW_ACCOUNT_DETAIL,
|
||||||
value: address,
|
value: address,
|
||||||
|
Loading…
Reference in New Issue
Block a user