Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/examples/packages/preinstalled/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"@jest/globals": "^29.5.0",
"@lavamoat/allow-scripts": "^4.0.0",
"@metamask/auto-changelog": "^6.1.1",
"@metamask/messenger": "^1.2.0",
"@metamask/snaps-cli": "workspace:^",
"@metamask/snaps-jest": "workspace:^",
"@metamask/snaps-sdk": "workspace:^",
Expand Down
7 changes: 5 additions & 2 deletions packages/examples/packages/preinstalled/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snaps.git"
},
"source": {
"shasum": "HEK+eFeY5FqLG4XSbZzP7BoXJgXptNV0lHtuxuFEym8=",
"shasum": "4Orr2LFWey4elfpvTf6tdUOBsaVCnahshTHv3v9Bf7I=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand All @@ -25,7 +25,10 @@
},
"snap_dialog": {},
"endowment:page-settings": {},
"snap_manageState": {}
"snap_manageState": {},
"endowment:messenger": {
"actions": ["PhishingController:testOrigin"]
}
},
"platformVersion": "11.1.1",
"manifestVersion": "0.1"
Expand Down
12 changes: 12 additions & 0 deletions packages/examples/packages/preinstalled/src/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,18 @@ describe('onRpcRequest', () => {
});
});
});

describe('messengerCall', () => {
it('calls the PhishingController', async () => {
const { request } = await installSnap();

const response = await request({
method: 'messengerCall',
});

expect(response).toRespondWith(false);
});
});
});

describe('onSettingsPage', () => {
Expand Down
18 changes: 18 additions & 0 deletions packages/examples/packages/preinstalled/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Messenger } from '@metamask/messenger';
import {
getJsonError,
getMessenger,
MethodNotFoundError,
UserInputEventType,
} from '@metamask/snaps-sdk';
Expand All @@ -17,6 +19,13 @@ type SnapState = {
setting3?: 'option1' | 'option2';
};

type PhishingControllerTestOrigin = {
type: 'PhishingController:testOrigin';
handler: (origin: string) => { result: boolean; type: string };
};

type SnapMessenger = Messenger<string, PhishingControllerTestOrigin>;

/**
* Handle incoming JSON-RPC requests from the dapp, sent through the
* `wallet_invokeSnap` method. This handler handles the following methods:
Expand Down Expand Up @@ -97,6 +106,15 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
});
}

case 'messengerCall': {
const messenger = getMessenger<SnapMessenger>();
const { result } = await messenger.call(
'PhishingController:testOrigin',
'https://metamask.io',
);
return result;
}

default:
throw new MethodNotFoundError({ method: request.method });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"resources": {
"@metamask/json-rpc-engine": {
"packages": {
"@metamask/snaps-utils>@metamask/messenger": true,
"@metamask/snaps-sdk>@metamask/messenger": true,
"@metamask/rpc-errors": true,
"@metamask/providers>@metamask/safe-event-emitter": true,
"@metamask/utils": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"resources": {
"@metamask/json-rpc-engine": {
"packages": {
"@metamask/snaps-utils>@metamask/messenger": true,
"@metamask/snaps-sdk>@metamask/messenger": true,
"@metamask/rpc-errors": true,
"@metamask/providers>@metamask/safe-event-emitter": true,
"@metamask/utils": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"resources": {
"@metamask/json-rpc-engine": {
"packages": {
"@metamask/snaps-utils>@metamask/messenger": true,
"@metamask/snaps-sdk>@metamask/messenger": true,
"@metamask/rpc-errors": true,
"@metamask/providers>@metamask/safe-event-emitter": true,
"@metamask/utils": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"resources": {
"@metamask/json-rpc-engine": {
"packages": {
"@metamask/snaps-utils>@metamask/messenger": true,
"@metamask/snaps-sdk>@metamask/messenger": true,
"@metamask/rpc-errors": true,
"@metamask/providers>@metamask/safe-event-emitter": true,
"@metamask/utils": true
Expand Down
8 changes: 4 additions & 4 deletions packages/snaps-rpc-methods/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ module.exports = deepmerge(baseConfig, {
],
coverageThreshold: {
global: {
branches: 97.28,
functions: 98.88,
lines: 99.19,
statements: 98.91,
branches: 97.38,
functions: 98.92,
lines: 99.22,
statements: 98.95,
},
},
});
1 change: 1 addition & 0 deletions packages/snaps-rpc-methods/src/endowments/enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export enum SnapEndowments {
SettingsPage = 'endowment:page-settings',
Assets = 'endowment:assets',
Protocol = 'endowment:protocol',
Messenger = 'endowment:messenger',
}
8 changes: 8 additions & 0 deletions packages/snaps-rpc-methods/src/endowments/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import {
keyringEndowmentBuilder,
} from './keyring';
import { lifecycleHooksEndowmentBuilder } from './lifecycle-hooks';
import {
getMessengerCaveatMapper,
messengerCaveatSpecifications,
messengerEndowmentBuilder,
} from './messenger';
import { multichainProviderEndowmentBuilder } from './multichain-provider';
import {
getNameLookupCaveatMapper,
Expand Down Expand Up @@ -71,6 +76,7 @@ export const endowmentPermissionBuilders = {
[signatureInsightEndowmentBuilder.targetName]:
signatureInsightEndowmentBuilder,
[assetsEndowmentBuilder.targetName]: assetsEndowmentBuilder,
[messengerEndowmentBuilder.targetName]: messengerEndowmentBuilder,
} as const;

export const endowmentCaveatSpecifications = {
Expand All @@ -82,6 +88,7 @@ export const endowmentCaveatSpecifications = {
...signatureInsightCaveatSpecifications,
...maxRequestTimeCaveatSpecifications,
...protocolCaveatSpecifications,
...messengerCaveatSpecifications,
};

export const endowmentCaveatMappers: Record<
Expand Down Expand Up @@ -114,6 +121,7 @@ export const endowmentCaveatMappers: Record<
[assetsEndowmentBuilder.targetName]: createMaxRequestTimeMapper(
getAssetsCaveatMapper,
),
[messengerEndowmentBuilder.targetName]: getMessengerCaveatMapper,
};

// We allow null because a permitted handler does not have an endowment
Expand Down
149 changes: 149 additions & 0 deletions packages/snaps-rpc-methods/src/endowments/messenger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { PermissionType, SubjectType } from '@metamask/permission-controller';
import { SnapCaveatType } from '@metamask/snaps-utils';

import { SnapEndowments } from './enum';
import {
getMessengerCaveatMapper,
messengerCaveatSpecifications,
messengerEndowmentBuilder,
getMessengerCaveatActions,
} from './messenger';

describe('endowment:messenger', () => {
it('builds the expected permission specification', () => {
const specification = messengerEndowmentBuilder.specificationBuilder({});
expect(specification).toStrictEqual({
permissionType: PermissionType.Endowment,
targetName: SnapEndowments.Messenger,
endowmentGetter: expect.any(Function),
allowedCaveats: [SnapCaveatType.MessengerScopes],
subjectTypes: [SubjectType.Snap],
validator: expect.any(Function),
});

expect(specification.endowmentGetter()).toBeNull();
});

describe('validator', () => {
it('throws if the caveat is not a single "messengerScopes"', () => {
const specification = messengerEndowmentBuilder.specificationBuilder({});

expect(() =>
specification.validator({
// @ts-expect-error Missing other required permission types.
caveats: undefined,
}),
).toThrow('Expected the following caveats: "messengerScopes".');

expect(() =>
// @ts-expect-error Missing other required permission types.
specification.validator({
caveats: [{ type: 'foo', value: 'bar' }],
}),
).toThrow(
'Expected the following caveats: "messengerScopes", received "foo".',
);

expect(() =>
// @ts-expect-error Missing other required permission types.
specification.validator({
caveats: [
{ type: SnapCaveatType.MessengerScopes, value: 'bar' },
{ type: SnapCaveatType.MessengerScopes, value: 'bar' },
],
}),
).toThrow('Duplicate caveats are not allowed.');
});
});
});

describe('getMessengerCaveatMapper', () => {
it('maps a value to a caveat', () => {
expect(
getMessengerCaveatMapper({
actions: ['Foo:bar'],
}),
).toStrictEqual({
caveats: [
{
type: SnapCaveatType.MessengerScopes,
value: {
actions: ['Foo:bar'],
},
},
],
});
});

it('returns null if value is empty', () => {
expect(getMessengerCaveatMapper({})).toStrictEqual({ caveats: null });
});
});

describe('getMessengerCaveatActions', () => {
it('returns the actions from the caveat', () => {
expect(
// @ts-expect-error Missing other required permission types.
getMessengerCaveatActions({
caveats: [
{
type: SnapCaveatType.MessengerScopes,
value: { actions: ['Foo:bar'] },
},
],
}),
).toStrictEqual(['Foo:bar']);
});

it('returns null if no caveat found', () => {
expect(
// @ts-expect-error Missing other required permission types.
getMessengerCaveatActions({
caveats: null,
}),
).toBeNull();
});
});

describe('messengerCaveatSpecifications', () => {
describe('validator', () => {
it('throws if the caveat values are invalid', () => {
expect(() =>
messengerCaveatSpecifications[
SnapCaveatType.MessengerScopes
].validator?.(
// @ts-expect-error Missing value type.
{
type: SnapCaveatType.MessengerScopes,
},
),
).toThrow('Expected an object.');

expect(() =>
messengerCaveatSpecifications[
SnapCaveatType.MessengerScopes
].validator?.({
type: SnapCaveatType.MessengerScopes,
value: {
foo: 'bar',
},
}),
).toThrow(
'Invalid messenger scopes specified: At path: foo -- Expected a value of type `never`, but received: `"bar"`',
);

expect(() =>
messengerCaveatSpecifications[
SnapCaveatType.MessengerScopes
].validator?.({
type: SnapCaveatType.MessengerScopes,
value: {
actions: [],
},
}),
).toThrow(
'Invalid messenger scopes specified: At path: actions -- Expected a array with a length between `1` and `Infinity` but received one with a length of `0`.',
);
});
});
});
Loading
Loading