Repository: vechain/vechain-sdk-js
Pull request #2048: feat(galactica): hardhat plugin
Author: login: freemanzMrojo
Created: 2025-04-25T14:01:13Z | Merged: 2025-04-29T12:58:05Z

# Description

Some changes to integrate the hardhat plugin with Galactica. The tests performed have been along with `ethers` and `hardhat-truffle`. 

For those confused about the changes (I have barely touched anything from the plugin package), the way it works is via mapping from RPC methods to logic in the SDK, placed in the `network` package.

Closes partially [#1988](https://github.com/vechain/vechain-sdk-js/issues/1988) (need a version as a package of this to run the pipeline for all the OpenZeppelin tests).

## Type of change

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

It has been tested from our fork of the OpenZeppelin contracts repo against the Solo image and Devnet

**Test Configuration**:
* Node.js Version: 20.18.1
* Yarn Version: 1.22.22

# Checklist:

- [x] My code follows the coding standards of this project
- [x] I have performed a self-review of my code
- [x] I have commented on my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes
- [x] New and existing integration tests pass locally with my changes
- [x] Any dependent changes have been merged and published in downstream modules
- [x] I have not added any vulnerable dependencies to my code

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **New Features**
	- Added support for testing against the Galactica devnet, including a new network configuration and test script.
	- Enhanced the Hex class with a compact string representation option.
- **Bug Fixes**
	- Improved error handling for reverted transactions and zero balance scenarios in RPC methods.
	- Gas price and gas estimation methods now better align with EIP-1559 standards and block parameter handling.
- **Tests**
	- Updated and added tests to reflect new compact hex formatting and revised RPC behaviors.
	- Adjusted test fixtures to match updated block and transaction formats.
- **Chores**
	- Reorganized and clarified import statements across multiple files for better maintainability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->


Diff:
diff --git a/.github/workflows/test-apps.yml b/.github/workflows/test-apps.yml
index 411b35c71..48e6f93eb 100644
--- a/.github/workflows/test-apps.yml
+++ b/.github/workflows/test-apps.yml
@@ -26,6 +26,8 @@ jobs:
               run: yarn build
 
             - name: Test apps
+              env:
+                GALACTICA_DEV_MNEMONIC: ${{ secrets.GALACTICA_DEV_MNEMONIC }}
               run: |
                   # Absolute path to the 'apps' directory
                   apps_directory="$(pwd)/apps"
@@ -33,6 +35,9 @@ jobs:
                   # Iterate over each folder in /apps
                   for current_app_directory in "$apps_directory"/*; do
                     if [ -d "$current_app_directory" ]; then
+                      # Get the directory name
+                      dir_name=$(basename "$current_app_directory")
+                      
                       # LOG
                       echo "Running yarn in $current_app_directory"
                   
@@ -41,6 +46,12 @@ jobs:
                   
                       # Test
                       yarn test
+                      
+                      # Galactica devnet test for sdk-hardhat-integration
+                      if [ "$dir_name" = "sdk-hardhat-integration" ]; then
+                        echo "Running additional galactica devnet tests"
+                        yarn test:galactica:devnet
+                      fi
                   
                       # Return to the original directory using absolute path
                       cd "../"
diff --git a/apps/sdk-hardhat-integration/hardhat.config.ts b/apps/sdk-hardhat-integration/hardhat.config.ts
index 82930765a..5d88209a0 100644
--- a/apps/sdk-hardhat-integration/hardhat.config.ts
+++ b/apps/sdk-hardhat-integration/hardhat.config.ts
@@ -1,7 +1,7 @@
-import { type HardhatUserConfig } from 'hardhat/config';
 import '@nomicfoundation/hardhat-toolbox';
-import '@vechain/sdk-hardhat-plugin';
 import { HDKey } from '@vechain/sdk-core';
+import '@vechain/sdk-hardhat-plugin';
+import { type HardhatUserConfig } from 'hardhat/config';
 import { type HttpNetworkConfig } from 'hardhat/types';
 
 /**
@@ -145,6 +145,26 @@ const config: HardhatUserConfig = {
             httpHeaders: {}
         } satisfies HttpNetworkConfig,
 
+        /**
+         * Galactica devnet configuration
+         */
+        vechain_galactica_devnet: {
+            // Galactica devnet
+            url: 'https://galactica.dev.node.vechain.org/',
+            accounts: {
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
+                path: HDKey.VET_DERIVATION_PATH,
+                count: 102, // 102 accounts since 101 have funds
+                initialIndex: 0,
+                passphrase: 'vechainthor'
+            },
+            gas: 'auto',
+            gasPrice: 'auto',
+            gasMultiplier: 1,
+            timeout: 20000,
+            httpHeaders: {}
+        } satisfies HttpNetworkConfig,
+
         /**
          * Default hardhat network configuration
          */
diff --git a/apps/sdk-hardhat-integration/package.json b/apps/sdk-hardhat-integration/package.json
index bfa124d61..5f238b5d0 100644
--- a/apps/sdk-hardhat-integration/package.json
+++ b/apps/sdk-hardhat-integration/package.json
@@ -9,6 +9,7 @@
   "scripts": {
     "compile": "npx hardhat compile",
     "test": "npx hardhat test --network vechain_testnet",
+    "test:galactica:devnet": "npx hardhat test --network vechain_galactica_devnet",
     "deploy-solo": "npx hardhat run scripts/deploy.ts --network vechain_solo",
     "deploy-testnet": "npx hardhat run scripts/deploy.ts --network vechain_testnet",
     "deploy-erc20": "npx hardhat run scripts/erc20/deploy.ts --network vechain_testnet",
diff --git a/apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts b/apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts
index 65cbad513..d1a7da59b 100644
--- a/apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts
+++ b/apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts
@@ -38,8 +38,9 @@ describe('VechainHelloWorldWithNonEmptyConstructor', function () {
     });
 
     it('should break with an specific error due to insufficient VTHO', async function () {
+        const signers = await ethers.getSigners();
         const accountWithNoVTHO = await ethers.getSigner(
-            '0xB381e7da548601B1CCB05C66d415b20baE40d828'
+            signers[signers.length - 1].address
         );
         const VechainHelloWorldWithNonEmptyConstructor =
             await ethers.getContractFactory(
diff --git a/packages/core/src/vcdm/Hex.ts b/packages/core/src/vcdm/Hex.ts
index b35da26e1..fea5436b4 100644
--- a/packages/core/src/vcdm/Hex.ts
+++ b/packages/core/src/vcdm/Hex.ts
@@ -339,9 +339,16 @@ class Hex implements VeChainDataModel<Hex> {
     /**
      * Returns a string representation of the object.
      *
+     * @param {boolean} compact - Whether to compact the string representation.
      * @return {string} The string representation of the object.
      */
-    public toString(): string {
+    public toString(compact: boolean = false): string {
+        if (compact) {
+            const stripped = this.digits.replace(/^0+/, '');
+            const compactDigits = stripped === '' ? '0' : stripped;
+            return (this.sign < 0 ? '-0x' : '0x') + compactDigits;
+        }
+
         return (this.sign < 0 ? '-0x' : '0x') + this.digits;
     }
 }
diff --git a/packages/core/src/vcdm/HexUInt.ts b/packages/core/src/vcdm/HexUInt.ts
index fc950b95f..b9b426b15 100644
--- a/packages/core/src/vcdm/HexUInt.ts
+++ b/packages/core/src/vcdm/HexUInt.ts
@@ -1,6 +1,6 @@
-import { HexInt } from './HexInt';
-import { Hex } from './Hex';
 import { InvalidDataType } from '@vechain/sdk-errors';
+import { Hex } from './Hex';
+import { HexInt } from './HexInt';
 
 /**
  * Represents a hexadecimal unsigned integer value.
diff --git a/packages/core/tests/vcdm/Hex.unit.test.ts b/packages/core/tests/vcdm/Hex.unit.test.ts
index a843c5444..b5666e285 100644
--- a/packages/core/tests/vcdm/Hex.unit.test.ts
+++ b/packages/core/tests/vcdm/Hex.unit.test.ts
@@ -1,6 +1,6 @@
 import { describe, expect, test } from '@jest/globals';
-import { Hex, Txt } from '../../src';
 import { InvalidDataType, InvalidOperation } from '@vechain/sdk-errors';
+import { Hex, Txt } from '../../src';
 
 /**
  * Test Hex class.
@@ -120,6 +120,24 @@ describe('Hex class tests', () => {
             expect(hex.toString()).toEqual(exp.toLowerCase()); // Normalized from is lower case.
         });
 
+        test('Return a compact string representation of the Hex instance', () => {
+            const exp = BigInt(10000000000000); // Base gas price for legacy transactions
+            const expectedHexString = '0x09184e72a000';
+            const expectedCompactHexString = '0x9184e72a000';
+            const hex = Hex.of(exp);
+            expect(hex).toBeInstanceOf(Hex);
+            expect(hex.toString()).toEqual(expectedHexString);
+            expect(hex.toString(true)).toEqual(expectedCompactHexString);
+
+            const expectedZeroHexString = '0x00000000000000000000000000000000';
+            const expectedCompactZeroHexString = '0x0';
+            const zeroHex = Hex.of(0);
+            expect(zeroHex.toString(true)).toEqual(
+                expectedCompactZeroHexString
+            );
+            expect(zeroHex.toString()).toEqual(expectedZeroHexString);
+        });
+
         test('Return an Hex instance if the passed argument is string - negative value without 0x prefix', () => {
             const exp = '-C0c0a';
             const hex = Hex.of(exp);
diff --git a/packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts b/packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts
index 4713b0727..9765c30e3 100644
--- a/packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts
+++ b/packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts
@@ -1,19 +1,19 @@
-import { VeChainProvider } from '../vechain-provider/vechain-provider';
-import type { EIP1193RequestArguments } from '../../eip1193';
 import {
     JSONRPCInternalError,
     stringifyData,
     VechainSDKError
 } from '@vechain/sdk-errors';
+import { VeChainSDKLogger } from '@vechain/sdk-logging';
+import { SimpleHttpClient } from '../../../http';
+import { ThorClient } from '../../../thor-client';
+import type { EIP1193RequestArguments } from '../../eip1193';
+import { type ProviderInternalWallet } from '../../helpers';
+import { VeChainProvider } from '../vechain-provider/vechain-provider';
 import {
     type BuildHardhatErrorFunction,
     type JsonRpcRequest,
     type JsonRpcResponse
 } from './types';
-import { ThorClient } from '../../../thor-client';
-import { type ProviderInternalWallet } from '../../helpers';
-import { VeChainSDKLogger } from '@vechain/sdk-logging';
-import { SimpleHttpClient } from '../../../http';
 
 /**
  * This class is a wrapper for the VeChainProvider that Hardhat uses.
@@ -186,6 +186,14 @@ class HardhatVeChainProvider extends VeChainProvider {
 
             if (error instanceof VechainSDKError) {
                 // Throw the error
+                // eth_call is a special case, @nomiclabs/truffle-contract uses this error to revert the transaction
+                // @NOTE: Review whether makes sense to handle this case in a different way (error message per RPC method?)
+                if (args.method === 'eth_call') {
+                    throw this.buildHardhatErrorFunctionCallback(
+                        'revert',
+                        error
+                    );
+                }
                 throw this.buildHardhatErrorFunctionCallback(
                     `Error on request ${args.method}: ${error.innerError}`,
                     error
diff --git a/packages/network/src/provider/utils/formatter/blocks/formatter.ts b/packages/network/src/provider/utils/formatter/blocks/formatter.ts
index fc54cc1ee..b89276b6f 100644
--- a/packages/network/src/provider/utils/formatter/blocks/formatter.ts
+++ b/packages/network/src/provider/utils/formatter/blocks/formatter.ts
@@ -1,11 +1,11 @@
-import { type BlocksRPC } from './types';
 import { HexUInt, Quantity, ZERO_BYTES } from '@vechain/sdk-core';
-import { transactionsFormatter } from '../transactions';
 import {
     type CompressedBlockDetail,
     type ExpandedBlockDetail,
     type TransactionsExpandedBlockDetail
 } from '../../../../thor-client';
+import { transactionsFormatter } from '../transactions';
+import { type BlocksRPC } from './types';
 
 /**
  * Output formatter for block details.
@@ -54,7 +54,9 @@ const formatToRPCStandard = (
         nonce: HexUInt.of(ZERO_BYTES(8)).toString(),
         logsBloom: HexUInt.of(ZERO_BYTES(256)).toString(),
         extraData: '0x',
-        baseFeePerGas: '0x0',
+        ...(block.baseFeePerGas !== undefined
+            ? { baseFeePerGas: block.baseFeePerGas }
+            : {}),
         mixHash: HexUInt.of(ZERO_BYTES(32)).toString()
     };
 };
diff --git a/packages/network/src/provider/utils/formatter/blocks/types.d.ts b/packages/network/src/provider/utils/formatter/blocks/types.d.ts
index 525fbbb33..9d92ac415 100644
--- a/packages/network/src/provider/utils/formatter/blocks/types.d.ts
+++ b/packages/network/src/provider/utils/formatter/blocks/types.d.ts
@@ -80,13 +80,17 @@ interface BlocksRPC extends BlockHeaderRPC {
      */
     transactions: string[] | TransactionRPC[];
 
+    /**
+     * Base fee per gas in hex string format (since the Galactica fork)
+     */
+    baseFeePerGas?: string;
+
     /**
      * Unsupported fields
      */
     difficulty: string;
     totalDifficulty: string;
     uncles: string[];
-    baseFeePerGas: string;
     mixHash: string;
 }
 
diff --git a/packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts b/packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts
index 038004691..8b236b553 100644
--- a/packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts
+++ b/packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts
@@ -3,14 +3,14 @@ import {
     JSONRPCInvalidParams,
     stringifyData
 } from '@vechain/sdk-errors';
-import { type DefaultBlock, DefaultBlockToRevision } from '../../../const';
-import { type TransactionObjectInput } from './types';
 import {
     type SimulateTransactionClause,
     type SimulateTransactionOptions,
     type ThorClient
 } from '../../../../../thor-client';
 import { RPC_DOCUMENTATION_URL } from '../../../../../utils';
+import { type DefaultBlock, DefaultBlockToRevision } from '../../../const';
+import { type TransactionObjectInput } from './types';
 
 /**
  * RPC Method eth_call implementation
@@ -30,12 +30,13 @@ const ethCall = async (
         params.length !== 2 ||
         typeof params[0] !== 'object' ||
         (typeof params[1] !== 'object' && typeof params[1] !== 'string')
-    )
+    ) {
         throw new JSONRPCInvalidParams(
             'eth_call',
             `Invalid input params for "eth_call" method. See ${RPC_DOCUMENTATION_URL} for details.`,
             { params }
         );
+    }
 
     try {
         const [inputOptions, block] = params as [
@@ -63,9 +64,23 @@ const ethCall = async (
             } satisfies SimulateTransactionOptions
         );
 
+        if (simulatedTx[0].reverted) {
+            throw new JSONRPCInternalError(
+                'eth_call()',
+                'Method "eth_call" failed when simulating the transaction.',
+                {
+                    params: stringifyData(params),
+                    innerError: simulatedTx[0].vmError
+                }
+            );
+        }
+
         // Return simulated transaction data
         return simulatedTx[0].data;
     } catch (e) {
+        if (e instanceof JSONRPCInternalError) {
+            throw e;
+        }
         throw new JSONRPCInternalError(
             'eth_call()',
             'Method "eth_call" failed.',
diff --git a/packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts b/packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts
index 3ac9a8fef..fe35361b4 100644
--- a/packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts
+++ b/packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts
@@ -1,15 +1,16 @@
+import { HexUInt } from '@vechain/sdk-core';
 import {
     JSONRPCInternalError,
     JSONRPCInvalidParams,
     stringifyData
 } from '@vechain/sdk-errors';
-import { type TransactionObjectInput } from './types';
 import {
     type SimulateTransactionClause,
     type ThorClient
 } from '../../../../../thor-client';
-import { type DefaultBlock, DefaultBlockToRevision } from '../../../const';
 import { RPC_DOCUMENTATION_URL } from '../../../../../utils';
+import { type DefaultBlock, DefaultBlockToRevision } from '../../../const';
+import { type TransactionObjectInput } from './types';
 
 /**
  * RPC Method eth_estimateGas implementation
@@ -30,7 +31,7 @@ const ethEstimateGas = async (
     params: unknown[]
 ): Promise<string> => {
     // Input validation
-    if (params.length !== 2 || typeof params[0] !== 'object')
+    if (params.length < 1 || params.length > 2 || typeof params[0] !== 'object')
         throw new JSONRPCInvalidParams(
             'eth_estimateGas',
             `Invalid input params for "eth_estimateGas" method. See ${RPC_DOCUMENTATION_URL} for details.`,
@@ -38,6 +39,9 @@ const ethEstimateGas = async (
         );
 
     try {
+        if (params.length === 1) {
+            params.push('latest');
+        }
         // NOTE: The standard requires block parameter.
         // Here it is ignored and can be added in the future compatibility reasons.
         // (INPUT CHECK TAKE CARE OF THIS)
@@ -62,7 +66,7 @@ const ethEstimateGas = async (
         );
 
         // Convert intrinsic gas to hex string and return
-        return '0x' + estimatedGas.totalGas.toString(16);
+        return HexUInt.of(estimatedGas.totalGas).toString(true);
     } catch (e) {
         throw new JSONRPCInternalError(
             'eth_estimateGas()',
diff --git a/packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts b/packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts
index 66dfb38b1..211b47437 100644
--- a/packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts
+++ b/packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts
@@ -1,12 +1,12 @@
-import { type ThorClient } from '../../../../../thor-client';
-import { type VeChainProvider } from '../../../../providers/vechain-provider';
 import {
-    JSONRPCInvalidParams,
     JSONRPCInternalError,
+    JSONRPCInvalidParams,
     JSONRPCMethodNotImplemented,
     stringifyData
 } from '@vechain/sdk-errors';
+import { type ThorClient } from '../../../../../thor-client';
 import { type FeeHistoryResponse } from '../../../../../thor-client/gas/types';
+import { type VeChainProvider } from '../../../../providers/vechain-provider';
 import { type DefaultBlock, DefaultBlockToRevision } from '../../../const';
 
 /**
diff --git a/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts b/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts
index 15e196c12..cd7db19f4 100644
--- a/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts
+++ b/packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts
@@ -1,3 +1,5 @@
+import { HexUInt } from '@vechain/sdk-core';
+import { JSONRPCInternalError } from '@vechain/sdk-errors';
 import { type ThorClient } from '../../../../../thor-client';
 
 /**
@@ -6,11 +8,31 @@ import { type ThorClient } from '../../../../../thor-client';
  * @returns The current gas price in Wei unit considering that 1 VTHO equals 1e18 Wei.
  */
 const ethGasPrice = async (thorClient: ThorClient): Promise<string> => {
-    const {
-        result: { plain }
-    } = await thorClient.contracts.getBaseGasPrice();
+    // Check if Galactica hardfork has happened
+    const galacticaForked = await thorClient.forkDetector.detectGalactica();
+    if (!galacticaForked) {
+        const {
+            result: { plain }
+        } = await thorClient.contracts.getBaseGasPrice();
+        return HexUInt.of(plain as bigint).toString(true);
+    }
 
-    return '0x' + BigInt(plain as bigint).toString(16);
+    const bestBlock = await thorClient.blocks.getBestBlockCompressed();
+    const baseFeePerGas = bestBlock?.baseFeePerGas;
+
+    if (baseFeePerGas === undefined) {
+        throw new JSONRPCInternalError(
+            'eth_gasPrice',
+            'Last block should have baseFeePerGas defined.',
+            { params: bestBlock, url: thorClient.httpClient.baseURL }
+        );
+    }
+    const maxPriorityFeePerGas = await thorClient.gas.getMaxPriorityFeePerGas();
+
+    const baseFee = HexUInt.of(baseFeePerGas).bi;
+    const priority = HexUInt.of(maxPriorityFeePerGas).bi;
+
+    return HexUInt.of(baseFee + priority).toString(true);
 };
 
 export { ethGasPrice };
diff --git a/packages/network/src/provider/utils/rpc-mapper/rpc-mapper.ts b/packages/network/src/provider/utils/rpc-mapper/rpc-mapper.ts
index a499b77be..9f9d009c7 100644
--- a/packages/network/src/provider/utils/rpc-mapper/rpc-mapper.ts
+++ b/packages/network/src/provider/utils/rpc-mapper/rpc-mapper.ts
@@ -1,4 +1,5 @@
 import { type ThorClient } from '../../../thor-client';
+import { type FeeHistoryResponse } from '../../../thor-client/gas/types';
 import { type VeChainProvider } from '../../providers/vechain-provider';
 import { RPC_METHODS } from '../const/rpc-mapper/rpc-methods';
 import {
@@ -57,9 +58,8 @@ import {
     web3ClientVersion,
     web3Sha3
 } from './methods';
-import { ethMaxPriorityFeePerGas } from './methods/eth_maxPriorityFeePerGas/eth_maxPriorityFeePerGas';
 import { ethFeeHistory } from './methods/eth_feeHistory/eth_feeHistory';
-import { type FeeHistoryResponse } from '../../../thor-client/gas/types';
+import { ethMaxPriorityFeePerGas } from './methods/eth_maxPriorityFeePerGas/eth_maxPriorityFeePerGas';
 
 type MethodHandlerType<TParams, TReturnType> = (
     params: TParams[]
diff --git a/packages/network/src/thor-client/transactions/transactions-module.ts b/packages/network/src/thor-client/transactions/transactions-module.ts
index 412bff20f..4823b25f2 100644
--- a/packages/network/src/thor-client/transactions/transactions-module.ts
+++ b/packages/network/src/thor-client/transactions/transactions-module.ts
@@ -19,6 +19,7 @@ import { InvalidDataType, InvalidTransactionField } from '@vechain/sdk-errors';
 import { ErrorFragment, Interface } from 'ethers';
 import { HttpMethod } from '../../http';
 import { blocksFormatter, getTransactionIndexIntoBlock } from '../../provider';
+import type { VeChainSigner } from '../../signer';
 import {
     buildQuery,
     BUILT_IN_CONTRACTS,
@@ -29,7 +30,18 @@ import {
     vnsUtils
 } from '../../utils';
 import { type BlocksModule, type ExpandedBlockDetail } from '../blocks';
+import type {
+    ContractCallOptions,
+    ContractCallResult,
+    ContractClause,
+    ContractTransactionOptions
+} from '../contracts';
 import { type CallNameReturnType, type DebugModule } from '../debug';
+import { type ForkDetector } from '../fork';
+import { type GasModule } from '../gas';
+import { decodeRevertReason } from '../gas/helpers/decode-evm-error';
+import type { EstimateGasOptions, EstimateGasResult } from '../gas/types';
+import { type LogsModule } from '../logs';
 import {
     type GetTransactionInputOptions,
     type GetTransactionReceiptInputOptions,
@@ -43,18 +55,6 @@ import {
     type TransactionSimulationResult,
     type WaitForTransactionOptions
 } from './types';
-import type { EstimateGasOptions, EstimateGasResult } from '../gas/types';
-import { decodeRevertReason } from '../gas/helpers/decode-evm-error';
-import type {
-    ContractCallOptions,
-    ContractCallResult,
-    ContractClause,
-    ContractTransactionOptions
-} from '../contracts';
-import type { VeChainSigner } from '../../signer';
-import { type LogsModule } from '../logs';
-import { type ForkDetector } from '../fork';
-import { type GasModule } from '../gas';
 
 /**
  * The `TransactionsModule` handles transaction related operations and provides
diff --git a/packages/network/tests/provider/fixture.ts b/packages/network/tests/provider/fixture.ts
index 06d593be8..ed9070cf0 100644
--- a/packages/network/tests/provider/fixture.ts
+++ b/packages/network/tests/provider/fixture.ts
@@ -97,7 +97,6 @@ const blockWithTransactionsExpanded = {
     logsBloom:
         '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
     extraData: '0x',
-    baseFeePerGas: '0x0',
     mixHash:
         '0x0000000000000000000000000000000000000000000000000000000000000000'
 };
@@ -135,7 +134,6 @@ const blockWithTransactionsNotExpanded = {
     logsBloom:
         '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
     extraData: '0x',
-    baseFeePerGas: '0x0',
     mixHash:
         '0x0000000000000000000000000000000000000000000000000000000000000000'
 };
diff --git a/packages/network/tests/provider/formatter/fixture.ts b/packages/network/tests/provider/formatter/fixture.ts
index 0e5cc7707..82faca0dc 100644
--- a/packages/network/tests/provider/formatter/fixture.ts
+++ b/packages/network/tests/provider/formatter/fixture.ts
@@ -61,7 +61,6 @@ const blockFixtures = [
             logsBloom:
                 '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
             extraData: '0x',
-            baseFeePerGas: '0x0',
             mixHash:
                 '0x0000000000000000000000000000000000000000000000000000000000000000'
         }
@@ -125,7 +124,6 @@ const blockFixtures = [
             logsBloom:
                 '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
             extraData: '0x',
-            baseFeePerGas: '0x0',
             mixHash:
                 '0x0000000000000000000000000000000000000000000000000000000000000000'
         }
@@ -305,7 +303,6 @@ const blockFixtures = [
             logsBloom:
                 '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
             extraData: '0x',
-            baseFeePerGas: '0x0',
             mixHash:
                 '0x0000000000000000000000000000000000000000000000000000000000000000'
         }
diff --git a/packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts b/packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts
index 102b15189..92637ae40 100644
--- a/packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts
+++ b/packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts
@@ -60,47 +60,6 @@ const positiveCasesFixtures = [
         ],
         expected: '0x'
     },
-    {
-        description:
-            'Sends 1 VET to the receiver. (using { blockNumber: 0x0 } )',
-        input: [
-            {
-                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
-                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
-                value: '1000000000000000000',
-                data: '0x'
-            },
-            '0x0'
-        ],
-        expected: '0x'
-    },
-    {
-        description:
-            'Sends 1 VET to the receiver. (using 0x0 string blockHash)',
-        input: [
-            {
-                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
-                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
-                value: '1000000000000000000',
-                data: '0x'
-            },
-            Hex.of(0).toString()
-        ],
-        expected: '0x'
-    },
-    {
-        description: 'Sends 1 VET to the receiver. (earliest tag)',
-        input: [
-            {
-                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
-                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
-                value: '1000000000000000000',
-                data: '0x'
-            },
-            'earliest'
-        ],
-        expected: '0x'
-    },
     {
         description: 'Send complex transaction object.',
         input: [
@@ -151,6 +110,48 @@ const negativeCasesFixtures = [
             'latest'
         ],
         expected: JSONRPCInternalError
+    },
+    {
+        description:
+            'Fails to send 1 VET to the receiver since balace is 0. (using { blockNumber: 0x0 } )',
+        input: [
+            {
+                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
+                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
+                value: '1000000000000000000',
+                data: '0x'
+            },
+            '0x0'
+        ],
+        expected: JSONRPCInternalError
+    },
+    {
+        description:
+            'Fails to send 1 VET to the receiver since balace is 0. (using 0x0 string blockHash)',
+        input: [
+            {
+                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
+                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
+                value: '1000000000000000000',
+                data: '0x'
+            },
+            Hex.of(0).toString()
+        ],
+        expected: JSONRPCInternalError
+    },
+    {
+        description:
+            'Fails to send 1 VET to the receiver since balace is 0. (earliest tag)',
+        input: [
+            {
+                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
+                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
+                value: '1000000000000000000',
+                data: '0x'
+            },
+            'earliest'
+        ],
+        expected: JSONRPCInternalError
     }
 ];
 
diff --git a/packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts b/packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts
index 4ebbe643e..d4d8eea23 100644
--- a/packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts
+++ b/packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts
@@ -38,6 +38,16 @@ const positiveCasesFixtures = [
             'latest'
         ],
         expected: '0x5208'
+    },
+    {
+        description: 'Missing block reference',
+        input: [
+            {
+                to: '0x7487d912d03ab9de786278f679592b3730bdd540',
+                value: '0x1000'
+            }
+        ],
+        expected: '0x5208'
     }
 ];
 
@@ -49,16 +59,6 @@ const negativeCasesFixtures = [
         description: 'No parameter passed',
         input: [],
         expected: JSONRPCInvalidParams
-    },
-    {
-        description: 'Missing block reference',
-        input: [
-            {
-                from: '0x37cce5c8bd6141cbe8172b277faa65af5cc83c6a',
-                data: '0x'
-            }
-        ],
-        expected: JSONRPCInvalidParams
     }
 ];
 
diff --git a/packages/network/tests/provider/rpc-mapper/methods/eth_getBlockByNumber/fixture.ts b/packages/network/tests/provider/rpc-mapper/methods/eth_getBlockByNumber/fixture.ts
index 1aa2a31a9..582ae7192 100644
--- a/packages/network/tests/provider/rpc-mapper/methods/eth_getBlockByNumber/fixture.ts
+++ b/packages/network/tests/provider/rpc-mapper/methods/eth_getBlockByNumber/fixture.ts
@@ -34,7 +34,6 @@ const zeroBlock = {
     logsBloom:
         '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
     extraData: '0x',
-    baseFeePerGas: '0x0',
     mixHash:
         '0x0000000000000000000000000000000000000000000000000000000000000000'
 };


Reviews:
user: login: coderabbitai[bot]
body: **Actionable comments posted: 1**

<details>
<summary>🧹 Nitpick comments (3)</summary><blockquote>

<details>
<summary>.github/workflows/test-apps.yml (1)</summary><blockquote>

`38-40`: **Extract directory name for conditional testing**

Good approach to extract the directory name into a variable for later conditional checks.


There's a trailing whitespace on line 40 that should be removed:

```diff
-      dir_name=$(basename "$current_app_directory")
-      
+      dir_name=$(basename "$current_app_directory")
```

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[error] 40-40: trailing spaces

(trailing-spaces)

</details>

</details>

</blockquote></details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts (1)</summary><blockquote>

`21-26`: **Support for EIP-1559 gas pricing**

The implementation correctly handles EIP-1559 style gas pricing by fetching the `maxPriorityFeePerGas`, converting both base fee and priority fee to big integers, and returning their sum. This enables proper integration with networks supporting the latest Ethereum transaction format.


Consider adding error handling for the `getMaxPriorityFeePerGas()` call to provide a more informative error message if this API call fails:

```diff
-const maxPriorityFeePerGas = await thorClient.gas.getMaxPriorityFeePerGas();
+let maxPriorityFeePerGas;
+try {
+    maxPriorityFeePerGas = await thorClient.gas.getMaxPriorityFeePerGas();
+} catch (error) {
+    throw new JSONRPCInternalError(
+        'ethGasPrice()',
+        'Failed to retrieve maxPriorityFeePerGas',
+        { innerError: stringifyData(error) }
+    );
+}
```

</blockquote></details>
<details>
<summary>apps/sdk-hardhat-integration/hardhat.config.ts (1)</summary><blockquote>

`148-167`: **Consider adding missing network configuration options for consistency**

The Galactica devnet configuration looks good overall, but it's missing some properties that are present in other network configurations such as `debug`, `gasPayer`, and `enableDelegation`. Consider adding these for consistency with other network configurations.

Also, ensure that `GALACTICA_DEV_MNEMONIC` is properly set in the environment where this will be used, as the fallback is an empty string which would result in invalid accounts.


```diff
        vechain_galactica_devnet: {
            // Galactica devnet
            url: 'https://galactica.dev.node.vechain.org/',
            accounts: {
                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
                path: HDKey.VET_DERIVATION_PATH,
                count: 102, // 102 accounts since 101 have funds
                initialIndex: 0,
                passphrase: 'vechainthor'
            },
+           debug: false,
+           gasPayer: undefined,
+           enableDelegation: false,
            gas: 'auto',
            gasPrice: 'auto',
            gasMultiplier: 1,
            timeout: 20000,
            httpHeaders: {}
        } satisfies HttpNetworkConfig,
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 9431afb10b41863151c82056b76c60f37addb3f5 and 84dd04ca1bfb790694ad941d80c5f7af6bc20952.

</details>

<details>
<summary>📒 Files selected for processing (21)</summary>

* `.github/workflows/test-apps.yml` (2 hunks)
* `apps/sdk-hardhat-integration/hardhat.config.ts` (2 hunks)
* `apps/sdk-hardhat-integration/package.json` (1 hunks)
* `apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts` (1 hunks)
* `packages/core/src/vcdm/Hex.ts` (1 hunks)
* `packages/core/src/vcdm/HexUInt.ts` (1 hunks)
* `packages/core/tests/vcdm/Hex.unit.test.ts` (2 hunks)
* `packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts` (2 hunks)
* `packages/network/src/provider/utils/formatter/blocks/formatter.ts` (2 hunks)
* `packages/network/src/provider/utils/formatter/blocks/types.d.ts` (1 hunks)
* `packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts` (3 hunks)
* `packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts` (3 hunks)
* `packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts` (1 hunks)
* `packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts` (2 hunks)
* `packages/network/src/provider/utils/rpc-mapper/rpc-mapper.ts` (2 hunks)
* `packages/network/src/thor-client/transactions/transactions-module.ts` (2 hunks)
* `packages/network/tests/provider/fixture.ts` (0 hunks)
* `packages/network/tests/provider/formatter/fixture.ts` (0 hunks)
* `packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts` (1 hunks)
* `packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts` (1 hunks)
* `packages/network/tests/provider/rpc-mapper/methods/eth_getBlockByNumber/fixture.ts` (0 hunks)

</details>

<details>
<summary>💤 Files with no reviewable changes (3)</summary>

* packages/network/tests/provider/rpc-mapper/methods/eth_getBlockByNumber/fixture.ts
* packages/network/tests/provider/formatter/fixture.ts
* packages/network/tests/provider/fixture.ts

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (4)</summary>

<details>
<summary>packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts (2)</summary><blockquote>

<details>
<summary>packages/errors/src/available-errors/provider/provider.ts (1)</summary>

* `JSONRPCInternalError` (164-164)

</details>
<details>
<summary>packages/core/src/vcdm/Hex.ts (1)</summary>

* `Hex` (356-356)

</details>

</blockquote></details>
<details>
<summary>apps/sdk-hardhat-integration/hardhat.config.ts (2)</summary><blockquote>

<details>
<summary>packages/core/src/hdkey/HDKey.ts (1)</summary>

* `HDKey` (249-249)

</details>
<details>
<summary>packages/hardhat-plugin/src/type-extensions.ts (1)</summary>

* `HttpNetworkConfig` (43-69)

</details>

</blockquote></details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts (2)</summary><blockquote>

<details>
<summary>packages/errors/src/available-errors/provider/provider.ts (1)</summary>

* `JSONRPCInvalidParams` (165-165)

</details>
<details>
<summary>packages/core/src/vcdm/HexUInt.ts (1)</summary>

* `HexUInt` (90-90)

</details>

</blockquote></details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts (2)</summary><blockquote>

<details>
<summary>packages/errors/src/available-errors/provider/provider.ts (2)</summary>

* `JSONRPCInvalidParams` (165-165)
* `JSONRPCInternalError` (164-164)

</details>
<details>
<summary>packages/errors/src/helpers/helpers.ts (1)</summary>

* `stringifyData` (86-86)

</details>

</blockquote></details>

</details><details>
<summary>🪛 YAMLlint (1.35.1)</summary>

<details>
<summary>.github/workflows/test-apps.yml</summary>

[warning] 30-30: wrong indentation: expected 18 but found 16

(indentation)

---

[error] 34-34: trailing spaces

(trailing-spaces)

---

[error] 40-40: trailing spaces

(trailing-spaces)

---

[error] 49-49: trailing spaces

(trailing-spaces)

</details>

</details>

</details>

<details>
<summary>🔇 Additional comments (28)</summary><blockquote>

<details>
<summary>packages/core/src/vcdm/Hex.ts (1)</summary>

`342-352`: **Well implemented compact hex string representation.**

The new `compact` parameter for the `toString` method provides a useful feature for generating compact hex strings by removing leading zeros. This is valuable for cases where string length matters or where standardization with other systems that use compact representations is needed.

The implementation handles the edge case where all digits are zero, correctly returning "0x0" instead of just "0x".

</details>
<details>
<summary>packages/core/tests/vcdm/Hex.unit.test.ts (1)</summary>

`123-139`: **Good test coverage for the new compact string feature.**

This test thoroughly verifies both the standard and compact string representations:
- Tests a large value to confirm leading zeros are removed when using `toString(true)`
- Tests the zero value case to ensure it returns "0x0" instead of "0x" or a zero-padded string
- Validates that the default behavior remains unchanged

The test cases are well-chosen to cover both standard use cases and edge conditions.

</details>
<details>
<summary>packages/network/src/thor-client/transactions/transactions-module.ts (1)</summary>

`22-44`: **Improved import organization.**

The import statements have been reorganized to group related imports together, improving code readability and maintainability. The change is particularly helpful for this file which has many imports from different modules.

The grouping by related functionality (contracts, gas, logs, etc.) makes it easier to understand the dependencies of this module.

</details>
<details>
<summary>packages/core/src/vcdm/HexUInt.ts (1)</summary>

`2-3`: **Minor improvement to import ordering.**

The import statements have been reordered to place `Hex` before `HexInt`, which is a logical ordering since `HexInt` extends `Hex`. This is a small but meaningful improvement to the code organization.

</details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts (1)</summary>

`2-8`: **Import organization looks good.**

The reordering of imports follows a logical pattern with error imports first, followed by type imports.

</details>
<details>
<summary>apps/sdk-hardhat-integration/package.json (1)</summary>

`12-12`: **Well-structured test script for Galactica devnet.**

The new test script enables running tests specifically against the Galactica devnet network, aligning with the PR's objective to integrate the Hardhat plugin with Galactica.

</details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/rpc-mapper.ts (1)</summary>

`2-2`: **Import order restructuring looks good.**

The reorganization of imports follows a consistent pattern with type imports at the top and method imports grouped logically.



Also applies to: 62-62

</details>
<details>
<summary>apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts (1)</summary>

`41-44`: **Good improvement to test robustness.**

Replacing a hardcoded address with dynamic signer selection makes the test more flexible and maintainable. The test will now work across different environments without requiring specific account configurations.

</details>
<details>
<summary>.github/workflows/test-apps.yml (2)</summary>

`29-30`: **Secure handling of mnemonic for Galactica devnet tests**

The addition of the environment variable from GitHub secrets is a secure approach for handling sensitive information like mnemonics.

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 YAMLlint (1.35.1)</summary>

[warning] 30-30: wrong indentation: expected 18 but found 16

(indentation)

</details>

</details>

---

`50-54`: **Support for Galactica devnet testing**

The conditional execution of additional tests specifically for the sdk-hardhat-integration directory is a good approach to implement specialized testing flows.

</details>
<details>
<summary>packages/network/src/provider/utils/formatter/blocks/types.d.ts (1)</summary>

`83-86`: **Making baseFeePerGas optional to reflect Galactica fork compatibility**

Good change to make the `baseFeePerGas` property optional with a clear JSDoc comment explaining its availability only since the Galactica fork. This properly reflects the protocol behavior where this field isn't present in pre-Galactica blocks.

</details>
<details>
<summary>packages/network/src/provider/utils/formatter/blocks/formatter.ts (2)</summary>

`7-8`: **Import organization**

Imports are reordered for better organization without changing functionality.

---

`57-59`: **Conditionally include baseFeePerGas only when defined**

Good implementation to conditionally include the `baseFeePerGas` property only when it's defined, which aligns with the type definition change making it optional. This ensures backward compatibility with pre-Galactica blocks while supporting the new field when present.

</details>
<details>
<summary>packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts (2)</summary>

`6-11`: **Import organization**

Imports are reordered for better organization without changing functionality.

---

`189-196`: **Special error handling for eth_call to support truffle-contract**

Great improvement to error handling for the `eth_call` RPC method by throwing a Hardhat error with the specific message `'revert'`. This enhances compatibility with `@nomiclabs/truffle-contract` which expects this format for error handling.

The comment explaining the rationale is helpful for future maintenance.

</details>
<details>
<summary>packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts (1)</summary>

`113-155`: **New test cases for zero balance scenarios**

The added negative test cases correctly reflect a behavior change in the `eth_call` implementation that now throws a `JSONRPCInternalError` when a transaction reverts - in this case, due to insufficient balance. This improves the test coverage by explicitly verifying the error handling for transactions that attempt to send VET when the balance is zero.

These test cases use different block identifiers (`0x0`, `Hex.of(0).toString()`, and `"earliest"`) which ensures proper testing of the block parameter handling in the error case scenario.

</details>
<details>
<summary>packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts (1)</summary>

`42-51`: **Support for omitted block reference parameter**

Good addition of a test case for the scenario where the block reference parameter is omitted from the input. This ensures that the enhanced flexibility in the `eth_estimateGas` implementation (which now accepts either one or two parameters) is properly tested.

This change aligns with Ethereum JSON-RPC API conventions where block parameters are often optional and default to "latest" when not provided.

</details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts (2)</summary>

`1-1`: **Import addition for HexUInt**

The addition of the HexUInt import is appropriate for handling hex formatting and big integer operations needed for gas price calculations.

---

`10-19`: **Support for legacy transaction gas pricing**

Good implementation of backward compatibility for legacy transactions. The code correctly checks if `baseFeePerGas` is undefined and falls back to fetching the base gas price from the contract when working with pre-EIP-1559 style transactions.

</details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts (3)</summary>

`33-39`: **Improved if-statement formatting**

Good improvement to add explicit braces around the if-statement body, ensuring proper scoping of the thrown error and following consistent code style.

---

`67-76`: **Enhanced error handling for reverted transactions**

Excellent addition to detect and properly report reverted transactions. This change ensures that simulation failures are propagated with detailed context, including the VM error message, which will help with debugging issues in client applications.

This implementation aligns with the updated test fixtures that now expect `JSONRPCInternalError` for zero balance scenarios.

---

`81-83`: **Prevent re-wrapping of internal errors**

Good improvement to re-throw already wrapped `JSONRPCInternalError` instances directly. This preserves the original error details and stack trace, making debugging easier by avoiding unnecessary error wrapping.

</details>
<details>
<summary>packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts (5)</summary>

`1-1`: **Appropriate use of core utilities**

Good addition of the `HexUInt` import which will be used for better hex string formatting.

---

`12-13`: **LGTM: Import reorganization**

Good job reordering imports by purpose and adding proper type imports.

---

`34-34`: **Improved parameter validation for better Ethereum compatibility**

Excellent enhancement that now accepts either one or two parameters, following common Ethereum RPC implementations which often make the block parameter optional.

---

`42-44`: **Sensible default for optional block parameter**

Good implementation that falls back to 'latest' when only the transaction object is provided, which is the standard default in Ethereum clients.

---

`69-69`: **More robust hex formatting using specialized utilities**

Great improvement replacing manual hex string conversion with `HexUInt` utility. This ensures consistent formatting and leverages the SDK's built-in utilities for numeric-to-hex conversion.

</details>
<details>
<summary>apps/sdk-hardhat-integration/hardhat.config.ts (1)</summary>

`3-4`: **LGTM: Import order adjustment**

The reordering of imports is clean and logical, placing the plugin import before the types.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T08:22:06Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T08:36:28Z
user: login: coderabbitai[bot]
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T08:37:07Z
user: login: claytonneal
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T08:40:04Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:05:33Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:05:48Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:06:23Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:07:23Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:12:44Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:15:25Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:27:04Z
user: login: freemanzMrojo
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T09:29:34Z
user: login: claytonneal
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-29T12:56:45Z

Review comments:
diff_hunk: @@ -26,13 +26,18 @@ jobs:
               run: yarn build
 
             - name: Test apps
+              env:
+                GALACTICA_DEV_MNEMONIC: ${{ secrets.GALACTICA_DEV_MNEMONIC }}
path: .github/workflows/test-apps.yml
user: login: claytonneal
body: where is mnemonic documented?
created_at: 2025-04-29T08:18:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,6 +46,12 @@ jobs:
                   
                       # Test
                       yarn test
+                      
+                      # Galactica devnet test for sdk-hardhat-integration
+                      if [ "$dir_name" = "sdk-hardhat-integration" ]; then
+                        echo "Running additional galactica devnet tests"
+                        yarn test:galactica:devnet
path: .github/workflows/test-apps.yml
user: login: claytonneal
body: why we using galactica devnet here and not solo?
created_at: 2025-04-29T08:19:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -145,6 +145,26 @@ const config: HardhatUserConfig = {
             httpHeaders: {}
         } satisfies HttpNetworkConfig,
 
+        /**
+         * Galactica devnet configuration
+         */
+        vechain_galactica_devnet: {
path: apps/sdk-hardhat-integration/hardhat.config.ts
user: login: claytonneal
body: can this not be done on solo, whats special about these accounts?
created_at: 2025-04-29T08:20:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,8 +38,9 @@ describe('VechainHelloWorldWithNonEmptyConstructor', function () {
     });
 
     it('should break with an specific error due to insufficient VTHO', async function () {
+        const signers = await ethers.getSigners();
         const accountWithNoVTHO = await ethers.getSigner(
-            '0xB381e7da548601B1CCB05C66d415b20baE40d828'
+            signers[signers.length - 1].address
path: apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts
user: login: claytonneal
body: is this clear that account will always have no VTHO ?
created_at: 2025-04-29T08:21:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -145,6 +145,26 @@ const config: HardhatUserConfig = {
             httpHeaders: {}
         } satisfies HttpNetworkConfig,
 
+        /**
+         * Galactica devnet configuration
+         */
+        vechain_galactica_devnet: {
+            // Galactica devnet
+            url: 'https://galactica.dev.node.vechain.org/',
+            accounts: {
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
path: apps/sdk-hardhat-integration/hardhat.config.ts
user: login: coderabbitai[bot]
body: _💡 Verification agent_

<details>
<summary>🧩 Analysis chain</summary>

**Consider a more explicit fallback for the mnemonic**

The current fallback to an empty string when `GALACTICA_DEV_MNEMONIC` is not set could lead to confusing errors during execution. Consider providing a more explicit fallback or throwing an error when the environment variable is missing.


```diff
-                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? 
+                   (function() { 
+                     if (process.env.NODE_ENV === 'production') {
+                       throw new Error('GALACTICA_DEV_MNEMONIC environment variable must be set in production');
+                     }
+                     return 'test test test test test test test test test test test junk';
+                   })(),
```

This provides a test mnemonic for development but will error explicitly in production environments.

---

🏁 Script executed:

```shell
#!/bin/bash
# Check if there are examples of this pattern elsewhere in the codebase
fd --type file --extension ts --extension js "process\.env.*\?\?" --exec grep -l "{}" \;
```

Length of output: 91

---

🏁 Script executed:

```shell
#!/bin/bash
set -e

# Search for other nullish-coalesce fallbacks on process.env in .ts/.js files
rg -l --type ts --type js 'process\.env\.\w+\s*\?\?' .

# Search for any usage of GALACTICA_DEV_MNEMONIC across .ts/.js files
rg -n --type ts --type js 'GALACTICA_DEV_MNEMONIC' .
```

Length of output: 288

---



</details>

**Use an explicit mnemonic fallback instead of an empty string**

Falling back to `''` when `GALACTICA_DEV_MNEMONIC` is unset will lead to confusing “invalid mnemonic” errors. Instead, require the env var in production and use a known test mnemonic (or let Hardhat’s default apply) in development:

• File: apps/sdk-hardhat-integration/hardhat.config.ts  
  Line: 155  

```diff
-                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ??
+                  (() => {
+                    if (process.env.NODE_ENV === 'production') {
+                      throw new Error(
+                        'GALACTICA_DEV_MNEMONIC must be set in production'
+                      );
+                    }
+                    // 12-word Hardhat default test mnemonic
+                    return 'test test test test test test test test test test test junk';
+                  })(),
```

This ensures:
- Production builds fail fast if the mnemonic is missing.  
- Development uses a predictable test account.  



<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

`````suggestion
                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ??
                  (() => {
                    if (process.env.NODE_ENV === 'production') {
                      throw new Error(
                        'GALACTICA_DEV_MNEMONIC must be set in production'
                      );
                    }
                    // 12-word Hardhat default test mnemonic
                    return 'test test test test test test test test test test test junk';
                  })(),
`````

</details>

<!-- suggestion_end -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-29T08:22:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -151,6 +110,48 @@ const negativeCasesFixtures = [
             'latest'
         ],
         expected: JSONRPCInternalError
+    },
+    {
+        description:
+            'Fails to send 1 VET to the receiver since balace is 0. (using { blockNumber: 0x0 } )',
+        input: [
+            {
+                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
+                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
+                value: '1000000000000000000',
+                data: '0x'
+            },
+            '0x0'
+        ],
+        expected: JSONRPCInternalError
path: packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts
user: login: claytonneal
body: think we need to assert on the actual RPC details not just the exception type
for me id like to know that the RPC response format is valid
created_at: 2025-04-29T08:34:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -145,6 +145,26 @@ const config: HardhatUserConfig = {
             httpHeaders: {}
         } satisfies HttpNetworkConfig,
 
+        /**
+         * Galactica devnet configuration
+         */
+        vechain_galactica_devnet: {
+            // Galactica devnet
+            url: 'https://galactica.dev.node.vechain.org/',
+            accounts: {
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
path: apps/sdk-hardhat-integration/hardhat.config.ts
user: login: freemanzMrojo
body: Not meant to be run in production
created_at: 2025-04-29T08:36:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -145,6 +145,26 @@ const config: HardhatUserConfig = {
             httpHeaders: {}
         } satisfies HttpNetworkConfig,
 
+        /**
+         * Galactica devnet configuration
+         */
+        vechain_galactica_devnet: {
+            // Galactica devnet
+            url: 'https://galactica.dev.node.vechain.org/',
+            accounts: {
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
path: apps/sdk-hardhat-integration/hardhat.config.ts
user: login: coderabbitai[bot]
body: @freemanzMrojo I understand - this configuration is meant for development/testing environments only. In that case, would you consider a simpler improvement that just provides a default test mnemonic instead of an empty string? This would prevent cryptic "invalid mnemonic" errors when the environment variable isn't set:

```diff
-                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? 'test test test test test test test test test test test junk',
```

If the empty string is intentional (perhaps to force setting the variable), that's perfectly fine too.

🐰


<!-- <agentComponentType>chat-answer</agentComponentType> -->

<!-- <rawResChunk><answer>@freemanzMrojo I understand - this configuration is meant for development/testing environments only. In that case, would you consider a simpler improvement that just provides a default test mnemonic instead of an empty string? This would prevent cryptic "invalid mnemonic" errors when the environment variable isn't set:

```diff
-                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? '',
+                mnemonic: process.env.GALACTICA_DEV_MNEMONIC ?? 'test test test test test test test test test test test junk',
```

If the empty string is intentional (perhaps to force setting the variable), that's perfectly fine too.

🐰</answer></rawResChunk> -->

<!-- This is an auto-generated reply by CodeRabbit -->
created_at: 2025-04-29T08:37:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -63,9 +64,23 @@ const ethCall = async (
             } satisfies SimulateTransactionOptions
         );
 
+        if (simulatedTx[0].reverted) {
path: packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts
user: login: claytonneal
body: want to check this is valid format in the end, do you know what RPC json gets produced?
created_at: 2025-04-29T08:37:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,14 +31,17 @@ const ethEstimateGas = async (
     params: unknown[]
 ): Promise<string> => {
     // Input validation
-    if (params.length !== 2 || typeof params[0] !== 'object')
+    if (params.length < 1 || params.length > 2 || typeof params[0] !== 'object')
         throw new JSONRPCInvalidParams(
             'eth_estimateGas',
             `Invalid input params for "eth_estimateGas" method. See ${RPC_DOCUMENTATION_URL} for details.`,
             { params }
         );
 
     try {
+        if (params.length === 1) {
path: packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts
user: login: claytonneal
body: is this needed - the spec is that the block "revision" is mandatory?
created_at: 2025-04-29T08:38:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,11 +7,23 @@ import { type ThorClient } from '../../../../../thor-client';
  * @returns The current gas price in Wei unit considering that 1 VTHO equals 1e18 Wei.
  */
 const ethGasPrice = async (thorClient: ThorClient): Promise<string> => {
-    const {
-        result: { plain }
-    } = await thorClient.contracts.getBaseGasPrice();
+    const bestBlock = await thorClient.blocks.getBestBlockCompressed();
path: packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts
user: login: claytonneal
body: we can use thorClient.forkDetector instead?
created_at: 2025-04-29T08:39:20Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,6 +46,12 @@ jobs:
                   
                       # Test
                       yarn test
+                      
+                      # Galactica devnet test for sdk-hardhat-integration
+                      if [ "$dir_name" = "sdk-hardhat-integration" ]; then
+                        echo "Running additional galactica devnet tests"
+                        yarn test:galactica:devnet
path: .github/workflows/test-apps.yml
user: login: freemanzMrojo
body: `sdk-hardhat-integration` currently only tests against `testnet` (`yarn test`) so it felt aligned to me to do the same towards galactica. 

otherwise we would need to set up a structure that IMO is outside of the scope of the ticket, if solo is required for this project.
created_at: 2025-04-29T09:05:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -26,13 +26,18 @@ jobs:
               run: yarn build
 
             - name: Test apps
+              env:
+                GALACTICA_DEV_MNEMONIC: ${{ secrets.GALACTICA_DEV_MNEMONIC }}
path: .github/workflows/test-apps.yml
user: login: freemanzMrojo
body: will reply to this in slack
created_at: 2025-04-29T09:05:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -145,6 +145,26 @@ const config: HardhatUserConfig = {
             httpHeaders: {}
         } satisfies HttpNetworkConfig,
 
+        /**
+         * Galactica devnet configuration
+         */
+        vechain_galactica_devnet: {
path: apps/sdk-hardhat-integration/hardhat.config.ts
user: login: freemanzMrojo
body: nothing special other than having funds. the reason is the one exposed above about the existing script running against testnet.
created_at: 2025-04-29T09:06:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,8 +38,9 @@ describe('VechainHelloWorldWithNonEmptyConstructor', function () {
     });
 
     it('should break with an specific error due to insufficient VTHO', async function () {
+        const signers = await ethers.getSigners();
         const accountWithNoVTHO = await ethers.getSigner(
-            '0xB381e7da548601B1CCB05C66d415b20baE40d828'
+            signers[signers.length - 1].address
path: apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts
user: login: freemanzMrojo
body: same criteria as the previous iteration, there was no guarantee either that `0xB381e7da548601B1CCB05C66d415b20baE40d828` wont have funds in the future.
created_at: 2025-04-29T09:07:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -63,9 +64,23 @@ const ethCall = async (
             } satisfies SimulateTransactionOptions
         );
 
+        if (simulatedTx[0].reverted) {
path: packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts
user: login: freemanzMrojo
body: This is an example of a response, I can see it currently covered by the existing type `TransactionSimulationResult[]`:

```
[
  {
    "data": "0x0000000000000000000000000000000000000000000000000000000000000001",
    "events": [
      {
        "address": "0x0000000000000000000000000000456e65726779",
        "topics": [
          "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
          "0x0000000000000000000000006d95e6dca01d109882fe1726a2fb9865fa41e7aa",
          "0x0000000000000000000000000f872421dc479f3c11edd89512731814d0598db5"
        ],
        "data": "0x0000000000000000000000000000000000000000000000013f306a2409fc0000"
      }
    ],
    "transfers": [],
    "gasUsed": 13326,
    "reverted": false,
    "vmError": ""
  },
  {
    "data": "0x",
    "events": [],
    "transfers": [
      {
        "sender": "0x6d95e6dca01d109882fe1726a2fb9865fa41e7aa",
        "recipient": "0xf077b491b355e64048ce21e3a6fc4751eeea77fa",
        "amount": "0x6124fee993bc00000"
      }
    ],
    "gasUsed": 0,
    "reverted": false,
    "vmError": ""
  },
  {
    "data": "0x608060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631820cabb146044575b600080fd5b348015604f57600080fd5b506056606c565b6040518082815260200191505060405180910390f35b62015180815600a165627a7a723058200ac7475da248e2fc26c057319e296e90c24d5f8b9bf956fb3b77545642cad3b10029",
    "events": [
      {
        "address": "0xecadd5492c1fa085e40e2c17e79f1a03f38f86ca",
        "topics": [
          "0xb35bf4274d4295009f1ec66ed3f579db287889444366c03d3a695539372e8951"
        ],
        "data": "0x0000000000000000000000006d95e6dca01d109882fe1726a2fb9865fa41e7aa"
      }
    ],
    "transfers": [],
    "gasUsed": 31881,
    "reverted": false,
    "vmError": ""
  }
]
```
created_at: 2025-04-29T09:12:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -30,14 +31,17 @@ const ethEstimateGas = async (
     params: unknown[]
 ): Promise<string> => {
     // Input validation
-    if (params.length !== 2 || typeof params[0] !== 'object')
+    if (params.length < 1 || params.length > 2 || typeof params[0] !== 'object')
         throw new JSONRPCInvalidParams(
             'eth_estimateGas',
             `Invalid input params for "eth_estimateGas" method. See ${RPC_DOCUMENTATION_URL} for details.`,
             { params }
         );
 
     try {
+        if (params.length === 1) {
path: packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts
user: login: freemanzMrojo
body: it is needed, yep. `latest` gets parsed to `best` at `DefaultBlockToRevision`. `hardhat-truffle` though does not pass it when calling `eth_estimateGas`, hence the need of this condition (before this PR it was mandatory).
created_at: 2025-04-29T09:15:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,11 +7,23 @@ import { type ThorClient } from '../../../../../thor-client';
  * @returns The current gas price in Wei unit considering that 1 VTHO equals 1e18 Wei.
  */
 const ethGasPrice = async (thorClient: ThorClient): Promise<string> => {
-    const {
-        result: { plain }
-    } = await thorClient.contracts.getBaseGasPrice();
+    const bestBlock = await thorClient.blocks.getBestBlockCompressed();
path: packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts
user: login: freemanzMrojo
body: done
created_at: 2025-04-29T09:27:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -151,6 +110,48 @@ const negativeCasesFixtures = [
             'latest'
         ],
         expected: JSONRPCInternalError
+    },
+    {
+        description:
+            'Fails to send 1 VET to the receiver since balace is 0. (using { blockNumber: 0x0 } )',
+        input: [
+            {
+                from: '0x7487d912d03ab9de786278f679592b3730bdd540',
+                to: '0x3db469a79593dcc67f07DE1869d6682fC1eaf535',
+                value: '1000000000000000000',
+                data: '0x'
+            },
+            '0x0'
+        ],
+        expected: JSONRPCInternalError
path: packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts
user: login: freemanzMrojo
body: i think that should be part of a different ticket since the current fixture is built like that and it is unrelated to the scope of what I am doing, I am just following the rails.

btw, I agree with you, payload should be checked, that is the reason why we got to this point without knowing that `eth_call` was not working as intended.
created_at: 2025-04-29T09:29:34Z
author_association: CONTRIBUTOR

PR comments:
user: login: coderabbitai[bot]
created_at: 2025-04-25T14:01:20Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are disabled on base/target branches other than the default branch.
> 
> 
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough

This update introduces support for the Galactica devnet network in the Hardhat integration app by adding a new network configuration and a corresponding test script. The workflow for testing apps is enhanced to conditionally run specialized tests for this network, using a mnemonic provided via GitHub secrets. Core provider and formatter logic are updated to handle EIP-1559 gas pricing, optional `baseFeePerGas` fields, and improved error handling for RPC methods. Related fixtures and unit tests are adjusted to reflect these changes, including new compact hex formatting and revised test scenarios for gas estimation and transaction simulation.

## Changes

| Files/Paths                                                                                 | Change Summary |
|--------------------------------------------------------------------------------------------|---------------|
| `.github/workflows/test-apps.yml`                                                          | Enhanced workflow to set `GALACTICA_DEV_MNEMONIC` from secrets and conditionally run `test:galactica:devnet` for the `sdk-hardhat-integration` app. |
| `apps/sdk-hardhat-integration/hardhat.config.ts`, `apps/sdk-hardhat-integration/package.json` | Added Galactica devnet network config and a script to run tests on this network. |
| `apps/sdk-hardhat-integration/test/VechainHelloWorldWithNonEmptyConstructor.testnet.test.ts` | Changed test to dynamically select the last signer instead of a hardcoded address. |
| `packages/core/src/vcdm/Hex.ts`, `packages/core/tests/vcdm/Hex.unit.test.ts`               | Updated `Hex.toString` to support a compact mode and added unit tests for this feature. |
| `packages/core/src/vcdm/HexUInt.ts`                                                        | Reordered import statements for clarity. |
| `packages/network/src/provider/providers/hardhat-provider/hardhat-provider.ts`             | Improved error handling for `eth_call` to throw Hardhat-compatible errors on revert. |
| `packages/network/src/provider/utils/formatter/blocks/formatter.ts`, `.../blocks/types.d.ts` | `baseFeePerGas` is now optional and only included if present in the block; type updated accordingly. |
| `packages/network/src/provider/utils/rpc-mapper/methods/eth_call/eth_call.ts`              | Added revert detection for simulated transactions and improved error propagation. |
| `packages/network/src/provider/utils/rpc-mapper/methods/eth_estimateGas/eth_estimateGas.ts` | Allowed single-parameter calls, defaulting block to `'latest'`, and used `HexUInt` for result formatting. |
| `packages/network/src/provider/utils/rpc-mapper/methods/eth_gasPrice/eth_gasPrice.ts`      | Added EIP-1559 gas price calculation, using `baseFeePerGas` and `maxPriorityFeePerGas` if available. |
| `packages/network/src/provider/utils/rpc-mapper/methods/eth_feeHistory/eth_feeHistory.ts`, `.../rpc-mapper.ts`, `.../transactions-module.ts` | Reordered import statements for clarity; no functional changes. |
| `packages/network/tests/provider/fixture.ts`, `.../formatter/fixture.ts`, `.../rpc-mapper/methods/eth_getBlockByNumber/fixture.ts` | Removed `baseFeePerGas: '0x0'` from block fixtures to match new optional field logic. |
| `packages/network/tests/provider/rpc-mapper/methods/eth_call/fixture.ts`                   | Moved certain cases from positive to negative, now expecting errors on zero-balance transfers. |
| `packages/network/tests/provider/rpc-mapper/methods/eth_estimateGas/fixture.ts`            | Added positive test for missing block reference and removed negative case for the same scenario. |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant GitHub Actions
    participant Apps Workflow
    participant sdk-hardhat-integration
    participant Hardhat
    participant Galactica Devnet

    GitHub Actions->>Apps Workflow: Start Test Apps Workflow
    Apps Workflow->>sdk-hardhat-integration: Set GALACTICA_DEV_MNEMONIC from secrets
    Apps Workflow->>sdk-hardhat-integration: yarn test
    Apps Workflow->>sdk-hardhat-integration: If dir_name == 'sdk-hardhat-integration', run yarn test:galactica:devnet
    sdk-hardhat-integration->>Hardhat: Run tests on vechain_galactica_devnet
    Hardhat->>Galactica Devnet: Connect using mnemonic, run tests
    Galactica Devnet-->>Hardhat: Return test results
    Hardhat-->>sdk-hardhat-integration: Report test status
    sdk-hardhat-integration-->>Apps Workflow: Test results
```

## Possibly related PRs

- **vechain/vechain-sdk-js#1971**: Introduces a new solo setup package and modifies tests to use addresses and configurations from this solo setup, similar to this PR's changes in testing infrastructure and configuration.

## Poem

> In the warren of code, a new path we pave,  
> Galactica devnet now joins the brave.  
> Hexes compact, gas prices anew,  
> Tests run smarter, with fixtures askew.  
> Bunnies rejoice as the network expands—  
> More hops for our paws, more carrots for our hands!  
> 🐇✨

<!-- walkthrough_end -->
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=vechain/vechain-sdk-js&utm_content=2048):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-25T15:46:08Z
body: <!-- Jest Coverage Comment: build -->
# Test Coverage

## Summary

| Lines | Statements | Branches | Functions |
| --- | --- | --- | --- |
| <a href="https://github.com/vechain/vechain-sdk-js/blob/42e1c6729b686b47335735ade0cf3a88edbcbd72/README.md"><img alt="Coverage: 98%" src="https://img.shields.io/badge/Coverage-98%25-brightgreen.svg" /></a><br/> | 98.08% (4156/4237) | 95.33% (1389/1457) | 97.87% (831/849) |


| Title | Tests | Skipped | Failures | Errors | Time |
| --- | --- | --- | --- | --- | --- |
| core | 863 | 0 :zzz: | 0 :x: | 0 :fire: | 43.484s :stopwatch: |
| network | 800 | 0 :zzz: | 0 :x: | 0 :fire: | 2m 39s :stopwatch: |
| errors | 43 | 0 :zzz: | 0 :x: | 0 :fire: | 9.365s :stopwatch: |
| logging | 3 | 0 :zzz: | 0 :x: | 0 :fire: | 7.092s :stopwatch: |
| hardhat-plugin | 19 | 0 :zzz: | 0 :x: | 0 :fire: | 17.493s :stopwatch: |
| aws-kms-adapter | 23 | 0 :zzz: | 0 :x: | 0 :fire: | 43.529s :stopwatch: |
| ethers-adapter | 5 | 0 :zzz: | 0 :x: | 0 :fire: | 10.375s :stopwatch: |

author_association: NONE
user: login: claytonneal
created_at: 2025-04-29T08:18:20Z
body: @coderabbitai review
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-04-29T08:18:26Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
<details>
<summary>✅ Actions performed</summary>

Review triggered.

> Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

</details>
author_association: CONTRIBUTOR