diff --git a/modules/bitgo/test/v2/unit/wallet.ts b/modules/bitgo/test/v2/unit/wallet.ts index 81506eb49c..6c7ec24cde 100644 --- a/modules/bitgo/test/v2/unit/wallet.ts +++ b/modules/bitgo/test/v2/unit/wallet.ts @@ -7,6 +7,7 @@ import * as sinon from 'sinon'; import '../lib/asserts'; import nock = require('nock'); import * as _ from 'lodash'; +import * as assert from 'assert'; import { BaseTssUtils, @@ -2543,6 +2544,46 @@ describe('V2 Wallet:', function () { sandbox.verifyAndRestore(); }); + it('should preserve tss txPrebuild buildParams when presign replaces the txPrebuild', async function () { + const recipients = [ + { + address: '6DadkZcx9JZgeQUDbHh12cmqCpaqehmVxv6sGy49jrah', + amount: '1000', + }, + ]; + const buildParams = { + recipients, + type: 'transfer', + }; + + sandbox.stub(tsol, 'presignTransaction').callsFake(async (presignParams) => { + return { + ...presignParams, + txPrebuild: { + txRequestId: 'id', + txHex: 'refreshed-tx-hex', + }, + }; + }); + const signTxRequest = sandbox.stub(TssUtils.prototype, 'signTxRequest').resolves(txRequest); + + await tssSolWallet.signTransaction({ + txPrebuild: { + txRequestId: 'id', + txHex: 'original-tx-hex', + buildParams, + }, + prv: 'user-prv', + }); + + signTxRequest.should.have.been.calledOnce(); + const firstSignTxRequestCall = signTxRequest.firstCall; + assert.ok(firstSignTxRequestCall); + const signTxRequestParams = firstSignTxRequestCall.args[0]; + assert.ok(signTxRequestParams); + should(signTxRequestParams.txParams).deepEqual(buildParams); + }); + describe('preBuildAndSignTransaction', async function () { const params = { walletPassphrase: 'passphrase12345', diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index c5ccbd4336..2c0ddcb2de 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -2235,6 +2235,19 @@ export class Wallet implements IWallet { tssUtils: this.tssUtils, }); + if ( + this.multisigType() === 'tss' && + this.multisigTypeVersion() === 'MPCv2' && + this.baseCoin.getMPCAlgorithm() === 'eddsa' && + typeof params.txPrebuild === 'object' && + typeof presign.txPrebuild === 'object' && + params.txPrebuild.buildParams && + !presign.txPrebuild.buildParams + ) { + // Sol presign hook refreshes txPrebuild, but buildParams is SDK-local intent metadata. + presign.txPrebuild.buildParams = params.txPrebuild.buildParams; + } + if (this.multisigType() === 'tss') { return this.signTransactionTss({ ...presign,