WARP

WARP.md

This file provides guidance to WARP (warp.dev) when working with code in this repository.

Project overview

  • Language / ecosystem: Raku module, published as Net::Ethereum (see META6.json).

  • Purpose: Client-side interface to an Ethereum JSON-RPC node, including RPC wrappers, ABI encoding/decoding, contract deployment, and fee/gas helpers.

  • Primary entry point: Net::Ethereum class in lib/Net/Ethereum.rakumod.

Refer to README.md for usage examples and background context.

Common commands

Test suite

Tests talk to a live Ethereum node and expect Solidity tooling to be installed.

  • Run all tests with the Raku test harness:

    • prove6 ./t

    • or prove -ve 'raku -Ilib'

  • Run a single test file (useful while iterating):

    • prove6 ./t/01.t

    • or raku -Ilib t/02.t

Tests assume:

  • Ethereum JSON-RPC node reachable at http://127.0.0.1:8501.

  • Solidity compiler available at /usr/local/bin/solc.

  • Environment variable TXHASH set to a valid contract transaction hash, e.g.:

    • export TXHASH=0x244409bb2cced62a2b93b2688167438ef47f60f1b5aa8b6c64e9de460ddec604

  • Optional helper for port forwarding to the node (when the node is on a different port):

    • ./hooks/forward.sh 8501 <actual_node_port>

Module build / install (Raku ecosystem)

Standard Raku module commands apply (driven by META6.json):

  • Run tests via zef:

    • zef test .

  • Install the module locally:

    • zef install .

These are useful when you want to validate or install the module in a fresh environment beyond prove6-driven tests.

CI pipeline

Continuous integration is defined in .gitlab-ci.yml and is Docker-heavy. Key points:

  • Spins up two containers:

    • ethereum-dev: provides a local geth-based Ethereum network.

    • net-ethereum-test: Rakudo-based environment for running Raku tests.

  • Inside CI, the pipeline:

    • Compiles and tests Solidity contracts from an external smart-contracts repo.

    • Produces a smart-contract.hash file and exports TXHASH from it.

    • Runs hooks/forward.sh in the Rakudo container to forward port 8501 to the actual Ethereum node port.

    • Clones http-useragent and pheix-research/smart-contracts, then runs tests via trove-cli using .trove.conf.yaml and writes artifacts testreport.*.

You typically do not need to reproduce the entire CI pipeline locally unless you are debugging integration with the smart-contracts test harness.

Code architecture

High-level structure

  • lib/Net/Ethereum.rakumod

    • Defines the main Net::Ethereum class.

    • Handles JSON-RPC transport, method wrappers for Ethereum APIs, ABI encoding/decoding logic, contract deployment helpers, and fee/gas calculations.

  • lib/Net/Ethereum/Utils.rakumod

    • Defines Net::Ethereum::Utils with numeric helpers used in fee calculations (e.g. blob gas fee exponential approximation).

  • t/*.t

    • Test bundle that exercises JSON-RPC calls against a live node, including account management, contract calls, and EIP-1559/EIP-4844-style fee paths.

  • t/data, t/solcoutput, t/solctarget

    • Test fixtures, compiled Solidity artifacts (*.abi/*.bin), and placeholder directories used by tests.

  • hooks/forward.sh

    • Shell script to forward local TCP connections from an external port to the actual Ethereum node port using socat.

Net::Ethereum responsibilities

  1. Connection and JSON-RPC transport

    • Uses HTTP::UserAgent, HTTP::Request, and HTTP::Cookies to talk to an Ethereum node at $.api_url (default http://127.0.0.1:8501).

    • Supports keep-alive connections via check_ua_keepalive, store_connection, and close_connection when $!keepalive is enabled.

    • All RPC calls ultimately go through node_request($query) which:

      • Assigns unique JSON-RPC ids.

      • Encodes requests with JSON::Fast::to-json.

      • Validates HTTP status codes and parses JSON responses with robust error handling.

      • Throws typed exceptions for malformed responses, mismatched IDs, or HTTP errors.

  2. Error and validation model

    • Custom exception hierarchy (Net::Ethereum::X and subclasses) for:

      • ABI parsing errors (X::ParseABI).

      • Invalid blocks/tags/data/topics (X::InvalidBlock, X::InvalidTag, X::InvalidData, X::InvalidTopics).

      • Password issues (X::InvalidPassword).

      • JSON-RPC errors (X::JSONAPI and nested subclasses).

    • Internal validators like !check_block and tag checks in methods such as eth_getBalance and eth_getTransactionCount ensure inputs conform to Ethereum semantics.

  3. Ethereum JSON-RPC surface

    • Direct mappings for core APIs:

      • Network introspection: web3_clientVersion, web3_sha3, net_version, net_listening, net_peerCount, eth_syncing, eth_coinbase, eth_mining, eth_hashrate, eth_gasPrice, eth_accounts, eth_blockNumber.

      • State queries: eth_getBalance, eth_getTransactionCount, eth_getTransactionByHash, eth_getBlockByNumber, eth_getBlockByHash, eth_getBlockTransactionCountByHash, eth_getCode, eth_getTransactionReceipt, eth_getLogs.

      • Calls and transactions: eth_call, eth_estimateGas, eth_sendTransaction, eth_signTransaction, eth_sendRawTransaction.

      • Personal API: personal_newAccount, personal_unlockAccount, personal_lockAccount, personal_listWallets, personal_sign, personal_ecRecover.

      • Debug API: debug_traceTransaction.

      • Fee-related APIs: eth_maxPriorityFeePerGas, eth_createAccessList.

    • A convenience get_account(:$index) accessor caches and validates accounts returned by eth_accounts.

  4. ABI handling and contract interaction

    • Maintains contract ABI JSON in $.abi and contract address in $.contract_id.

    • ABI introspection helpers:

      • get_function_abi($name) and get_constructor_abi parse the ABI JSON and select the corresponding entry.

    • Encoding/decoding:

      • marshal_int / unmarshal_int implement 256-bit signed/unsigned integer encoding.

      • string2hex, hex2string, buf2hex, hex2buf handle non-integer payloads.

      • getContractMethodId($signature) computes the 4-byte method selector via Keccak256 (web3_sha3).

      • marshal($fname, $fparams) builds full call data for functions and constructors, including multi-pass handling of dynamic types (string, bytes) and offsets.

      • unmarshal($fname, $raw_data) decodes returned ABI-encoded data into a Hash, with optional inclusion of raw data via $.return_raw_data.

    • High-level contract helpers:

      • contract_method_call_estimate_gas and contract_method_call construct the call, perform eth_call, and decode the result using ABI metadata.

  5. Contract deployment pipeline

    • compile_and_deploy_contract is the high-level workflow used both by users and tests:

      • Invokes solc via shell with --bin and --abi, honoring $.solidity, $.evmver, and :contract_path / :compile_output_path.

      • Loads generated *.bin and *.abi files and stores ABI in $.abi.

      • Unlocks the source account via personal_unlockAccount unless :skipunlock is set.

      • Uses deploy_contract_estimate_gas and deploy_contract to submit the transaction with a configurable gas safety factor ($!gaspercent).

      • Waits for the deployment transaction to be mined via wait_for_transaction(:contract) which also sets $.contract_id.

      • Polls eth_getCode to ensure the contract code is deployed.

      • Optionally cleans up artifacts in :compile_output_path when $.cleanup is true.

    • retrieve_contract($hash) is a convenience wrapper over eth_getTransactionReceipt to retrieve contractAddress.

  6. Fee and gas utilities (EIP-1559 and blob gas)

    • Constants and logic near the top of Net::Ethereum implement blob gas fee behavior inspired by EIP-4844/EIP-7892.

    • get_fee_data computes a fee data structure combining:

      • Legacy gasPrice.

      • EIP-1559 max base fee and priority fee (maxFeePerGas, maxPriorityFeePerGas) using eth_getBlockByNumber("latest") and eth_maxPriorityFeePerGas.

      • Blob gas components (baseFeePerBlobGas, maxFeePerBlobGas) when excessBlobGas / blobGasUsed are present.

    • get_base_fee_per_blob_gas uses Net::Ethereum::Utils.fake_exponential to calculate blob base fees given block blob gas metrics.

Utility class: Net::Ethereum::Utils

  • Located in lib/Net/Ethereum/Utils.rakumod.

  • Exposes fake_exponential(:$factor, :$numerator, :$denominator) which implements an integer-only exponential-style approximation used in blob gas fee calculations.

  • This function is central to maintaining consistency with Ethereumโ€™s fee update formulas in get_base_fee_per_blob_gas.

Test bundle

  • t/01.t

    • Basic connectivity and JSON-RPC coverage: node health (node_ping), web3, net, and core eth endpoints.

  • t/02.t

    • More advanced behavioral tests:

      • Wallet and account management via personal_* calls.

      • Balance and transaction count queries across different tags (latest, earliest, pending, specific blocks).

      • Transaction/receipt retrieval and smart-contract interaction driven by TXHASH and compiled artifacts in t/solcoutput.

      • Fee and gas-related calls (eth_estimateGas, eth_maxPriorityFeePerGas, eth_createAccessList).

  • Other t/*.t files continue coverage of additional methods and scenarios, generally assuming the same live-node and contract setup.

When modifying core behavior (RPC wrappers, ABI handling, fee calculations), adjust or extend the corresponding tests under t/ and ensure the live-node environment assumptions are kept in sync with README.md and the CI pipeline.

Net::Ethereum v0.0.185

A Raku interface for interacting with the Ethereum blockchain and ecosystem via JSON RPC API

Authors

  • Konstantin Narkhov

License

Artistic-2.0

Dependencies

Node::Ethereum::Keccak256::NativeJSON::FastHTTP::UserAgent:ver<1.1.58+>:auth<zef:knarkhov>HTTP::Request:ver<1.1.58+>:auth<zef:knarkhov>HTTP::Cookies:ver<1.1.58+>:auth<zef:knarkhov>Test::MockHTTP::Tiny

Provides

  • Net::Ethereum
  • Net::Ethereum::HTTP::Client
  • Net::Ethereum::HTTP::Client::Tiny
  • Net::Ethereum::HTTP::Client::UserAgent
  • Net::Ethereum::Utils

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.