diff --git a/modules/sdk-coin-vet/src/lib/constants.ts b/modules/sdk-coin-vet/src/lib/constants.ts index 2d7873733c..73120e9e90 100644 --- a/modules/sdk-coin-vet/src/lib/constants.ts +++ b/modules/sdk-coin-vet/src/lib/constants.ts @@ -6,7 +6,7 @@ export const ZERO_VALUE_AMOUNT = '0'; export const TRANSFER_TOKEN_METHOD_ID = '0xa9059cbb'; export const STAKING_METHOD_ID = '0xd8da3bbf'; export const STAKE_CLAUSE_METHOD_ID = '0x604f2177'; -export const DELEGATE_CLAUSE_METHOD_ID = '0x3207555d'; +export const DELEGATE_CLAUSE_METHOD_ID = '0x08bbb824'; export const EXIT_DELEGATION_METHOD_ID = '0x69e79b7d'; export const BURN_NFT_METHOD_ID = '0x2e17de78'; export const TRANSFER_NFT_METHOD_ID = '0x23b872dd'; @@ -15,9 +15,10 @@ export const CLAIM_STAKING_REWARDS_METHOD_ID = '0x0962ef79'; // claimRewards(uin export const STARGATE_NFT_ADDRESS = '0x1856c533ac2d94340aaa8544d35a5c1d4a21dee7'; export const STARGATE_DELEGATION_ADDRESS = '0x4cb1c9ef05b529c093371264fab2c93cc6cddb0e'; +export const STARGATE_DELEGATION_ADDRESS_TESTNET = '0x7240e3bc0d26431512d5b67dbd26d199205bffe8'; export const STARGATE_NFT_ADDRESS_TESTNET = '0x1ec1d168574603ec35b9d229843b7c2b44bcb770'; -export const STARGATE_DELEGATION_ADDRESS_TESTNET = '0x7240e3bc0d26431512d5b67dbd26d199205bffe8'; +export const STARGATE_CONTRACT_ADDRESS_TESTNET = '0x1e02b2953adefec225cf0ec49805b1146a4429c1'; export const AVG_GAS_UNITS = '21000'; export const EXPIRATION = 400; diff --git a/modules/sdk-coin-vet/src/lib/iface.ts b/modules/sdk-coin-vet/src/lib/iface.ts index 0541f4dc4c..b927e21035 100644 --- a/modules/sdk-coin-vet/src/lib/iface.ts +++ b/modules/sdk-coin-vet/src/lib/iface.ts @@ -28,10 +28,12 @@ export interface VetTransactionData { tokenId?: string; // Added for unstaking and burn NFT transactions stakingContractAddress?: string; amountToStake?: string; + levelId?: number; // NFT tier level nftTokenId?: number; // Used as tier level (levelId) for stakeAndDelegate method (not the actual NFT token ID) autorenew?: boolean; // Autorenew flag for stakeAndDelegate method nftCollectionId?: string; claimRewardsData?: ClaimRewardsData; + validatorAddress?: string; } export interface VetTransactionExplanation extends BaseTransactionExplanation { diff --git a/modules/sdk-coin-vet/src/lib/transaction/delegateClauseTransaction.ts b/modules/sdk-coin-vet/src/lib/transaction/delegateClauseTransaction.ts index c588e16010..2bb2ac271e 100644 --- a/modules/sdk-coin-vet/src/lib/transaction/delegateClauseTransaction.ts +++ b/modules/sdk-coin-vet/src/lib/transaction/delegateClauseTransaction.ts @@ -6,19 +6,27 @@ import { VetTransactionData } from '../iface'; import EthereumAbi from 'ethereumjs-abi'; import utils from '../utils'; import BigNumber from 'bignumber.js'; -import { addHexPrefix } from 'ethereumjs-util'; +import { addHexPrefix, BN } from 'ethereumjs-util'; import { ZERO_VALUE_AMOUNT } from '../constants'; export class DelegateClauseTransaction extends Transaction { private _stakingContractAddress: string; - private _tokenId: number; - private _delegateForever = true; + private _tokenId: string; + private _validator: string; constructor(_coinConfig: Readonly) { super(_coinConfig); this._type = TransactionType.StakingDelegate; } + get validator(): string { + return this._validator; + } + + set validator(address: string) { + this._validator = address; + } + get stakingContractAddress(): string { return this._stakingContractAddress; } @@ -27,22 +35,14 @@ export class DelegateClauseTransaction extends Transaction { this._stakingContractAddress = address; } - get tokenId(): number { + get tokenId(): string { return this._tokenId; } - set tokenId(tokenId: number) { + set tokenId(tokenId: string) { this._tokenId = tokenId; } - get delegateForever(): boolean { - return this._delegateForever; - } - - set delegateForever(delegateForever: boolean) { - this._delegateForever = delegateForever; - } - buildClauses(): void { if (!this.stakingContractAddress) { throw new Error('Staking contract address is not set'); @@ -54,7 +54,11 @@ export class DelegateClauseTransaction extends Transaction { throw new Error('Token ID is not set'); } - const data = this.getDelegateData(this.tokenId, this.delegateForever); + if (this.validator === undefined || this.validator === null) { + throw new Error('Validator address is not set'); + } + + const data = this.getDelegateData(this.tokenId, this.validator); this._transactionData = data; // Create the clause for delegation @@ -80,10 +84,10 @@ export class DelegateClauseTransaction extends Transaction { * @param {number} tokenId - The Token ID for delegation * @returns {string} - The encoded transaction data */ - getDelegateData(levelId: number, delegateForever = true): string { + getDelegateData(tokenId: string, validatorAddress: string): string { const methodName = 'delegate'; - const types = ['uint256', 'bool']; - const params = [levelId, delegateForever]; + const types = ['uint256', 'address']; + const params = [new BN(tokenId), validatorAddress]; const method = EthereumAbi.methodID(methodName, types); const args = EthereumAbi.rawEncode(types, params); @@ -107,8 +111,8 @@ export class DelegateClauseTransaction extends Transaction { to: this.stakingContractAddress, stakingContractAddress: this.stakingContractAddress, amountToStake: ZERO_VALUE_AMOUNT, - nftTokenId: this.tokenId, - autorenew: this.delegateForever, + tokenId: this.tokenId, + validatorAddress: this.validator, }; return json; @@ -144,7 +148,7 @@ export class DelegateClauseTransaction extends Transaction { this.transactionData = clause.data; const decoded = utils.decodeDelegateClauseData(clause.data); this.tokenId = decoded.tokenId; - this.delegateForever = decoded.delegateForever; + this.validator = decoded.validator; } } diff --git a/modules/sdk-coin-vet/src/lib/transaction/stakeClauseTransaction.ts b/modules/sdk-coin-vet/src/lib/transaction/stakeClauseTransaction.ts index 4fb2aafca1..57ad27d449 100644 --- a/modules/sdk-coin-vet/src/lib/transaction/stakeClauseTransaction.ts +++ b/modules/sdk-coin-vet/src/lib/transaction/stakeClauseTransaction.ts @@ -110,7 +110,7 @@ export class StakeClauseTransaction extends Transaction { to: this.stakingContractAddress, stakingContractAddress: this.stakingContractAddress, amountToStake: this.amountToStake, - nftTokenId: this.levelId, + levelId: this.levelId, }; return json; @@ -143,7 +143,7 @@ export class StakeClauseTransaction extends Transaction { this.stakingContractAddress = clause.to; } if (clause.value) { - this.amountToStake = String(clause.value); + this.amountToStake = new BigNumber(clause.value).toFixed(); } if (clause.data) { this.transactionData = clause.data; diff --git a/modules/sdk-coin-vet/src/lib/transactionBuilder/delegateTxnBuilder.ts b/modules/sdk-coin-vet/src/lib/transactionBuilder/delegateTxnBuilder.ts index 137c23758e..3c358489d3 100644 --- a/modules/sdk-coin-vet/src/lib/transactionBuilder/delegateTxnBuilder.ts +++ b/modules/sdk-coin-vet/src/lib/transactionBuilder/delegateTxnBuilder.ts @@ -88,14 +88,28 @@ export class DelegateTxnBuilder extends TransactionBuilder { /** * Sets the token ID for this delegate tx. * - * @param {number} levelId - The level ID for staking + * @param {number} levelId - The NFT token ID * @returns {DelegateTxnBuilder} This transaction builder */ - tokenId(tokenId: number): this { + tokenId(tokenId: string): this { this.delegateTransaction.tokenId = tokenId; return this; } + /** + * Sets the validator address for this delegate tx. + * @param {string} address - The validator address + * @returns {DelegateTxnBuilder} This transaction builder + */ + validator(address: string): this { + if (!address) { + throw new Error('Validator address is required'); + } + this.validateAddress({ address }); + this.delegateTransaction.validator = address; + return this; + } + /** * Sets the transaction data for this delegate tx. * @@ -115,7 +129,7 @@ export class DelegateTxnBuilder extends TransactionBuilder { assert(transaction.stakingContractAddress, 'Staking contract address is required'); assert(transaction.tokenId, 'Token ID is required'); - assert(transaction.delegateForever, 'delegate forever flag is required'); + assert(transaction.validator, 'Validator address is required'); this.validateAddress({ address: transaction.stakingContractAddress }); } diff --git a/modules/sdk-coin-vet/src/lib/utils.ts b/modules/sdk-coin-vet/src/lib/utils.ts index 90d1858af0..01310b5f73 100644 --- a/modules/sdk-coin-vet/src/lib/utils.ts +++ b/modules/sdk-coin-vet/src/lib/utils.ts @@ -23,8 +23,9 @@ import { STARGATE_NFT_ADDRESS, STARGATE_NFT_ADDRESS_TESTNET, STARGATE_DELEGATION_ADDRESS, - STARGATE_DELEGATION_ADDRESS_TESTNET, DELEGATE_CLAUSE_METHOD_ID, + STARGATE_CONTRACT_ADDRESS_TESTNET, + STARGATE_DELEGATION_ADDRESS_TESTNET, } from './constants'; import { KeyPair } from './keyPair'; import { BaseCoin as CoinConfig } from '@bitgo/statics'; @@ -179,21 +180,21 @@ export class Utils implements BaseUtils { } /** - * Decodes delegate transaction data to extract tokenId and delegateForever + * Decodes delegate transaction data to extract tokenId and validatorAddress * * @param {string} data - The encoded transaction data - * @returns {object} - Object containing tokenId and delegateForever + * @returns {object} - Object containing levelId and validator address */ - decodeDelegateClauseData(data: string): { tokenId: number; delegateForever: boolean } { + decodeDelegateClauseData(data: string): { tokenId: string; validator: string } { try { const parameters = data.slice(10); // Decode using ethereumjs-abi directly - const decoded = EthereumAbi.rawDecode(['uint256', 'bool'], Buffer.from(parameters, 'hex')); + const decoded = EthereumAbi.rawDecode(['uint256', 'address'], Buffer.from(parameters, 'hex')); return { - tokenId: Number(decoded[0]), - delegateForever: Boolean(decoded[1]), + tokenId: String(decoded[0]), + validator: String(decoded[1]), }; } catch (error) { throw new Error(`Failed to decode delegation data: ${error.message}`); @@ -298,13 +299,13 @@ export class Utils implements BaseUtils { } /** - * Get the network-appropriate delegation contract address + * Get the network-appropriate stargate contract address * @param {CoinConfig} coinConfig - The coin configuration object * @returns {string} The delegation contract address for the network */ getDefaultDelegationAddress(coinConfig: Readonly): string { const isTestnet = coinConfig.network.type === 'testnet'; - return isTestnet ? STARGATE_DELEGATION_ADDRESS_TESTNET : STARGATE_DELEGATION_ADDRESS; + return isTestnet ? STARGATE_CONTRACT_ADDRESS_TESTNET : STARGATE_DELEGATION_ADDRESS; } /** @@ -314,7 +315,7 @@ export class Utils implements BaseUtils { */ getDefaultStakingAddress(coinConfig: Readonly): string { const isTestnet = coinConfig.network.type === 'testnet'; - return isTestnet ? STARGATE_NFT_ADDRESS_TESTNET : STARGATE_NFT_ADDRESS; + return isTestnet ? STARGATE_CONTRACT_ADDRESS_TESTNET : STARGATE_NFT_ADDRESS; } /** @@ -343,10 +344,10 @@ export class Utils implements BaseUtils { } /** - * Validate that a contract address matches the expected NFT/staking contract for the network + * Validate that a contract address matches the expected stargate address for the network * @param {string} address - The contract address to validate * @param {CoinConfig} coinConfig - The coin configuration object - * @throws {Error} If the address doesn't match the expected NFT contract address + * @throws {Error} If the address doesn't match the expected contract address */ validateStakingContractAddress(address: string, coinConfig: Readonly): void { const expectedAddress = this.getDefaultStakingAddress(coinConfig); @@ -358,7 +359,7 @@ export class Utils implements BaseUtils { } /** - * Validate that a contract address matches the expected delegation contract for the network + * Validate that a contract address matches the expected stargate contract for the network * @param {string} address - The contract address to validate * @param {CoinConfig} coinConfig - The coin configuration object * @throws {Error} If the address doesn't match the expected delegation contract address diff --git a/modules/sdk-coin-vet/test/resources/vet.ts b/modules/sdk-coin-vet/test/resources/vet.ts index fb7051113e..32dd6fb8d3 100644 --- a/modules/sdk-coin-vet/test/resources/vet.ts +++ b/modules/sdk-coin-vet/test/resources/vet.ts @@ -15,14 +15,14 @@ export const STAKING_TRANSACTION = '0xf901032788015d55fcf2457e7c40f866f864941856c533ac2d94340aaa8544d35a5c1d4a21dee7880de0b6b3a7640000b844d8da3bbf0000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000181808265848083094c53c101b882efcb9ea88e908d1a142db96c1b44dd056ea194f1ad45670c100a8c52348cc7b20387741260ebe7fe9b7594f96693c88662fa60edba5992332728222b0bdd8a30008535368bd901319eb4513d16bebc428dc8454d32a19eeb76372849a6134ebbba79f1eeceea1f6546574b945c05489222cb451f5b0e2901b0c687b750e833aeb800'; export const STAKE_CLAUSE_TRANSACTION = - '0xf8e3278801618b7b1354c4ca40f845f843941ec1d168574603ec35b9d229843b7c2b44bcb770880de0b6b3a7640000a4604f2177000000000000000000000000000000000000000000000000000000000000000881808305fd5a808307b278c101b882b380970580d957b8e7989aa9aa9281e57245fa3835cb2aaae6475b4062bb4f1c2dd2ca694df6503d5dfd654579130b3484bee75420247cf8f6b6b4b76b7939f101db6e6cef5a27375274741f3c0aba4be13a9e086337c3290866afe049efcdaa2d3227c9e12b52627c4d71f5b667821f9d33adcc4c97fdc28b93c34013d32e242300'; + '0xf8e5278801638298c53767ac40f847f845941e02b2953adefec225cf0ec49805b1146a4429c18a021e19e0c9bab2400000a4604f2177000000000000000000000000000000000000000000000000000000000000000881808306338a80830f340bc101b882b4970b0c160552162de719b9ed1fa6268bbfe9b36fd4e4a5c13e956cf539e60478f69179e8db4a3106fdbe775e3d923510b16f48da56c66076d1f66ffd822abf01ebc040c795b1e17cb0ca5ba747e3a181b4eefea7db5378f64f82361bdb7745da45aba2ace3db9822b675474552f13849052987c431cd4867813c2cf635302b1101'; export const DELEGATION_TRANSACTION = - '0xf8fb278801618aa3e0a55fc940f85ef85c947240e3bc0d26431512d5b67dbd26d199205bffe880b8443207555d00000000000000000000000000000000000000000000000000000000000187690000000000000000000000000000000000000000000000000000000000000001818082e43a808306af07c101b882fb8030f6e2ef6563ff3b0e7e2a2292c1db5fc41c7ab9f598bad370c5cfd3dc32286ae8d709e941c0312c8cd33a3505156b44d1639c73980ffa66bc72f37820f2001c0e6b6e76a6a4d806c377a0a279053eb6ea4356bd235f4396585bb071d70f992c639d45c53431a3c1493a52a136203905e42c671dd384ee5f5ead0a70cb607001'; + '0xf8fc278801640639091a26ce40f85ef85c941e02b2953adefec225cf0ec49805b1146a4429c180b84408bbb8240000000000000000000000000000000000000000000000000000000000003d2e00000000000000000000000000563ec3cafbbe7e60b04b3190e6eca66579706d8180830464b080830d8b05c101b8821a3cca8e8339456c6055ef796e5d716dda00de45f4cd9431bedf2119ae5de01b1f0a7268690784ba8f5c22b3043d0530ece5303a813ffdd9c0a5ae0ae85deee400b04543d6874f30eca88b3efb927c44934e9eb64a6f2327cce44a0a94faaca13615d153e804ba3fdd02bf5f8e1b6bc8e0f6149a1c7694803ed4fbb549bb79066101'; export const STAKING_LEVEL_ID = 8; export const STAKING_AUTORENEW = true; -export const STAKING_CONTRACT_ADDRESS = '0x1ec1d168574603ec35b9d229843b7c2b44bcb770'; +export const STAKING_CONTRACT_ADDRESS = '0x1e02b2953adefec225cf0ec49805b1146a4429c1'; export const VALID_TOKEN_SIGNABLE_PAYLOAD = 'f8762788014ead140e77bbc140f85ef85c940000000000000000000000000000456e6572677980b844a9059cbb000000000000000000000000e59f1cea4e0fef511e3d0f4eec44adf19c4cbeec000000000000000000000000000000000000000000000000016345785d8a000081808252088082faf8c101'; diff --git a/modules/sdk-coin-vet/test/transactionBuilder/burnNftBuilder.ts b/modules/sdk-coin-vet/test/transactionBuilder/burnNftBuilder.ts index 29ef361039..9ff10dd5de 100644 --- a/modules/sdk-coin-vet/test/transactionBuilder/burnNftBuilder.ts +++ b/modules/sdk-coin-vet/test/transactionBuilder/burnNftBuilder.ts @@ -4,7 +4,7 @@ import { coins } from '@bitgo/statics'; import { TransactionBuilderFactory } from '../../src'; import { BurnNftTransaction } from '../../src/lib/transaction/burnNftTransaction'; import * as testData from '../resources/vet'; -import { BURN_NFT_METHOD_ID, STARGATE_NFT_ADDRESS_TESTNET } from '../../src/lib/constants'; +import { BURN_NFT_METHOD_ID, STARGATE_CONTRACT_ADDRESS_TESTNET } from '../../src/lib/constants'; describe('Vet Burn NFT Transaction', () => { const factory = new TransactionBuilderFactory(coins.get('tvet')); @@ -16,7 +16,7 @@ describe('Vet Burn NFT Transaction', () => { txBuilder.sender(testData.addresses.validAddresses[0]); txBuilder.tokenId(tokenId); - txBuilder.nftContract(STARGATE_NFT_ADDRESS_TESTNET); + txBuilder.nftContract(STARGATE_CONTRACT_ADDRESS_TESTNET); txBuilder.gas(21000); txBuilder.nonce('64248'); txBuilder.blockRef('0x014ead140e77bbc1'); @@ -27,7 +27,7 @@ describe('Vet Burn NFT Transaction', () => { should.equal(tx.sender, testData.addresses.validAddresses[0]); should.equal(tx.tokenId, tokenId); - should.equal(tx.contract, STARGATE_NFT_ADDRESS_TESTNET); + should.equal(tx.contract, STARGATE_CONTRACT_ADDRESS_TESTNET); should.equal(tx.gas, 21000); should.equal(tx.nonce, '64248'); should.equal(tx.expiration, 64); @@ -40,7 +40,7 @@ describe('Vet Burn NFT Transaction', () => { tx.clauses.length.should.equal(1); should.exist(tx.clauses[0]); should.exist(tx.clauses[0].to); - tx.clauses[0]?.to?.should.equal(STARGATE_NFT_ADDRESS_TESTNET); + tx.clauses[0]?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); should.exist(tx.clauses[0].value); tx.clauses[0].value.should.equal('0x0'); @@ -51,14 +51,14 @@ describe('Vet Burn NFT Transaction', () => { should.equal(tx.inputs[0].value, '0'); should.equal(tx.inputs[0].coin, 'tvet'); - should.equal(tx.outputs[0].address, STARGATE_NFT_ADDRESS_TESTNET); + should.equal(tx.outputs[0].address, STARGATE_CONTRACT_ADDRESS_TESTNET); should.equal(tx.outputs[0].value, '0'); should.equal(tx.outputs[0].coin, 'tvet'); }); it('should build a burn NFT transaction with custom contract address', async function () { const tokenId = '123456'; - const customContractAddress = STARGATE_NFT_ADDRESS_TESTNET; // Use the valid testnet NFT address + const customContractAddress = STARGATE_CONTRACT_ADDRESS_TESTNET; // Use the valid testnet NFT address const txBuilder = factory.getBurnNftBuilder(); txBuilder.sender(testData.addresses.validAddresses[0]); @@ -85,7 +85,7 @@ describe('Vet Burn NFT Transaction', () => { txBuilder.sender(testData.addresses.validAddresses[0]); txBuilder.tokenId(tokenId); - txBuilder.nftContract(STARGATE_NFT_ADDRESS_TESTNET); + txBuilder.nftContract(STARGATE_CONTRACT_ADDRESS_TESTNET); txBuilder.gas(21000); txBuilder.nonce('64248'); txBuilder.blockRef('0x014ead140e77bbc1'); @@ -101,7 +101,7 @@ describe('Vet Burn NFT Transaction', () => { should.equal(deserializedTx.type, TransactionType.StakingWithdraw); should.equal(deserializedTx.tokenId, tokenId); - should.equal(deserializedTx.contract, STARGATE_NFT_ADDRESS_TESTNET); + should.equal(deserializedTx.contract, STARGATE_CONTRACT_ADDRESS_TESTNET); }); it('should validate the transaction data structure', async function () { @@ -111,7 +111,7 @@ describe('Vet Burn NFT Transaction', () => { await should(txBuilder.build()).be.rejectedWith('NFT contract address is required'); txBuilder.sender(testData.addresses.validAddresses[0]); - txBuilder.nftContract(STARGATE_NFT_ADDRESS_TESTNET); + txBuilder.nftContract(STARGATE_CONTRACT_ADDRESS_TESTNET); await should(txBuilder.build()).be.rejectedWith('Token ID is required'); // Now add the token ID and it should build successfully @@ -134,7 +134,7 @@ describe('Vet Burn NFT Transaction', () => { it('should fail with invalid token ID', async function () { const txBuilder = factory.getBurnNftBuilder(); txBuilder.sender(testData.addresses.validAddresses[0]); - txBuilder.nftContract(STARGATE_NFT_ADDRESS_TESTNET); + txBuilder.nftContract(STARGATE_CONTRACT_ADDRESS_TESTNET); txBuilder.tokenId(''); await should(txBuilder.build()).be.rejectedWith('Token ID is required'); diff --git a/modules/sdk-coin-vet/test/transactionBuilder/claimRewardsBuilder.ts b/modules/sdk-coin-vet/test/transactionBuilder/claimRewardsBuilder.ts index 0e3bb634cf..a2328b8352 100644 --- a/modules/sdk-coin-vet/test/transactionBuilder/claimRewardsBuilder.ts +++ b/modules/sdk-coin-vet/test/transactionBuilder/claimRewardsBuilder.ts @@ -5,8 +5,7 @@ import should from 'should'; import { CLAIM_BASE_REWARDS_METHOD_ID, CLAIM_STAKING_REWARDS_METHOD_ID, - STARGATE_DELEGATION_ADDRESS_TESTNET, - STARGATE_NFT_ADDRESS_TESTNET, + STARGATE_CONTRACT_ADDRESS_TESTNET, } from '../../src/lib/constants'; import { TransactionType } from '@bitgo/sdk-core'; @@ -58,7 +57,7 @@ describe('VET Claim Rewards Transaction', function () { // Find base rewards clause (claimVetGeneratedVtho) const baseRewardsClause = claimTx.clauses.find((clause) => clause.data.startsWith(CLAIM_BASE_REWARDS_METHOD_ID)); should.exist(baseRewardsClause); - baseRewardsClause?.to?.should.equal(STARGATE_NFT_ADDRESS_TESTNET); + baseRewardsClause?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); baseRewardsClause?.value.should.equal('0x0'); // Find staking rewards clause (claimRewards) @@ -66,7 +65,7 @@ describe('VET Claim Rewards Transaction', function () { clause.data.startsWith(CLAIM_STAKING_REWARDS_METHOD_ID) ); should.exist(stakingRewardsClause); - stakingRewardsClause?.to?.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + stakingRewardsClause?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); stakingRewardsClause?.value.should.equal('0x0'); // Verify recipients should be empty for claim rewards @@ -87,7 +86,7 @@ describe('VET Claim Rewards Transaction', function () { // Should have only 1 clause for base rewards claimTx.clauses.length.should.equal(1); claimTx.clauses[0].data.should.startWith(CLAIM_BASE_REWARDS_METHOD_ID); - claimTx.clauses[0].to?.should.equal(STARGATE_NFT_ADDRESS_TESTNET); + claimTx.clauses[0].to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); claimTx.clauses[0].value.should.equal('0x0'); claimTx.claimRewardsData.claimBaseRewards?.should.be.true(); @@ -108,7 +107,7 @@ describe('VET Claim Rewards Transaction', function () { // Should have only 1 clause for staking rewards claimTx.clauses.length.should.equal(1); claimTx.clauses[0].data.should.startWith(CLAIM_STAKING_REWARDS_METHOD_ID); - claimTx.clauses[0].to?.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + claimTx.clauses[0].to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); claimTx.clauses[0].value.should.equal('0x0'); claimTx.claimRewardsData.claimBaseRewards?.should.be.false(); @@ -194,8 +193,8 @@ describe('VET Claim Rewards Transaction', function () { should.exist(baseRewardsClause); should.exist(stakingRewardsClause); - baseRewardsClause?.to?.should.equal(STARGATE_NFT_ADDRESS_TESTNET); - stakingRewardsClause?.to?.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + baseRewardsClause?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); + stakingRewardsClause?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); }); it('should build transaction with undefined sender but include it in inputs', async function () { @@ -298,8 +297,8 @@ describe('VET Claim Rewards Transaction', function () { clause.data.startsWith(CLAIM_STAKING_REWARDS_METHOD_ID) ); - baseRewardsClause?.to?.should.equal(STARGATE_NFT_ADDRESS_TESTNET); - stakingRewardsClause?.to?.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + baseRewardsClause?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); + stakingRewardsClause?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); }); }); }); diff --git a/modules/sdk-coin-vet/test/transactionBuilder/delegateClauseTxnBuilder.ts b/modules/sdk-coin-vet/test/transactionBuilder/delegateClauseTxnBuilder.ts index 799d8d1f16..bded9eb271 100644 --- a/modules/sdk-coin-vet/test/transactionBuilder/delegateClauseTxnBuilder.ts +++ b/modules/sdk-coin-vet/test/transactionBuilder/delegateClauseTxnBuilder.ts @@ -1,14 +1,15 @@ import { coins } from '@bitgo/statics'; import { TransactionBuilderFactory, Transaction, DelegateClauseTransaction } from '../../src/lib'; import should from 'should'; -import { DELEGATE_CLAUSE_METHOD_ID, STARGATE_DELEGATION_ADDRESS_TESTNET } from '../../src/lib/constants'; +import { DELEGATE_CLAUSE_METHOD_ID, STARGATE_CONTRACT_ADDRESS_TESTNET } from '../../src/lib/constants'; import EthereumAbi from 'ethereumjs-abi'; import * as testData from '../resources/vet'; +import { BN } from 'ethereumjs-util'; describe('VET Delegation Transaction', function () { const factory = new TransactionBuilderFactory(coins.get('tvet')); - const tokenId = 100201; // Test level ID - const delegateForever = true; // Test delegateForever flag + const tokenId = '100201'; // Test token ID + const validatorAddress = '0x9a7aFCACc88c106f3bbD6B213CD0821D9224d945'; // Helper function to create a basic transaction builder with common properties const createBasicTxBuilder = () => { @@ -25,7 +26,7 @@ describe('VET Delegation Transaction', function () { it('should build a delegate transaction', async function () { const txBuilder = factory.getStakingDelegateBuilder(); - txBuilder.stakingContractAddress(STARGATE_DELEGATION_ADDRESS_TESTNET); + txBuilder.stakingContractAddress(STARGATE_CONTRACT_ADDRESS_TESTNET); txBuilder.tokenId(tokenId); txBuilder.sender('0x9378c12BD7502A11F770a5C1F223c959B2805dA9'); txBuilder.chainTag(0x27); // Testnet chain tag @@ -34,6 +35,7 @@ describe('VET Delegation Transaction', function () { txBuilder.gas(100000); txBuilder.gasPriceCoef(0); txBuilder.nonce('12345'); + txBuilder.validator(validatorAddress); const tx = await txBuilder.build(); should.exist(tx); @@ -41,14 +43,14 @@ describe('VET Delegation Transaction', function () { tx.should.be.instanceof(DelegateClauseTransaction); const delegationTx = tx as DelegateClauseTransaction; - delegationTx.stakingContractAddress.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + delegationTx.stakingContractAddress.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); delegationTx.tokenId.should.equal(tokenId); - delegationTx.delegateForever.should.equal(delegateForever); + delegationTx.validator.should.equal(validatorAddress); // Verify clauses delegationTx.clauses.length.should.equal(1); should.exist(delegationTx.clauses[0].to); - delegationTx.clauses[0].to?.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + delegationTx.clauses[0].to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); // Verify transaction data is correctly encoded using ethereumABI should.exist(delegationTx.clauses[0].data); @@ -57,8 +59,8 @@ describe('VET Delegation Transaction', function () { // Verify the encoded data matches what we expect from ethereumABI const methodName = 'delegate'; - const types = ['uint256', 'bool']; - const params = [tokenId, delegateForever]; + const types = ['uint256', 'address']; + const params = [new BN(tokenId), validatorAddress]; const method = EthereumAbi.methodID(methodName, types); const args = EthereumAbi.rawEncode(types, params); @@ -68,24 +70,33 @@ describe('VET Delegation Transaction', function () { // Verify recipients delegationTx.recipients.length.should.equal(1); - delegationTx.recipients[0].address.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + delegationTx.recipients[0].address.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); }); describe('Failure scenarios', function () { it('should throw error when stakingContractAddress is missing', async function () { const txBuilder = createBasicTxBuilder(); txBuilder.tokenId(tokenId); + txBuilder.validator(validatorAddress); await txBuilder.build().should.be.rejectedWith('Staking contract address is required'); }); it('should throw error when tokenId is missing', async function () { const txBuilder = createBasicTxBuilder(); - txBuilder.stakingContractAddress(STARGATE_DELEGATION_ADDRESS_TESTNET); + txBuilder.stakingContractAddress(STARGATE_CONTRACT_ADDRESS_TESTNET); await txBuilder.build().should.be.rejectedWith('Token ID is required'); }); + it('should throw error when validator address is missing', async function () { + const txBuilder = createBasicTxBuilder(); + txBuilder.stakingContractAddress(STARGATE_CONTRACT_ADDRESS_TESTNET); + txBuilder.tokenId(tokenId); + + await txBuilder.build().should.be.rejectedWith('Validator address is required'); + }); + it('should throw error when stakingContractAddress is invalid', async function () { const txBuilder = createBasicTxBuilder(); @@ -97,7 +108,7 @@ describe('VET Delegation Transaction', function () { it('should build transaction with undefined sender but include it in inputs', async function () { const txBuilder = factory.getStakingDelegateBuilder(); - txBuilder.stakingContractAddress(STARGATE_DELEGATION_ADDRESS_TESTNET); + txBuilder.stakingContractAddress(STARGATE_CONTRACT_ADDRESS_TESTNET); txBuilder.tokenId(tokenId); txBuilder.chainTag(0x27); txBuilder.blockRef('0x0000000000000000'); @@ -105,6 +116,7 @@ describe('VET Delegation Transaction', function () { txBuilder.gas(100000); txBuilder.gasPriceCoef(0); txBuilder.nonce('12345'); + txBuilder.validator(validatorAddress); // Not setting sender const tx = await txBuilder.build(); @@ -117,12 +129,12 @@ describe('VET Delegation Transaction', function () { // Verify the transaction has the correct output delegationTx.outputs.length.should.equal(1); - delegationTx.outputs[0].address.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + delegationTx.outputs[0].address.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); }); it('should use network default chainTag when not explicitly set', async function () { const txBuilder = factory.getStakingDelegateBuilder(); - txBuilder.stakingContractAddress(STARGATE_DELEGATION_ADDRESS_TESTNET); + txBuilder.stakingContractAddress(STARGATE_CONTRACT_ADDRESS_TESTNET); txBuilder.tokenId(tokenId); // Not setting chainTag txBuilder.blockRef('0x0000000000000000'); @@ -131,6 +143,7 @@ describe('VET Delegation Transaction', function () { txBuilder.gasPriceCoef(0); txBuilder.nonce('12345'); txBuilder.sender('0x9378c12BD7502A11F770a5C1F223c959B2805dA9'); + txBuilder.validator(validatorAddress); const tx = await txBuilder.build(); tx.should.be.instanceof(DelegateClauseTransaction); @@ -141,19 +154,20 @@ describe('VET Delegation Transaction', function () { }); it('should build a signed tx and validate its toJson', async function () { + const tokenIdForDelegateTxn = '15662'; const txBuilder = factory.from(testData.DELEGATION_TRANSACTION); const tx = txBuilder.transaction as DelegateClauseTransaction; const toJson = tx.toJson(); - toJson.id.should.equal('0x4d41f712736a528e85cf8cefaee61f7842a6ddd5f20977b8d97182391dee6f42'); - toJson.stakingContractAddress?.should.equal('0x7240e3bc0d26431512d5b67dbd26d199205bffe8'); - toJson.nonce.should.equal('438023'); - toJson.gas.should.equal(58426); + toJson.id.should.equal('0xc47792a421d90cb52a4aedbd9abe96f779a8ad68e508680ac3cc135428c3f4c5'); + toJson.stakingContractAddress?.should.equal('0x1e02b2953adefec225cf0ec49805b1146a4429c1'); + toJson.nonce.should.equal('887557'); + toJson.gas.should.equal(287920); toJson.gasPriceCoef.should.equal(128); toJson.expiration.should.equal(64); toJson.chainTag.should.equal(39); // in delegate txn, nftTokenId indicates the tokenId - toJson.nftTokenId?.should.equal(tokenId); - toJson.autorenew?.should.equal(true); + toJson.tokenId?.should.equal(tokenIdForDelegateTxn); + toJson.validatorAddress?.should.equal('00563ec3cafbbe7e60b04b3190e6eca66579706d'); }); }); }); diff --git a/modules/sdk-coin-vet/test/transactionBuilder/exitDelegationBuilder.ts b/modules/sdk-coin-vet/test/transactionBuilder/exitDelegationBuilder.ts index e5ff87d353..d8f35dacb2 100644 --- a/modules/sdk-coin-vet/test/transactionBuilder/exitDelegationBuilder.ts +++ b/modules/sdk-coin-vet/test/transactionBuilder/exitDelegationBuilder.ts @@ -4,7 +4,7 @@ import { coins } from '@bitgo/statics'; import { TransactionBuilderFactory } from '../../src'; import { ExitDelegationTransaction } from '../../src/lib/transaction/exitDelegation'; import * as testData from '../resources/vet'; -import { EXIT_DELEGATION_METHOD_ID, STARGATE_DELEGATION_ADDRESS_TESTNET } from '../../src/lib/constants'; +import { EXIT_DELEGATION_METHOD_ID, STARGATE_CONTRACT_ADDRESS_TESTNET } from '../../src/lib/constants'; describe('Vet Exit Delegation Transaction', () => { const factory = new TransactionBuilderFactory(coins.get('tvet')); @@ -27,7 +27,7 @@ describe('Vet Exit Delegation Transaction', () => { should.equal(tx.sender, testData.addresses.validAddresses[0]); should.equal(tx.tokenId, tokenId); - should.equal(tx.contract, STARGATE_DELEGATION_ADDRESS_TESTNET); + should.equal(tx.contract, STARGATE_CONTRACT_ADDRESS_TESTNET); should.equal(tx.gas, 21000); should.equal(tx.nonce, '64248'); should.equal(tx.expiration, 64); @@ -40,7 +40,7 @@ describe('Vet Exit Delegation Transaction', () => { tx.clauses.length.should.equal(1); should.exist(tx.clauses[0]); should.exist(tx.clauses[0].to); - tx.clauses[0]?.to?.should.equal(STARGATE_DELEGATION_ADDRESS_TESTNET); + tx.clauses[0]?.to?.should.equal(STARGATE_CONTRACT_ADDRESS_TESTNET); should.exist(tx.clauses[0].value); tx.clauses[0].value.should.equal('0x0'); @@ -51,14 +51,14 @@ describe('Vet Exit Delegation Transaction', () => { should.equal(tx.inputs[0].value, '0'); should.equal(tx.inputs[0].coin, 'tvet'); - should.equal(tx.outputs[0].address, STARGATE_DELEGATION_ADDRESS_TESTNET); + should.equal(tx.outputs[0].address, STARGATE_CONTRACT_ADDRESS_TESTNET); should.equal(tx.outputs[0].value, '0'); should.equal(tx.outputs[0].coin, 'tvet'); }); it('should build an exit delegation transaction with custom contract address', async function () { const tokenId = '123456'; - const customContractAddress = STARGATE_DELEGATION_ADDRESS_TESTNET; // Use the valid testnet delegation address + const customContractAddress = STARGATE_CONTRACT_ADDRESS_TESTNET; // Use the valid testnet delegation address const txBuilder = factory.getExitDelegationBuilder(); txBuilder.sender(testData.addresses.validAddresses[0]); @@ -101,7 +101,7 @@ describe('Vet Exit Delegation Transaction', () => { should.equal(deserializedTx.type, TransactionType.StakingUnlock); should.equal(deserializedTx.tokenId, tokenId); - should.equal(deserializedTx.contract, STARGATE_DELEGATION_ADDRESS_TESTNET); + should.equal(deserializedTx.contract, STARGATE_CONTRACT_ADDRESS_TESTNET); }); it('should validate the transaction data structure', async function () { diff --git a/modules/sdk-coin-vet/test/transactionBuilder/stakeClauseTransactionBuilder.ts b/modules/sdk-coin-vet/test/transactionBuilder/stakeClauseTransactionBuilder.ts index ee0fecfe9c..a02f9e8f40 100644 --- a/modules/sdk-coin-vet/test/transactionBuilder/stakeClauseTransactionBuilder.ts +++ b/modules/sdk-coin-vet/test/transactionBuilder/stakeClauseTransactionBuilder.ts @@ -1,14 +1,14 @@ import { coins } from '@bitgo/statics'; import { TransactionBuilderFactory, Transaction, StakeClauseTransaction } from '../../src/lib'; import should from 'should'; -import { STAKE_CLAUSE_METHOD_ID, STARGATE_NFT_ADDRESS_TESTNET } from '../../src/lib/constants'; +import { STAKE_CLAUSE_METHOD_ID, STARGATE_CONTRACT_ADDRESS_TESTNET } from '../../src/lib/constants'; import EthereumAbi from 'ethereumjs-abi'; import * as testData from '../resources/vet'; describe('VET Staking Transaction', function () { const factory = new TransactionBuilderFactory(coins.get('tvet')); - const stakingContractAddress = STARGATE_NFT_ADDRESS_TESTNET; - const amountToStake = '1000000000000000000'; // 1 VET in wei + const stakingContractAddress = STARGATE_CONTRACT_ADDRESS_TESTNET; + const amountToStake = '10000000000000000000000'; // 10000 VET in wei const levelId = 8; // Test level ID // Helper function to create a basic transaction builder with common properties @@ -240,16 +240,15 @@ describe('VET Staking Transaction', function () { const txBuilder = factory.from(testData.STAKE_CLAUSE_TRANSACTION); const tx = txBuilder.transaction as StakeClauseTransaction; const toJson = tx.toJson(); - toJson.id.should.equal('0x2f96e4c16d70bd3e2dabec29a07eb3d6066691ba5b812d6e897676f6ebc0a798'); - toJson.stakingContractAddress?.should.equal('0x1ec1d168574603ec35b9d229843b7c2b44bcb770'); - toJson.amountToStake?.should.equal('0xde0b6b3a7640000'); - toJson.nonce.should.equal('504440'); - toJson.gas.should.equal(392538); + toJson.id.should.equal('0x7148f62b42ecfdcb7ee62ac0654514e4b5f65f2fe5fdee79d4d29f56ab1722eb'); + toJson.stakingContractAddress?.should.equal('0x1e02b2953adefec225cf0ec49805b1146a4429c1'); + toJson.amountToStake?.should.equal(amountToStake); + toJson.nonce.should.equal('996363'); + toJson.gas.should.equal(406410); toJson.gasPriceCoef.should.equal(128); toJson.expiration.should.equal(64); toJson.chainTag.should.equal(39); - // in stake txn, nftTokenId indicates the levelId - toJson.nftTokenId?.should.equal(8); + toJson.levelId?.should.equal(8); }); }); }); diff --git a/modules/sdk-coin-vet/test/transactionBuilder/stakingTransaction.ts b/modules/sdk-coin-vet/test/transactionBuilder/stakingTransaction.ts index 8b133ec47a..f1fd4bbbd8 100644 --- a/modules/sdk-coin-vet/test/transactionBuilder/stakingTransaction.ts +++ b/modules/sdk-coin-vet/test/transactionBuilder/stakingTransaction.ts @@ -1,13 +1,13 @@ import { coins } from '@bitgo/statics'; import { TransactionBuilderFactory, Transaction, StakingTransaction } from '../../src/lib'; import should from 'should'; -import { STAKING_METHOD_ID, STARGATE_NFT_ADDRESS_TESTNET } from '../../src/lib/constants'; +import { STAKING_METHOD_ID, STARGATE_CONTRACT_ADDRESS_TESTNET } from '../../src/lib/constants'; import EthereumAbi from 'ethereumjs-abi'; import * as testData from '../resources/vet'; describe('VET Staking Transaction', function () { const factory = new TransactionBuilderFactory(coins.get('tvet')); - const stakingContractAddress = STARGATE_NFT_ADDRESS_TESTNET; + const stakingContractAddress = STARGATE_CONTRACT_ADDRESS_TESTNET; const amountToStake = '1000000000000000000'; // 1 VET in wei const levelId = 8; // Test level ID const autorenew = true; // Test autorenew flag diff --git a/modules/sdk-coin-vet/test/unit/stakingFlowE2E.ts b/modules/sdk-coin-vet/test/unit/stakingFlowE2E.ts index 19e3be6ef5..ce6c00784c 100644 --- a/modules/sdk-coin-vet/test/unit/stakingFlowE2E.ts +++ b/modules/sdk-coin-vet/test/unit/stakingFlowE2E.ts @@ -1,7 +1,7 @@ import should from 'should'; import { coins } from '@bitgo/statics'; import { TransactionType } from '@bitgo/sdk-core'; -import { TransactionBuilderFactory, StakingTransaction } from '../../src/lib'; +import { TransactionBuilderFactory, StakeClauseTransaction } from '../../src/lib'; import * as testData from '../resources/vet'; describe('VET Staking Flow - End-to-End Test', function () { @@ -11,9 +11,7 @@ describe('VET Staking Flow - End-to-End Test', function () { // Test data const stakingContractAddress = testData.STAKING_CONTRACT_ADDRESS; const amountToStake = '1000000000000000000'; // 1 VET in wei - const amountToStakeHex = '0xde0b6b3a7640000'; // Same amount in hex const levelId = testData.STAKING_LEVEL_ID; - const autorenew = testData.STAKING_AUTORENEW; const senderAddress = '0x9378c12BD7502A11F770a5C1F223c959B2805dA9'; const feePayerAddress = '0xdc9fef0b84a0ccf3f1bd4b84e41743e3e051a083'; @@ -24,7 +22,7 @@ describe('VET Staking Flow - End-to-End Test', function () { describe('Complete Staking Transaction Flow', function () { it('should build, sign, and serialize a complete staking transaction with fee delegation', async function () { // Step 1: Build the staking transaction - const stakingBuilder = factory.getStakingBuilder(); + const stakingBuilder = factory.getStakingActivateBuilder(); stakingBuilder .stakingContractAddress(stakingContractAddress) @@ -42,16 +40,15 @@ describe('VET Staking Flow - End-to-End Test', function () { const unsignedTx = await stakingBuilder.build(); should.exist(unsignedTx); - unsignedTx.should.be.instanceof(StakingTransaction); + unsignedTx.should.be.instanceof(StakeClauseTransaction); - const stakingTx = unsignedTx as StakingTransaction; + const stakingTx = unsignedTx as StakeClauseTransaction; // Verify transaction structure - stakingTx.type.should.equal(TransactionType.ContractCall); + stakingTx.type.should.equal(TransactionType.StakingActivate); stakingTx.stakingContractAddress.should.equal(stakingContractAddress); stakingTx.amountToStake.should.equal(amountToStake); stakingTx.levelId.should.equal(levelId); - stakingTx.autorenew.should.equal(autorenew); should.exist(stakingTx.rawTransaction); should.exist(stakingTx.rawTransaction.body); @@ -85,14 +82,12 @@ describe('VET Staking Flow - End-to-End Test', function () { // Step 7: Verify transaction can be deserialized const deserializedBuilder = factory.from(serializedTx); - const deserializedTx = deserializedBuilder.transaction as StakingTransaction; + const deserializedTx = deserializedBuilder.transaction as StakeClauseTransaction; - deserializedTx.should.be.instanceof(StakingTransaction); + deserializedTx.should.be.instanceof(StakeClauseTransaction); deserializedTx.stakingContractAddress.should.equal(stakingContractAddress); - // Amount is stored in hex format in deserialized transaction - deserializedTx.amountToStake.should.equal(amountToStakeHex); + deserializedTx.amountToStake.should.equal(amountToStake); deserializedTx.levelId.should.equal(levelId); - deserializedTx.autorenew.should.equal(autorenew); // Step 8: Verify toJson output const jsonOutput = stakingTx.toJson(); @@ -101,13 +96,12 @@ describe('VET Staking Flow - End-to-End Test', function () { jsonOutput.should.have.property('stakingContractAddress', stakingContractAddress); // JSON output keeps decimal format for amounts jsonOutput.should.have.property('amountToStake', amountToStake); - jsonOutput.should.have.property('nftTokenId', levelId); - jsonOutput.should.have.property('autorenew', autorenew); + jsonOutput.should.have.property('levelId', levelId); }); it('should handle signature combination in the correct order', async function () { // This test specifically validates the signature combination flow that was failing - const stakingBuilder = factory.getStakingBuilder(); + const stakingBuilder = factory.getStakingActivateBuilder(); stakingBuilder .stakingContractAddress(stakingContractAddress) @@ -123,7 +117,7 @@ describe('VET Staking Flow - End-to-End Test', function () { stakingBuilder.addFeePayerAddress(feePayerAddress); - const tx = (await stakingBuilder.build()) as StakingTransaction; + const tx = (await stakingBuilder.build()) as StakeClauseTransaction; // Test 1: Only sender signature - should generate half-signed transaction tx.addSenderSignature(mockSenderSignature); @@ -143,7 +137,7 @@ describe('VET Staking Flow - End-to-End Test', function () { it('should properly set transaction type for fee delegation validation', async function () { // This test ensures our fix for TransactionType.ContractCall is working - const stakingBuilder = factory.getStakingBuilder(); + const stakingBuilder = factory.getStakingActivateBuilder(); stakingBuilder .stakingContractAddress(stakingContractAddress) @@ -159,10 +153,10 @@ describe('VET Staking Flow - End-to-End Test', function () { stakingBuilder.addFeePayerAddress(feePayerAddress); - const tx = (await stakingBuilder.build()) as StakingTransaction; + const tx = (await stakingBuilder.build()) as StakeClauseTransaction; // Verify the transaction type is ContractCall - tx.type.should.equal(TransactionType.ContractCall); + tx.type.should.equal(TransactionType.StakingActivate); // Verify fee delegation is enabled via reserved.features = 1 const rawTxBody = tx.rawTransaction.body; @@ -175,7 +169,7 @@ describe('VET Staking Flow - End-to-End Test', function () { it('should work with pre-built signed transaction from test data', async function () { // Test using the actual signed transaction from our test data const txBuilder = factory.from(testData.STAKING_TRANSACTION); - const tx = txBuilder.transaction as StakingTransaction; + const tx = txBuilder.transaction as StakeClauseTransaction; // Should be able to get ID without throwing errors const txId = tx.id; @@ -187,7 +181,6 @@ describe('VET Staking Flow - End-to-End Test', function () { // The actual contract address from the parsed transaction is 0x1856c533ac2d94340aaa8544d35a5c1d4a21dee7 tx.stakingContractAddress.should.equal('0x1856c533ac2d94340aaa8544d35a5c1d4a21dee7'); tx.levelId.should.equal(testData.STAKING_LEVEL_ID); - tx.autorenew.should.equal(testData.STAKING_AUTORENEW); }); }); @@ -201,7 +194,7 @@ describe('VET Staking Flow - End-to-End Test', function () { ]; for (const testCase of testTypes) { - const stakingBuilder = factory.getStakingBuilder(); + const stakingBuilder = factory.getStakingActivateBuilder(); stakingBuilder .stakingContractAddress(stakingContractAddress) .amountToStake(amountToStake) @@ -217,7 +210,7 @@ describe('VET Staking Flow - End-to-End Test', function () { stakingBuilder.addFeePayerAddress(feePayerAddress); // Manually set the transaction type to test different types - const tx = (await stakingBuilder.build()) as StakingTransaction; + const tx = (await stakingBuilder.build()) as StakeClauseTransaction; (tx as any)._type = testCase.type; // Rebuild the raw transaction to test fee delegation flag