npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

besu-network-manager

v1.0.1

Published

TypeScript library for managing Hyperledger Besu networks with Clique consensus using Docker

Readme

Besu Network SDK

A clean, focused TypeScript library providing essential building blocks for managing Hyperledger Besu networks with Docker containers. This SDK provides individual components that can be composed together in applications like Next.js to create complete network management solutions.

Features

  • Modular Architecture: Individual components for Docker, Genesis, and Key management
  • Docker Integration: Native dockerode integration for container management
  • Clique Consensus: Built-in support for Clique PoA consensus mechanism
  • TypeScript First: Fully typed with comprehensive TypeScript definitions
  • Key Generation: Ethereum key generation with enode URL creation
  • Genesis Generation: Clique genesis block generation with validator configuration
  • Network Management: Docker network and container lifecycle management

Installation

yarn add besu-network-manager
# or
npm install besu-network-manager

Prerequisites

  • Docker daemon running
  • Node.js 16+
  • TypeScript 4.5+ (for development)

Components Overview

The SDK provides three main components:

  • DockerManager - Handles Docker networks and container operations
  • GenesisGenerator - Creates Clique consensus genesis blocks
  • KeyGenerator - Generates Ethereum keypairs and enode URLs

Usage Examples

1. DockerManager - Container & Network Operations

import { DockerManager, NetworkConfig, BesuNodeConfig } from 'besu-network-manager';

const dockerManager = new DockerManager();

// Check Docker availability
const isAvailable = await dockerManager.isDockerAvailable();
if (!isAvailable) {
  throw new Error('Docker is not available');
}

// Create a Docker network
const networkConfig: NetworkConfig = {
  networkId: 'my-besu-network',
  chainId: 1337,
  subnet: '172.20.0.0/24',
  gateway: '172.20.0.1',
  nodes: [] // Will be populated with node configs
};

const dockerNetworkId = await dockerManager.createDockerNetwork(networkConfig);
console.log('Docker network created:', dockerNetworkId);

// Check if network exists
const exists = await dockerManager.networkExists('my-besu-network');
console.log('Network exists:', exists);

// Find containers in network
const containers = await dockerManager.findNetworkContainers('my-besu-network');
console.log('Containers in network:', containers.length);

2. KeyGenerator - Ethereum Key Management

import { KeyGenerator } from 'besu-network-manager';

const keyGenerator = new KeyGenerator();

// Generate a new keypair with enode
const credentials = keyGenerator.generateKeyPair('172.20.0.10', 30303);
console.log('Generated credentials:', {
  address: credentials.address,
  enode: credentials.enode,
  // privateKey and publicKey are also available
});

// Generate from existing private key
const existingKey = '0x1234567890abcdef...';
const restoredCredentials = keyGenerator.fromPrivateKey(
  existingKey, 
  '172.20.0.11', 
  30303
);

// Generate multiple keypairs (useful for initial network setup)
const multipleKeys = KeyGenerator.generateMultiple(3, '172.20.0.0/24', 30303);
multipleKeys.forEach((cred, index) => {
  console.log(`Node ${index + 1}:`, cred.address);
});

3. GenesisGenerator - Clique Genesis Blocks

import { GenesisGenerator } from 'besu-network-manager';

// Generate genesis with validators
const validatorAddresses = [
  '0x1234567890123456789012345678901234567890',
  '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
];

const genesis = GenesisGenerator.generateGenesis({
  chainId: 1337,
  validators: validatorAddresses,
  gasLimit: '0x1fffffffffffff'
});

console.log('Generated genesis:', JSON.stringify(genesis, null, 2));

// Validate existing genesis
const isValid = GenesisGenerator.isValidGenesis(genesis);
console.log('Genesis is valid:', isValid);

4. Complete Network Creation Example (Next.js API Route)

// pages/api/networks/create.ts
import { NextRequest, NextResponse } from 'next/server';
import { 
  DockerManager, 
  GenesisGenerator, 
  KeyGenerator,
  NetworkConfig,
  BesuNodeConfig 
} from 'besu-network-manager';
import * as fs from 'fs';
import * as path from 'path';

export async function POST(request: NextRequest) {
  const dockerManager = new DockerManager();
  const keyGenerator = new KeyGenerator();
  
  try {
    const { networkId, chainId, nodeCount } = await request.json();
    
    // 1. Check Docker availability
    if (!await dockerManager.isDockerAvailable()) {
      return NextResponse.json(
        { error: 'Docker is not available' }, 
        { status: 500 }
      );
    }
    
    // 2. Generate network configuration
    const networkConfig: NetworkConfig = {
      networkId,
      chainId,
      subnet: '172.20.0.0/24',
      gateway: '172.20.0.1',
      nodes: []
    };
    
    // 3. Generate keys for nodes
    const nodeCredentials = [];
    const validators = [];
    
    for (let i = 0; i < nodeCount; i++) {
      const ip = `172.20.0.${10 + i}`;
      const credentials = keyGenerator.generateKeyPair(ip, 30303 + i);
      
      const nodeConfig: BesuNodeConfig = {
        id: `node-${i}`,
        type: i === 0 ? 'bootnode' : 'miner',
        ip,
        rpcPort: 8545 + i,
        p2pPort: 30303 + i,
        address: credentials.address,
        enode: credentials.enode
      };
      
      networkConfig.nodes.push(nodeConfig);
      nodeCredentials.push(credentials);
      
      if (nodeConfig.type === 'miner') {
        validators.push(credentials.address);
      }
    }
    
    // 4. Generate genesis file
    const genesis = GenesisGenerator.generateGenesis({
      chainId,
      validators
    });
    
    // 5. Create Docker network
    const dockerNetworkId = await dockerManager.createDockerNetwork(networkConfig);
    
    // 6. Create node directories and save keys
    const networkPath = `/tmp/besu-networks/${networkId}`;
    await fs.promises.mkdir(networkPath, { recursive: true });
    
    for (let i = 0; i < networkConfig.nodes.length; i++) {
      const node = networkConfig.nodes[i];
      const credentials = nodeCredentials[i];
      
      // Create node directory
      const nodePath = path.join(networkPath, node.id);
      await fs.promises.mkdir(nodePath, { recursive: true });
      
      // Save node files
      await fs.promises.writeFile(
        path.join(nodePath, 'key'), 
        credentials.privateKey.slice(2)
      );
      await fs.promises.writeFile(
        path.join(nodePath, 'address'), 
        credentials.address
      );
      await fs.promises.writeFile(
        path.join(nodePath, 'enode'), 
        credentials.enode
      );
    }
    
    // Save genesis file
    await fs.promises.writeFile(
      path.join(networkPath, 'genesis.json'),
      JSON.stringify(genesis, null, 2)
    );
    
    // 7. Create and start containers
    const containers = [];
    for (const node of networkConfig.nodes) {
      const nodePath = path.join(networkPath, node.id);
      const container = await dockerManager.createBesuContainer(
        networkConfig,
        node,
        nodePath
      );
      containers.push(container);
    }
    
    return NextResponse.json({
      success: true,
      network: {
        networkId,
        dockerNetworkId,
        chainId,
        containers: containers.length,
        nodes: networkConfig.nodes.map(n => ({
          id: n.id,
          type: n.type,
          rpcPort: n.rpcPort,
          address: n.address
        }))
      }
    });
    
  } catch (error) {
    console.error('Network creation failed:', error);
    return NextResponse.json(
      { error: 'Failed to create network' },
      { status: 500 }
    );
  }
}

5. Adding a Node to Existing Network

// pages/api/networks/[id]/nodes/add.ts
import { NextRequest, NextResponse } from 'next/server';
import { DockerManager, KeyGenerator } from 'besu-network-manager';
import * as fs from 'fs';
import * as path from 'path';

export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const dockerManager = new DockerManager();
  const keyGenerator = new KeyGenerator();
  
  try {
    const { id: networkId } = await params;
    const { nodeType, ip, rpcPort, p2pPort } = await request.json();
    
    // 1. Check if network exists
    if (!await dockerManager.networkExists(networkId)) {
      return NextResponse.json(
        { error: 'Network not found' }, 
        { status: 404 }
      );
    }
    
    // 2. Generate node configuration
    const nodeId = `node-${Date.now()}`;
    const credentials = keyGenerator.generateKeyPair(ip, p2pPort);
    
    const nodeConfig = {
      id: nodeId,
      type: nodeType,
      ip,
      rpcPort,
      p2pPort,
      address: credentials.address,
      enode: credentials.enode
    };
    
    // 3. Create node directory and save keys
    const networkPath = `/tmp/besu-networks/${networkId}`;
    const nodePath = path.join(networkPath, nodeId);
    await fs.promises.mkdir(nodePath, { recursive: true });
    
    await fs.promises.writeFile(
      path.join(nodePath, 'key'), 
      credentials.privateKey.slice(2)
    );
    await fs.promises.writeFile(
      path.join(nodePath, 'address'), 
      credentials.address
    );
    await fs.promises.writeFile(
      path.join(nodePath, 'enode'), 
      credentials.enode
    );
    
    // 4. Add node to network
    const networkConfig = {
      networkId,
      chainId: 1337, // Load from stored config
      subnet: '172.20.0.0/24',
      gateway: '172.20.0.1',
      nodes: [nodeConfig]
    };
    
    const container = await dockerManager.addNodeToNetwork(
      networkConfig,
      nodeConfig,
      nodePath
    );
    
    return NextResponse.json({
      success: true,
      node: {
        id: nodeId,
        containerId: container.containerId,
        type: nodeType,
        address: credentials.address,
        rpcPort,
        p2pPort
      }
    });
    
  } catch (error) {
    console.error('Failed to add node:', error);
    return NextResponse.json(
      { error: 'Failed to add node' },
      { status: 500 }
    );
  }
}

6. Network Cleanup

// pages/api/networks/[id]/delete.ts
import { NextRequest, NextResponse } from 'next/server';
import { DockerManager } from 'besu-network-manager';
import * as fs from 'fs';

export async function DELETE(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const dockerManager = new DockerManager();
  
  try {
    const { id: networkId } = await params;
    
    // 1. Remove all containers in the network
    const containers = await dockerManager.findNetworkContainers(networkId);
    for (const container of containers) {
      await dockerManager.removeContainer(container.Id);
    }
    
    // 2. Remove Docker network
    await dockerManager.removeDockerNetwork(networkId);
    
    // 3. Clean up files
    const networkPath = `/tmp/besu-networks/${networkId}`;
    if (fs.existsSync(networkPath)) {
      await fs.promises.rm(networkPath, { recursive: true });
    }
    
    return NextResponse.json({ success: true });
    
  } catch (error) {
    console.error('Failed to delete network:', error);
    return NextResponse.json(
      { error: 'Failed to delete network' },
      { status: 500 }
    );
  }
}

Type Definitions

// Core network configuration
interface NetworkConfig {
  networkId: string;
  chainId: number;
  subnet: string;
  gateway: string;
  nodes: BesuNodeConfig[];
  genesis?: any;
}

// Node configuration
interface BesuNodeConfig {
  id: string;
  type: 'bootnode' | 'miner' | 'rpc';
  rpcPort: number;
  p2pPort: number;
  ip: string;
  enode?: string;
  address?: string;
  bootnodes?: string[];
}

// Container information
interface ContainerInfo {
  id: string;
  containerId: string;
  containerName: string;
  status: 'running' | 'stopped' | 'error';
}

// Node credentials
interface NodeCredentials {
  privateKey: string;
  publicKey: string;
  address: string;
  enode: string;
}

Architecture Principles

This SDK follows a modular, building-block approach:

  1. Single Responsibility: Each component has one clear purpose
  2. Composable: Components can be combined in applications as needed
  3. Framework Agnostic: Works with Next.js, Express, or any Node.js application
  4. Docker Native: Direct integration with Docker APIs, no shell scripts
  5. Type Safe: Full TypeScript support with comprehensive type definitions

Development

# Install dependencies
yarn install

# Build the project
yarn build

# Check types
npx tsc --noEmit

Requirements

  • Docker daemon running and accessible
  • Node.js 16+
  • Proper Docker permissions for container management

License

MIT