@@ -124,6 +124,70 @@ describe('Go Staking Wallet Common', function () {
124124 msScope1 . isDone ( ) . should . be . True ( ) ;
125125 msScope2 . isDone ( ) . should . be . True ( ) ;
126126 } ) ;
127+
128+ it ( 'should stake without a wallet passphrase for an OFC wallet that signs remotely (userKeySigningRequired === false)' , async function ( ) {
129+ // OFC wallet signs remotely via the BitGo key instead of decrypting the user key locally.
130+ const remoteWallet = new Wallet ( bitgo , baseCoin , {
131+ id : 'remoteWalletId' ,
132+ coin : ofcCoin ,
133+ enterprise : enterprise . id ,
134+ keys : [ '5b3424f91bf349930e340175' , '5b3424f91bf349930e340174' , '5b3424f91bf349930e340173' ] ,
135+ coinSpecific : { userKeySigningRequired : false } ,
136+ } ) ;
137+ const remoteStakingWallet = remoteWallet . toGoStakingWallet ( ) ;
138+
139+ // prebuildAndSignTransaction still fetches the user keychain (index 0), but with no passphrase
140+ // the decrypt check is skipped and the key is never used to sign.
141+ nock ( microservicesUri ) . get ( `/api/v2/${ ofcCoin } /key/${ remoteStakingWallet . wallet . keyIds ( ) [ 0 ] } ` ) . reply ( 200 , {
142+ id : remoteStakingWallet . wallet . keyIds ( ) [ 0 ] ,
143+ pub : 'xpub661MyMwAqRbcFq65dvGMeEVb81KKDRRkWkawSVesWcyevGc5gr8V27LjNfkktaMuKtM362jhgKy2eu35RdArcmmEAoULzAvgKkJpWQPvLXM' ,
144+ source : 'user' ,
145+ coinSpecific : { } ,
146+ } ) ;
147+
148+ const preview = fixtures . previewGoStakingRequest ( coin ) ;
149+ const msScope1 = nock ( microservicesUri )
150+ . post ( `/api/go-staking/v1/${ ofcCoin } /accounts/${ remoteStakingWallet . accountId } /requests/preview` , {
151+ amount : '1' ,
152+ clientId : 'clientId' ,
153+ type : 'STAKE' ,
154+ } )
155+ . reply ( 201 , preview ) ;
156+
157+ // remote signing: the BitGo key signs the payload and returns the signature
158+ const signature =
159+ '1f4f7e789ef485363b33dca7273717a4a4413330f2badbcaf302758bc404ff8e930943db81aa2c77007738afa23166934c2a3136bae281bea037095be7183c0602' ;
160+ const signScope = nock ( microservicesUri )
161+ . post ( `/api/v2/ofc/wallet/${ remoteWallet . id ( ) } /tx/sign` , { payload : preview . payload } )
162+ . reply ( 200 , { signature } ) ;
163+
164+ const expected = fixtures . finalizeGoStakingRequest ( coin , 'STAKE' ) ;
165+ const msScope2 = nock ( microservicesUri )
166+ . post ( `/api/go-staking/v1/${ ofcCoin } /accounts/${ remoteStakingWallet . accountId } /requests/finalize` , {
167+ amount : '1' ,
168+ clientId : 'clientId' ,
169+ frontTransferSendRequest : {
170+ halfSigned : {
171+ payload : preview . payload ,
172+ signature,
173+ } ,
174+ } ,
175+ type : 'STAKE' ,
176+ } )
177+ . reply ( 201 , expected ) ;
178+
179+ const stakingRequest = await remoteStakingWallet . stake ( {
180+ amount : '1' ,
181+ clientId : 'clientId' ,
182+ } ) ;
183+
184+ should . exist ( stakingRequest ) ;
185+
186+ stakingRequest . should . deepEqual ( expected ) ;
187+ msScope1 . isDone ( ) . should . be . True ( ) ;
188+ signScope . isDone ( ) . should . be . True ( ) ;
189+ msScope2 . isDone ( ) . should . be . True ( ) ;
190+ } ) ;
127191 } ) ;
128192
129193 describe ( 'unstake' , function ( ) {
0 commit comments