Skip to content

[base-controller] Implement utility type ControllerActionsMap for generating, storing, exposing internal action types #4583

Open
@MajorLift

Description

@MajorLift

Motivation

  • Currently, we manually enumerate each individual internal action type definition in controller files, and then manually enumerate them again in the type union for internal actions (example). We should have a DRY-er way of doing this.
  • Most handlers for controller internal actions are simply public controller class methods bound to the controller instance.
  • Instead of exporting each action separately, we could export a single "controller actions map" type that contains all internal actions, and use it to select and extract any number of its stored action types.

Proof of concept

/**
 * A utility type that derives the public method names of a given messenger consumer class,
 * and uses it to generate the class's internal messenger action types.
 * @template Controller - A messenger consumer class.
 */
// TODO: Figure out generic constraint and move to base-controller
type ControllerActionsMap<Controller> = {
  [ClassMethod in keyof PublicInterface<Controller> as Controller[ClassMethod] extends ActionConstraint['handler']
    ? ClassMethod
    : never]: {
    type: `${typeof name}:${ClassMethod & string}`;
    handler: Controller[ClassMethod];
  };
};

type AssetsContractControllerActionsMap =
  ControllerActionsMap<AssetsContractController>;

/**
 * The union of all public class method names of {@link AssetsContractController}.
 */
type AssetsContractControllerMethodName =
  keyof AssetsContractControllerActionsMap;

/**
 * The union of all internal messenger actions available to the {@link AssetsContractControllerMessenger}.
 */
export type AssetsContractControllerActions =
  AssetsContractControllerActionsMap[AssetsContractControllerMethodName];

/* 
 * A single internal action type selected from the controller actions map
 */
export type AssetsContractControllerGetERC20StandardAction =
  AssetsContractControllerActionsMap['getERC20Standard'];

/**
 * A union of several internal types selected from the controller actions map
 */
export type AssetsContractControllerGetStandardActions = 
  AssetsContractControllerActionsMap['getERC20Standard' | 'getERC721Standard' | 'getERC1155Standard']

https://github.com/MetaMask/core/pull/4397/files#diff-7ada7b099f6bcc6f3d4acd71f94b604636abd22cc556a76dbe7b3e610b1d9233R90-R118

Acceptance Criteria

  • MVP: Write a generic type that...
    • a) Accepts a controller class.
    • b) Derives its public class method names.
    • c) Uses them to generate the class's internal messenger action types.
    • d) Outputs a type object populated with the action types.
    • e) The types are keyed with the de-namespaced action names (i.e. getERC20Standard instead of AssetsContractController:getERC20Standard).
  • Stretch: Better handling for exceptions.
    • a) Accepts a map of action names and handlers which are exceptions to the general rule that each class method corresponds to an action handler.
    • b) Add these exceptions to the controller actions map as well.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions