Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions modules/bitgo/test/v2/unit/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
{
Expand Down Expand Up @@ -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 = [
{
Expand Down
7 changes: 7 additions & 0 deletions modules/sdk-core/src/bitgo/utils/mpcUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`);
}
Expand Down
42 changes: 42 additions & 0 deletions modules/sdk-core/src/bitgo/wallet/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`);
}
Expand Down
Loading