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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ linkStyle default opacity:0.5
eth_snap_keyring --> keyring_api;
eth_snap_keyring --> keyring_internal_api;
eth_snap_keyring --> keyring_internal_snap_client;
eth_snap_keyring --> keyring_utils;
keyring_snap_client --> keyring_api;
keyring_snap_client --> keyring_utils;
keyring_snap_sdk --> keyring_utils;
Expand Down
24 changes: 23 additions & 1 deletion packages/keyring-api/src/api/account.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { assert } from '@metamask/superstruct';

import { KeyringAccountStruct } from './account';
import { EthAccountType, KeyringAccountStruct } from './account';

const supportedKeyringAccountTypes = Object.keys(
KeyringAccountStruct.schema.type.schema,
Expand All @@ -12,6 +12,7 @@ describe('api', () => {
const baseAccount = {
id: '606a7759-b0fb-48e4-9874-bab62ff8e7eb',
address: '0x000',
scopes: [],
options: {},
methods: [],
};
Expand All @@ -33,5 +34,26 @@ describe('api', () => {
);
},
);

it.each([
// Namespace too short (< 3):
'',
'a',
'ei',
'bi',
'bi:p122something',
// Namespace too long (> 8):
'eip11155111',
'eip11155111:11155111',
])('throws an error if account scopes is: %s', (scope: string) => {
const account = {
...baseAccount,
type: EthAccountType.Eoa,
scopes: [scope],
};
expect(() => assert(account, KeyringAccountStruct)).toThrow(
`At path: scopes.0 -- Expected the value to satisfy a union of \`string | string\`, but received: "${scope}"`,
);
});
});
});
20 changes: 18 additions & 2 deletions packages/keyring-api/src/api/account.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import { object, UuidStruct } from '@metamask/keyring-utils';
import type { Infer } from '@metamask/superstruct';
import { array, enums, record, string } from '@metamask/superstruct';
import { JsonStruct } from '@metamask/utils';
import {
nonempty,
array,
enums,
record,
string,
union,
} from '@metamask/superstruct';
import {
CaipChainIdStruct,
CaipNamespaceStruct,
JsonStruct,
} from '@metamask/utils';

/**
* Supported Ethereum account types.
Expand Down Expand Up @@ -62,6 +73,11 @@ export const KeyringAccountStruct = object({
*/
address: string(),

/**
* Account supported scopes (CAIP-2 chain IDs).
*/
scopes: nonempty(array(union([CaipNamespaceStruct, CaipChainIdStruct]))),

/**
* Account options.
*/
Expand Down
13 changes: 13 additions & 0 deletions packages/keyring-api/src/btc/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* istanbul ignore file */

/**
* Scopes for Bitcoin account type. See {@link KeyringAccount.scopes}.
*/
export enum BtcScopes {
Namespace = 'bip122',
Mainnet = 'bip122:000000000019d6689c085ae165831e93',
Testnet = 'bip122:000000000933ea01ad0ee984209779ba',
Testnet4 = 'bip122:00000000da84f2bafbbc53dee25a72ae',
Signet = 'bip122:00000008819873e925422c1ff0f99f7c',
Regtest = 'bip122:regtest',
}
1 change: 1 addition & 0 deletions packages/keyring-api/src/btc/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './constants';
export * from './types';
9 changes: 9 additions & 0 deletions packages/keyring-api/src/eth/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* istanbul ignore file */

/**
* Scopes for EVM account type. See {@link KeyringAccount.scopes}.
*/
export enum EthScopes {
Namespace = 'eip155',
Mainnet = 'eip155:1',
}
1 change: 1 addition & 0 deletions packages/keyring-api/src/eth/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './constants';
export * from './erc4337';
export * from './types';
export * from './utils';
8 changes: 7 additions & 1 deletion packages/keyring-api/src/eth/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { object, definePattern } from '@metamask/keyring-utils';
import type { Infer } from '@metamask/superstruct';
import { array, enums, literal } from '@metamask/superstruct';
import { nonempty, array, enums, literal } from '@metamask/superstruct';

import { EthScopes } from '.';
import { EthAccountType, KeyringAccountStruct } from '../api';

export const EthBytesStruct = definePattern('EthBytes', /^0x[0-9a-f]*$/iu);
Expand Down Expand Up @@ -46,6 +47,11 @@ export const EthEoaAccountStruct = object({
*/
type: literal(`${EthAccountType.Eoa}`),

/**
* Account scopes (must be ['eip155']).
*/
scopes: nonempty(array(literal(EthScopes.Namespace))),

/**
* Account supported methods.
*/
Expand Down
6 changes: 6 additions & 0 deletions packages/keyring-api/src/events.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { is } from '@metamask/superstruct';

import { EthAccountType } from './api';
import { EthScopes } from './eth/constants';
import {
AccountCreatedEventStruct,
AccountDeletedEventStruct,
Expand All @@ -21,6 +22,7 @@ describe('events', () => {
address: '0x0123',
methods: [],
options: {},
scopes: [EthScopes.Namespace],
type: EthAccountType.Eoa,
},
},
Expand All @@ -38,6 +40,7 @@ describe('events', () => {
address: '0x0123',
methods: [],
options: {},
scopes: [EthScopes.Namespace],
type: EthAccountType.Eoa,
},
},
Expand All @@ -55,6 +58,7 @@ describe('events', () => {
address: '0x0123',
methods: [],
options: {},
scopes: [EthScopes.Namespace],
type: EthAccountType.Eoa,
},
displayConfirmation: true,
Expand All @@ -75,6 +79,7 @@ describe('events', () => {
address: '0x0123',
methods: [],
options: {},
scopes: [EthScopes.Namespace],
type: EthAccountType.Eoa,
},
},
Expand All @@ -92,6 +97,7 @@ describe('events', () => {
address: '0x0123',
methods: [],
options: {},
scopes: [EthScopes.Namespace],
type: EthAccountType.Eoa,
},
},
Expand Down
11 changes: 11 additions & 0 deletions packages/keyring-api/src/sol/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* istanbul ignore file */

/**
* Scopes for Solana account type. See {@link KeyringAccount.scopes}.
*/
export enum SolScopes {
Namespace = 'solana',
Devnet = 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
Mainnet = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp',
Testnet = 'solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z',
}
1 change: 1 addition & 0 deletions packages/keyring-api/src/sol/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './constants';
export * from './types';
36 changes: 30 additions & 6 deletions packages/keyring-internal-api/src/types.test.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
import { assert } from '@metamask/superstruct';

import type { InternalAccount } from '.';
import { InternalAccountStruct } from '.';

describe('InternalAccount', () => {
it.each([
{ type: 'eip155:eoa', address: '0x000' },
{ type: 'eip155:eoa', address: '0x000', scopes: ['eip155'] },
{
type: 'bip122:p2wpkh',
address: 'bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4',
scopes: ['bip122:000000000019d6689c085ae165831e93'],
},
])('should have the correct structure: %s', ({ type, address }) => {
])('should have the correct structure: %s', ({ type, address, scopes }) => {
const account = {
id: '606a7759-b0fb-48e4-9874-bab62ff8e7eb',
address,
options: {},
methods: [],
scopes,
type,
metadata: {
keyring: {
Expand All @@ -34,6 +37,7 @@ describe('InternalAccount', () => {
address: '0x000',
options: {},
methods: [],
scopes: ['eip155'],
type: 'eip155:eoa',
metadata: {
keyring: {},
Expand All @@ -53,6 +57,7 @@ describe('InternalAccount', () => {
address: '0x000',
options: {},
methods: [],
scopes: ['eip155'],
type: 'eip155:eoa',
metadata: {
name: 'Account 1',
Expand All @@ -71,6 +76,7 @@ describe('InternalAccount', () => {
address: '0x000',
options: {},
methods: [],
scopes: ['eip155'],
type: 'eip155:eoa',
};

Expand All @@ -79,12 +85,27 @@ describe('InternalAccount', () => {
);
});

it('should throw if scopes is not set', () => {
const account = {
id: '606a7759-b0fb-48e4-9874-bab62ff8e7eb',
address: '0x000',
options: {},
methods: [],
type: 'eip155:eoa',
};

expect(() => assert(account, InternalAccountStruct)).toThrow(
'At path: scopes -- Expected an array value, but received: undefined',
);
});

it('should throw if there are extra fields', () => {
const account = {
id: '606a7759-b0fb-48e4-9874-bab62ff8e7eb',
address: '0x000',
options: {},
methods: [],
scopes: ['eip155'],
type: 'eip155:eoa',
metadata: {
keyring: {
Expand All @@ -102,12 +123,13 @@ describe('InternalAccount', () => {
});

it('should contain snap name, id and enabled if the snap metadata exists', () => {
const account = {
const account: InternalAccount = {
id: '606a7759-b0fb-48e4-9874-bab62ff8e7eb',
address: '0x000',
options: {},
methods: [],
type: 'eip155:eoa',
scopes: ['eip155'],
metadata: {
keyring: {
type: 'Test Keyring',
Expand All @@ -126,13 +148,14 @@ describe('InternalAccount', () => {
});

it.each([['name', 'enabled', 'id']])(
'should throw if snap.%i is not set',
'should throw if snap.%s is not set',
(key: string) => {
const account = {
const account: InternalAccount = {
id: '606a7759-b0fb-48e4-9874-bab62ff8e7eb',
address: '0x000',
options: {},
methods: [],
scopes: ['eip155'],
type: 'eip155:eoa',
metadata: {
keyring: {
Expand All @@ -148,7 +171,8 @@ describe('InternalAccount', () => {
},
};

delete account.metadata.snap[key as keyof typeof account.metadata.snap];
// On `InternalAccount` the `metadata.snap` is optional, hence the `?.` here.
delete account.metadata.snap?.[key as keyof typeof account.metadata.snap];

const regex = new RegExp(`At path: metadata.snap.${key}`, 'u');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('KeyringSnapControllerClient', () => {
address: '0xE9A74AACd7df8112911ca93260fC5a046f8a64Ae',
options: {},
methods: [],
scopes: ['eip155'],
type: 'eip155:eoa',
},
];
Expand Down
1 change: 1 addition & 0 deletions packages/keyring-snap-bridge/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@metamask/keyring-api": "workspace:^",
"@metamask/keyring-internal-api": "workspace:^",
"@metamask/keyring-internal-snap-client": "workspace:^",
"@metamask/keyring-utils": "workspace:^",
"@metamask/snaps-controllers": "^9.10.0",
"@metamask/snaps-sdk": "^6.7.0",
"@metamask/snaps-utils": "^8.3.0",
Expand Down
Loading