quantumcoin 6.14.1 → 6.14.2
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.
- package/README.md +2 -0
- package/dist/quantumcoin.js +2697 -7812
- package/dist/quantumcoin.js.map +1 -1
- package/dist/quantumcoin.min.js +1 -1
- package/dist/quantumcoin.min.js'.gz' +0 -0
- package/dist/quantumcoin.umd.js +2698 -7835
- package/dist/quantumcoin.umd.js.map +1 -1
- package/dist/quantumcoin.umd.min.js +1 -1
- package/dist/quantumcoin.umd.min.js'.gz' +0 -0
- package/dist/wordlists-extra.min.js'.gz' +0 -0
- package/lib.commonjs/address/address.d.ts +1 -21
- package/lib.commonjs/address/address.d.ts.map +1 -1
- package/lib.commonjs/address/address.js +2 -30
- package/lib.commonjs/address/address.js.map +1 -1
- package/lib.commonjs/address/index.d.ts +1 -1
- package/lib.commonjs/address/index.d.ts.map +1 -1
- package/lib.commonjs/address/index.js +1 -2
- package/lib.commonjs/address/index.js.map +1 -1
- package/lib.commonjs/crypto/signature.d.ts +4 -17
- package/lib.commonjs/crypto/signature.d.ts.map +1 -1
- package/lib.commonjs/crypto/signature.js +57 -60
- package/lib.commonjs/crypto/signature.js.map +1 -1
- package/lib.commonjs/crypto/signing-key.d.ts +5 -64
- package/lib.commonjs/crypto/signing-key.d.ts.map +1 -1
- package/lib.commonjs/crypto/signing-key.js +27 -101
- package/lib.commonjs/crypto/signing-key.js.map +1 -1
- package/lib.commonjs/providers/default-provider.d.ts +0 -8
- package/lib.commonjs/providers/default-provider.d.ts.map +1 -1
- package/lib.commonjs/providers/default-provider.js +0 -108
- package/lib.commonjs/providers/default-provider.js.map +1 -1
- package/lib.commonjs/providers/index.d.ts +0 -9
- package/lib.commonjs/providers/index.d.ts.map +1 -1
- package/lib.commonjs/providers/index.js +1 -21
- package/lib.commonjs/providers/index.js.map +1 -1
- package/lib.commonjs/providers/network.js +1 -99
- package/lib.commonjs/providers/network.js.map +1 -1
- package/lib.commonjs/quantumcoin.d.ts +4 -4
- package/lib.commonjs/quantumcoin.d.ts.map +1 -1
- package/lib.commonjs/quantumcoin.js +4 -26
- package/lib.commonjs/quantumcoin.js.map +1 -1
- package/lib.commonjs/transaction/address.d.ts +1 -1
- package/lib.commonjs/transaction/address.d.ts.map +1 -1
- package/lib.commonjs/transaction/address.js +9 -5
- package/lib.commonjs/transaction/address.js.map +1 -1
- package/lib.commonjs/wallet/hdwallet.d.ts.map +1 -1
- package/lib.commonjs/wallet/hdwallet.js +4 -5
- package/lib.commonjs/wallet/hdwallet.js.map +1 -1
- package/lib.commonjs/wallet/index.d.ts +2 -6
- package/lib.commonjs/wallet/index.d.ts.map +1 -1
- package/lib.commonjs/wallet/index.js +1 -14
- package/lib.commonjs/wallet/index.js.map +1 -1
- package/lib.commonjs/wallet/json-keystore.d.ts +3 -52
- package/lib.commonjs/wallet/json-keystore.d.ts.map +1 -1
- package/lib.commonjs/wallet/json-keystore.js +41 -246
- package/lib.commonjs/wallet/json-keystore.js.map +1 -1
- package/lib.commonjs/wallet/seedwallet.d.ts +4 -0
- package/lib.commonjs/wallet/seedwallet.d.ts.map +1 -0
- package/lib.commonjs/wallet/seedwallet.js +8 -0
- package/lib.commonjs/wallet/seedwallet.js.map +1 -0
- package/lib.commonjs/wallet/wallet.d.ts +5 -14
- package/lib.commonjs/wallet/wallet.d.ts.map +1 -1
- package/lib.commonjs/wallet/wallet.js +12 -51
- package/lib.commonjs/wallet/wallet.js.map +1 -1
- package/lib.esm/address/address.d.ts +1 -21
- package/lib.esm/address/address.d.ts.map +1 -1
- package/lib.esm/address/address.js +1 -28
- package/lib.esm/address/address.js.map +1 -1
- package/lib.esm/address/index.d.ts +1 -1
- package/lib.esm/address/index.d.ts.map +1 -1
- package/lib.esm/address/index.js +1 -1
- package/lib.esm/address/index.js.map +1 -1
- package/lib.esm/crypto/signature.d.ts +4 -17
- package/lib.esm/crypto/signature.d.ts.map +1 -1
- package/lib.esm/crypto/signature.js +45 -46
- package/lib.esm/crypto/signature.js.map +1 -1
- package/lib.esm/crypto/signing-key.d.ts +5 -64
- package/lib.esm/crypto/signing-key.d.ts.map +1 -1
- package/lib.esm/crypto/signing-key.js +26 -102
- package/lib.esm/crypto/signing-key.js.map +1 -1
- package/lib.esm/providers/default-provider.d.ts +0 -8
- package/lib.esm/providers/default-provider.d.ts.map +1 -1
- package/lib.esm/providers/default-provider.js +0 -108
- package/lib.esm/providers/default-provider.js.map +1 -1
- package/lib.esm/providers/index.d.ts +0 -9
- package/lib.esm/providers/index.d.ts.map +1 -1
- package/lib.esm/providers/index.js +0 -9
- package/lib.esm/providers/index.js.map +1 -1
- package/lib.esm/providers/network.js +3 -101
- package/lib.esm/providers/network.js.map +1 -1
- package/lib.esm/quantumcoin.d.ts +4 -4
- package/lib.esm/quantumcoin.d.ts.map +1 -1
- package/lib.esm/quantumcoin.js +3 -3
- package/lib.esm/quantumcoin.js.map +1 -1
- package/lib.esm/transaction/address.d.ts +1 -1
- package/lib.esm/transaction/address.d.ts.map +1 -1
- package/lib.esm/transaction/address.js +7 -4
- package/lib.esm/transaction/address.js.map +1 -1
- package/lib.esm/wallet/hdwallet.d.ts.map +1 -1
- package/lib.esm/wallet/hdwallet.js +4 -5
- package/lib.esm/wallet/hdwallet.js.map +1 -1
- package/lib.esm/wallet/index.d.ts +2 -6
- package/lib.esm/wallet/index.d.ts.map +1 -1
- package/lib.esm/wallet/index.js +1 -4
- package/lib.esm/wallet/index.js.map +1 -1
- package/lib.esm/wallet/json-keystore.d.ts +3 -52
- package/lib.esm/wallet/json-keystore.d.ts.map +1 -1
- package/lib.esm/wallet/json-keystore.js +32 -241
- package/lib.esm/wallet/json-keystore.js.map +1 -1
- package/lib.esm/wallet/seedwallet.d.ts +4 -0
- package/lib.esm/wallet/seedwallet.d.ts.map +1 -0
- package/lib.esm/wallet/seedwallet.js +4 -0
- package/lib.esm/wallet/seedwallet.js.map +1 -0
- package/lib.esm/wallet/wallet.d.ts +5 -14
- package/lib.esm/wallet/wallet.d.ts.map +1 -1
- package/lib.esm/wallet/wallet.js +12 -53
- package/lib.esm/wallet/wallet.js.map +1 -1
- package/package.json +5 -2
- package/src.ts/address/address.ts +2 -27
- package/src.ts/address/index.ts +1 -1
- package/src.ts/crypto/signature.ts +31 -45
- package/src.ts/crypto/signing-key.ts +31 -109
- package/src.ts/providers/default-provider.ts +0 -106
- package/src.ts/providers/index.ts +0 -10
- package/src.ts/providers/network.ts +3 -111
- package/src.ts/quantumcoin.ts +7 -17
- package/src.ts/transaction/address.ts +8 -5
- package/src.ts/wallet/index.ts +2 -17
- package/src.ts/wallet/json-keystore.ts +42 -325
- package/src.ts/wallet/wallet.ts +23 -47
- package/src.ts/providers/provider-alchemy.ts +0 -166
- package/src.ts/providers/provider-ankr.ts +0 -153
- package/src.ts/providers/provider-blockscout.ts +0 -167
- package/src.ts/providers/provider-chainstack.ts +0 -113
- package/src.ts/providers/provider-cloudflare.ts +0 -24
- package/src.ts/providers/provider-etherscan.ts +0 -671
- package/src.ts/providers/provider-infura.ts +0 -220
- package/src.ts/providers/provider-pocket.ts +0 -121
- package/src.ts/providers/provider-quicknode.ts +0 -177
- package/src.ts/wallet/hdwallet.ts +0 -586
- package/src.ts/wallet/json-crowdsale.ts +0 -74
- package/src.ts/wallet/mnemonic.ts +0 -203
|
@@ -1,586 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Explain HD Wallets..
|
|
3
|
-
*
|
|
4
|
-
* @_subsection: api/wallet:HD Wallets [hd-wallets]
|
|
5
|
-
*/
|
|
6
|
-
import { computeHmac, randomBytes, ripemd160, SigningKey, sha256 } from "../crypto/index.js";
|
|
7
|
-
import { VoidSigner } from "../providers/index.js";
|
|
8
|
-
import { computeAddress } from "../transaction/index.js";
|
|
9
|
-
import {
|
|
10
|
-
concat, dataSlice, decodeBase58, defineProperties, encodeBase58,
|
|
11
|
-
getBytes, hexlify, isBytesLike,
|
|
12
|
-
getNumber, toBeArray, toBigInt, toBeHex,
|
|
13
|
-
assertPrivate, assert, assertArgument
|
|
14
|
-
} from "../utils/index.js";
|
|
15
|
-
import { LangEn } from "../wordlists/lang-en.js";
|
|
16
|
-
|
|
17
|
-
import { BaseWallet } from "./base-wallet.js";
|
|
18
|
-
import { Mnemonic } from "./mnemonic.js";
|
|
19
|
-
import {
|
|
20
|
-
encryptKeystoreJson, encryptKeystoreJsonSync,
|
|
21
|
-
} from "./json-keystore.js";
|
|
22
|
-
|
|
23
|
-
import type { ProgressCallback } from "../crypto/index.js";
|
|
24
|
-
import type { Provider } from "../providers/index.js";
|
|
25
|
-
import type { BytesLike, Numeric } from "../utils/index.js";
|
|
26
|
-
import type { Wordlist } from "../wordlists/index.js";
|
|
27
|
-
|
|
28
|
-
import type { KeystoreAccount } from "./json-keystore.js";
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* The default derivation path for Ethereum HD Nodes. (i.e. ``"m/44'/60'/0'/0/0"``)
|
|
32
|
-
*/
|
|
33
|
-
export const defaultPath: string = "m/44'/60'/0'/0/0";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
// "Bitcoin seed"
|
|
37
|
-
const MasterSecret = new Uint8Array([ 66, 105, 116, 99, 111, 105, 110, 32, 115, 101, 101, 100 ]);
|
|
38
|
-
|
|
39
|
-
const HardenedBit = 0x80000000;
|
|
40
|
-
|
|
41
|
-
const N = BigInt("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141");
|
|
42
|
-
|
|
43
|
-
const Nibbles = "0123456789abcdef";
|
|
44
|
-
function zpad(value: number, length: number): string {
|
|
45
|
-
let result = "";
|
|
46
|
-
while (value) {
|
|
47
|
-
result = Nibbles[value % 16] + result;
|
|
48
|
-
value = Math.trunc(value / 16);
|
|
49
|
-
}
|
|
50
|
-
while (result.length < length * 2) { result = "0" + result; }
|
|
51
|
-
return "0x" + result;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function encodeBase58Check(_value: BytesLike): string {
|
|
55
|
-
const value = getBytes(_value);
|
|
56
|
-
const check = dataSlice(sha256(sha256(value)), 0, 4);
|
|
57
|
-
const bytes = concat([ value, check ]);
|
|
58
|
-
return encodeBase58(bytes);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const _guard = { };
|
|
62
|
-
|
|
63
|
-
function ser_I(index: number, chainCode: string, publicKey: string, privateKey: null | string): { IL: Uint8Array, IR: Uint8Array } {
|
|
64
|
-
const data = new Uint8Array(37);
|
|
65
|
-
|
|
66
|
-
if (index & HardenedBit) {
|
|
67
|
-
assert(privateKey != null, "cannot derive child of neutered node", "UNSUPPORTED_OPERATION", {
|
|
68
|
-
operation: "deriveChild"
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Data = 0x00 || ser_256(k_par)
|
|
72
|
-
data.set(getBytes(privateKey), 1);
|
|
73
|
-
|
|
74
|
-
} else {
|
|
75
|
-
// Data = ser_p(point(k_par))
|
|
76
|
-
data.set(getBytes(publicKey));
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Data += ser_32(i)
|
|
80
|
-
for (let i = 24; i >= 0; i -= 8) { data[33 + (i >> 3)] = ((index >> (24 - i)) & 0xff); }
|
|
81
|
-
const I = getBytes(computeHmac("sha512", chainCode, data));
|
|
82
|
-
|
|
83
|
-
return { IL: I.slice(0, 32), IR: I.slice(32) };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
type HDNodeLike<T> = { depth: number, deriveChild: (i: number) => T };
|
|
87
|
-
function derivePath<T extends HDNodeLike<T>>(node: T, path: string): T {
|
|
88
|
-
const components = path.split("/");
|
|
89
|
-
|
|
90
|
-
assertArgument(components.length > 0, "invalid path", "path", path);
|
|
91
|
-
|
|
92
|
-
if (components[0] === "m") {
|
|
93
|
-
assertArgument(node.depth === 0, `cannot derive root path (i.e. path starting with "m/") for a node at non-zero depth ${ node.depth }`, "path", path);
|
|
94
|
-
components.shift();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
let result: T = node;
|
|
98
|
-
for (let i = 0; i < components.length; i++) {
|
|
99
|
-
const component = components[i];
|
|
100
|
-
|
|
101
|
-
if (component.match(/^[0-9]+'$/)) {
|
|
102
|
-
const index = parseInt(component.substring(0, component.length - 1));
|
|
103
|
-
assertArgument(index < HardenedBit, "invalid path index", `path[${ i }]`, component);
|
|
104
|
-
result = result.deriveChild(HardenedBit + index);
|
|
105
|
-
|
|
106
|
-
} else if (component.match(/^[0-9]+$/)) {
|
|
107
|
-
const index = parseInt(component);
|
|
108
|
-
assertArgument(index < HardenedBit, "invalid path index", `path[${ i }]`, component);
|
|
109
|
-
result = result.deriveChild(index);
|
|
110
|
-
|
|
111
|
-
} else {
|
|
112
|
-
assertArgument(false, "invalid path component", `path[${ i }]`, component);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return result;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* An **HDNodeWallet** is a [[Signer]] backed by the private key derived
|
|
121
|
-
* from an HD Node using the [[link-bip-32]] stantard.
|
|
122
|
-
*
|
|
123
|
-
* An HD Node forms a hierarchal structure with each HD Node having a
|
|
124
|
-
* private key and the ability to derive child HD Nodes, defined by
|
|
125
|
-
* a path indicating the index of each child.
|
|
126
|
-
*/
|
|
127
|
-
export class HDNodeWallet extends BaseWallet {
|
|
128
|
-
/**
|
|
129
|
-
* The compressed public key.
|
|
130
|
-
*/
|
|
131
|
-
readonly publicKey!: string;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* The fingerprint.
|
|
135
|
-
*
|
|
136
|
-
* A fingerprint allows quick qay to detect parent and child nodes,
|
|
137
|
-
* but developers should be prepared to deal with collisions as it
|
|
138
|
-
* is only 4 bytes.
|
|
139
|
-
*/
|
|
140
|
-
readonly fingerprint!: string;
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* The parent fingerprint.
|
|
144
|
-
*/
|
|
145
|
-
readonly parentFingerprint!: string;
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* The mnemonic used to create this HD Node, if available.
|
|
149
|
-
*
|
|
150
|
-
* Sources such as extended keys do not encode the mnemonic, in
|
|
151
|
-
* which case this will be ``null``.
|
|
152
|
-
*/
|
|
153
|
-
readonly mnemonic!: null | Mnemonic;
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* The chaincode, which is effectively a public key used
|
|
157
|
-
* to derive children.
|
|
158
|
-
*/
|
|
159
|
-
readonly chainCode!: string;
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* The derivation path of this wallet.
|
|
163
|
-
*
|
|
164
|
-
* Since extended keys do not provide full path details, this
|
|
165
|
-
* may be ``null``, if instantiated from a source that does not
|
|
166
|
-
* encode it.
|
|
167
|
-
*/
|
|
168
|
-
readonly path!: null | string;
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* The child index of this wallet. Values over ``2 *\* 31`` indicate
|
|
172
|
-
* the node is hardened.
|
|
173
|
-
*/
|
|
174
|
-
readonly index!: number;
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* The depth of this wallet, which is the number of components
|
|
178
|
-
* in its path.
|
|
179
|
-
*/
|
|
180
|
-
readonly depth!: number;
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* @private
|
|
184
|
-
*/
|
|
185
|
-
constructor(guard: any, signingKey: SigningKey, parentFingerprint: string, chainCode: string, path: null | string, index: number, depth: number, mnemonic: null | Mnemonic, provider: null | Provider) {
|
|
186
|
-
super(signingKey, provider);
|
|
187
|
-
assertPrivate(guard, _guard, "HDNodeWallet");
|
|
188
|
-
|
|
189
|
-
defineProperties<HDNodeWallet>(this, { publicKey: signingKey.compressedPublicKey });
|
|
190
|
-
|
|
191
|
-
const fingerprint = dataSlice(ripemd160(sha256(this.publicKey)), 0, 4);
|
|
192
|
-
defineProperties<HDNodeWallet>(this, {
|
|
193
|
-
parentFingerprint, fingerprint,
|
|
194
|
-
chainCode, path, index, depth
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
defineProperties<HDNodeWallet>(this, { mnemonic });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
connect(provider: null | Provider): HDNodeWallet {
|
|
201
|
-
return new HDNodeWallet(_guard, this.signingKey, this.parentFingerprint,
|
|
202
|
-
this.chainCode, this.path, this.index, this.depth, this.mnemonic, provider);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
#account(): KeystoreAccount {
|
|
206
|
-
const account: KeystoreAccount = { address: this.address, privateKey: this.privateKey };
|
|
207
|
-
const m = this.mnemonic;
|
|
208
|
-
if (this.path && m && m.wordlist.locale === "en" && m.password === "") {
|
|
209
|
-
account.mnemonic = {
|
|
210
|
-
path: this.path,
|
|
211
|
-
locale: "en",
|
|
212
|
-
entropy: m.entropy
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
return account;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Resolves to a [JSON Keystore Wallet](json-wallets) encrypted with
|
|
221
|
-
* %%password%%.
|
|
222
|
-
*
|
|
223
|
-
* If %%progressCallback%% is specified, it will receive periodic
|
|
224
|
-
* updates as the encryption process progreses.
|
|
225
|
-
*/
|
|
226
|
-
async encrypt(password: Uint8Array | string, progressCallback?: ProgressCallback): Promise<string> {
|
|
227
|
-
return await encryptKeystoreJson(this.#account(), password, { progressCallback });
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Returns a [JSON Keystore Wallet](json-wallets) encryped with
|
|
232
|
-
* %%password%%.
|
|
233
|
-
*
|
|
234
|
-
* It is preferred to use the [async version](encrypt) instead,
|
|
235
|
-
* which allows a [[ProgressCallback]] to keep the user informed.
|
|
236
|
-
*
|
|
237
|
-
* This method will block the event loop (freezing all UI) until
|
|
238
|
-
* it is complete, which may be a non-trivial duration.
|
|
239
|
-
*/
|
|
240
|
-
encryptSync(password: Uint8Array | string): string {
|
|
241
|
-
return encryptKeystoreJsonSync(this.#account(), password);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
/**
|
|
245
|
-
* The extended key.
|
|
246
|
-
*
|
|
247
|
-
* This key will begin with the prefix ``xpriv`` and can be used to
|
|
248
|
-
* reconstruct this HD Node to derive its children.
|
|
249
|
-
*/
|
|
250
|
-
get extendedKey(): string {
|
|
251
|
-
// We only support the mainnet values for now, but if anyone needs
|
|
252
|
-
// testnet values, let me know. I believe current sentiment is that
|
|
253
|
-
// we should always use mainnet, and use BIP-44 to derive the network
|
|
254
|
-
// - Mainnet: public=0x0488B21E, private=0x0488ADE4
|
|
255
|
-
// - Testnet: public=0x043587CF, private=0x04358394
|
|
256
|
-
|
|
257
|
-
assert(this.depth < 256, "Depth too deep", "UNSUPPORTED_OPERATION", { operation: "extendedKey" });
|
|
258
|
-
|
|
259
|
-
return encodeBase58Check(concat([
|
|
260
|
-
"0x0488ADE4", zpad(this.depth, 1), this.parentFingerprint,
|
|
261
|
-
zpad(this.index, 4), this.chainCode,
|
|
262
|
-
concat([ "0x00", this.privateKey ])
|
|
263
|
-
]));
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Returns true if this wallet has a path, providing a Type Guard
|
|
268
|
-
* that the path is non-null.
|
|
269
|
-
*/
|
|
270
|
-
hasPath(): this is { path: string } { return (this.path != null); }
|
|
271
|
-
|
|
272
|
-
/**
|
|
273
|
-
* Returns a neutered HD Node, which removes the private details
|
|
274
|
-
* of an HD Node.
|
|
275
|
-
*
|
|
276
|
-
* A neutered node has no private key, but can be used to derive
|
|
277
|
-
* child addresses and other public data about the HD Node.
|
|
278
|
-
*/
|
|
279
|
-
neuter(): HDNodeVoidWallet {
|
|
280
|
-
return new HDNodeVoidWallet(_guard, this.address, this.publicKey,
|
|
281
|
-
this.parentFingerprint, this.chainCode, this.path, this.index,
|
|
282
|
-
this.depth, this.provider);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* Return the child for %%index%%.
|
|
287
|
-
*/
|
|
288
|
-
deriveChild(_index: Numeric): HDNodeWallet {
|
|
289
|
-
const index = getNumber(_index, "index");
|
|
290
|
-
assertArgument(index <= 0xffffffff, "invalid index", "index", index);
|
|
291
|
-
|
|
292
|
-
// Base path
|
|
293
|
-
let path = this.path;
|
|
294
|
-
if (path) {
|
|
295
|
-
path += "/" + (index & ~HardenedBit);
|
|
296
|
-
if (index & HardenedBit) { path += "'"; }
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const { IR, IL } = ser_I(index, this.chainCode, this.publicKey, this.privateKey);
|
|
300
|
-
const ki = new SigningKey(toBeHex((toBigInt(IL) + BigInt(this.privateKey)) % N, 32));
|
|
301
|
-
|
|
302
|
-
return new HDNodeWallet(_guard, ki, this.fingerprint, hexlify(IR),
|
|
303
|
-
path, index, this.depth + 1, this.mnemonic, this.provider);
|
|
304
|
-
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Return the HDNode for %%path%% from this node.
|
|
309
|
-
*/
|
|
310
|
-
derivePath(path: string): HDNodeWallet {
|
|
311
|
-
return derivePath<HDNodeWallet>(this, path);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
static #fromSeed(_seed: BytesLike, mnemonic: null | Mnemonic): HDNodeWallet {
|
|
315
|
-
assertArgument(isBytesLike(_seed), "invalid seed", "seed", "[REDACTED]");
|
|
316
|
-
|
|
317
|
-
const seed = getBytes(_seed, "seed");
|
|
318
|
-
assertArgument(seed.length >= 16 && seed.length <= 64 , "invalid seed", "seed", "[REDACTED]");
|
|
319
|
-
|
|
320
|
-
const I = getBytes(computeHmac("sha512", MasterSecret, seed));
|
|
321
|
-
const signingKey = new SigningKey(hexlify(I.slice(0, 32)));
|
|
322
|
-
|
|
323
|
-
return new HDNodeWallet(_guard, signingKey, "0x00000000", hexlify(I.slice(32)),
|
|
324
|
-
"m", 0, 0, mnemonic, null);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
/**
|
|
328
|
-
* Creates a new HD Node from %%extendedKey%%.
|
|
329
|
-
*
|
|
330
|
-
* If the %%extendedKey%% will either have a prefix or ``xpub`` or
|
|
331
|
-
* ``xpriv``, returning a neutered HD Node ([[HDNodeVoidWallet]])
|
|
332
|
-
* or full HD Node ([[HDNodeWallet) respectively.
|
|
333
|
-
*/
|
|
334
|
-
static fromExtendedKey(extendedKey: string): HDNodeWallet | HDNodeVoidWallet {
|
|
335
|
-
const bytes = toBeArray(decodeBase58(extendedKey)); // @TODO: redact
|
|
336
|
-
|
|
337
|
-
assertArgument(bytes.length === 82 || encodeBase58Check(bytes.slice(0, 78)) === extendedKey,
|
|
338
|
-
"invalid extended key", "extendedKey", "[ REDACTED ]");
|
|
339
|
-
|
|
340
|
-
const depth = bytes[4];
|
|
341
|
-
const parentFingerprint = hexlify(bytes.slice(5, 9));
|
|
342
|
-
const index = parseInt(hexlify(bytes.slice(9, 13)).substring(2), 16);
|
|
343
|
-
const chainCode = hexlify(bytes.slice(13, 45));
|
|
344
|
-
const key = bytes.slice(45, 78);
|
|
345
|
-
|
|
346
|
-
switch (hexlify(bytes.slice(0, 4))) {
|
|
347
|
-
// Public Key
|
|
348
|
-
case "0x0488b21e": case "0x043587cf": {
|
|
349
|
-
const publicKey = hexlify(key);
|
|
350
|
-
return new HDNodeVoidWallet(_guard, computeAddress(publicKey), publicKey,
|
|
351
|
-
parentFingerprint, chainCode, null, index, depth, null);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Private Key
|
|
355
|
-
case "0x0488ade4": case "0x04358394 ":
|
|
356
|
-
if (key[0] !== 0) { break; }
|
|
357
|
-
return new HDNodeWallet(_guard, new SigningKey(key.slice(1)),
|
|
358
|
-
parentFingerprint, chainCode, null, index, depth, null, null);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
assertArgument(false, "invalid extended key prefix", "extendedKey", "[ REDACTED ]");
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* Creates a new random HDNode.
|
|
367
|
-
*/
|
|
368
|
-
static createRandom(password?: string, path?: string, wordlist?: Wordlist): HDNodeWallet {
|
|
369
|
-
if (password == null) { password = ""; }
|
|
370
|
-
if (path == null) { path = defaultPath; }
|
|
371
|
-
if (wordlist == null) { wordlist = LangEn.wordlist(); }
|
|
372
|
-
const mnemonic = Mnemonic.fromEntropy(randomBytes(16), password, wordlist)
|
|
373
|
-
return HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Create an HD Node from %%mnemonic%%.
|
|
378
|
-
*/
|
|
379
|
-
static fromMnemonic(mnemonic: Mnemonic, path?: string): HDNodeWallet {
|
|
380
|
-
if (!path) { path = defaultPath; }
|
|
381
|
-
return HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Creates an HD Node from a mnemonic %%phrase%%.
|
|
386
|
-
*/
|
|
387
|
-
static fromPhrase(phrase: string, password?: string, path?: string, wordlist?: Wordlist): HDNodeWallet {
|
|
388
|
-
if (password == null) { password = ""; }
|
|
389
|
-
if (path == null) { path = defaultPath; }
|
|
390
|
-
if (wordlist == null) { wordlist = LangEn.wordlist(); }
|
|
391
|
-
const mnemonic = Mnemonic.fromPhrase(phrase, password, wordlist)
|
|
392
|
-
return HDNodeWallet.#fromSeed(mnemonic.computeSeed(), mnemonic).derivePath(path);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
/**
|
|
396
|
-
* Creates an HD Node from a %%seed%%.
|
|
397
|
-
*/
|
|
398
|
-
static fromSeed(seed: BytesLike): HDNodeWallet {
|
|
399
|
-
return HDNodeWallet.#fromSeed(seed, null);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
/**
|
|
404
|
-
* A **HDNodeVoidWallet** cannot sign, but provides access to
|
|
405
|
-
* the children nodes of a [[link-bip-32]] HD wallet addresses.
|
|
406
|
-
*
|
|
407
|
-
* The can be created by using an extended ``xpub`` key to
|
|
408
|
-
* [[HDNodeWallet_fromExtendedKey]] or by
|
|
409
|
-
* [nuetering](HDNodeWallet-neuter) a [[HDNodeWallet]].
|
|
410
|
-
*/
|
|
411
|
-
export class HDNodeVoidWallet extends VoidSigner {
|
|
412
|
-
/**
|
|
413
|
-
* The compressed public key.
|
|
414
|
-
*/
|
|
415
|
-
readonly publicKey!: string;
|
|
416
|
-
|
|
417
|
-
/**
|
|
418
|
-
* The fingerprint.
|
|
419
|
-
*
|
|
420
|
-
* A fingerprint allows quick qay to detect parent and child nodes,
|
|
421
|
-
* but developers should be prepared to deal with collisions as it
|
|
422
|
-
* is only 4 bytes.
|
|
423
|
-
*/
|
|
424
|
-
readonly fingerprint!: string;
|
|
425
|
-
|
|
426
|
-
/**
|
|
427
|
-
* The parent node fingerprint.
|
|
428
|
-
*/
|
|
429
|
-
readonly parentFingerprint!: string;
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* The chaincode, which is effectively a public key used
|
|
433
|
-
* to derive children.
|
|
434
|
-
*/
|
|
435
|
-
readonly chainCode!: string;
|
|
436
|
-
|
|
437
|
-
/**
|
|
438
|
-
* The derivation path of this wallet.
|
|
439
|
-
*
|
|
440
|
-
* Since extended keys do not provider full path details, this
|
|
441
|
-
* may be ``null``, if instantiated from a source that does not
|
|
442
|
-
* enocde it.
|
|
443
|
-
*/
|
|
444
|
-
readonly path!: null | string;
|
|
445
|
-
|
|
446
|
-
/**
|
|
447
|
-
* The child index of this wallet. Values over ``2 *\* 31`` indicate
|
|
448
|
-
* the node is hardened.
|
|
449
|
-
*/
|
|
450
|
-
readonly index!: number;
|
|
451
|
-
|
|
452
|
-
/**
|
|
453
|
-
* The depth of this wallet, which is the number of components
|
|
454
|
-
* in its path.
|
|
455
|
-
*/
|
|
456
|
-
readonly depth!: number;
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* @private
|
|
460
|
-
*/
|
|
461
|
-
constructor(guard: any, address: string, publicKey: string, parentFingerprint: string, chainCode: string, path: null | string, index: number, depth: number, provider: null | Provider) {
|
|
462
|
-
super(address, provider);
|
|
463
|
-
assertPrivate(guard, _guard, "HDNodeVoidWallet");
|
|
464
|
-
|
|
465
|
-
defineProperties<HDNodeVoidWallet>(this, { publicKey });
|
|
466
|
-
|
|
467
|
-
const fingerprint = dataSlice(ripemd160(sha256(publicKey)), 0, 4);
|
|
468
|
-
defineProperties<HDNodeVoidWallet>(this, {
|
|
469
|
-
publicKey, fingerprint, parentFingerprint, chainCode, path, index, depth
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
connect(provider: null | Provider): HDNodeVoidWallet {
|
|
474
|
-
return new HDNodeVoidWallet(_guard, this.address, this.publicKey,
|
|
475
|
-
this.parentFingerprint, this.chainCode, this.path, this.index, this.depth, provider);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
/**
|
|
479
|
-
* The extended key.
|
|
480
|
-
*
|
|
481
|
-
* This key will begin with the prefix ``xpub`` and can be used to
|
|
482
|
-
* reconstruct this neutered key to derive its children addresses.
|
|
483
|
-
*/
|
|
484
|
-
get extendedKey(): string {
|
|
485
|
-
// We only support the mainnet values for now, but if anyone needs
|
|
486
|
-
// testnet values, let me know. I believe current sentiment is that
|
|
487
|
-
// we should always use mainnet, and use BIP-44 to derive the network
|
|
488
|
-
// - Mainnet: public=0x0488B21E, private=0x0488ADE4
|
|
489
|
-
// - Testnet: public=0x043587CF, private=0x04358394
|
|
490
|
-
|
|
491
|
-
assert(this.depth < 256, "Depth too deep", "UNSUPPORTED_OPERATION", { operation: "extendedKey" });
|
|
492
|
-
|
|
493
|
-
return encodeBase58Check(concat([
|
|
494
|
-
"0x0488B21E",
|
|
495
|
-
zpad(this.depth, 1),
|
|
496
|
-
this.parentFingerprint,
|
|
497
|
-
zpad(this.index, 4),
|
|
498
|
-
this.chainCode,
|
|
499
|
-
this.publicKey,
|
|
500
|
-
]));
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Returns true if this wallet has a path, providing a Type Guard
|
|
505
|
-
* that the path is non-null.
|
|
506
|
-
*/
|
|
507
|
-
hasPath(): this is { path: string } { return (this.path != null); }
|
|
508
|
-
|
|
509
|
-
/**
|
|
510
|
-
* Return the child for %%index%%.
|
|
511
|
-
*/
|
|
512
|
-
deriveChild(_index: Numeric): HDNodeVoidWallet {
|
|
513
|
-
const index = getNumber(_index, "index");
|
|
514
|
-
assertArgument(index <= 0xffffffff, "invalid index", "index", index);
|
|
515
|
-
|
|
516
|
-
// Base path
|
|
517
|
-
let path = this.path;
|
|
518
|
-
if (path) {
|
|
519
|
-
path += "/" + (index & ~HardenedBit);
|
|
520
|
-
if (index & HardenedBit) { path += "'"; }
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
const { IR, IL } = ser_I(index, this.chainCode, this.publicKey, null);
|
|
524
|
-
const Ki = SigningKey.addPoints(IL, this.publicKey, true);
|
|
525
|
-
|
|
526
|
-
const address = computeAddress(Ki);
|
|
527
|
-
|
|
528
|
-
return new HDNodeVoidWallet(_guard, address, Ki, this.fingerprint, hexlify(IR),
|
|
529
|
-
path, index, this.depth + 1, this.provider);
|
|
530
|
-
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Return the signer for %%path%% from this node.
|
|
535
|
-
*/
|
|
536
|
-
derivePath(path: string): HDNodeVoidWallet {
|
|
537
|
-
return derivePath<HDNodeVoidWallet>(this, path);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
/*
|
|
542
|
-
export class HDNodeWalletManager {
|
|
543
|
-
#root: HDNodeWallet;
|
|
544
|
-
|
|
545
|
-
constructor(phrase: string, password?: null | string, path?: null | string, locale?: null | Wordlist) {
|
|
546
|
-
if (password == null) { password = ""; }
|
|
547
|
-
if (path == null) { path = "m/44'/60'/0'/0"; }
|
|
548
|
-
if (locale == null) { locale = LangEn.wordlist(); }
|
|
549
|
-
this.#root = HDNodeWallet.fromPhrase(phrase, password, path, locale);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
getSigner(index?: number): HDNodeWallet {
|
|
553
|
-
return this.#root.deriveChild((index == null) ? 0: index);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
*/
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
* Returns the [[link-bip-32]] path for the account at %%index%%.
|
|
560
|
-
*
|
|
561
|
-
* This is the pattern used by wallets like Ledger.
|
|
562
|
-
*
|
|
563
|
-
* There is also an [alternate pattern](getIndexedAccountPath) used by
|
|
564
|
-
* some software.
|
|
565
|
-
*/
|
|
566
|
-
export function getAccountPath(_index: Numeric): string {
|
|
567
|
-
const index = getNumber(_index, "index");
|
|
568
|
-
assertArgument(index >= 0 && index < HardenedBit, "invalid account index", "index", index);
|
|
569
|
-
return `m/44'/60'/${ index }'/0/0`;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
/**
|
|
573
|
-
* Returns the path using an alternative pattern for deriving accounts,
|
|
574
|
-
* at %%index%%.
|
|
575
|
-
*
|
|
576
|
-
* This derivation path uses the //index// component rather than the
|
|
577
|
-
* //account// component to derive sequential accounts.
|
|
578
|
-
*
|
|
579
|
-
* This is the pattern used by wallets like MetaMask.
|
|
580
|
-
*/
|
|
581
|
-
export function getIndexedAccountPath(_index: Numeric): string {
|
|
582
|
-
const index = getNumber(_index, "index");
|
|
583
|
-
assertArgument(index >= 0 && index < HardenedBit, "invalid account index", "index", index);
|
|
584
|
-
return `m/44'/60'/0'/0/${ index}`;
|
|
585
|
-
}
|
|
586
|
-
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @_subsection: api/wallet:JSON Wallets [json-wallets]
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { CBC, pkcs7Strip } from "aes-js";
|
|
6
|
-
|
|
7
|
-
import { getAddress } from "../address/index.js";
|
|
8
|
-
import { pbkdf2 } from "../crypto/index.js";
|
|
9
|
-
import { id } from "../hash/index.js";
|
|
10
|
-
import { getBytes, assertArgument } from "../utils/index.js";
|
|
11
|
-
|
|
12
|
-
import { getPassword, looseArrayify, spelunk } from "./utils.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* The data stored within a JSON Crowdsale wallet is fairly
|
|
17
|
-
* minimal.
|
|
18
|
-
*/
|
|
19
|
-
export type CrowdsaleAccount = {
|
|
20
|
-
privateKey: string;
|
|
21
|
-
address: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Returns true if %%json%% is a valid JSON Crowdsale wallet.
|
|
26
|
-
*/
|
|
27
|
-
export function isCrowdsaleJson(json: string): boolean {
|
|
28
|
-
try {
|
|
29
|
-
const data = JSON.parse(json);
|
|
30
|
-
if (data.encseed) { return true; }
|
|
31
|
-
} catch (error) { }
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// See: https://github.com/ethereum/pyethsaletool
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Before Ethereum launched, it was necessary to create a wallet
|
|
39
|
-
* format for backers to use, which would be used to receive ether
|
|
40
|
-
* as a reward for contributing to the project.
|
|
41
|
-
*
|
|
42
|
-
* The [[link-crowdsale]] format is now obsolete, but it is still
|
|
43
|
-
* useful to support and the additional code is fairly trivial as
|
|
44
|
-
* all the primitives required are used through core portions of
|
|
45
|
-
* the library.
|
|
46
|
-
*/
|
|
47
|
-
export function decryptCrowdsaleJson(json: string, _password: string | Uint8Array): CrowdsaleAccount {
|
|
48
|
-
const data = JSON.parse(json);
|
|
49
|
-
const password = getPassword(_password);
|
|
50
|
-
|
|
51
|
-
// Ethereum Address
|
|
52
|
-
const address = getAddress(spelunk(data, "ethaddr:string!"));
|
|
53
|
-
|
|
54
|
-
// Encrypted Seed
|
|
55
|
-
const encseed = looseArrayify(spelunk(data, "encseed:string!"));
|
|
56
|
-
assertArgument(encseed && (encseed.length % 16) === 0, "invalid encseed", "json", json);
|
|
57
|
-
|
|
58
|
-
const key = getBytes(pbkdf2(password, password, 2000, 32, "sha256")).slice(0, 16);
|
|
59
|
-
|
|
60
|
-
const iv = encseed.slice(0, 16);
|
|
61
|
-
const encryptedSeed = encseed.slice(16);
|
|
62
|
-
|
|
63
|
-
// Decrypt the seed
|
|
64
|
-
const aesCbc = new CBC(key, iv);
|
|
65
|
-
const seed = pkcs7Strip(getBytes(aesCbc.decrypt(encryptedSeed)));
|
|
66
|
-
|
|
67
|
-
// This wallet format is weird... Convert the binary encoded hex to a string.
|
|
68
|
-
let seedHex = "";
|
|
69
|
-
for (let i = 0; i < seed.length; i++) {
|
|
70
|
-
seedHex += String.fromCharCode(seed[i]);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return { address, privateKey: id(seedHex) };
|
|
74
|
-
}
|