@leather.io/crypto 1.12.7 → 1.12.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
- import { HDKey } from '@scure/bip32';
1
+ import { HDKey } from "@scure/bip32";
2
2
 
3
+ //#region src/derivation-path-utils.d.ts
3
4
  declare enum DerivationPathDepth {
4
- Root = 0,
5
- Purpose = 1,
6
- CoinType = 2,
7
- Account = 3,
8
- Change = 4,
9
- AddressIndex = 5
5
+ Root = 0,
6
+ Purpose = 1,
7
+ CoinType = 2,
8
+ Account = 3,
9
+ Change = 4,
10
+ AddressIndex = 5,
10
11
  }
11
12
  declare const extractPurposeFromPath: (path: string) => number;
12
13
  declare const extractAccountIndexFromPath: (path: string) => number;
@@ -56,13 +57,14 @@ declare function extractKeyFromDescriptor(descriptor: string): string;
56
57
  declare function extractAccountPathFromFullPath(path: string): string;
57
58
  declare function keyOriginToDerivationPath(keyOrigin: string): string;
58
59
  declare function decomposeDescriptor(descriptor: string): {
59
- descriptor: string;
60
- keyOrigin: string;
61
- fingerprint: string;
62
- derivationPath: string;
63
- accountIndex: number;
60
+ descriptor: string;
61
+ keyOrigin: string;
62
+ fingerprint: string;
63
+ derivationPath: string;
64
+ accountIndex: number;
64
65
  };
65
-
66
+ //#endregion
67
+ //#region src/keychain.d.ts
66
68
  declare function generateMnemonic(): string;
67
69
  declare function deriveBip39SeedFromMnemonic(mnemonic: string, passphrase?: string): Promise<Uint8Array<ArrayBufferLike>>;
68
70
  /** @deprecated Inaccurately named fn, use `deriveBip39SeedFromMnemonic` */
@@ -83,13 +85,15 @@ declare function isValidMnemonic(mnemonic: string): boolean;
83
85
  * Create a unique accountId using wallet's fingerprint and accountIndex
84
86
  */
85
87
  declare function makeAccountIdentifer(fingerprint: string, accountIndex: number): string;
86
-
88
+ //#endregion
89
+ //#region src/signer/signer.d.ts
87
90
  type SignFn<T> = (tx: T, ...args: unknown[]) => Promise<T>;
88
91
  interface Signer {
89
- sign: SignFn<any>;
90
- address: string;
91
- publicKey: Uint8Array;
92
- derivationPath: string;
92
+ sign: SignFn<any>;
93
+ address: string;
94
+ publicKey: Uint8Array;
95
+ derivationPath: string;
93
96
  }
94
-
95
- export { DerivationPathDepth, type Signer, appendAddressIndexToPath, createDescriptor, createKeyOriginPath, decomposeDescriptor, deriveBip39MnemonicFromSeed, deriveBip39SeedFromMnemonic, deriveChildKeychainFromMnemnonic, deriveKeychainExtendedPublicKeyDescriptor, deriveKeychainFromXpub, deriveRootBip32Keychain, deriveRootKeychainFromMnemonic, extractAccountIndexFromDescriptor, extractAccountIndexFromPath, extractAccountPathFromFullPath, extractAddressIndexFromPath, extractChangeIndexFromPath, extractDerivationPathFromDescriptor, extractFingerprintFromDescriptor, extractFingerprintFromKeyOriginPath, extractKeyFromDescriptor, extractKeyOriginPathFromDescriptor, extractPurposeFromPath, generateMnemonic, getMnemonicRootKeyFingerprint, isValidMnemonic, isValidMnemonicWord, keyOriginToDerivationPath, makeAccountIdentifer, validateKeyOriginPath };
97
+ //#endregion
98
+ export { DerivationPathDepth, Signer, appendAddressIndexToPath, createDescriptor, createKeyOriginPath, decomposeDescriptor, deriveBip39MnemonicFromSeed, deriveBip39SeedFromMnemonic, deriveChildKeychainFromMnemnonic, deriveKeychainExtendedPublicKeyDescriptor, deriveKeychainFromXpub, deriveRootBip32Keychain, deriveRootKeychainFromMnemonic, extractAccountIndexFromDescriptor, extractAccountIndexFromPath, extractAccountPathFromFullPath, extractAddressIndexFromPath, extractChangeIndexFromPath, extractDerivationPathFromDescriptor, extractFingerprintFromDescriptor, extractFingerprintFromKeyOriginPath, extractKeyFromDescriptor, extractKeyOriginPathFromDescriptor, extractPurposeFromPath, generateMnemonic, getMnemonicRootKeyFingerprint, isValidMnemonic, isValidMnemonicWord, keyOriginToDerivationPath, makeAccountIdentifer, validateKeyOriginPath };
99
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/derivation-path-utils.ts","../src/keychain.ts","../src/signer/signer.ts"],"sourcesContent":[],"mappings":";;;aAEY,mBAAA;;;EAAA,QAAA,GAAA,CAAA;EAkBC,OAAA,GAAA,CAAA;EAEA,MAAA,GAAA,CAAA;EAIA,YAAA,GAAA,CAAA;AAIb;AAIgB,cAdH,sBAc2B,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAMxB,cAlBH,2BAkBsC,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAcnC,cA5BH,0BA4BsB,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAKnB,cA7BH,2BA6BwB,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GAAA,MAAA;AAqBrB,iBA9CA,wBAAA,CA8CgB,IAAA,EAAA,MAAA,EAAA,MAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAQhB,iBAhDA,mCAAA,CAgDkC,aAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AASlD;AAQA;AAOA;AAOA;AAOA;AAKA;AAKA;;iBAlFgB,mBAAA;iBAKA,qBAAA;ACzChB;AAIA;;;;AAAuF,iBD0DvE,gBAAA,CC1DuE,aAAA,EAAA,MAAA,EAAA,GAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAIvF;AAEA;AAIA;AAIsB,iBDoDN,kCAAA,CCjDK,UAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAMrB;AAMA;AAKA;AAWgB,iBD8BA,mCAAA,CC9BmB,UAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAInC;AAMA;;iBD4BgB,gCAAA;;;;AEzGwC,iBFgHxC,iCAAA,CEhHwC,UAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;AAExD;iBFqHgB,wBAAA;;;;iBAOA,8BAAA;iBAKA,yBAAA;iBAKA,mBAAA;;;;;;;;;iBCtHA,gBAAA,CAAA;iBAIM,2BAAA,yCAAiE,QAAA,WAAA;ADpBvF;AAkBa,cCMA,2BDNsF,EAAA,OCM3D,2BDN2D;AAEtF,iBCMG,uBAAA,CDJf,IAAA,ECI6C,UDJ7C,CAAA,ECIuD,KDJvD;AAEY,iBCMS,8BAAA,CDJrB,QAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,CAAA,ECIyF,ODJzF,CCIyF,KDJzF,CAAA;AAEY,iBCMS,gCAAA,CDJrB,IAAA,EAAA,MAAA,EAAA,QAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,CAAA,ECOoB,ODPpB,CCOoB,KDPpB,CAAA;AAEe,cCWH,sBDX2B,EAAA,CAAA,IAAA,EAAA,MAAA,EAAA,GCWmB,KDXnB;AAMxC;AAcA;AAKA;AAqBA;AAQgB,iBCrCM,6BAAA,CDqC4B,QAAA,EAAA,MAAA,EAAA,UAAA,CAAA,EAAA,MAAA,CAAA,ECrCuC,ODqCvC,CAAA,MAAA,CAAA;AASlC,iBCzCA,yCAAA,CDyCmC,YAAA,ECzCqB,KDyCrB,EAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA;AAQnC,iBCtCA,mBAAA,CDsCgC,IAAA,EAAA,MAAA,CAAA,EAAA,OAAA;AAOhC,iBCzCA,eAAA,CDyCiC,QAAA,EAAA,MAAA,CAAA,EAAA,OAAA;AAOjD;AAOA;AAKA;AAKgB,iBC3DA,oBAAA,CD2DmB,WAAA,EAAA,MAAA,EAAA,YAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;KExI9B,iBAAiB,0BAA0B,QAAQ;UAEvC,MAAA;QACT;EFDI,OAAA,EAAA,MAAA;EAkBC,SAAA,EEfA,UFeA;EAEA,cAAA,EAAA,MAAA;AAIb"}
package/dist/index.js ADDED
@@ -0,0 +1,166 @@
1
+ import { isHexString, toHexString } from "@leather.io/utils";
2
+ import { HDKey } from "@scure/bip32";
3
+ import { generateMnemonic as generateMnemonic$1, mnemonicToSeed, validateMnemonic } from "@scure/bip39";
4
+ import { wordlist } from "@scure/bip39/wordlists/english";
5
+ import memoize from "just-memoize";
6
+
7
+ //#region src/derivation-path-utils.ts
8
+ let DerivationPathDepth = /* @__PURE__ */ function(DerivationPathDepth$1) {
9
+ DerivationPathDepth$1[DerivationPathDepth$1["Root"] = 0] = "Root";
10
+ DerivationPathDepth$1[DerivationPathDepth$1["Purpose"] = 1] = "Purpose";
11
+ DerivationPathDepth$1[DerivationPathDepth$1["CoinType"] = 2] = "CoinType";
12
+ DerivationPathDepth$1[DerivationPathDepth$1["Account"] = 3] = "Account";
13
+ DerivationPathDepth$1[DerivationPathDepth$1["Change"] = 4] = "Change";
14
+ DerivationPathDepth$1[DerivationPathDepth$1["AddressIndex"] = 5] = "AddressIndex";
15
+ return DerivationPathDepth$1;
16
+ }({});
17
+ function extractSectionFromDerivationPath(depth) {
18
+ return (path) => {
19
+ const segments = path.split("/");
20
+ const accountNum = parseInt(segments[depth].replaceAll("'", ""), 10);
21
+ if (isNaN(accountNum)) throw new Error(`Cannot parse ${DerivationPathDepth[depth]} from path`);
22
+ return accountNum;
23
+ };
24
+ }
25
+ const extractPurposeFromPath = extractSectionFromDerivationPath(DerivationPathDepth.Purpose);
26
+ const extractAccountIndexFromPath = extractSectionFromDerivationPath(DerivationPathDepth.Account);
27
+ const extractChangeIndexFromPath = extractSectionFromDerivationPath(DerivationPathDepth.Change);
28
+ const extractAddressIndexFromPath = extractSectionFromDerivationPath(DerivationPathDepth.AddressIndex);
29
+ function appendAddressIndexToPath(path, change, addressIndex) {
30
+ const accountIndex = extractAccountIndexFromPath(path);
31
+ if (!Number.isInteger(accountIndex)) throw new Error("Invalid path, must have account index");
32
+ return `${path}/${change}/${addressIndex}`;
33
+ }
34
+ function extractFingerprintFromKeyOriginPath(keyOriginPath) {
35
+ const fingerprint = keyOriginPath.split("/")[0];
36
+ if (!isHexString(fingerprint)) throw new Error("Fingerprint must be a hexadecimal string");
37
+ return fingerprint;
38
+ }
39
+ /**
40
+ * @description
41
+ * A key origin path refers to the identifier commonly used as part of the key
42
+ * information provided as part of a Output Descriptor described in BIP-380. It
43
+ * replaces the `m/` part of a derivation path with the master key fingerprint to which the
44
+ * key it describes belongs.
45
+ * @example `0a3fd8ef/84'/0'/0'`
46
+ */
47
+ function createKeyOriginPath(fingerprint, path) {
48
+ if (!isHexString(fingerprint)) throw new Error("Fingerprint must be a hexadecimal string");
49
+ return `${fingerprint}/${path.replace("m/", "")}`;
50
+ }
51
+ function validateKeyOriginPath(keyOriginPath) {
52
+ if (keyOriginPath.includes("[") || keyOriginPath.includes("]")) throw new Error("Key origin path should not contain square brackets");
53
+ if (!keyOriginPath.includes("/")) throw new Error("Key origin path must contain a fingerprint and derivation path");
54
+ if (!isHexString(extractFingerprintFromKeyOriginPath(keyOriginPath))) throw new Error("Fingerprint must be a hexadecimal string");
55
+ if (keyOriginPath.split("/").length < 4) throw new Error("Key origin path is too short. Should describe at least to the account level");
56
+ return true;
57
+ }
58
+ /**
59
+ * @description
60
+ * Creates a descriptor with key origin and xpub or public key
61
+ * @returns `[0a3fd8ef/84'/0'/0']xpuba1b…2c3`
62
+ */
63
+ function createDescriptor(keyOriginPath, key) {
64
+ validateKeyOriginPath(keyOriginPath);
65
+ return `[${keyOriginPath}]${key}`;
66
+ }
67
+ /**
68
+ * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `0a3fd8ef/84'/0'/0'`
69
+ */
70
+ function extractKeyOriginPathFromDescriptor(descriptor) {
71
+ const keyOriginPath = descriptor.split("]")[0].replace("[", "");
72
+ validateKeyOriginPath(keyOriginPath);
73
+ return keyOriginPath;
74
+ }
75
+ /**
76
+ * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `m/84'/0'/0'`
77
+ */
78
+ function extractDerivationPathFromDescriptor(descriptor) {
79
+ return "m/" + extractKeyOriginPathFromDescriptor(descriptor).split("/").slice(1).join("/");
80
+ }
81
+ /**
82
+ * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `0a3fd8ef`
83
+ */
84
+ function extractFingerprintFromDescriptor(descriptor) {
85
+ return extractFingerprintFromKeyOriginPath(extractKeyOriginPathFromDescriptor(descriptor));
86
+ }
87
+ /**
88
+ * @example `[0a3fd8ef/84'/0'/6']xpuba1b…2c3` -> `6`
89
+ */
90
+ function extractAccountIndexFromDescriptor(descriptor) {
91
+ return extractAccountIndexFromPath(extractKeyOriginPathFromDescriptor(descriptor));
92
+ }
93
+ /**
94
+ * @example `[0a3fd8ef/84'/0'/6']xpuba1b…2c3` -> `xpuba1b…2c3`
95
+ */
96
+ function extractKeyFromDescriptor(descriptor) {
97
+ return descriptor.split("]")[1];
98
+ }
99
+ /**
100
+ * @example `0a3fd8ef/84'/0'/0/0/0` -> `0a3fd8ef/84'/0'/0`
101
+ */
102
+ function extractAccountPathFromFullPath(path) {
103
+ return path.split("/").slice(0, 4).join("/");
104
+ }
105
+ function keyOriginToDerivationPath(keyOrigin) {
106
+ const [_fingerprint, ...remainingPath] = keyOrigin.split("/");
107
+ return `m/${remainingPath.join("/")}`;
108
+ }
109
+ function decomposeDescriptor(descriptor) {
110
+ return {
111
+ descriptor,
112
+ keyOrigin: extractKeyOriginPathFromDescriptor(descriptor),
113
+ fingerprint: extractFingerprintFromDescriptor(descriptor),
114
+ derivationPath: extractDerivationPathFromDescriptor(descriptor),
115
+ accountIndex: extractAccountIndexFromDescriptor(descriptor)
116
+ };
117
+ }
118
+
119
+ //#endregion
120
+ //#region src/keychain.ts
121
+ function generateMnemonic() {
122
+ return generateMnemonic$1(wordlist, 256);
123
+ }
124
+ async function deriveBip39SeedFromMnemonic(mnemonic, passphrase) {
125
+ return mnemonicToSeed(mnemonic, passphrase);
126
+ }
127
+ /** @deprecated Inaccurately named fn, use `deriveBip39SeedFromMnemonic` */
128
+ const deriveBip39MnemonicFromSeed = deriveBip39SeedFromMnemonic;
129
+ function deriveRootBip32Keychain(seed) {
130
+ return HDKey.fromMasterSeed(seed);
131
+ }
132
+ async function deriveRootKeychainFromMnemonic(mnemonic, passphrase) {
133
+ return deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));
134
+ }
135
+ async function deriveChildKeychainFromMnemnonic(path, mnemonic, passphrase) {
136
+ return deriveRootBip32Keychain(await mnemonicToSeed(mnemonic, passphrase)).derive(keyOriginToDerivationPath(path));
137
+ }
138
+ const deriveKeychainFromXpub = memoize((xpub) => HDKey.fromExtendedKey(xpub));
139
+ /**
140
+ * Gets keychain fingerprint directly from mnemonic. This is useful for
141
+ * referencing a mnemonic safely by an identifier.
142
+ */
143
+ async function getMnemonicRootKeyFingerprint(mnemonic, passphrase) {
144
+ return toHexString(deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase)).fingerprint);
145
+ }
146
+ function deriveKeychainExtendedPublicKeyDescriptor(rootKeychain, path) {
147
+ const keyOriginPath = createKeyOriginPath(toHexString(rootKeychain.fingerprint), path);
148
+ if (rootKeychain.depth !== DerivationPathDepth.Root) throw new Error("Cannot derive account keychain from non-root keychain");
149
+ return createDescriptor(keyOriginPath, rootKeychain.derive(path).publicExtendedKey);
150
+ }
151
+ function isValidMnemonicWord(word) {
152
+ return wordlist.includes(word);
153
+ }
154
+ function isValidMnemonic(mnemonic) {
155
+ return validateMnemonic(mnemonic, wordlist);
156
+ }
157
+ /**
158
+ * Create a unique accountId using wallet's fingerprint and accountIndex
159
+ */
160
+ function makeAccountIdentifer(fingerprint, accountIndex) {
161
+ return [fingerprint, accountIndex].join("/");
162
+ }
163
+
164
+ //#endregion
165
+ export { DerivationPathDepth, appendAddressIndexToPath, createDescriptor, createKeyOriginPath, decomposeDescriptor, deriveBip39MnemonicFromSeed, deriveBip39SeedFromMnemonic, deriveChildKeychainFromMnemnonic, deriveKeychainExtendedPublicKeyDescriptor, deriveKeychainFromXpub, deriveRootBip32Keychain, deriveRootKeychainFromMnemonic, extractAccountIndexFromDescriptor, extractAccountIndexFromPath, extractAccountPathFromFullPath, extractAddressIndexFromPath, extractChangeIndexFromPath, extractDerivationPathFromDescriptor, extractFingerprintFromDescriptor, extractFingerprintFromKeyOriginPath, extractKeyFromDescriptor, extractKeyOriginPathFromDescriptor, extractPurposeFromPath, generateMnemonic, getMnemonicRootKeyFingerprint, isValidMnemonic, isValidMnemonicWord, keyOriginToDerivationPath, makeAccountIdentifer, validateKeyOriginPath };
166
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["scureGenerateMnemonic"],"sources":["../src/derivation-path-utils.ts","../src/keychain.ts"],"sourcesContent":["import { isHexString } from '@leather.io/utils';\n\nexport enum DerivationPathDepth {\n Root = 0,\n Purpose = 1,\n CoinType = 2,\n Account = 3,\n Change = 4,\n AddressIndex = 5,\n}\n\nfunction extractSectionFromDerivationPath(depth: DerivationPathDepth) {\n return (path: string) => {\n const segments = path.split('/');\n const accountNum = parseInt(segments[depth].replaceAll(\"'\", ''), 10);\n if (isNaN(accountNum)) throw new Error(`Cannot parse ${DerivationPathDepth[depth]} from path`);\n return accountNum;\n };\n}\n\nexport const extractPurposeFromPath = extractSectionFromDerivationPath(DerivationPathDepth.Purpose);\n\nexport const extractAccountIndexFromPath = extractSectionFromDerivationPath(\n DerivationPathDepth.Account\n);\n\nexport const extractChangeIndexFromPath = extractSectionFromDerivationPath(\n DerivationPathDepth.Change\n);\n\nexport const extractAddressIndexFromPath = extractSectionFromDerivationPath(\n DerivationPathDepth.AddressIndex\n);\n\nexport function appendAddressIndexToPath(path: string, change: number, addressIndex: number) {\n const accountIndex = extractAccountIndexFromPath(path);\n if (!Number.isInteger(accountIndex)) throw new Error('Invalid path, must have account index');\n return `${path}/${change}/${addressIndex}`;\n}\n\nexport function extractFingerprintFromKeyOriginPath(keyOriginPath: string) {\n const fingerprint = keyOriginPath.split('/')[0];\n if (!isHexString(fingerprint)) throw new Error('Fingerprint must be a hexadecimal string');\n return fingerprint;\n}\n\n/**\n * @description\n * A key origin path refers to the identifier commonly used as part of the key\n * information provided as part of a Output Descriptor described in BIP-380. It\n * replaces the `m/` part of a derivation path with the master key fingerprint to which the\n * key it describes belongs.\n * @example `0a3fd8ef/84'/0'/0'`\n */\nexport function createKeyOriginPath(fingerprint: string, path: string) {\n if (!isHexString(fingerprint)) throw new Error('Fingerprint must be a hexadecimal string');\n return `${fingerprint}/${path.replace('m/', '')}`;\n}\n\nexport function validateKeyOriginPath(keyOriginPath: string) {\n if (keyOriginPath.includes('[') || keyOriginPath.includes(']'))\n throw new Error('Key origin path should not contain square brackets');\n\n if (!keyOriginPath.includes('/'))\n throw new Error('Key origin path must contain a fingerprint and derivation path');\n\n if (!isHexString(extractFingerprintFromKeyOriginPath(keyOriginPath)))\n throw new Error('Fingerprint must be a hexadecimal string');\n\n if (keyOriginPath.split('/').length < 4)\n throw new Error('Key origin path is too short. Should describe at least to the account level');\n\n return true;\n}\n\n/**\n * @description\n * Creates a descriptor with key origin and xpub or public key\n * @returns `[0a3fd8ef/84'/0'/0']xpuba1b…2c3`\n */\nexport function createDescriptor(keyOriginPath: string, key: string) {\n validateKeyOriginPath(keyOriginPath);\n return `[${keyOriginPath}]${key}`;\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `0a3fd8ef/84'/0'/0'`\n */\nexport function extractKeyOriginPathFromDescriptor(descriptor: string) {\n const keyOriginPath = descriptor.split(']')[0].replace('[', '');\n validateKeyOriginPath(keyOriginPath);\n return keyOriginPath;\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `m/84'/0'/0'`\n */\nexport function extractDerivationPathFromDescriptor(descriptor: string) {\n const keyOriginPath = extractKeyOriginPathFromDescriptor(descriptor);\n return 'm/' + keyOriginPath.split('/').slice(1).join('/');\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `0a3fd8ef`\n */\nexport function extractFingerprintFromDescriptor(descriptor: string) {\n return extractFingerprintFromKeyOriginPath(extractKeyOriginPathFromDescriptor(descriptor));\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/6']xpuba1b…2c3` -> `6`\n */\nexport function extractAccountIndexFromDescriptor(descriptor: string) {\n return extractAccountIndexFromPath(extractKeyOriginPathFromDescriptor(descriptor));\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/6']xpuba1b…2c3` -> `xpuba1b…2c3`\n */\nexport function extractKeyFromDescriptor(descriptor: string) {\n return descriptor.split(']')[1];\n}\n\n/**\n * @example `0a3fd8ef/84'/0'/0/0/0` -> `0a3fd8ef/84'/0'/0`\n */\nexport function extractAccountPathFromFullPath(path: string) {\n const segments = path.split('/');\n return segments.slice(0, 4).join('/');\n}\n\nexport function keyOriginToDerivationPath(keyOrigin: string) {\n const [_fingerprint, ...remainingPath] = keyOrigin.split('/');\n return `m/${remainingPath.join('/')}`;\n}\n\nexport function decomposeDescriptor(descriptor: string) {\n return {\n descriptor,\n keyOrigin: extractKeyOriginPathFromDescriptor(descriptor),\n fingerprint: extractFingerprintFromDescriptor(descriptor),\n derivationPath: extractDerivationPathFromDescriptor(descriptor),\n accountIndex: extractAccountIndexFromDescriptor(descriptor),\n };\n}\n","import { HDKey } from '@scure/bip32';\nimport {\n mnemonicToSeed,\n generateMnemonic as scureGenerateMnemonic,\n validateMnemonic,\n} from '@scure/bip39';\nimport { wordlist } from '@scure/bip39/wordlists/english';\nimport memoize from 'just-memoize';\n\nimport { toHexString } from '@leather.io/utils';\n\nimport {\n DerivationPathDepth,\n createDescriptor,\n createKeyOriginPath,\n keyOriginToDerivationPath,\n} from './derivation-path-utils';\n\nexport function generateMnemonic() {\n return scureGenerateMnemonic(wordlist, 256);\n}\n\nexport async function deriveBip39SeedFromMnemonic(mnemonic: string, passphrase?: string) {\n return mnemonicToSeed(mnemonic, passphrase);\n}\n/** @deprecated Inaccurately named fn, use `deriveBip39SeedFromMnemonic` */\nexport const deriveBip39MnemonicFromSeed = deriveBip39SeedFromMnemonic;\n\nexport function deriveRootBip32Keychain(seed: Uint8Array) {\n return HDKey.fromMasterSeed(seed);\n}\n\nexport async function deriveRootKeychainFromMnemonic(mnemonic: string, passphrase?: string) {\n return deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));\n}\n\nexport async function deriveChildKeychainFromMnemnonic(\n path: string,\n mnemonic: string,\n passphrase?: string\n) {\n const rootKeychain = deriveRootBip32Keychain(await mnemonicToSeed(mnemonic, passphrase));\n return rootKeychain.derive(keyOriginToDerivationPath(path));\n}\n\nexport const deriveKeychainFromXpub = memoize((xpub: string) => HDKey.fromExtendedKey(xpub));\n\n/**\n * Gets keychain fingerprint directly from mnemonic. This is useful for\n * referencing a mnemonic safely by an identifier.\n */\nexport async function getMnemonicRootKeyFingerprint(mnemonic: string, passphrase?: string) {\n const keychain = deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));\n return toHexString(keychain.fingerprint);\n}\n\nexport function deriveKeychainExtendedPublicKeyDescriptor(rootKeychain: HDKey, path: string) {\n const masterFingerprint = toHexString(rootKeychain.fingerprint);\n const keyOriginPath = createKeyOriginPath(masterFingerprint, path);\n\n if (rootKeychain.depth !== DerivationPathDepth.Root)\n throw new Error('Cannot derive account keychain from non-root keychain');\n\n const accountKeychain = rootKeychain.derive(path);\n return createDescriptor(keyOriginPath, accountKeychain.publicExtendedKey);\n}\n\nexport function isValidMnemonicWord(word: string): boolean {\n return wordlist.includes(word);\n}\n\nexport function isValidMnemonic(mnemonic: string): boolean {\n return validateMnemonic(mnemonic, wordlist);\n}\n/**\n * Create a unique accountId using wallet's fingerprint and accountIndex\n */\nexport function makeAccountIdentifer(fingerprint: string, accountIndex: number) {\n return [fingerprint, accountIndex].join('/');\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -2,30 +2,37 @@
2
2
  "name": "@leather.io/crypto",
3
3
  "author": "leather.io",
4
4
  "description": "Generic crypto utils package for Leather",
5
- "version": "1.12.7",
5
+ "version": "1.12.8",
6
6
  "license": "MIT",
7
+ "type": "module",
7
8
  "exports": {
8
- ".": "./dist/index.mjs"
9
+ ".": "./dist/index.js"
9
10
  },
10
11
  "dependencies": {
11
12
  "@scure/bip32": "1.6.2",
12
13
  "@scure/bip39": "1.5.4",
13
14
  "just-memoize": "2.2.0",
14
- "@leather.io/utils": "0.49.1"
15
+ "@leather.io/utils": "0.49.2"
15
16
  },
16
17
  "devDependencies": {
17
- "tsup": "8.4.0",
18
- "vitest": "2.1.9"
18
+ "prettier": "3.5.1",
19
+ "tsdown": "0.16.5",
20
+ "vitest": "2.1.9",
21
+ "@leather.io/test-config": "0.1.1",
22
+ "@leather.io/prettier-config": "0.9.0"
19
23
  },
20
24
  "files": [
21
25
  "dist"
22
26
  ],
27
+ "prettier": "@leather.io/prettier-config",
23
28
  "publishConfig": {
24
29
  "access": "public"
25
30
  },
26
31
  "scripts": {
27
- "build": "tsup",
28
- "build:watch": "tsup --watch --onSuccess 'tsup --dts-only'",
32
+ "build": "tsdown",
33
+ "build:watch": "tsdown --watch",
34
+ "format": "prettier . --write --ignore-path ../../.prettierignore",
35
+ "format:check": "prettier . --check --ignore-path ../../.prettierignore",
29
36
  "prepublish": "pnpm build",
30
37
  "test:coverage": "vitest run --coverage",
31
38
  "test:unit": "vitest run",
package/dist/index.mjs DELETED
@@ -1,176 +0,0 @@
1
- // src/derivation-path-utils.ts
2
- import { isHexString } from "@leather.io/utils";
3
- var DerivationPathDepth = /* @__PURE__ */ ((DerivationPathDepth2) => {
4
- DerivationPathDepth2[DerivationPathDepth2["Root"] = 0] = "Root";
5
- DerivationPathDepth2[DerivationPathDepth2["Purpose"] = 1] = "Purpose";
6
- DerivationPathDepth2[DerivationPathDepth2["CoinType"] = 2] = "CoinType";
7
- DerivationPathDepth2[DerivationPathDepth2["Account"] = 3] = "Account";
8
- DerivationPathDepth2[DerivationPathDepth2["Change"] = 4] = "Change";
9
- DerivationPathDepth2[DerivationPathDepth2["AddressIndex"] = 5] = "AddressIndex";
10
- return DerivationPathDepth2;
11
- })(DerivationPathDepth || {});
12
- function extractSectionFromDerivationPath(depth) {
13
- return (path) => {
14
- const segments = path.split("/");
15
- const accountNum = parseInt(segments[depth].replaceAll("'", ""), 10);
16
- if (isNaN(accountNum)) throw new Error(`Cannot parse ${DerivationPathDepth[depth]} from path`);
17
- return accountNum;
18
- };
19
- }
20
- var extractPurposeFromPath = extractSectionFromDerivationPath(1 /* Purpose */);
21
- var extractAccountIndexFromPath = extractSectionFromDerivationPath(
22
- 3 /* Account */
23
- );
24
- var extractChangeIndexFromPath = extractSectionFromDerivationPath(
25
- 4 /* Change */
26
- );
27
- var extractAddressIndexFromPath = extractSectionFromDerivationPath(
28
- 5 /* AddressIndex */
29
- );
30
- function appendAddressIndexToPath(path, change, addressIndex) {
31
- const accountIndex = extractAccountIndexFromPath(path);
32
- if (!Number.isInteger(accountIndex)) throw new Error("Invalid path, must have account index");
33
- return `${path}/${change}/${addressIndex}`;
34
- }
35
- function extractFingerprintFromKeyOriginPath(keyOriginPath) {
36
- const fingerprint = keyOriginPath.split("/")[0];
37
- if (!isHexString(fingerprint)) throw new Error("Fingerprint must be a hexadecimal string");
38
- return fingerprint;
39
- }
40
- function createKeyOriginPath(fingerprint, path) {
41
- if (!isHexString(fingerprint)) throw new Error("Fingerprint must be a hexadecimal string");
42
- return `${fingerprint}/${path.replace("m/", "")}`;
43
- }
44
- function validateKeyOriginPath(keyOriginPath) {
45
- if (keyOriginPath.includes("[") || keyOriginPath.includes("]"))
46
- throw new Error("Key origin path should not contain square brackets");
47
- if (!keyOriginPath.includes("/"))
48
- throw new Error("Key origin path must contain a fingerprint and derivation path");
49
- if (!isHexString(extractFingerprintFromKeyOriginPath(keyOriginPath)))
50
- throw new Error("Fingerprint must be a hexadecimal string");
51
- if (keyOriginPath.split("/").length < 4)
52
- throw new Error("Key origin path is too short. Should describe at least to the account level");
53
- return true;
54
- }
55
- function createDescriptor(keyOriginPath, key) {
56
- validateKeyOriginPath(keyOriginPath);
57
- return `[${keyOriginPath}]${key}`;
58
- }
59
- function extractKeyOriginPathFromDescriptor(descriptor) {
60
- const keyOriginPath = descriptor.split("]")[0].replace("[", "");
61
- validateKeyOriginPath(keyOriginPath);
62
- return keyOriginPath;
63
- }
64
- function extractDerivationPathFromDescriptor(descriptor) {
65
- const keyOriginPath = extractKeyOriginPathFromDescriptor(descriptor);
66
- return "m/" + keyOriginPath.split("/").slice(1).join("/");
67
- }
68
- function extractFingerprintFromDescriptor(descriptor) {
69
- return extractFingerprintFromKeyOriginPath(extractKeyOriginPathFromDescriptor(descriptor));
70
- }
71
- function extractAccountIndexFromDescriptor(descriptor) {
72
- return extractAccountIndexFromPath(extractKeyOriginPathFromDescriptor(descriptor));
73
- }
74
- function extractKeyFromDescriptor(descriptor) {
75
- return descriptor.split("]")[1];
76
- }
77
- function extractAccountPathFromFullPath(path) {
78
- const segments = path.split("/");
79
- return segments.slice(0, 4).join("/");
80
- }
81
- function keyOriginToDerivationPath(keyOrigin) {
82
- const [_fingerprint, ...remainingPath] = keyOrigin.split("/");
83
- return `m/${remainingPath.join("/")}`;
84
- }
85
- function decomposeDescriptor(descriptor) {
86
- return {
87
- descriptor,
88
- keyOrigin: extractKeyOriginPathFromDescriptor(descriptor),
89
- fingerprint: extractFingerprintFromDescriptor(descriptor),
90
- derivationPath: extractDerivationPathFromDescriptor(descriptor),
91
- accountIndex: extractAccountIndexFromDescriptor(descriptor)
92
- };
93
- }
94
-
95
- // src/keychain.ts
96
- import { HDKey } from "@scure/bip32";
97
- import {
98
- mnemonicToSeed,
99
- generateMnemonic as scureGenerateMnemonic,
100
- validateMnemonic
101
- } from "@scure/bip39";
102
- import { wordlist } from "@scure/bip39/wordlists/english";
103
- import memoize from "just-memoize";
104
- import { toHexString } from "@leather.io/utils";
105
- function generateMnemonic() {
106
- return scureGenerateMnemonic(wordlist, 256);
107
- }
108
- async function deriveBip39SeedFromMnemonic(mnemonic, passphrase) {
109
- return mnemonicToSeed(mnemonic, passphrase);
110
- }
111
- var deriveBip39MnemonicFromSeed = deriveBip39SeedFromMnemonic;
112
- function deriveRootBip32Keychain(seed) {
113
- return HDKey.fromMasterSeed(seed);
114
- }
115
- async function deriveRootKeychainFromMnemonic(mnemonic, passphrase) {
116
- return deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));
117
- }
118
- async function deriveChildKeychainFromMnemnonic(path, mnemonic, passphrase) {
119
- const rootKeychain = deriveRootBip32Keychain(await mnemonicToSeed(mnemonic, passphrase));
120
- return rootKeychain.derive(keyOriginToDerivationPath(path));
121
- }
122
- var deriveKeychainFromXpub = memoize((xpub) => HDKey.fromExtendedKey(xpub));
123
- async function getMnemonicRootKeyFingerprint(mnemonic, passphrase) {
124
- const keychain = deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));
125
- return toHexString(keychain.fingerprint);
126
- }
127
- function deriveKeychainExtendedPublicKeyDescriptor(rootKeychain, path) {
128
- const masterFingerprint = toHexString(rootKeychain.fingerprint);
129
- const keyOriginPath = createKeyOriginPath(masterFingerprint, path);
130
- if (rootKeychain.depth !== 0 /* Root */)
131
- throw new Error("Cannot derive account keychain from non-root keychain");
132
- const accountKeychain = rootKeychain.derive(path);
133
- return createDescriptor(keyOriginPath, accountKeychain.publicExtendedKey);
134
- }
135
- function isValidMnemonicWord(word) {
136
- return wordlist.includes(word);
137
- }
138
- function isValidMnemonic(mnemonic) {
139
- return validateMnemonic(mnemonic, wordlist);
140
- }
141
- function makeAccountIdentifer(fingerprint, accountIndex) {
142
- return [fingerprint, accountIndex].join("/");
143
- }
144
- export {
145
- DerivationPathDepth,
146
- appendAddressIndexToPath,
147
- createDescriptor,
148
- createKeyOriginPath,
149
- decomposeDescriptor,
150
- deriveBip39MnemonicFromSeed,
151
- deriveBip39SeedFromMnemonic,
152
- deriveChildKeychainFromMnemnonic,
153
- deriveKeychainExtendedPublicKeyDescriptor,
154
- deriveKeychainFromXpub,
155
- deriveRootBip32Keychain,
156
- deriveRootKeychainFromMnemonic,
157
- extractAccountIndexFromDescriptor,
158
- extractAccountIndexFromPath,
159
- extractAccountPathFromFullPath,
160
- extractAddressIndexFromPath,
161
- extractChangeIndexFromPath,
162
- extractDerivationPathFromDescriptor,
163
- extractFingerprintFromDescriptor,
164
- extractFingerprintFromKeyOriginPath,
165
- extractKeyFromDescriptor,
166
- extractKeyOriginPathFromDescriptor,
167
- extractPurposeFromPath,
168
- generateMnemonic,
169
- getMnemonicRootKeyFingerprint,
170
- isValidMnemonic,
171
- isValidMnemonicWord,
172
- keyOriginToDerivationPath,
173
- makeAccountIdentifer,
174
- validateKeyOriginPath
175
- };
176
- //# sourceMappingURL=index.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/derivation-path-utils.ts","../src/keychain.ts"],"sourcesContent":["import { isHexString } from '@leather.io/utils';\n\nexport enum DerivationPathDepth {\n Root = 0,\n Purpose = 1,\n CoinType = 2,\n Account = 3,\n Change = 4,\n AddressIndex = 5,\n}\n\nfunction extractSectionFromDerivationPath(depth: DerivationPathDepth) {\n return (path: string) => {\n const segments = path.split('/');\n const accountNum = parseInt(segments[depth].replaceAll(\"'\", ''), 10);\n if (isNaN(accountNum)) throw new Error(`Cannot parse ${DerivationPathDepth[depth]} from path`);\n return accountNum;\n };\n}\n\nexport const extractPurposeFromPath = extractSectionFromDerivationPath(DerivationPathDepth.Purpose);\n\nexport const extractAccountIndexFromPath = extractSectionFromDerivationPath(\n DerivationPathDepth.Account\n);\n\nexport const extractChangeIndexFromPath = extractSectionFromDerivationPath(\n DerivationPathDepth.Change\n);\n\nexport const extractAddressIndexFromPath = extractSectionFromDerivationPath(\n DerivationPathDepth.AddressIndex\n);\n\nexport function appendAddressIndexToPath(path: string, change: number, addressIndex: number) {\n const accountIndex = extractAccountIndexFromPath(path);\n if (!Number.isInteger(accountIndex)) throw new Error('Invalid path, must have account index');\n return `${path}/${change}/${addressIndex}`;\n}\n\nexport function extractFingerprintFromKeyOriginPath(keyOriginPath: string) {\n const fingerprint = keyOriginPath.split('/')[0];\n if (!isHexString(fingerprint)) throw new Error('Fingerprint must be a hexadecimal string');\n return fingerprint;\n}\n\n/**\n * @description\n * A key origin path refers to the identifier commonly used as part of the key\n * information provided as part of a Output Descriptor described in BIP-380. It\n * replaces the `m/` part of a derivation path with the master key fingerprint to which the\n * key it describes belongs.\n * @example `0a3fd8ef/84'/0'/0'`\n */\nexport function createKeyOriginPath(fingerprint: string, path: string) {\n if (!isHexString(fingerprint)) throw new Error('Fingerprint must be a hexadecimal string');\n return `${fingerprint}/${path.replace('m/', '')}`;\n}\n\nexport function validateKeyOriginPath(keyOriginPath: string) {\n if (keyOriginPath.includes('[') || keyOriginPath.includes(']'))\n throw new Error('Key origin path should not contain square brackets');\n\n if (!keyOriginPath.includes('/'))\n throw new Error('Key origin path must contain a fingerprint and derivation path');\n\n if (!isHexString(extractFingerprintFromKeyOriginPath(keyOriginPath)))\n throw new Error('Fingerprint must be a hexadecimal string');\n\n if (keyOriginPath.split('/').length < 4)\n throw new Error('Key origin path is too short. Should describe at least to the account level');\n\n return true;\n}\n\n/**\n * @description\n * Creates a descriptor with key origin and xpub or public key\n * @returns `[0a3fd8ef/84'/0'/0']xpuba1b…2c3`\n */\nexport function createDescriptor(keyOriginPath: string, key: string) {\n validateKeyOriginPath(keyOriginPath);\n return `[${keyOriginPath}]${key}`;\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `0a3fd8ef/84'/0'/0'`\n */\nexport function extractKeyOriginPathFromDescriptor(descriptor: string) {\n const keyOriginPath = descriptor.split(']')[0].replace('[', '');\n validateKeyOriginPath(keyOriginPath);\n return keyOriginPath;\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `m/84'/0'/0'`\n */\nexport function extractDerivationPathFromDescriptor(descriptor: string) {\n const keyOriginPath = extractKeyOriginPathFromDescriptor(descriptor);\n return 'm/' + keyOriginPath.split('/').slice(1).join('/');\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/0']xpuba1b…2c3` -> `0a3fd8ef`\n */\nexport function extractFingerprintFromDescriptor(descriptor: string) {\n return extractFingerprintFromKeyOriginPath(extractKeyOriginPathFromDescriptor(descriptor));\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/6']xpuba1b…2c3` -> `6`\n */\nexport function extractAccountIndexFromDescriptor(descriptor: string) {\n return extractAccountIndexFromPath(extractKeyOriginPathFromDescriptor(descriptor));\n}\n\n/**\n * @example `[0a3fd8ef/84'/0'/6']xpuba1b…2c3` -> `xpuba1b…2c3`\n */\nexport function extractKeyFromDescriptor(descriptor: string) {\n return descriptor.split(']')[1];\n}\n\n/**\n * @example `0a3fd8ef/84'/0'/0/0/0` -> `0a3fd8ef/84'/0'/0`\n */\nexport function extractAccountPathFromFullPath(path: string) {\n const segments = path.split('/');\n return segments.slice(0, 4).join('/');\n}\n\nexport function keyOriginToDerivationPath(keyOrigin: string) {\n const [_fingerprint, ...remainingPath] = keyOrigin.split('/');\n return `m/${remainingPath.join('/')}`;\n}\n\nexport function decomposeDescriptor(descriptor: string) {\n return {\n descriptor,\n keyOrigin: extractKeyOriginPathFromDescriptor(descriptor),\n fingerprint: extractFingerprintFromDescriptor(descriptor),\n derivationPath: extractDerivationPathFromDescriptor(descriptor),\n accountIndex: extractAccountIndexFromDescriptor(descriptor),\n };\n}\n","import { HDKey } from '@scure/bip32';\nimport {\n mnemonicToSeed,\n generateMnemonic as scureGenerateMnemonic,\n validateMnemonic,\n} from '@scure/bip39';\nimport { wordlist } from '@scure/bip39/wordlists/english';\nimport memoize from 'just-memoize';\n\nimport { toHexString } from '@leather.io/utils';\n\nimport {\n DerivationPathDepth,\n createDescriptor,\n createKeyOriginPath,\n keyOriginToDerivationPath,\n} from './derivation-path-utils';\n\nexport function generateMnemonic() {\n return scureGenerateMnemonic(wordlist, 256);\n}\n\nexport async function deriveBip39SeedFromMnemonic(mnemonic: string, passphrase?: string) {\n return mnemonicToSeed(mnemonic, passphrase);\n}\n/** @deprecated Inaccurately named fn, use `deriveBip39SeedFromMnemonic` */\nexport const deriveBip39MnemonicFromSeed = deriveBip39SeedFromMnemonic;\n\nexport function deriveRootBip32Keychain(seed: Uint8Array) {\n return HDKey.fromMasterSeed(seed);\n}\n\nexport async function deriveRootKeychainFromMnemonic(mnemonic: string, passphrase?: string) {\n return deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));\n}\n\nexport async function deriveChildKeychainFromMnemnonic(\n path: string,\n mnemonic: string,\n passphrase?: string\n) {\n const rootKeychain = deriveRootBip32Keychain(await mnemonicToSeed(mnemonic, passphrase));\n return rootKeychain.derive(keyOriginToDerivationPath(path));\n}\n\nexport const deriveKeychainFromXpub = memoize((xpub: string) => HDKey.fromExtendedKey(xpub));\n\n/**\n * Gets keychain fingerprint directly from mnemonic. This is useful for\n * referencing a mnemonic safely by an identifier.\n */\nexport async function getMnemonicRootKeyFingerprint(mnemonic: string, passphrase?: string) {\n const keychain = deriveRootBip32Keychain(await deriveBip39SeedFromMnemonic(mnemonic, passphrase));\n return toHexString(keychain.fingerprint);\n}\n\nexport function deriveKeychainExtendedPublicKeyDescriptor(rootKeychain: HDKey, path: string) {\n const masterFingerprint = toHexString(rootKeychain.fingerprint);\n const keyOriginPath = createKeyOriginPath(masterFingerprint, path);\n\n if (rootKeychain.depth !== DerivationPathDepth.Root)\n throw new Error('Cannot derive account keychain from non-root keychain');\n\n const accountKeychain = rootKeychain.derive(path);\n return createDescriptor(keyOriginPath, accountKeychain.publicExtendedKey);\n}\n\nexport function isValidMnemonicWord(word: string): boolean {\n return wordlist.includes(word);\n}\n\nexport function isValidMnemonic(mnemonic: string): boolean {\n return validateMnemonic(mnemonic, wordlist);\n}\n/**\n * Create a unique accountId using wallet's fingerprint and accountIndex\n */\nexport function makeAccountIdentifer(fingerprint: string, accountIndex: number) {\n return [fingerprint, accountIndex].join('/');\n}\n"],"mappings":"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","names":["DerivationPathDepth"]}