@@ -126,33 +126,7 @@ export class Key {
126126 break ;
127127 case 'extendedPrivateKey' :
128128 $ . checkArgument ( x , 'Need to provide opts.seedData' ) ;
129-
130- let xpriv ;
131- try {
132- xpriv = new Bitcore . HDPrivateKey ( x ) ;
133- } catch ( e ) {
134- throw new Error ( 'Invalid argument' ) ;
135- }
136- for ( const algo of SUPPORTED_ALGOS ) {
137- const params = { algo }
138- this . #setFingerprint( { value : xpriv . fingerPrint . toString ( 'hex' ) , ...params } ) ;
139- if ( opts . password ) {
140- this . #setPrivKeyEncrypted( {
141- value : sjcl . encrypt (
142- opts . password ,
143- xpriv . toString ( ) ,
144- opts
145- ) ,
146- ...params
147- } ) ;
148- const xPrivKeyEncrypted = this . #getPrivKeyEncrypted( params ) ;
149- if ( ! xPrivKeyEncrypted ) throw new Error ( 'Could not encrypt' ) ;
150- } else {
151- this . #setPrivKey( { value : xpriv . toString ( ) , ...params } ) ;
152- }
153- }
154- this . #mnemonic = null ;
155- this . #mnemonicHasPassphrase = null ;
129+ this . setFromExtendedPrivateKey ( x , opts ) ;
156130 break ;
157131 case 'object' :
158132 $ . shouldBeObject ( x , 'Need to provide an object at opts.seedData' ) ;
@@ -240,7 +214,8 @@ export class Key {
240214 m ,
241215 opts : { passphrase ?: string ; password ?: string ; sjclOpts ?: any , algo ?: string }
242216 ) {
243- for ( const algo of SUPPORTED_ALGOS ) {
217+ const algos = opts . algo ? [ opts . algo ] : SUPPORTED_ALGOS ;
218+ for ( const algo of algos ) {
244219 const xpriv = m . toHDPrivateKey ( opts . passphrase , NETWORK , ALGO_TO_KEY_TYPE [ algo ] ) ;
245220 this . #setFingerprint( { value : xpriv . fingerPrint . toString ( 'hex' ) , algo } ) ;
246221
@@ -267,6 +242,78 @@ export class Key {
267242 }
268243 }
269244
245+ private setFromExtendedPrivateKey ( extendedPrivateKey , opts : { password ?: string ; algo ?: string } ) {
246+ let xpriv ;
247+ if ( this . #mnemonic || this . #mnemonicEncrypted) {
248+ throw new Error ( 'Set key from existing mnemonic' )
249+ }
250+ try {
251+ xpriv = new Bitcore . HDPrivateKey ( extendedPrivateKey ) ;
252+ } catch ( e ) {
253+ throw new Error ( 'Invalid argument' ) ;
254+ }
255+ const algos = opts . algo ? [ opts . algo ] : SUPPORTED_ALGOS ;
256+ for ( const algo of algos ) {
257+ const params = { algo }
258+ this . #setFingerprint( { value : xpriv . fingerPrint . toString ( 'hex' ) , ...params } ) ;
259+ if ( opts . password ) {
260+ this . #setPrivKeyEncrypted( {
261+ value : sjcl . encrypt (
262+ opts . password ,
263+ xpriv . toString ( ) ,
264+ opts
265+ ) ,
266+ ...params
267+ } ) ;
268+ const xPrivKeyEncrypted = this . #getPrivKeyEncrypted( params ) ;
269+ if ( ! xPrivKeyEncrypted ) throw new Error ( 'Could not encrypt' ) ;
270+ } else {
271+ this . #setPrivKey( { value : xpriv . toString ( ) , ...params } ) ;
272+ }
273+ }
274+ this . #mnemonic = null ;
275+ this . #mnemonicHasPassphrase = null ;
276+ }
277+
278+ // Adds an additonal supported key to the object
279+ // By default it creates the new key based on the existing bitcoin key (ECDSA)
280+ addKeyByAlgorithm ( algo , opts : { passphrase ?: string ; password ?: string ; sjclOpts ?: any , algo ?: string , existingAlgo ?: string } ) {
281+ const existingAlgo = opts . existingAlgo || 'ECDSA' ;
282+ if ( this . #mnemonic) {
283+ if ( this . #mnemonicHasPassphrase) {
284+ if ( ! opts . passphrase ) {
285+ throw new Error ( 'Missing Passphrase' )
286+ }
287+ this . setFromMnemonic ( this . #mnemonic, { passphrase : opts . passphrase , algo } )
288+ } else {
289+ this . setFromMnemonic ( this . #mnemonic, { algo } ) ;
290+ }
291+ } else if ( this . #mnemonicEncrypted) {
292+ if ( ! opts . password ) {
293+ throw new Error ( 'Missing Password' )
294+ }
295+ if ( this . #mnemonicHasPassphrase) {
296+ if ( ! opts . passphrase ) {
297+ throw new Error ( 'Missing Passphrase' )
298+ }
299+ this . setFromMnemonic ( this . #mnemonic, { passphrase : opts . passphrase , algo, password : opts . password } )
300+ } else {
301+ this . setFromMnemonic ( this . #mnemonic, { algo, password : opts . password } ) ;
302+ }
303+ } else if ( this . #getPrivKeyEncrypted( { algo : existingAlgo } ) ) {
304+ if ( ! opts . password ) {
305+ throw new Error ( 'Missing Password' )
306+ }
307+ const xPriv = sjcl . decrypt ( opts . password , this . #getPrivKeyEncrypted( { algo : existingAlgo } ) ) ;
308+ this . setFromExtendedPrivateKey ( xPriv , { algo, password : opts . password } ) ;
309+ } else if ( this . #getPrivKey( { algo : existingAlgo } ) ) {
310+ const xPriv = this . #getPrivKey( { algo : existingAlgo } ) ;
311+ this . setFromExtendedPrivateKey ( xPriv , { algo } )
312+ } else {
313+ throw new Error ( `Missing Priv Key ${ existingAlgo } ` ) ;
314+ }
315+ }
316+
270317 toObj ( ) {
271318 const ret = {
272319 xPrivKey : this . #xPrivKey,
0 commit comments