-
Notifications
You must be signed in to change notification settings - Fork 578
/
Copy pathgetBip44Entropy.ts
93 lines (83 loc) · 2.67 KB
/
getBip44Entropy.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import {
PermissionSpecificationBuilder,
PermissionType,
RestrictedMethodOptions,
ValidPermissionSpecification,
} from '@metamask/snap-controllers';
import { ethErrors } from 'eth-rpc-errors';
import { BIP44CoinTypeNode, JsonBIP44CoinTypeNode } from '@metamask/key-tree';
import { NonEmptyArray } from '@metamask/snap-controllers/src/utils';
// TODO: Remove this after key-tree is bumped
// We redeclare this type locally because the import relies on an interface,
// which is incompatible with our Json type.
type _JsonBIP44CoinTypeNode = {
// eslint-disable-next-line camelcase
coin_type: number;
depth: JsonBIP44CoinTypeNode['depth'];
key: string;
path: JsonBIP44CoinTypeNode['path'];
};
const methodPrefix = 'snap_getBip44Entropy_';
const targetKey = `${methodPrefix}*` as const;
export type GetBip44EntropyMethodHooks = {
/**
* @returns The mnemonic of the user's primary keyring.
*/
getMnemonic: () => Promise<string>;
};
type GetBip44EntropySpecificationBuilderOptions = {
allowedCaveats?: Readonly<NonEmptyArray<string>> | null;
methodHooks: GetBip44EntropyMethodHooks;
};
type GetBip44EntropySpecification = ValidPermissionSpecification<{
permissionType: PermissionType.RestrictedMethod;
targetKey: typeof targetKey;
methodImplementation: ReturnType<typeof getBip44EntropyImplementation>;
allowedCaveats: Readonly<NonEmptyArray<string>> | null;
}>;
/**
* `snap_getBip44Entropy_*` lets the Snap control private keys for a particular
* BIP-32 coin type.
*/
const specificationBuilder: PermissionSpecificationBuilder<
PermissionType.RestrictedMethod,
GetBip44EntropySpecificationBuilderOptions,
GetBip44EntropySpecification
> = ({
allowedCaveats = null,
methodHooks,
}: GetBip44EntropySpecificationBuilderOptions) => {
return {
permissionType: PermissionType.RestrictedMethod,
targetKey,
allowedCaveats,
methodImplementation: getBip44EntropyImplementation(methodHooks),
};
};
export const getBip44EntropyBuilder = Object.freeze({
targetKey,
specificationBuilder,
methodHooks: {
getMnemonic: true,
},
} as const);
const ALL_DIGIT_REGEX = /^\d+$/u;
function getBip44EntropyImplementation({
getMnemonic,
}: GetBip44EntropyMethodHooks) {
return async function getBip44Entropy(
args: RestrictedMethodOptions<void>,
): Promise<_JsonBIP44CoinTypeNode> {
const bip44Code = args.method.substr(methodPrefix.length);
if (!ALL_DIGIT_REGEX.test(bip44Code)) {
throw ethErrors.rpc.methodNotFound({
message: `Invalid BIP-44 code: ${bip44Code}`,
});
}
return new BIP44CoinTypeNode([
`bip39:${await getMnemonic()}`,
`bip32:44'`,
`bip32:${Number(bip44Code)}'`,
]).toJSON();
};
}