-
Notifications
You must be signed in to change notification settings - Fork 5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tokens per account & network basis #4884
Changes from 10 commits
2770df8
adee549
1d3ad7c
2827e13
f79a249
f5107fa
5b9725d
228f48c
e687bc5
dd6a725
0757f47
3128667
fbcba8f
822c173
22cf5a1
ccae79d
3124e8c
d8817b2
c0cdda8
b3af9cd
66c76c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ class PreferencesController { | |
* @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 {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 {object} store.featureFlags A key-boolean map, where keys refer to features and booleans to whether the | ||
* user wishes to see that feature | ||
|
@@ -24,6 +25,7 @@ class PreferencesController { | |
const initState = extend({ | ||
frequentRpcList: [], | ||
currentAccountTab: 'history', | ||
accountTokens: {}, | ||
tokens: [], | ||
useBlockie: false, | ||
featureFlags: {}, | ||
|
@@ -33,8 +35,10 @@ class PreferencesController { | |
}, opts.initState) | ||
|
||
this.diagnostics = opts.diagnostics | ||
|
||
this.network = opts.network | ||
this.store = new ObservableStore(initState) | ||
this._defineTokens() | ||
this._subscribeProviderType() | ||
} | ||
// PUBLIC METHODS | ||
|
||
|
@@ -77,12 +81,17 @@ class PreferencesController { | |
*/ | ||
setAddresses (addresses) { | ||
const oldIdentities = this.store.getState().identities | ||
const accountTokens = this.store.getState().accountTokens | ||
|
||
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 }) | ||
for (const address in identities) { | ||
if (!(address in accountTokens)) accountTokens[address] = {} | ||
} | ||
this.store.updateState({ identities, accountTokens }) | ||
} | ||
|
||
/** | ||
|
@@ -93,11 +102,13 @@ class PreferencesController { | |
*/ | ||
removeAddress (address) { | ||
const identities = this.store.getState().identities | ||
const accountTokens = this.store.getState().accountTokens | ||
if (!identities[address]) { | ||
throw new Error(`${address} can't be deleted cause it was not found`) | ||
} | ||
delete identities[address] | ||
this.store.updateState({ identities }) | ||
delete accountTokens[address] | ||
this.store.updateState({ identities, accountTokens }) | ||
|
||
// If the selected account is no longer valid, | ||
// select an arbitrary other account: | ||
|
@@ -117,14 +128,17 @@ class PreferencesController { | |
*/ | ||
addAddresses (addresses) { | ||
const identities = this.store.getState().identities | ||
const accountTokens = this.store.getState().accountTokens | ||
addresses.forEach((address) => { | ||
// skip if already exists | ||
if (identities[address]) return | ||
// add missing identity | ||
const identityCount = Object.keys(identities).length | ||
|
||
if (!(address in accountTokens)) accountTokens[address] = {} | ||
identities[address] = { name: `Account ${identityCount + 1}`, address } | ||
}) | ||
this.store.updateState({ identities }) | ||
this.store.updateState({ identities, accountTokens }) | ||
} | ||
|
||
/* | ||
|
@@ -179,11 +193,16 @@ class PreferencesController { | |
* | ||
*/ | ||
setSelectedAddress (_address) { | ||
return new Promise((resolve, reject) => { | ||
const address = normalizeAddress(_address) | ||
this.store.updateState({ selectedAddress: address }) | ||
resolve() | ||
}) | ||
const address = normalizeAddress(_address) | ||
const accountTokens = this.store.getState().accountTokens | ||
const providerType = this.network.providerStore.getState().type | ||
|
||
if (!(address in accountTokens)) accountTokens[address] = {} | ||
if (!(providerType in accountTokens[address])) accountTokens[address][providerType] = [] | ||
const tokens = accountTokens[address][providerType] | ||
this.store.updateState({ selectedAddress: address, tokens }) | ||
|
||
return Promise.resolve(tokens) | ||
} | ||
|
||
/** | ||
|
@@ -233,7 +252,11 @@ class PreferencesController { | |
tokens.push(newEntry) | ||
} | ||
|
||
this.store.updateState({ tokens }) | ||
const selectedAddress = this.store.getState().selectedAddress | ||
const accountTokens = this.store.getState().accountTokens | ||
const providerType = this.network.providerStore.getState().type | ||
accountTokens[selectedAddress][providerType] = tokens | ||
this.store.updateState({ accountTokens, tokens }) | ||
|
||
return Promise.resolve(tokens) | ||
} | ||
|
@@ -246,11 +269,13 @@ class PreferencesController { | |
* | ||
*/ | ||
removeToken (rawAddress) { | ||
const tokens = this.store.getState().tokens | ||
const accountTokens = this.store.getState().accountTokens | ||
const selectedAddress = this.store.getState().selectedAddress | ||
const providerType = this.network.providerStore.getState().type | ||
const updatedTokens = accountTokens[selectedAddress][providerType].filter(token => token.address !== rawAddress) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might want to normalize the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The normalization of |
||
accountTokens[selectedAddress][providerType] = updatedTokens | ||
this.store.updateState({ accountTokens, tokens: updatedTokens }) | ||
|
||
const updatedTokens = tokens.filter(token => token.address !== rawAddress) | ||
|
||
this.store.updateState({ tokens: updatedTokens }) | ||
return Promise.resolve(updatedTokens) | ||
} | ||
|
||
|
@@ -376,6 +401,35 @@ class PreferencesController { | |
// | ||
// PRIVATE METHODS | ||
// | ||
|
||
/** | ||
* Getter definition for the `tokens` property of store when controller is initialized | ||
* | ||
* | ||
*/ | ||
_defineTokens () { | ||
const selectedAddress = this.store.getState().selectedAddress | ||
const accountTokens = this.store.getState().accountTokens | ||
const providerType = this.network.providerStore.getState().type | ||
if (!(selectedAddress in accountTokens)) accountTokens[selectedAddress] = {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This line is in at least two other functions. We might want to DRY that up. Then again, if it's only one line, not much to reduce... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good one, this is not necessary since the entry is created for each account when it is added, so the only place where it should be is on |
||
if (!(providerType in accountTokens[selectedAddress])) return [] | ||
this.tokens = accountTokens[selectedAddress][providerType] | ||
} | ||
|
||
/** | ||
* Subscription to network provider type | ||
* | ||
* | ||
*/ | ||
_subscribeProviderType () { | ||
this.network.providerStore.subscribe(({ type }) => { | ||
const selectedAddress = this.store.getState().selectedAddress | ||
const accountTokens = this.store.getState().accountTokens | ||
if (!(type in accountTokens[selectedAddress])) accountTokens[selectedAddress][type] = [] | ||
const tokens = accountTokens[selectedAddress][type] | ||
this.store.updateState({ tokens }) | ||
}) | ||
} | ||
} | ||
|
||
module.exports = PreferencesController |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// 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 tokens = newState.TransactionController.tokens | ||
const selectedAddress = newState.PreferencesController.selectedAddress | ||
newState.PreferencesController.tokens = [] | ||
newState.PreferencesController.accountTokens = {[selectedAddress]: {'mainnet': tokens}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So this migration removes tokens from all accounts except the main address. I think it would be more cautious/considerate to just keep all their tokens on all their accounts, so they don't notice any abrupt change. This is so far the only thing I'd briefly block over. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good, then users can remove/add tokens as they want. |
||
} | ||
} | ||
|
||
return newState | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,4 +38,5 @@ module.exports = [ | |
require('./025'), | ||
require('./026'), | ||
require('./027'), | ||
require('./028'), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like there's an opportunity to de-duplicate some logic between here and
setAddress
.Or at least, this function is getting a little big, we could probably tuck more of the token managing code into its own methods (eventually might want its own controller).