OnchainTestKit uses a fluent builder pattern for configuration, making it easy to set up different wallet and network combinations for your tests.
Configuration Builder
The configure() function provides a chainable API for building test configurations:
import { configure } from '@coinbase/onchaintestkit' ;
const config = configure ()
. withLocalNode ({ chainId: 1337 })
. withMetaMask ()
. withNetwork ({
name: 'Base Sepolia' ,
rpcUrl: 'http://localhost:8545' ,
chainId: 84532 ,
symbol: 'ETH' ,
})
. withSeedPhrase ({
seedPhrase: process . env . E2E_TEST_SEED_PHRASE ! ,
password: 'PASSWORD' ,
})
. build ();
Wallet Configuration
Basic Setup
With Local Node
Complete Example
import { configure } from '@coinbase/onchaintestkit' ;
const metamaskConfig = configure ()
. withMetaMask ()
. withSeedPhrase ({
seedPhrase: process . env . E2E_TEST_SEED_PHRASE ! ,
password: 'PASSWORD' ,
})
. build ();
import { baseSepolia } from 'viem/chains' ;
const metamaskConfig = configure ()
. withLocalNode ({
chainId: baseSepolia . id ,
forkUrl: process . env . E2E_TEST_FORK_URL ,
forkBlockNumber: BigInt ( process . env . E2E_TEST_FORK_BLOCK_NUMBER ?? "0" ),
hardfork: 'cancun' ,
})
. withMetaMask ()
. withSeedPhrase ({
seedPhrase: process . env . E2E_TEST_SEED_PHRASE ! ,
password: 'PASSWORD' ,
})
. withNetwork ({
name: 'Base Sepolia' ,
chainId: baseSepolia . id ,
symbol: 'ETH' ,
rpcUrl: 'http://localhost:8545' ,
})
. build ();
// e2e/config/metamask.config.ts
import { baseSepolia } from "viem/chains"
import { configure } from "@coinbase/onchaintestkit"
export const DEFAULT_PASSWORD = "PASSWORD"
export const DEFAULT_SEED_PHRASE = process . env . E2E_TEST_SEED_PHRASE
const config = configure ()
. withLocalNode ({
chainId: baseSepolia . id ,
forkUrl: process . env . E2E_TEST_FORK_URL ,
forkBlockNumber: BigInt ( process . env . E2E_TEST_FORK_BLOCK_NUMBER ?? "0" ),
hardfork: "cancun" ,
})
. withMetaMask ()
. withSeedPhrase ({
seedPhrase: DEFAULT_SEED_PHRASE ?? "" ,
password: DEFAULT_PASSWORD ,
})
. withNetwork ({
name: "Base Sepolia" ,
chainId: baseSepolia . id ,
symbol: "ETH" ,
rpcUrl: "http://localhost:8545" ,
})
. build ()
export const metamaskWalletConfig = config
Coinbase Wallet Configuration
Basic Setup
Complete Example
import { configure } from '@coinbase/onchaintestkit' ;
const coinbaseConfig = configure ()
. withCoinbase ()
. withSeedPhrase ({
seedPhrase: process . env . E2E_TEST_SEED_PHRASE ! ,
password: 'COMPLEXPASSWORD1' ,
})
. build ();
// e2e/config/coinbase.config.ts
import { baseSepolia } from "viem/chains"
import { configure } from "@coinbase/onchaintestkit"
export const DEFAULT_PASSWORD = "COMPLEXPASSWORD1"
export const DEFAULT_SEED_PHRASE = process . env . E2E_TEST_SEED_PHRASE
const config = configure ()
. withLocalNode ({
chainId: baseSepolia . id ,
forkUrl: process . env . E2E_TEST_FORK_URL ,
forkBlockNumber: BigInt ( process . env . E2E_TEST_FORK_BLOCK_NUMBER ?? "0" ),
hardfork: "cancun" ,
})
. withCoinbase ()
. withSeedPhrase ({
seedPhrase: DEFAULT_SEED_PHRASE ?? "" ,
password: DEFAULT_PASSWORD ,
})
. withNetwork ({
name: "Base Sepolia" ,
chainId: baseSepolia . id ,
symbol: "ETH" ,
rpcUrl: "http://localhost:8545" ,
})
. build ()
export const coinbaseWalletConfig = config
Network Configuration
Local Node Options
Configure a local Anvil node with specific parameters:
. withLocalNode ({
// Required: Chain ID for the local network
chainId: 1337 ,
// Optional: Fork from an existing network
forkUrl: "https://mainnet.base.org" ,
// Optional: Fork from a specific block
forkBlockNumber: BigInt ( "12345678" ),
// Optional: EVM hardfork to use
hardfork: "cancun" ,
// Optional: Port range for parallel testing
minPort: 9545 ,
maxPort: 9645 ,
})
Network Details
Add custom networks to your wallet:
. withNetwork ({
name: "My Custom Network" ,
chainId: 12345 ,
symbol: "ETH" ,
rpcUrl: "https://my-rpc-endpoint.com" , // This is ususally localhost:8545 since the onchaintestkit network interceptor listens to this port and forwards RPC requests sent to this port to the anvil node
isTestnet: true , // Optional: mark as testnet
})
Environment Variables
Use environment variables to keep sensitive data out of your code and enable different configurations for different environments.
Required Variables
# Test wallet seed phrase
E2E_TEST_SEED_PHRASE = "test test test test test test test test test test test junk"
Other Env Variables
# Fork configuration
E2E_TEST_FORK_URL = "https://mainnet.base.org"
E2E_TEST_FORK_BLOCK_NUMBER = "12345678"
# Smart contract project
E2E_CONTRACT_PROJECT_ROOT = "../smart-contracts"
# Custom RPC endpoints
E2E_BASE_MAINNET_RPC = "https://my-custom-rpc.com"
E2E_BASE_SEPOLIA_RPC = "https://my-testnet-rpc.com"
# Test timeouts
E2E_TEST_TIMEOUT = "60000"
Using Configurations in Tests
import { createOnchainTest } from '@coinbase/onchaintestkit' ;
import { metamaskWalletConfig } from './config/metamask.config' ;
const test = createOnchainTest ( metamaskWalletConfig );
test ( 'my test' , async ({ page , metamask , node }) => {
// Your test code here
console . log ( `Local node running on port: ${ node ?. port } ` );
});
Configuration Best Practices
Separate config files
Create separate configuration files for each wallet type to keep your code organized: e2e/config/
├── metamask.config.ts
├── coinbase.config.ts
└── shared.config.ts
Use environment variables
Never hardcode sensitive data. Always use environment variables for:
Seed phrases
API keys
RPC endpoints
Private keys
Type your configurations
Export typed configurations for better IDE support: import type { OnchainTestConfig } from '@coinbase/onchaintestkit' ;
export const metamaskConfig : OnchainTestConfig = configure ()
. withMetaMask ()
// ... rest of config
. build ();
Validate environment
Add validation for required environment variables: if ( ! process . env . E2E_TEST_SEED_PHRASE ) {
throw new Error ( 'E2E_TEST_SEED_PHRASE is required' );
}
Next Steps