Documentation Index
Fetch the complete documentation index at: https://voltaire.tevm.sh/llms.txt
Use this file to discover all available pages before exploring further.
Try it Live
Run Chain examples in the interactive playground
Usage Patterns
Practical patterns for chain ID validation, network detection, and multi-chain applications.Chain Identification
Network Detection
import * as Chain from 'tevm/Chain';
// Detect network from chain ID
function getNetworkName(chainId: BrandedChain): string {
const metadata = Chain.getMetadata(chainId);
return metadata?.name ?? `Unknown (${chainId})`;
}
// Check if mainnet
function isMainnet(chainId: BrandedChain): boolean {
return Chain.equals(chainId, Chain(1));
}
// Check if testnet
function isTestnet(chainId: BrandedChain): boolean {
const testnets = [5, 11155111, 17000]; // Goerli, Sepolia, Holesky
return testnets.some(id => Chain.equals(chainId, Chain(id)));
}
Multi-chain Support
// Supported chains configuration
const SUPPORTED_CHAINS = [
1, // Ethereum Mainnet
10, // Optimism
137, // Polygon
8453, // Base
42161, // Arbitrum One
] as const;
function isSupportedChain(chainId: BrandedChain): boolean {
return SUPPORTED_CHAINS.some(id =>
Chain.equals(chainId, Chain(id))
);
}
function requireSupportedChain(chainId: BrandedChain): void {
if (!isSupportedChain(chainId)) {
const supported = SUPPORTED_CHAINS.join(', ');
throw new Error(
`Unsupported chain ${chainId}. Supported: ${supported}`
);
}
}
Provider Configuration
Dynamic Provider Setup
interface ProviderConfig {
rpcUrl: string;
chainId: BrandedChain;
name: string;
}
// Configure provider based on chain
function getProviderConfig(chainId: BrandedChain): ProviderConfig {
const configs: Record<number, ProviderConfig> = {
1: {
rpcUrl: "https://eth.llamarpc.com",
chainId: Chain(1),
name: "Ethereum Mainnet"
},
137: {
rpcUrl: "https://polygon.llamarpc.com",
chainId: Chain(137),
name: "Polygon"
},
// ... more chains
};
const config = configs[Number(chainId)];
if (!config) {
throw new Error(`No provider config for chain ${chainId}`);
}
return config;
}
// Create provider
async function createProvider(chainId: BrandedChain): Promise<Provider> {
const config = getProviderConfig(chainId);
const provider = new Provider(config.rpcUrl);
// Verify chain ID
const actualChainId = await provider.getChainId();
if (!Chain.equals(Chain(actualChainId), chainId)) {
throw new Error(
`Chain ID mismatch. Expected: ${chainId}, Got: ${actualChainId}`
);
}
return provider;
}
Chain-specific Configuration
// Get block explorer URL
function getExplorerUrl(chainId: BrandedChain): string {
const explorers: Record<number, string> = {
1: "https://etherscan.io",
10: "https://optimistic.etherscan.io",
137: "https://polygonscan.com",
8453: "https://basescan.org",
42161: "https://arbiscan.io"
};
return explorers[Number(chainId)] ?? "";
}
// Get native token symbol
function getNativeToken(chainId: BrandedChain): string {
const tokens: Record<number, string> = {
1: "ETH",
137: "MATIC",
56: "BNB",
43114: "AVAX"
};
return tokens[Number(chainId)] ?? "ETH";
}
Transaction Routing
Chain-aware Transaction Builder
// Build transaction for specific chain
function buildTransaction(
chainId: BrandedChain,
params: {
to: string;
value: bigint;
data: Uint8Array;
}
): Transaction {
const metadata = Chain.getMetadata(chainId);
// Chain-specific gas settings
const gasSettings = getGasSettings(chainId);
return Transaction({
chainId,
to: params.to,
value: params.value,
data: params.data,
...gasSettings
});
}
// Get chain-specific gas settings
function getGasSettings(chainId: BrandedChain): {
maxFeePerGas?: bigint;
maxPriorityFeePerGas?: bigint;
gasPrice?: bigint;
} {
// Use EIP-1559 for chains that support it
const eip1559Chains = [1, 10, 137, 8453, 42161];
if (eip1559Chains.some(id => Chain.equals(chainId, Chain(id)))) {
return {
maxFeePerGas: 50_000_000_000n,
maxPriorityFeePerGas: 2_000_000_000n
};
}
// Legacy gas price for others
return {
gasPrice: 20_000_000_000n
};
}
Cross-chain Message Routing
interface CrossChainMessage {
sourceChain: BrandedChain;
targetChain: BrandedChain;
data: Uint8Array;
}
// Route message between chains
async function routeCrossChainMessage(
msg: CrossChainMessage
): Promise<void> {
// Validate chains
requireSupportedChain(msg.sourceChain);
requireSupportedChain(msg.targetChain);
// Get bridge contract for chain pair
const bridge = getBridgeContract(msg.sourceChain, msg.targetChain);
// Submit message
await bridge.sendMessage(msg.data);
}
Validation
Input Validation
// Validate chain ID from user input
function validateChainId(input: string | number): BrandedChain {
let chainId: number;
if (typeof input === 'string') {
chainId = parseInt(input, 10);
if (isNaN(chainId)) {
throw new Error(`Invalid chain ID: ${input}`);
}
} else {
chainId = input;
}
if (chainId < 1 || chainId > 4294967295) { // uint32 max
throw new Error(`Chain ID out of range: ${chainId}`);
}
return Chain(chainId);
}
// Safe chain ID parsing
function safeParseChainId(input: unknown): BrandedChain | null {
try {
if (typeof input === 'number') {
return Chain(input);
}
if (typeof input === 'string') {
return validateChainId(input);
}
return null;
} catch {
return null;
}
}
Transaction Validation
// Verify transaction chain ID
function verifyTransactionChain(
tx: Transaction,
expectedChainId: BrandedChain
): void {
if (!Chain.equals(tx.chainId, expectedChainId)) {
throw new Error(
`Transaction chain ID mismatch. ` +
`Expected: ${expectedChainId}, Got: ${tx.chainId}`
);
}
}
// Validate replay protection
function hasReplayProtection(tx: Transaction): boolean {
// EIP-155 replay protection requires chain ID
return tx.chainId !== 0n;
}
Metadata Access
Chain Information Display
// Display chain information
function displayChainInfo(chainId: BrandedChain): void {
const metadata = Chain.getMetadata(chainId);
if (metadata) {
console.log(`Chain: ${metadata.name}`);
console.log(`ID: ${chainId}`);
console.log(`Native Token: ${metadata.nativeCurrency.symbol}`);
console.log(`RPC: ${metadata.rpcUrls[0]}`);
console.log(`Explorer: ${metadata.blockExplorers?.[0]}`);
} else {
console.log(`Chain ID: ${chainId} (unknown network)`);
}
}
// Get chain selector for UI
function getChainSelector(): Array<{
value: number;
label: string;
icon: string;
}> {
return SUPPORTED_CHAINS.map(id => {
const chainId = Chain(id);
const metadata = Chain.getMetadata(chainId);
return {
value: id,
label: metadata?.name ?? `Chain ${id}`,
icon: metadata?.icon ?? ""
};
});
}
Testing
Mock Chain IDs
// Test chains
const TEST_CHAINS = {
mainnet: Chain(1),
sepolia: Chain(11155111),
hardhat: Chain(31337),
ganache: Chain(1337)
};
// Use in tests
function setupTestProvider(network: keyof typeof TEST_CHAINS): Provider {
const chainId = TEST_CHAINS[network];
return createTestProvider(chainId);
}
Chain Mocking
// Mock chain metadata for tests
function mockChainMetadata(chainId: number) {
return {
chainId: Chain(chainId),
name: `Test Chain ${chainId}`,
nativeCurrency: {
name: "Test Ether",
symbol: "TEST",
decimals: 18
},
rpcUrls: [`http://localhost:8545`],
blockExplorers: []
};
}
Related
- Constructors - Creating chain IDs
- Metadata - Chain information
- Network Comparison - Chain comparison
- Fundamentals - Chain ID basics

