Skip to content

fix: ComposableController instantiation and functionality is broken #10073

@MajorLift

Description

@MajorLift

What is this about?

Explanation

ComposableController usage in the mobile Engine is currently broken in two ways.

  1. The first argument of the ComposableController's constructor has a type constraint that is incompatible with V1 members of the controllers input array.
Argument of type '(PhishingController | AccountsController | AccountTrackerController | AddressBookController | ... 22 more ... | SwapsController)[]' is not assignable to parameter of type 'ControllerList'.
  Type 'PhishingController | AccountsController | AccountTrackerController | AddressBookController | ... 22 more ... | SwapsController' is not assignable to type 'BaseController<any, any> | { name: string; state: Record<string, unknown>; }'.
    Type 'AccountTrackerController' is not assignable to type 'BaseController<any, any> | { name: string; state: Record<string, unknown>; }'.
      Type 'AccountTrackerController' is not assignable to type 'BaseController<any, any>'.
        Types have separate declarations of a private property 'initialConfig'.ts(2345)

(This error is also encountered with later versions of ComposableController. See MetaMask/core#4448)

Up until now, this error has been suppressed with the following comment, which is incorrect:

// @ts-expect-error The ComposableController needs to be updated to support BaseControllerV2
  1. The second argument passed into the ComposableController constructor has always been a ControllerMessenger class instance, when it should have been a RestrictedControllerMessenger.
    this.datamodel = new ComposableController(
      controllers,
-     this.controllerMessenger,
+     this.controllerMessenger.getRestricted({
+       name: 'ComposableController',
+       allowedActions: [],
+       allowedEvents: [
...
+       ],
+     )},
    );

This grants the ComposableController wider permissions than intended (we only want to allow stateChange events for all child controllers), and generally goes against our recommended usage pattern for messengers.

(However, it shouldn't prevent the controllerMessenger or ComposableController state from subscribing to state updates from child controllers)

Solution

  1. Add tests to Engine.test.js file verifying that the datamodel has subscribed to state updates from all child controllers (both those with a messagingSystem, and V1 controllers with no messagingSystem).

  2. Bump @metamask/composable-controller to the latest version which offers better type safety and quality-of-life improvements.

@metamask/[email protected] features widespread any usage, which would unnecessarily complicate any debugging efforts.

  1. For the issue of defining a type constraint that can accept V1 controllers for the first argument controllers, attempt to resolve by bumping V1 controllers from mobile.

If unsuccessful, wait until the issue is fixed from the ComposableController side: MetaMask/core#4448

Scenario

No response

Design

No response

Technical Details

No response

Threat Modeling Framework

No response

Acceptance Criteria

No response

Stakeholder review needed before the work gets merged

  • Engineering (needed in most cases)
  • Design
  • Product
  • QA (automation tests are required to pass before merging PRs but not all changes are covered by automation tests - please review if QA is needed beyond automation tests)
  • Security
  • Legal
  • Marketing
  • Management (please specify)
  • Other (please specify)

References

No response

Metadata

Metadata

Assignees

Labels

Sev2-normalAn issue that may lead to users misunderstanding some limited risks they are takingrelease-7.38.0Issue or pull request that will be included in release 7.38.0team-wallet-frameworktype-bugSomething isn't working

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions