Skip to content
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

feat: Integrate new TokenListController polling pattern [Extension] #28198

Closed
wants to merge 65 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
85fe12d
bump asset controllers to 39
bergeron Oct 22, 2024
0f3cd64
update ConfirmTransaction
bergeron Oct 22, 2024
bdf921b
fix useGasFeeEstimates unit test
bergeron Oct 22, 2024
9bc4ecf
fix usePolling tests
bergeron Oct 23, 2024
9b1529b
bump controller utils
bergeron Oct 23, 2024
c8bcc0b
remove patch
bergeron Oct 23, 2024
d1a3782
Merge branch 'develop' into brian/asset-controller-39
bergeron Oct 23, 2024
05fd6ef
Update LavaMoat policies
metamaskbot Oct 23, 2024
9dfdfa8
lint
bergeron Oct 23, 2024
04ea3d6
Merge branch 'brian/asset-controller-39' of github.com:MetaMask/metam…
bergeron Oct 23, 2024
cf66072
Merge branch 'develop' into brian/asset-controller-39
bergeron Oct 24, 2024
785de28
initial multi chain polling for currency and token rates
bergeron Oct 29, 2024
f461767
fix testnets
bergeron Oct 29, 2024
f1da818
only refetch prices on chains whose tokens changed
bergeron Oct 29, 2024
878f407
poll multiple native currencies
bergeron Oct 30, 2024
074c5fc
feat: add tokenListStartPolling and tokenListStopPollingByPollingToke…
gambinish Oct 30, 2024
e8a9d6a
fix test
bergeron Oct 30, 2024
245f8d3
yarn dedupe
bergeron Oct 30, 2024
1afebee
Update LavaMoat policies
metamaskbot Oct 30, 2024
e99e2ef
Merge branch 'develop' into brian/currency-rate-multichain-polling2
bergeron Oct 30, 2024
ca590ec
fix e2e test mocks
bergeron Oct 30, 2024
d2191ac
Merge branch 'develop' of github.com:MetaMask/metamask-extension into…
bergeron Oct 30, 2024
6321d83
feat: Bind new polling methods in metamask state
gambinish Oct 30, 2024
0633b8e
feat: Introduce useTokenListPolling hook
gambinish Oct 30, 2024
5a57889
chore: Remove chainId from constructor of TokenListController
gambinish Oct 30, 2024
70c0db4
fix e2e test
bergeron Oct 30, 2024
6b7df4d
.
bergeron Oct 30, 2024
4e816c2
lint
bergeron Oct 30, 2024
aaef377
fix e2e test
bergeron Oct 30, 2024
48bff46
Merge branch 'brian/currency-rate-multichain-polling2' of github.com:…
bergeron Oct 31, 2024
0450b04
package.json
bergeron Oct 31, 2024
2e26728
fix: Update comment
gambinish Oct 31, 2024
9d21f84
chore: Cleanup
gambinish Oct 31, 2024
b28d396
chore: Cleanup
gambinish Oct 31, 2024
fdc04ad
Merge branch 'develop' of github.com:MetaMask/metamask-extension into…
bergeron Oct 31, 2024
3ec3574
bump controller preview version
bergeron Oct 31, 2024
7c78314
fix: Provide chainId in contructor of TokenList
gambinish Oct 31, 2024
2a51a23
chore: Consider global settings when useTokeListPolling
gambinish Oct 31, 2024
0557e3f
fix: actions should only accept a single hook, multiPolling will dest…
gambinish Oct 31, 2024
a216bc9
chore: Remove comments
gambinish Oct 31, 2024
8810e88
chore: Incorporate tokensChainCache selector in useTokenListPolling hook
gambinish Oct 31, 2024
dcc8a64
Merge branch 'develop' into brian/multiexchangerate
bergeron Oct 31, 2024
3f772a2
chore: Add tokenList global context
gambinish Oct 31, 2024
92c22ea
fix: Correct naming convention in context
gambinish Oct 31, 2024
fc9a8ea
chore: Include tokenList in hook result
gambinish Oct 31, 2024
0e7a872
fix: fix lint
sahar-fehri Oct 31, 2024
ea95aca
fix: update js file to tsx
sahar-fehri Oct 31, 2024
3bf7b78
Merge branch 'develop' into brian/multiexchangerate
sahar-fehri Nov 1, 2024
bb1f278
make polling input a chain id
bergeron Nov 1, 2024
14dc84b
Merge branch 'develop' into brian/multiexchangerate
bergeron Nov 1, 2024
0af4924
fix: Correctly bind controller method to action
gambinish Nov 1, 2024
090390f
fix: Correct usage of tokenListStartPolling action
gambinish Nov 1, 2024
0efe6ed
Merge branch 'brian/multiexchangerate' into 3429_tokenlist-controller…
gambinish Nov 1, 2024
a02d772
fix: Remove action should remove polling token from AppState
gambinish Nov 1, 2024
3e4a2a3
Merge branch '3429_tokenlist-controller-polling' of github.com:MetaMa…
gambinish Nov 1, 2024
2e54266
chore: Merge main, address conflicts
gambinish Nov 4, 2024
90bd51c
fix: Missed unresolved merge conflict
gambinish Nov 4, 2024
b7e9327
fix: Leverage preview build of core
gambinish Nov 4, 2024
731baa2
fix: Update fixture builder to include tokenChainsCache
gambinish Nov 4, 2024
d9a3f33
Merge branch 'develop' into 3429_tokenlist-controller-polling
gambinish Nov 4, 2024
c404ccb
Update LavaMoat policies
metamaskbot Nov 4, 2024
7a0cac3
fix: Remove deprecated start and stop tokenListPolling
gambinish Nov 4, 2024
558b5c8
Merge branch '3429_tokenlist-controller-polling' of github.com:MetaMa…
gambinish Nov 4, 2024
5fc34e4
fix: Lint and cleanup comments
gambinish Nov 4, 2024
9b9bbc5
chore: Lint useTokenListPolling hook
gambinish Nov 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 11 additions & 47 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -645,9 +645,9 @@ export default class MetamaskController extends EventEmitter {

this.tokenListController = new TokenListController({
chainId: getCurrentChainId({ metamask: this.networkController.state }),
preventPollingOnNetworkRestart: !this.#isTokenListPollingRequired(
this.preferencesController.state,
),
// preventPollingOnNetworkRestart: !this.#isTokenListPollingRequired(
// this.preferencesController.state,
// ),
messenger: tokenListMessenger,
state: initState.TokenListController,
});
Expand Down Expand Up @@ -2590,24 +2590,12 @@ export default class MetamaskController extends EventEmitter {
this.accountTrackerController.start();
this.txController.startIncomingTransactionPolling();
this.tokenDetectionController.enable();

const preferencesControllerState = this.preferencesController.state;

if (this.#isTokenListPollingRequired(preferencesControllerState)) {
this.tokenListController.start();
}
}

stopNetworkRequests() {
this.accountTrackerController.stop();
this.txController.stopIncomingTransactionPolling();
this.tokenDetectionController.disable();

const preferencesControllerState = this.preferencesController.state;

if (this.#isTokenListPollingRequired(preferencesControllerState)) {
this.tokenListController.stop();
}
}

resetStates(resetMethods) {
Expand Down Expand Up @@ -2855,7 +2843,7 @@ export default class MetamaskController extends EventEmitter {
let lastSelectedAddress;
this.controllerMessenger.subscribe(
'PreferencesController:stateChange',
previousValueComparator(async (prevState, currState) => {
previousValueComparator(async (_, currState) => {
const { currentLocale } = currState;
const chainId = getCurrentChainId({
metamask: this.networkController.state,
Expand All @@ -2867,8 +2855,6 @@ export default class MetamaskController extends EventEmitter {
} else {
this.txController.stopIncomingTransactionPolling();
}

this.#checkTokenListPolling(currState, prevState);
}, this.preferencesController.state),
);

Expand Down Expand Up @@ -3242,6 +3228,7 @@ export default class MetamaskController extends EventEmitter {
approvalController,
phishingController,
tokenRatesController,
tokenListController,
// Notification Controllers
authenticationController,
userStorageController,
Expand Down Expand Up @@ -4019,6 +4006,12 @@ export default class MetamaskController extends EventEmitter {
tokenRatesController,
),

// TokenListController
tokenListStartPolling:
tokenListController.startPolling.bind(tokenListController),
tokenListStopPollingByPollingToken:
tokenListController.stopPollingByPollingToken.bind(tokenListController),

// GasFeeController
gasFeeStartPollingByNetworkClientId:
gasFeeController.startPollingByNetworkClientId.bind(gasFeeController),
Expand Down Expand Up @@ -7176,33 +7169,4 @@ export default class MetamaskController extends EventEmitter {
metamask: this.getState(),
};
}

#checkTokenListPolling(currentState, previousState) {
const previousEnabled = this.#isTokenListPollingRequired(previousState);
const newEnabled = this.#isTokenListPollingRequired(currentState);

if (previousEnabled === newEnabled) {
return;
}

this.tokenListController.updatePreventPollingOnNetworkRestart(!newEnabled);

if (newEnabled) {
log.debug('Started token list controller polling');
this.tokenListController.start();
} else {
log.debug('Stopped token list controller polling');
this.tokenListController.clearingTokenListData();
this.tokenListController.stop();
}
}

#isTokenListPollingRequired(preferencesControllerState) {
const { useTokenDetection, useTransactionSimulations, preferences } =
preferencesControllerState ?? {};

const { petnamesEnabled } = preferences ?? {};

return useTokenDetection || petnamesEnabled || useTransactionSimulations;
}
}
2 changes: 1 addition & 1 deletion lavamoat/browserify/beta/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@
"Headers": true,
"URL": true,
"URLSearchParams": true,
"__import__": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
Expand All @@ -668,7 +669,6 @@
"setTimeout": true
},
"packages": {
"@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
Expand Down
2 changes: 1 addition & 1 deletion lavamoat/browserify/flask/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@
"Headers": true,
"URL": true,
"URLSearchParams": true,
"__import__": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
Expand All @@ -668,7 +669,6 @@
"setTimeout": true
},
"packages": {
"@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
Expand Down
2 changes: 1 addition & 1 deletion lavamoat/browserify/main/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,7 @@
"Headers": true,
"URL": true,
"URLSearchParams": true,
"__import__": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
Expand All @@ -668,7 +669,6 @@
"setTimeout": true
},
"packages": {
"@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
Expand Down
2 changes: 1 addition & 1 deletion lavamoat/browserify/mmi/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,7 @@
"Headers": true,
"URL": true,
"URLSearchParams": true,
"__import__": true,
"clearInterval": true,
"clearTimeout": true,
"console.error": true,
Expand All @@ -760,7 +761,6 @@
"setTimeout": true
},
"packages": {
"@ensdomains/content-hash>multicodec>uint8arrays>multiformats": true,
"@ethereumjs/tx>@ethereumjs/util": true,
"@ethersproject/contracts": true,
"@ethersproject/providers": true,
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
"attributions:generate": "./development/generate-attributions.sh"
},
"resolutions": {
"@metamask/assets-controllers": "npm:@metamask-previews/[email protected]",
"chokidar": "^3.6.0",
"gridplus-sdk/elliptic": "^6.5.7",
"gridplus-sdk/secp256k1": "^5.0.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,13 @@
},
"TokenListController": {
"tokenList": "object",
"tokensChainsCache": {},
"tokensChainsCache": {
"0x1": "object",
"0x539": "object",
"0xaa36a7": "object",
"0xe705": "object",
"0xe708": "object"
},
"preventPollingOnNetworkRestart": false
},
"TokenRatesController": { "marketData": "object" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,13 @@
"gasEstimateType": "none",
"nonRPCGasFeeApisDisabled": "boolean",
"tokenList": "object",
"tokensChainsCache": {},
"tokensChainsCache": {
"0x1": "object",
"0x539": "object",
"0xaa36a7": "object",
"0xe705": "object",
"0xe708": "object"
},
"preventPollingOnNetworkRestart": false,
"tokens": "object",
"ignoredTokens": "object",
Expand Down
8 changes: 7 additions & 1 deletion test/integration/data/onboarding-completion-route.json
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,13 @@
"theme": "os",
"tokenList": {},
"tokens": [],
"tokensChainsCache": {},
"tokensChainsCache": {
"0x1": "object",
"0x539": "object",
"0xaa36a7": "object",
"0xe705": "object",
"0xe708": "object"
},
"traits": {},
"transactions": [],
"trezorModel": null,
Expand Down
2 changes: 2 additions & 0 deletions ui/contexts/assetPolling.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { ReactNode } from 'react';
import useCurrencyRatePolling from '../hooks/useCurrencyRatePolling';
import useTokenRatesPolling from '../hooks/useTokenRatesPolling';
import useTokenListPolling from '../hooks/useTokenListPolling';

// This provider is a step towards making controller polling fully UI based.
// Eventually, individual UI components will call the use*Polling hooks to
// poll and return particular data. This polls globally in the meantime.
export const AssetPollingProvider = ({ children }: { children: ReactNode }) => {
useCurrencyRatePolling();
useTokenRatesPolling();
useTokenListPolling();

return <>{children}</>;
};
12 changes: 12 additions & 0 deletions ui/contexts/tokenList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import useTokenListPolling from '../hooks/useTokenListPolling';

export const TokenListProvider = ({ children }) => {
useTokenListPolling();

return <>{children}</>;
};
TokenListProvider.propTypes = {
children: PropTypes.node,
};
12 changes: 12 additions & 0 deletions ui/contexts/tokenRates.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React, { ReactElement } from 'react';
import useTokenRatesPolling from '../hooks/useTokenRatesPolling';

export const TokenRatesProvider = ({
children,
}: {
children: ReactElement;
}) => {
useTokenRatesPolling();

return <>{children}</>;
};
37 changes: 37 additions & 0 deletions ui/hooks/useTokenListPolling.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useSelector } from 'react-redux';
import { Hex } from '@metamask/utils';
import {
getNetworkConfigurationsByChainId,
getPreferences,
selectERC20Tokens,
selectERC20TokensByChain,
} from '../selectors';
import {
tokenListStartPolling,
tokenListStopPollingByPollingToken,
} from '../store/actions';
import useMultiPolling from './useMultiPolling';

const useTokenListPolling = () => {
const networkConfigurations = useSelector(getNetworkConfigurationsByChainId);
const { petnamesEnabled, useTokenDetection, useTransactionSimulations } =
useSelector(getPreferences);
const tokenList = useSelector(selectERC20Tokens);
const tokensChainsCache = useSelector(selectERC20TokensByChain);

const chainIds = Object.keys(networkConfigurations) as Hex[];

if (useTokenDetection || petnamesEnabled || useTransactionSimulations) {
useMultiPolling({
startPolling: tokenListStartPolling,
stopPollingByPollingToken: tokenListStopPollingByPollingToken,
input: chainIds,
});
}

return {
tokenList,
tokensChainsCache,
};
};
export default useTokenListPolling;
30 changes: 30 additions & 0 deletions ui/store/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4586,6 +4586,36 @@ export async function tokenRatesStopPollingByPollingToken(
await removePollingTokenFromAppState(pollingToken);
}

/**
* Informs the TokenListController that the UI requires tokenlist polling
*
* @param chainId
* @returns polling token that can be used to stop polling
*/
export async function tokenListStartPolling(chainId: Hex): Promise<string> {
const pollingToken = await submitRequestToBackground(
'tokenListStartPolling',
[{ chainId }],
);
await addPollingTokenToAppState(pollingToken);
return pollingToken;
}

/**
* Informs the TokenListController that the UI requires tokenlist to stop polling given a specific polling token
*
* @param pollingToken
* @returns polling token that can be used to stop polling
*/
export async function tokenListStopPollingByPollingToken(
pollingToken: string,
): Promise<string> {
await submitRequestToBackground('tokenListStopPollingByPollingToken', [
pollingToken,
]);
await removePollingTokenFromAppState(pollingToken);
}

/**
* Informs the GasFeeController that the UI requires gas fee polling
*
Expand Down
Loading
Loading