Skip to content

Commit 205bfaf

Browse files
MajorLiftnickewansmith
authored andcommitted
fix: Type fixes and optimizations for EngineService, Redux store (#12509)
## **Description** - ~Define types: `ReduxStore`, `ReduxState`~ (superseded by #12538) - Fix `any` types in `EngineService`. - Optimize `EngineService` event subscriptions: - Fix `update_bg_state_cb` callback being re-defined on every iteration. - Consolidate `stateChange` events collections into `BACKGROUND_STATE_CHANGE_EVENT_NAMES` constant for maintainability. ## **Related issues** - Blocked by #10441 - Blocked by MetaMask/core#4968 and corresponding release. ## **Manual testing steps** ## **Screenshots/Recordings** ## **Pre-merge author checklist** - [x] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I’ve included tests if applicable - [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots.
1 parent a2d09de commit 205bfaf

File tree

2 files changed

+33
-150
lines changed

2 files changed

+33
-150
lines changed

app/core/EngineService/EngineService.ts

Lines changed: 24 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Engine from '../Engine';
2-
import AppConstants from '../AppConstants';
1+
import UntypedEngine from '../Engine';
2+
import { Engine as TypedEngine } from '../Engine/Engine';
33
import { getVaultFromBackup } from '../BackupVault';
44
import Logger from '../../util/Logger';
55
import {
@@ -9,6 +9,7 @@ import {
99
import { getTraceTags } from '../../util/sentry/tags';
1010
import { trace, endTrace, TraceName, TraceOperation } from '../../util/trace';
1111
import getUIStartupSpan from '../Performance/UIStartup';
12+
import { BACKGROUND_STATE_CHANGE_EVENT_NAMES } from '../Engine/constants';
1213
import ReduxService from '../redux';
1314
import NavigationService from '../NavigationService';
1415
import Routes from '../../constants/navigation/Routes';
@@ -52,15 +53,17 @@ export class EngineService {
5253
parentContext: getUIStartupSpan(),
5354
tags: getTraceTags(reduxState),
5455
});
55-
const state = reduxState?.engine?.backgroundState || {};
56+
const state = reduxState?.engine?.backgroundState ?? {};
57+
const Engine = UntypedEngine;
5658
try {
5759
Logger.log(`${LOG_TAG}: Initializing Engine:`, {
5860
hasState: Object.keys(state).length > 0,
5961
});
6062

6163
const metaMetricsId = await MetaMetrics.getInstance().getMetaMetricsId();
6264
Engine.init(state, null, metaMetricsId);
63-
this.updateControllers(Engine);
65+
// `Engine.init()` call mutates `typeof UntypedEngine` to `TypedEngine`
66+
this.updateControllers(Engine as unknown as TypedEngine);
6467
} catch (error) {
6568
Logger.error(
6669
error as Error,
@@ -74,9 +77,7 @@ export class EngineService {
7477
endTrace({ name: TraceName.EngineInitialization });
7578
};
7679

77-
// TODO: Replace "any" with type
78-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
79-
private updateControllers = (engine: any) => {
80+
private updateControllers = (engine: TypedEngine) => {
8081
if (!engine.context) {
8182
Logger.error(
8283
new Error(
@@ -86,125 +87,6 @@ export class EngineService {
8687
return;
8788
}
8889

89-
const controllers = [
90-
{
91-
name: 'AddressBookController',
92-
key: `${engine.context.AddressBookController.name}:stateChange`,
93-
},
94-
{ name: 'NftController', key: 'NftController:stateChange' },
95-
{
96-
name: 'TokensController',
97-
key: `${engine.context.TokensController.name}:stateChange`,
98-
},
99-
{
100-
name: 'KeyringController',
101-
key: `${engine.context.KeyringController.name}:stateChange`,
102-
},
103-
{
104-
name: 'AccountTrackerController',
105-
key: 'AccountTrackerController:stateChange',
106-
},
107-
{
108-
name: 'NetworkController',
109-
key: AppConstants.NETWORK_STATE_CHANGE_EVENT,
110-
},
111-
{
112-
name: 'PhishingController',
113-
key: `${engine.context.PhishingController.name}:stateChange`,
114-
},
115-
{
116-
name: 'PreferencesController',
117-
key: `${engine.context.PreferencesController.name}:stateChange`,
118-
},
119-
{
120-
name: 'RemoteFeatureFlagController',
121-
key: `${engine.context.RemoteFeatureFlagController.name}:stateChange`,
122-
},
123-
{
124-
name: 'SelectedNetworkController',
125-
key: `${engine.context.SelectedNetworkController.name}:stateChange`,
126-
},
127-
{
128-
name: 'TokenBalancesController',
129-
key: `${engine.context.TokenBalancesController.name}:stateChange`,
130-
},
131-
{ name: 'TokenRatesController', key: 'TokenRatesController:stateChange' },
132-
{
133-
name: 'TransactionController',
134-
key: `${engine.context.TransactionController.name}:stateChange`,
135-
},
136-
{
137-
name: 'SmartTransactionsController',
138-
key: `${engine.context.SmartTransactionsController.name}:stateChange`,
139-
},
140-
{
141-
name: 'SwapsController',
142-
key: `${engine.context.SwapsController.name}:stateChange`,
143-
},
144-
{
145-
name: 'TokenListController',
146-
key: `${engine.context.TokenListController.name}:stateChange`,
147-
},
148-
{
149-
name: 'CurrencyRateController',
150-
key: `${engine.context.CurrencyRateController.name}:stateChange`,
151-
},
152-
{
153-
name: 'GasFeeController',
154-
key: `${engine.context.GasFeeController.name}:stateChange`,
155-
},
156-
{
157-
name: 'ApprovalController',
158-
key: `${engine.context.ApprovalController.name}:stateChange`,
159-
},
160-
///: BEGIN:ONLY_INCLUDE_IF(preinstalled-snaps,external-snaps)
161-
{
162-
name: 'SnapController',
163-
key: `${engine.context.SnapController.name}:stateChange`,
164-
},
165-
{
166-
name: 'SubjectMetadataController',
167-
key: `${engine.context.SubjectMetadataController.name}:stateChange`,
168-
},
169-
{
170-
name: 'AuthenticationController',
171-
key: 'AuthenticationController:stateChange',
172-
},
173-
{
174-
name: 'UserStorageController',
175-
key: 'UserStorageController:stateChange',
176-
},
177-
{
178-
name: 'NotificationServicesController',
179-
key: 'NotificationServicesController:stateChange',
180-
},
181-
{
182-
name: 'NotificationServicesPushController',
183-
key: 'NotificationServicesPushController:stateChange',
184-
},
185-
///: END:ONLY_INCLUDE_IF
186-
{
187-
name: 'PermissionController',
188-
key: `${engine.context.PermissionController.name}:stateChange`,
189-
},
190-
{
191-
name: 'LoggingController',
192-
key: `${engine.context.LoggingController.name}:stateChange`,
193-
},
194-
{
195-
name: 'AccountsController',
196-
key: `${engine.context.AccountsController.name}:stateChange`,
197-
},
198-
{
199-
name: 'PPOMController',
200-
key: `${engine.context.PPOMController.name}:stateChange`,
201-
},
202-
{
203-
name: 'SignatureController',
204-
key: `${engine.context.SignatureController.name}:stateChange`,
205-
},
206-
];
207-
20890
engine.controllerMessenger.subscribeOnceIf(
20991
'ComposableController:stateChange',
21092
() => {
@@ -217,18 +99,20 @@ export class EngineService {
21799
() => !this.engineInitialized,
218100
);
219101

220-
controllers.forEach((controller) => {
221-
const { name, key } = controller;
222-
const update_bg_state_cb = () => {
223-
if (!engine.context.KeyringController.metadata.vault) {
224-
Logger.log('keyringController vault missing for UPDATE_BG_STATE_KEY');
225-
}
226-
ReduxService.store.dispatch({
227-
type: UPDATE_BG_STATE_KEY,
228-
payload: { key: name },
229-
});
230-
};
231-
engine.controllerMessenger.subscribe(key, update_bg_state_cb);
102+
const update_bg_state_cb = (controllerName: string) => {
103+
if (!engine.context.KeyringController.metadata.vault) {
104+
Logger.log('keyringController vault missing for UPDATE_BG_STATE_KEY');
105+
}
106+
ReduxService.store.dispatch({
107+
type: UPDATE_BG_STATE_KEY,
108+
payload: { key: controllerName },
109+
});
110+
};
111+
112+
BACKGROUND_STATE_CHANGE_EVENT_NAMES.forEach((eventName) => {
113+
engine.controllerMessenger.subscribe(eventName, () =>
114+
update_bg_state_cb(eventName.split(':')[0]),
115+
);
232116
});
233117
};
234118

@@ -244,7 +128,8 @@ export class EngineService {
244128
async initializeVaultFromBackup(): Promise<InitializeEngineResult> {
245129
const keyringState = await getVaultFromBackup();
246130
const reduxState = ReduxService.store.getState();
247-
const state = reduxState?.engine?.backgroundState || {};
131+
const state = reduxState?.engine?.backgroundState ?? {};
132+
const Engine = UntypedEngine;
248133
// This ensures we create an entirely new engine
249134
await Engine.destroyEngine();
250135
this.engineInitialized = false;

app/store/index.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Store } from 'redux';
1+
import { AnyAction } from 'redux';
22
import { configureStore } from '@reduxjs/toolkit';
33
import { persistStore, persistReducer } from 'redux-persist';
44
import createSagaMiddleware from 'redux-saga';
@@ -12,20 +12,18 @@ import thunk from 'redux-thunk';
1212

1313
import persistConfig from './persistConfig';
1414
import getUIStartupSpan from '../core/Performance/UIStartup';
15-
import ReduxService from '../core/redux';
15+
import ReduxService, { ReduxStore } from '../core/redux';
1616
import { onPersistedDataLoaded } from '../actions/user';
1717
import { validatePostMigrationState } from './validateMigration/validateMigration';
1818

19-
// TODO: Improve type safety by using real Action types instead of `any`
20-
// TODO: Replace "any" with type
21-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
22-
const pReducer = persistReducer<RootState, any>(persistConfig, rootReducer);
19+
// TODO: Improve type safety by using real Action types instead of `AnyAction`
20+
const pReducer = persistReducer<RootState, AnyAction>(
21+
persistConfig,
22+
rootReducer,
23+
);
2324

24-
// TODO: Fix the Action type. It's set to `any` now because some of the
25-
// TypeScript reducers have invalid actions
26-
// TODO: Replace "any" with type
27-
// eslint-disable-next-line @typescript-eslint/no-explicit-any, import/no-mutable-exports
28-
let store: Store<RootState, any>, persistor;
25+
// eslint-disable-next-line import/no-mutable-exports
26+
let store: ReduxStore, persistor;
2927
const createStoreAndPersistor = async () => {
3028
trace({
3129
name: TraceName.StoreInit,

0 commit comments

Comments
 (0)