@@ -223,10 +223,103 @@ describe('OfcSignPayload codec tests', function () {
223223 const decodedResponse = assertDecode ( OfcSignPayloadResponse200 , result . body ) ;
224224 assert . strictEqual ( decodedResponse . signature , mockSignPayloadResponse . signature ) ;
225225
226+ // Verify env passphrase was forwarded to signPayload
227+ const signCall = mockTradingAccount . signPayload . getCall ( 0 ) ;
228+ assert . ok ( signCall , 'tradingAccount.signPayload should have been called' ) ;
229+ assert . strictEqual ( signCall . args [ 0 ] . walletPassphrase , 'env_passphrase' , 'env passphrase should be forwarded' ) ;
230+
226231 // Cleanup environment variable
227232 delete process . env [ 'WALLET_ofc-wallet-id-123_PASSPHRASE' ] ;
228233 } ) ;
229234
235+ it ( 'should pass undefined walletPassphrase to signPayload when no passphrase in body or env (KMS path)' , async function ( ) {
236+ const requestBody = {
237+ walletId : 'ofc-wallet-id-no-passphrase' ,
238+ payload : { amount : '1000000' , currency : 'USD' } ,
239+ // no walletPassphrase
240+ } ;
241+
242+ // Ensure no env var is set for this wallet
243+ delete process . env [ 'WALLET_ofc-wallet-id-no-passphrase_PASSPHRASE' ] ;
244+
245+ const mockTradingAccount = {
246+ signPayload : sinon . stub ( ) . resolves ( mockSignPayloadResponse . signature ) ,
247+ } ;
248+
249+ const mockWallet = {
250+ id : ( ) => requestBody . walletId ,
251+ toTradingAccount : sinon . stub ( ) . returns ( mockTradingAccount ) ,
252+ } ;
253+
254+ const walletsGetStub = sinon . stub ( ) . resolves ( mockWallet ) ;
255+ const mockWallets = { get : walletsGetStub } ;
256+ const mockCoin = { wallets : sinon . stub ( ) . returns ( mockWallets ) } ;
257+ sinon . stub ( BitGo . prototype , 'coin' ) . returns ( mockCoin as any ) ;
258+
259+ const result = await agent
260+ . post ( '/api/v2/ofc/signPayload' )
261+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
262+ . set ( 'Content-Type' , 'application/json' )
263+ . send ( requestBody ) ;
264+
265+ assert . strictEqual ( result . status , 200 ) ;
266+ const decodedResponse = assertDecode ( OfcSignPayloadResponse200 , result . body ) ;
267+ assert . strictEqual ( decodedResponse . signature , mockSignPayloadResponse . signature ) ;
268+
269+ // signPayload must be called with walletPassphrase=undefined so the SDK routes to KMS
270+ const signCall = mockTradingAccount . signPayload . getCall ( 0 ) ;
271+ assert . ok ( signCall , 'tradingAccount.signPayload should have been called' ) ;
272+ assert . strictEqual (
273+ signCall . args [ 0 ] . walletPassphrase ,
274+ undefined ,
275+ 'walletPassphrase should be undefined to trigger KMS signing'
276+ ) ;
277+ } ) ;
278+
279+ it ( 'should prefer body walletPassphrase over env passphrase' , async function ( ) {
280+ const requestBody = {
281+ walletId : 'ofc-wallet-id-123' ,
282+ payload : { amount : '500' } ,
283+ walletPassphrase : 'body_passphrase' ,
284+ } ;
285+
286+ // Set a different env passphrase — body should win
287+ process . env [ 'WALLET_ofc-wallet-id-123_PASSPHRASE' ] = 'env_passphrase' ;
288+
289+ const mockTradingAccount = {
290+ signPayload : sinon . stub ( ) . resolves ( mockSignPayloadResponse . signature ) ,
291+ } ;
292+
293+ const mockWallet = {
294+ id : ( ) => requestBody . walletId ,
295+ toTradingAccount : sinon . stub ( ) . returns ( mockTradingAccount ) ,
296+ } ;
297+
298+ const walletsGetStub = sinon . stub ( ) . resolves ( mockWallet ) ;
299+ const mockWallets = { get : walletsGetStub } ;
300+ const mockCoin = { wallets : sinon . stub ( ) . returns ( mockWallets ) } ;
301+ sinon . stub ( BitGo . prototype , 'coin' ) . returns ( mockCoin as any ) ;
302+
303+ const result = await agent
304+ . post ( '/api/v2/ofc/signPayload' )
305+ . set ( 'Authorization' , 'Bearer test_access_token_12345' )
306+ . set ( 'Content-Type' , 'application/json' )
307+ . send ( requestBody ) ;
308+
309+ assert . strictEqual ( result . status , 200 ) ;
310+
311+ // body passphrase should take precedence
312+ const signCall = mockTradingAccount . signPayload . getCall ( 0 ) ;
313+ assert . ok ( signCall , 'tradingAccount.signPayload should have been called' ) ;
314+ assert . strictEqual (
315+ signCall . args [ 0 ] . walletPassphrase ,
316+ 'body_passphrase' ,
317+ 'body passphrase should take precedence over env'
318+ ) ;
319+
320+ delete process . env [ 'WALLET_ofc-wallet-id-123_PASSPHRASE' ] ;
321+ } ) ;
322+
230323 it ( 'should successfully sign complex nested JSON payload' , async function ( ) {
231324 const requestBody = {
232325 walletId : 'ofc-wallet-id-123' ,
0 commit comments