import { FabricNode } from '../fabricModel/FabricNode' ; import { FabricWalletRegistryEntry } from '../registries/FabricWalletRegistryEntry' ; import { FabricGatewayRegistryEntry } from '../registries/FabricGatewayRegistryEntry' ; import { FabricIdentity } from '../fabricModel/FabricIdentity' ; import { FabricGateway } from '../fabricModel/FabricGateway' ; import { MicrofabClient , isPeer , isOrderer , MicrofabComponent , MicrofabIdentity , isIdentity , isGateway , MicrofabGateway , isCertificateAuthority } from './MicrofabClient' ; import { FileConfigurations } from '../registries/FileConfigurations' ; import { IFabricWalletGenerator } from '../interfaces/IFabricWalletGenerator' ; import { FabricWalletGeneratorFactory } from '../util/FabricWalletGeneratorFactory' ; import { IFabricWallet } from '../interfaces/IFabricWallet' ; import * as fs from 'fs-extra' ; import * as path from 'path' ; import { FabricEnvironment } from './FabricEnvironment' ; export class MicrofabEnvironment extends FabricEnvironment { public client : MicrofabClient ; constructor ( name , environmentPath , public url ) { super ( name , environmentPath ) ; this . setClient ( url ) ; } public getURL ( ) { return this . url ; } public setClient ( url ) { if ( ! ( url . includes ( 'http://' ) || url . includes ( 'https://' ) ) ) { this . url = `http://${ url }` ; } else { this . url = url ; } this . client = new MicrofabClient ( this . url ) ; } public async isAlive ( ) { return this . client . isAlive ( ) ; } public async getAllOrganizationNames ( showOrderer = true ) { return super . getAllOrganizationNames ( showOrderer ) ; } public async getNodes ( _withoutIdentities = false , _showAll = false ) { const components = await this . client . getComponents ( ) ; const nodes = [ ] ; for ( const component of components ) { if ( isPeer ( component ) ) { const node = FabricNode . newPeer ( component . id , component . display_name , component . api_url , component . wallet , component . identity , component . msp_id , false ) ; node . api_options = component . api_options ; node . chaincode_url = component . chaincode_url ; node . chaincode_options = component . chaincode_options ; nodes . push ( node ) ; } else if ( isOrderer ( component ) ) { const node = FabricNode . newOrderer ( component . id , component . display_name , component . api_url , component . wallet , component . identity , component . msp_id , component . display_name , false ) ; node . api_options = component . api_options ; nodes . push ( node ) ; } else if ( isCertificateAuthority ( component ) ) { const node = FabricNode . newCertificateAuthority ( component . id , component . display_name , component . api_url , null , component . wallet , component . identity , component . msp_id , null , null , false ) ; node . api_options = component . api_options ; nodes . push ( node ) ; } } return nodes ; } public async updateNode ( _node , _isOpsTools = false ) { throw new Error ( 'Operation not supported' ) ; } public async deleteNode ( _node ) { throw new Error ( 'Operation not supported' ) ; } public async requireSetup ( ) { return false ; } public async getWalletsAndIdentities ( ) { const walletNames = await this . getWalletNames ( ) ; const walletRegistryEntries = [ ] ; const walletGenerator = FabricWalletGeneratorFactory . getFabricWalletGenerator ( ) ; for ( const walletName of walletNames ) { if ( walletName === 'Orderer' ) { continue ; } const walletPath = path . join ( this . path , FileConfigurations . FABRIC_WALLETS , walletName ) ; await fs . mkdirp ( walletPath ) ; const walletRegistryEntry = new FabricWalletRegistryEntry ( { name : walletName , displayName : `${ this . name } - ${ walletName }` , walletPath , managedWallet : true , fromEnvironment : this . name , environmentGroups : [ this . name ] } ) ; walletRegistryEntries . push ( walletRegistryEntry ) ; const wallet = await walletGenerator . getWallet ( walletRegistryEntry ) ; const expectedIdentities = await this . getIdentities ( walletName ) ; const existingIdentities = await wallet . getIdentities ( ) ; const identitiesToImport = [ ] ; for ( const expectedIdentity of expectedIdentities ) { const identityExists = await wallet . exists ( expectedIdentity . name ) ; if ( ! identityExists ) { identitiesToImport . push ( expectedIdentity ) ; continue ; } const existingIdentity = existingIdentities . find ( ( identity ) => identity . name === expectedIdentity . name ) ; const identityMatches = existingIdentity . msp_id === expectedIdentity . msp_id && Buffer . from ( existingIdentity . cert , 'utf8' ) . toString ( 'base64' ) === expectedIdentity . cert && Buffer . from ( existingIdentity . private_key , 'utf8' ) . toString ( 'base64' ) === expectedIdentity . private_key ; if ( ! identityMatches ) { identitiesToImport . push ( expectedIdentity ) ; continue ; } } for ( const identityToImport of identitiesToImport ) { await wallet . importIdentity ( Buffer . from ( identityToImport . cert , 'base64' ) . toString ( 'utf8' ) , Buffer . from ( identityToImport . private_key , 'base64' ) . toString ( 'utf8' ) , identityToImport . name , identityToImport . msp_id ) ; } } return walletRegistryEntries ; } public async getGateways ( ) { const gateways = await this . getFabricGateways ( ) ; return gateways . map ( ( gateway ) => { return new FabricGatewayRegistryEntry ( { name : `${ this . name } - ${ gateway . name }` , associatedWallet : ( gateway . connectionProfile as any ) . wallet , displayName : gateway . name , connectionProfilePath : gateway . path , fromEnvironment : this . name , environmentGroup : this . name } ) ; } ) ; } public async getWalletNames ( ) { const components = await this . client . getComponents ( ) ; const identities = components . filter ( ( component ) => isIdentity ( component ) ) as MicrofabIdentity [ ] ; const walletNames = [ ] ; for ( const identity of identities ) { if ( walletNames . indexOf ( identity . wallet ) < 0 ) { walletNames . push ( identity . wallet ) ; } } return walletNames ; } public async getVisibleIdentities ( walletName ) { const components = await this . client . getComponents ( ) ; const identities = components . filter ( ( component ) => isIdentity ( component ) && component . wallet === walletName && component . hide === false ) as MicrofabIdentity [ ] ; return identities . map ( ( identity ) => { return new FabricIdentity ( identity . display_name , identity . cert , identity . private_key , identity . msp_id ) ; } ) ; } public async getIdentities ( walletName ) { const components = await this . client . getComponents ( ) ; const identities = components . filter ( ( component ) => isIdentity ( component ) && component . wallet === walletName ) as MicrofabIdentity [ ] ; return identities . map ( ( identity ) => { return new FabricIdentity ( identity . display_name , identity . cert , identity . private_key , identity . msp_id ) ; } ) ; } public async getFabricGateways ( ) { const components = await this . client . getComponents ( ) ; const gateways = components . filter ( ( component ) => isGateway ( component ) ) as MicrofabGateway [ ] ; const result = [ ] ; for ( const gateway of gateways ) { const gatewaysPath = path . join ( this . path , FileConfigurations . FABRIC_GATEWAYS ) ; await fs . mkdirp ( gatewaysPath ) ; const gatewayPath = path . join ( gatewaysPath , `${ gateway . display_name }.json` ) ; const gatewayExists = await fs . pathExists ( gatewayPath ) ; if ( ! gatewayExists ) { await fs . writeJson ( gatewayPath , gateway ) ; } else { const existingGateway = await fs . readJson ( gatewayPath ) ; const gatewaysMatch = JSON . stringify ( existingGateway ) === JSON . stringify ( gateway ) ; if ( ! gatewaysMatch ) { await fs . writeJson ( gatewayPath , gateway ) ; } } result . push ( new FabricGateway ( gateway . name , gatewayPath , gateway ) ) ; } return result ; } }