1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

cache balances by chain id (#10545)

This commit is contained in:
Brad Decker 2021-03-02 16:53:07 -06:00 committed by GitHub
parent d44c4d3747
commit e42658b590
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 39 additions and 26 deletions

View File

@ -3,7 +3,7 @@ import { ObservableStore } from '@metamask/obs-store';
/** /**
* @typedef {Object} CachedBalancesOptions * @typedef {Object} CachedBalancesOptions
* @property {Object} accountTracker An {@code AccountTracker} reference * @property {Object} accountTracker An {@code AccountTracker} reference
* @property {Function} getNetwork A function to get the current network * @property {Function} getCurrentChainId A function to get the current chain id
* @property {Object} initState The initial controller state * @property {Object} initState The initial controller state
*/ */
@ -18,10 +18,10 @@ export default class CachedBalancesController {
* @param {CachedBalancesOptions} [opts] - Controller configuration parameters * @param {CachedBalancesOptions} [opts] - Controller configuration parameters
*/ */
constructor(opts = {}) { constructor(opts = {}) {
const { accountTracker, getNetwork } = opts; const { accountTracker, getCurrentChainId } = opts;
this.accountTracker = accountTracker; this.accountTracker = accountTracker;
this.getNetwork = getNetwork; this.getCurrentChainId = getCurrentChainId;
const initState = { cachedBalances: {}, ...opts.initState }; const initState = { cachedBalances: {}, ...opts.initState };
this.store = new ObservableStore(initState); this.store = new ObservableStore(initState);
@ -30,37 +30,37 @@ export default class CachedBalancesController {
} }
/** /**
* Updates the cachedBalances property for the current network. Cached balances will be updated to those in the passed accounts * Updates the cachedBalances property for the current chain. Cached balances will be updated to those in the passed accounts
* if balances in the passed accounts are truthy. * if balances in the passed accounts are truthy.
* *
* @param {Object} obj - The the recently updated accounts object for the current network * @param {Object} obj - The the recently updated accounts object for the current chain
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async updateCachedBalances({ accounts }) { async updateCachedBalances({ accounts }) {
const network = await this.getNetwork(); const chainId = this.getCurrentChainId();
const balancesToCache = await this._generateBalancesToCache( const balancesToCache = await this._generateBalancesToCache(
accounts, accounts,
network, chainId,
); );
this.store.updateState({ this.store.updateState({
cachedBalances: balancesToCache, cachedBalances: balancesToCache,
}); });
} }
_generateBalancesToCache(newAccounts, currentNetwork) { _generateBalancesToCache(newAccounts, chainId) {
const { cachedBalances } = this.store.getState(); const { cachedBalances } = this.store.getState();
const currentNetworkBalancesToCache = { ...cachedBalances[currentNetwork] }; const currentChainBalancesToCache = { ...cachedBalances[chainId] };
Object.keys(newAccounts).forEach((accountID) => { Object.keys(newAccounts).forEach((accountID) => {
const account = newAccounts[accountID]; const account = newAccounts[accountID];
if (account.balance) { if (account.balance) {
currentNetworkBalancesToCache[accountID] = account.balance; currentChainBalancesToCache[accountID] = account.balance;
} }
}); });
const balancesToCache = { const balancesToCache = {
...cachedBalances, ...cachedBalances,
[currentNetwork]: currentNetworkBalancesToCache, [chainId]: currentChainBalancesToCache,
}; };
return balancesToCache; return balancesToCache;

View File

@ -218,7 +218,7 @@ export default class MetamaskController extends EventEmitter {
this.cachedBalancesController = new CachedBalancesController({ this.cachedBalancesController = new CachedBalancesController({
accountTracker: this.accountTracker, accountTracker: this.accountTracker,
getNetwork: this.networkController.getNetworkState.bind( getCurrentChainId: this.networkController.getCurrentChainId.bind(
this.networkController, this.networkController,
), ),
initState: initState.CachedBalancesController, initState: initState.CachedBalancesController,

View File

@ -1,12 +1,13 @@
import assert from 'assert'; import assert from 'assert';
import sinon from 'sinon'; import sinon from 'sinon';
import CachedBalancesController from '../../../../app/scripts/controllers/cached-balances'; import CachedBalancesController from '../../../../app/scripts/controllers/cached-balances';
import { KOVAN_CHAIN_ID } from '../../../../shared/constants/network';
describe('CachedBalancesController', function () { describe('CachedBalancesController', function () {
describe('updateCachedBalances', function () { describe('updateCachedBalances', function () {
it('should update the cached balances', async function () { it('should update the cached balances', async function () {
const controller = new CachedBalancesController({ const controller = new CachedBalancesController({
getNetwork: () => Promise.resolve(17), getCurrentChainId: () => KOVAN_CHAIN_ID,
accountTracker: { accountTracker: {
store: { store: {
subscribe: () => undefined, subscribe: () => undefined,
@ -26,7 +27,7 @@ describe('CachedBalancesController', function () {
assert.equal(controller._generateBalancesToCache.callCount, 1); assert.equal(controller._generateBalancesToCache.callCount, 1);
assert.deepEqual(controller._generateBalancesToCache.args[0], [ assert.deepEqual(controller._generateBalancesToCache.args[0], [
'mockAccounts', 'mockAccounts',
17, KOVAN_CHAIN_ID,
]); ]);
assert.equal( assert.equal(
controller.store.getState().cachedBalances, controller.store.getState().cachedBalances,
@ -45,7 +46,7 @@ describe('CachedBalancesController', function () {
}, },
initState: { initState: {
cachedBalances: { cachedBalances: {
17: { [KOVAN_CHAIN_ID]: {
a: '0x1', a: '0x1',
b: '0x2', b: '0x2',
c: '0x3', c: '0x3',
@ -65,11 +66,11 @@ describe('CachedBalancesController', function () {
b: { balance: null }, b: { balance: null },
c: { balance: '0x5' }, c: { balance: '0x5' },
}, },
17, KOVAN_CHAIN_ID,
); );
assert.deepEqual(result, { assert.deepEqual(result, {
17: { [KOVAN_CHAIN_ID]: {
a: '0x4', a: '0x4',
b: '0x2', b: '0x2',
c: '0x5', c: '0x5',
@ -91,7 +92,7 @@ describe('CachedBalancesController', function () {
}, },
initState: { initState: {
cachedBalances: { cachedBalances: {
17: { [KOVAN_CHAIN_ID]: {
a: '0x1', a: '0x1',
b: '0x2', b: '0x2',
c: '0x3', c: '0x3',
@ -110,7 +111,7 @@ describe('CachedBalancesController', function () {
); );
assert.deepEqual(result, { assert.deepEqual(result, {
17: { [KOVAN_CHAIN_ID]: {
a: '0x1', a: '0x1',
b: '0x2', b: '0x2',
c: '0x3', c: '0x3',
@ -127,7 +128,7 @@ describe('CachedBalancesController', function () {
it('should subscribe to the account tracker with the updateCachedBalances method', async function () { it('should subscribe to the account tracker with the updateCachedBalances method', async function () {
const subscribeSpy = sinon.spy(); const subscribeSpy = sinon.spy();
const controller = new CachedBalancesController({ const controller = new CachedBalancesController({
getNetwork: () => Promise.resolve(17), getCurrentChainId: () => KOVAN_CHAIN_ID,
accountTracker: { accountTracker: {
store: { store: {
subscribe: subscribeSpy, subscribe: subscribeSpy,

View File

@ -11,10 +11,9 @@ import { renderWithProvider } from '../../../../../../../test/lib/render-helpers
import * as actions from '../../../../../store/actions'; import * as actions from '../../../../../store/actions';
import UnconnectedAccountAlert from '..'; import UnconnectedAccountAlert from '..';
import { KOVAN_CHAIN_ID } from '../../../../../../../shared/constants/network';
describe('Unconnected Account Alert', function () { describe('Unconnected Account Alert', function () {
const network = '123';
const selectedAddress = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b'; const selectedAddress = '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b';
const identities = { const identities = {
@ -40,7 +39,7 @@ describe('Unconnected Account Alert', function () {
}; };
const cachedBalances = { const cachedBalances = {
123: { [KOVAN_CHAIN_ID]: {
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': '0x0', '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': '0x0',
'0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b': '0x0', '0xec1adf982415d2ef5ec55899b9bfb8bc0f29251b': '0x0',
}, },
@ -58,12 +57,14 @@ describe('Unconnected Account Alert', function () {
const mockState = { const mockState = {
metamask: { metamask: {
network,
selectedAddress, selectedAddress,
identities, identities,
accounts, accounts,
cachedBalances, cachedBalances,
keyrings, keyrings,
provider: {
chainId: KOVAN_CHAIN_ID,
},
permissionsHistory: { permissionsHistory: {
'https://test.dapp': { 'https://test.dapp': {
eth_accounts: { eth_accounts: {

View File

@ -127,9 +127,16 @@ export function getMetaMaskAccountsRaw(state) {
} }
export function getMetaMaskCachedBalances(state) { export function getMetaMaskCachedBalances(state) {
const chainId = getCurrentChainId(state);
// Fallback to fetching cached balances from network id
// this can eventually be removed
const network = getCurrentNetworkId(state); const network = getCurrentNetworkId(state);
return state.metamask.cachedBalances[network]; return (
state.metamask.cachedBalances[chainId] ??
state.metamask.cachedBalances[network]
);
} }
/** /**
@ -155,7 +162,7 @@ export function isBalanceCached(state) {
} }
export function getSelectedAccountCachedBalance(state) { export function getSelectedAccountCachedBalance(state) {
const cachedBalances = state.metamask.cachedBalances[state.metamask.network]; const cachedBalances = getMetaMaskCachedBalances(state);
const selectedAddress = getSelectedAddress(state); const selectedAddress = getSelectedAddress(state);
return cachedBalances && cachedBalances[selectedAddress]; return cachedBalances && cachedBalances[selectedAddress];

View File

@ -1,4 +1,5 @@
import assert from 'assert'; import assert from 'assert';
import { KOVAN_CHAIN_ID } from '../../../../shared/constants/network';
import { import {
getConnectedDomainsForSelectedAddress, getConnectedDomainsForSelectedAddress,
getOrderedConnectedAccountsForActiveTab, getOrderedConnectedAccountsForActiveTab,
@ -163,6 +164,9 @@ describe('selectors', function () {
url: 'https://remix.ethereum.org/', url: 'https://remix.ethereum.org/',
}, },
metamask: { metamask: {
provider: {
chainId: KOVAN_CHAIN_ID,
},
accounts: { accounts: {
0x7250739de134d33ec7ab1ee592711e15098c9d2d: { 0x7250739de134d33ec7ab1ee592711e15098c9d2d: {
address: '0x7250739de134d33ec7ab1ee592711e15098c9d2d', address: '0x7250739de134d33ec7ab1ee592711e15098c9d2d',