Skip to content

Commit 943928b

Browse files
author
Arik Sosman
committed
preliminary tx recreation for v2 pending approvals
Reviewers: andrew, alex Subscribers: ben Differential Revision: https://phabricator.bitgo.com/D5487
1 parent ec7f4bb commit 943928b

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed

src/v2/pendingApproval.js

Lines changed: 65 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ PendingApproval.prototype.populateWallet = function() {
140140
});
141141
}
142142

143-
if (self.wallet.id() != self.info().transactionRequest.sourceWallet) {
143+
if (self.wallet.id() !== self.info().transactionRequest.sourceWallet) {
144144
throw new Error('unexpected source wallet for pending approval');
145145
}
146146

@@ -163,15 +163,50 @@ PendingApproval.prototype.approve = function(params, callback) {
163163
var self = this;
164164
return Q()
165165
.then(function() {
166-
let txHex;
167-
if(self.info && self.info().transactionRequest && self.info().transactionRequest.coinSpecific
166+
if (self.type() === 'transactionRequest') {
167+
/*
168+
If this is a request for approving a transaction, depending on whether this user has a private key to the wallet
169+
(some admins may not have the spend permission), the transaction could either be rebroadcast as is, or it could
170+
be reconstructed. It is preferable to reconstruct a tx in order to adhere to the latest network conditions
171+
such as newer unspents, different fees, or a higher sequence id
172+
*/
173+
if (params.tx) {
174+
// the approval tx was reconstructed and explicitly specified - pass it through
175+
return {
176+
txHex: params.tx
177+
};
178+
}
179+
180+
let transaction;
181+
if (self.info && self.info().transactionRequest && self.info().transactionRequest.coinSpecific
168182
&& self.info().transactionRequest.coinSpecific[self.baseCoin.type]
169183
&& self.info().transactionRequest.coinSpecific[self.baseCoin.type].txHex) {
170-
txHex = self.info().transactionRequest.coinSpecific[self.baseCoin.type].txHex;
171-
} else {
172-
throw new Error('missing txHex on pending approval');
184+
transaction = self.info().transactionRequest.coinSpecific[self.baseCoin.type];
185+
}
186+
187+
// this user may not have spending privileges or a passphrase may not have been passed in
188+
if (!canRecreateTransaction) {
189+
if (!transaction) {
190+
throw new Error('missing txHex on pending approval');
191+
}
192+
return {
193+
txHex: transaction.txHex
194+
};
195+
}
196+
197+
return self.populateWallet()
198+
.then(function() {
199+
return self.recreateAndSignTransaction();
200+
});
201+
}
202+
})
203+
.then(function(transaction) {
204+
205+
var approvalParams = { 'state': 'approved', 'otp': params.otp };
206+
if (transaction) {
207+
// if in the previous instance, we recreated a transaction, we need to add its hex to the approval params
208+
approvalParams.txHex = transaction.txHex;
173209
}
174-
var approvalParams = { txHex: txHex, 'state': 'approved', 'otp': params.otp };
175210
return self.bitgo.put(self.url())
176211
.send(approvalParams)
177212
.result()
@@ -213,4 +248,27 @@ PendingApproval.prototype.cancel = function(params, callback) {
213248
return this.reject(params, callback);
214249
};
215250

251+
/**
252+
* Recreate a transaction for a pending approval to respond to updated network conditions
253+
* @param params
254+
*/
255+
PendingApproval.prototype.recreateAndSignTransaction = function(params) {
256+
params = _.extend({}, params);
257+
common.validateParams(params, [], []);
258+
259+
// this method only makes sense with existing transaction requests
260+
assert(this.info().transactionRequest);
261+
262+
// let's prebuild this transaction
263+
var wallet = this.wallet;
264+
var recipients = this.info().transactionRequest.recipients;
265+
var txPrebuildPromise = this.wallet.prebuildTransaction({ recipients: recipients });
266+
var userKeychainPromise = this.baseCoin.keychains().get({ id: wallet._wallet.keys[0] });
267+
return Q.all([txPrebuildPromise, userKeychainPromise])
268+
.spread(function(txPrebuild, userKeychain) {
269+
var signingParams = _.extend({}, params, { txPrebuild: txPrebuild, keychain: userKeychain });
270+
return wallet.signTransaction(signingParams);
271+
});
272+
};
273+
216274
module.exports = PendingApproval;

0 commit comments

Comments
 (0)