Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Test Client Setup

Overview

This guide covers how to create and configure Brane.Tester clients for integration testing. Brane provides multiple ways to connect to test nodes, from simple one-liners to fully customized builder patterns.

connectTest() Factory Methods

The Brane interface provides static factory methods for quickly creating test clients. These methods are designed for common testing scenarios with sensible defaults.

Default Connection

The simplest way to connect uses Anvil at http://127.0.0.1:8545 with the default test key (account 0):

import sh.brane.rpc.Brane;
 
// Connect with all defaults
Brane.Tester tester = Brane.connectTest();

This is equivalent to:

Brane.Tester tester = Brane.builder()
    .rpcUrl("http://127.0.0.1:8545")
    .signer(AnvilSigners.defaultKey())
    .testMode(TestNodeMode.ANVIL)
    .buildTester();

With Custom Signer

Connect to the default Anvil URL with a specific test account:

import sh.brane.rpc.AnvilSigners;
 
// Use account at index 3
Signer signer = AnvilSigners.keyAt(3);
Brane.Tester tester = Brane.connectTest(signer);

With Custom URL

Connect to a remote or custom-port Anvil instance:

// Remote Anvil instance
Brane.Tester tester = Brane.connectTest("http://192.168.1.100:8545");
 
// Custom local port
Brane.Tester tester = Brane.connectTest("http://127.0.0.1:9545");

With Custom URL and Signer

import sh.brane.core.crypto.PrivateKeySigner;
 
Signer signer = new PrivateKeySigner("0x...");
Brane.Tester tester = Brane.connectTest("http://localhost:8545", signer);

With Different Test Node

Connect to Hardhat or Ganache instead of Anvil:

import sh.brane.rpc.TestNodeMode;
import sh.brane.core.crypto.PrivateKeySigner;
 
Signer signer = new PrivateKeySigner("0x...");
Brane.Tester tester = Brane.connectTest(
    "http://localhost:8545",
    signer,
    TestNodeMode.HARDHAT
);

Method Reference

MethodURLSignerMode
connectTest()DefaultDefault keyANVIL
connectTest(Signer)DefaultCustomANVIL
connectTest(String)CustomDefault keyANVIL
connectTest(String, Signer)CustomCustomANVIL
connectTest(String, Signer, TestNodeMode)CustomCustomCustom

Default URL: http://127.0.0.1:8545

TestNodeMode

TestNodeMode specifies which test node implementation you're connecting to. Each node uses different RPC method prefixes for its custom operations.

Available Modes

public enum TestNodeMode {
    ANVIL("anvil_"),    // Foundry's Anvil (recommended)
    HARDHAT("hardhat_"), // Hardhat Network
    GANACHE("evm_")      // Truffle's Ganache
}

RPC Method Prefixes

Each test node uses a different prefix for custom RPC methods:

OperationAnvilHardhatGanache
Mine blocksanvil_minehardhat_mineevm_mine
Set balanceanvil_setBalancehardhat_setBalanceevm_setBalance
Impersonateanvil_impersonateAccounthardhat_impersonateAccountevm_impersonateAccount

When to Specify Mode

You only need to specify TestNodeMode when connecting to non-Anvil nodes:

// Anvil - mode is optional (default)
Brane.Tester tester = Brane.connectTest();
 
// Hardhat - must specify mode
Brane.Tester tester = Brane.connectTest(
    "http://localhost:8545",
    signer,
    TestNodeMode.HARDHAT
);
 
// Ganache - must specify mode
Brane.Tester tester = Brane.connectTest(
    "http://localhost:7545",
    signer,
    TestNodeMode.GANACHE
);

Builder Pattern

For advanced configuration, use Brane.builder() with buildTester():

Brane.Tester tester = Brane.builder()
    .rpcUrl("http://localhost:8545")
    .signer(AnvilSigners.defaultKey())
    .testMode(TestNodeMode.ANVIL)
    .retries(5)
    .buildTester();

Builder Methods

MethodDescriptionDefault
rpcUrl(String)HTTP/HTTPS RPC endpointRequired
signer(Signer)Transaction signerRequired for buildTester()
testMode(TestNodeMode)Test node typeANVIL
chain(ChainProfile)Network-specific configNone
retries(int)Max retry attempts3
retryConfig(RpcRetryConfig)Backoff timingDefaults

Build Methods

The builder provides three terminal methods:

// Read-only client (no signer required)
Brane.Reader reader = Brane.builder()
    .rpcUrl("https://eth.example.com")
    .buildReader();
 
// Signing client (signer required)
Brane.Signer signer = Brane.builder()
    .rpcUrl("https://eth.example.com")
    .signer(key)
    .buildSigner();
 
// Test client (signer required)
Brane.Tester tester = Brane.builder()
    .rpcUrl("http://localhost:8545")
    .signer(key)
    .buildTester();

Advanced Configuration

import sh.brane.core.chain.ChainProfiles;
import sh.brane.rpc.RpcRetryConfig;
 
Brane.Tester tester = Brane.builder()
    .rpcUrl("http://localhost:8545")
    .signer(AnvilSigners.keyAt(0))
    .testMode(TestNodeMode.ANVIL)
    .chain(ChainProfiles.MAINNET)
    .retries(5)
    .retryConfig(RpcRetryConfig.builder()
        .baseDelay(100)
        .maxDelay(5000)
        .build())
    .buildTester();

AnvilSigners

AnvilSigners provides access to Anvil's 10 pre-funded test accounts. Each account is funded with 10,000 ETH when Anvil starts.

Getting Test Keys

import sh.brane.rpc.AnvilSigners;
 
// Default key (account 0) - most commonly used
Signer signer = AnvilSigners.defaultKey();
 
// Specific account by index (0-9)
Signer account3 = AnvilSigners.keyAt(3);
 
// Number of available accounts
int count = AnvilSigners.count(); // 10

Default Addresses

The 10 pre-funded accounts and their addresses:

IndexAddress
00xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
10x70997970C51812dc3A010C7d01b50e0d17dc79C8
20x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
30x90F79bf6EB2c4f870365E785982E1f101E93b906
40x15d34AAf54267DB7D7c367839AAf71A00a2C6A65
50x9965507D1a55bcC2695C58ba16FB37d819B0A4dc
60x976EA74026E726554dB657fA54763abd0C3a0aa9
70x14dC79964da2C08b23698B3D3cc7Ca32193d9955
80x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f
90xa0Ee7A142d267C1f36714E4a8F75612F20a79720

Key Derivation

These keys are derived from the well-known test mnemonic:

test test test test test test test test test test test junk

Using derivation path m/44'/60'/0'/0/i where i is the account index.

Using Multiple Accounts

// Iterate over all accounts
for (int i = 0; i < AnvilSigners.count(); i++) {
    Signer signer = AnvilSigners.keyAt(i);
    System.out.println("Account " + i + ": " + signer.address());
}
 
// Use different accounts for different roles
Signer deployer = AnvilSigners.keyAt(0);
Signer alice = AnvilSigners.keyAt(1);
Signer bob = AnvilSigners.keyAt(2);

Complete Example

import sh.brane.rpc.Brane;
import sh.brane.rpc.AnvilSigners;
import sh.brane.rpc.SnapshotId;
import sh.brane.core.types.Address;
import sh.brane.core.types.Wei;
 
public class TestSetupExample {
    public static void main(String[] args) {
        // 1. Create tester with builder for full control
        Brane.Tester tester = Brane.builder()
            .rpcUrl("http://127.0.0.1:8545")
            .signer(AnvilSigners.keyAt(0))
            .retries(3)
            .buildTester();
 
        // 2. Take snapshot for test isolation
        SnapshotId snapshot = tester.snapshot();
        try {
            // 3. Get additional test accounts
            Signer alice = AnvilSigners.keyAt(1);
            Signer bob = AnvilSigners.keyAt(2);
 
            // 4. Fund a test address
            Address testAddr = new Address("0x1234567890123456789012345678901234567890");
            tester.setBalance(testAddr, Wei.fromEther(new java.math.BigDecimal("100")));
 
            // 5. Run test operations
            // ...
 
        } finally {
            // 6. Restore state for next test
            tester.revert(snapshot);
        }
    }
}

Prerequisites

Before using Brane.Tester, start your test node:

Anvil (Recommended)

# Install Foundry
curl -L https://foundry.paradigm.xyz | bash
foundryup
 
# Start Anvil
anvil

Hardhat

npx hardhat node

Ganache

npx ganache --port 7545