Skip to content

Commit 2f6a404

Browse files
committed
Add snap metadata to account if owned
1 parent 20ed5ef commit 2f6a404

File tree

7 files changed

+155
-20
lines changed

7 files changed

+155
-20
lines changed

packages/snaps-simulation/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export const DEFAULT_ACCOUNTS: SimulationAccount[] = [
4040
id: '29bc7513-d1b9-4466-98a6-f5f9e0b90137',
4141
scopes: ['eip155:0'],
4242
selected: false,
43+
owned: false,
4344
// We don't expose assets for EVM accounts as it's not supported in the AssetSelector.
4445
assets: [],
4546
},
@@ -52,6 +53,7 @@ export const DEFAULT_ACCOUNTS: SimulationAccount[] = [
5253
'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',
5354
],
5455
selected: true,
56+
owned: true,
5557
assets: [
5658
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:501',
5759
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',

packages/snaps-simulation/src/options.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('getOptions', () => {
1111
"address": "0x1234567890abcdef1234567890abcdef12345678",
1212
"assets": [],
1313
"id": "29bc7513-d1b9-4466-98a6-f5f9e0b90137",
14+
"owned": false,
1415
"scopes": [
1516
"eip155:0",
1617
],
@@ -23,6 +24,7 @@ describe('getOptions', () => {
2324
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
2425
],
2526
"id": "e051723c-85d0-43a3-b9bf-568a90d3f378",
27+
"owned": true,
2628
"scopes": [
2729
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
2830
"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
@@ -72,6 +74,7 @@ describe('getOptions', () => {
7274
"address": "0x1234567890abcdef1234567890abcdef12345678",
7375
"assets": [],
7476
"id": "29bc7513-d1b9-4466-98a6-f5f9e0b90137",
77+
"owned": false,
7578
"scopes": [
7679
"eip155:0",
7780
],
@@ -84,6 +87,7 @@ describe('getOptions', () => {
8487
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
8588
],
8689
"id": "e051723c-85d0-43a3-b9bf-568a90d3f378",
90+
"owned": true,
8791
"scopes": [
8892
"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
8993
"solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",

packages/snaps-simulation/src/options.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const SimulationAccountStruct = object({
2929
id: string(),
3030
scopes: array(CaipChainIdStruct),
3131
selected: defaulted(optional(boolean()), false),
32+
owned: defaulted(optional(boolean()), false),
3233
assets: defaulted(optional(array(CaipAssetTypeStruct)), []),
3334
});
3435

packages/snaps-simulation/src/simulation.test.ts

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import { DIALOG_APPROVAL_TYPES } from '@metamask/snaps-rpc-methods';
1010
import type { CaipAssetType, CaipChainId } from '@metamask/snaps-sdk';
1111
import { AuxiliaryFileEncoding, text } from '@metamask/snaps-sdk';
1212
import { VirtualFile } from '@metamask/snaps-utils';
13-
import { getSnapManifest } from '@metamask/snaps-utils/test-utils';
13+
import {
14+
getSnapManifest,
15+
MOCK_SNAP_ID,
16+
} from '@metamask/snaps-utils/test-utils';
1417

1518
import { DEFAULT_SRP } from './constants';
1619
import {
@@ -26,6 +29,7 @@ import {
2629
getRestrictedSnapInterfaceControllerMessenger,
2730
getRootControllerMessenger,
2831
} from './test-utils';
32+
import { addSnapMetadataToAccount } from './utils/account';
2933

3034
describe('installSnap', () => {
3135
it('installs a Snap and returns the execution service', async () => {
@@ -693,15 +697,15 @@ describe('registerActions', () => {
693697
const controllerMessenger = getRootControllerMessenger(false);
694698

695699
it('registers `PhishingController:testOrigin`', async () => {
696-
registerActions(controllerMessenger, runSaga, options);
700+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
697701

698702
expect(
699703
controllerMessenger.call('PhishingController:testOrigin', 'foo'),
700704
).toStrictEqual({ result: false, type: 'all' });
701705
});
702706

703707
it('registers `ApprovalController:hasRequest`', async () => {
704-
registerActions(controllerMessenger, runSaga, options);
708+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
705709

706710
store.dispatch(
707711
setInterface({ type: DIALOG_APPROVAL_TYPES.default, id: 'foo' }),
@@ -713,7 +717,7 @@ describe('registerActions', () => {
713717
});
714718

715719
it('registers `ApprovalController:acceptRequest`', async () => {
716-
registerActions(controllerMessenger, runSaga, options);
720+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
717721

718722
store.dispatch(
719723
setInterface({ type: DIALOG_APPROVAL_TYPES.default, id: 'foo' }),
@@ -729,36 +733,59 @@ describe('registerActions', () => {
729733
});
730734

731735
it('registers `AccountsController:getAccountByAddress`', async () => {
732-
registerActions(controllerMessenger, runSaga, options);
736+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
733737

734738
expect(
735739
controllerMessenger.call(
736740
'AccountsController:getAccountByAddress',
737741
mockedAccounts[0].address,
738742
),
739-
).toStrictEqual(mockedAccounts[0]);
743+
).toStrictEqual(addSnapMetadataToAccount(mockedAccounts[0], MOCK_SNAP_ID));
744+
745+
expect(
746+
controllerMessenger.call('AccountsController:getAccountByAddress', 'foo'),
747+
).toBeUndefined();
740748
});
741749

742750
it('registers `AccountsController:getSelectedMultichainAccount`', async () => {
743-
registerActions(controllerMessenger, runSaga, options);
751+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
744752

745753
expect(
746754
controllerMessenger.call(
747755
'AccountsController:getSelectedMultichainAccount',
748756
),
749-
).toStrictEqual(mockedAccounts[0]);
757+
).toStrictEqual(addSnapMetadataToAccount(mockedAccounts[0], MOCK_SNAP_ID));
758+
});
759+
760+
it('returns `undefined` in `AccountsController:getSelectedMultichainAccount` if no account is selected', async () => {
761+
registerActions(
762+
controllerMessenger,
763+
runSaga,
764+
{ ...options, accounts: [] },
765+
MOCK_SNAP_ID,
766+
);
767+
768+
expect(
769+
controllerMessenger.call(
770+
'AccountsController:getSelectedMultichainAccount',
771+
),
772+
).toBeUndefined();
750773
});
751774

752775
it('registers `AccountsController:listMultichainAccounts`', async () => {
753-
registerActions(controllerMessenger, runSaga, options);
776+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
754777

755778
expect(
756779
controllerMessenger.call('AccountsController:listMultichainAccounts'),
757-
).toStrictEqual(mockedAccounts);
780+
).toStrictEqual(
781+
mockedAccounts.map((account) =>
782+
addSnapMetadataToAccount(account, MOCK_SNAP_ID),
783+
),
784+
);
758785
});
759786

760787
it('registers `MultichainAssetsController:getState`', async () => {
761-
registerActions(controllerMessenger, runSaga, options);
788+
registerActions(controllerMessenger, runSaga, options, MOCK_SNAP_ID);
762789

763790
expect(
764791
controllerMessenger.call('MultichainAssetsController:getState'),

packages/snaps-simulation/src/simulation.ts

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import type { SimulationOptions, SimulationUserOptions } from './options';
5050
import { getOptions } from './options';
5151
import type { Interface, RunSagaFunction, Store } from './store';
5252
import { createStore, getCurrentInterface } from './store';
53+
import { addSnapMetadataToAccount } from './utils/account';
5354

5455
/**
5556
* Options for the execution service, without the options that are shared
@@ -303,7 +304,7 @@ export async function installSnap<
303304

304305
const controllerMessenger = new Messenger<any, any>();
305306

306-
registerActions(controllerMessenger, runSaga, options);
307+
registerActions(controllerMessenger, runSaga, options, snapId);
307308

308309
// Set up controllers and JSON-RPC stack.
309310
const restrictedHooks = getRestrictedHooks(options);
@@ -474,11 +475,13 @@ export function getPermittedHooks(
474475
* @param controllerMessenger - The controller messenger.
475476
* @param runSaga - The run saga function.
476477
* @param options - The simulation options.
478+
* @param snapId - The ID of the Snap.
477479
*/
478480
export function registerActions(
479481
controllerMessenger: RootControllerMessenger,
480482
runSaga: RunSagaFunction,
481483
options: SimulationOptions,
484+
snapId: SnapId,
482485
) {
483486
controllerMessenger.registerActionHandler(
484487
'PhishingController:testOrigin',
@@ -487,24 +490,47 @@ export function registerActions(
487490

488491
controllerMessenger.registerActionHandler(
489492
'AccountsController:getAccountByAddress',
490-
(address) =>
491-
// @ts-expect-error - This is a partial account with only the necessary
492-
// data used by the interface controller.
493-
options.accounts.find((account) => address === account.address),
493+
// @ts-expect-error - This is a partial account with only the necessary
494+
// data used by the interface controller.
495+
(address) => {
496+
const matchingAccount = options.accounts.find(
497+
(account) => address === account.address,
498+
);
499+
500+
if (!matchingAccount) {
501+
return undefined;
502+
}
503+
504+
return addSnapMetadataToAccount(matchingAccount, snapId);
505+
},
494506
);
495507

496508
controllerMessenger.registerActionHandler(
497509
'AccountsController:getSelectedMultichainAccount',
498510
// @ts-expect-error - This is a partial account with only the necessary
499511
// data used by the interface controller.
500-
() => options.accounts.find((account) => account.selected),
512+
() => {
513+
const selectedAccount = options.accounts.find(
514+
(account) => account.selected,
515+
);
516+
517+
if (!selectedAccount) {
518+
return undefined;
519+
}
520+
521+
return addSnapMetadataToAccount(selectedAccount, snapId);
522+
},
501523
);
502524

503525
controllerMessenger.registerActionHandler(
504526
'AccountsController:listMultichainAccounts',
505-
// @ts-expect-error - These are partial accounts with only the necessary
506-
// data used by the interface controller.
507-
() => options.accounts,
527+
528+
() =>
529+
// @ts-expect-error - These are partial accounts with only the necessary
530+
// data used by the interface controller.
531+
options.accounts.map((account) =>
532+
addSnapMetadataToAccount(account, snapId),
533+
),
508534
);
509535

510536
controllerMessenger.registerActionHandler(
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { MOCK_SNAP_ID } from '@metamask/snaps-utils/test-utils';
2+
import type { SimulationAccount } from 'src/options';
3+
4+
import { addSnapMetadataToAccount } from './account';
5+
6+
describe('addSnapMetadataToAccount', () => {
7+
it('adds snap metadata to an owned account', () => {
8+
const account: SimulationAccount = {
9+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
10+
selected: true,
11+
address: '7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv',
12+
owned: true,
13+
scopes: ['solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'],
14+
assets: [
15+
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:105',
16+
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
17+
],
18+
};
19+
20+
const result = addSnapMetadataToAccount(account, MOCK_SNAP_ID);
21+
22+
expect(result).toStrictEqual({
23+
...account,
24+
metadata: {
25+
snap: {
26+
id: MOCK_SNAP_ID,
27+
},
28+
},
29+
});
30+
});
31+
32+
it('returns an account without snap metadata if not owned', () => {
33+
const account: SimulationAccount = {
34+
id: 'f47ac10b-58cc-4372-a567-0e02b2c3d479',
35+
selected: true,
36+
address: '7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv',
37+
owned: false,
38+
scopes: ['solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'],
39+
assets: [
40+
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/slip44:105',
41+
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/token:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
42+
],
43+
};
44+
45+
const result = addSnapMetadataToAccount(account, MOCK_SNAP_ID);
46+
47+
expect(result).toStrictEqual({
48+
...account,
49+
metadata: {},
50+
});
51+
});
52+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { SnapId } from '@metamask/snaps-sdk';
2+
import type { SimulationAccount } from 'src/options';
3+
4+
export const addSnapMetadataToAccount = (
5+
account: SimulationAccount,
6+
snapId: SnapId,
7+
) => {
8+
if (!account.owned) {
9+
return {
10+
...account,
11+
metadata: {},
12+
};
13+
}
14+
15+
return {
16+
...account,
17+
metadata: {
18+
snap: {
19+
id: snapId,
20+
},
21+
},
22+
};
23+
};

0 commit comments

Comments
 (0)