Skip to content

Commit 67d3797

Browse files
committed
Use UI messenger in Snaps settings component
1 parent b4283be commit 67d3797

6 files changed

Lines changed: 83 additions & 21 deletions

File tree

app/components/Views/Snaps/SnapSettings/SnapSettings.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ import { selectInternalAccounts } from '../../../../selectors/accountsController
3535
import { InternalAccount } from '@metamask/keyring-internal-api';
3636
import Logger from '../../../../util/Logger';
3737
import { areAddressesEqual } from '../../../../util/address';
38+
import { RouteMessengerInstance } from './messenger';
39+
import { useMessenger } from '../../../../hooks/useMessenger';
3840
interface SnapSettingsProps {
3941
snap: Snap;
4042
}
@@ -46,6 +48,7 @@ const SnapSettings = () => {
4648
const { styles, theme } = useStyles(stylesheet, {});
4749
const { colors } = theme;
4850
const navigation = useNavigation();
51+
const messenger = useMessenger<RouteMessengerInstance>();
4952

5053
const { snap } = useParams<SnapSettingsProps>();
5154
const permissionsState = useSelector(selectPermissionControllerState);
@@ -105,8 +108,7 @@ const SnapSettings = () => {
105108
}, []);
106109

107110
const removeSnap = useCallback(async () => {
108-
const { SnapController } = Engine.context;
109-
await SnapController.removeSnap(snap.id);
111+
await messenger.call('SnapController:removeSnap', snap.id);
110112

111113
if (isKeyringSnap && keyringAccounts.length > 0) {
112114
try {
@@ -121,7 +123,7 @@ const SnapSettings = () => {
121123
}
122124
}
123125
navigation.goBack();
124-
}, [isKeyringSnap, keyringAccounts, navigation, snap.id]);
126+
}, [isKeyringSnap, keyringAccounts, navigation, messenger, snap.id]);
125127

126128
const handleRemoveSnap = useCallback(() => {
127129
if (isKeyringSnap && keyringAccounts.length > 0) {

app/components/Views/Snaps/SnapSettings/messenger.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ import { defineAllowedRouteCapabilities } from '../../../../messengers/helpers/r
22
import type { RouteMessengerFromCapabilities } from '../../../../messengers/route-messenger';
33

44
export const ALLOWED_CAPABILITIES = defineAllowedRouteCapabilities({
5-
actions: ['SnapController:disconnectOrigin', 'SnapController:installSnaps'],
5+
actions: [
6+
'SnapController:disconnectOrigin',
7+
'SnapController:installSnaps',
8+
'SnapController:removeSnap',
9+
],
610
events: [],
711
});
812

app/hooks/useMessenger.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { useRouteMessenger } from '../contexts/route-messenger';
2+
import type { RouteMessenger } from '../messengers/route-messenger';
3+
4+
/**
5+
* Use this hook to access the messenger that corresponds to the current route.
6+
* You can then use the messenger to call actions and subscribe to events that
7+
* the route has permission to access.
8+
*
9+
* Supply a {@link RouteMessenger} type as the type parameter to narrow the
10+
* returned messenger to only the actions and events you need.
11+
*
12+
* @returns The route messenger cast to the requested messenger type.
13+
* @example
14+
* ```typescript
15+
* type NetworkListMessenger = RouteMessenger<
16+
* 'NetworkController:addNetwork',
17+
* never
18+
* >;
19+
*
20+
* function NetworkList() {
21+
* const messenger = useMessenger<NetworkListMessenger>();
22+
*
23+
* const onAddNetworkClick = async () => {
24+
* await messenger.call('NetworkController:addNetwork', ...);
25+
* }
26+
*
27+
* return (
28+
* <Button onClick={onAddNetworkClick}>Add Sepolia</Button>
29+
* ):
30+
* }
31+
* ```
32+
*/
33+
export function useMessenger<
34+
RouteMessengerInstance extends RouteMessenger,
35+
>(): RouteMessengerInstance {
36+
const routeMessenger = useRouteMessenger();
37+
38+
// The context only tells us we have *some* kind of route messenger, but not
39+
// what capabilities it has. We trust the caller's type parameter here — the
40+
// route configuration is responsible for ensuring the messenger actually
41+
// supports the requested actions/events.
42+
return routeMessenger as unknown as RouteMessengerInstance;
43+
}

app/messengers/ui-messenger.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -83,21 +83,34 @@ export class UIMessenger extends Messenger<
8383
super({ namespace: UI_MESSENGER_NAMESPACE, captureException });
8484
}
8585

86-
// @ts-expect-error This `call` is purposely not the same `call` from
87-
// `Messenger`.
88-
async call<ActionType extends UIMessengerActions['type']>(
89-
actionType: ActionType,
90-
...params: ExtractActionParameters<UIMessengerActions, ActionType>
91-
): Promise<Awaited<ExtractActionResponse<UIMessengerActions, ActionType>>> {
86+
/**
87+
* Get the handler for a given action type.
88+
*
89+
* This is called when `call` is invoked on the messenger. We override it here
90+
* to route all calls through the background connection, except for the
91+
* excluded actions.
92+
*
93+
* @param actionType - The action type. This is a unique identifier for this
94+
* action.
95+
* @returns The handler for this action type, or undefined if this action type
96+
* is excluded or not found.
97+
*/
98+
protected override getAction(
99+
actionType: UIMessengerActions['type'],
100+
): ActionConstraint['handler'] | undefined {
92101
const excludedActions: string[] = EXCLUDED_ACTIONS;
93102
const anyActionType: string = actionType;
94103

95-
if (!excludedActions.includes(anyActionType)) {
96-
throw new Error(`Action '${actionType}' has not been exposed to the UI`);
104+
if (excludedActions.includes(anyActionType)) {
105+
throw new Error(
106+
`The action "${actionType}" has not been exposed to the UI.`,
107+
);
97108
}
98109

99-
// @ts-expect-error: Type of handler is not compatible.
100-
return await Engine.controllerMessenger.call(actionType, ...params);
110+
return (...args: unknown[]) =>
111+
// @ts-expect-error: `unknown[]` is not assignable to `args`, but the type
112+
// here is checked in `call`, so this is safe.
113+
Engine.controllerMessenger.call(actionType, ...args);
101114
}
102115

103116
/**

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@
201201
"bn.js@npm:5.2.1": "5.2.3",
202202
"expo-web-browser@npm:~14.0.2": "patch:expo-web-browser@npm%3A14.0.2#~/.yarn/patches/expo-web-browser-npm-14.0.2-98d00ce880.patch",
203203
"@metamask/messenger@^0.3.0": "^1.0.0",
204-
"@metamask/messenger": "^1.1.0",
204+
"@metamask/messenger": "^1.2.0",
205205
"@metamask/keyring-internal-api": "^11.0.1",
206206
"@metamask/accounts-controller": "^38.0.0",
207207
"@metamask/profile-sync-controller": "^28.0.2",
@@ -286,7 +286,7 @@
286286
"@metamask/keyring-utils": "^3.2.0",
287287
"@metamask/logging-controller": "^8.0.0",
288288
"@metamask/message-signing-snap": "^1.1.2",
289-
"@metamask/messenger": "^1.1.0",
289+
"@metamask/messenger": "^1.2.0",
290290
"@metamask/metamask-eth-abis": "3.1.1",
291291
"@metamask/mobile-wallet-protocol-core": "^0.4.0",
292292
"@metamask/mobile-wallet-protocol-wallet-client": "^0.3.0",

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9125,17 +9125,17 @@ __metadata:
91259125
languageName: node
91269126
linkType: hard
91279127

9128-
"@metamask/messenger@npm:^1.0.0, @metamask/messenger@npm:^1.1.0":
9129-
version: 1.1.1
9130-
resolution: "@metamask/messenger@npm:1.1.1"
9128+
"@metamask/messenger@npm:^1.0.0, @metamask/messenger@npm:^1.2.0":
9129+
version: 1.2.0
9130+
resolution: "@metamask/messenger@npm:1.2.0"
91319131
dependencies:
91329132
"@metamask/utils": "npm:^11.9.0"
91339133
yargs: "npm:^17.7.2"
91349134
peerDependencies:
91359135
typescript: ">=5.0.0"
91369136
bin:
91379137
messenger-generate-action-types: ./dist/generate-action-types/cli.mjs
9138-
checksum: 10/a959af95e9e117aa0f7ad1c280f7817fef2c0b575c76837b1a6c884c9c9ef1dd0faeaef0c2c0c2035f68c7638d1f87cd172956ee962dec97d8ab6176fa6964e3
9138+
checksum: 10/6818e4609d6162a436cc07955905f9e57ff6dbef841e9066a5fb9cc0538e981526fbcb5eef1fa1968d79212d57ddda2fce4dda5f87eb64d8d98f7db1216a6a98
91399139
languageName: node
91409140
linkType: hard
91419141

@@ -35684,7 +35684,7 @@ __metadata:
3568435684
"@metamask/keyring-utils": "npm:^3.2.0"
3568535685
"@metamask/logging-controller": "npm:^8.0.0"
3568635686
"@metamask/message-signing-snap": "npm:^1.1.2"
35687-
"@metamask/messenger": "npm:^1.1.0"
35687+
"@metamask/messenger": "npm:^1.2.0"
3568835688
"@metamask/metamask-eth-abis": "npm:3.1.1"
3568935689
"@metamask/mobile-provider": "npm:^3.0.0"
3569035690
"@metamask/mobile-wallet-protocol-core": "npm:^0.4.0"

0 commit comments

Comments
 (0)