diff --git a/modules/bitgo/test/v2/unit/wallet.ts b/modules/bitgo/test/v2/unit/wallet.ts index 2e9e9b8e82..81506eb49c 100644 --- a/modules/bitgo/test/v2/unit/wallet.ts +++ b/modules/bitgo/test/v2/unit/wallet.ts @@ -3536,6 +3536,76 @@ describe('V2 Wallet:', function () { args[1]!.should.equal('full'); }); + it('should call prebuildTxWithIntent with the correct params for Export', async function () { + const recipients = [ + { + address: 'P-costwo1xxt27rgnrjyaw2wmuswxumlmme2tapj62s7uy0', + amount: '50000000000000000', + }, + ]; + const feeOptions = { + maxFeePerGas: 3000000000, + maxPriorityFeePerGas: 2000000000, + }; + + const prebuildTxWithIntent = sandbox.stub(ECDSAUtils.EcdsaUtils.prototype, 'prebuildTxWithIntent'); + prebuildTxWithIntent.resolves(txRequestFull); + + await tssEthWallet.prebuildTransaction({ + reqId, + type: 'Export', + recipients, + nonce: '5', + feeOptions, + }); + + sinon.assert.calledOnce(prebuildTxWithIntent); + const args = prebuildTxWithIntent.args[0]; + args[0]!.intentType.should.equal('export'); + args[0]!.recipients!.should.deepEqual(recipients); + args[0]!.nonce!.should.equal('5'); + args[0]!.feeOptions!.should.deepEqual(feeOptions); + args[1]!.should.equal('full'); + }); + + it('should call prebuildTxWithIntent with the correct params for Import', async function () { + const prebuildTxWithIntent = sandbox.stub(ECDSAUtils.EcdsaUtils.prototype, 'prebuildTxWithIntent'); + prebuildTxWithIntent.resolves(txRequestFull); + + await tssEthWallet.prebuildTransaction({ + reqId, + type: 'Import', + recipients: [], + }); + + sinon.assert.calledOnce(prebuildTxWithIntent); + const args = prebuildTxWithIntent.args[0]; + args[0]!.intentType.should.equal('import'); + args[0]!.recipients!.should.deepEqual([]); + args[0]!.should.not.have.property('nonce'); + args[0]!.should.not.have.property('feeOptions'); + args[1]!.should.equal('full'); + }); + + it('should call prebuildTxWithIntent with the correct params for ImportToC', async function () { + const prebuildTxWithIntent = sandbox.stub(ECDSAUtils.EcdsaUtils.prototype, 'prebuildTxWithIntent'); + prebuildTxWithIntent.resolves(txRequestFull); + + await tssEthWallet.prebuildTransaction({ + reqId, + type: 'ImportToC', + recipients: [], + }); + + sinon.assert.calledOnce(prebuildTxWithIntent); + const args = prebuildTxWithIntent.args[0]; + args[0]!.intentType.should.equal('importtoc'); + args[0]!.recipients!.should.deepEqual([]); + args[0]!.should.not.have.property('nonce'); + args[0]!.should.not.have.property('feeOptions'); + args[1]!.should.equal('full'); + }); + it('should call prebuildTxWithIntent with the correct feeOptions when passing using the legacy format', async function () { const recipients = [ { @@ -3845,6 +3915,34 @@ describe('V2 Wallet:', function () { intent.should.have.property('recipients', undefined); }); + it('populate intent should return valid export intent for EVM cross-chain', async function () { + const mpcUtils = new ECDSAUtils.EcdsaUtils(bitgo, bitgo.coin('hteth')); + const feeOptions = { + maxFeePerGas: 3000000000, + maxPriorityFeePerGas: 2000000000, + }; + const recipients = [ + { + address: 'P-costwo1xxt27rgnrjyaw2wmuswxumlmme2tapj62s7uy0', + amount: '50000000000000000', + }, + ]; + + const intent = mpcUtils.populateIntent(bitgo.coin('hteth'), { + reqId, + intentType: 'export', + recipients, + feeOptions, + nonce: '5', + }); + + intent.intentType.should.equal('export'); + intent.feeOptions!.should.deepEqual(feeOptions); + intent.nonce!.should.equal('5'); + intent.recipients!.should.be.an.Array().with.lengthOf(1); + intent.recipients![0].address.address.should.equal(recipients[0].address); + }); + it('should build a single recipient transfer transaction providing apiVersion parameter as "full" ', async function () { const recipients = [ { diff --git a/modules/sdk-core/src/bitgo/utils/mpcUtils.ts b/modules/sdk-core/src/bitgo/utils/mpcUtils.ts index fed7abdf2c..c3c9265c16 100644 --- a/modules/sdk-core/src/bitgo/utils/mpcUtils.ts +++ b/modules/sdk-core/src/bitgo/utils/mpcUtils.ts @@ -236,6 +236,13 @@ export abstract class MpcUtils { feeOptions: params.feeOptions, feeToken: params.feeToken, }; + case 'export': + return { + ...baseIntent, + feeOptions: params.feeOptions, + feeToken: params.feeToken, + nonce: params.nonce, + }; default: throw new Error(`Unsupported intent type ${params.intentType}`); } diff --git a/modules/sdk-core/src/bitgo/wallet/wallet.ts b/modules/sdk-core/src/bitgo/wallet/wallet.ts index d05427cff5..2eba5c7906 100644 --- a/modules/sdk-core/src/bitgo/wallet/wallet.ts +++ b/modules/sdk-core/src/bitgo/wallet/wallet.ts @@ -4141,6 +4141,48 @@ export class Wallet implements IWallet { params.preview ); break; + case 'Export': + txRequest = await this.tssUtils!.prebuildTxWithIntent( + { + reqId, + intentType: 'export', + sequenceId: params.sequenceId, + comment: params.comment, + recipients: params.recipients || [], + nonce: params.nonce, + feeOptions, + feeToken: params.feeToken, + }, + apiVersion, + params.preview + ); + break; + case 'Import': + txRequest = await this.tssUtils!.prebuildTxWithIntent( + { + reqId, + intentType: 'import', + sequenceId: params.sequenceId, + comment: params.comment, + recipients: params.recipients || [], + }, + apiVersion, + params.preview + ); + break; + case 'ImportToC': + txRequest = await this.tssUtils!.prebuildTxWithIntent( + { + reqId, + intentType: 'importtoc', + sequenceId: params.sequenceId, + comment: params.comment, + recipients: params.recipients || [], + }, + apiVersion, + params.preview + ); + break; default: throw new Error(`transaction type not supported: ${params.type}`); }