Complete API reference for HuiNet - A decentralized Agent-to-Agent (A2A) networking library with P2P communication.
- Core Classes
- Configuration
- Methods
- Routing Management
- Network Utilities
- Events
- Type Definitions
- Utility Functions
The main P2P network node class that provides decentralized networking capabilities for Agents.
Extends: EventEmitter
import { HuiNet } from '@huinet/network';
const huinet = new HuiNet({
listenPort: 8000,
enableMDNS: true
});
await huinet.start();Alias for HuiNet class, providing clearer naming conventions for Agent integration.
Note: HuiNetNode is an alias of HuiNet and can be used interchangeably.
import { HuiNetNode } from '@huinet/network';
const node = new HuiNetNode({
listenPort: 8000
});Configuration interface for initializing a HuiNet node.
interface HuiNetConfig {
keyPair?: KeyPair; // Optional: Cryptographic key pair (auto-generated if not provided)
listenPort?: number; // Optional: Port to listen on (default: 8000)
listenHost?: string; // Optional: Host address to bind to (default: '0.0.0.0')
bootstrapNodes?: string[]; // Optional: Array of bootstrap node addresses (host:port format)
maxCoreConnections?: number; // Optional: Maximum number of core/persistent connections (default: 10)
maxActiveConnections?: number; // Optional: Maximum number of active cached connections (default: 50)
enableMDNS?: boolean; // Optional: Enable mDNS discovery (default: true)
promoteToActiveThreshold?: number; // Optional: Connections to promote to Active layer (default: 3)
promoteToCoreThreshold?: number; // Optional: Connections to promote to Core layer (default: 10)
routingCleanupInterval?: number; // Optional: Routing table cleanup interval in ms (default: 300000)
maxNodeAge?: number; // Optional: Maximum node age in ms before cleanup (default: 3600000)
}- keyPair (
KeyPair, optional): Cryptographic key pair for node identity. If not provided, a new key pair will be generated automatically. - listenPort (
number, optional): TCP port for incoming connections. Defaults to8000. - listenHost (
string, optional): Host address to bind the server to. Defaults to'0.0.0.0'(all interfaces). - bootstrapNodes (
string[], optional): Array of bootstrap node addresses in'host:port'format. The node will attempt to connect to these on startup. - maxCoreConnections (
number, optional): Maximum number of persistent core connections to maintain. Defaults to10. - maxActiveConnections (
number, optional): Maximum number of active cached connections. Defaults to50. - enableMDNS (
boolean, optional): Whether to enable mDNS-based peer discovery. Defaults totrue. - promoteToActiveThreshold (
number, optional): Number of connections after which a node is auto-promoted to Active layer. Defaults to3. - promoteToCoreThreshold (
number, optional): Number of connections after which a node is auto-promoted to Core layer. Defaults to10. - routingCleanupInterval (
number, optional): Interval in milliseconds for routing table cleanup. Defaults to300000(5 minutes). - maxNodeAge (
number, optional): Maximum age in milliseconds for a node before cleanup. Defaults to3600000(1 hour).
import { HuiNet, generateKeyPair } from '@huinet/network';
// Basic configuration
const config1: HuiNetConfig = {
listenPort: 9000,
enableMDNS: true
};
// Advanced configuration with custom key pair
const keyPair = generateKeyPair();
const config2: HuiNetConfig = {
keyPair: keyPair,
listenPort: 8000,
listenHost: '0.0.0.0',
bootstrapNodes: [
'192.168.1.100:8000',
'example.com:9000'
],
maxCoreConnections: 20,
maxActiveConnections: 100,
enableMDNS: true,
// Routing table configuration
promoteToActiveThreshold: 5,
promoteToCoreThreshold: 15,
routingCleanupInterval: 600000, // 10 minutes
maxNodeAge: 7200000 // 2 hours
};
const huinet = new HuiNet(config2);Start the HuiNet node, initializing the TCP server, mDNS discovery (if enabled), and connecting to bootstrap nodes.
async start(): Promise<void>- Starts the TCP server on the configured host and port
- Initializes mDNS discovery service if
enableMDNSistrue - Attempts to connect to all configured bootstrap nodes
- Sets the node state to running
- Emits the
readyevent when complete
const huinet = new HuiNet({ listenPort: 8000 });
huinet.on('ready', () => {
console.log('Node is ready and listening');
});
await huinet.start();Stop the HuiNet node, closing all connections and services.
async stop(): Promise<void>- Stops the TCP server
- Stops the mDNS discovery service
- Disconnects all client connections
- Clears the connection pool
- Sets the node state to stopped
// Graceful shutdown
process.on('SIGINT', async () => {
console.log('Shutting down...');
await huinet.stop();
process.exit(0);
});Send a message to a target node by NodeID.
async send(targetNodeID: string, message: any): Promise<void>- targetNodeID (
string): The NodeID of the recipient - message (
any): Message data (any JSON-serializable object)
Error- If the target node is unknown (not in routing table)Error- If connection to the target fails
- Looks up the target node in the routing table
- Establishes a connection if not already connected
- Sends the message as JSON
- Automatically handles reconnection if needed
// Send a simple message
await huinet.send(targetNodeID, {
type: 'chat',
text: 'Hello, World!'
});
// Send complex data
await huinet.send(targetNodeID, {
type: 'file-transfer',
filename: 'document.pdf',
size: 1024000,
data: base64EncodedData
});Manually connect to a node at a specific address.
async connectToNode(host: string, port: number, nodeID?: string): Promise<boolean>- host (
string): Target host address - port (
number): Target port number - nodeID (
string, optional): NodeID of the target (used for event tracking)
boolean - true if connection succeeded, false otherwise
- Creates a new TCP client connection
- Sets up event handlers for the connection
- Adds the node to the routing table on success
- Emits
peerConnectedevent on success - Returns
falseon connection failure
// Connect to a known node
const success = await huinet.connectToNode('192.168.1.100', 8000);
if (success) {
console.log('Connected successfully');
} else {
console.log('Connection failed');
}
// Connect with known NodeID
await huinet.connectToNode('example.com', 9000, 'QmXxx...');
// Handle connection events
huinet.on('peerConnected', (nodeID) => {
console.log(`Connected to ${nodeID}`);
});Get the current node's ID.
getNodeID(): stringstring - The NodeID (Base58-encoded SHA-256 hash of the public key)
const nodeID = huinet.getNodeID();
console.log(`My NodeID: ${nodeID}`);Get the current node's public key.
getPublicKey(): BufferBuffer - The node's public key (32 bytes)
const publicKey = huinet.getPublicKey();
console.log(`Public Key: ${publicKey.toString('hex')}`);Get the routing table containing known nodes.
getRoutingTable(): RoutingTableRoutingTable - The routing table object
const routingTable = huinet.getRoutingTable();
// Get all known nodes
const allNodes = routingTable.getAllKnownNodes();
// Get a specific node
const node = routingTable.getKnownNode(nodeID);
if (node) {
console.log(`Node state: ${node.state}`);
console.log(`Addresses: ${node.addresses.length}`);
}Get the connection pool managing active connections.
getConnectionPool(): ConnectionPoolConnectionPool - The connection pool object
const pool = huinet.getConnectionPool();
// Get connection statistics
const stats = pool.getStats();
console.log(`Core connections: ${stats.coreCount}`);
console.log(`Active connections: ${stats.activeCount}`);Check if the node is currently running.
isRunning(): booleanboolean - true if the node is running, false otherwise
if (huinet.isRunning()) {
console.log('Node is active');
} else {
console.log('Node is stopped');
}Disconnect from a connected node.
async disconnectFromNode(nodeID: string): Promise<boolean>- nodeID (
string): The NodeID of the node to disconnect from
boolean - true if disconnection succeeded, false otherwise
const success = await huinet.disconnectFromNode(targetNodeID);
if (success) {
console.log('Disconnected successfully');
} else {
console.log('Node not connected or disconnection failed');
}Get a list of all connected node IDs.
getConnectedNodes(): string[]string[] - Array of connected NodeIDs
const connected = huinet.getConnectedNodes();
console.log(`Connected nodes: ${connected.length}`);
for (const nodeID of connected) {
console.log(`- ${nodeID}`);
}Get statistics about the routing table.
getRoutingStats(): RoutingStatsRoutingStats - Object containing routing statistics:
totalNodes(number): Total number of nodescoreCount(number): Number of core connectionsactiveCount(number): Number of active connectionsknownCount(number): Number of known nodesconnectionCounts(Record<string, number>): Connection count per node
const stats = huinet.getRoutingStats();
console.log(`Total nodes: ${stats.totalNodes}`);
console.log(`Core: ${stats.coreCount}, Active: ${stats.activeCount}, Known: ${stats.knownCount}`);Manually promote a node to the Active layer.
promoteToActive(nodeID: string): boolean- nodeID (
string): The NodeID of the node to promote
boolean - true if promotion succeeded, false otherwise
const promoted = huinet.promoteToActive(nodeID);
if (promoted) {
console.log('Node promoted to Active layer');
} else {
console.log('Promotion failed - node not found');
}Manually promote a node to the Core layer.
promoteToCore(nodeID: string): boolean- nodeID (
string): The NodeID of the node to promote
boolean - true if promotion succeeded, false otherwise
const promoted = huinet.promoteToCore(nodeID);
if (promoted) {
console.log('Node promoted to Core layer - will maintain persistent connection');
}Demote a node from Active to Known layer.
demoteFromActive(nodeID: string): boolean- nodeID (
string): The NodeID of the node to demote
boolean - true if demotion succeeded, false otherwise
const demoted = huinet.demoteFromActive(nodeID);
if (demoted) {
console.log('Node demoted from Active to Known');
}Demote a node from Core to Active layer.
demoteFromCore(nodeID: string): boolean- nodeID (
string): The NodeID of the node to demote
boolean - true if demotion succeeded, false otherwise
const demoted = huinet.demoteFromCore(nodeID);
if (demoted) {
console.log('Node demoted from Core to Active');
}Get all local IP addresses with optional filtering.
getLocalIPs(options?: GetLocalIPOptions): string[]- options (
GetLocalIPOptions, optional):ipv4Only(boolean): Return only IPv4 addressesexcludeInternal(boolean): Exclude loopback addressesinterfaceName(string): Filter by interface name
string[] - Array of IP addresses
// Get all local IPs
const allIPs = huinet.getLocalIPs();
// Get only IPv4 addresses
const ipv4Only = huinet.getLocalIPs({ ipv4Only: true });
// Exclude loopback (127.0.0.1)
const externalIPs = huinet.getLocalIPs({ excludeInternal: true });Get the primary local IP address (non-loopback IPv4).
getPrimaryLocalIP(): stringstring - The primary local IP address
const primaryIP = huinet.getPrimaryLocalIP();
console.log(`Primary IP: ${primaryIP}`);Check if a node is on the same local network.
isSameNetwork(nodeID: string, subnetMask?: number): boolean- nodeID (
string): The NodeID of the target node - subnetMask (
number, optional): Subnet mask bits (default: 24)
boolean - true if on the same network, false otherwise
// Check if node is on same /24 subnet
const sameNetwork = huinet.isSameNetwork(targetNodeID, 24);
if (sameNetwork) {
console.log('Node is on the same local network');
} else {
console.log('Node is on a different network');
}
// Check with custom subnet mask
const sameSubnet = huinet.isSameNetwork(targetNodeID, 16); // /16 subnetHuiNet extends EventEmitter and emits the following events:
Emitted when the node has started and is ready to accept connections.
huinet.on('ready', () => {
console.log('Node is ready');
});Callback Signature: () => void
Emitted when a message is received from a peer node.
huinet.on('message', (from: NodeID, data: any) => {
console.log(`Received from ${from}:`, data);
});Callback Signature: (from: NodeID, data: any) => void
Parameters:
- from (
NodeID): The NodeID of the sender - data (
any): The message data (parsed JSON object)
huinet.on('message', (from, data) => {
if (data.type === 'chat') {
console.log(`${from}: ${data.text}`);
} else if (data.type === 'file-transfer') {
handleFileTransfer(from, data);
}
});Emitted when a connection to a peer node is established.
huinet.on('peerConnected', (nodeID: NodeID, type?: ConnectionType) => {
console.log(`Connected to ${nodeID}`);
});Callback Signature: (nodeID: NodeID, type?: ConnectionType) => void
Parameters:
- nodeID (
NodeID): The NodeID of the connected peer - type (
ConnectionType, optional): The connection type (CORE, ACTIVE, or ON_DEMAND)
huinet.on('peerConnected', (nodeID, type) => {
console.log(`New connection: ${nodeID} (${type || 'unknown'})`);
});Emitted when a peer node disconnects.
huinet.on('peerDisconnected', (nodeID: NodeID) => {
console.log(`Disconnected from ${nodeID}`);
});Callback Signature: (nodeID: NodeID) => void
Parameters:
- nodeID (
NodeID): The NodeID of the disconnected peer
huinet.on('peerDisconnected', (nodeID) => {
console.log(`Peer ${nodeID} disconnected`);
// Attempt to reconnect after delay
setTimeout(async () => {
const node = huinet.getRoutingTable().getKnownNode(nodeID);
if (node && node.addresses.length > 0) {
const addr = node.addresses[0];
await huinet.connectToNode(addr.host, addr.port, nodeID);
}
}, 5000);
});Emitted when a new node is discovered through mDNS.
huinet.on('nodeDiscovered', (node: DiscoveredNode) => {
console.log(`Discovered ${node.nodeId}`);
});Callback Signature: (node: DiscoveredNode) => void
Parameters:
- node (
DiscoveredNode): Information about the discovered node
huinet.on('nodeDiscovered', (node) => {
console.log(`Discovered node: ${node.nodeId} at ${node.address}`);
});Emitted when an error occurs.
huinet.on('error', (error: Error) => {
console.error('Error:', error);
});Callback Signature: (error: Error) => void
Parameters:
- error (
Error): The error object
huinet.on('error', (error) => {
console.error('HuiNet error:', error.message);
// Handle specific errors
if (error.message.includes('Unknown node')) {
console.log('Node not found in routing table');
}
});A NodeID is a string representing a unique node identifier.
type NodeID = string;Format: Base58-encoded SHA-256 hash of a public key (43-44 characters)
Example: 'QmXxx...'
Interface for message data structure.
interface MessageData {
from: NodeID; // Sender's NodeID
to: NodeID; // Recipient's NodeID
timestamp: number; // Unix timestamp in milliseconds
data: any; // Actual message payload
}Example:
const message: MessageData = {
from: 'QmSender123...',
to: 'QmRecipient456...',
timestamp: Date.now(),
data: {
type: 'chat',
text: 'Hello, World!'
}
};Enum representing the state of a node in the routing table.
enum NodeState {
UNKNOWN = 'UNKNOWN', // Node state not yet determined
ONLINE = 'ONLINE', // Node is online and reachable
OFFLINE = 'OFFLINE', // Node is offline or unreachable
RESTRICTED = 'RESTRICTED' // Node is restricted/blocked
}Values:
- UNKNOWN: Initial state when a node is discovered but not yet verified
- ONLINE: Node has been successfully contacted
- OFFLINE: Node is known to be offline
- RESTRICTED: Node is blocked or restricted
Enum representing the type of connection.
enum ConnectionType {
CORE = 'CORE', // Persistent connection to super nodes
ACTIVE = 'ACTIVE', // Cached connection to recently used nodes
ON_DEMAND = 'ON_DEMAND' // Temporary connection for one-off operations
}Enum representing the state of a connection.
enum ConnectionState {
CONNECTING = 'CONNECTING', // Connection is being established
CONNECTED = 'CONNECTED', // Connection is active
IDLE = 'IDLE', // Connection is idle
DISCONNECTED = 'DISCONNECTED', // Connection is closed
RECONNECTING = 'RECONNECTING', // Reconnection in progress
FAILED = 'FAILED' // Connection failed
}Enum representing the transport protocol.
enum TransportType {
TCP = 'tcp', // TCP transport
WS = 'ws', // WebSocket transport
QUIC = 'quic', // QUIC transport
RELAY = 'relay' // Relay transport
}Generate a new cryptographic key pair for node identity.
function generateKeyPair(): KeyPairKeyPair - Object containing publicKey and secretKey buffers
import { generateKeyPair } from '@huinet/network';
const keyPair = generateKeyPair();
console.log('Public Key:', keyPair.publicKey.toString('hex'));
console.log('Secret Key:', keyPair.secretKey.toString('hex'));Derive a NodeID from a public key.
function deriveNodeID(publicKey: Buffer): NodeID- publicKey (
Buffer): The public key buffer (32 bytes)
NodeID - The derived NodeID (Base58-encoded string)
import { deriveNodeID } from '@huinet/network';
const nodeID = deriveNodeID(publicKey);
console.log('NodeID:', nodeID);Validate a NodeID string format.
function validateNodeID(nodeID: string): boolean- nodeID (
string): The NodeID to validate
boolean - true if valid, false otherwise
import { validateNodeID } from '@huinet/network';
const isValid = validateNodeID('QmXxx...');
if (isValid) {
console.log('Valid NodeID');
} else {
console.log('Invalid NodeID');
}import { HuiNet, HuiNetConfig, generateKeyPair } from '@huinet/network';
// Create configuration
const config: HuiNetConfig = {
listenPort: 8000,
listenHost: '0.0.0.0',
bootstrapNodes: ['192.168.1.100:8000'],
maxCoreConnections: 10,
maxActiveConnections: 50,
enableMDNS: true
};
// Initialize HuiNet
const huinet = new HuiNet(config);
// Set up event handlers
huinet.on('ready', () => {
console.log(`Node ready! ID: ${huinet.getNodeID()}`);
});
huinet.on('message', (from, data) => {
console.log(`Message from ${from}:`, data);
});
huinet.on('peerConnected', (nodeID) => {
console.log(`Connected to ${nodeID}`);
});
huinet.on('peerDisconnected', (nodeID) => {
console.log(`Disconnected from ${nodeID}`);
});
huinet.on('nodeDiscovered', (node) => {
console.log(`Discovered ${node.nodeId}`);
});
huinet.on('error', (error) => {
console.error('Error:', error);
});
// Start the node
await huinet.start();
// Send a message
await huinet.send(targetNodeID, {
type: 'chat',
text: 'Hello from HuiNet!'
});
// Get routing information
const routingTable = huinet.getRoutingTable();
const allNodes = routingTable.getAllKnownNodes();
console.log(`Known nodes: ${allNodes.length}`);
// Graceful shutdown
process.on('SIGINT', async () => {
await huinet.stop();
process.exit(0);
});- Agent Integration Guide - Getting started guide for Agent integration
- Examples - Code examples and sample implementations
- GitHub Repository - Source code and issues