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
109 changes: 109 additions & 0 deletions modules/bitgo/test/v2/lib/recovery-nocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,115 @@ module.exports.nockVetRecovery = function (bitgo, baseAddress) {
});
};

module.exports.nockVetTokenRecovery = function (bitgo, baseAddress) {
// nock for account balance
const url = Environments[bitgo.getEnv()].vetNodeUrl;
nock(url)
.post('/accounts/*', {
clauses: [
{
to: '0x0000000000000000000000000000456E65726779',
value: '0x0',
data: `0x70a08231000000000000000000000000${baseAddress.slice(2)}`,
},
],
})
.reply(200, [
{
data: '0x000000000000000000000000000000000000000000000000416003863bd917f8',
events: [],
transfers: [],
gasUsed: 870,
reverted: false,
vmError: '',
},
]);

nock(url).get('/blocks/best').reply(200, {
number: 23107826,
id: '0x016098f2a6779c3ad2bb52ef0a3f57c770af55a77bfa1b2837266f752118ad8d',
size: 368,
parentID: '0x016098f1acffb0125ffeca9b3e2491d31574d14b55a15e912e45e8081e063e0e',
timestamp: 1761116630,
gasLimit: 40000000,
beneficiary: '0xae99cb89767a09d53e589a40cb4016974aba4b94',
gasUsed: 0,
totalScore: 218523577,
txsRoot: '0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0',
txsFeatures: 1,
stateRoot: '0x7a5e7b3b8b89958e7fdd5e14acbc79dbc419672e84d02376a43b3beebe555e33',
receiptsRoot: '0x45b0cfc220ceec5b7c1c62c4d4193d38e4eba48e8815729ce75f9c0ab0e4c1c0',
com: true,
signer: '0xae99cb89767a09d53e589a40cb4016974aba4b94',
isTrunk: true,
isFinalized: false,
baseFeePerGas: '0x9184e72a000',
transactions: [],
});

nock(url)
.post('/accounts/*', {
clauses: [
{
to: '0x0000000000000000000000000000456E65726779',
value: '0x0',
data: '0xa9059cbb000000000000000000000000ac05da78464520aa7c9d4c19bd7a440b111b305400000000000000000000000000000000000000000000000036a9d31575bcee8e',
},
],
caller: `${baseAddress}`,
})
.reply(200, [
{
data: '0x0000000000000000000000000000000000000000000000000000000000000001',
events: [
{
address: '0x0000000000000000000000000000456e65726779',
topics: [
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
'0x000000000000000000000000880ff4718587d678e78fc7803b3634bd12ecf019',
'0x000000000000000000000000ac05da78464520aa7c9d4c19bd7a440b111b3054',
],
data: '0x00000000000000000000000000000000000000000000000036a9d31575bcee8e',
},
],
transfers: [],
gasUsed: 13326,
reverted: false,
vmError: '',
},
]);
// nock for vtho balance for gas
nock(url)
.post('/accounts/*', {
clauses: [
{
to: '0x0000000000000000000000000000456E65726779',
value: '0x0',
data: `0x70a08231000000000000000000000000${baseAddress.slice(2)}`,
},
],
})
.reply(200, [
{
data: '0x000000000000000000000000000000000000000000000000416003863bd917f8',
events: [],
transfers: [],
gasUsed: 870,
reverted: false,
vmError: '',
},
]);

nock(url)
.post('/transactions', {
raw: /^0x[0-9a-f]+$/i,
})
.reply(200, {
id: '0x' + 'a'.repeat(64), // A fake transaction ID
reverted: false,
});
};

module.exports.nockEtherscanRateLimitError = function () {
const response = {
status: '0',
Expand Down
38 changes: 38 additions & 0 deletions modules/bitgo/test/v2/unit/recovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1500,5 +1500,43 @@ describe('Recovery:', function () {
recovery.should.have.property('coin');
recovery.coin.should.equal('tvet');
});

it('should construct a token(vtho) recovery tx with MPCv2 TSS', async function () {
const basecoin = bitgo.coin('tvet:vtho');
const baseAddress = ethLikeDKLSKeycard.senderAddress;
recoveryNocks.nockVetTokenRecovery(bitgo, baseAddress);
recoveryParams = {
userKey: ethLikeDKLSKeycard.userKey,
backupKey: ethLikeDKLSKeycard.backupKey,
walletContractAddress: baseAddress,
recoveryDestination: ethLikeDKLSKeycard.destinationAddress,
walletPassphrase: ethLikeDKLSKeycard.walletPassphrase,
tokenContractAddress: '0x0000000000000000000000000000456E65726779',
};

const recovery = await basecoin.recover(recoveryParams);

should.exist(recovery);
recovery.should.have.property('id');
recovery.should.have.property('tx');
});

it('should construct an unsigned sweep token tx(vtho) with TSS', async function () {
recoveryNocks.nockVetTokenRecovery(bitgo, '0xad848d2c97a08b2cd5e7f28f76ecd45dd0f82e0e');
const basecoin = bitgo.coin('tvet:vtho');

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

const recovery = await basecoin.recover(unsignedSweepRecoveryParams);
should.exist(recovery);
recovery.should.have.property('txHex');
recovery.should.have.property('coin');
recovery.coin.should.equal('tvet:vtho');
});
});
});
7 changes: 7 additions & 0 deletions modules/sdk-coin-vet/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,10 @@ export const EXPIRATION = 400;
export const GAS_PRICE_COEF = '128';
export const GAS_UNIT_PRICE = '10000000000000'; // vechain has fixed gas unit price of 10^13 wei
export const COEF_DIVISOR = '255';

export const feeEstimateData = {
gas: AVG_GAS_UNITS,
gasUnitPrice: GAS_UNIT_PRICE,
gasPriceCoef: GAS_PRICE_COEF,
coefDivisor: COEF_DIVISOR,
};
1 change: 1 addition & 0 deletions modules/sdk-coin-vet/src/lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export type RecoverOptions = {
recoveryDestination: string;
isUnsignedSweep?: boolean; // specify if this is an unsigned recovery
bitgoKey?: string;
tokenContractAddress?: string;
};

export interface RecoveryTransaction {
Expand Down
18 changes: 3 additions & 15 deletions modules/sdk-coin-vet/src/vet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import {
VetParseTransactionOptions,
} 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 { AVG_GAS_UNITS, EXPIRATION, GAS_PRICE_COEF, feeEstimateData } from './lib/constants';

interface FeeEstimateData {
gas: string;
Expand All @@ -52,13 +52,6 @@ interface FeeEstimateData {
coefDivisor: string;
}

const feeEstimateData: FeeEstimateData = {
gas: AVG_GAS_UNITS,
gasUnitPrice: GAS_UNIT_PRICE,
gasPriceCoef: GAS_PRICE_COEF,
coefDivisor: COEF_DIVISOR,
};

/**
* Full Name: Vechain
* Docs: https://docs.vechain.org/
Expand Down Expand Up @@ -419,11 +412,6 @@ export class Vet extends BaseCoin {

const signedTx = await txBuilder.build();

// broadcast this transaction
await this.broadcastTransaction({
serializedSignedTransaction: signedTx.toBroadcastFormat(),
});

return {
id: signedTx.id,
tx: signedTx.toBroadcastFormat(),
Expand All @@ -447,7 +435,7 @@ export class Vet extends BaseCoin {
* @param {BigNumber} estimatedGasLimit - The estimated gas limit for the transaction.
* @returns {BigNumber} The calculated transaction fee.
*/
private calculateFee(feeEstimateData: FeeEstimateData, estimatedGasLimit: BigNumber): BigNumber {
protected calculateFee(feeEstimateData: FeeEstimateData, estimatedGasLimit: BigNumber): BigNumber {
const gasLimit = estimatedGasLimit;
const adjustmentFactor = new BigNumber(1).plus(
new BigNumber(feeEstimateData.gasPriceCoef)
Expand Down Expand Up @@ -630,7 +618,7 @@ export class Vet extends BaseCoin {
* @returns {Promise<Transaction>} A promise that resolves to the built recovery transaction.
* @throws {Error} If there's no VET balance to recover or if there's an error building the transaction.
*/
private async buildRecoveryTransaction(buildParams: {
protected async buildRecoveryTransaction(buildParams: {
baseAddress: string;
params: RecoverOptions;
}): Promise<Transaction> {
Expand Down
Loading