14
14
* @prop {HDToXKeyBytes } toXPrvBytes
15
15
* @prop {HDToXPub } toXPub
16
16
* @prop {HDToXKeyBytes } toXPubBytes
17
- * @prop {HDUtils } utils
17
+ * @prop {HDUtils } _utils
18
18
* @prop {HDWipePrivates } wipePrivateData - randomizes private key buffer in-place
19
19
* @prop {HDToPublic } toPublic - returns public key
20
20
* @prop {Number } HARDENED_OFFSET - 0x80000000
61
61
62
62
/**
63
63
* @typedef HDKeyOptions
64
- * @prop {HDVersions ? } [versions]
64
+ * @prop {HDVersionsOption ? } [versions]
65
65
* @prop {Number? } [depth]
66
66
* @prop {Number? } [parentFingerprint]
67
67
* @prop {Number } index
@@ -106,25 +106,41 @@ var DashHd = ("object" === typeof module && exports) || {};
106
106
/**
107
107
* @param {Uint8Array } keyBytes
108
108
* @param {Object } opts
109
- * @param {Number } [opts.version]
109
+ * @param {String|Uint32 } [opts.version]
110
110
*/
111
111
Utils . encodeXPrv = async function ( keyBytes , opts ) {
112
112
let version = "xprv" ;
113
113
if ( opts ?. version ) {
114
- version = opts ?. version . toString ( 16 ) ;
115
- version = version . padStart ( 8 , "0" ) ;
114
+ if ( opts . version === "tprv" ) {
115
+ version = opts . version ;
116
+ } else {
117
+ // intended for numbers, but won't break hex strings
118
+ version = opts . version . toString ( 16 ) ;
119
+ version = version . padStart ( 8 , "0" ) ;
120
+ }
116
121
}
117
122
//@ts -ignore
118
123
return await DashKeys . encodeKey ( keyBytes , { version } ) ;
119
124
} ;
120
125
121
126
/**
122
127
* @param {Uint8Array } keyBytes
123
- * TODO - pass tpub
128
+ * @param {Object } opts
129
+ * @param {String|Uint32 } [opts.version]
124
130
*/
125
- Utils . encodeXPub = async function ( keyBytes ) {
131
+ Utils . encodeXPub = async function ( keyBytes , opts ) {
132
+ let version = "xpub" ;
133
+ if ( opts ?. version ) {
134
+ if ( opts . version === "tpub" ) {
135
+ version = opts . version ;
136
+ } else {
137
+ // intended for numbers, but won't break hex strings
138
+ version = opts . version . toString ( 16 ) ;
139
+ version = version . padStart ( 8 , "0" ) ;
140
+ }
141
+ }
126
142
//@ts -ignore
127
- return await DashKeys . encodeKey ( keyBytes , { version : "xpub" } ) ;
143
+ return await DashKeys . encodeKey ( keyBytes , { version : version } ) ;
128
144
} ;
129
145
/** @type {HDKeyTweak } */
130
146
Utils . privateKeyTweakAdd = async function ( privateKeyCopy , tweak ) {
@@ -247,6 +263,7 @@ var DashHd = ("object" === typeof module && exports) || {};
247
263
let XKEY_SIZE = 74 ;
248
264
let XKEY_DEPTH = 4 ; // m/44'/5'/0'/<0>[/0]
249
265
266
+ //@ts -ignore
250
267
DashHd . _utils = Utils ;
251
268
252
269
// Bitcoin defaults hard-coded by default.
@@ -296,19 +313,21 @@ var DashHd = ("object" === typeof module && exports) || {};
296
313
if ( privBytes . length !== 32 ) {
297
314
throw new Error ( "expected a private key (size 32)" ) ;
298
315
}
299
- return await DashKeys . encodeKey ( privBytes ) ;
316
+ return await DashKeys . encodeKey ( privBytes , opts ) ;
300
317
} ;
301
318
302
- DashHd . toXPrv = async function ( hdkey ) {
319
+ DashHd . toXPrv = async function ( hdkey , opts ) {
303
320
//@ts -ignore - will throw if null
304
321
let xprvBytes = DashHd . _toXBytes ( hdkey , hdkey . privateKey ) ;
305
322
//@ts -ignore - wth?
306
- let xprv = await Utils . encodeXPrv ( xprvBytes ) ;
323
+ let xprv = await Utils . encodeXPrv ( xprvBytes , opts ) ;
307
324
return xprv ;
308
325
} ;
309
326
310
327
// TODO - missing custom version
311
328
DashHd . toXPrvBytes = function ( hdkey , opts ) {
329
+ /** @type {Number } */
330
+ //@ts -ignore
312
331
let version = opts ?. version || DashHd . MAINNET . private ;
313
332
314
333
//@ts -ignore - will throw if null
@@ -320,14 +339,28 @@ var DashHd = ("object" === typeof module && exports) || {};
320
339
return xprvBytes ;
321
340
} ;
322
341
323
- DashHd . toXPub = async function ( hdkey ) {
342
+ DashHd . toXPub = async function ( hdkey , opts ) {
324
343
let xpubBytes = DashHd . _toXBytes ( hdkey , hdkey . publicKey ) ;
325
- let xpub = await Utils . encodeXPub ( xpubBytes ) ;
344
+ let xpub = await Utils . encodeXPub ( xpubBytes , opts ) ;
326
345
return xpub ;
327
346
} ;
328
347
329
348
DashHd . toXPubBytes = function ( hdkey , opts ) {
330
- let version = opts ?. version || DashHd . MAINNET . public ;
349
+ /** @type {Uint32 } */
350
+ //@ts -ignore - it's a number, I promise
351
+ let version = DashHd . MAINNET . public ;
352
+ if ( opts ?. version ) {
353
+ let [ _ , versionUint32 ] = // jshint ignore:line
354
+ _versionToTuple (
355
+ opts . version ,
356
+ "xpub" ,
357
+ //@ts -ignore - it's a number, I promise
358
+ DashHd . MAINNET . public ,
359
+ "tpub" ,
360
+ DashHd . TESTNET . public ,
361
+ ) ;
362
+ version = versionUint32 ;
363
+ }
331
364
332
365
let xpubPart = DashHd . _toXBytes ( hdkey , hdkey . publicKey ) ;
333
366
let xpubBytes = new Uint8Array ( xpubPart . length + 4 ) ;
@@ -605,11 +638,17 @@ var DashHd = ("object" === typeof module && exports) || {};
605
638
publicKey = key ;
606
639
}
607
640
608
- let xprvHex = "0x0" + versions . private . toString ( 16 ) ;
609
- let xpubHex = "0x0" + versions . public . toString ( 16 ) ;
610
641
if ( publicKey ) {
642
+ let [ xpubHex , xpubUint32 ] = _versionToTuple (
643
+ versions . public ,
644
+ "xpub" ,
645
+ //@ts -ignore - it's a number, I promise
646
+ DashHd . MAINNET . public ,
647
+ "tpub" ,
648
+ DashHd . TESTNET . public ,
649
+ ) ;
611
650
assert (
612
- version === versions . public ,
651
+ version === xpubUint32 ,
613
652
`Version mismatch: version does not match ${ xpubHex } (public)` ,
614
653
) ;
615
654
// at one point xy pubs (1 + 64 bytes) were allowed (per spec)
@@ -619,8 +658,16 @@ var DashHd = ("object" === typeof module && exports) || {};
619
658
publicKey = await Utils . publicKeyNormalize ( publicKey ) ;
620
659
}
621
660
} else {
661
+ let [ xprvHex , xprvUint32 ] = _versionToTuple (
662
+ versions . private ,
663
+ "xprv" ,
664
+ //@ts -ignore - it's a number, I promise
665
+ DashHd . MAINNET . private ,
666
+ "tprv" ,
667
+ DashHd . TESTNET . private ,
668
+ ) ;
622
669
assert (
623
- version === versions . private ,
670
+ version === xprvUint32 ,
624
671
`Version mismatch: version does not match ${ xprvHex } (private)` ,
625
672
) ;
626
673
publicKey = await Utils . toPublicKey ( privateKey ) ;
@@ -652,6 +699,33 @@ var DashHd = ("object" === typeof module && exports) || {};
652
699
return hdkey ;
653
700
} ;
654
701
702
+ /**
703
+ *
704
+ * @param {String|Number } version
705
+ * @param {String } mainStr - 'xprv'|'xpub'
706
+ * @param {Number } mainInt - DashHd.MAINNET.private|DashHd.MAINNET.public
707
+ * @param {String } testStr - 'tprv'|'tpub'
708
+ * @param {Number } testInt - DashHd.TESTNET.private|DashHd.TESTNET.publi c
709
+ * @returns {[String, Number] }
710
+ */
711
+ function _versionToTuple ( version , mainStr , mainInt , testInt , testStr ) {
712
+ let isMainnet = version === mainStr || version === "mainnet" ;
713
+ let isTestnet = version === testStr || version === "testnet" ;
714
+ if ( isMainnet ) {
715
+ version = mainInt ;
716
+ } else if ( isTestnet ) {
717
+ version = testInt ;
718
+ }
719
+ // intended for uint32, but doesn't break hex
720
+ let xkeyHex = version . toString ( 16 ) ;
721
+ xkeyHex = xkeyHex . padStart ( 8 , "0" ) ;
722
+ let xkeyUint32 = parseInt ( xkeyHex , 16 ) ;
723
+ xkeyUint32 = xkeyUint32 >>> 0 ; /* jshint ignore:line */ // coerce uint32
724
+ xkeyHex = `0x${ xkeyHex } ` ;
725
+
726
+ return [ xkeyHex , xkeyUint32 ] ;
727
+ }
728
+
655
729
DashHd . toId = async function ( hdkey ) {
656
730
let idBytes = await DashHd . toIdBytes ( hdkey ) ;
657
731
let id = Utils . bytesToBase64Url ( idBytes ) ;
@@ -721,8 +795,14 @@ if ("object" === typeof module) {
721
795
722
796
/**
723
797
* @typedef HDVersions
724
- * @prop {Number } private - 32-bit (4-byte) int (encodes to 'xprv' in base58)
725
- * @prop {Number } public - 32-bit (4-byte) int (encodes to 'xpub' in base58)
798
+ * @prop {Uint32 } private - 'mainnet', 'testnet', 'xprv' or 'tprv', or 4-byte hex or uint32
799
+ * @prop {Uint32 } public - 'mainnet', 'testnet', 'xpub' or 'tpub', or 4-byte hex or uint32
800
+ */
801
+
802
+ /**
803
+ * @typedef HDVersionsOption
804
+ * @prop {Uint32|String } [private] - 'mainnet', 'testnet', 'xprv' or 'tprv', or 4-byte hex or uint32
805
+ * @prop {Uint32|String } [public] - 'mainnet', 'testnet', 'xpub' or 'tpub', or 4-byte hex or uint32
726
806
*/
727
807
728
808
/**
@@ -825,8 +905,7 @@ if ("object" === typeof module) {
825
905
826
906
/**
827
907
* @typedef HDFromXKeyOptions
828
- * @prop {HDVersions } [versions]
829
- * @prop {String } xkey - base58check-encoded xkey
908
+ * @prop {HDVersionsOption } [versions]
830
909
* @prop {Boolean } [bip32] - allow non-account depths
831
910
* @prop {Boolean } [normalizePublicKey]
832
911
* returns {Promise<HDKey>}
@@ -843,7 +922,7 @@ if ("object" === typeof module) {
843
922
* @typedef HDFromSeedOptions
844
923
* @prop {Number } [purpose] - 44 (BIP-44) by default
845
924
* @prop {Number } [coinType] - 5 (DASH) by default
846
- * @prop {HDVersions } [versions] - mainnet ('xprv', 'xpub') by default
925
+ * @prop {HDVersionsOption } [versions] - mainnet ('xprv', 'xpub') by default
847
926
*/
848
927
849
928
/**
@@ -904,12 +983,16 @@ if ("object" === typeof module) {
904
983
/**
905
984
* @callback HDToXPrv
906
985
* @param {HDKey } hdkey
986
+ * @param {Object } [opts]
987
+ * @param {String|Uint32 } [opts.version]
907
988
* @returns {Promise<String> }
908
989
*/
909
990
910
991
/**
911
992
* @callback HDToXPub
912
993
* @param {HDKey } hdkey
994
+ * @param {Object } [opts]
995
+ * @param {String|Uint32 } [opts.version]
913
996
* @returns {Promise<String> }
914
997
*/
915
998
@@ -966,3 +1049,7 @@ if ("object" === typeof module) {
966
1049
* @callback HDWipePrivates
967
1050
* @param {HDKey } hdkey
968
1051
*/
1052
+
1053
+ /**
1054
+ * @typedef {Number } Uint32
1055
+ */
0 commit comments