Skip to content

fix(sdk-coin-trx): fees on freeze, vote transactions #6332

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
wants to merge 1 commit into from
Closed
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
31 changes: 28 additions & 3 deletions modules/sdk-coin-trx/src/lib/freezeBalanceTxBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { createHash } from 'crypto';
import { TransactionType, BaseKey, ExtendTransactionError, BuildTransactionError, SigningError } from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import {
TransactionType,
BaseKey,
ExtendTransactionError,
BuildTransactionError,
SigningError,
InvalidParameterValueError,
} from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig, TronNetwork } from '@bitgo/statics';
import { TransactionBuilder } from './transactionBuilder';
import { Transaction } from './transaction';
import { TransactionReceipt, FreezeBalanceV2Contract } from './iface';
import { Fee, TransactionReceipt, FreezeBalanceV2Contract } from './iface';
import {
decodeTransaction,
getByteArrayFromHexAddress,
Expand All @@ -14,11 +21,13 @@ import {
import { protocol } from '../../resources/protobuf/tron';

import ContractType = protocol.Transaction.Contract.ContractType;
import BigNumber from 'bignumber.js';

export class FreezeBalanceTxBuilder extends TransactionBuilder {
protected _signingKeys: BaseKey[];
private _frozenBalance: string;
private _resource: string;
private _fee: Fee;

constructor(_coinConfig: Readonly<CoinConfig>) {
super(_coinConfig);
Expand Down Expand Up @@ -93,12 +102,23 @@ export class FreezeBalanceTxBuilder extends TransactionBuilder {
this._refBlockHash = rawData.ref_block_hash;
this._expiration = rawData.expiration;
this._timestamp = rawData.timestamp;
this._fee = { feeLimit: rawData.fee_limit!.toString() };
this.transaction.setTransactionType(TransactionType.StakingActivate);
const contractCall = rawData.contract[0] as FreezeBalanceV2Contract;
this.initFreezeContractCall(contractCall);
return this;
}

fee(fee: Fee): this {
const feeLimit = new BigNumber(fee.feeLimit);
const tronNetwork = this._coinConfig.network as TronNetwork;
if (feeLimit.isNaN() || feeLimit.isLessThan(0) || feeLimit.isGreaterThan(tronNetwork.maxFeeLimit)) {
throw new InvalidParameterValueError('Invalid fee limit value');
}
this._fee = fee;
return this;
}

/**
* Initialize the freeze contract call specific data
*
Expand Down Expand Up @@ -183,6 +203,7 @@ export class FreezeBalanceTxBuilder extends TransactionBuilder {
expiration: this._expiration || Date.now() + TRANSACTION_DEFAULT_EXPIRATION,
timestamp: this._timestamp || Date.now(),
contract: [txContract],
feeLimit: parseInt(this._fee.feeLimit, 10),
};
const rawTx = protocol.Transaction.raw.create(raw);
return Buffer.from(protocol.Transaction.raw.encode(rawTx).finish()).toString('hex');
Expand Down Expand Up @@ -239,5 +260,9 @@ export class FreezeBalanceTxBuilder extends TransactionBuilder {
if (!this._refBlockBytes || !this._refBlockHash) {
throw new BuildTransactionError('Missing block reference information');
}

if (!this._fee) {
throw new BuildTransactionError('Missing fee');
}
}
}
31 changes: 28 additions & 3 deletions modules/sdk-coin-trx/src/lib/voteWitnessTxBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { createHash } from 'crypto';
import { TransactionType, BaseKey, BuildTransactionError, SigningError, ExtendTransactionError } from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig } from '@bitgo/statics';
import {
TransactionType,
BaseKey,
BuildTransactionError,
SigningError,
ExtendTransactionError,
InvalidParameterValueError,
} from '@bitgo/sdk-core';
import { BaseCoin as CoinConfig, TronNetwork } from '@bitgo/statics';
import { TransactionBuilder } from './transactionBuilder';
import { Transaction } from './transaction';
import { TransactionReceipt, VoteWitnessData, VoteWitnessContract } from './iface';
import { TransactionReceipt, VoteWitnessData, VoteWitnessContract, Fee } from './iface';
import {
decodeTransaction,
getHexAddressFromBase58Address,
Expand All @@ -15,10 +22,12 @@ import {
import { protocol } from '../../resources/protobuf/tron';

import ContractType = protocol.Transaction.Contract.ContractType;
import BigNumber from 'bignumber.js';

export class VoteWitnessTxBuilder extends TransactionBuilder {
protected _signingKeys: BaseKey[];
private _votes: VoteWitnessData[];
private _fee: Fee;

constructor(_coinConfig: Readonly<CoinConfig>) {
super(_coinConfig);
Expand Down Expand Up @@ -85,12 +94,23 @@ export class VoteWitnessTxBuilder extends TransactionBuilder {
this._refBlockHash = rawData.ref_block_hash;
this._expiration = rawData.expiration;
this._timestamp = rawData.timestamp;
this._fee = { feeLimit: rawData.fee_limit!.toString() };
this.transaction.setTransactionType(TransactionType.StakingVote);
const contractCall = rawData.contract[0] as VoteWitnessContract;
this.initVoteWitnessContractCall(contractCall);
return this;
}

fee(fee: Fee): this {
const feeLimit = new BigNumber(fee.feeLimit);
const tronNetwork = this._coinConfig.network as TronNetwork;
if (feeLimit.isNaN() || feeLimit.isLessThan(0) || feeLimit.isGreaterThan(tronNetwork.maxFeeLimit)) {
throw new InvalidParameterValueError('Invalid fee limit value');
}
this._fee = fee;
return this;
}

/**
* Initialize the votewitnesscontract call specific data
*
Expand Down Expand Up @@ -182,6 +202,7 @@ export class VoteWitnessTxBuilder extends TransactionBuilder {
expiration: this._expiration || Date.now() + TRANSACTION_DEFAULT_EXPIRATION,
timestamp: this._timestamp || Date.now(),
contract: [txContract],
feeLimit: parseInt(this._fee.feeLimit, 10),
};
const rawTx = protocol.Transaction.raw.create(raw);
return Buffer.from(protocol.Transaction.raw.encode(rawTx).finish()).toString('hex');
Expand Down Expand Up @@ -250,5 +271,9 @@ export class VoteWitnessTxBuilder extends TransactionBuilder {
if (!this._votes || this._votes.length === 0) {
throw new BuildTransactionError('Missing or empty votes array');
}

if (!this._fee) {
throw new BuildTransactionError('Missing fee');
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
RESOURCE_ENERGY,
FROZEN_BALANCE,
FREEZE_BALANCE_V2_CONTRACT,
FEE_LIMIT,
} from '../../resources';
import { getBuilder } from '../../../src/lib/builder';
import { Transaction, WrappedBuilder } from '../../../src';
Expand All @@ -20,7 +21,8 @@ describe('Tron FreezeBalanceV2 builder', function () {
.source({ address: PARTICIPANTS.custodian.address })
.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH })
.setFrozenBalance(FROZEN_BALANCE)
.setResource(RESOURCE_ENERGY);
.setResource(RESOURCE_ENERGY)
.fee({ feeLimit: FEE_LIMIT });

return builder;
};
Expand Down Expand Up @@ -262,9 +264,10 @@ describe('Tron FreezeBalanceV2 builder', function () {
builder
.source({ address: PARTICIPANTS.custodian.address })
.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH })
.fee({ feeLimit: FEE_LIMIT })
.setFrozenBalance(FROZEN_BALANCE);
builder.setResource('ENERGY');
assert.doesNotReject(() => {
await assert.doesNotReject(() => {
return builder.build();
});
});
Expand All @@ -274,9 +277,10 @@ describe('Tron FreezeBalanceV2 builder', function () {
builder
.source({ address: PARTICIPANTS.custodian.address })
.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH })
.fee({ feeLimit: FEE_LIMIT })
.setFrozenBalance(FROZEN_BALANCE);
builder.setResource('BANDWIDTH');
assert.doesNotReject(() => {
await assert.doesNotReject(() => {
return builder.build();
});
});
Expand All @@ -287,6 +291,7 @@ describe('Tron FreezeBalanceV2 builder', function () {
builder
.source({ address: PARTICIPANTS.custodian.address })
.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH })
.fee({ feeLimit: FEE_LIMIT })
.setFrozenBalance(FROZEN_BALANCE);

assert.throws(() => builder.setResource(invalidResource), `${invalidResource} is a not valid resource type.`);
Expand Down Expand Up @@ -315,7 +320,12 @@ describe('Tron FreezeBalanceV2 builder', function () {
});

txBuilder.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH });
assert.doesNotReject(() => {
await assert.rejects(txBuilder.build(), {
message: 'Missing fee',
});

txBuilder.fee({ feeLimit: FEE_LIMIT });
await assert.doesNotReject(() => {
return txBuilder.build();
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import assert from 'assert';
import { TransactionType } from '@bitgo/sdk-core';
import { describe, it } from 'node:test';
import { PARTICIPANTS, BLOCK_HASH, BLOCK_NUMBER, EXPIRATION, VOTE_WITNESS_CONTRACT } from '../../resources';
import { PARTICIPANTS, BLOCK_HASH, BLOCK_NUMBER, EXPIRATION, VOTE_WITNESS_CONTRACT, FEE_LIMIT } from '../../resources';
import { getBuilder } from '../../../src/lib/builder';
import { Transaction, WrappedBuilder } from '../../../src';

Expand All @@ -22,7 +22,8 @@ describe('Tron VoteWitnessContract builder', function () {
builder
.source({ address: PARTICIPANTS.custodian.address })
.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH })
.setVotes(voteArray);
.setVotes(voteArray)
.fee({ feeLimit: FEE_LIMIT });

return builder;
};
Expand Down Expand Up @@ -264,9 +265,10 @@ describe('Tron VoteWitnessContract builder', function () {
builder
.source({ address: PARTICIPANTS.custodian.address })
.block({ number: BLOCK_NUMBER, hash: BLOCK_HASH })
.fee({ feeLimit: FEE_LIMIT })
.setVotes(voteArray);

assert.doesNotReject(() => {
await assert.doesNotReject(() => {
return builder.build();
});
});
Expand Down Expand Up @@ -335,7 +337,12 @@ describe('Tron VoteWitnessContract builder', function () {
});

txBuilder.setVotes(voteArray);
assert.doesNotReject(() => {
await assert.rejects(txBuilder.build(), {
message: 'Missing fee',
});

txBuilder.fee({ feeLimit: FEE_LIMIT });
await assert.doesNotReject(() => {
return txBuilder.build();
});
});
Expand Down