Skip to content

Commit d44830c

Browse files
authored
Merge pull request #7308 from BitGo/vechain-wrw-unsigned-sweep
feat: add unsigned sweep logic for vet
2 parents c60c8c5 + 934fc0b commit d44830c

File tree

4 files changed

+50
-53
lines changed

4 files changed

+50
-53
lines changed

modules/bitgo/test/v2/lib/recovery-nocks.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,10 @@ module.exports.nockEthLikeRecovery = function (bitgo, nockData = nockEthData) {
416416
});
417417
};
418418

419-
module.exports.nockVetRecovery = function (bitgo) {
419+
module.exports.nockVetRecovery = function (bitgo, baseAddress) {
420420
// nock for account balance
421421
const url = Environments[bitgo.getEnv()].vetNodeUrl;
422-
nock(url).get('/accounts/0x88c2ab227908d39f6afdb85203dca3e937bb77af').reply(200, {
422+
nock(url).get(`/accounts/${baseAddress}`).reply(200, {
423423
balance: '0x8ac7230489e80000',
424424
energy: '0x5969b539627800',
425425
hasCode: false,
@@ -456,15 +456,15 @@ module.exports.nockVetRecovery = function (bitgo) {
456456
data: '0x',
457457
},
458458
],
459-
caller: '0x88c2ab227908d39f6afdb85203dca3e937bb77af',
459+
caller: `${baseAddress}`,
460460
})
461461
.reply(200, [
462462
{
463463
data: '0x',
464464
events: [],
465465
transfers: [
466466
{
467-
sender: '0x880ff4718587d678e78fc7803b3634bd12ecf019',
467+
sender: `${baseAddress}`,
468468
recipient: '0xac05da78464520aa7c9d4c19bd7a440b111b3054',
469469
amount: '0x8ac7230489e80000',
470470
},
@@ -481,7 +481,7 @@ module.exports.nockVetRecovery = function (bitgo) {
481481
{
482482
to: '0x0000000000000000000000000000456E65726779',
483483
value: '0x0',
484-
data: '0x70a0823100000000000000000000000088c2ab227908d39f6afdb85203dca3e937bb77af',
484+
data: `0x70a08231000000000000000000000000${baseAddress.slice(2)}`,
485485
},
486486
],
487487
})

modules/bitgo/test/v2/unit/recovery.ts

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1465,9 +1465,9 @@ describe('Recovery:', function () {
14651465
let recoveryParams;
14661466

14671467
it('should construct a recovery tx with MPCv2 TSS', async function () {
1468-
recoveryNocks.nockVetRecovery(bitgo);
14691468
const basecoin = bitgo.coin('tvet');
14701469
const baseAddress = ethLikeDKLSKeycard.senderAddress;
1470+
recoveryNocks.nockVetRecovery(bitgo, baseAddress);
14711471
recoveryParams = {
14721472
userKey: ethLikeDKLSKeycard.userKey,
14731473
backupKey: ethLikeDKLSKeycard.backupKey,
@@ -1484,48 +1484,21 @@ describe('Recovery:', function () {
14841484
recovery.should.have.property('tx');
14851485
});
14861486

1487-
// it('should construct an unsigned sweep tx with TSS', async function () {
1488-
// recoveryNocks.nockEthLikeRecovery(bitgo, nockUnsignedSweepTSSData);
1489-
//
1490-
// const basecoin = bitgo.coin('hteth');
1491-
//
1492-
// const userKey =
1493-
// '0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
1494-
// const backupKey =
1495-
// '0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
1496-
//
1497-
// recoveryParams = {
1498-
// userKey: userKey,
1499-
// backupKey: backupKey,
1500-
// walletContractAddress: '0xe7406dc43d13f698fb41a345c7783d39a4c2d191',
1501-
// recoveryDestination: '0xac05da78464520aa7c9d4c19bd7a440b111b3054',
1502-
// walletPassphrase: TestBitGo.V2.TEST_RECOVERY_PASSCODE,
1503-
// isTss: true,
1504-
// gasPrice: '20000000000',
1505-
// gasLimit: '500000',
1506-
// replayProtectionOptions: {
1507-
// chain: 42,
1508-
// hardfork: 'london',
1509-
// },
1510-
// };
1511-
//
1512-
// const transaction = await basecoin.recover(recoveryParams);
1513-
// should.exist(transaction);
1514-
// const output = transaction as unknown as UnsignedSweepTxMPCv2;
1515-
// output.should.have.property('txRequests');
1516-
// output.txRequests.should.have.length(1);
1517-
// output.txRequests[0].should.have.property('transactions');
1518-
// output.txRequests[0].transactions.should.have.length(1);
1519-
// output.txRequests[0].should.have.property('walletCoin');
1520-
// output.txRequests[0].transactions[0].should.have.property('unsignedTx');
1521-
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('serializedTxHex');
1522-
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('signableHex');
1523-
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('derivationPath');
1524-
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('feeInfo');
1525-
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('parsedTx');
1526-
// const parsedTx = output.txRequests[0].transactions[0].unsignedTx.parsedTx as { spendAmount: string };
1527-
// parsedTx.should.have.property('spendAmount');
1528-
// (output.txRequests[0].transactions[0].unsignedTx.parsedTx as { outputs: any[] }).should.have.property('outputs');
1529-
// });
1487+
it('should construct an unsigned sweep tx with TSS', async function () {
1488+
recoveryNocks.nockVetRecovery(bitgo, '0xad848d2c97a08b2cd5e7f28f76ecd45dd0f82e0e');
1489+
const basecoin = bitgo.coin('tvet');
1490+
1491+
const unsignedSweepRecoveryParams = {
1492+
bitgoKey:
1493+
'03f54983c529802697d9a2320ded23eb7f15118fcba01156356c2264f04d32b4caa77fcf8cf3f73547078e984f28787c4c1e694586214b609e45b6de9cc32ad6e5',
1494+
recoveryDestination: ethLikeDKLSKeycard.destinationAddress,
1495+
};
1496+
1497+
const recovery = await basecoin.recover(unsignedSweepRecoveryParams);
1498+
should.exist(recovery);
1499+
recovery.should.have.property('txHex');
1500+
recovery.should.have.property('coin');
1501+
recovery.coin.should.equal('tvet');
1502+
});
15301503
});
15311504
});

modules/sdk-coin-vet/src/lib/types.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ export interface ClaimRewardsData {
1717
}
1818

1919
export type RecoverOptions = {
20-
userKey: string;
21-
backupKey: string;
20+
userKey?: string;
21+
backupKey?: string;
2222
walletPassphrase?: string;
23-
walletContractAddress: string; // use this as walletBaseAddress for TSS
2423
recoveryDestination: string;
2524
isUnsignedSweep?: boolean; // specify if this is an unsigned recovery
25+
bitgoKey?: string;
2626
};
2727

2828
export interface RecoveryTransaction {

modules/sdk-coin-vet/src/vet.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
} from './lib/types';
4444
import { VetTransactionExplanation } from './lib/iface';
4545
import { AVG_GAS_UNITS, COEF_DIVISOR, EXPIRATION, GAS_PRICE_COEF, GAS_UNIT_PRICE } from './lib/constants';
46+
import * as mpc from '@bitgo/sdk-lib-mpc';
4647

4748
interface FeeEstimateData {
4849
gas: string;
@@ -331,7 +332,22 @@ export class Vet extends BaseCoin {
331332
const MPC = new Ecdsa();
332333

333334
if (isUnsignedSweep) {
334-
throw new Error('Unsigned sweep recovery is not supported for VET');
335+
const bitgoKey = params.bitgoKey;
336+
if (!bitgoKey) {
337+
throw new Error('missing bitgoKey');
338+
}
339+
340+
const hdTree = new mpc.Secp256k1Bip32HdTree();
341+
const derivationPath = 'm/0';
342+
const derivedPub = hdTree.publicDerive(
343+
{
344+
pk: mpc.bigIntFromBufferBE(Buffer.from(bitgoKey.slice(0, 66), 'hex')),
345+
chaincode: mpc.bigIntFromBufferBE(Buffer.from(bitgoKey.slice(66), 'hex')),
346+
},
347+
derivationPath
348+
);
349+
350+
publicKey = mpc.bigIntToBufferBE(derivedPub.pk).toString('hex');
335351
} else {
336352
if (!params.userKey) {
337353
throw new Error('missing userKey');
@@ -370,6 +386,14 @@ export class Vet extends BaseCoin {
370386

371387
const signableHex = await tx.signablePayload;
372388
const serializedTxHex = await tx.toBroadcastFormat();
389+
390+
if (isUnsignedSweep) {
391+
return {
392+
txHex: serializedTxHex,
393+
coin: this.getChain(),
394+
};
395+
}
396+
373397
const signableMessage = this.getHashFunction().update(signableHex).digest();
374398

375399
const signatureObj = await ECDSAUtils.signRecoveryMpcV2(

0 commit comments

Comments
 (0)