feat: shield controller wire in wallet package#9616
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 0fc9607. Configure here.
| options: ShieldControllerInstanceOptions; | ||
| }) => { | ||
| return new ShieldController({ | ||
| messenger: messenger as unknown as ShieldControllerMessenger, |
| transactionHistoryLimit: options.transactionHistoryLimit, | ||
| coverageHistoryLimit: options.coverageHistoryLimit, | ||
| normalizeSignatureRequest: options.normalizeSignatureRequest, |
There was a problem hiding this comment.
Let's just forward instead of hard assigning each.
| transactionHistoryLimit: options.transactionHistoryLimit, | |
| coverageHistoryLimit: options.coverageHistoryLimit, | |
| normalizeSignatureRequest: options.normalizeSignatureRequest, | |
| ...options, |
| import type { SignatureStateChange } from '@metamask/signature-controller'; | ||
| import type { TransactionControllerStateChangeEvent } from '@metamask/transaction-controller'; | ||
|
|
||
| export type ShieldBackend = Pick< |
There was a problem hiding this comment.
Why do we need to modify this?
I've noticed that this is being used in ShieldControllerInstanceOptions. I don't think we will ever provide the custom backend instance here.
| export type ShieldControllerInitializationMessenger = Messenger< | ||
| 'ShieldController', | ||
| ShieldControllerActions | AuthenticationControllerGetBearerTokenAction, | ||
| | ShieldControllerEvents | ||
| | SignatureStateChange | ||
| | TransactionControllerStateChangeEvent | ||
| >; |
There was a problem hiding this comment.
Messenger should come from the controller package right? Why?
| export type ShieldControllerInstanceOptions = { | ||
| /** | ||
| * When set, used as-is; `baseUrl`, `fetchFunction`, `getAccessToken`, and | ||
| * `captureException` are ignored for backend construction. | ||
| */ | ||
| backend?: ShieldBackend; | ||
| /** Required when building the default `ShieldRemoteBackend`. */ | ||
| baseUrl: string; | ||
| fetchFunction: typeof fetch; | ||
| getAccessToken?: () => Promise<string>; | ||
| captureException?: (error: Error) => void; | ||
| getCoverageResultTimeout?: number; | ||
| getCoverageResultPollInterval?: number; | ||
| transactionHistoryLimit?: number; | ||
| coverageHistoryLimit?: number; | ||
| normalizeSignatureRequest?: NormalizeSignatureRequestFn; | ||
| }; |
There was a problem hiding this comment.
Please use direct type reference from controller, instead of redefining or overrides.
| export type ShieldControllerInstanceOptions = { | |
| /** | |
| * When set, used as-is; `baseUrl`, `fetchFunction`, `getAccessToken`, and | |
| * `captureException` are ignored for backend construction. | |
| */ | |
| backend?: ShieldBackend; | |
| /** Required when building the default `ShieldRemoteBackend`. */ | |
| baseUrl: string; | |
| fetchFunction: typeof fetch; | |
| getAccessToken?: () => Promise<string>; | |
| captureException?: (error: Error) => void; | |
| getCoverageResultTimeout?: number; | |
| getCoverageResultPollInterval?: number; | |
| transactionHistoryLimit?: number; | |
| coverageHistoryLimit?: number; | |
| normalizeSignatureRequest?: NormalizeSignatureRequestFn; | |
| }; | |
| export type ShieldControllerInstanceOptions = | |
| ConstructorParameters<typeof ShieldController>[0]; |
| transactionController?: TransactionControllerInstanceOptions; | ||
| passkeyController?: PasskeyControllerInstanceOptions; | ||
| seedlessOnboardingController?: SeedlessOnboardingControllerInstanceOptions; | ||
| shieldController: ShieldControllerInstanceOptions; |
There was a problem hiding this comment.
Why shieldController is required type here?
There was a problem hiding this comment.
Most controllers/services are optional here.

Explanation
Adds ShieldController as a default initialized unit in @metamask/wallet.
@metamask/wallet is the shared controller-integration layer for extension, mobile, and other clients. Build-specific and runtime values are injected via instanceOptions rather than hardcoded.
Breaking changes
References
Checklist
Note
High Risk
Breaking change for all wallet consumers; Shield touches transaction/signature coverage and auth token wiring, so misconfiguration or missing peer controllers could affect security-related flows.
Overview
Breaking:
@metamask/walletnow initializes ShieldController by default and requires a newinstanceOptions.shieldControllerslot (baseUrl,fetchFunction, or an injectedbackend).The wallet adds a shield initialization module that builds
ShieldRemoteBackendby default (optionalgetAccessToken, polling, history limits,normalizeSignatureRequest), delegatesAuthenticationController:getBearerTokenand transaction/signaturestateChangeevents on the root messenger, and does not auto-start Shield—hosts must registerAuthenticationControllerandSignatureControllerand callShieldController:startexplicitly.wallet-cli passes the production ruleset URL (
https://ruleset-engine.api.cx.metamask.io) andfetchfor the daemon. shield-controller tests update the default API host to the same URL. Package deps add@metamask/shield-controllerand@metamask/signature-controller; CODEOWNERS and README dependency graph are updated.Reviewed by Cursor Bugbot for commit a905ac5. Bugbot is set up for automated code reviews on this repo. Configure here.