@@ -113,6 +113,145 @@ describe('Wallet - resource management', function () {
113113 bodyArg . should . have . property ( 'delegations' ) ;
114114 bodyArg . should . not . have . property ( 'walletPassphrase' ) ;
115115 } ) ;
116+
117+ describe ( 'TSS wallet — txHex population from full txRequest' , function ( ) {
118+ function stubTxRequestFetch ( txRequest : any ) {
119+ const resultStub = sinon . stub ( ) . resolves ( { txRequests : [ txRequest ] } ) ;
120+ const retryStub = sinon . stub ( ) . returns ( { result : resultStub } ) ;
121+ const queryStub = sinon . stub ( ) . returns ( { retry : retryStub } ) ;
122+ mockBitGo . get = sinon . stub ( ) . returns ( { query : queryStub } ) ;
123+ mockBitGo . url = sinon . stub ( ) . returns ( '/mock-api/v2/wallet/test-wallet-id/txrequests' ) ;
124+ return { resultStub } ;
125+ }
126+
127+ beforeEach ( function ( ) {
128+ mockWalletData = {
129+ id : 'test-wallet-id' ,
130+ keys : [ 'user-key' , 'backup-key' , 'bitgo-key' ] ,
131+ type : 'hot' ,
132+ multisigType : 'tss' ,
133+ } ;
134+ wallet = new Wallet ( mockBitGo , mockBaseCoin , mockWalletData ) ;
135+ } ) ;
136+
137+ it ( 'should fetch full txRequest and map serializedTxHex to txHex when apiVersion is full' , async function ( ) {
138+ stubPost ( { transactions : [ { txRequestId : 'req-1' , stakingParams : { } } ] , errors : [ ] } ) ;
139+ stubTxRequestFetch ( {
140+ txRequestId : 'req-1' ,
141+ apiVersion : 'full' ,
142+ transactions : [ { unsignedTx : { serializedTxHex : 'serialized-hex-aaa' } } ] ,
143+ } ) ;
144+
145+ const result = await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
146+
147+ result . prebuilds . should . have . length ( 1 ) ;
148+ result . prebuilds [ 0 ] ! . txHex ! . should . equal ( 'serialized-hex-aaa' ) ;
149+ sinon . assert . calledOnce ( mockBitGo . get ) ;
150+ } ) ;
151+
152+ it ( 'should fetch full txRequest and map serializedTxHex to txHex when apiVersion is lite' , async function ( ) {
153+ stubPost ( { transactions : [ { txRequestId : 'req-2' , stakingParams : { } } ] , errors : [ ] } ) ;
154+ stubTxRequestFetch ( {
155+ txRequestId : 'req-2' ,
156+ apiVersion : 'lite' ,
157+ unsignedTxs : [ { serializedTxHex : 'serialized-hex-bbb' } ] ,
158+ } ) ;
159+
160+ const result = await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
161+
162+ result . prebuilds . should . have . length ( 1 ) ;
163+ result . prebuilds [ 0 ] ! . txHex ! . should . equal ( 'serialized-hex-bbb' ) ;
164+ } ) ;
165+
166+ it ( 'should throw when txRequest has no serializedTxHex' , async function ( ) {
167+ stubPost ( { transactions : [ { txRequestId : 'req-3' , stakingParams : { } } ] , errors : [ ] } ) ;
168+ stubTxRequestFetch ( {
169+ txRequestId : 'req-3' ,
170+ apiVersion : 'full' ,
171+ transactions : [ { unsignedTx : { } } ] ,
172+ } ) ;
173+
174+ await ( wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) as any ) . should . be . rejectedWith (
175+ / E x p e c t e d s e r i a l i z e d T x H e x /
176+ ) ;
177+ } ) ;
178+
179+ it ( 'should NOT fetch txRequest when txHex is already present in the build response' , async function ( ) {
180+ stubPost ( { transactions : [ { txRequestId : 'req-4' , txHex : 'already-present' } ] , errors : [ ] } ) ;
181+ mockBitGo . get = sinon . stub ( ) ;
182+
183+ const result = await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
184+
185+ result . prebuilds [ 0 ] ! . txHex ! . should . equal ( 'already-present' ) ;
186+ sinon . assert . notCalled ( mockBitGo . get ) ;
187+ } ) ;
188+
189+ it ( 'should NOT fetch txRequest when build response has no txRequestId' , async function ( ) {
190+ stubPost ( { transactions : [ { stakingParams : { } } ] , errors : [ ] } ) ;
191+ mockBitGo . get = sinon . stub ( ) ;
192+
193+ await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
194+
195+ sinon . assert . notCalled ( mockBitGo . get ) ;
196+ } ) ;
197+
198+ it ( 'should fetch txRequest once per delegation for bulk delegations' , async function ( ) {
199+ stubPost ( {
200+ transactions : [
201+ { txRequestId : 'req-bulk-1' , stakingParams : { } } ,
202+ { txRequestId : 'req-bulk-2' , stakingParams : { } } ,
203+ ] ,
204+ errors : [ ] ,
205+ } ) ;
206+ const resultStub = sinon
207+ . stub ( )
208+ . onFirstCall ( )
209+ . resolves ( {
210+ txRequests : [
211+ {
212+ txRequestId : 'req-bulk-1' ,
213+ apiVersion : 'full' ,
214+ transactions : [ { unsignedTx : { serializedTxHex : 'hex-bulk-1' } } ] ,
215+ } ,
216+ ] ,
217+ } )
218+ . onSecondCall ( )
219+ . resolves ( {
220+ txRequests : [
221+ {
222+ txRequestId : 'req-bulk-2' ,
223+ apiVersion : 'full' ,
224+ transactions : [ { unsignedTx : { serializedTxHex : 'hex-bulk-2' } } ] ,
225+ } ,
226+ ] ,
227+ } ) ;
228+ const retryStub = sinon . stub ( ) . returns ( { result : resultStub } ) ;
229+ const queryStub = sinon . stub ( ) . returns ( { retry : retryStub } ) ;
230+ mockBitGo . get = sinon . stub ( ) . returns ( { query : queryStub } ) ;
231+ mockBitGo . url = sinon . stub ( ) . returns ( '/mock-api/v2/wallet/test-wallet-id/txrequests' ) ;
232+
233+ const result = await wallet . buildResourceDelegations ( { delegations } ) ;
234+
235+ result . prebuilds . should . have . length ( 2 ) ;
236+ result . prebuilds [ 0 ] ! . txHex ! . should . equal ( 'hex-bulk-1' ) ;
237+ result . prebuilds [ 1 ] ! . txHex ! . should . equal ( 'hex-bulk-2' ) ;
238+ sinon . assert . calledTwice ( mockBitGo . get ) ;
239+ } ) ;
240+ } ) ;
241+ } ) ;
242+
243+ // ---------------------------------------------------------------------------
244+ // buildResourceDelegations — non-TSS wallet, no txRequest fetch
245+ // ---------------------------------------------------------------------------
246+ describe ( 'buildResourceDelegations non-TSS wallet — no txRequest fetch' , function ( ) {
247+ it ( 'should NOT call getTxRequest for non-TSS wallet even when txRequestId is present' , async function ( ) {
248+ stubPost ( { transactions : [ { txRequestId : 'req-hot' , stakingParams : { } } ] , errors : [ ] } ) ;
249+ mockBitGo . get = sinon . stub ( ) ;
250+
251+ await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
252+
253+ sinon . assert . notCalled ( mockBitGo . get ) ;
254+ } ) ;
116255 } ) ;
117256
118257 // ---------------------------------------------------------------------------
0 commit comments