@@ -10,6 +10,7 @@ import {
1010} from '@metamask/snaps-sdk' ;
1111import {
1212 AssetSelector ,
13+ AccountSelector ,
1314 Box ,
1415 Field ,
1516 FileInput ,
@@ -27,6 +28,7 @@ import { MOCK_SNAP_ID } from '@metamask/snaps-utils/test-utils';
2728
2829import { SnapInterfaceController } from './SnapInterfaceController' ;
2930import {
31+ MOCK_ACCOUNT_ID ,
3032 MockApprovalController ,
3133 getRestrictedSnapInterfaceControllerMessenger ,
3234 getRootSnapInterfaceControllerMessenger ,
@@ -243,7 +245,213 @@ describe('SnapInterfaceController', () => {
243245 ) ;
244246
245247 expect ( content ) . toStrictEqual ( element ) ;
246- expect ( state ) . toStrictEqual ( { foo : { bar : null } } ) ;
248+ expect ( state ) . toStrictEqual ( {
249+ foo : {
250+ bar : null ,
251+ } ,
252+ } ) ;
253+ } ) ;
254+
255+ it ( 'can retrieve the selected account from the client' , async ( ) => {
256+ const rootMessenger = getRootSnapInterfaceControllerMessenger ( ) ;
257+ const controllerMessenger =
258+ getRestrictedSnapInterfaceControllerMessenger ( rootMessenger ) ;
259+
260+ // eslint-disable-next-line no-new
261+ new SnapInterfaceController ( {
262+ messenger : controllerMessenger ,
263+ } ) ;
264+
265+ const element = (
266+ < Box >
267+ < AccountSelector name = "foo" />
268+ </ Box >
269+ ) ;
270+
271+ const id = await rootMessenger . call (
272+ 'SnapInterfaceController:createInterface' ,
273+ MOCK_SNAP_ID ,
274+ element ,
275+ ) ;
276+
277+ const { content, state } = rootMessenger . call (
278+ 'SnapInterfaceController:getInterface' ,
279+ MOCK_SNAP_ID ,
280+ id ,
281+ ) ;
282+
283+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
284+ 2 ,
285+ 'AccountsController:getSelectedMultichainAccount' ,
286+ ) ;
287+
288+ expect ( content ) . toStrictEqual ( element ) ;
289+ expect ( state ) . toStrictEqual ( {
290+ foo : {
291+ accountId : MOCK_ACCOUNT_ID ,
292+ addresses : [ 'eip155:0:0x1234567890123456789012345678901234567890' ] ,
293+ } ,
294+ } ) ;
295+ } ) ;
296+
297+ it ( 'can select an account owned by the snap' , async ( ) => {
298+ const rootMessenger = getRootSnapInterfaceControllerMessenger ( ) ;
299+ const controllerMessenger = getRestrictedSnapInterfaceControllerMessenger (
300+ rootMessenger ,
301+ false ,
302+ ) ;
303+
304+ rootMessenger . registerActionHandler (
305+ 'AccountsController:getSelectedMultichainAccount' ,
306+ ( ) => ( {
307+ id : MOCK_ACCOUNT_ID ,
308+ address : '0x1234567890123456789012345678901234567890' ,
309+ scopes : [ 'eip155:0' ] ,
310+ metadata : {
311+ // @ts -expect-error partial mock
312+ snap : {
313+ id :
'npm:[email protected] ' as SnapId , 314+ } ,
315+ } ,
316+ } ) ,
317+ ) ;
318+
319+ rootMessenger . registerActionHandler (
320+ 'AccountsController:listMultichainAccounts' ,
321+ ( ) => [
322+ {
323+ id : MOCK_ACCOUNT_ID ,
324+ address : '7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv' ,
325+ scopes : [ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' ] ,
326+ metadata : {
327+ // @ts -expect-error partial mock
328+ snap : {
329+ id : MOCK_SNAP_ID ,
330+ } ,
331+ } ,
332+ } ,
333+ ] ,
334+ ) ;
335+
336+ // eslint-disable-next-line no-new
337+ new SnapInterfaceController ( {
338+ messenger : controllerMessenger ,
339+ } ) ;
340+
341+ const element = (
342+ < Box >
343+ < AccountSelector name = "foo" hideExternalAccounts />
344+ </ Box >
345+ ) ;
346+
347+ const id = await rootMessenger . call (
348+ 'SnapInterfaceController:createInterface' ,
349+ MOCK_SNAP_ID ,
350+ element ,
351+ ) ;
352+
353+ const { content, state } = rootMessenger . call (
354+ 'SnapInterfaceController:getInterface' ,
355+ MOCK_SNAP_ID ,
356+ id ,
357+ ) ;
358+
359+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
360+ 2 ,
361+ 'AccountsController:getSelectedMultichainAccount' ,
362+ ) ;
363+
364+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
365+ 3 ,
366+ 'AccountsController:listMultichainAccounts' ,
367+ ) ;
368+
369+ expect ( content ) . toStrictEqual ( element ) ;
370+ expect ( state ) . toStrictEqual ( {
371+ foo : {
372+ accountId : MOCK_ACCOUNT_ID ,
373+ addresses : [
374+ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv' ,
375+ ] ,
376+ } ,
377+ } ) ;
378+ } ) ;
379+
380+ it ( 'can get accounts of a specific chain ID from the client' , async ( ) => {
381+ const rootMessenger = getRootSnapInterfaceControllerMessenger ( ) ;
382+ const controllerMessenger = getRestrictedSnapInterfaceControllerMessenger (
383+ rootMessenger ,
384+ false ,
385+ ) ;
386+
387+ rootMessenger . registerActionHandler (
388+ 'AccountsController:getSelectedMultichainAccount' ,
389+ // @ts -expect-error partial mock
390+ ( ) => ( {
391+ id : MOCK_ACCOUNT_ID ,
392+ address : '0x1234567890123456789012345678901234567890' ,
393+ scopes : [ 'eip155:0' ] ,
394+ } ) ,
395+ ) ;
396+
397+ rootMessenger . registerActionHandler (
398+ 'AccountsController:listMultichainAccounts' ,
399+ ( ) => [
400+ // @ts -expect-error partial mock
401+ {
402+ id : MOCK_ACCOUNT_ID ,
403+ address : '7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv' ,
404+ scopes : [ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' ] ,
405+ } ,
406+ ] ,
407+ ) ;
408+
409+ // eslint-disable-next-line no-new
410+ new SnapInterfaceController ( {
411+ messenger : controllerMessenger ,
412+ } ) ;
413+
414+ const element = (
415+ < Box >
416+ < AccountSelector
417+ name = "foo"
418+ switchGlobalAccount
419+ chainIds = { [ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' ] }
420+ />
421+ </ Box >
422+ ) ;
423+
424+ const id = await rootMessenger . call (
425+ 'SnapInterfaceController:createInterface' ,
426+ MOCK_SNAP_ID ,
427+ element ,
428+ ) ;
429+
430+ const { content, state } = rootMessenger . call (
431+ 'SnapInterfaceController:getInterface' ,
432+ MOCK_SNAP_ID ,
433+ id ,
434+ ) ;
435+
436+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
437+ 2 ,
438+ 'AccountsController:getSelectedMultichainAccount' ,
439+ ) ;
440+
441+ expect ( rootMessenger . call ) . toHaveBeenNthCalledWith (
442+ 3 ,
443+ 'AccountsController:listMultichainAccounts' ,
444+ ) ;
445+
446+ expect ( content ) . toStrictEqual ( element ) ;
447+ expect ( state ) . toStrictEqual ( {
448+ foo : {
449+ accountId : MOCK_ACCOUNT_ID ,
450+ addresses : [
451+ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv' ,
452+ ] ,
453+ } ,
454+ } ) ;
247455 } ) ;
248456
249457 it ( 'supports providing interface context' , async ( ) => {
@@ -1164,6 +1372,94 @@ describe('SnapInterfaceController', () => {
11641372 ) ,
11651373 ) . rejects . toThrow ( 'Interface not created by foo.' ) ;
11661374 } ) ;
1375+
1376+ it ( 'can select an account owned by the snap' , async ( ) => {
1377+ const rootMessenger = getRootSnapInterfaceControllerMessenger ( ) ;
1378+ const controllerMessenger = getRestrictedSnapInterfaceControllerMessenger (
1379+ rootMessenger ,
1380+ false ,
1381+ ) ;
1382+
1383+ rootMessenger . registerActionHandler (
1384+ 'AccountsController:getSelectedMultichainAccount' ,
1385+ ( ) => ( {
1386+ id : MOCK_ACCOUNT_ID ,
1387+ address : '0x1234567890123456789012345678901234567890' ,
1388+ scopes : [ 'eip155:0' ] ,
1389+ metadata : {
1390+ // @ts -expect-error partial mock
1391+ snap : {
1392+ id :
'npm:[email protected] ' as SnapId , 1393+ } ,
1394+ } ,
1395+ } ) ,
1396+ ) ;
1397+
1398+ rootMessenger . registerActionHandler (
1399+ 'AccountsController:getAccountByAddress' ,
1400+ ( ) => ( {
1401+ id : MOCK_ACCOUNT_ID ,
1402+ address : '7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv' ,
1403+ scopes : [ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp' ] ,
1404+ metadata : {
1405+ // @ts -expect-error partial mock
1406+ snap : {
1407+ id : MOCK_SNAP_ID ,
1408+ } ,
1409+ } ,
1410+ } ) ,
1411+ ) ;
1412+
1413+ // eslint-disable-next-line no-new
1414+ new SnapInterfaceController ( {
1415+ messenger : controllerMessenger ,
1416+ } ) ;
1417+
1418+ const element = (
1419+ < Box >
1420+ < AccountSelector name = "foo" />
1421+ </ Box >
1422+ ) ;
1423+
1424+ const newElement = (
1425+ < Box >
1426+ < AccountSelector
1427+ name = "foo"
1428+ hideExternalAccounts
1429+ value = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv"
1430+ />
1431+ </ Box >
1432+ ) ;
1433+
1434+ const id = await rootMessenger . call (
1435+ 'SnapInterfaceController:createInterface' ,
1436+ MOCK_SNAP_ID ,
1437+ element ,
1438+ ) ;
1439+
1440+ await rootMessenger . call (
1441+ 'SnapInterfaceController:updateInterface' ,
1442+ MOCK_SNAP_ID ,
1443+ id ,
1444+ newElement ,
1445+ ) ;
1446+
1447+ const { content, state } = rootMessenger . call (
1448+ 'SnapInterfaceController:getInterface' ,
1449+ MOCK_SNAP_ID ,
1450+ id ,
1451+ ) ;
1452+
1453+ expect ( content ) . toStrictEqual ( newElement ) ;
1454+ expect ( state ) . toStrictEqual ( {
1455+ foo : {
1456+ accountId : MOCK_ACCOUNT_ID ,
1457+ addresses : [
1458+ 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv' ,
1459+ ] ,
1460+ } ,
1461+ } ) ;
1462+ } ) ;
11671463 } ) ;
11681464
11691465 describe ( 'updateInterfaceState' , ( ) => {
0 commit comments