@@ -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+
216274module . exports = PendingApproval ;
0 commit comments