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
10 changes: 5 additions & 5 deletions modules/bitgo/test/v2/lib/recovery-nocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,10 +416,10 @@ module.exports.nockEthLikeRecovery = function (bitgo, nockData = nockEthData) {
});
};

module.exports.nockVetRecovery = function (bitgo) {
module.exports.nockVetRecovery = function (bitgo, baseAddress) {
// nock for account balance
const url = Environments[bitgo.getEnv()].vetNodeUrl;
nock(url).get('/accounts/0x88c2ab227908d39f6afdb85203dca3e937bb77af').reply(200, {
nock(url).get(`/accounts/${baseAddress}`).reply(200, {
balance: '0x8ac7230489e80000',
energy: '0x5969b539627800',
hasCode: false,
Expand Down Expand Up @@ -456,15 +456,15 @@ module.exports.nockVetRecovery = function (bitgo) {
data: '0x',
},
],
caller: '0x88c2ab227908d39f6afdb85203dca3e937bb77af',
caller: `${baseAddress}`,
})
.reply(200, [
{
data: '0x',
events: [],
transfers: [
{
sender: '0x880ff4718587d678e78fc7803b3634bd12ecf019',
sender: `${baseAddress}`,
recipient: '0xac05da78464520aa7c9d4c19bd7a440b111b3054',
amount: '0x8ac7230489e80000',
},
Expand All @@ -481,7 +481,7 @@ module.exports.nockVetRecovery = function (bitgo) {
{
to: '0x0000000000000000000000000000456E65726779',
value: '0x0',
data: '0x70a0823100000000000000000000000088c2ab227908d39f6afdb85203dca3e937bb77af',
data: `0x70a08231000000000000000000000000${baseAddress.slice(2)}`,
},
],
})
Expand Down
61 changes: 17 additions & 44 deletions modules/bitgo/test/v2/unit/recovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1465,9 +1465,9 @@ describe('Recovery:', function () {
let recoveryParams;

it('should construct a recovery tx with MPCv2 TSS', async function () {
recoveryNocks.nockVetRecovery(bitgo);
const basecoin = bitgo.coin('tvet');
const baseAddress = ethLikeDKLSKeycard.senderAddress;
recoveryNocks.nockVetRecovery(bitgo, baseAddress);
recoveryParams = {
userKey: ethLikeDKLSKeycard.userKey,
backupKey: ethLikeDKLSKeycard.backupKey,
Expand All @@ -1484,48 +1484,21 @@ describe('Recovery:', function () {
recovery.should.have.property('tx');
});

// it('should construct an unsigned sweep tx with TSS', async function () {
// recoveryNocks.nockEthLikeRecovery(bitgo, nockUnsignedSweepTSSData);
//
// const basecoin = bitgo.coin('hteth');
//
// const userKey =
// '0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
// const backupKey =
// '0234eb39b22fed523ece7c78da29ba1f1de5b64a6e48013e0914de793bc1df0570e779de04758732734d97e54b782c8b336283811af6a2c57bd81438798e1c2446';
//
// recoveryParams = {
// userKey: userKey,
// backupKey: backupKey,
// walletContractAddress: '0xe7406dc43d13f698fb41a345c7783d39a4c2d191',
// recoveryDestination: '0xac05da78464520aa7c9d4c19bd7a440b111b3054',
// walletPassphrase: TestBitGo.V2.TEST_RECOVERY_PASSCODE,
// isTss: true,
// gasPrice: '20000000000',
// gasLimit: '500000',
// replayProtectionOptions: {
// chain: 42,
// hardfork: 'london',
// },
// };
//
// const transaction = await basecoin.recover(recoveryParams);
// should.exist(transaction);
// const output = transaction as unknown as UnsignedSweepTxMPCv2;
// output.should.have.property('txRequests');
// output.txRequests.should.have.length(1);
// output.txRequests[0].should.have.property('transactions');
// output.txRequests[0].transactions.should.have.length(1);
// output.txRequests[0].should.have.property('walletCoin');
// output.txRequests[0].transactions[0].should.have.property('unsignedTx');
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('serializedTxHex');
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('signableHex');
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('derivationPath');
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('feeInfo');
// output.txRequests[0].transactions[0].unsignedTx.should.have.property('parsedTx');
// const parsedTx = output.txRequests[0].transactions[0].unsignedTx.parsedTx as { spendAmount: string };
// parsedTx.should.have.property('spendAmount');
// (output.txRequests[0].transactions[0].unsignedTx.parsedTx as { outputs: any[] }).should.have.property('outputs');
// });
it('should construct an unsigned sweep tx with TSS', async function () {
recoveryNocks.nockVetRecovery(bitgo, '0xad848d2c97a08b2cd5e7f28f76ecd45dd0f82e0e');
const basecoin = bitgo.coin('tvet');

const unsignedSweepRecoveryParams = {
bitgoKey:
'03f54983c529802697d9a2320ded23eb7f15118fcba01156356c2264f04d32b4caa77fcf8cf3f73547078e984f28787c4c1e694586214b609e45b6de9cc32ad6e5',
recoveryDestination: ethLikeDKLSKeycard.destinationAddress,
};

const recovery = await basecoin.recover(unsignedSweepRecoveryParams);
should.exist(recovery);
recovery.should.have.property('txHex');
recovery.should.have.property('coin');
recovery.coin.should.equal('tvet');
});
});
});
6 changes: 3 additions & 3 deletions modules/sdk-coin-vet/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ export interface ClaimRewardsData {
}

export type RecoverOptions = {
userKey: string;
backupKey: string;
userKey?: string;
backupKey?: string;
walletPassphrase?: string;
walletContractAddress: string; // use this as walletBaseAddress for TSS
recoveryDestination: string;
isUnsignedSweep?: boolean; // specify if this is an unsigned recovery
bitgoKey?: string;
};

export interface RecoveryTransaction {
Expand Down
26 changes: 25 additions & 1 deletion modules/sdk-coin-vet/src/vet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
} from './lib/types';
import { VetTransactionExplanation } from './lib/iface';
import { AVG_GAS_UNITS, COEF_DIVISOR, EXPIRATION, GAS_PRICE_COEF, GAS_UNIT_PRICE } from './lib/constants';
import * as mpc from '@bitgo/sdk-lib-mpc';

interface FeeEstimateData {
gas: string;
Expand Down Expand Up @@ -331,7 +332,22 @@ export class Vet extends BaseCoin {
const MPC = new Ecdsa();

if (isUnsignedSweep) {
throw new Error('Unsigned sweep recovery is not supported for VET');
const bitgoKey = params.bitgoKey;
if (!bitgoKey) {
throw new Error('missing bitgoKey');
}

const hdTree = new mpc.Secp256k1Bip32HdTree();
const derivationPath = 'm/0';
const derivedPub = hdTree.publicDerive(
{
pk: mpc.bigIntFromBufferBE(Buffer.from(bitgoKey.slice(0, 66), 'hex')),
chaincode: mpc.bigIntFromBufferBE(Buffer.from(bitgoKey.slice(66), 'hex')),
},
derivationPath
);

publicKey = mpc.bigIntToBufferBE(derivedPub.pk).toString('hex');
} else {
if (!params.userKey) {
throw new Error('missing userKey');
Expand Down Expand Up @@ -370,6 +386,14 @@ export class Vet extends BaseCoin {

const signableHex = await tx.signablePayload;
const serializedTxHex = await tx.toBroadcastFormat();

if (isUnsignedSweep) {
return {
txHex: serializedTxHex,
coin: this.getChain(),
};
}

const signableMessage = this.getHashFunction().update(signableHex).digest();

const signatureObj = await ECDSAUtils.signRecoveryMpcV2(
Expand Down