|
9 | 9 | * @prop {HDToAddr} toAddr
|
10 | 10 | * @prop {HDToWif} toWif
|
11 | 11 | * @prop {HDToXPrv} toXPrv
|
| 12 | + * @prop {HDToXKeyBytes} toXPrvBytes |
12 | 13 | * @prop {HDToXPub} toXPub
|
| 14 | + * @prop {HDToXKeyBytes} toXPubBytes |
13 | 15 | * @prop {HDUtils} utils
|
14 | 16 | * @prop {HDWipePrivates} wipePrivateData - randomizes private key buffer in-place
|
15 | 17 | * @prop {Number} HARDENED_OFFSET - 0x80000000
|
|
22 | 24 | * @prop {HDCreateAccountKey} _createAccount - helper
|
23 | 25 | * @prop {HDCreateXKey} _createXKey - helper
|
24 | 26 | * @prop {HDDeriveHelper} _derive - helper
|
| 27 | + * @prop {HDToXBytes} _toXBytes - helper |
25 | 28 | */
|
26 | 29 |
|
27 | 30 | /**
|
@@ -295,20 +298,69 @@ var DashHd = ("object" === typeof module && exports) || {};
|
295 | 298 | };
|
296 | 299 |
|
297 | 300 | DashHd.toXPrv = async function (hdkey) {
|
298 |
| - if (!hdkey.privateKey) { |
299 |
| - return null; |
300 |
| - } |
301 |
| - |
| 301 | + //@ts-ignore - will throw if null |
| 302 | + let xprvBytes = DashHd._toXBytes(hdkey, hdkey.privateKey); |
302 | 303 | //@ts-ignore - wth?
|
303 |
| - return await Utils.encodeXPrv(serialize(hdkey, hdkey.privateKey)); |
| 304 | + let xprv = await Utils.encodeXPrv(xprvBytes); |
| 305 | + return xprv; |
| 306 | + }; |
| 307 | + |
| 308 | + // TODO - missing custom version |
| 309 | + DashHd.toXPrvBytes = function (hdkey) { |
| 310 | + //@ts-ignore - will throw if null |
| 311 | + let xprvPart = DashHd._toXBytes(hdkey, hdkey.privateKey); |
| 312 | + let xprvBytes = new Uint8Array(xprvPart.length + 4); |
| 313 | + let xkeyDv = new DataView(xprvBytes.buffer); |
| 314 | + xkeyDv.setUint32(0, DashHd.MAINNET.private, BUFFER_BE); |
| 315 | + xprvBytes.set(xprvPart, 4); |
| 316 | + return xprvBytes; |
304 | 317 | };
|
305 | 318 |
|
306 | 319 | DashHd.toXPub = async function (hdkey) {
|
307 |
| - if (!hdkey.publicKey) { |
308 |
| - throw new Error("Missing public key"); |
| 320 | + let xpubBytes = DashHd._toXBytes(hdkey, hdkey.publicKey); |
| 321 | + let xpub = await Utils.encodeXPub(xpubBytes); |
| 322 | + return xpub; |
| 323 | + }; |
| 324 | + |
| 325 | + // TODO - missing custom version |
| 326 | + DashHd.toXPubBytes = function (hdkey) { |
| 327 | + let xpubPart = DashHd._toXBytes(hdkey, hdkey.publicKey); |
| 328 | + let xpubBytes = new Uint8Array(xpubPart.length + 4); |
| 329 | + let xkeyDv = new DataView(xpubBytes.buffer); |
| 330 | + xkeyDv.setUint32(0, DashHd.MAINNET.private, BUFFER_BE); |
| 331 | + xpubBytes.set(xpubPart, 4); |
| 332 | + return xpubBytes; |
| 333 | + }; |
| 334 | + |
| 335 | + DashHd._toXBytes = function (hdkey, keyBytes) { |
| 336 | + if (!keyBytes) { |
| 337 | + throw new Error("missing key bytes"); |
309 | 338 | }
|
| 339 | + // version(4) is part of Base58Check (perhaps mistakenly) |
| 340 | + // depth(1) + fingerprint(4) + index(4) + chain(32) + key(1 + 32) |
| 341 | + let xkey = new Uint8Array(XKEY_SIZE); |
| 342 | + let xkeyDv = new DataView(xkey.buffer); |
| 343 | + |
| 344 | + xkeyDv.setUint8(0, hdkey.depth); |
310 | 345 |
|
311 |
| - return await Utils.encodeXPub(serialize(hdkey, hdkey.publicKey)); |
| 346 | + let fingerprint = 0x00000000; |
| 347 | + if (hdkey.depth > 0) { |
| 348 | + fingerprint = hdkey.parentFingerprint; |
| 349 | + } |
| 350 | + xkeyDv.setUint32(1, fingerprint, BUFFER_BE); |
| 351 | + xkeyDv.setUint32(5, hdkey.index, BUFFER_BE); |
| 352 | + |
| 353 | + xkey.set(hdkey.chainCode, 9); |
| 354 | + |
| 355 | + let keyStart = 41; |
| 356 | + let isPrivate = 32 === keyBytes.length; |
| 357 | + if (isPrivate) { |
| 358 | + xkey[keyStart] = 0x00; |
| 359 | + keyStart += 1; |
| 360 | + } |
| 361 | + xkey.set(keyBytes, keyStart); |
| 362 | + |
| 363 | + return xkey; |
312 | 364 | };
|
313 | 365 |
|
314 | 366 | // IMPORTANT: never allow `await` (or other async) between writing to
|
@@ -607,37 +659,6 @@ var DashHd = ("object" === typeof module && exports) || {};
|
607 | 659 | }
|
608 | 660 | }
|
609 | 661 |
|
610 |
| - /** |
611 |
| - * @param {HDKey} hdkey - TODO attach to hdkey |
612 |
| - * @param {Uint8Array} keyBytes |
613 |
| - */ |
614 |
| - function serialize(hdkey, keyBytes) { |
615 |
| - // version(4) + depth(1) + fingerprint(4) + index(4) + chain(32) + key(1 + 32) |
616 |
| - let xkey = new Uint8Array(XKEY_SIZE); |
617 |
| - let xkeyDv = new DataView(xkey.buffer); |
618 |
| - |
619 |
| - xkeyDv.setUint8(0, hdkey.depth); |
620 |
| - |
621 |
| - let fingerprint = 0x00000000; |
622 |
| - if (hdkey.depth > 0) { |
623 |
| - fingerprint = hdkey.parentFingerprint; |
624 |
| - } |
625 |
| - xkeyDv.setUint32(1, fingerprint, BUFFER_BE); |
626 |
| - xkeyDv.setUint32(5, hdkey.index, BUFFER_BE); |
627 |
| - |
628 |
| - xkey.set(hdkey.chainCode, 9); |
629 |
| - |
630 |
| - let keyStart = 41; |
631 |
| - let isPrivate = 32 === keyBytes.length; |
632 |
| - if (isPrivate) { |
633 |
| - xkey[keyStart] = 0x00; |
634 |
| - keyStart += 1; |
635 |
| - } |
636 |
| - xkey.set(keyBytes, keyStart); |
637 |
| - |
638 |
| - return xkey; |
639 |
| - } |
640 |
| - |
641 | 662 | DashHd.HARDENED_OFFSET = HARDENED_OFFSET;
|
642 | 663 | })(("object" === typeof window && window) || {}, DashHd);
|
643 | 664 | if ("object" === typeof module) {
|
@@ -794,6 +815,19 @@ if ("object" === typeof module) {
|
794 | 815 | * @returns {Promise<String>}
|
795 | 816 | */
|
796 | 817 |
|
| 818 | +/** |
| 819 | + * @callback HDToXKeyBytes |
| 820 | + * @param {HDKey} hdkey |
| 821 | + * @returns {Uint8Array} |
| 822 | + */ |
| 823 | + |
| 824 | +/** |
| 825 | + * @callback HDToXBytes |
| 826 | + * @param {HDKey} hdkey |
| 827 | + * @param {Uint8Array?} keyBytes |
| 828 | + * @returns {Uint8Array} |
| 829 | + */ |
| 830 | + |
797 | 831 | /**
|
798 | 832 | * @callback HDToWif
|
799 | 833 | * @param {Uint8Array} privBytes
|
|
0 commit comments