@@ -98,6 +98,38 @@ const getHDNodeAndVerify = function(xprv, expectedXpub) {
98
98
return node ;
99
99
} ;
100
100
101
+ /**
102
+ * Prints the recovery transaction information and prompt for the confirmation as well as the key, if needed to.
103
+ * @param recoveryRequest The recovery transansaction request object.
104
+ * @param key The provided private key of the wallet.
105
+ * @param outputs The outputs of the transaction.
106
+ * @param skipConfirm The boolean value that indicates to whether or not to prompt the user to confirm the transaction.
107
+ * @returns The private key of the wallet.
108
+ */
109
+ const promptForConfirmatioAndKey = function ( recoveryRequest , key , outputs , skipConfirm ) {
110
+ const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
111
+ confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
112
+
113
+ if ( ! key ) {
114
+ console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
115
+ key = prompt ( ) ;
116
+ }
117
+
118
+ return key ;
119
+ }
120
+
121
+ /**
122
+ * Gets the backup private key that can be used to sign the transaction.
123
+ * @param key The provided private key.
124
+ * @param expectedXpub The public key specified with the request.
125
+ * @returns The private key to sign the transaction.
126
+ */
127
+ const getBackupSigningKey = function ( key , expectedXpub ) {
128
+ const backupKeyNode = getHDNodeAndVerify ( key , expectedXpub ) ;
129
+
130
+ return backupKeyNode . keyPair . getPrivateKeyBuffer ;
131
+ }
132
+
101
133
const handleSignUtxo = function ( recoveryRequest , key , skipConfirm ) {
102
134
const network = utxoNetworks [ recoveryRequest . coin ] ;
103
135
const decimals = coinDecimals [ recoveryRequest . coin ] ;
@@ -113,13 +145,8 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
113
145
address : utxoLib . address . fromOutputScript ( out . script , network ) ,
114
146
amount : ( new BN ( out . value ) ) . div ( TEN . pow ( decimals ) ) . toString ( )
115
147
} ) ) ;
116
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
117
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
118
-
119
- if ( ! key ) {
120
- console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
121
- key = prompt ( ) ;
122
- }
148
+
149
+ key = promptForConfirmatioAndKey ( recoveryRequest , key , outputs , skipConfirm ) ;
123
150
124
151
const backupKeyNode = getHDNodeAndVerify ( key , recoveryRequest . backupKey ) ;
125
152
@@ -179,31 +206,39 @@ const handleHalfSignEth = function(recoveryRequest, key, skipConfirm, basecoin)
179
206
}
180
207
181
208
const handleSignEthereum = function ( recoveryRequest , key , skipConfirm ) {
209
+ return signEthTx ( recoveryRequest , key , skipConfirm , false ) ;
210
+ } ;
211
+
212
+ /**
213
+ * Signs an Ethereum transaction.
214
+ * @param recoveryRequest The recovery request object.
215
+ * @param key The provided private key of the wallet.
216
+ * @param kipConfirm The boolean value that indicates to whether or not to prompt the user to confirm the transaction.
217
+ * @param isCoinToken The boolean value that indicates if the transaction is for erc20 or ETH.
218
+ * @returns The 'hex' value of the signed transaction.
219
+ */
220
+ const signEthTx = function ( recoveryRequest , key , skipConfirm , isCoinToken ) {
182
221
const EthTx = require ( 'ethereumjs-tx' ) ;
183
222
184
223
const txHex = getTransactionHexFromRequest ( recoveryRequest ) ;
185
224
const transaction = new EthTx ( txHex ) ;
186
- const decimals = coinDecimals [ recoveryRequest . coin ] ;
187
225
188
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
189
226
const txData = transaction . data ;
227
+
190
228
const outputs = [ {
191
229
address : '0x' + txData . slice ( 16 , 36 ) . toString ( 'hex' ) ,
192
- amount : ( new BN ( txData . slice ( 36 , 68 ) . toString ( 'hex' ) , 16 ) ) . div ( TEN . pow ( decimals ) )
230
+ amount : new BN ( txData . slice ( 36 , 68 ) . toString ( 'hex' ) , 16 )
193
231
} ] ;
194
232
195
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
196
-
197
- if ( ! key ) {
198
- console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
199
- key = prompt ( ) ;
233
+ // if request is for ETH, need to correct the amount decimals.
234
+ if ( ! isCoinToken ) {
235
+ const decimals = coinDecimals [ recoveryRequest . coin ] ;
236
+ outputs [ 0 ] . amount = outputs [ 0 ] . amount . div ( TEN . pow ( decimals ) ) ;
200
237
}
201
238
202
- const backupKeyNode = getHDNodeAndVerify ( key , recoveryRequest . backupKey ) ;
203
-
204
- const backupSigningKey = backupKeyNode . keyPair . getPrivateKeyBuffer ( ) ;
239
+ key = promptForConfirmatioAndKey ( recoveryRequest , key , outputs , skipConfirm ) ;
205
240
206
- transaction . sign ( backupSigningKey ) ;
241
+ transaction . sign ( getBackupSigningKey ( key , recoveryRequest . backupKey ) ) ;
207
242
208
243
return transaction . serialize ( ) . toString ( 'hex' ) ;
209
244
} ;
@@ -215,24 +250,16 @@ const handleSignTrx = function(recoveryRequest, key, skipConfirm) {
215
250
const builder = new accountLib . TransactionBuilder ( { coinName : coin } ) ;
216
251
builder . from ( txHex ) ;
217
252
218
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
219
-
220
253
const outputs = builder . build ( ) . destinations . map ( d => {
221
254
return {
222
255
address : d . address ,
223
256
amount : d . value . toString ( 10 )
224
257
} ;
225
258
} ) ;
226
259
227
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
228
-
229
- if ( ! key ) {
230
- console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
231
- key = prompt ( ) ;
232
- }
260
+ key = promptForConfirmatioAndKey ( recoveryRequest , key , outputs , skipConfirm ) ;
233
261
234
- const backupKeyNode = getHDNodeAndVerify ( key , recoveryRequest . backupKey ) ;
235
- builder . sign ( { key : backupKeyNode . keyPair . getPrivateKeyBuffer ( ) } ) ;
262
+ builder . sign ( { key : getBackupSigningKey ( key , recoveryRequest . backupKey ) } ) ;
236
263
return JSON . stringify ( builder . build ( ) . toJson ( ) ) ;
237
264
} ;
238
265
@@ -252,25 +279,16 @@ const handleSignEos = function(recoveryRequest, key, skipConfirm) {
252
279
253
280
const { recipient, amount } = utils . deserializeEOSTransaction ( EosJs , packed_trx ) ;
254
281
255
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
256
-
257
282
const outputs = [ {
258
283
address : recipient ,
259
284
amount : new BN ( amount )
260
285
} ] ;
261
286
262
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
263
-
264
- if ( ! key ) {
265
- console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
266
- key = prompt ( ) ;
267
- }
268
-
269
- const backupKeyNode = getHDNodeAndVerify ( key , recoveryRequest . backupKey ) ;
287
+ key = promptForConfirmatioAndKey ( recoveryRequest , key , outputs , skipConfirm ) ;
270
288
271
289
const dataToSign = utils . getEOSSignatureData ( packed_trx , chainId ) ;
272
290
const signBuffer = Buffer . from ( dataToSign , 'hex' ) ;
273
- const privateKeyBuffer = backupKeyNode . keyPair . getPrivateKeyBuffer ( ) ;
291
+ const privateKeyBuffer = getBackupSigningKey ( key , recoveryRequest . backupKey ) ;
274
292
const signature = ecc . Signature . sign ( signBuffer , privateKeyBuffer ) . toString ( ) ;
275
293
276
294
eosTx . signatures . push ( signature ) ;
@@ -289,19 +307,13 @@ const handleSignXrp = function(recoveryRequest, key, skipConfirm) {
289
307
290
308
const decimals = coinDecimals [ recoveryRequest . coin ] ;
291
309
const transaction = rippleParse . decode ( txHex ) ;
292
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
293
310
294
311
const outputs = [ {
295
312
address : transaction . Destination ,
296
313
amount : ( new BN ( transaction . Amount ) ) . div ( TEN . pow ( decimals ) )
297
314
} ] ;
298
315
299
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
300
-
301
- if ( ! key ) {
302
- console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
303
- key = prompt ( ) ;
304
- }
316
+ key = promptForConfirmatioAndKey ( recoveryRequest , key , outputs , skipConfirm ) ;
305
317
306
318
const backupKeyNode = getHDNodeAndVerify ( key , recoveryRequest . backupKey ) ;
307
319
@@ -321,11 +333,8 @@ const handleSignXlm = function(recoveryRequest, key, skipConfirm) {
321
333
stellar . Network . useTestNetwork ( ) ;
322
334
}
323
335
324
- const decimals = coinDecimals [ recoveryRequest . coin ] ;
325
-
326
336
const txHex = getTransactionHexFromRequest ( recoveryRequest ) ;
327
337
const transaction = new stellar . Transaction ( txHex ) ;
328
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
329
338
330
339
if ( transaction . operations . length !== 1 ) {
331
340
throw new Error ( 'Recovery transaction is trying to perform multiple operations - aborting' ) ;
@@ -340,12 +349,7 @@ const handleSignXlm = function(recoveryRequest, key, skipConfirm) {
340
349
amount : transaction . operations [ 0 ] . amount || transaction . operations [ 0 ] . startingBalance
341
350
} ] ;
342
351
343
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
344
-
345
- if ( ! key ) {
346
- console . log ( 'Please enter the private key of the wallet for signing: ' ) ;
347
- key = prompt ( ) ;
348
- }
352
+ key = promptForConfirmatioAndKey ( recoveryRequest , key , outputs , skipConfirm ) ;
349
353
350
354
let backupKeypair ;
351
355
@@ -359,38 +363,13 @@ const handleSignXlm = function(recoveryRequest, key, skipConfirm) {
359
363
throw new Error ( 'provided private key does not match public key specified with recovery request' ) ;
360
364
}
361
365
362
- transaction . sign ( stellar . Keypair . fromSecret ( key ) ) ;
366
+ transaction . sign ( backupKeypair ) ;
363
367
364
368
return transaction . toEnvelope ( ) . toXDR ( 'base64' ) ;
365
369
} ;
366
370
367
371
const handleSignErc20 = function ( recoveryRequest , key , skipConfirm ) {
368
- const EthTx = require ( 'ethereumjs-tx' ) ;
369
-
370
- const txHex = getTransactionHexFromRequest ( recoveryRequest ) ;
371
- const transaction = new EthTx ( txHex ) ;
372
-
373
- const customMessage = recoveryRequest . custom ? recoveryRequest . custom . message : 'None' ;
374
- const txData = transaction . data ;
375
- const outputs = [ {
376
- address : '0x' + txData . slice ( 16 , 36 ) . toString ( 'hex' ) ,
377
- amount : new BN ( txData . slice ( 36 , 68 ) . toString ( 'hex' ) , 16 )
378
- } ] ;
379
-
380
- confirmRecovery ( recoveryRequest . backupKey , outputs , customMessage , skipConfirm ) ;
381
-
382
- if ( ! key ) {
383
- console . log ( 'Please enter the xprv of the wallet for signing: ' ) ;
384
- key = prompt ( ) ;
385
- }
386
-
387
- const backupKeyNode = getHDNodeAndVerify ( key , recoveryRequest . backupKey ) ;
388
-
389
- const backupSigningKey = backupKeyNode . keyPair . getPrivateKeyBuffer ( ) ;
390
-
391
- transaction . sign ( backupSigningKey ) ;
392
-
393
- return transaction . serialize ( ) . toString ( 'hex' ) ;
372
+ return signEthTx ( recoveryRequest , key , skipConfirm , true ) ;
394
373
} ;
395
374
396
375
/* *
@@ -478,7 +457,7 @@ const handleSign = function(args) {
478
457
if ( coin . family === 'eth' && ! coin . isToken ) {
479
458
txHex = handleSignEthereum ( recoveryRequest , key , args . confirm ) ;
480
459
} else {
481
- txHex = handleSignErc20 ( recoveryRequest , key , args . confirm , basecoin ) ;
460
+ txHex = handleSignErc20 ( recoveryRequest , key , args . confirm ) ;
482
461
}
483
462
}
484
463
break ;
0 commit comments