'use strict' ; import * as vscode from 'vscode' ; import * as path from 'path' ; import * as os from 'os' ; import * as fs from 'fs-extra' ; import { InstantiatedTreeItem } from '../explorer/model/InstantiatedTreeItem' ; import { ContractTreeItem } from '../explorer/model/ContractTreeItem' ; import { FabricGatewayConnectionManager } from '../fabric/FabricGatewayConnectionManager' ; import { ExtensionCommands } from '../../ExtensionCommands' ; import { UserInputUtil , IBlockchainQuickPickItem } from './UserInputUtil' ; import { VSCodeBlockchainOutputAdapter } from '../logging/VSCodeBlockchainOutputAdapter' ; import { LogType , FabricGatewayRegistryEntry , ConnectionProfileUtil , FabricWalletRegistryEntry , IFabricWallet , FabricWalletGeneratorFactory , IFabricWalletGenerator , FabricIdentity , FabricEnvironmentRegistryEntry , FabricEnvironmentRegistry , FabricNode , FabricEnvironment } from 'ibm-blockchain-platform-common' ; import { Reporter } from '../util/Reporter' ; import { EnvironmentFactory } from '../fabric/environments/EnvironmentFactory' ; export async function exportAppData ( chaincode ? ) { let chosenChaincode ; let appData = '' ; let chaincodeName ; let channelName ; const outputAdapter = VSCodeBlockchainOutputAdapter . instance ( ) ; outputAdapter . log ( LogType . INFO , undefined , 'exportAppData' ) ; if ( ! chaincode ) { if ( ! FabricGatewayConnectionManager . instance ( ) . getConnection ( ) ) { await vscode . commands . executeCommand ( ExtensionCommands . CONNECT_TO_GATEWAY ) ; if ( ! FabricGatewayConnectionManager . instance ( ) . getConnection ( ) ) { return ; } } chosenChaincode = await UserInputUtil . showClientInstantiatedSmartContractsQuickPick ( 'Choose the smart contract you want to generate client app assets from' ) ; if ( ! chosenChaincode ) { return ; } chaincodeName = chosenChaincode . data . name ; channelName = chosenChaincode . data . channel ; } else { if ( chaincode instanceof ContractTreeItem ) { chaincodeName = chaincode . instantiatedChaincode . name ; channelName = chaincode . channelName ; } else { chaincodeName = chaincode . name ; channelName = chaincode . channels [ 0 ] . label ; } } const items = [ { label : UserInputUtil . GENERATE_ENVIRONMENT_PROFILE , data : UserInputUtil . GENERATE_ENVIRONMENT_PROFILE , description : UserInputUtil . GENERATE_ENVIRONMENT_PROFILE_DESCRIPTION } ] ; const appAssets = await UserInputUtil . showQuickPickItem ( 'Choose which client app assets to generate' , items , true ) as IBlockchainQuickPickItem < string > [ ] ; if ( ! appAssets || appAssets . length === 0 ) { return ; } let defaultPath ; const fileName = 'env.properties' ; const workspaceFolders = UserInputUtil . getWorkspaceFolders ( ) ; if ( workspaceFolders . length > 0 ) { defaultPath = path . join ( workspaceFolders [ 0 ] . uri . fsPath , fileName ) ; } else { defaultPath = path . join ( os . homedir ( ) , fileName ) ; } let chosenPathUri ; try { const connectedGateway = await FabricGatewayConnectionManager . instance ( ) . getGatewayRegistryEntry ( ) ; const connectionProfilePath = connectedGateway . connectionProfilePath ; let connectionProfile = await ConnectionProfileUtil . readConnectionProfile ( connectionProfilePath ) ; delete connectionProfile . wallet ; const connectionProfileString = JSON . stringify ( connectionProfile ) ; if ( connectionProfileString . includes ( 'localhost' ) ) { const envName = connectedGateway . fromEnvironment ; if ( ! envName ) { throw new Error ( 'Gateway not supported' ) ; } else { connectionProfile = await updateConnectionProfile ( envName , connectionProfile ) ; } } const connectionProfileData = JSON . stringify ( connectionProfile ) ; appData += `FABRIC_CONNECTION_PROFILE=${ connectionProfileData }\n` ; const identityName = FabricGatewayConnectionManager . instance ( ) . getConnectionIdentity ( ) ; const walletEntry = FabricGatewayConnectionManager . instance ( ) . getConnectionWallet ( ) ; const FabricWalletGenerator = FabricWalletGeneratorFactory . getFabricWalletGenerator ( ) ; const wallet = await FabricWalletGenerator . getWallet ( walletEntry ) ; const idNames = await wallet . getIdentityNames ( ) ; const chosenIDs = await UserInputUtil . showIdentitiesQuickPickBox ( 'Choose the identities which you would like to export' , true , idNames ) ; if ( ! chosenIDs ) { return ; } else if ( chosenIDs . length === 0 ) { throw new Error ( 'No identities were selected.' ) ; } const allIDs = await wallet . getIDs ( chosenIDs ) ; appData += `FABRIC_WALLET_CREDENTIALS=${ [ JSON . stringify ( allIDs ) ] }\n` ; appData += `FABRIC_DEFAULT_IDENTITY=${ identityName }\n` ; appData += `FABRIC_CHANNEL=${ channelName }\n` ; appData += `FABRIC_CONTRACT=${ chaincodeName }` ; chosenPathUri = await vscode . window . showSaveDialog ( { defaultUri : vscode . Uri . file ( defaultPath ) , saveLabel : 'Export' } ) ; if ( ! chosenPathUri ) { return ; } await fs . writeFile ( chosenPathUri . fsPath , appData ) ; } catch ( error ) { outputAdapter . log ( LogType . ERROR , `Error exporting application data: ${ error . message }` , `Error exporting application data: ${ error . toString ( ) }` ) ; return ; } outputAdapter . log ( LogType . SUCCESS , `Successfully exported application data to ${ chosenPathUri . fsPath }` ) ; Reporter . instance ( ) . sendTelemetryEvent ( 'exportAppDataCommand' ) ; } async function updateConnectionProfile ( envName , connectionProfile ) { const environmentEntry = await FabricEnvironmentRegistry . instance ( ) . get ( envName ) ; const environment = EnvironmentFactory . getEnvironment ( environmentEntry ) as FabricEnvironment ; const nodes = await environment . getNodes ( ) ; const peers = connectionProfile . peers ; const certificateAuthorities = connectionProfile . certificateAuthorities ; const peerKeys = Object . keys ( peers ) ; const caKeys = Object . keys ( certificateAuthorities ) ; peerKeys . forEach ( ( key ) => { const url = peers [ key ] . url ; const peer = nodes . find ( ( node ) => { if ( node . name === key ) { return node ; } } ) ; const newURL = url . replace ( 'localhost' , peer . container_name . split ( '_' ) [ 1 ] ) ; peers [ key ] . url = newURL ; } ) ; caKeys . forEach ( ( key ) => { const url = certificateAuthorities [ key ] . url ; const ca = nodes . find ( ( node ) => { if ( node . name === key ) { return node ; } } ) ; const newURL = url . replace ( 'localhost' , ca . container_name . split ( '_' ) [ 1 ] ) ; certificateAuthorities [ key ] . url = newURL ; } ) ; connectionProfile . peers = peers ; connectionProfile . certificateAuthorities = certificateAuthorities ; return connectionProfile ; }