Go wrapper for ethpandaops/ethereum-package to create Ethereum devnets.
go get github.com/ethpandaops/ethereum-package-gopackage main
import (
"context"
"fmt"
"github.com/ethpandaops/ethereum-package-go"
"github.com/ethpandaops/ethereum-package-go/pkg/types"
)
func main() {
ctx := context.Background()
// Start a minimal network (auto-cleanup on process exit)
network, err := ethereum.Run(ctx, ethereum.Minimal())
if err != nil {
panic(err)
}
// Network auto-cleans up when process exits (testcontainers-style)
// Optional: defer network.Cleanup(ctx) for explicit cleanup
// Access clients
clients := network.ExecutionClients().ByType(types.ClientGeth)
if len(clients) > 0 {
fmt.Printf("Geth RPC: %s\n", clients[0].RPCURL())
}
}ethereum.Minimal() // Geth + Lighthouse (1 node)
ethereum.AllELs() // All execution clients + Lighthouse
ethereum.AllCLs() // Geth + all consensus clients
ethereum.AllClientsMatrix() // All combinations (30 nodes)ethereum.WithChainID(12345)
ethereum.WithCustomChain(12345, 6, 16) // chainID, secondsPerSlot, slotsPerEpoch
ethereum.WithExplorer() // Doraimport (
"github.com/ethpandaops/ethereum-package-go"
"github.com/ethpandaops/ethereum-package-go/pkg/config"
"github.com/ethpandaops/ethereum-package-go/pkg/client"
)
config := &config.EthereumPackageConfig{
Participants: []config.ParticipantConfig{{
ELType: client.Geth,
CLType: client.Lighthouse,
Count: 3,
}},
}
network, err := ethereum.Run(ctx, ethereum.WithConfig(config))Enable checkpoint sync for faster node startup:
config := &config.EthereumPackageConfig{
Participants: []config.ParticipantConfig{{
ELType: client.Geth,
CLType: client.Lighthouse,
Count: 1,
}},
// Enable checkpoint sync for faster startup (root level)
CheckpointSyncEnabled: true,
CheckpointSyncURL: "https://beaconstate.info",
}Enable supernode mode for PeerDAS subnet coverage:
config := &config.EthereumPackageConfig{
Participants: []config.ParticipantConfig{{
ELType: client.Geth,
CLType: client.Lighthouse,
Count: 1,
// Enable supernode - subscribes to all subnet topics
Supernode: true,
}},
}// By type
gethClients := network.ExecutionClients().ByType(types.ClientGeth)
lighthouseClients := network.ConsensusClients().ByType(types.ClientLighthouse)
// All clients
for _, client := range network.ExecutionClients().All() {
fmt.Printf("%s: %s\n", client.Name(), client.RPCURL())
}apache := network.ApacheConfig()
genesisURL := apache.GenesisSSZURL()
configURL := apache.ConfigYAMLURL()Networks automatically clean up when the process exits (testcontainers-style):
// Default behavior - auto cleanup on exit
network, err := ethereum.Run(ctx, ethereum.Minimal())
// Network will be destroyed when process exitsPrevent auto-cleanup to create persistent networks:
// Network persists after process exit
network, err := ethereum.Run(ctx,
ethereum.Minimal(),
ethereum.WithOrphanOnExit(),
)
// Manual cleanup: kurtosis enclave rm <enclave-name>Connect to existing networks or create reusable ones:
// Reuse existing network or create with specific name
network, err := ethereum.Run(ctx,
ethereum.Minimal(),
ethereum.WithReuse("my-persistent-network"),
)
// Or use FindOrCreateNetwork to find existing by name or create new
network, err := ethereum.FindOrCreateNetwork(ctx, "my-persistent-network", ethereum.Minimal())The FindOrCreateNetwork function looks for an existing network with the given name and reuses it if found. If no network exists with that name, it creates a new one with the specified configuration.
For manual control over cleanup timing:
network, err := ethereum.Run(ctx, ethereum.Minimal())
defer network.Cleanup(ctx) // Explicit cleanup- Go 1.21+
- Kurtosis running locally
- Docker