Skip to content

Commit

Permalink
refactor: split keyring-api (#24)
Browse files Browse the repository at this point in the history
## Description

Split of the `keyring-api` into smaller packages.

Fixes: MetaMask/accounts-planning#729

---------

Co-authored-by: Daniel Rocha <[email protected]>
  • Loading branch information
ccharly and danroc authored Dec 6, 2024
1 parent c99dfd5 commit 0488168
Show file tree
Hide file tree
Showing 118 changed files with 1,850 additions and 325 deletions.
48 changes: 48 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ module.exports = {
'@typescript-eslint/naming-convention': 'warn',
},
},
// @metamask/keyring-utils
{
files: ['packages/keyring-utils/src/**/*.ts'],
extends: ['@metamask/eslint-config-typescript'],
parserOptions,
rules: {
// TODO: re-lint everything once the migration is done
'@typescript-eslint/no-explicit-any': 'off',
},
},
// @metamask/keyring-api
{
files: ['packages/keyring-api/src/**/*.ts'],
Expand All @@ -77,6 +87,18 @@ module.exports = {
'jsdoc/newline-after-description': 'off',
},
},
// @metamask/keyring-internal-api
{
files: ['packages/keyring-internal-api/src/**/*.ts'],
extends: ['@metamask/eslint-config-typescript'],
parserOptions,
rules: {
// FIXME: for some reason, it seems eslint is not able to infere those (this
// works on the original repository, so there might be some side-effects now that
// we are building in a monorepo)
'@typescript-eslint/restrict-template-expressions': 'off',
},
},
// @metamask/keyring-eth-hd
{
files: ['packages/keyring-eth-hd/**/*.js'],
Expand Down Expand Up @@ -169,6 +191,32 @@ module.exports = {
'@typescript-eslint/restrict-template-expressions': 'off',
},
},
// @metamask/keyring-snap-sdk
{
files: ['packages/keyring-snap-sdk/src/**/*.test.ts'],
extends: ['@metamask/eslint-config-typescript'],
parserOptions,
rules: {
// FIXME: for some reason, it seems eslint is not able to infere those (this
// works on the original repository, so there might be some side-effects now that
// we are building in a monorepo)
'@typescript-eslint/restrict-template-expressions': 'off',
},
},
// @metamask/keyring-snap-client
{
files: ['packages/keyring-snap-client/src/**/*.ts'],
extends: ['@metamask/eslint-config-typescript'],
parserOptions,
rules: {
// TODO: re-lint everything once the migration is done
'@typescript-eslint/no-explicit-any': 'off',
// FIXME: for some reason, it seems eslint is not able to infere those (this
// works on the original repository, so there might be some side-effects now that
// we are building in a monorepo)
'@typescript-eslint/restrict-template-expressions': 'off',
},
},
],
rules: {
'jsdoc/match-description': [
Expand Down
32 changes: 31 additions & 1 deletion .syncpackrc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,36 @@
"dependencyTypes": ["!local"],
"dependencies": ["@metamask/keyring-api"],
"pinVersion": "workspace:^"
}
},
{
"label": "use workspace version of the keyring-internal-api",
"dependencyTypes": ["!local"],
"dependencies": ["@metamask/keyring-internal-api"],
"pinVersion": "workspace:^"
},
{
"label": "use workspace version of the keyring-snap-sdk",
"dependencyTypes": ["!local"],
"dependencies": ["@metamask/keyring-snap-sdk"],
"pinVersion": "workspace:^"
},
{
"label": "use workspace version of the keyring-snap-client",
"dependencyTypes": ["!local"],
"dependencies": ["@metamask/keyring-snap-client"],
"pinVersion": "workspace:^"
},
{
"label": "use workspace version of the keyring-snap-internal-client",
"dependencyTypes": ["!local"],
"dependencies": ["@metamask/keyring-snap-internal-client"],
"pinVersion": "workspace:^"
},
{
"label": "use workspace version of the keyring-utils",
"dependencyTypes": ["!local"],
"dependencies": ["@metamask/keyring-utils"],
"pinVersion": "workspace:^"
},
]
}
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ This repository contains the following packages [^fn1]:
- [`@metamask/eth-hd-keyring`](packages/keyring-eth-hd)
- [`@metamask/eth-ledger-bridge-keyring`](packages/keyring-eth-ledger-bridge)
- [`@metamask/eth-simple-keyring`](packages/keyring-eth-simple)
- [`@metamask/eth-snap-keyring`](packages/keyring-snap)
- [`@metamask/eth-snap-keyring`](packages/keyring-snap-bridge)
- [`@metamask/eth-trezor-keyring`](packages/keyring-eth-trezor)
- [`@metamask/keyring-api`](packages/keyring-api)
- [`@metamask/keyring-internal-api`](packages/keyring-internal-api)
- [`@metamask/keyring-snap-client`](packages/keyring-snap-client)
- [`@metamask/keyring-snap-internal-client`](packages/keyring-snap-internal-client)
- [`@metamask/keyring-snap-sdk`](packages/keyring-snap-sdk)
- [`@metamask/keyring-utils`](packages/keyring-utils)

<!-- end package list -->

Expand All @@ -34,8 +39,25 @@ linkStyle default opacity:0.5
eth_ledger_bridge_keyring(["@metamask/eth-ledger-bridge-keyring"]);
eth_simple_keyring(["@metamask/eth-simple-keyring"]);
eth_trezor_keyring(["@metamask/eth-trezor-keyring"]);
keyring_internal_api(["@metamask/keyring-internal-api"]);
eth_snap_keyring(["@metamask/eth-snap-keyring"]);
keyring_snap_client(["@metamask/keyring-snap-client"]);
keyring_snap_internal_client(["@metamask/keyring-snap-internal-client"]);
keyring_snap_sdk(["@metamask/keyring-snap-sdk"]);
keyring_utils(["@metamask/keyring-utils"]);
keyring_api --> keyring_utils;
keyring_internal_api --> keyring_api;
keyring_internal_api --> keyring_utils;
eth_snap_keyring --> keyring_api;
eth_snap_keyring --> keyring_internal_api;
eth_snap_keyring --> keyring_snap_internal_client;
keyring_snap_client --> keyring_api;
keyring_snap_client --> keyring_utils;
keyring_snap_internal_client --> keyring_api;
keyring_snap_internal_client --> keyring_snap_client;
keyring_snap_internal_client --> keyring_utils;
keyring_snap_sdk --> keyring_utils;
keyring_snap_sdk --> keyring_api;
```

<!-- end dependency graph -->
Expand Down
16 changes: 7 additions & 9 deletions jest.config.packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ module.exports = {
collectCoverage: true,

// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: ['./src/**/*.ts', '!./src/**/*.test-d.ts'],
collectCoverageFrom: [
'./src/**/*.ts',
// Ignore typing test files
'!./src/**/*.test-d.ts',
// Ignore index of subdirectories
'!./src/**/*/index.ts',
],

// The directory where Jest should output its coverage files
coverageDirectory: 'coverage',
Expand Down Expand Up @@ -80,14 +86,6 @@ module.exports = {
// Here we ensure that Jest resolves `@metamask/*` imports to the uncompiled source code for packages that live in this repo.
// NOTE: This must be synchronized with the `paths` option in `tsconfig.packages.json`.
moduleNameMapper: {
// FIXME: For now we do require to build some packages (keyring-api) that is then used
// in the keyring-snap package. This might be fixed after splitting the keyring-api into
// smaller internal packages!
// TODO: Remove this after the split of the keyring-api
// {
'^@metamask/keyring-api/dist/(.*)$': ['<rootDir>/../keyring-api/dist/$1'],
// }
'^jest-environment-jsdom$': ['<rootDir>/../keyring-api/dist/$1'],
'^@metamask/(.+)$': [
'<rootDir>/../$1/src',
// Some @metamask/* packages we are referencing aren't in this monorepo,
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
"lint:eslint": "eslint . --cache --ext js,cjs,mjs,ts",
"lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write && yarn constraints --fix && yarn lint:dependencies:fix",
"lint:misc": "prettier '**/*.json' '**/*.md' '!**/CHANGELOG.old.md' '**/*.yml' '!.yarnrc.yml' '!merged-packages/**' --ignore-path .gitignore",
"prepare:preview": "ts-node scripts/prepare-preview-builds.ts",
"prepare:preview": "ts-node --project tsconfig.scripts.json scripts/prepare-preview-builds.ts",
"prepare:preview:local": "yarn prepare:preview @metamask-previews $(git rev-parse --short HEAD)",
"publish:preview": "yarn workspaces foreach --all --no-private --parallel --verbose run publish:preview",
"readme:update": "ts-node scripts/update-readme-content.ts",
"readme:update": "ts-node --project tsconfig.scripts.json scripts/update-readme-content.ts",
"release": "./scripts/release.sh",
"setup": "yarn install",
"test": "yarn workspaces foreach --all --parallel --verbose run test",
Expand Down
19 changes: 8 additions & 11 deletions packages/keyring-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,20 @@
"test": "yarn test:source && yarn test:types",
"test:clean": "jest --clearCache",
"test:source": "jest && jest-it-up",
"test:types": "tsd",
"test:types": "../../scripts/tsd-test.sh ./src",
"test:watch": "jest --watch"
},
"dependencies": {
"@metamask/snaps-sdk": "^6.7.0",
"@metamask/keyring-utils": "workspace:^",
"@metamask/superstruct": "^3.1.0",
"@metamask/utils": "^9.3.0",
"@types/uuid": "^9.0.8",
"bech32": "^2.0.0",
"uuid": "^9.0.1",
"webextension-polyfill": "^0.12.0"
"bech32": "^2.0.0"
},
"devDependencies": {
"@lavamoat/allow-scripts": "^3.2.1",
"@lavamoat/preinstall-always-fail": "^2.1.0",
"@metamask/auto-changelog": "^3.4.4",
"@metamask/providers": "^18.1.0",
"@metamask/keyring-utils": "workspace:^",
"@ts-bridge/cli": "^0.6.0",
"@types/jest": "^29.5.12",
"@types/node": "^20.12.12",
Expand All @@ -73,9 +70,6 @@
"typedoc": "^0.25.13",
"typescript": "~5.6.3"
},
"peerDependencies": {
"@metamask/providers": "^18.1.0"
},
"engines": {
"node": "^18.18 || >=20"
},
Expand All @@ -91,6 +85,9 @@
}
},
"tsd": {
"directory": "src"
"directory": "src",
"compilerOptions": {
"composite": "false"
}
}
}
4 changes: 1 addition & 3 deletions packages/keyring-api/src/api/account.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
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 { object } from '../superstruct';
import { UuidStruct } from '../utils';

/**
* Supported Ethereum account types.
*/
Expand Down
8 changes: 5 additions & 3 deletions packages/keyring-api/src/api/asset.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
object,
selectiveUnion,
StringNumberStruct,
} from '@metamask/keyring-utils';
import type { Infer } from '@metamask/superstruct';
import { literal, string } from '@metamask/superstruct';
import {
Expand All @@ -6,9 +11,6 @@ import {
isPlainObject,
} from '@metamask/utils';

import { object, selectiveUnion } from '../superstruct';
import { StringNumberStruct } from '../utils';

/**
* Fungible asset struct.
*/
Expand Down
28 changes: 28 additions & 0 deletions packages/keyring-api/src/api/balance.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { is } from '@metamask/superstruct';

import { BalanceStruct } from './balance';

describe('BalanceStruct', () => {
it.each([
// Valid
{ balance: { amount: '1.0', unit: 'ETH' }, expected: true },
{ balance: { amount: '0.1', unit: 'BTC' }, expected: true },
// Missing amount
{ balance: { unit: 'ETH' }, expected: false },
// Missing unit
{ balance: { amount: '1.0' }, expected: false },
// Invalid amount type
{ balance: { amount: 1, unit: 'ETH' }, expected: false },
{ balance: { amount: true, unit: 'ETH' }, expected: false },
{ balance: { amount: null, unit: 'ETH' }, expected: false },
// Invalid unit type
{ balance: { amount: '1.0', unit: 1 }, expected: false },
{ balance: { amount: '1.0', unit: true }, expected: false },
{ balance: { amount: '1.0', unit: null }, expected: false },
])(
'returns $expected for is($balance, BalanceStruct)',
({ balance, expected }) => {
expect(is(balance, BalanceStruct)).toBe(expected);
},
);
});
4 changes: 1 addition & 3 deletions packages/keyring-api/src/api/balance.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { object, StringNumberStruct } from '@metamask/keyring-utils';
import type { Infer } from '@metamask/superstruct';
import { string } from '@metamask/superstruct';

import { object } from '../superstruct';
import { StringNumberStruct } from '../utils';

export const BalanceStruct = object({
amount: StringNumberStruct,
unit: string(),
Expand Down
3 changes: 1 addition & 2 deletions packages/keyring-api/src/api/caip.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { definePattern } from '@metamask/keyring-utils';
import { is, type Infer } from '@metamask/superstruct';

import { definePattern } from '../superstruct';

const CAIP_ASSET_TYPE_REGEX =
/^(?<chainId>(?<namespace>[-a-z0-9]{3,8}):(?<reference>[-_a-zA-Z0-9]{1,32}))\/(?<assetNamespace>[-a-z0-9]{3,8}):(?<assetReference>[-.%a-zA-Z0-9]{1,128})$/u;

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

import { KeyringAccountDataStruct } from './export';

describe('KeyringAccountDataStruct', () => {
const sym = Symbol('Unique symbol for testing purposes');
it.each([
// Valid
{ data: { foo: 'bar' }, expected: true },
{ data: { foo: 'bar', bar: 1 }, expected: true },
// Undefined is not allowed in JSON
{ data: { foo: undefined, bar: null }, expected: false },
// Invalid
{ data: 0, expected: false },
{
data: '34a0b893b66e312a8b0f7dc4bc4c7930b67f8823513aff5444fb5c64aa060c5a',
expected: false,
},
{ data: sym, expected: false },
// FIXME: Not sure why this one works, maybe the array is
// mapped as: { 0: 0xdead, 1: 0xbeef, 2: '!' }?
{ data: [0xdead, 0xbeef, '!'], expected: true },
])(
'returns $expected for is($data, KeyringAccountDataStruct)',
({ data, expected }) => {
expect(is(data, KeyringAccountDataStruct)).toBe(expected);
},
);
});
1 change: 1 addition & 0 deletions packages/keyring-api/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export * from './export';
export * from './request';
export * from './response';
export * from './transaction';
export * from './pagination';
export type * from './keyring';
5 changes: 4 additions & 1 deletion packages/keyring-api/src/api/keyring.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
// This rule seems to be triggering a false positive on the `KeyringAccount`.

import type { Json } from '@metamask/utils';

import type { KeyringAccount } from './account';
import type { Balance } from './balance';
import type { CaipAssetType } from './caip';
import type { KeyringAccountData } from './export';
import type { Paginated, Pagination } from './pagination';
import type { KeyringRequest } from './request';
import type { KeyringResponse } from './response';
import type { Transaction } from './transaction';
import type { Paginated, Pagination } from '../utils';

/**
* Keyring interface.
Expand Down
Loading

0 comments on commit 0488168

Please sign in to comment.