From c749d205450ccd4808be9c639629d5d230dc03cb Mon Sep 17 00:00:00 2001 From: Bhuvan R Date: Wed, 20 May 2026 10:51:30 +0530 Subject: [PATCH] fix(express): use wallet multisigType instead of coin.supportsTss() for TRX consolidation routing On-chain TRX wallets with an external signer configured were failing consolidation with "TxRequestId required to sign TSS transactions with External Signer." because handleV2ConsolidateAccount used coin.supportsTss() to decide signing params. For TRX, supportsTss() is always true at the coin level regardless of wallet type, causing TSS MPC generators to be injected for on-chain wallets that have no txRequestId in their build response. Align with handleV2SendMany (fixed in BG-65857) by switching to wallet._wallet.multisigType === 'tss', which reflects the actual wallet configuration rather than coin capability. TICKET: CHALO-473 --- modules/express/src/clientRoutes.ts | 3 +- .../unit/clientRoutes/consolidateAccount.ts | 43 +++++++++++++++++-- .../unit/typedRoutes/consolidateAccount.ts | 15 +++++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/modules/express/src/clientRoutes.ts b/modules/express/src/clientRoutes.ts index 169086b7cd..4fd562760c 100755 --- a/modules/express/src/clientRoutes.ts +++ b/modules/express/src/clientRoutes.ts @@ -23,6 +23,7 @@ import { GetNetworkPartnersResponse, GShare, MPCType, + multisigTypes, ShareType, SignShare, SShare, @@ -816,7 +817,7 @@ export async function handleV2ConsolidateAccount( let result: any; try { - if (coin.supportsTss()) { + if (wallet._wallet.multisigType === multisigTypes.tss) { result = await wallet.sendAccountConsolidations(createTSSSendParams(req, wallet)); } else { result = await wallet.sendAccountConsolidations(createSendParams(req)); diff --git a/modules/express/test/unit/clientRoutes/consolidateAccount.ts b/modules/express/test/unit/clientRoutes/consolidateAccount.ts index df3278a509..3db8b26149 100644 --- a/modules/express/test/unit/clientRoutes/consolidateAccount.ts +++ b/modules/express/test/unit/clientRoutes/consolidateAccount.ts @@ -9,6 +9,7 @@ import * as express from 'express'; import { handleV2ConsolidateAccount } from '../../../src/clientRoutes'; import { BitGo } from 'bitgo'; +import { MultisigType } from '@bitgo/sdk-core'; describe('Consolidate account', () => { it('should fail if coin does not allow consolidation', async () => { @@ -71,11 +72,13 @@ describe('Consolidate account', () => { ); }); - function createConsolidateMocks(res, allowsAccountConsolidations = false, supportsTss = false) { + function createConsolidateMocks(res, allowsAccountConsolidations = false, multisigType: MultisigType = 'onchain') { const consolidationStub = sinon.stub().returns(res); - const walletStub = { sendAccountConsolidations: consolidationStub }; + const walletStub = { + sendAccountConsolidations: consolidationStub, + _wallet: { multisigType }, + }; const coinStub = { - supportsTss: () => supportsTss, allowsAccountConsolidations: () => allowsAccountConsolidations, wallets: () => ({ get: () => Promise.resolve(walletStub) }), }; @@ -108,7 +111,7 @@ describe('Consolidate account', () => { it('should pass the apiVersion param to bitgo api consolidate/build', async () => { const result = { success: [], failure: [] }; const body = { apiVersion: 'full' }; - const { bitgoStub, consolidationStub } = createConsolidateMocks(result, true, true); + const { bitgoStub, consolidationStub } = createConsolidateMocks(result, true, 'tss'); const mockRequest = { bitgo: bitgoStub, decoded: { @@ -124,6 +127,38 @@ describe('Consolidate account', () => { consolidationStub.should.be.calledOnceWith(body); }); + it('should use on-chain signing params for a TRX on-chain wallet even though TRX supportsTss', async () => { + const result = { failure: [] }; + const body = { consolidateAddresses: ['addr1'] }; + const { bitgoStub, consolidationStub } = createConsolidateMocks(result, true, 'onchain'); + const mockRequest = { + bitgo: bitgoStub, + decoded: { coin: 'ttrx', id: '23423423423423' }, + body, + }; + + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.resolvedWith( + result + ); + consolidationStub.should.be.calledOnceWith(body); + }); + + it('should use TSS signing params for a TRX TSS wallet', async () => { + const result = { failure: [] }; + const body = { consolidateAddresses: ['addr1'] }; + const { bitgoStub, consolidationStub } = createConsolidateMocks(result, true, 'tss'); + const mockRequest = { + bitgo: bitgoStub, + decoded: { coin: 'ttrx', id: '23423423423423' }, + body, + }; + + await handleV2ConsolidateAccount(mockRequest as express.Request & typeof mockRequest).should.be.resolvedWith( + result + ); + consolidationStub.should.be.calledOnceWith(body); + }); + it('should return 202 when some transactions fail', async () => { const result = { success: [0], failure: [0] }; const body = 'testbody'; diff --git a/modules/express/test/unit/typedRoutes/consolidateAccount.ts b/modules/express/test/unit/typedRoutes/consolidateAccount.ts index a78ef29a93..ea8e2619f8 100644 --- a/modules/express/test/unit/typedRoutes/consolidateAccount.ts +++ b/modules/express/test/unit/typedRoutes/consolidateAccount.ts @@ -181,6 +181,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -217,6 +218,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -250,6 +252,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -286,6 +289,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -329,6 +333,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockMultipleSuccess), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -367,6 +372,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockPartialSuccess), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -410,6 +416,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockAllFailed), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -494,6 +501,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().rejects(new Error('Invalid passphrase')), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -523,6 +531,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().rejects(new Error('Insufficient funds')), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -621,6 +630,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -655,6 +665,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -691,6 +702,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -726,6 +738,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -756,6 +769,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = { @@ -789,6 +803,7 @@ describe('Consolidate Account API Tests', function () { const mockWallet = { sendAccountConsolidations: sinon.stub().resolves(mockSuccessResponse), + _wallet: { multisigType: 'onchain' }, }; const mockCoin = {