@@ -298,4 +298,118 @@ describe('POST /api/:coin/wallet/:walletId/sendmany', () => {
298298 response . body . should . have . property ( 'error' ) ;
299299 response . body . error . should . equal ( 'Please configure enclaved express configs.' ) ;
300300 } ) ;
301+
302+ it ( 'should fail when transaction verification returns false' , async ( ) => {
303+ // Mock wallet get request
304+ const walletGetNock = nock ( bitgoApiUrl )
305+ . get ( `/api/v2/${ coin } /wallet/${ walletId } ` )
306+ . matchHeader ( 'any' , ( ) => true )
307+ . reply ( 200 , {
308+ id : walletId ,
309+ type : 'cold' ,
310+ subType : 'onPrem' ,
311+ keys : [ 'user-key-id' , 'backup-key-id' , 'bitgo-key-id' ] ,
312+ } ) ;
313+
314+ // Mock keychain get request
315+ const keychainGetNock = nock ( bitgoApiUrl )
316+ . get ( `/api/v2/${ coin } /key/user-key-id` )
317+ . matchHeader ( 'any' , ( ) => true )
318+ . reply ( 200 , {
319+ id : 'user-key-id' ,
320+ pub : 'xpub_user' ,
321+ } ) ;
322+
323+ const prebuildStub = sinon . stub ( Wallet . prototype , 'prebuildTransaction' ) . resolves ( {
324+ txHex : 'prebuilt-tx-hex' ,
325+ txInfo : {
326+ nP2SHInputs : 1 ,
327+ nSegwitInputs : 0 ,
328+ nOutputs : 2 ,
329+ } ,
330+ walletId,
331+ } ) ;
332+
333+ // Mock verifyTransaction to return false
334+ const verifyStub = sinon . stub ( Coin . Btc . prototype , 'verifyTransaction' ) . resolves ( false ) ;
335+
336+ const response = await agent
337+ . post ( `/api/${ coin } /wallet/${ walletId } /sendMany` )
338+ . set ( 'Authorization' , `Bearer ${ accessToken } ` )
339+ . send ( {
340+ recipients : [
341+ {
342+ address : 'tb1qtest1' ,
343+ amount : '100000' ,
344+ } ,
345+ ] ,
346+ source : 'user' ,
347+ pubkey : 'xpub_user' ,
348+ } ) ;
349+
350+ response . status . should . equal ( 500 ) ;
351+
352+ walletGetNock . done ( ) ;
353+ keychainGetNock . done ( ) ;
354+ sinon . assert . calledOnce ( prebuildStub ) ;
355+ sinon . assert . calledOnce ( verifyStub ) ;
356+ } ) ;
357+
358+ it ( 'should fail when transaction verification throws an error' , async ( ) => {
359+ // Mock wallet get request
360+ const walletGetNock = nock ( bitgoApiUrl )
361+ . get ( `/api/v2/${ coin } /wallet/${ walletId } ` )
362+ . matchHeader ( 'any' , ( ) => true )
363+ . reply ( 200 , {
364+ id : walletId ,
365+ type : 'cold' ,
366+ subType : 'onPrem' ,
367+ keys : [ 'user-key-id' , 'backup-key-id' , 'bitgo-key-id' ] ,
368+ } ) ;
369+
370+ // Mock keychain get request
371+ const keychainGetNock = nock ( bitgoApiUrl )
372+ . get ( `/api/v2/${ coin } /key/user-key-id` )
373+ . matchHeader ( 'any' , ( ) => true )
374+ . reply ( 200 , {
375+ id : 'user-key-id' ,
376+ pub : 'xpub_user' ,
377+ } ) ;
378+
379+ const prebuildStub = sinon . stub ( Wallet . prototype , 'prebuildTransaction' ) . resolves ( {
380+ txHex : 'prebuilt-tx-hex' ,
381+ txInfo : {
382+ nP2SHInputs : 1 ,
383+ nSegwitInputs : 0 ,
384+ nOutputs : 2 ,
385+ } ,
386+ walletId,
387+ } ) ;
388+
389+ // Mock verifyTransaction to throw an error
390+ const verifyStub = sinon
391+ . stub ( Coin . Btc . prototype , 'verifyTransaction' )
392+ . rejects ( new Error ( 'Invalid transaction' ) ) ;
393+
394+ const response = await agent
395+ . post ( `/api/${ coin } /wallet/${ walletId } /sendMany` )
396+ . set ( 'Authorization' , `Bearer ${ accessToken } ` )
397+ . send ( {
398+ recipients : [
399+ {
400+ address : 'tb1qtest1' ,
401+ amount : '100000' ,
402+ } ,
403+ ] ,
404+ source : 'user' ,
405+ pubkey : 'xpub_user' ,
406+ } ) ;
407+
408+ response . status . should . equal ( 500 ) ;
409+
410+ walletGetNock . done ( ) ;
411+ keychainGetNock . done ( ) ;
412+ sinon . assert . calledOnce ( prebuildStub ) ;
413+ sinon . assert . calledOnce ( verifyStub ) ;
414+ } ) ;
301415} ) ;
0 commit comments