Skip to content

Commit bf62d71

Browse files
committed
[ISSUE-60] Refactor the signing functions in sign.js to reduce boilerplate code.
1 parent fadf3b7 commit bf62d71

File tree

1 file changed

+63
-84
lines changed

1 file changed

+63
-84
lines changed

app/sign.js

Lines changed: 63 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,38 @@ const getHDNodeAndVerify = function(xprv, expectedXpub) {
9898
return node;
9999
};
100100

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+
101133
const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
102134
const network = utxoNetworks[recoveryRequest.coin];
103135
const decimals = coinDecimals[recoveryRequest.coin];
@@ -113,13 +145,8 @@ const handleSignUtxo = function(recoveryRequest, key, skipConfirm) {
113145
address: utxoLib.address.fromOutputScript(out.script, network),
114146
amount: ( new BN(out.value) ).div( TEN.pow(decimals) ).toString()
115147
}));
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);
123150

124151
const backupKeyNode = getHDNodeAndVerify(key, recoveryRequest.backupKey);
125152

@@ -179,31 +206,39 @@ const handleHalfSignEth = function(recoveryRequest, key, skipConfirm, basecoin)
179206
}
180207

181208
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) {
182221
const EthTx = require('ethereumjs-tx');
183222

184223
const txHex = getTransactionHexFromRequest(recoveryRequest);
185224
const transaction = new EthTx(txHex);
186-
const decimals = coinDecimals[recoveryRequest.coin];
187225

188-
const customMessage = recoveryRequest.custom ? recoveryRequest.custom.message : 'None';
189226
const txData = transaction.data;
227+
190228
const outputs = [{
191229
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)
193231
}];
194232

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));
200237
}
201238

202-
const backupKeyNode = getHDNodeAndVerify(key, recoveryRequest.backupKey);
203-
204-
const backupSigningKey = backupKeyNode.keyPair.getPrivateKeyBuffer();
239+
key = promptForConfirmatioAndKey(recoveryRequest, key, outputs, skipConfirm);
205240

206-
transaction.sign(backupSigningKey);
241+
transaction.sign(getBackupSigningKey(key, recoveryRequest.backupKey));
207242

208243
return transaction.serialize().toString('hex');
209244
};
@@ -215,24 +250,16 @@ const handleSignTrx = function(recoveryRequest, key, skipConfirm) {
215250
const builder = new accountLib.TransactionBuilder({ coinName: coin });
216251
builder.from(txHex);
217252

218-
const customMessage = recoveryRequest.custom ? recoveryRequest.custom.message : 'None';
219-
220253
const outputs = builder.build().destinations.map(d => {
221254
return {
222255
address: d.address,
223256
amount: d.value.toString(10)
224257
};
225258
});
226259

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);
233261

234-
const backupKeyNode = getHDNodeAndVerify(key, recoveryRequest.backupKey);
235-
builder.sign({ key: backupKeyNode.keyPair.getPrivateKeyBuffer() });
262+
builder.sign({ key: getBackupSigningKey(key, recoveryRequest.backupKey) });
236263
return JSON.stringify(builder.build().toJson());
237264
};
238265

@@ -252,25 +279,16 @@ const handleSignEos = function(recoveryRequest, key, skipConfirm) {
252279

253280
const { recipient, amount } = utils.deserializeEOSTransaction(EosJs, packed_trx);
254281

255-
const customMessage = recoveryRequest.custom ? recoveryRequest.custom.message : 'None';
256-
257282
const outputs = [{
258283
address: recipient,
259284
amount: new BN(amount)
260285
}];
261286

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);
270288

271289
const dataToSign = utils.getEOSSignatureData(packed_trx, chainId);
272290
const signBuffer = Buffer.from(dataToSign, 'hex');
273-
const privateKeyBuffer = backupKeyNode.keyPair.getPrivateKeyBuffer();
291+
const privateKeyBuffer = getBackupSigningKey(key, recoveryRequest.backupKey);
274292
const signature = ecc.Signature.sign(signBuffer, privateKeyBuffer).toString();
275293

276294
eosTx.signatures.push(signature);
@@ -289,19 +307,13 @@ const handleSignXrp = function(recoveryRequest, key, skipConfirm) {
289307

290308
const decimals = coinDecimals[recoveryRequest.coin];
291309
const transaction = rippleParse.decode(txHex);
292-
const customMessage = recoveryRequest.custom ? recoveryRequest.custom.message : 'None';
293310

294311
const outputs = [{
295312
address: transaction.Destination,
296313
amount: (new BN(transaction.Amount)).div(TEN.pow(decimals))
297314
}];
298315

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);
305317

306318
const backupKeyNode = getHDNodeAndVerify(key, recoveryRequest.backupKey);
307319

@@ -321,11 +333,8 @@ const handleSignXlm = function(recoveryRequest, key, skipConfirm) {
321333
stellar.Network.useTestNetwork();
322334
}
323335

324-
const decimals = coinDecimals[recoveryRequest.coin];
325-
326336
const txHex = getTransactionHexFromRequest(recoveryRequest);
327337
const transaction = new stellar.Transaction(txHex);
328-
const customMessage = recoveryRequest.custom ? recoveryRequest.custom.message : 'None';
329338

330339
if (transaction.operations.length !== 1) {
331340
throw new Error('Recovery transaction is trying to perform multiple operations - aborting');
@@ -340,12 +349,7 @@ const handleSignXlm = function(recoveryRequest, key, skipConfirm) {
340349
amount: transaction.operations[0].amount || transaction.operations[0].startingBalance
341350
}];
342351

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);
349353

350354
let backupKeypair;
351355

@@ -359,38 +363,13 @@ const handleSignXlm = function(recoveryRequest, key, skipConfirm) {
359363
throw new Error('provided private key does not match public key specified with recovery request');
360364
}
361365

362-
transaction.sign(stellar.Keypair.fromSecret(key));
366+
transaction.sign(backupKeypair);
363367

364368
return transaction.toEnvelope().toXDR('base64');
365369
};
366370

367371
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);
394373
};
395374

396375
/* *
@@ -478,7 +457,7 @@ const handleSign = function(args) {
478457
if (coin.family === 'eth' && !coin.isToken) {
479458
txHex = handleSignEthereum(recoveryRequest, key, args.confirm);
480459
} else {
481-
txHex = handleSignErc20(recoveryRequest, key, args.confirm, basecoin);
460+
txHex = handleSignErc20(recoveryRequest, key, args.confirm);
482461
}
483462
}
484463
break;

0 commit comments

Comments
 (0)