@@ -113,6 +113,146 @@ 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 leave txHex undefined 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+ const result = await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
175+
176+ result . prebuilds . should . have . length ( 1 ) ;
177+ ( result . prebuilds [ 0 ] . txHex === undefined ) . should . be . true ( ) ;
178+ } ) ;
179+
180+ it ( 'should NOT fetch txRequest when txHex is already present in the build response' , async function ( ) {
181+ stubPost ( { transactions : [ { txRequestId : 'req-4' , txHex : 'already-present' } ] , errors : [ ] } ) ;
182+ mockBitGo . get = sinon . stub ( ) ;
183+
184+ const result = await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
185+
186+ result . prebuilds [ 0 ] ! . txHex ! . should . equal ( 'already-present' ) ;
187+ sinon . assert . notCalled ( mockBitGo . get ) ;
188+ } ) ;
189+
190+ it ( 'should NOT fetch txRequest when build response has no txRequestId' , async function ( ) {
191+ stubPost ( { transactions : [ { stakingParams : { } } ] , errors : [ ] } ) ;
192+ mockBitGo . get = sinon . stub ( ) ;
193+
194+ await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
195+
196+ sinon . assert . notCalled ( mockBitGo . get ) ;
197+ } ) ;
198+
199+ it ( 'should fetch txRequest once per delegation for bulk delegations' , async function ( ) {
200+ stubPost ( {
201+ transactions : [
202+ { txRequestId : 'req-bulk-1' , stakingParams : { } } ,
203+ { txRequestId : 'req-bulk-2' , stakingParams : { } } ,
204+ ] ,
205+ errors : [ ] ,
206+ } ) ;
207+ const resultStub = sinon
208+ . stub ( )
209+ . onFirstCall ( )
210+ . resolves ( {
211+ txRequests : [
212+ {
213+ txRequestId : 'req-bulk-1' ,
214+ apiVersion : 'full' ,
215+ transactions : [ { unsignedTx : { serializedTxHex : 'hex-bulk-1' } } ] ,
216+ } ,
217+ ] ,
218+ } )
219+ . onSecondCall ( )
220+ . resolves ( {
221+ txRequests : [
222+ {
223+ txRequestId : 'req-bulk-2' ,
224+ apiVersion : 'full' ,
225+ transactions : [ { unsignedTx : { serializedTxHex : 'hex-bulk-2' } } ] ,
226+ } ,
227+ ] ,
228+ } ) ;
229+ const retryStub = sinon . stub ( ) . returns ( { result : resultStub } ) ;
230+ const queryStub = sinon . stub ( ) . returns ( { retry : retryStub } ) ;
231+ mockBitGo . get = sinon . stub ( ) . returns ( { query : queryStub } ) ;
232+ mockBitGo . url = sinon . stub ( ) . returns ( '/mock-api/v2/wallet/test-wallet-id/txrequests' ) ;
233+
234+ const result = await wallet . buildResourceDelegations ( { delegations } ) ;
235+
236+ result . prebuilds . should . have . length ( 2 ) ;
237+ result . prebuilds [ 0 ] ! . txHex ! . should . equal ( 'hex-bulk-1' ) ;
238+ result . prebuilds [ 1 ] ! . txHex ! . should . equal ( 'hex-bulk-2' ) ;
239+ sinon . assert . calledTwice ( mockBitGo . get ) ;
240+ } ) ;
241+ } ) ;
242+ } ) ;
243+
244+ // ---------------------------------------------------------------------------
245+ // buildResourceDelegations — non-TSS wallet, no txRequest fetch
246+ // ---------------------------------------------------------------------------
247+ describe ( 'buildResourceDelegations non-TSS wallet — no txRequest fetch' , function ( ) {
248+ it ( 'should NOT call getTxRequest for non-TSS wallet even when txRequestId is present' , async function ( ) {
249+ stubPost ( { transactions : [ { txRequestId : 'req-hot' , stakingParams : { } } ] , errors : [ ] } ) ;
250+ mockBitGo . get = sinon . stub ( ) ;
251+
252+ await wallet . buildResourceDelegations ( { delegations : [ delegations [ 0 ] ] } ) ;
253+
254+ sinon . assert . notCalled ( mockBitGo . get ) ;
255+ } ) ;
116256 } ) ;
117257
118258 // ---------------------------------------------------------------------------
0 commit comments