Skip to content

Commit dfa086a

Browse files
refactor: migrate RateLimitController to @metamask/messenger (#6503)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> This PR migrates `RateLimitController` to the new `@metamask/messenger` message bus, as opposed to the one exported from `@metamask/base-controller`. ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> * Related to #5626 ## Checklist - [ ] I've updated the test suite for new or updated code as appropriate - [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [ ] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/contributing.md#updating-changelogs), highlighting breaking changes as necessary - [ ] I've prepared draft pull requests for clients and consumer packages to resolve any breaking changes <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Migrates RateLimitController to the new @metamask/messenger, updates types/tests, and renames metadata flag; adds dependency and updates docs/config. > > - **@metamask/rate-limit-controller**: > - Migrate from `RestrictedMessenger` (base-controller) to `Messenger` from `@metamask/messenger` and `BaseController` from `@metamask/base-controller/next`. > - Update action registration to `messenger.registerActionHandler` and adjust types (`RateLimitMessenger`, action/event types, `controllerName`). > - Rename metadata field `anonymous` to `includeInDebugSnapshot`. > - Update tests to construct root and namespaced messengers via `@metamask/messenger`. > - Add dependency `@metamask/messenger@^0.3.0`; update TS project references. > - Changelog: note BREAKING changes for messenger migration and metadata rename. > - **Repo Docs/Config**: > - README dependency graph: add `rate_limit_controller --> messenger`; add `eip_7702_internal_rpc_middleware --> controller_utils`. > - ESLint warning thresholds: adjust entries for `RateLimitController.ts`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b0aab99. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Michele Esposito <michele@esposito.codes>
1 parent 66d6ae1 commit dfa086a

File tree

9 files changed

+100
-60
lines changed

9 files changed

+100
-60
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ linkStyle default opacity:0.5
317317
profile_sync_controller --> address_book_controller;
318318
profile_sync_controller --> keyring_controller;
319319
rate_limit_controller --> base_controller;
320+
rate_limit_controller --> messenger;
320321
remote_feature_flag_controller --> base_controller;
321322
remote_feature_flag_controller --> controller_utils;
322323
sample_controllers --> base_controller;

eslint-warning-thresholds.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,7 @@
405405
"@typescript-eslint/prefer-readonly": 1
406406
},
407407
"packages/rate-limit-controller/src/RateLimitController.ts": {
408-
"jsdoc/check-tag-names": 4,
409-
"jsdoc/require-returns": 1,
410-
"jsdoc/tag-lines": 3
408+
"jsdoc/check-tag-names": 4
411409
},
412410
"packages/remote-feature-flag-controller/src/client-config-api-service/client-config-api-service.test.ts": {
413411
"import-x/order": 1,

packages/rate-limit-controller/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- **BREAKING:** Use new `Messenger` from `@metamask/messenger` ([#6503](https://github.com/MetaMask/core/pull/6503))
13+
- Previously, `RateLimitController` accepted a `RestrictedMessenger` instance from `@metamask/base-controller`.
14+
- **BREAKING:** Metadata property `anonymous` renamed to `includeInDebugSnapshot` ([#6503](https://github.com/MetaMask/core/pull/6503))
15+
1016
## [6.1.1]
1117

1218
### Changed

packages/rate-limit-controller/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
},
4949
"dependencies": {
5050
"@metamask/base-controller": "^8.4.2",
51+
"@metamask/messenger": "^0.3.0",
5152
"@metamask/rpc-errors": "^7.0.2",
5253
"@metamask/utils": "^11.8.1"
5354
},

packages/rate-limit-controller/src/RateLimitController.test.ts

Lines changed: 57 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
import { Messenger, deriveStateFromMetadata } from '@metamask/base-controller';
2-
3-
import type {
4-
RateLimitControllerActions,
5-
RateLimitControllerEvents,
6-
} from './RateLimitController';
1+
import { deriveStateFromMetadata } from '@metamask/base-controller/next';
2+
import {
3+
Messenger,
4+
MOCK_ANY_NAMESPACE,
5+
type MessengerActions,
6+
type MessengerEvents,
7+
type MockAnyNamespace,
8+
} from '@metamask/messenger';
9+
10+
import type { RateLimitMessenger } from './RateLimitController';
711
import { RateLimitController } from './RateLimitController';
812

9-
const name = 'RateLimitController';
13+
const controllerName = 'RateLimitController';
1014

1115
const implementations = {
1216
apiWithoutCustomLimit: {
@@ -21,29 +25,48 @@ const implementations = {
2125

2226
type RateLimitedApis = typeof implementations;
2327

28+
type AllRateLimitControllerActions = MessengerActions<
29+
RateLimitMessenger<RateLimitedApis>
30+
>;
31+
32+
type AllRateLimitControllerEvents = MessengerEvents<
33+
RateLimitMessenger<RateLimitedApis>
34+
>;
35+
36+
type RootMessenger = Messenger<
37+
MockAnyNamespace,
38+
AllRateLimitControllerActions,
39+
AllRateLimitControllerEvents
40+
>;
41+
2442
/**
25-
* Constructs an unrestricted messenger.
43+
* Creates and returns a root messenger for testing
2644
*
27-
* @returns An unrestricted messenger.
45+
* @returns A messenger instance
2846
*/
29-
function getUnrestrictedMessenger() {
30-
return new Messenger<
31-
RateLimitControllerActions<RateLimitedApis>,
32-
RateLimitControllerEvents<RateLimitedApis>
33-
>();
47+
function getRootMessenger(): RootMessenger {
48+
return new Messenger({
49+
namespace: MOCK_ANY_NAMESPACE,
50+
});
3451
}
3552

3653
/**
37-
* Constructs a restricted messenger.
54+
* Constructs a messenger for the RateLimitController.
3855
*
39-
* @param messenger - An optional unrestricted messenger
40-
* @returns A restricted messenger.
56+
* @param rootMessenger - An optional root messenger
57+
* @returns A messenger for the RateLimitController.
4158
*/
42-
function getRestrictedMessenger(messenger = getUnrestrictedMessenger()) {
43-
return messenger.getRestricted({
44-
name,
45-
allowedActions: [],
46-
allowedEvents: [],
59+
function getMessenger(
60+
rootMessenger = getRootMessenger(),
61+
): RateLimitMessenger<RateLimitedApis> {
62+
return new Messenger<
63+
typeof controllerName,
64+
AllRateLimitControllerActions,
65+
AllRateLimitControllerEvents,
66+
RootMessenger
67+
>({
68+
namespace: controllerName,
69+
parent: rootMessenger,
4770
});
4871
}
4972

@@ -62,8 +85,8 @@ describe('RateLimitController', () => {
6285
});
6386

6487
it('action: RateLimitController:call', async () => {
65-
const unrestricted = getUnrestrictedMessenger();
66-
const messenger = getRestrictedMessenger(unrestricted);
88+
const rootMessenger = getRootMessenger();
89+
const messenger = getMessenger(rootMessenger);
6790

6891
// Registers action handlers
6992
new RateLimitController({
@@ -72,7 +95,7 @@ describe('RateLimitController', () => {
7295
});
7396

7497
expect(
75-
await unrestricted.call(
98+
await rootMessenger.call(
7699
'RateLimitController:call',
77100
origin,
78101
'apiWithoutCustomLimit',
@@ -88,7 +111,7 @@ describe('RateLimitController', () => {
88111
});
89112

90113
it('uses apiWithoutCustomLimit method', async () => {
91-
const messenger = getRestrictedMessenger();
114+
const messenger = getMessenger();
92115

93116
const controller = new RateLimitController({
94117
implementations,
@@ -105,7 +128,7 @@ describe('RateLimitController', () => {
105128
});
106129

107130
it('returns false if rate-limited', async () => {
108-
const messenger = getRestrictedMessenger();
131+
const messenger = getMessenger();
109132
const controller = new RateLimitController({
110133
implementations,
111134
messenger,
@@ -154,7 +177,7 @@ describe('RateLimitController', () => {
154177
});
155178

156179
it('rate limit is reset after timeout', async () => {
157-
const messenger = getRestrictedMessenger();
180+
const messenger = getMessenger();
158181
const controller = new RateLimitController({
159182
implementations,
160183
messenger,
@@ -198,7 +221,7 @@ describe('RateLimitController', () => {
198221
});
199222

200223
it('timeout is only applied once per window', async () => {
201-
const messenger = getRestrictedMessenger();
224+
const messenger = getMessenger();
202225
const controller = new RateLimitController({
203226
implementations,
204227
messenger,
@@ -225,22 +248,22 @@ describe('RateLimitController', () => {
225248
it('includes expected state in debug snapshots', () => {
226249
const controller = new RateLimitController({
227250
implementations,
228-
messenger: getRestrictedMessenger(),
251+
messenger: getMessenger(),
229252
});
230253

231254
expect(
232255
deriveStateFromMetadata(
233256
controller.state,
234257
controller.metadata,
235-
'anonymous',
258+
'includeInDebugSnapshot',
236259
),
237260
).toMatchInlineSnapshot(`Object {}`);
238261
});
239262

240263
it('includes expected state in state logs', () => {
241264
const controller = new RateLimitController({
242265
implementations,
243-
messenger: getRestrictedMessenger(),
266+
messenger: getMessenger(),
244267
});
245268

246269
expect(
@@ -255,7 +278,7 @@ describe('RateLimitController', () => {
255278
it('persists expected state', () => {
256279
const controller = new RateLimitController({
257280
implementations,
258-
messenger: getRestrictedMessenger(),
281+
messenger: getMessenger(),
259282
});
260283

261284
expect(
@@ -270,7 +293,7 @@ describe('RateLimitController', () => {
270293
it('exposes expected state to UI', () => {
271294
const controller = new RateLimitController({
272295
implementations,
273-
messenger: getRestrictedMessenger(),
296+
messenger: getMessenger(),
274297
});
275298

276299
expect(

packages/rate-limit-controller/src/RateLimitController.ts

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import type {
2-
ActionConstraint,
3-
RestrictedMessenger,
4-
ControllerGetStateAction,
5-
ControllerStateChangeEvent,
6-
} from '@metamask/base-controller';
7-
import { BaseController } from '@metamask/base-controller';
1+
import {
2+
BaseController,
3+
type ControllerGetStateAction,
4+
type ControllerStateChangeEvent,
5+
} from '@metamask/base-controller/next';
6+
import type { Messenger, ActionConstraint } from '@metamask/messenger';
87
import { rpcErrors } from '@metamask/rpc-errors';
98
import { getKnownPropertyNames } from '@metamask/utils';
109

1110
/**
1211
* A rate-limited API endpoint.
12+
*
1313
* @property method - The method that is rate-limited.
1414
* @property rateLimitTimeout - The time window in which the rate limit is applied (in ms).
1515
* @property rateLimitCount - The amount of calls an origin can make in the rate limit time window.
@@ -27,34 +27,42 @@ export type RateLimitedApiMap = Record<string, RateLimitedApi>;
2727

2828
/**
2929
* A map of rate-limited API types to the number of requests made in a given interval for each origin and api type combination.
30+
*
3031
* @template RateLimitedApis - A {@link RateLimitedApiMap} containing the rate-limited API endpoints that is used by the {@link RateLimitController}.
3132
*/
3233
export type RateLimitedRequests<RateLimitedApis extends RateLimitedApiMap> =
3334
Record<keyof RateLimitedApis, Record<string, number>>;
3435

3536
/**
3637
* The state of the {@link RateLimitController}.
38+
*
3739
* @template RateLimitedApis - A {@link RateLimitedApiMap} containing the rate-limited API endpoints that is used by the {@link RateLimitController}.
3840
* @property requests - An object containing the number of requests made in a given interval for each origin and api type combination.
3941
*/
4042
export type RateLimitState<RateLimitedApis extends RateLimitedApiMap> = {
4143
requests: RateLimitedRequests<RateLimitedApis>;
4244
};
4345

44-
const name = 'RateLimitController';
46+
const controllerName = 'RateLimitController';
4547

4648
export type RateLimitControllerStateChangeEvent<
4749
RateLimitedApis extends RateLimitedApiMap,
48-
> = ControllerStateChangeEvent<typeof name, RateLimitState<RateLimitedApis>>;
50+
> = ControllerStateChangeEvent<
51+
typeof controllerName,
52+
RateLimitState<RateLimitedApis>
53+
>;
4954

5055
export type RateLimitControllerGetStateAction<
5156
RateLimitedApis extends RateLimitedApiMap,
52-
> = ControllerGetStateAction<typeof name, RateLimitState<RateLimitedApis>>;
57+
> = ControllerGetStateAction<
58+
typeof controllerName,
59+
RateLimitState<RateLimitedApis>
60+
>;
5361

5462
export type RateLimitControllerCallApiAction<
5563
RateLimitedApis extends RateLimitedApiMap,
5664
> = {
57-
type: `${typeof name}:call`;
65+
type: `${typeof controllerName}:call`;
5866
handler: RateLimitController<RateLimitedApis>['call'];
5967
};
6068

@@ -69,19 +77,17 @@ export type RateLimitControllerEvents<
6977
> = RateLimitControllerStateChangeEvent<RateLimitedApis>;
7078

7179
export type RateLimitMessenger<RateLimitedApis extends RateLimitedApiMap> =
72-
RestrictedMessenger<
73-
typeof name,
80+
Messenger<
81+
typeof controllerName,
7482
RateLimitControllerActions<RateLimitedApis>,
75-
RateLimitControllerEvents<RateLimitedApis>,
76-
never,
77-
never
83+
RateLimitControllerEvents<RateLimitedApis>
7884
>;
7985

8086
const metadata = {
8187
requests: {
8288
includeInStateLogs: false,
8389
persist: false,
84-
anonymous: false,
90+
includeInDebugSnapshot: false,
8591
usedInUi: false,
8692
},
8793
};
@@ -92,7 +98,7 @@ const metadata = {
9298
export class RateLimitController<
9399
RateLimitedApis extends RateLimitedApiMap,
94100
> extends BaseController<
95-
typeof name,
101+
typeof controllerName,
96102
RateLimitState<RateLimitedApis>,
97103
RateLimitMessenger<RateLimitedApis>
98104
> {
@@ -131,7 +137,7 @@ export class RateLimitController<
131137
>((acc, key) => ({ ...acc, [key]: {} }), {} as never),
132138
};
133139
super({
134-
name,
140+
name: controllerName,
135141
metadata,
136142
messenger,
137143
state: { ...defaultState, ...state },
@@ -140,8 +146,8 @@ export class RateLimitController<
140146
this.rateLimitTimeout = rateLimitTimeout;
141147
this.rateLimitCount = rateLimitCount;
142148

143-
this.messagingSystem.registerActionHandler(
144-
`${name}:call`,
149+
this.messenger.registerActionHandler(
150+
`${controllerName}:call`,
145151
(
146152
origin: string,
147153
type: keyof RateLimitedApis,
@@ -156,6 +162,7 @@ export class RateLimitController<
156162
* @param origin - The requesting origin.
157163
* @param type - The type of API call to make.
158164
* @param args - Arguments for the API call.
165+
* @returns The result of the API call.
159166
*/
160167
async call<ApiType extends keyof RateLimitedApis>(
161168
origin: string,

packages/rate-limit-controller/tsconfig.build.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
"outDir": "./dist",
66
"rootDir": "./src"
77
},
8-
"references": [{ "path": "../base-controller/tsconfig.build.json" }],
8+
"references": [
9+
{ "path": "../base-controller/tsconfig.build.json" },
10+
{ "path": "../messenger/tsconfig.build.json" }
11+
],
912
"include": ["../../types", "./src"]
1013
}

packages/rate-limit-controller/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
"compilerOptions": {
44
"baseUrl": "./"
55
},
6-
"references": [{ "path": "../base-controller" }],
6+
"references": [{ "path": "../base-controller" }, { "path": "../messenger" }],
77
"include": ["../../types", "./src"]
88
}

yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,6 +4592,7 @@ __metadata:
45924592
dependencies:
45934593
"@metamask/auto-changelog": "npm:^3.4.4"
45944594
"@metamask/base-controller": "npm:^8.4.2"
4595+
"@metamask/messenger": "npm:^0.3.0"
45954596
"@metamask/rpc-errors": "npm:^7.0.2"
45964597
"@metamask/utils": "npm:^11.8.1"
45974598
"@types/jest": "npm:^27.4.1"

0 commit comments

Comments
 (0)