Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[base-controller] Controller constructors accept messengers that do not allow any of its internal actions and/or events #4501

Open
MajorLift opened this issue Jul 3, 2024 · 0 comments
Assignees
Labels
bug Something isn't working team-wallet-framework

Comments

@MajorLift
Copy link
Contributor

Problem

Constructor controllers currently raise a type error when instantiated with a messenger that was defined with an incomplete list of internal actions/events, but fail to raise that error if either the Action or Event type union of the messenger's parent ControllerMessenger doesn't contain any of the controller's internal actions/events.

Repro

/**
 * 1. Controller constructor erroneously accepts messenger if one or more of its internal message lists are "empty"
 */

/* A. Both internal message lists are empty */

const emptyInternalMessageListsControllerMessenger = new ControllerMessenger<
  // `TokenRatesControllerGetStateAction` is the only member of `TokenRatesControllerActions`
  Exclude<TokenRatesControllerActions, TokenRatesControllerGetStateAction> | TokenRatesControllerAllowedActions,
  // `TokenRatesControllerStateChangeEvent` is the only member of `TokenRatesControllerEvents`
  Exclude<TokenRatesControllerEvents, TokenRatesControllerStateChangeEvent> | TokenRatesControllerAllowedEvents
>()
  
new TokenRatesController({
  messenger: emptyInternalMessageListsControllerMessenger.getRestricted({
    name: 'TokenRatesController',
    allowedActions: [
      'TokensController:getState',
      'NetworkController:getNetworkClientById',
      'NetworkController:getState',
      'AccountsController:getAccount',
      'AccountsController:getSelectedAccount',
    ],
    allowedEvents: [
      'TokensController:stateChange',
      'NetworkController:stateChange',
      'AccountsController:selectedEvmAccountChange'
    ],
  }),
  tokenPricesService: buildMockTokenPricesService(),
})

/* B. Only one internal message list is empty */

const emptyInternalMessageListControllerMessenger = new ControllerMessenger<
  TokenRatesControllerActions | TokenRatesControllerAllowedActions,
  // `TokenRatesControllerStateChangeEvent` is the only member of `TokenRatesControllerEvents`
  Exclude<TokenRatesControllerEvents, TokenRatesControllerStateChangeEvent> | TokenRatesControllerAllowedEvents
>()
  
new TokenRatesController({
  messenger: emptyInternalMessageListControllerMessenger.getRestricted({
    name: 'TokenRatesController',
    allowedActions: [
      'TokensController:getState',
      'NetworkController:getNetworkClientById',
      'NetworkController:getState',
      'AccountsController:getAccount',
      'AccountsController:getSelectedAccount',
    ],
    allowedEvents: [
      'TokensController:stateChange',
      'NetworkController:stateChange',
      'AccountsController:selectedEvmAccountChange'
    ],
  }),
  tokenPricesService: buildMockTokenPricesService(),
})

// Argument of type '"TokenRatesController:getState"' is not assignable to parameter of type 
// '"TokensController:getState" | "NetworkController:getNetworkClientById" | "NetworkController:getState" | 
// "AccountsController:getAccount" | "AccountsController:getSelectedAccount"'.(2345)
emptyInternalMessageListsControllerMessenger.call('TokenRatesController:getState')
emptyInternalMessageListsControllerMessenger.call('NetworkController:getState')

// Argument of type '"TokenRatesController:stateChange"' is not assignable to parameter of type 
// '"TokensController:stateChange" | "NetworkController:stateChange" | "AccountsController:selectedEvmAccountChange"'.(2345)
emptyInternalMessageListControllerMessenger.subscribe('TokenRatesController:stateChange', [])


/**
 * 2. Controller constructor raises error when passed messenger with "incomplete" internal message lists
 */

const incompleteInternalMessageListControllerMessenger = new ControllerMessenger<
  | Extract<
      AccountsControllerActions, 
      | AccountsControllerGetAccountAction 
      | AccountsControllerGetSelectedAccountAction
    > 
  | AccountsControllerAllowedActions,
  | Extract<
      AccountsControllerEvents,
      AccountsControllerSelectedEvmAccountChangeEvent
    > 
  | AccountsControllerAllowedEvents
>()

new AccountsController({
//   Type 'ControllerMessenger<AccountsControllerGetAccountAction | AccountsControllerGetSelectedAccountAction 
// | AccountsControllerAllowedActions, AccountsControllerSelectedEvmAccountChangeEvent | AccountsControllerAllowedEvents>' 
// is not assignable to type 'AccountsControllerMessenger'.
//   Property '#private' in type 'ControllerMessenger' refers to a different member 
// that cannot be accessed from within type 'RestrictedControllerMessenger'.(2322)
// AccountsController.d.ts(102, 9): The expected type comes from property 'messenger' 
// which is declared here on type '{ messenger: AccountsControllerMessenger; state: AccountsControllerState; }'
  messenger: incompleteInternalMessageListControllerMessenger,
  state: {
    internalAccounts: {
      accounts: {},
      selectedAccount: '',
    },
  },
})

playground link

Acceptance Criteria

Controllers inheriting from BaseControllerV2 must raise a type and/or runtime error if they are initialized with a messenger that is derived from an unrestricted ControllerMessenger that does not contain any of the controller's internal actions and/or events.

References

@MajorLift MajorLift mentioned this issue Jul 3, 2024
3 tasks
@MajorLift MajorLift added the bug Something isn't working label Jul 17, 2024
@MajorLift MajorLift self-assigned this Jul 24, 2024
@MajorLift MajorLift mentioned this issue Jul 25, 2024
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working team-wallet-framework
Projects
None yet
Development

No branches or pull requests

1 participant