/** * Blockchain Lifecycle Manager * Manages Hyperledger stack deployments (Fabric, Besu, Indy, FireFly) */ import { getDb } from '../db/index.js' import { logger } from '../lib/logger.js' import { Context } from '../types/context.js' import { deploymentService } from './deployment.js' export enum BlockchainFramework { HYPERLEDGER_FABRIC = 'HYPERLEDGER_FABRIC', HYPERLEDGER_BESU = 'HYPERLEDGER_BESU', HYPERLEDGER_INDY = 'HYPERLEDGER_INDY', HYPERLEDGER_FIREFLY = 'HYPERLEDGER_FIREFLY', CACTI = 'CACTI', } export enum NodeRole { PEER = 'PEER', ORDERER = 'ORDERER', VALIDATOR = 'VALIDATOR', ENDORSER = 'ENDORSER', CA = 'CA', IDENTITY_NODE = 'IDENTITY_NODE', FIREFLY_NODE = 'FIREFLY_NODE', CACTI_NODE = 'CACTI_NODE', } export interface BlockchainNetwork { id: string name: string framework: BlockchainFramework deploymentId?: string networkId?: string status: string configuration: Record metadata: Record createdAt: Date updatedAt: Date } export interface BlockchainNode { id: string networkId: string name: string role: NodeRole nodeType?: string endpointUrl?: string rpcEndpoint?: string grpcEndpoint?: string websocketEndpoint?: string status: string configuration: Record createdAt: Date updatedAt: Date } export interface CreateBlockchainNetworkInput { name: string framework: BlockchainFramework region?: string configuration: { nodeRoles: Array<{ role: NodeRole count: number }> ledgerStorage?: string consensus?: string permissioning?: Record } } class BlockchainLifecycleManager { /** * Create blockchain network */ async createNetwork( context: Context, input: CreateBlockchainNetworkInput ): Promise { logger.info('Creating blockchain network', { name: input.name, framework: input.framework, }) const db = getDb() // Create deployment for blockchain network const deployment = await deploymentService.createDeployment(context, { name: input.name, templateId: await this.getTemplateIdForFramework(input.framework), region: input.region, deploymentType: 'KUBERNETES', parameters: { framework: input.framework, ...input.configuration, }, }) // Create network record const result = await db.query( `INSERT INTO blockchain_networks ( name, framework, deployment_id, status, configuration ) VALUES ($1, $2, $3, $4, $5) RETURNING *`, [ input.name, input.framework, deployment.id, 'PROVISIONING', JSON.stringify(input.configuration), ] ) const network = this.mapNetwork(result.rows[0]) // Create nodes based on configuration for (const nodeRole of input.configuration.nodeRoles) { for (let i = 0; i < nodeRole.count; i++) { await this.createNode(context, network.id, { name: `${input.name}-${nodeRole.role.toLowerCase()}-${i + 1}`, role: nodeRole.role, configuration: {}, }) } } logger.info('Blockchain network created', { networkId: network.id }) return network } /** * Create blockchain node */ async createNode( context: Context, networkId: string, input: { name: string role: NodeRole nodeType?: string configuration?: Record } ): Promise { const db = getDb() const result = await db.query( `INSERT INTO blockchain_nodes ( network_id, name, role, node_type, status, configuration ) VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`, [ networkId, input.name, input.role, input.nodeType || 'KUBERNETES', 'PENDING', JSON.stringify(input.configuration || {}), ] ) return this.mapNode(result.rows[0]) } /** * Get network by ID */ async getNetwork(context: Context, id: string): Promise { const db = getDb() const result = await db.query( `SELECT * FROM blockchain_networks WHERE id = $1`, [id] ) if (result.rows.length === 0) return null return this.mapNetwork(result.rows[0]) } /** * Get nodes for network */ async getNodes(context: Context, networkId: string): Promise { const db = getDb() const result = await db.query( `SELECT * FROM blockchain_nodes WHERE network_id = $1 ORDER BY created_at`, [networkId] ) return result.rows.map(this.mapNode) } /** * Get template ID for framework */ private async getTemplateIdForFramework(framework: BlockchainFramework): Promise { // In production, this would look up the template from catalog const templateMap: Record = { [BlockchainFramework.HYPERLEDGER_FABRIC]: 'fabric-template-id', [BlockchainFramework.HYPERLEDGER_BESU]: 'besu-template-id', [BlockchainFramework.HYPERLEDGER_INDY]: 'indy-template-id', [BlockchainFramework.HYPERLEDGER_FIREFLY]: 'firefly-template-id', [BlockchainFramework.CACTI]: 'cacti-template-id', } return templateMap[framework] } // Mapper functions private mapNetwork(row: any): BlockchainNetwork { return { id: row.id, name: row.name, framework: row.framework as BlockchainFramework, deploymentId: row.deployment_id, networkId: row.network_id, status: row.status, configuration: row.configuration || {}, metadata: row.metadata || {}, createdAt: row.created_at, updatedAt: row.updated_at, } } private mapNode(row: any): BlockchainNode { return { id: row.id, networkId: row.network_id, name: row.name, role: row.role as NodeRole, nodeType: row.node_type, endpointUrl: row.endpoint_url, rpcEndpoint: row.rpc_endpoint, grpcEndpoint: row.grpc_endpoint, websocketEndpoint: row.websocket_endpoint, status: row.status, configuration: row.configuration || {}, createdAt: row.created_at, updatedAt: row.updated_at, } } } export const blockchainLifecycleManager = new BlockchainLifecycleManager()