Skip to content

Commit

Permalink
Add initialConnections to requestState (#2322)
Browse files Browse the repository at this point in the history
This PR adds `initialConnections` specification from manifest to
`requestState` object which is used on Snap installation or update
process.

Related ticket:
https://github.com/MetaMask/MetaMask-planning/issues/1895
Blocking: https://github.com/MetaMask/MetaMask-planning/issues/1895
  • Loading branch information
david0xd authored Apr 10, 2024
1 parent f6ac2b0 commit 0f54270
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 3 deletions.
2 changes: 1 addition & 1 deletion packages/snaps-controllers/coverage.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"branches": 90.9,
"branches": 91.22,
"functions": 96.58,
"lines": 97.85,
"statements": 97.52
Expand Down
120 changes: 120 additions & 0 deletions packages/snaps-controllers/src/snaps/SnapController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,114 @@ describe('SnapController', () => {
await service.terminateAllSnaps();
});

it('includes the initialConnections data in the approval requestState when installing a Snap', async () => {
const rootMessenger = getControllerMessenger();
const messenger = getSnapControllerMessenger(rootMessenger);

rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => ({}),
);

const initialConnections = {
'npm:filsnap': {},
'https://snaps.metamask.io': {},
};

const { manifest } = await getMockSnapFilesWithUpdatedChecksum({
manifest: getSnapManifest({
initialConnections,
}),
});

const snapController = getSnapController(
getSnapControllerOptions({
messenger,
detectSnapLocation: loopbackDetect({ manifest }),
}),
);

await snapController.installSnaps(MOCK_ORIGIN, {
[MOCK_SNAP_ID]: {},
});

expect(messenger.call).toHaveBeenNthCalledWith(
4,
'ApprovalController:updateRequestState',
{
id: expect.any(String),
requestState: {
loading: false,
connections: initialConnections,
permissions: expect.anything(),
},
},
);

snapController.destroy();
});

it('includes the initialConnections data in the approval requestState when updating a Snap', async () => {
const rootMessenger = getControllerMessenger();
const messenger = getSnapControllerMessenger(rootMessenger);

rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => ({}),
);

const initialConnections = {
'npm:filsnap': {},
'https://snaps.metamask.io': {},
};

const { manifest } = await getMockSnapFilesWithUpdatedChecksum({
manifest: getSnapManifest({
version: '1.1.0' as SemVerVersion,
initialConnections,
}),
});

const detectSnapLocation = loopbackDetect({
manifest: manifest.result,
});

const snapController = getSnapController(
getSnapControllerOptions({
messenger,
state: {
snaps: getPersistedSnapsState(),
},
detectSnapLocation,
}),
);

await snapController.updateSnap(
MOCK_ORIGIN,
MOCK_SNAP_ID,
detectSnapLocation(),
);

expect(messenger.call).toHaveBeenNthCalledWith(
4,
'ApprovalController:updateRequestState',
{
id: expect.any(String),
requestState: {
connections: initialConnections,
permissions: expect.anything(),
newVersion: '1.1.0',
newPermissions: expect.anything(),
approvedPermissions: {},
unusedPermissions: {},
loading: false,
},
},
);

snapController.destroy();
});

it('installs a snap via installSnaps', async () => {
const messenger = getSnapControllerMessenger();
const snapController = getSnapController(
Expand Down Expand Up @@ -613,6 +721,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions,
},
},
Expand Down Expand Up @@ -3594,6 +3703,7 @@ describe('SnapController', () => {
expect.objectContaining({
id: expect.any(String),
requestState: {
connections: {},
permissions,
loading: false,
},
Expand Down Expand Up @@ -3744,6 +3854,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions,
},
}),
Expand Down Expand Up @@ -3838,6 +3949,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions,
},
}),
Expand Down Expand Up @@ -4463,6 +4575,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions,
},
}),
Expand Down Expand Up @@ -4651,6 +4764,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions: {
[handlerEndowments.onRpcRequest as string]: {
caveats: [
Expand Down Expand Up @@ -4780,6 +4894,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions: {
[SnapEndowments.Rpc]: {
caveats: [caveat],
Expand Down Expand Up @@ -5012,6 +5127,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions: {},
newVersion,
newPermissions: {},
Expand Down Expand Up @@ -5736,6 +5852,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions: {},
newVersion: '1.1.0',
newPermissions: {},
Expand Down Expand Up @@ -5927,6 +6044,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions: {},
newVersion: '1.1.0',
newPermissions: {},
Expand Down Expand Up @@ -6086,6 +6204,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions,
newVersion: '1.1.0',
newPermissions: permissions,
Expand Down Expand Up @@ -6260,6 +6379,7 @@ describe('SnapController', () => {
id: expect.any(String),
requestState: {
loading: false,
connections: {},
permissions: { 'endowment:network-access': {} },
newVersion: '1.1.0',
newPermissions: { 'endowment:network-access': {} },
Expand Down
5 changes: 4 additions & 1 deletion packages/snaps-controllers/src/snaps/SnapController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2386,6 +2386,7 @@ export class SnapController extends BaseController<
this.#calculatePermissionsChange(snapId, processedPermissions);

this.#updateApproval(pendingApproval.id, {
connections: manifest.initialConnections ?? {},
permissions: newPermissions,
newVersion: manifest.version,
newPermissions,
Expand Down Expand Up @@ -2738,6 +2739,7 @@ export class SnapController extends BaseController<
preinstalled,

id: snapId,
initialConnections: manifest.result.initialConnections,
initialPermissions: manifest.result.initialPermissions,
manifest: manifest.result,
status: this.#statusMachine.config.initial as StatusStates['value'],
Expand Down Expand Up @@ -2835,7 +2837,7 @@ export class SnapController extends BaseController<
log(`Authorizing snap: ${snapId}`);
const snapsState = this.state.snaps;
const snap = snapsState[snapId];
const { initialPermissions } = snap;
const { initialPermissions, initialConnections } = snap;

try {
const processedPermissions = processSnapPermissions(initialPermissions);
Expand All @@ -2844,6 +2846,7 @@ export class SnapController extends BaseController<

this.#updateApproval(pendingApproval.id, {
loading: false,
connections: initialConnections ?? {},
permissions: processedPermissions,
});

Expand Down
10 changes: 9 additions & 1 deletion packages/snaps-utils/src/snaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ import validateNPMPackage from 'validate-npm-package-name';
import { SnapCaveatType } from './caveats';
import { checksumFiles } from './checksum';
import type { LocalizationFile } from './localization';
import type { SnapManifest, SnapPermissions } from './manifest/validation';
import type {
InitialConnections,
SnapManifest,
SnapPermissions,
} from './manifest/validation';
import type { FetchedSnapFiles, SnapsPermissionRequest } from './types';
import { SnapIdPrefixes, SnapValidationFailureReason, uri } from './types';
import type { VirtualFile } from './virtual-file';
Expand Down Expand Up @@ -85,6 +89,10 @@ export type PersistedSnap = Snap;
* A Snap as it exists in {@link SnapController} state.
*/
export type Snap = TruncatedSnap & {
/**
* The initial connections of the Snap, optional, requested on installation.
*/
initialConnections?: InitialConnections;
/**
* The initial permissions of the Snap, which will be requested when it is
* installed.
Expand Down

0 comments on commit 0f54270

Please sign in to comment.