'use strict' ; import { VSCodeBlockchainOutputAdapter } from '../logging/VSCodeBlockchainOutputAdapter' ; import { IFabricGatewayConnection , LogType } from 'ibm-blockchain-platform-common' ; import * as vscode from 'vscode' ; import { FabricDebugConfigurationProvider } from '../debug/FabricDebugConfigurationProvider' ; import { LocalMicroEnvironment } from '../fabric/environments/LocalMicroEnvironment' ; import { LocalMicroEnvironmentManager } from '../fabric/environments/LocalMicroEnvironmentManager' ; export class MetadataUtil { public static async getTransactionNames ( connection , instantiatedChaincodeName , channelName ) { const metadataTransactions = await this . getTransactions ( connection , instantiatedChaincodeName , channelName ) ; if ( ! metadataTransactions || metadataTransactions . size === 0 ) { return null ; } const transactionNames = new Map ( ) ; for ( const [ name , transactionObj ] of metadataTransactions ) { const transactions = [ ] ; for ( const transaction of transactionObj ) { transactions . push ( transaction . name ) ; } transactionNames . set ( name , transactions ) ; } return transactionNames ; } public static async getContractNames ( connection , instantiatedChaincodeName , channelName ) { const metadataTransactions = await this . getTransactions ( connection , instantiatedChaincodeName , channelName ) ; if ( ! metadataTransactions ) { return null ; } const contractNames = [ ] ; for ( const name of metadataTransactions . keys ( ) ) { contractNames . push ( name ) ; } return contractNames ; } public static async getTransactions ( connection , instantiatedChaincodeName , channelName , checkForEmpty ? ) { const outputAdapter = VSCodeBlockchainOutputAdapter . instance ( ) ; let metadataObj = { contracts : { '' : { name : '' , transactions : [ ] , } } } ; const contractsMap = new Map ( ) ; try { metadataObj = await connection . getMetadata ( instantiatedChaincodeName , channelName ) ; await this . killChaincodeContainer ( instantiatedChaincodeName ) ; const contractsObject = metadataObj . contracts ; Object . keys ( contractsObject ) . forEach ( ( key ) => { if ( key !== 'org.hyperledger.fabric' && ( contractsObject [ key ] . transactions . length > 0 ) ) { contractsMap . set ( key , contractsObject [ key ] . transactions ) ; } } ) ; if ( checkForEmpty && ( contractsMap . size === 0 ) ) { outputAdapter . log ( LogType . ERROR , `No metadata returned. Please ensure this smart contract is developed using the programming model delivered in Hyperledger Fabric v1.4+ for Java, JavaScript and TypeScript` ) ; return ; } } catch ( error ) { outputAdapter . log ( LogType . WARNING , null , `Could not get metadata for smart contract ${ instantiatedChaincodeName }. The smart contract may not have been developed with the programming model delivered in Hyperledger Fabric v1.4+ for Java, JavaScript and TypeScript. Error: ${ error . message }` ) ; if ( ! error . message . includes ( 'Transaction function "org.hyperledger.fabric:GetMetadata"' ) ) { return null ; } } return contractsMap ; } private static async killChaincodeContainer ( chaincodeName ) { const activeSession = vscode . debug . activeDebugSession ; if ( activeSession && activeSession . configuration . debugEvent === FabricDebugConfigurationProvider . debugEvent && activeSession . configuration . env && activeSession . configuration . env . CORE_CHAINCODE_ID_NAME ) { const chaincodeInfo = activeSession . configuration . env . CORE_CHAINCODE_ID_NAME . split ( ':' ) ; const name = chaincodeInfo [ 0 ] ; const version = chaincodeInfo [ 1 ] ; if ( chaincodeName === name ) { const runtime = LocalMicroEnvironmentManager . instance ( ) . getRuntime ( FabricDebugConfigurationProvider . environmentName ) ; const isContainerRunning = await runtime . isRunning ( [ name , version ] ) ; if ( isContainerRunning ) { await runtime . killChaincode ( [ name , version ] ) ; } } } } }