diff --git a/.eslintignore b/.eslintignore index 138020cb96..84dfe84cdb 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,11 +1,112 @@ +**/node_modules/** **/dist/** +examples/cactus-example-carbon-accounting-frontend/www/ +examples/cactus-example-supply-chain-frontend/www/ + **/src/main/typescript/generated/proto/** **/src/main/typescript/generated/wasm-pack/** -packages/cactus-verifier/src/main/typescript/ -packages/cactus-cmd-socketio-server/** -packages/cactus-plugin-ledger-connector-go-ethereum-socketio/** -packages/cactus-plugin-ledger-connector-*-socketio/** +packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BusinessLogicBase.ts +packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/LedgerOperation.ts +packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/app.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/TransactionManagement.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/login.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/BLPRegistry.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ContractInfoHolder.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/LPInfoHolder.ts +packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/RIFUtil.ts +packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts +packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts + +packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierFactory.ts +packages/cactus-cmd-socketio-server/src/test/typescript/unit/Verifier.test.ts + +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/app.ts +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/bin/www.ts +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/template/ServerMonitorPlugin_template.ts +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/template/ServerPlugin_template.ts +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/test/typescript/unit-test/validatorDriver_getNonceHex.ts +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/test/typescript/unit-test/validatorDriver_sendRawTransaction.ts +packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/test/typescript/unit-test/validatorDriver_transferNumericAsset.ts +packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/common/core/app.ts +packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts -weaver/** +weaver/common/policy-dsl/index.js +weaver/common/policy-dsl/parser/PolicyListener.js +weaver/common/policy-dsl/parser/PolicyParser.js +weaver/common/policy-dsl/test/MyErrorListener.js +weaver/common/policy-dsl/test/MyParseTreeVisitor.js +weaver/core/drivers/fabric-driver/server/dbConnector.ts +weaver/core/drivers/fabric-driver/server/events.ts +weaver/core/drivers/fabric-driver/server/fabric-code.ts +weaver/core/drivers/fabric-driver/server/listener.ts +weaver/core/drivers/fabric-driver/server/server.ts +weaver/core/drivers/fabric-driver/server/tests.ts +weaver/core/drivers/fabric-driver/server/utils.ts +weaver/core/drivers/fabric-driver/server/walletSetup.ts +weaver/core/identity-management/iin-agent/src/common/ledgerBase.ts +weaver/core/identity-management/iin-agent/src/common/utils.ts +weaver/core/identity-management/iin-agent/src/fabric-ledger/connector.ts +weaver/core/identity-management/iin-agent/src/fabric-ledger/networkUtils.ts +weaver/core/identity-management/iin-agent/src/fabric-ledger/walletUtils.ts +weaver/core/identity-management/iin-agent/src/protocols/externalOperations.ts +weaver/core/identity-management/iin-agent/src/protocols/localOperations.ts +weaver/core/identity-management/iin-agent/src/server.ts +weaver/core/identity-management/iin-agent/test/membershipTest.js +weaver/core/identity-management/iin-agent/test/utilsTest.js +weaver/samples/besu/besu-cli/src/commands/asset/claim.ts +weaver/samples/besu/besu-cli/src/commands/asset/exchange.ts +weaver/samples/besu/besu-cli/src/commands/asset/issue.ts +weaver/samples/besu/besu-cli/src/commands/asset/lock.ts +weaver/samples/besu/besu-cli/src/commands/asset/unlock.ts +weaver/samples/besu/simpleasset/app/AssetExchangeERC1155_20.js +weaver/samples/besu/simpleasset/app/AssetExchangeERC20.js +weaver/samples/besu/simpleasset/app/AssetExchangeERC721_20.js +weaver/samples/besu/simpleasset/get-network-details.js +weaver/samples/besu/simplestate/get-network-details.js +weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-all.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/claim.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/is-locked.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/lock.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/unlock.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/claim.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/pledge.ts +weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/reclaim.ts +weaver/samples/fabric/fabric-cli/src/commands/chaincode/invoke.ts +weaver/samples/fabric/fabric-cli/src/commands/chaincode/query.ts +weaver/samples/fabric/fabric-cli/src/commands/config-helper.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/asset/add.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/create/access-control.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/create/all.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/create/membership.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/create/verification-policy.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/membership.ts +weaver/samples/fabric/fabric-cli/src/commands/configure/network.ts +weaver/samples/fabric/fabric-cli/src/commands/env-helper.ts +weaver/samples/fabric/fabric-cli/src/commands/event/get-all.ts +weaver/samples/fabric/fabric-cli/src/commands/event/get-subscription-status.ts +weaver/samples/fabric/fabric-cli/src/commands/event/receive.ts +weaver/samples/fabric/fabric-cli/src/commands/event/subscribe.ts +weaver/samples/fabric/fabric-cli/src/commands/event/unsubscribe.ts +weaver/samples/fabric/fabric-cli/src/commands/hash-helper.ts +weaver/samples/fabric/fabric-cli/src/commands/helper-helper.ts +weaver/samples/fabric/fabric-cli/src/commands/helper/getKeyAndCert.ts +weaver/samples/fabric/fabric-cli/src/commands/interop-helper.ts +weaver/samples/fabric/fabric-cli/src/commands/user-helper.ts +weaver/samples/fabric/fabric-cli/src/commands/user/add.ts +weaver/samples/fabric/fabric-cli/src/helpers/fabric-functions.ts +weaver/samples/fabric/fabric-cli/src/helpers/helpers.ts +weaver/samples/fabric/fabric-cli/src/helpers/interop-setup/configure-network.ts +weaver/sdks/besu/node/src/AssetManager.ts +weaver/sdks/fabric/interoperation-node-sdk/src/AssetManager.ts +weaver/sdks/fabric/interoperation-node-sdk/src/EventsManager.ts +weaver/sdks/fabric/interoperation-node-sdk/src/HashFunctions.ts +weaver/sdks/fabric/interoperation-node-sdk/src/InteroperableHelper.ts +weaver/sdks/fabric/interoperation-node-sdk/src/MembershipManager.ts +weaver/sdks/fabric/interoperation-node-sdk/src/Relay.ts +weaver/sdks/fabric/interoperation-node-sdk/src/helpers.ts +weaver/sdks/fabric/interoperation-node-sdk/test/AssetManager.js +weaver/sdks/fabric/interoperation-node-sdk/test/InteroperableHelper.js +weaver/sdks/fabric/interoperation-node-sdk/test/Relay.js diff --git a/.prettierignore b/.prettierignore index a7e509ae92..4191d5a494 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,4 +7,8 @@ packages/core packages/connection-chain contribs/ -**/src/main/typescript/generated/** \ No newline at end of file +**/src/main/typescript/generated/** + +# TODO: Send a PR that moves these generated code files under a sub-directory +# that is called "generated" so that the default ignore pattern above matches it +packages/cactus-plugin-ledger-connector-sawtooth/src/main/typescript/sawtooth-api/** \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js index ec3d2f9797..3d19b40221 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -5,4 +5,4 @@ module.exports = { tabWidth: 2, trailingComma: "all", singleQuote: false, -}; \ No newline at end of file +}; diff --git a/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/.eslintignore b/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/.eslintignore deleted file mode 100644 index 1595847010..0000000000 --- a/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/.eslintignore +++ /dev/null @@ -1,5 +0,0 @@ -# -# SPDX-License-Identifier: Apache-2.0 -# - -coverage diff --git a/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/package.json b/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/package.json index 2a0a21457b..e516e5e60c 100644 --- a/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/package.json +++ b/examples/cactus-example-cbdc-bridging-backend/src/fabric-contracts/cbdc-erc-20/javascript/package.json @@ -8,7 +8,6 @@ "npm": ">=5" }, "scripts": { - "lint": "eslint .", "test": "nyc mocha --recursive", "mocha": "mocha --recursive", "start": "fabric-chaincode-node start" @@ -24,7 +23,6 @@ "@types/sinon-chai": "^3.2.8", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", - "eslint": "^4.19.1", "mocha": "^8.0.1", "nyc": "^14.1.1", "sinon": "^6.0.0", diff --git a/examples/cactus-example-cbdc-bridging-frontend/package.json b/examples/cactus-example-cbdc-bridging-frontend/package.json index 17bedecc40..3810106632 100644 --- a/examples/cactus-example-cbdc-bridging-frontend/package.json +++ b/examples/cactus-example-cbdc-bridging-frontend/package.json @@ -21,12 +21,6 @@ "last 1 safari version" ] }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, "dependencies": { "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", diff --git a/examples/cactus-example-discounted-asset-trade/trades.ts b/examples/cactus-example-discounted-asset-trade/trades.ts index 088a3b1d03..83558a76d9 100644 --- a/examples/cactus-example-discounted-asset-trade/trades.ts +++ b/examples/cactus-example-discounted-asset-trade/trades.ts @@ -18,7 +18,8 @@ const logger = getLogger(`${moduleName}`); logger.level = config.logLevel; const router: Router = Router(); -export const transactionManagement: TransactionManagement = new TransactionManagement(); +export const transactionManagement: TransactionManagement = + new TransactionManagement(); // Request Execution of Trade router.post("/", (req: Request, res: Response, next: NextFunction) => { diff --git a/examples/cactus-example-electricity-trade/BusinessLogicElectricityTrade.ts b/examples/cactus-example-electricity-trade/BusinessLogicElectricityTrade.ts index ae54bf5694..e5c78c430e 100644 --- a/examples/cactus-example-electricity-trade/BusinessLogicElectricityTrade.ts +++ b/examples/cactus-example-electricity-trade/BusinessLogicElectricityTrade.ts @@ -11,7 +11,6 @@ import { MeterManagement } from "./MeterManagement"; import { MeterInfo } from "./MeterInfo"; import { BusinessLogicBase, - LedgerEvent, json2str, ConfigUtil, } from "@hyperledger/cactus-cmd-socketio-server"; @@ -141,7 +140,7 @@ export class BusinessLogicElectricityTrade extends BusinessLogicBase { }); } - onEvent(ledgerEvent: LedgerEvent, targetIndex: number): void { + onEvent(): void { logger.error( "onEvent() ERROR - No monitors are running, should not be called!", ); diff --git a/examples/cactus-example-electricity-trade/package.json b/examples/cactus-example-electricity-trade/package.json index 021b79e95a..101d890b66 100644 --- a/examples/cactus-example-electricity-trade/package.json +++ b/examples/cactus-example-electricity-trade/package.json @@ -46,13 +46,7 @@ "devDependencies": { "@types/escape-html": "1.0.1", "@types/express": "4.17.19", - "@types/uuid": "9.0.8", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", - "eslint": "7.32.0", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-prettier": "5.0.0", - "prettier": "2.8.8" + "@types/uuid": "9.0.8" }, "engines": { "node": ">=18", diff --git a/examples/cactus-example-tcs-huawei/BusinessLogicTcsElectricityTrade.ts b/examples/cactus-example-tcs-huawei/BusinessLogicTcsElectricityTrade.ts index 354f7c2c23..234344725e 100644 --- a/examples/cactus-example-tcs-huawei/BusinessLogicTcsElectricityTrade.ts +++ b/examples/cactus-example-tcs-huawei/BusinessLogicTcsElectricityTrade.ts @@ -280,7 +280,7 @@ export class BusinessLogicElectricityTrade extends BusinessLogicBase { } } - getOperationStatus(tradeID: string): object { + getOperationStatus(): object { logger.debug(`##in getOperationStatus()`); return {}; } @@ -290,7 +290,6 @@ export class BusinessLogicElectricityTrade extends BusinessLogicBase { targetIndex: number, ): string | null { logger.debug(`##in getTxIDFromEvent`); - // logger.debug(`##event: ${json2str(ledgerEvent)}`); switch (ledgerEvent.verifierId) { case config.electricityTradeInfo.tcsHuawei.validatorID: diff --git a/examples/cactus-example-tcs-huawei/MeterManagement.ts b/examples/cactus-example-tcs-huawei/MeterManagement.ts index 89b4c9bc2c..f3b5299325 100644 --- a/examples/cactus-example-tcs-huawei/MeterManagement.ts +++ b/examples/cactus-example-tcs-huawei/MeterManagement.ts @@ -7,8 +7,7 @@ import { MeterInfo } from "./MeterInfo"; import { ConfigUtil } from "@hyperledger/cactus-cmd-socketio-server"; -import fs from "fs" -import yaml from "js-yaml" +import fs from "fs"; const config: any = ConfigUtil.getConfig(); import { getLogger } from "log4js"; const moduleName = "MeterManagement"; @@ -52,7 +51,7 @@ export class MeterManagement { }; let existFlag = false; let action = ""; - meterInfoTable.forEach((meterInfoJSON, index) => { + meterInfoTable.forEach((meterInfoJSON) => { const meterInfo: MeterInfo = JSON.parse(meterInfoJSON) as MeterInfo; // Determine if it is a target record @@ -105,7 +104,7 @@ export class MeterManagement { // Search target records let retMeterInfo: MeterInfo | null = null; - meterInfoTable.forEach((meterInfoJSON, index) => { + meterInfoTable.forEach((meterInfoJSON) => { const meterInfo: MeterInfo = JSON.parse(meterInfoJSON) as MeterInfo; // Determine if it is a target record @@ -117,188 +116,4 @@ export class MeterManagement { return retMeterInfo; } - - /* - setStatus(tradeInfo: TradeInfo, status: CartradeStatus) { - - // Existence check of table file - try { - fs.statSync(this.fileName); - } catch (err) { - throw err; - } - - // Read table file - const fileData: string = fs.readFileSync(this.fileName, 'utf8'); - const transactionInfoTable: string[] = JSON.parse(fileData).table as string[]; - - // Search target records / replace data - const transactionInfoTableNew = { - table: [] - }; - transactionInfoTable.forEach((transactionInfoJSON, index) => { - const transactionInfo: TransactionInfo = JSON.parse(transactionInfoJSON) as TransactionInfo; - - // Determine if it is a target record - if (transactionInfo.businessLogicID === tradeInfo.businessLogicID && transactionInfo.tradeID === tradeInfo.tradeID) { - // Change Status - transactionInfo.status = status; - } - - // Register Record - const transactionInfoJson: string = JSON.stringify(transactionInfo); - transactionInfoTableNew.table.push(transactionInfoJson); - }); - - // Table File Write - const transactionInfoTableNewJson: string = JSON.stringify(transactionInfoTableNew); - fs.writeFileSync(this.fileName, transactionInfoTableNewJson, 'utf8'); - - this.fileDump(); - } - - setTransactionData(tradeInfo: TradeInfo, transactionData: TransactionData) { - - // Existence check of table file - try { - fs.statSync(this.fileName); - } catch (err) { - throw err; - } - - // Read table file - const fileData: string = fs.readFileSync(this.fileName, 'utf8'); - const transactionInfoTable: string[] = JSON.parse(fileData).table as string[]; - - // Search target records / replace data - const transactionInfoTableNew = { - table: [] - }; - transactionInfoTable.forEach((transactionInfoJSON, index) => { - const transactionInfo: TransactionInfo = JSON.parse(transactionInfoJSON) as TransactionInfo; - - // Determine if it is a target record - if (transactionInfo.businessLogicID === tradeInfo.businessLogicID && transactionInfo.tradeID === tradeInfo.tradeID) { - - // Determine if it is the target transaction - if (transactionData.target === "escrow") { - // escrow: dataset - transactionInfo.escrowLedger = transactionData.ledger; - transactionInfo.escrowTxID = transactionData.txID; - } - else if (transactionData.target === "transfer") { - // transfer: dataset - transactionInfo.transferLedger = transactionData.ledger; - transactionInfo.transferTxID = transactionData.txID; - } - else if (transactionData.target === "settlement") { - // settlement: dataset - transactionInfo.settlementLedger = transactionData.ledger; - transactionInfo.settlementTxID = transactionData.txID; - } - - } - - // Register Record - const transactionInfoJson: string = JSON.stringify(transactionInfo); - transactionInfoTableNew.table.push(transactionInfoJson); - }); - - // Table File Write - const transactionInfoTableNewJson: string = JSON.stringify(transactionInfoTableNew); - fs.writeFileSync(this.fileName, transactionInfoTableNewJson, 'utf8'); - - this.fileDump(); - } - - setTxInfo(tradeInfo: TradeInfo, txInfoData: TxInfoData) { - - // Existence check of table file - try { - fs.statSync(this.fileName); - } catch (err) { - throw err; - } - - // Read table file - const fileData: string = fs.readFileSync(this.fileName, 'utf8'); - const transactionInfoTable: string[] = JSON.parse(fileData).table as string[]; - - // Search target records / replace data - const transactionInfoTableNew = { - table: [] - }; - transactionInfoTable.forEach((transactionInfoJSON, index) => { - const transactionInfo: TransactionInfo = JSON.parse(transactionInfoJSON) as TransactionInfo; - - // Determine if it is a target record - if (transactionInfo.businessLogicID === tradeInfo.businessLogicID && transactionInfo.tradeID === tradeInfo.tradeID) { - - // Determine if it is the target transaction - if (txInfoData.target === "escrow") { - // escrow: dataset - transactionInfo.escrowTxInfo = txInfoData.txInfo; - } - else if (txInfoData.target === "transfer") { - // transfer: dataset - transactionInfo.transferTxInfo = txInfoData.txInfo; - } - else if (txInfoData.target === "settlement") { - // settlement: dataset - transactionInfo.settlementTxInfo = txInfoData.txInfo; - } - - } - - // Register Record - const transactionInfoJson: string = JSON.stringify(transactionInfo); - transactionInfoTableNew.table.push(transactionInfoJson); - }); - - // Table File Write - const transactionInfoTableNewJson: string = JSON.stringify(transactionInfoTableNew); - fs.writeFileSync(this.fileName, transactionInfoTableNewJson, 'utf8'); - - this.fileDump(); - } -*/ - /** - * Get transaction data corresponding to the specified txId. - * (*Return if any of escrowTxID, transferTxID, settlementTxID matches txId) - * - * @return Transaction data corresponding to txId. Returns null if it does not exist. - * - */ - /* - getTransactionInfoByTxId(txId: string): TransactionInfo { - - // Existence check of table file - try { - fs.statSync(this.fileName); - } catch (err) { - throw err; - } - - // Read table file - const fileData: string = fs.readFileSync(this.fileName, 'utf8'); - const transactionInfoTable: string[] = JSON.parse(fileData).table as string[]; - - // Search target records - const transactionInfoTableNew = { - table: [] - }; - let retTransactionInfo: TransactionInfo | null = null; - transactionInfoTable.forEach((transactionInfoJSON, index) => { - const transactionInfo: TransactionInfo = JSON.parse(transactionInfoJSON) as TransactionInfo; - - // Determine if it is a target record - if (transactionInfo.escrowTxID === txId || transactionInfo.transferTxID === txId || transactionInfo.settlementTxID === txId) { - retTransactionInfo = transactionInfo; - return; - } - }); - - return retTransactionInfo; - } -*/ } diff --git a/examples/cactus-example-tcs-huawei/electricity-trade.ts b/examples/cactus-example-tcs-huawei/electricity-trade.ts index 5fc73c4703..c6aeb4d7d0 100644 --- a/examples/cactus-example-tcs-huawei/electricity-trade.ts +++ b/examples/cactus-example-tcs-huawei/electricity-trade.ts @@ -26,7 +26,7 @@ export const transactionManagement: TransactionManagement = // Request Execution of Trade router.post("/", (req: Request, res: Response, next: NextFunction) => { try { - logger.warn("pre startBusinessLogic ") + logger.warn("pre startBusinessLogic "); const tradeID = transactionManagement.startBusinessLogic(req); if (!tradeID) { throw new RIFError(`Could not run BLP, tradeId = ${tradeID}`); @@ -69,7 +69,7 @@ router.post( next(err); } - } + }, ); export default router; diff --git a/examples/cactus-example-tcs-huawei/package.json b/examples/cactus-example-tcs-huawei/package.json index d7ec2b16bd..7b9037c7e5 100644 --- a/examples/cactus-example-tcs-huawei/package.json +++ b/examples/cactus-example-tcs-huawei/package.json @@ -42,13 +42,7 @@ "@types/body-parser": "1.19.3", "@types/cookie-parser": "1.4.2", "@types/escape-html": "1.0.1", - "@types/express": "4.17.19", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", - "eslint": "7.32.0", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-prettier": "5.0.0", - "prettier": "2.8.8" + "@types/express": "4.17.19" }, "engines": { "node": ">=18", diff --git a/examples/cactus-example-tcs-huawei/tools/periodicExecuter/periodicExecuter.ts b/examples/cactus-example-tcs-huawei/tools/periodicExecuter/periodicExecuter.ts index 36b33374af..441de7b685 100644 --- a/examples/cactus-example-tcs-huawei/tools/periodicExecuter/periodicExecuter.ts +++ b/examples/cactus-example-tcs-huawei/tools/periodicExecuter/periodicExecuter.ts @@ -5,7 +5,7 @@ * periodicExecuter.ts */ -const { execSync } = require("child_process"); +import { execSync } from "child_process"; console.log("## start periodicExecuter"); @@ -14,17 +14,10 @@ if (process.argv.length !== 5 && process.argv.length !== 6) { process.exit(-1); } -const interval = parseInt(process.argv[2]); const keyString = process.argv[3]; -const valueAdd = process.argv[4]; const dockerExecString = "docker exec sawtooth-shell-default "; const submitCommand = "sawtooth batch submit -f batches.intkey --url http://rest-api:8008"; -const incCommand = - "intkey create_batch --key-name " + - keyString + - " --value-inc-rand " + - valueAdd; if (process.argv.length === 6) { const valueInitial = process.argv[5]; @@ -42,34 +35,3 @@ if (process.argv.length === 6) { const stdoutSetSubmit = execSync(dockerExecString + submitCommand); console.log(`submitCommand(set) stdout: ${stdoutSetSubmit.toString()}`); } - -const timerIdArowDown = setInterval(function () { - console.log(`incCommand : ${incCommand}`); - const stdoutInc = execSync(dockerExecString + incCommand); - console.log(`incCommand stdout: ${stdoutInc.toString()}`); - - console.log(`submitCommand(inc) : ${submitCommand}`); - const stdoutIncSubmit = execSync(dockerExecString + submitCommand); - console.log(`submitCommand(inc) stdout: ${stdoutIncSubmit.toString()}`); - - console.log(`##${getCurrentTime()} execute intkey`); -}, interval * 1000); - -function getCurrentTime(): string { - const now = new Date(); - return ( - "[" + - now.getFullYear() + - "/" + - ("0" + (now.getMonth() + 1)).slice(-2) + - "/" + - ("0" + now.getDate()).slice(-2) + - " " + - ("0" + now.getHours()).slice(-2) + - ":" + - ("0" + now.getMinutes()).slice(-2) + - ":" + - ("0" + now.getSeconds()).slice(-2) + - "]" - ); -} diff --git a/examples/test-run-transaction/BusinessLogicRunTransaction.ts b/examples/test-run-transaction/BusinessLogicRunTransaction.ts index 3ec7ed5ab0..6317c8c433 100644 --- a/examples/test-run-transaction/BusinessLogicRunTransaction.ts +++ b/examples/test-run-transaction/BusinessLogicRunTransaction.ts @@ -7,22 +7,17 @@ import { Request } from "express"; import { RequestInfo } from "./RequestInfo"; -//import { MeterManagement } from './MeterManagement'; -//import { MeterInfo } from './MeterInfo'; import { TradeInfo } from "../../packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/TradeInfo"; import { transactionManagement } from "../../packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/index"; import { verifierFactory } from "../../packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/index"; import { BusinessLogicBase } from "../../packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BusinessLogicBase"; -//import { makeRawTransaction } from './TransactionEthereum' import { LedgerEvent } from "../../packages/cactus-cmd-socketio-server/src/main/typescript/verifier/LedgerPlugin"; import { json2str } from "../../packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon"; -const fs = require("fs"); -const path = require("path"); -const yaml = require("js-yaml"); -//const config: any = JSON.parse(fs.readFileSync("/etc/cactus/default.json", 'utf8')); +import fs from "fs"; +import yaml from "js-yaml"; const config: any = yaml.safeLoad( - fs.readFileSync("/etc/cactus/default.yaml", "utf8") + fs.readFileSync("/etc/cactus/default.yaml", "utf8"), ); import { getLogger } from "log4js"; const moduleName = "BusinessLogicRunTransaction"; @@ -57,7 +52,7 @@ export class BusinessLogicRunTransaction extends BusinessLogicBase { // Create trade information const tradeInfo: TradeInfo = new TradeInfo( requestInfo.businessLogicID, - requestInfo.tradeID + requestInfo.tradeID, ); // Call Verifier to perform the function @@ -68,7 +63,7 @@ export class BusinessLogicRunTransaction extends BusinessLogicBase { logger.debug("called execTransaction()"); const useValidator = JSON.parse( - transactionManagement.getValidatorToUse(tradeInfo.businessLogicID) + transactionManagement.getValidatorToUse(tradeInfo.businessLogicID), ); // TODO: Temporarily specify no monitoring required (# 4rd parameter = false) @@ -76,7 +71,7 @@ export class BusinessLogicRunTransaction extends BusinessLogicBase { useValidator["validatorID"][0], "BusinessLogicRunTransaction", {}, - false + false, ); logger.debug("getVerifier"); @@ -104,7 +99,7 @@ export class BusinessLogicRunTransaction extends BusinessLogicBase { }); } - onEvent(ledgerEvent: LedgerEvent, targetIndex: number): void { + onEvent(ledgerEvent: LedgerEvent): void { logger.debug(`##in BLP:onEvent()`); logger.debug(`##onEvent(): ${json2str(ledgerEvent)}`); } @@ -113,21 +108,18 @@ export class BusinessLogicRunTransaction extends BusinessLogicBase { // NOTE: This method implements the BisinessLogcPlugin operation(* Override by subclass) // TODO: logger.debug( - `##in getEventDataNum(), ledgerEvent: ${JSON.stringify(ledgerEvent)}` + `##in getEventDataNum(), ledgerEvent: ${JSON.stringify(ledgerEvent)}`, ); const retEventNum = ledgerEvent.data["blockData"].length; logger.debug(`##retEventNum: ${retEventNum}`); return retEventNum; } - getTxIDFromEvent( - ledgerEvent: LedgerEvent, - targetIndex: number - ): string | null { - // NOTE: This method implements the BisinessLogcPlugin operation(* Override by subclass) + getTxIDFromEvent(ledgerEvent: LedgerEvent): string | null { + // NOTE: This method implements the BusinessLogicPlugin operation(* Override by subclass) // TODO: logger.debug( - `##in getTxIDFromEvent(), ledgerEvent: ${JSON.stringify(ledgerEvent)}` + `##in getTxIDFromEvent(), ledgerEvent: ${JSON.stringify(ledgerEvent)}`, ); const txId = ledgerEvent.data["txId"]; @@ -135,8 +127,8 @@ export class BusinessLogicRunTransaction extends BusinessLogicBase { if (typeof txId !== "string") { logger.warn( `#getTxIDFromEvent(): skip(invalid block, not found txId.), event: ${json2str( - ledgerEvent - )}` + ledgerEvent, + )}`, ); return null; } diff --git a/examples/test-run-transaction/config/BLP_config.ts b/examples/test-run-transaction/config/BLP_config.ts index 8361e71771..f92543b002 100644 --- a/examples/test-run-transaction/config/BLP_config.ts +++ b/examples/test-run-transaction/config/BLP_config.ts @@ -9,7 +9,7 @@ import { BusinessLogicPlugin } from "../../../packages/cactus-cmd-socketio-serve import { BusinessLogicRunTransaction } from "../BusinessLogicRunTransaction"; export function getTargetBLPInstance( - businessLogicID: string + businessLogicID: string, ): BusinessLogicPlugin | null { switch (businessLogicID) { case "j71S9gLN": diff --git a/examples/test-run-transaction/copyBLPConfig.ts b/examples/test-run-transaction/copyBLPConfig.ts index 6a4e170641..c2e2d194d7 100644 --- a/examples/test-run-transaction/copyBLPConfig.ts +++ b/examples/test-run-transaction/copyBLPConfig.ts @@ -12,5 +12,5 @@ import * as shell from "shelljs"; // shell.cp('-R', 'src/routing-interface/views', 'dist/routing-interface/views/'); shell.cp( "../../dist/examples/test-run-transaction/config/BLP_config.js", - "../../dist/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/" + "../../dist/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/", ); diff --git a/examples/test-run-transaction/package.json b/examples/test-run-transaction/package.json index 517b0d7e03..9411e23e6e 100644 --- a/examples/test-run-transaction/package.json +++ b/examples/test-run-transaction/package.json @@ -35,14 +35,7 @@ "xmlhttprequest": "1.8.0" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", "@types/escape-html": "1.0.1", - "eslint": "7.32.0", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-prettier": "4.0.0", - "prettier": "2.8.8", - "tslint": "6.0.0", "typescript": "5.3.3" } } \ No newline at end of file diff --git a/examples/test-run-transaction/supply-chain-app-stub/app/routes/supply-chain-app.ts b/examples/test-run-transaction/supply-chain-app-stub/app/routes/supply-chain-app.ts index 9f531b36fd..ff03913771 100644 --- a/examples/test-run-transaction/supply-chain-app-stub/app/routes/supply-chain-app.ts +++ b/examples/test-run-transaction/supply-chain-app-stub/app/routes/supply-chain-app.ts @@ -40,9 +40,9 @@ router.post("/", (req: Request, res: Response, next: NextFunction) => { } }); -function sleep(waitSec: number, callbackFunc: any) { +function sleep(waitSec: number, callbackFunc: unknown) { let spanedSec = 0; - var id = setInterval(function () { + const id = setInterval(function () { spanedSec++; if (spanedSec >= waitSec) { clearInterval(id); diff --git a/package.json b/package.json index aac14862c4..835b09460b 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "purge-build-cache": "del-cli .build-cache/*", "clean": "npm run purge-build-cache && del-cli \"./{packages,examples,extensions}/cactus-*/{dist,.nyc_output,src/main/kotlin/generated/openapi/kotlin-client/*,src/main/proto/generated/*,src/main/typescript/generated/openapi/typescript-axios/*,src/main-server/kotlin/gen/kotlin-spring/src/**/{model,api}/*}\" \"!**/.openapi-generator-ignore\"", "lint": "yarn run format && yarn run spellcheck", - "format": "eslint '*/*/src/**/*.{js,ts}' --quiet --fix", + "format": "eslint '**/*.{js,ts}' --quiet --fix", "spellcheck": "cspell lint --no-progress \"*/*/src/**/*.{js,ts}\"", "tsc": "tsc --build --verbose", "codegen": "run-s 'codegen:warmup-*' codegen:lerna codegen:cleanup", @@ -76,7 +76,7 @@ "test:jest:all": "NODE_OPTIONS=\"--max_old_space_size=3072 --experimental-vm-modules\" jest", "test:tap:all": "NODE_OPTIONS=\"--experimental-vm-modules\" tap", "test:all": "NODE_OPTIONS=\"--experimental-vm-modules\" yarn test:jest:all && yarn test:tap:all", - "prettier": "prettier --write --config .prettierrc.js \"./**/src/main/json/openapi.json\"", + "prettier": "prettier --write --config .prettierrc.js \"./**/{openapi.json,*.ts,*.js}\"", "lerna-publish-canary": "lerna publish --canary --force-publish --dist-tag $(git branch --show-current) --preid $(git branch --show-current) --loglevel=silly --ignore-scripts --ignore-prepublish", "prepare": "husky install", "init-registries": "npm config set @iroha2:registry=https://nexus.iroha.tech/repository/npm-group/" @@ -187,7 +187,6 @@ "web3-eth": "4.1.1", "web3-utils": "4.0.5", "webpack": "5.88.2", - "webpack-bundle-analyzer": "4.9.0", "webpack-cli": "4.10.0", "wget-improved": "3.4.0", "yargs": "17.7.2" diff --git a/packages/cacti-ledger-browser-react/package.json b/packages/cacti-ledger-browser-react/package.json index 62b9ff04ba..6d6a630f49 100644 --- a/packages/cacti-ledger-browser-react/package.json +++ b/packages/cacti-ledger-browser-react/package.json @@ -72,12 +72,7 @@ "@types/react": "18.2.43", "@types/react-dom": "18.2.17", "@types/sort-by": "1", - "@typescript-eslint/eslint-plugin": "6.14.0", - "@typescript-eslint/parser": "6.14.0", "@vitejs/plugin-react": "4.2.1", - "eslint": "8.55.0", - "eslint-plugin-react-hooks": "4.6.0", - "eslint-plugin-react-refresh": "0.4.5", "typescript": "5.2.2", "vite": "5.0.12" } diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BLP_config.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BLP_config.ts index 2eb3dbf3fb..1e47e669f4 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BLP_config.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BLP_config.ts @@ -8,7 +8,7 @@ import { BusinessLogicPlugin } from "./BusinessLogicPlugin"; // Singleton of BLPs -let _blpMapping = new Map(); +const _blpMapping = new Map(); export function getTargetBLPInstance( businessLogicID: string, @@ -23,8 +23,6 @@ export function setTargetBLPInstance( _blpMapping.set(businessLogicID, blp); } -export function deleteTargetBLPInstance( - businessLogicID: string, -) { +export function deleteTargetBLPInstance(businessLogicID: string) { return _blpMapping.delete(businessLogicID); } diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BusinessLogicBase.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BusinessLogicBase.ts index 1727958610..d3a486b0eb 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BusinessLogicBase.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/business-logic-plugin/BusinessLogicBase.ts @@ -25,7 +25,7 @@ export class BusinessLogicBase implements BusinessLogicPlugin { startTransaction( req: Request, businessLogicID: string, - tradeID: string + tradeID: string, ): void { // NOTE: This method implements the BisinessLogcPlugin operation(* Override by subclass) } @@ -66,7 +66,7 @@ export class BusinessLogicBase implements BusinessLogicPlugin { this.eventFilter = filter; logger.debug( - `##called setEventFilter(after): ${json2str(this.eventFilter)}` + `##called setEventFilter(after): ${json2str(this.eventFilter)}`, ); } @@ -77,7 +77,7 @@ export class BusinessLogicBase implements BusinessLogicPlugin { getTxIDFromEvent( ledgerEvent: LedgerEvent, - targetIndex: number + targetIndex: number, ): string | null { // NOTE: This method implements the BisinessLogcPlugin operation(* Override by subclass) return null; diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/public-api.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/public-api.ts index d987ec775d..c0e2ac630d 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/public-api.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/public-api.ts @@ -2,7 +2,7 @@ export { Verifier } from "./verifier/Verifier"; export { LedgerEvent } from "./verifier/LedgerPlugin"; export { json2str } from "./verifier/DriverCommon"; -export { signMessageJwt } from './verifier/validator-authentication'; +export { signMessageJwt } from "./verifier/validator-authentication"; // Routing Interface export { RIFError } from "./routing-interface/RIFError"; diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/CactusSocketIOServer.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/CactusSocketIOServer.ts index f4f3166f93..675306b999 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/CactusSocketIOServer.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/CactusSocketIOServer.ts @@ -29,17 +29,20 @@ export type BLPConfig = { plugin: BusinessLogicPlugin; }; -export function startCactusSocketIOServer(blp?: BLPConfig | BLPConfig[], onListening?: () => void) { +export function startCactusSocketIOServer( + blp?: BLPConfig | BLPConfig[], + onListening?: () => void, +) { if (blp) { - // Support both single and multiple BLPs - if(!Array.isArray(blp)) { - blp = [blp]; - } + // Support both single and multiple BLPs + if (!Array.isArray(blp)) { + blp = [blp]; + } - blp.forEach((cfg) => { - logger.info("Using BLP with id =", cfg.id); - setTargetBLPInstance(cfg.id, cfg.plugin); - }); + blp.forEach((cfg) => { + logger.info("Using BLP with id =", cfg.id); + setTargetBLPInstance(cfg.id, cfg.plugin); + }); } runExpressApp(); @@ -102,7 +105,7 @@ export function startCactusSocketIOServer(blp?: BLPConfig | BLPConfig[], onListe } else { throw new Error("Could not get server address!"); } - } + }; } /** diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/index.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/index.ts index 36544364fd..0018288100 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/index.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/routes/index.ts @@ -11,7 +11,8 @@ import { VerifierFactory } from "../../verifier/VerifierFactory"; import escapeHtml from "escape-html"; const router: Router = Router(); -export const transactionManagement: TransactionManagement = new TransactionManagement(); +export const transactionManagement: TransactionManagement = + new TransactionManagement(); export const verifierFactory: VerifierFactory = new VerifierFactory( transactionManagement, ); @@ -100,9 +101,9 @@ router.delete( "/api/v1/bl/wallets/:id", (req: Request, res: Response, next: NextFunction) => { try { - res.render( - "Not Implemented (Delete a Wallet" + ", id=" + escapeHtml(req.params.id) + ")\n", - ); + const walletIdEsc = escapeHtml(req.params.id); + const out = "Not Implemented (Delete a Wallet, id=" + walletIdEsc + ")\n"; + res.status(501).send(out); } catch (err) { next(err); } diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/BLPRegistry.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/BLPRegistry.ts index 5a864c96d6..c5216e1b93 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/BLPRegistry.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/BLPRegistry.ts @@ -34,7 +34,7 @@ export class BLPRegistry { }); if (ret === "") { logger.warn( - "BLPRegistryInfo is Not Found : businessLogicId = " + businessLogicId + "BLPRegistryInfo is Not Found : businessLogicId = " + businessLogicId, ); } return ret; diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts index 5590d1e946..b55575c21d 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ConfigUtil.ts @@ -10,11 +10,9 @@ const yaml = require("js-yaml"); function readConfig(path: string, encoding = "utf8"): object { try { - return yaml.safeLoad( - fs.readFileSync(path, encoding) - ); + return yaml.safeLoad(fs.readFileSync(path, encoding)); } catch (err: unknown) { - return {} + return {}; } } diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ContractInfoHolder.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ContractInfoHolder.ts index 01e73fc2d1..ad24871eba 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ContractInfoHolder.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/ContractInfoHolder.ts @@ -37,7 +37,7 @@ export class ContractInfoHolder { }); if (ret === "") { logger.warn( - "ContractInfo is Not Found : contractName = " + contractName + "ContractInfo is Not Found : contractName = " + contractName, ); } return ret; diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/DBAccess.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/DBAccess.ts index 3f31387625..324de11af3 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/DBAccess.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/DBAccess.ts @@ -32,7 +32,7 @@ export class DBAccess { getLedgerPluginInfo(): LedgerPluginInfo[] { try { const configVerifier: ValidatorRegistry = new ValidatorRegistry( - path.resolve(__dirname, "/etc/cactus/validator-registry-config.yaml") + path.resolve(__dirname, "/etc/cactus/validator-registry-config.yaml"), ); this.ledgerPluginInfo = configVerifier.ledgerPluginInfo; } catch (error) { @@ -46,7 +46,7 @@ export class DBAccess { getContractInfo(): [] { try { const configContract: any = yaml.safeLoad( - fs.readFileSync("/etc/cactus/contractInfo.yaml", "utf8") + fs.readFileSync("/etc/cactus/contractInfo.yaml", "utf8"), ); this.contractInfo = configContract.contractInfo; diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/LPInfoHolder.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/LPInfoHolder.ts index 9f97249687..98d7b21ab1 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/LPInfoHolder.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/routing-interface/util/LPInfoHolder.ts @@ -38,7 +38,7 @@ export class LPInfoHolder { }); if (ret === "") { logger.warn( - "LegerPluginInfo is Not Found : validatorId = " + validatorId + "LegerPluginInfo is Not Found : validatorId = " + validatorId, ); } return ret; diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/util/config.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/util/config.ts index bc7e328b90..f8030e00b4 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/util/config.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/util/config.ts @@ -8,7 +8,6 @@ * config.js */ - import config from "config"; /** diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts index 093b0e6bc4..59c73f7618 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/DriverCommon.ts @@ -24,4 +24,4 @@ export function json2str(jsonObj: unknown) { logger.warn("invalid json format."); return null; } -} \ No newline at end of file +} diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/LedgerPlugin.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/LedgerPlugin.ts index a27e182cf4..553a33625b 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/LedgerPlugin.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/LedgerPlugin.ts @@ -20,4 +20,3 @@ export class RequestedData { dataName = ""; dataType = ""; } - diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts index 7a23254a9a..527f67fe9b 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/Verifier.ts @@ -33,7 +33,7 @@ const VALIDATOR_TYPE = { SOCKET: "socketio", OPENAPI: "openapi", } as const; -type VALIDATOR_TYPE = typeof VALIDATOR_TYPE[keyof typeof VALIDATOR_TYPE]; // 'socketio' | 'openapi' +type VALIDATOR_TYPE = (typeof VALIDATOR_TYPE)[keyof typeof VALIDATOR_TYPE]; // 'socketio' | 'openapi' // abolish template-trade // const validatorRregistryConf: any = yaml.safeLoad(fs.readFileSync("/etc/cactus/validator-registry.yaml", 'utf8')); diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierFactory.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierFactory.ts index 7330afed42..4580dc212d 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierFactory.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/VerifierFactory.ts @@ -36,9 +36,8 @@ export class VerifierFactory { if (VerifierFactory.verifierHash[validatorId]) { return VerifierFactory.verifierHash[validatorId]; } else { - const ledgerPluginInfo: string = this.connectInfo.getLegerPluginInfo( - validatorId, - ); + const ledgerPluginInfo: string = + this.connectInfo.getLegerPluginInfo(validatorId); // TODO: I want to manage an instance using the validatorId as a key instead of a dedicated member variable VerifierFactory.verifierHash[validatorId] = new Verifier( ledgerPluginInfo, diff --git a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/validator-authentication.ts b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/validator-authentication.ts index a07918157a..0fde312c5c 100644 --- a/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/validator-authentication.ts +++ b/packages/cactus-cmd-socketio-server/src/main/typescript/verifier/validator-authentication.ts @@ -33,7 +33,7 @@ let privateKey: string; * @param expirationTime - JWT expiration time * @returns JWT signed message that can be sent over the wire. */ - export function signValidatorMessageJwt( +export function signValidatorMessageJwt( privateKey: jwt.Secret, payload: PayloadType, jwtAlgo: jwt.Algorithm = "ES256", @@ -75,11 +75,11 @@ let privateKey: string; export function signMessageJwt(payload: object): string { if (!privateKey) { try { - privateKey = configRead('sslParam.keyValue'); + privateKey = configRead("sslParam.keyValue"); } catch { - privateKey = fs.readFileSync(configRead('sslParam.key'), "ascii"); + privateKey = fs.readFileSync(configRead("sslParam.key"), "ascii"); } } - const jwtAlgo = configRead('sslParam.jwtAlgo', 'ES256'); + const jwtAlgo = configRead("sslParam.jwtAlgo", "ES256"); return signValidatorMessageJwt(privateKey, payload, jwtAlgo); } diff --git a/packages/cactus-cmd-socketio-server/src/test/typescript/unit/Verifier.test.ts b/packages/cactus-cmd-socketio-server/src/test/typescript/unit/Verifier.test.ts index 655472285e..73bf20c214 100644 --- a/packages/cactus-cmd-socketio-server/src/test/typescript/unit/Verifier.test.ts +++ b/packages/cactus-cmd-socketio-server/src/test/typescript/unit/Verifier.test.ts @@ -172,10 +172,8 @@ describe("SocketIO Validator Tests", function () { let sut: Verifier; beforeAll(async () => { - [ - testServer, - testServerPort, - ] = await SocketIOTestSetupHelpers.createListeningMockServer(); + [testServer, testServerPort] = + await SocketIOTestSetupHelpers.createListeningMockServer(); }, setupTimeout); afterAll((done) => { @@ -230,7 +228,7 @@ describe("SocketIO Validator Tests", function () { }); test("Sends request2 with valid arguments", () => { - let reqReceived = new Promise((resolve) => { + const reqReceived = new Promise((resolve) => { serverSocket.on("request2", (req: any) => resolve(req)); }); @@ -417,7 +415,9 @@ describe("SocketIO Validator Tests", function () { }; // Two listeners - const listenerMockFirst: IVerifierEventListener = { onEvent: onEventMock }; + const listenerMockFirst: IVerifierEventListener = { + onEvent: onEventMock, + }; const listenerMockSecond: IVerifierEventListener = { onEvent: onEventMock, }; @@ -540,7 +540,7 @@ describe("SocketIO Validator Tests", function () { }, setupTimeout); test("Sends request2 with valid args for socketio verifier", () => { - let reqReceived = new Promise((resolve) => { + const reqReceived = new Promise((resolve) => { serverSocket.on("request2", (req: any) => resolve(req)); }); diff --git a/packages/cactus-cmd-socketio-server/src/test/typescript/unit/VerifierFactory.test.ts b/packages/cactus-cmd-socketio-server/src/test/typescript/unit/VerifierFactory.test.ts index 641588289e..d56e904ea7 100644 --- a/packages/cactus-cmd-socketio-server/src/test/typescript/unit/VerifierFactory.test.ts +++ b/packages/cactus-cmd-socketio-server/src/test/typescript/unit/VerifierFactory.test.ts @@ -29,11 +29,11 @@ const log: Logger = LoggerProvider.getOrCreate({ jest.mock("fs"); import { LPInfoHolder } from "../../../main/typescript/routing-interface/util/LPInfoHolder"; jest.mock("../../../main/typescript/routing-interface/util/LPInfoHolder"); -const mockLedgerData = "{mockLedgerData}" +const mockLedgerData = "{mockLedgerData}"; const mockGetLegerPluginInfo = jest.fn().mockReturnValue(mockLedgerData); (LPInfoHolder as jest.Mock).mockImplementation(() => { return { - getLegerPluginInfo: mockGetLegerPluginInfo + getLegerPluginInfo: mockGetLegerPluginInfo, }; }); @@ -112,4 +112,4 @@ describe("VerifierFactory getVerifier tests", () => { expect(Object.keys(VerifierFactory.verifierHash).length).toBe(2); expect(newVerifierAgain).toBe(newVerifier); }); -}); \ No newline at end of file +}); diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/basic-asset-transfer/chaincode-javascript/package.json b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/basic-asset-transfer/chaincode-javascript/package.json index 3b9135c342..6bc5f122b6 100644 --- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/basic-asset-transfer/chaincode-javascript/package.json +++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/fixtures/go/basic-asset-transfer/chaincode-javascript/package.json @@ -16,31 +16,5 @@ "dependencies": { "fabric-contract-api": "2.2.2", "fabric-shim": "2.2.2" - }, - "devDependencies": { - "chai": "4.3.6", - "eslint": "4.19.1", - "mocha": "8.4.0", - "nyc": "14.1.1", - "sinon": "6.3.5", - "sinon-chai": "3.7.0" - }, - "nyc": { - "exclude": [ - "coverage/**", - "test/**", - "index.js", - ".eslintrc.js" - ], - "reporter": [ - "text-summary", - "html" - ], - "all": true, - "check-coverage": true, - "statements": 100, - "branches": 100, - "functions": 100, - "lines": 100 } } diff --git a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/app.ts b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/app.ts index b86a7e295f..ff72979cc3 100644 --- a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/app.ts +++ b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/app.ts @@ -32,7 +32,7 @@ app.use( err: { message: string; status?: number }, req: Request, res: Response, - next: NextFunction + next: NextFunction, ) => { // set locals, only providing error in development res.locals.message = err.message; @@ -47,7 +47,7 @@ app.use( // render the error page res.status(err.status || 500); res.send(errorResponse); - } + }, ); export default app; diff --git a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/bin/www.ts b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/bin/www.ts index 832147b51f..a69f3e3a34 100644 --- a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/bin/www.ts +++ b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/common/core/bin/www.ts @@ -160,7 +160,7 @@ export async function startGoEthereumSocketIOConnector() { // TODO: "request2" -> "request" client.on("request2", function (data) { const methodType = data.method.type; - let args: Record = { + const args: Record = { contract: data.contract, method: data.method, args: data.args, diff --git a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/PluginUtil.ts b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/PluginUtil.ts index b8864e193f..259b9af065 100644 --- a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/PluginUtil.ts +++ b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/PluginUtil.ts @@ -67,4 +67,4 @@ export function convNum(value: number | string, defaultValue: number | string) { } return retValue; -}; +} diff --git a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts index 56be15efe8..d4b78125ec 100644 --- a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts +++ b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts @@ -131,7 +131,7 @@ export class ServerMonitorPlugin { */ async stopMonitor(clientId: string) { // Implement a process to end EC monitoring - let sub = this._subscriptionTable.get(clientId); + const sub = this._subscriptionTable.get(clientId); if (sub) { // Stop the subscription & Remove it from table logger.info("stop watching and remove subscription."); diff --git a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerPlugin.ts b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerPlugin.ts index a385369245..d4fcb4b078 100644 --- a/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerPlugin.ts +++ b/packages/cactus-plugin-ledger-connector-go-ethereum-socketio/src/main/typescript/connector/ServerPlugin.ts @@ -629,7 +629,7 @@ export class ServerPlugin { ); } - let result = await looseWeb3Eth[sendFunction](...sendArgs); + const result = await looseWeb3Eth[sendFunction](...sendArgs); const signedResults = signMessageJwt({ result: result }); const retObj = { diff --git a/packages/cactus-plugin-ledger-connector-polkadot/package.json b/packages/cactus-plugin-ledger-connector-polkadot/package.json index b1dbb7c135..d21bc55634 100644 --- a/packages/cactus-plugin-ledger-connector-polkadot/package.json +++ b/packages/cactus-plugin-ledger-connector-polkadot/package.json @@ -72,7 +72,6 @@ "@polkadot/types": "10.9.1", "@polkadot/util": "12.6.2", "bl": "5.0.0", - "eslint": "7.21.0", "express": "4.17.1", "express-openapi-validator": "4.13.1", "form-data": "4.0.0", diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json b/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json index 6a41999fa3..2220437deb 100644 --- a/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json @@ -11,560 +11,526 @@ }, "components": { "schemas": { - "PrometheusExporterMetricsResponse": { - "type": "string", - "nullable": false - }, - "TransactionInfoRequest": { - "type": "object", - "required": [ - "accountAddress", - "transactionExpiration" - ], - "additionalProperties": false, - "properties": { - "accountAddress": { - "type": "string", - "nullable": false - }, - "transactionExpiration":{ - "type": "number", - "nullable": true - } + "PrometheusExporterMetricsResponse": { + "type": "string", + "nullable": false + }, + "TransactionInfoRequest": { + "type": "object", + "required": ["accountAddress", "transactionExpiration"], + "additionalProperties": false, + "properties": { + "accountAddress": { + "type": "string", + "nullable": false + }, + "transactionExpiration": { + "type": "number", + "nullable": true } - }, - "TransactionInfoResponseData": { - "type": "object", - "required": [ - "nonce", - "blockHash", - "era" - ], - "additionalProperties": false, - "properties": { - "nonce": { - "type": "object", - "nullable": false - }, - "blockHash": { - "type": "object", - "nullable": false - }, - "era": { - "type": "object", - "nullable": true - } + } + }, + "TransactionInfoResponseData": { + "type": "object", + "required": ["nonce", "blockHash", "era"], + "additionalProperties": false, + "properties": { + "nonce": { + "type": "object", + "nullable": false + }, + "blockHash": { + "type": "object", + "nullable": false + }, + "era": { + "type": "object", + "nullable": true } - }, - "TransactionInfoResponse": { - "type": "object", - "required": [ - "responseContainer" - ], - "additionalProperties": false, - "properties": { - "responseContainer": { - "type": "object", - "required": [ - "response_data", - "succeeded", - "message", - "error" - ], - "additionalProperties": false, - "properties": { - "response_data": { - "$ref": "#/components/schemas/TransactionInfoResponseData", - "nullable": false - }, - "succeeded": { - "type": "boolean", - "nullable": false - }, - "message": { - "type": "string", - "nullable": false - }, - "error": { - "type": "string", - "nullable": true - } + } + }, + "TransactionInfoResponse": { + "type": "object", + "required": ["responseContainer"], + "additionalProperties": false, + "properties": { + "responseContainer": { + "type": "object", + "required": ["response_data", "succeeded", "message", "error"], + "additionalProperties": false, + "properties": { + "response_data": { + "$ref": "#/components/schemas/TransactionInfoResponseData", + "nullable": false + }, + "succeeded": { + "type": "boolean", + "nullable": false + }, + "message": { + "type": "string", + "nullable": false + }, + "error": { + "type": "string", + "nullable": true } } } - }, - "RawTransactionRequest": { - "type": "object", - "required": ["to", "value"], - "additionalProperties": false, - "properties": { - "to": { - "type": "string", - "nullable": false - }, - "value": { - "type": "number", - "nullable": false - } + } + }, + "RawTransactionRequest": { + "type": "object", + "required": ["to", "value"], + "additionalProperties": false, + "properties": { + "to": { + "type": "string", + "nullable": false + }, + "value": { + "type": "number", + "nullable": false } - }, - "RawTransactionResponseData": { - "type": "object", - "required": [ - "rawTransaction" - ], - "additionalProperties": false, - "properties": { - "rawTransaction": { - "type": "string", - "nullable": false - } + } + }, + "RawTransactionResponseData": { + "type": "object", + "required": ["rawTransaction"], + "additionalProperties": false, + "properties": { + "rawTransaction": { + "type": "string", + "nullable": false } - }, - "RawTransactionResponse": { - "type": "object", - "required": ["responseContainer"], - "additionalProperties": false, - "properties": { - "responseContainer": { - "type": "object", - "required": [ - "response_data", - "succeeded", - "message", - "error" - ], - "additionalProperties": false, - "properties": { - "response_data": { - "$ref": "#/components/schemas/RawTransactionResponseData", - "nullable": false - }, - "succeeded": { - "type": "boolean", - "nullable": false - }, - "message": { - "type": "string", - "nullable": false - }, - "error": { - "type": "string", - "nullable": true - } + } + }, + "RawTransactionResponse": { + "type": "object", + "required": ["responseContainer"], + "additionalProperties": false, + "properties": { + "responseContainer": { + "type": "object", + "required": ["response_data", "succeeded", "message", "error"], + "additionalProperties": false, + "properties": { + "response_data": { + "$ref": "#/components/schemas/RawTransactionResponseData", + "nullable": false + }, + "succeeded": { + "type": "boolean", + "nullable": false + }, + "message": { + "type": "string", + "nullable": false + }, + "error": { + "type": "string", + "nullable": true } } } - }, - "SignRawTransactionRequest": { - "type": "object", - "required": ["rawTransaction", "mnemonic"], - "additionalProperties": false, - "properties": { - "rawTransaction": { - "type": "string", - "nullable": false - }, - "mnemonic": { - "type": "string", - "nullable": false - }, - "signingOptions": { - "type": "object", - "nullable": false - } + } + }, + "SignRawTransactionRequest": { + "type": "object", + "required": ["rawTransaction", "mnemonic"], + "additionalProperties": false, + "properties": { + "rawTransaction": { + "type": "string", + "nullable": false + }, + "mnemonic": { + "type": "string", + "nullable": false + }, + "signingOptions": { + "type": "object", + "nullable": false } - }, - "SignRawTransactionResponse": { - "type": "object", - "required": ["success", "signedTransaction"], - "additionalProperties": false, - "properties": { - "success": { - "type": "boolean", - "nullable": false - }, - "signedTransaction": { - "type": "string", - "nullable": false - } + } + }, + "SignRawTransactionResponse": { + "type": "object", + "required": ["success", "signedTransaction"], + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean", + "nullable": false + }, + "signedTransaction": { + "type": "string", + "nullable": false } - }, - "web3SigningCredential": { - "type": "object", - "required": ["type"], - "discriminator": { - "propertyName": "type" - }, - "oneOf": [ - { - "$ref": "#/components/schemas/Web3SigningCredentialCactusKeychainRef" - }, - { - "$ref": "#/components/schemas/Web3SigningCredentialMnemonicString" - }, - { - "$ref": "#/components/schemas/Web3SigningCredentialNone" - } - ], - "properties": { - "type": { - "$ref": "#/components/schemas/Web3SigningCredentialType" - } + } + }, + "web3SigningCredential": { + "type": "object", + "required": ["type"], + "discriminator": { + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/Web3SigningCredentialCactusKeychainRef" + }, + { + "$ref": "#/components/schemas/Web3SigningCredentialMnemonicString" + }, + { + "$ref": "#/components/schemas/Web3SigningCredentialNone" } - }, - "Web3SigningCredentialCactusKeychainRef": { - "type": "object", - "required": ["type", "ethAccount", "keychainId", "keychainEntryKey"], - "properties": { - "type": { - "$ref": "#/components/schemas/Web3SigningCredentialType" - }, - "keychainEntryKey": { - "type": "string", - "description": "The key to use when looking up the the keychain entry holding the secret pointed to by the keychainEntryKey parameter.", - "minLength": 0, - "maxLength": 1024 - }, - "keychainId": { - "type": "string", - "description": "The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter.", - "minLength": 0, - "maxLength": 1024 - } + ], + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" } - }, - "Web3SigningCredentialMnemonicString": { - "type": "object", - "required": ["type", "mnemonic"], - "properties": { - "type": { - "$ref": "#/components/schemas/Web3SigningCredentialType" - }, - "mnemonic": { - "type": "string", - "description": "The Polkadot account's seed phrase for signing transaction", - "nullable": false - } + } + }, + "Web3SigningCredentialCactusKeychainRef": { + "type": "object", + "required": ["type", "ethAccount", "keychainId", "keychainEntryKey"], + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" + }, + "keychainEntryKey": { + "type": "string", + "description": "The key to use when looking up the the keychain entry holding the secret pointed to by the keychainEntryKey parameter.", + "minLength": 0, + "maxLength": 1024 + }, + "keychainId": { + "type": "string", + "description": "The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter.", + "minLength": 0, + "maxLength": 1024 } - }, - "Web3SigningCredentialNone": { - "type": "object", - "required": ["type"], - "description": "Using this denotes that there is no signing required because the transaction is pre-signed.", - "properties": { - "type": { - "$ref": "#/components/schemas/Web3SigningCredentialType" - } + } + }, + "Web3SigningCredentialMnemonicString": { + "type": "object", + "required": ["type", "mnemonic"], + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" + }, + "mnemonic": { + "type": "string", + "description": "The Polkadot account's seed phrase for signing transaction", + "nullable": false } - }, - "Web3SigningCredentialType": { - "type": "string", - "enum": [ - "CACTUS_KEYCHAIN_REF", - "MNEMONIC_STRING", - "NONE" - ] - }, - "PolkadotTransactionConfig": { - "type": "object", - "additionalProperties": true, - "properties": { - "transferSubmittable": { - "oneOf": [ - { - "type": "string" - } - ] - }, - "to": { - "oneOf": [ - { - "type": "string" - } - ] - }, - "value": { - "oneOf": [ - { - "type": "number" - } - ] - } + } + }, + "Web3SigningCredentialNone": { + "type": "object", + "required": ["type"], + "description": "Using this denotes that there is no signing required because the transaction is pre-signed.", + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" } - }, - "RunTransactionRequest": { - "type": "object", - "required": [ - "web3SigningCredential", "transactionConfig" - ], - "additionalProperties": false, - "properties": { - "web3SigningCredential": { - "$ref": "#/components/schemas/web3SigningCredential", - "nullable": false - }, - "transactionConfig": { - "$ref": "#/components/schemas/PolkadotTransactionConfig", - "nullable": false - } } }, - "RunTransactionResponse": { - "type": "object", - "required": [ - "success" - ], - "additionalProperties": false, - "properties": { - "success": { - "type": "boolean", - "nullable": false - }, - "txHash": { - "type": "string", - "nullable": false - }, - "blockHash": { - "type": "string", - "nullable": false - } + "Web3SigningCredentialType": { + "type": "string", + "enum": ["CACTUS_KEYCHAIN_REF", "MNEMONIC_STRING", "NONE"] + }, + "PolkadotTransactionConfig": { + "type": "object", + "additionalProperties": true, + "properties": { + "transferSubmittable": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "to": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "value": { + "oneOf": [ + { + "type": "number" + } + ] } - }, - "DeployContractInkRequest": { - "type": "object", - "required": [ - "web3SigningCredential", - "wasm", - "metadata", - "gasLimit" - ], - "additionalProperties": false, - "properties": { - "web3SigningCredential": { - "$ref": "#/components/schemas/web3SigningCredential", - "nullable": false - }, - "wasm": { - "description": "raw wasm for the compiled contract in base64 format", - "type": "string", - "format": "byte", - "nullable": false - }, - "constructorMethod": { - "oneOf": [ - { - "type": "string" - } - ] - }, - "metadata": { - "oneOf": [ - { - "type": "string" - } - ] - }, - "gasLimit": { - "type": "object", - "required": ["refTime", "proofSize"], - "properties": { - "refTime": { - "type": "integer", - "minimum": 0 - }, - "proofSize": { - "type": "integer", - "minimum": 0 - } + } + }, + "RunTransactionRequest": { + "type": "object", + "required": ["web3SigningCredential", "transactionConfig"], + "additionalProperties": false, + "properties": { + "web3SigningCredential": { + "$ref": "#/components/schemas/web3SigningCredential", + "nullable": false + }, + "transactionConfig": { + "$ref": "#/components/schemas/PolkadotTransactionConfig", + "nullable": false + } + } + }, + "RunTransactionResponse": { + "type": "object", + "required": ["success"], + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean", + "nullable": false + }, + "txHash": { + "type": "string", + "nullable": false + }, + "blockHash": { + "type": "string", + "nullable": false + } + } + }, + "DeployContractInkRequest": { + "type": "object", + "required": ["web3SigningCredential", "wasm", "metadata", "gasLimit"], + "additionalProperties": false, + "properties": { + "web3SigningCredential": { + "$ref": "#/components/schemas/web3SigningCredential", + "nullable": false + }, + "wasm": { + "description": "raw wasm for the compiled contract in base64 format", + "type": "string", + "format": "byte", + "nullable": false + }, + "constructorMethod": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "metadata": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "gasLimit": { + "type": "object", + "required": ["refTime", "proofSize"], + "properties": { + "refTime": { + "type": "integer", + "minimum": 0 + }, + "proofSize": { + "type": "integer", + "minimum": 0 } - }, - "storageDepositLimit": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "minimum": 0 - } - ], - "nullable": true - }, - "params": { - "description": "The list of arguments to pass in to the contract method being deployed", - "type": "array", - "default": [], - "items": {} - }, - "balance": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "minimum": 0 - } - ] - }, - "salt": { - "oneOf": [ - { - "type": "string" - } - ], - "nullable": true } + }, + "storageDepositLimit": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ], + "nullable": true + }, + "params": { + "description": "The list of arguments to pass in to the contract method being deployed", + "type": "array", + "default": [], + "items": {} + }, + "balance": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ] + }, + "salt": { + "oneOf": [ + { + "type": "string" + } + ], + "nullable": true } - }, - "DeployContractInkResponse": { - "type": "object", - "required": ["success"], - "additionalProperties": false, - "properties": { - "success": { - "type": "boolean", - "nullable": false - }, - "contractAddress": { - "type": "string", - "nullable": false - } + } + }, + "DeployContractInkResponse": { + "type": "object", + "required": ["success"], + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean", + "nullable": false + }, + "contractAddress": { + "type": "string", + "nullable": false } - }, - "PolkadotContractInvocationType": { - "type": "string", - "enum": ["SEND", "QUERY"] - }, - "InvokeContractRequest": { - "type": "object", - "required": [ - "invocationType", - "metadata", - "contractAddress", - "methodName", - "gasLimit", - "accountAddress", - "web3SigningCredential" - ], - "additionalProperties": false, - "properties": { - "invocationType": { - "$ref": "#/components/schemas/PolkadotContractInvocationType", - "nullable": false, - "description": "Indicates whether it is a QUERY or a SEND type of invocation where only SEND ends up creating an actual transaction on the ledger." - }, - "accountAddress": { - "type": "string", - "nullable": false - }, - "web3SigningCredential": { - "$ref": "#/components/schemas/web3SigningCredential", - "nullable": false - }, - "metadata": { - "oneOf": [ - { - "type": "string" - } - ] - }, - "contractAddress": { - "type": "string", - "nullable": false - }, - "methodName": { - "description": "The name of the contract method to invoke.", - "type": "string", - "nullable": false, - "minLength": 1, - "maxLength": 2048 - }, - "gasLimit": { - "type": "object", - "required": ["refTime", "proofSize"], - "properties": { - "refTime": { - "type": "integer", - "minimum": 0 - }, - "proofSize": { - "type": "integer", - "minimum": 0 - } + } + }, + "PolkadotContractInvocationType": { + "type": "string", + "enum": ["SEND", "QUERY"] + }, + "InvokeContractRequest": { + "type": "object", + "required": [ + "invocationType", + "metadata", + "contractAddress", + "methodName", + "gasLimit", + "accountAddress", + "web3SigningCredential" + ], + "additionalProperties": false, + "properties": { + "invocationType": { + "$ref": "#/components/schemas/PolkadotContractInvocationType", + "nullable": false, + "description": "Indicates whether it is a QUERY or a SEND type of invocation where only SEND ends up creating an actual transaction on the ledger." + }, + "accountAddress": { + "type": "string", + "nullable": false + }, + "web3SigningCredential": { + "$ref": "#/components/schemas/web3SigningCredential", + "nullable": false + }, + "metadata": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "contractAddress": { + "type": "string", + "nullable": false + }, + "methodName": { + "description": "The name of the contract method to invoke.", + "type": "string", + "nullable": false, + "minLength": 1, + "maxLength": 2048 + }, + "gasLimit": { + "type": "object", + "required": ["refTime", "proofSize"], + "properties": { + "refTime": { + "type": "integer", + "minimum": 0 + }, + "proofSize": { + "type": "integer", + "minimum": 0 } - }, - "storageDepositLimit": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "minimum": 0 - } - ], - "nullable": true - }, - "balance": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "integer", - "minimum": 0 - } - ] - }, - "params": { - "description": "The list of arguments to pass in to the contract method being invoked", - "type": "array", - "default": [], - "items": {} } + }, + "storageDepositLimit": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ], + "nullable": true + }, + "balance": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ] + }, + "params": { + "description": "The list of arguments to pass in to the contract method being invoked", + "type": "array", + "default": [], + "items": {} } - }, - "InvokeContractResponse": { - "type": "object", - "required": ["success"], - "properties": { - "callOutput": {}, - "success": { - "type": "boolean", - "nullable": false - }, - "txHash": { - "type": "string", - "nullable": false - }, - "blockHash": { - "type": "string", - "nullable": false - } + } + }, + "InvokeContractResponse": { + "type": "object", + "required": ["success"], + "properties": { + "callOutput": {}, + "success": { + "type": "boolean", + "nullable": false + }, + "txHash": { + "type": "string", + "nullable": false + }, + "blockHash": { + "type": "string", + "nullable": false } - }, - "ErrorExceptionResponse": { - "type": "object", - "description": "Error response from the connector.", - "required": ["message", "error"], - "properties": { - "message": { - "type": "string", - "description": "Short error description message.", - "nullable": false - }, - "error": { - "type": "string", - "description": "Detailed error information.", - "nullable": false - } + } + }, + "ErrorExceptionResponse": { + "type": "object", + "description": "Error response from the connector.", + "required": ["message", "error"], + "properties": { + "message": { + "type": "string", + "description": "Short error description message.", + "nullable": false + }, + "error": { + "type": "string", + "description": "Detailed error information.", + "nullable": false } } } - }, - "paths": { + } + }, + "paths": { "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-prometheus-exporter-metrics": { "get": { "x-hyperledger-cactus": { @@ -613,11 +579,11 @@ "parameters": [], "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TransactionInfoRequest" - } + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionInfoRequest" } + } } }, "responses": { @@ -657,11 +623,11 @@ "parameters": [], "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RawTransactionRequest" - } + "application/json": { + "schema": { + "$ref": "#/components/schemas/RawTransactionRequest" } + } } }, "responses": { @@ -701,11 +667,11 @@ "parameters": [], "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/SignRawTransactionRequest" - } + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignRawTransactionRequest" } + } } }, "responses": { @@ -745,11 +711,11 @@ "parameters": [], "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/RunTransactionRequest" - } + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunTransactionRequest" } + } } }, "responses": { @@ -789,11 +755,11 @@ "parameters": [], "requestBody": { "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/DeployContractInkRequest" - } + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployContractInkRequest" } + } } }, "responses": { @@ -865,4 +831,4 @@ } } } -} \ No newline at end of file +} diff --git a/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/common/core/bin/www.ts b/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/common/core/bin/www.ts index c4ad1b794e..62be3ba22d 100644 --- a/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/common/core/bin/www.ts +++ b/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/common/core/bin/www.ts @@ -19,7 +19,7 @@ import https = require("https"); import * as config from "../config"; import fs = require("fs"); - import { Server } from "socket.io" + import { Server } from "socket.io"; // Log settings import { getLogger } from "log4js"; diff --git a/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts b/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts index 5622b93bf8..81799d552d 100644 --- a/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts +++ b/packages/cactus-plugin-ledger-connector-tcs-huawei-socketio/src/main/typescript/connector/ServerMonitorPlugin.ts @@ -63,9 +63,9 @@ export class ServerMonitorPlugin { args: ["a"], }); //- (not recommended - only for development): Temporarily set CertCheck to false when using a self-signed certificate - var CertCheck = config.read("CertCheck") - if (CertCheck == undefined){ - CertCheck = true + let CertCheck = config.read("CertCheck"); + if (CertCheck == undefined) { + CertCheck = true; } const options: https.RequestOptions = { hostname: "agent", @@ -123,9 +123,9 @@ export class ServerMonitorPlugin { to_query_func_name: "GetBlockByNumber", args: [targetBlockNum.toString()], }); - var CertCheck = config.read("CertCheck") - if (CertCheck == undefined){ - CertCheck = true + let CertCheck = config.read("CertCheck"); + if (CertCheck == undefined) { + CertCheck = true; } const options: https.RequestOptions = { hostname: "agent", diff --git a/packages/cactus-plugin-satp-hermes/knex/knexfile-remote.ts b/packages/cactus-plugin-satp-hermes/knex/knexfile-remote.ts index 27e1209742..7966df074d 100644 --- a/packages/cactus-plugin-satp-hermes/knex/knexfile-remote.ts +++ b/packages/cactus-plugin-satp-hermes/knex/knexfile-remote.ts @@ -1,5 +1,4 @@ import path from "path"; -import { v4 as uuidv4 } from "uuid"; // default configuration for knex module.exports = { @@ -13,4 +12,4 @@ module.exports = { }, useNullAsDefault: true, }, -}; \ No newline at end of file +}; diff --git a/packages/cactus-plugin-satp-hermes/knex/migrations/20240130234303_create_remote_logs_table.js b/packages/cactus-plugin-satp-hermes/knex/migrations/20240130234303_create_remote_logs_table.js index 4eac46af46..50625d7833 100644 --- a/packages/cactus-plugin-satp-hermes/knex/migrations/20240130234303_create_remote_logs_table.js +++ b/packages/cactus-plugin-satp-hermes/knex/migrations/20240130234303_create_remote_logs_table.js @@ -1,13 +1,13 @@ exports.up = async (knex) => { - return await knex.schema.createTable("remote-logs", function (table) { - table.string("key").notNullable(); - table.string("hash").notNullable(); - table.string("signature").notNullable(); - table.string("signerPubKey").notNullable(); - table.primary("key") - }); - }; + return await knex.schema.createTable("remote-logs", function (table) { + table.string("key").notNullable(); + table.string("hash").notNullable(); + table.string("signature").notNullable(); + table.string("signerPubKey").notNullable(); + table.primary("key"); + }); +}; - exports.down = async (knex) => { - return await knex.schema.dropTable("remote-logs"); - }; +exports.down = async (knex) => { + return await knex.schema.dropTable("remote-logs"); +}; diff --git a/packages/cactus-test-plugin-htlc-eth-besu-erc20/src/test/typescript/integration/plugin-htlc-eth-besu-erc20/openapi/openapi-validation.test.ts b/packages/cactus-test-plugin-htlc-eth-besu-erc20/src/test/typescript/integration/plugin-htlc-eth-besu-erc20/openapi/openapi-validation.test.ts index 4e3f8b4bd4..7bef6a2706 100644 --- a/packages/cactus-test-plugin-htlc-eth-besu-erc20/src/test/typescript/integration/plugin-htlc-eth-besu-erc20/openapi/openapi-validation.test.ts +++ b/packages/cactus-test-plugin-htlc-eth-besu-erc20/src/test/typescript/integration/plugin-htlc-eth-besu-erc20/openapi/openapi-validation.test.ts @@ -775,7 +775,7 @@ test(testCase, async (t: Test) => { try { // eslint-disable-next-line prettier/prettier - await api.getSingleStatusV1((parameters as any) as GetSingleStatusRequest); + await api.getSingleStatusV1(parameters as any as GetSingleStatusRequest); } catch (e) { t2.equal( e.response.status, diff --git a/tools/clear-openapi-codegen-folders.js b/tools/clear-openapi-codegen-folders.js index 01f1e44e81..d8c41084bf 100644 --- a/tools/clear-openapi-codegen-folders.js +++ b/tools/clear-openapi-codegen-folders.js @@ -1,5 +1,5 @@ import { globby } from "globby"; -import { rm, rmdir } from "fs"; +import { rm } from "fs"; import { readFile } from "fs/promises"; import { dirname } from "path"; import { fileURLToPath } from "url"; diff --git a/tools/custom-checks/check-missing-node-deps.ts b/tools/custom-checks/check-missing-node-deps.ts index abb1ee2fc8..0233511572 100644 --- a/tools/custom-checks/check-missing-node-deps.ts +++ b/tools/custom-checks/check-missing-node-deps.ts @@ -41,7 +41,7 @@ export async function checkMissingNodeDeps( "sandbox", "dist", "bower_components", - "node_modules" + "node_modules", ], ignoreMatches: [ // ignore dependencies that matches these globs @@ -50,7 +50,7 @@ export async function checkMissingNodeDeps( "tape-promise", "tape", "tap", - "@ionic-native/*" + "@ionic-native/*", ], // parsers: { // // the target parsers diff --git a/tools/custom-checks/check-package-json-sort.ts b/tools/custom-checks/check-package-json-sort.ts index a0a2ef558b..7d5701559b 100644 --- a/tools/custom-checks/check-package-json-sort.ts +++ b/tools/custom-checks/check-package-json-sort.ts @@ -28,7 +28,6 @@ export async function checkPackageJsonSort( const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const SCRIPT_DIR = __dirname; - const LERNA_JSON = "lerna.json"; const PROJECT_DIR = path.join(SCRIPT_DIR, "../../"); const PACKAGE_JSON = "package.json"; console.log(`${TAG} SCRIPT_DIR=${SCRIPT_DIR}`); diff --git a/tools/get-latest-sem-ver-git-tag.ts b/tools/get-latest-sem-ver-git-tag.ts index 9d3676c841..45e963106c 100644 --- a/tools/get-latest-sem-ver-git-tag.ts +++ b/tools/get-latest-sem-ver-git-tag.ts @@ -1,5 +1,5 @@ import path from "path"; -import { fileURLToPath } from "url" +import { fileURLToPath } from "url"; import { simpleGit, SimpleGit, SimpleGitOptions } from "simple-git"; import { compareSemVer, isValidSemVer } from "semver-parser"; import { RuntimeError } from "run-time-error"; @@ -7,8 +7,8 @@ import { RuntimeError } from "run-time-error"; const TAG = "[tools/get-latest-sem-ver-git-tag.ts]"; const nodePath = path.resolve(process.argv[1]); -const modulePath = path.resolve(fileURLToPath(import.meta.url)) -const isRunningDirectlyViaCLI = nodePath === modulePath +const modulePath = path.resolve(fileURLToPath(import.meta.url)); +const isRunningDirectlyViaCLI = nodePath === modulePath; if (isRunningDirectlyViaCLI) { const excludedTags = process.argv.slice(2); @@ -24,44 +24,45 @@ export interface IGetLatestSemVerGitTagV1Response { readonly latestSemVerTag: string; } -export async function getLatestSemVerGitTagV1(req: IGetLatestSemVerGitTagV1Request): Promise { - const options: Partial = { - baseDir: process.cwd(), - binary: "git", - maxConcurrentProcesses: 6, - trimmed: false, - }; - - // when setting all options in a single object - const git: SimpleGit = simpleGit(options); - - if (req.omitFetch) { - console.log(`${TAG} omitted git fetch`); - } else { - console.log(`${TAG} running git fetch...`); - await git.fetch(); - } - console.log(`${TAG} retrieving git tags...`); - const { all: allTags } = await git.tags(); - console.log(`${TAG} found ${allTags.length} git tags total.`); +export async function getLatestSemVerGitTagV1( + req: IGetLatestSemVerGitTagV1Request, +): Promise { + const options: Partial = { + baseDir: process.cwd(), + binary: "git", + maxConcurrentProcesses: 6, + trimmed: false, + }; - const excludedTags = new Set(req.excludedTags); - const filteredTags = allTags.filter((t) => !excludedTags.has(t)); - console.log(`${TAG} ${filteredTags.length} tags remain after exclusions.`); + // when setting all options in a single object + const git: SimpleGit = simpleGit(options); - const semVerTags = filteredTags.filter((t) => isValidSemVer(t)); - console.log(`${TAG} found ${semVerTags.length} semver tags.`, semVerTags); + if (req.omitFetch) { + console.log(`${TAG} omitted git fetch`); + } else { + console.log(`${TAG} running git fetch...`); + await git.fetch(); + } + console.log(`${TAG} retrieving git tags...`); + const { all: allTags } = await git.tags(); + console.log(`${TAG} found ${allTags.length} git tags total.`); - - const sorted = semVerTags.sort(compareSemVer); - console.log(`${TAG} sorted ${semVerTags.length} git tags:`, semVerTags); - - const latestSemVerTag = sorted.pop(); - console.log(`${TAG} latestSemVerTag ${latestSemVerTag}`); + const excludedTags = new Set(req.excludedTags); + const filteredTags = allTags.filter((t) => !excludedTags.has(t)); + console.log(`${TAG} ${filteredTags.length} tags remain after exclusions.`); - if (!latestSemVerTag) { - throw new RuntimeError(`Could not find any semver git tags in the repo.`); - } else { - return { latestSemVerTag }; - } - } \ No newline at end of file + const semVerTags = filteredTags.filter((t) => isValidSemVer(t)); + console.log(`${TAG} found ${semVerTags.length} semver tags.`, semVerTags); + + const sorted = semVerTags.sort(compareSemVer); + console.log(`${TAG} sorted ${semVerTags.length} git tags:`, semVerTags); + + const latestSemVerTag = sorted.pop(); + console.log(`${TAG} latestSemVerTag ${latestSemVerTag}`); + + if (!latestSemVerTag) { + throw new RuntimeError(`Could not find any semver git tags in the repo.`); + } else { + return { latestSemVerTag }; + } +} diff --git a/tools/get-package-info-list.js b/tools/get-package-info-list.js index 9fbd6b0d37..08004d31ce 100644 --- a/tools/get-package-info-list.js +++ b/tools/get-package-info-list.js @@ -66,7 +66,7 @@ export function getPackageInfoList(ignorePatterns = []) { /** @type {PackageInfo[]} */ const pkgInfoList = JSON.parse(processOutput).filter( - (pkgInfo) => !ignorePatterns.some((ip) => ip.test(pkgInfo.name)) + (pkgInfo) => !ignorePatterns.some((ip) => ip.test(pkgInfo.name)), ); pkgInfoList.forEach((pkgInfo) => { diff --git a/tools/has-key.ts b/tools/has-key.ts index 03131dba88..38dd83e704 100644 --- a/tools/has-key.ts +++ b/tools/has-key.ts @@ -1,3 +1,6 @@ -export function hasKey(obj: unknown, key: T): obj is { [key in T]: unknown } { - return Boolean(typeof obj === 'object' && obj && key in obj); -} \ No newline at end of file +export function hasKey( + obj: unknown, + key: T, +): obj is { [key in T]: unknown } { + return Boolean(typeof obj === "object" && obj && key in obj); +} diff --git a/weaver/common/policy-dsl/index.js b/weaver/common/policy-dsl/index.js index ee4853ec30..cf6fa8b3c2 100644 --- a/weaver/common/policy-dsl/index.js +++ b/weaver/common/policy-dsl/index.js @@ -4,15 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import antlr4 from 'antlr4'; -import PolicyLexer from "./parser/PolicyLexer.js" -import PolicyParser from "./parser/PolicyParser.js" +import antlr4 from "antlr4"; +import PolicyLexer from "./parser/PolicyLexer.js"; +import PolicyParser from "./parser/PolicyParser.js"; -var input = 'org1 && org2' +var input = "org1 && org2"; var chars = new antlr4.InputStream(input); var lexer = new PolicyLexer(chars); -var tokens = new antlr4.CommonTokenStream(lexer); -tokens.fill() -tokens.tokens.forEach(tok => { - console.log(tok.text); -}) +var tokens = new antlr4.CommonTokenStream(lexer); +tokens.fill(); +tokens.tokens.forEach((tok) => { + console.log(tok.text); +}); diff --git a/weaver/common/policy-dsl/parser/PolicyLexer.js b/weaver/common/policy-dsl/parser/PolicyLexer.js index 46da013c89..b146d2f5b3 100644 --- a/weaver/common/policy-dsl/parser/PolicyLexer.js +++ b/weaver/common/policy-dsl/parser/PolicyLexer.js @@ -6,87 +6,124 @@ // Generated from parser/Policy.g4 by ANTLR 4.9 // jshint ignore: start -import antlr4 from 'antlr4'; - - - -const serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786", - "\u5964\u0002\rP\b\u0001\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004", - "\u0004\t\u0004\u0004\u0005\t\u0005\u0004\u0006\t\u0006\u0004\u0007\t", - "\u0007\u0004\b\t\b\u0004\t\t\t\u0004\n\t\n\u0004\u000b\t\u000b\u0004", - "\f\t\f\u0003\u0002\u0006\u0002\u001b\n\u0002\r\u0002\u000e\u0002\u001c", - "\u0003\u0002\u0003\u0002\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003", - "\u0003\u0003\u0003\u0003\u0003\u0004\u0003\u0004\u0003\u0004\u0007\u0004", - "*\n\u0004\f\u0004\u000e\u0004-\u000b\u0004\u0005\u0004/\n\u0004\u0003", - "\u0005\u0003\u0005\u0003\u0005\u0003\u0006\u0003\u0006\u0003\u0006\u0003", - "\u0007\u0003\u0007\u0003\b\u0003\b\u0003\t\u0003\t\u0003\t\u0003\n\u0003", - "\n\u0003\n\u0003\u000b\u0003\u000b\u0003\u000b\u0003\f\u0007\fE\n\f", - "\f\f\u000e\fH\u000b\f\u0003\f\u0003\f\u0007\fL\n\f\f\f\u000e\fO\u000b", - "\f\u0002\u0002\r\u0003\u0003\u0005\u0004\u0007\u0005\t\u0006\u000b\u0007", - "\r\b\u000f\t\u0011\n\u0013\u000b\u0015\f\u0017\r\u0003\u0002\b\u0004", - "\u0002\"\"vv\u0003\u00023;\u0003\u00022;\u0003\u0002aa\u0003\u0002c", - "|\u0006\u00022;C\\aac|\u0002T\u0002\u0003\u0003\u0002\u0002\u0002\u0002", - "\u0005\u0003\u0002\u0002\u0002\u0002\u0007\u0003\u0002\u0002\u0002\u0002", - "\t\u0003\u0002\u0002\u0002\u0002\u000b\u0003\u0002\u0002\u0002\u0002", - "\r\u0003\u0002\u0002\u0002\u0002\u000f\u0003\u0002\u0002\u0002\u0002", - "\u0011\u0003\u0002\u0002\u0002\u0002\u0013\u0003\u0002\u0002\u0002\u0002", - "\u0015\u0003\u0002\u0002\u0002\u0002\u0017\u0003\u0002\u0002\u0002\u0003", - "\u001a\u0003\u0002\u0002\u0002\u0005 \u0003\u0002\u0002\u0002\u0007", - ".\u0003\u0002\u0002\u0002\t0\u0003\u0002\u0002\u0002\u000b3\u0003\u0002", - "\u0002\u0002\r6\u0003\u0002\u0002\u0002\u000f8\u0003\u0002\u0002\u0002", - "\u0011:\u0003\u0002\u0002\u0002\u0013=\u0003\u0002\u0002\u0002\u0015", - "@\u0003\u0002\u0002\u0002\u0017F\u0003\u0002\u0002\u0002\u0019\u001b", - "\t\u0002\u0002\u0002\u001a\u0019\u0003\u0002\u0002\u0002\u001b\u001c", - "\u0003\u0002\u0002\u0002\u001c\u001a\u0003\u0002\u0002\u0002\u001c\u001d", - "\u0003\u0002\u0002\u0002\u001d\u001e\u0003\u0002\u0002\u0002\u001e\u001f", - "\b\u0002\u0002\u0002\u001f\u0004\u0003\u0002\u0002\u0002 !\u0007e\u0002", - "\u0002!\"\u0007q\u0002\u0002\"#\u0007w\u0002\u0002#$\u0007p\u0002\u0002", - "$%\u0007v\u0002\u0002%\u0006\u0003\u0002\u0002\u0002&/\u00072\u0002", - "\u0002\'+\t\u0003\u0002\u0002(*\t\u0004\u0002\u0002)(\u0003\u0002\u0002", - "\u0002*-\u0003\u0002\u0002\u0002+)\u0003\u0002\u0002\u0002+,\u0003\u0002", - "\u0002\u0002,/\u0003\u0002\u0002\u0002-+\u0003\u0002\u0002\u0002.&\u0003", - "\u0002\u0002\u0002.\'\u0003\u0002\u0002\u0002/\b\u0003\u0002\u0002\u0002", - "01\u0007(\u0002\u000212\u0007(\u0002\u00022\n\u0003\u0002\u0002\u0002", - "34\u0007~\u0002\u000245\u0007~\u0002\u00025\f\u0003\u0002\u0002\u0002", - "67\u0007@\u0002\u00027\u000e\u0003\u0002\u0002\u000289\u0007>\u0002", - "\u00029\u0010\u0003\u0002\u0002\u0002:;\u0007?\u0002\u0002;<\u0007?", - "\u0002\u0002<\u0012\u0003\u0002\u0002\u0002=>\u0007@\u0002\u0002>?\u0007", - "?\u0002\u0002?\u0014\u0003\u0002\u0002\u0002@A\u0007>\u0002\u0002AB", - "\u0007?\u0002\u0002B\u0016\u0003\u0002\u0002\u0002CE\t\u0005\u0002\u0002", - "DC\u0003\u0002\u0002\u0002EH\u0003\u0002\u0002\u0002FD\u0003\u0002\u0002", - "\u0002FG\u0003\u0002\u0002\u0002GI\u0003\u0002\u0002\u0002HF\u0003\u0002", - "\u0002\u0002IM\t\u0006\u0002\u0002JL\t\u0007\u0002\u0002KJ\u0003\u0002", - "\u0002\u0002LO\u0003\u0002\u0002\u0002MK\u0003\u0002\u0002\u0002MN\u0003", - "\u0002\u0002\u0002N\u0018\u0003\u0002\u0002\u0002OM\u0003\u0002\u0002", - "\u0002\b\u0002\u001c+.FM\u0003\b\u0002\u0002"].join(""); +import antlr4 from "antlr4"; +const serializedATN = [ + "\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786", + "\u5964\u0002\rP\b\u0001\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004", + "\u0004\t\u0004\u0004\u0005\t\u0005\u0004\u0006\t\u0006\u0004\u0007\t", + "\u0007\u0004\b\t\b\u0004\t\t\t\u0004\n\t\n\u0004\u000b\t\u000b\u0004", + "\f\t\f\u0003\u0002\u0006\u0002\u001b\n\u0002\r\u0002\u000e\u0002\u001c", + "\u0003\u0002\u0003\u0002\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003", + "\u0003\u0003\u0003\u0003\u0003\u0004\u0003\u0004\u0003\u0004\u0007\u0004", + "*\n\u0004\f\u0004\u000e\u0004-\u000b\u0004\u0005\u0004/\n\u0004\u0003", + "\u0005\u0003\u0005\u0003\u0005\u0003\u0006\u0003\u0006\u0003\u0006\u0003", + "\u0007\u0003\u0007\u0003\b\u0003\b\u0003\t\u0003\t\u0003\t\u0003\n\u0003", + "\n\u0003\n\u0003\u000b\u0003\u000b\u0003\u000b\u0003\f\u0007\fE\n\f", + "\f\f\u000e\fH\u000b\f\u0003\f\u0003\f\u0007\fL\n\f\f\f\u000e\fO\u000b", + "\f\u0002\u0002\r\u0003\u0003\u0005\u0004\u0007\u0005\t\u0006\u000b\u0007", + "\r\b\u000f\t\u0011\n\u0013\u000b\u0015\f\u0017\r\u0003\u0002\b\u0004", + '\u0002""vv\u0003\u00023;\u0003\u00022;\u0003\u0002aa\u0003\u0002c', + "|\u0006\u00022;C\\aac|\u0002T\u0002\u0003\u0003\u0002\u0002\u0002\u0002", + "\u0005\u0003\u0002\u0002\u0002\u0002\u0007\u0003\u0002\u0002\u0002\u0002", + "\t\u0003\u0002\u0002\u0002\u0002\u000b\u0003\u0002\u0002\u0002\u0002", + "\r\u0003\u0002\u0002\u0002\u0002\u000f\u0003\u0002\u0002\u0002\u0002", + "\u0011\u0003\u0002\u0002\u0002\u0002\u0013\u0003\u0002\u0002\u0002\u0002", + "\u0015\u0003\u0002\u0002\u0002\u0002\u0017\u0003\u0002\u0002\u0002\u0003", + "\u001a\u0003\u0002\u0002\u0002\u0005 \u0003\u0002\u0002\u0002\u0007", + ".\u0003\u0002\u0002\u0002\t0\u0003\u0002\u0002\u0002\u000b3\u0003\u0002", + "\u0002\u0002\r6\u0003\u0002\u0002\u0002\u000f8\u0003\u0002\u0002\u0002", + "\u0011:\u0003\u0002\u0002\u0002\u0013=\u0003\u0002\u0002\u0002\u0015", + "@\u0003\u0002\u0002\u0002\u0017F\u0003\u0002\u0002\u0002\u0019\u001b", + "\t\u0002\u0002\u0002\u001a\u0019\u0003\u0002\u0002\u0002\u001b\u001c", + "\u0003\u0002\u0002\u0002\u001c\u001a\u0003\u0002\u0002\u0002\u001c\u001d", + "\u0003\u0002\u0002\u0002\u001d\u001e\u0003\u0002\u0002\u0002\u001e\u001f", + "\b\u0002\u0002\u0002\u001f\u0004\u0003\u0002\u0002\u0002 !\u0007e\u0002", + '\u0002!"\u0007q\u0002\u0002"#\u0007w\u0002\u0002#$\u0007p\u0002\u0002', + "$%\u0007v\u0002\u0002%\u0006\u0003\u0002\u0002\u0002&/\u00072\u0002", + "\u0002'+\t\u0003\u0002\u0002(*\t\u0004\u0002\u0002)(\u0003\u0002\u0002", + "\u0002*-\u0003\u0002\u0002\u0002+)\u0003\u0002\u0002\u0002+,\u0003\u0002", + "\u0002\u0002,/\u0003\u0002\u0002\u0002-+\u0003\u0002\u0002\u0002.&\u0003", + "\u0002\u0002\u0002.'\u0003\u0002\u0002\u0002/\b\u0003\u0002\u0002\u0002", + "01\u0007(\u0002\u000212\u0007(\u0002\u00022\n\u0003\u0002\u0002\u0002", + "34\u0007~\u0002\u000245\u0007~\u0002\u00025\f\u0003\u0002\u0002\u0002", + "67\u0007@\u0002\u00027\u000e\u0003\u0002\u0002\u000289\u0007>\u0002", + "\u00029\u0010\u0003\u0002\u0002\u0002:;\u0007?\u0002\u0002;<\u0007?", + "\u0002\u0002<\u0012\u0003\u0002\u0002\u0002=>\u0007@\u0002\u0002>?\u0007", + "?\u0002\u0002?\u0014\u0003\u0002\u0002\u0002@A\u0007>\u0002\u0002AB", + "\u0007?\u0002\u0002B\u0016\u0003\u0002\u0002\u0002CE\t\u0005\u0002\u0002", + "DC\u0003\u0002\u0002\u0002EH\u0003\u0002\u0002\u0002FD\u0003\u0002\u0002", + "\u0002FG\u0003\u0002\u0002\u0002GI\u0003\u0002\u0002\u0002HF\u0003\u0002", + "\u0002\u0002IM\t\u0006\u0002\u0002JL\t\u0007\u0002\u0002KJ\u0003\u0002", + "\u0002\u0002LO\u0003\u0002\u0002\u0002MK\u0003\u0002\u0002\u0002MN\u0003", + "\u0002\u0002\u0002N\u0018\u0003\u0002\u0002\u0002OM\u0003\u0002\u0002", + "\u0002\b\u0002\u001c+.FM\u0003\b\u0002\u0002", +].join(""); const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN); -const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) ); +const decisionsToDFA = atn.decisionToState.map( + (ds, index) => new antlr4.dfa.DFA(ds, index), +); export default class PolicyLexer extends antlr4.Lexer { + static grammarFileName = "Policy.g4"; + static channelNames = ["DEFAULT_TOKEN_CHANNEL", "HIDDEN"]; + static modeNames = ["DEFAULT_MODE"]; + static literalNames = [ + null, + null, + "'count'", + null, + "'&&'", + "'||'", + "'>'", + "'<'", + "'=='", + "'>='", + "'<='", + ]; + static symbolicNames = [ + null, + "WS", + "COUNT", + "INTLIT", + "AND", + "OR", + "GREATER_THAN", + "LESS_THAN", + "EQUAL", + "GREATER_THAN_EQUAL", + "LESS_THAN_EQUAL", + "ID", + ]; + static ruleNames = [ + "WS", + "COUNT", + "INTLIT", + "AND", + "OR", + "GREATER_THAN", + "LESS_THAN", + "EQUAL", + "GREATER_THAN_EQUAL", + "LESS_THAN_EQUAL", + "ID", + ]; - static grammarFileName = "Policy.g4"; - static channelNames = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; - static modeNames = [ "DEFAULT_MODE" ]; - static literalNames = [ null, null, "'count'", null, "'&&'", "'||'", "'>'", - "'<'", "'=='", "'>='", "'<='" ]; - static symbolicNames = [ null, "WS", "COUNT", "INTLIT", "AND", "OR", "GREATER_THAN", - "LESS_THAN", "EQUAL", "GREATER_THAN_EQUAL", "LESS_THAN_EQUAL", - "ID" ]; - static ruleNames = [ "WS", "COUNT", "INTLIT", "AND", "OR", "GREATER_THAN", - "LESS_THAN", "EQUAL", "GREATER_THAN_EQUAL", "LESS_THAN_EQUAL", - "ID" ]; - - constructor(input) { - super(input) - this._interp = new antlr4.atn.LexerATNSimulator(this, atn, decisionsToDFA, new antlr4.PredictionContextCache()); - } + constructor(input) { + super(input); + this._interp = new antlr4.atn.LexerATNSimulator( + this, + atn, + decisionsToDFA, + new antlr4.PredictionContextCache(), + ); + } - get atn() { - return atn; - } + get atn() { + return atn; + } } PolicyLexer.EOF = antlr4.Token.EOF; @@ -101,6 +138,3 @@ PolicyLexer.EQUAL = 8; PolicyLexer.GREATER_THAN_EQUAL = 9; PolicyLexer.LESS_THAN_EQUAL = 10; PolicyLexer.ID = 11; - - - diff --git a/weaver/common/policy-dsl/parser/PolicyListener.js b/weaver/common/policy-dsl/parser/PolicyListener.js index a8a53cebf9..a7e43a2d9b 100644 --- a/weaver/common/policy-dsl/parser/PolicyListener.js +++ b/weaver/common/policy-dsl/parser/PolicyListener.js @@ -6,64 +6,43 @@ // Generated from parser/Policy.g4 by ANTLR 4.9 // jshint ignore: start -import antlr4 from 'antlr4'; +import antlr4 from "antlr4"; // This class defines a complete listener for a parse tree produced by PolicyParser. export default class PolicyListener extends antlr4.tree.ParseTreeListener { + // Enter a parse tree produced by PolicyParser#root. + enterRoot(ctx) {} - // Enter a parse tree produced by PolicyParser#root. - enterRoot(ctx) { - } + // Exit a parse tree produced by PolicyParser#root. + exitRoot(ctx) {} - // Exit a parse tree produced by PolicyParser#root. - exitRoot(ctx) { - } + // Enter a parse tree produced by PolicyParser#idExpression. + enterIdExpression(ctx) {} + // Exit a parse tree produced by PolicyParser#idExpression. + exitIdExpression(ctx) {} - // Enter a parse tree produced by PolicyParser#idExpression. - enterIdExpression(ctx) { - } + // Enter a parse tree produced by PolicyParser#booleanOrExpression. + enterBooleanOrExpression(ctx) {} - // Exit a parse tree produced by PolicyParser#idExpression. - exitIdExpression(ctx) { - } + // Exit a parse tree produced by PolicyParser#booleanOrExpression. + exitBooleanOrExpression(ctx) {} + // Enter a parse tree produced by PolicyParser#countExpression. + enterCountExpression(ctx) {} - // Enter a parse tree produced by PolicyParser#booleanOrExpression. - enterBooleanOrExpression(ctx) { - } + // Exit a parse tree produced by PolicyParser#countExpression. + exitCountExpression(ctx) {} - // Exit a parse tree produced by PolicyParser#booleanOrExpression. - exitBooleanOrExpression(ctx) { - } + // Enter a parse tree produced by PolicyParser#booleanAndExpression. + enterBooleanAndExpression(ctx) {} + // Exit a parse tree produced by PolicyParser#booleanAndExpression. + exitBooleanAndExpression(ctx) {} - // Enter a parse tree produced by PolicyParser#countExpression. - enterCountExpression(ctx) { - } + // Enter a parse tree produced by PolicyParser#count_expression. + enterCount_expression(ctx) {} - // Exit a parse tree produced by PolicyParser#countExpression. - exitCountExpression(ctx) { - } - - - // Enter a parse tree produced by PolicyParser#booleanAndExpression. - enterBooleanAndExpression(ctx) { - } - - // Exit a parse tree produced by PolicyParser#booleanAndExpression. - exitBooleanAndExpression(ctx) { - } - - - // Enter a parse tree produced by PolicyParser#count_expression. - enterCount_expression(ctx) { - } - - // Exit a parse tree produced by PolicyParser#count_expression. - exitCount_expression(ctx) { - } - - - -} \ No newline at end of file + // Exit a parse tree produced by PolicyParser#count_expression. + exitCount_expression(ctx) {} +} diff --git a/weaver/common/policy-dsl/parser/PolicyParser.js b/weaver/common/policy-dsl/parser/PolicyParser.js index 89503a5c30..24805967de 100644 --- a/weaver/common/policy-dsl/parser/PolicyParser.js +++ b/weaver/common/policy-dsl/parser/PolicyParser.js @@ -6,266 +6,323 @@ // Generated from parser/Policy.g4 by ANTLR 4.9 // jshint ignore: start -import antlr4 from 'antlr4'; -import PolicyListener from './PolicyListener.js'; - -const serializedATN = ["\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786", - "\u5964\u0003\r$\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004\u0004", - "\t\u0004\u0003\u0002\u0003\u0002\u0003\u0002\u0003\u0003\u0003\u0003", - "\u0003\u0003\u0005\u0003\u000f\n\u0003\u0003\u0003\u0003\u0003\u0003", - "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u0003\u0017\n\u0003", - "\f\u0003\u000e\u0003\u001a\u000b\u0003\u0003\u0004\u0003\u0004\u0003", - "\u0004\u0003\u0004\u0003\u0004\u0003\u0004\u0005\u0004\"\n\u0004\u0003", - "\u0004\u0002\u0003\u0004\u0005\u0002\u0004\u0006\u0002\u0003\u0004\u0002", - "\b\t\u000b\f\u0002$\u0002\b\u0003\u0002\u0002\u0002\u0004\u000e\u0003", - "\u0002\u0002\u0002\u0006!\u0003\u0002\u0002\u0002\b\t\u0005\u0004\u0003", - "\u0002\t\n\u0007\u0002\u0002\u0003\n\u0003\u0003\u0002\u0002\u0002\u000b", - "\f\b\u0003\u0001\u0002\f\u000f\u0007\r\u0002\u0002\r\u000f\u0005\u0006", - "\u0004\u0002\u000e\u000b\u0003\u0002\u0002\u0002\u000e\r\u0003\u0002", - "\u0002\u0002\u000f\u0018\u0003\u0002\u0002\u0002\u0010\u0011\f\u0006", - "\u0002\u0002\u0011\u0012\u0007\u0006\u0002\u0002\u0012\u0017\u0005\u0004", - "\u0003\u0007\u0013\u0014\f\u0005\u0002\u0002\u0014\u0015\u0007\u0007", - "\u0002\u0002\u0015\u0017\u0005\u0004\u0003\u0006\u0016\u0010\u0003\u0002", - "\u0002\u0002\u0016\u0013\u0003\u0002\u0002\u0002\u0017\u001a\u0003\u0002", - "\u0002\u0002\u0018\u0016\u0003\u0002\u0002\u0002\u0018\u0019\u0003\u0002", - "\u0002\u0002\u0019\u0005\u0003\u0002\u0002\u0002\u001a\u0018\u0003\u0002", - "\u0002\u0002\u001b\u001c\u0007\u0004\u0002\u0002\u001c\u001d\t\u0002", - "\u0002\u0002\u001d\"\u0007\u0005\u0002\u0002\u001e\u001f\u0007\u0005", - "\u0002\u0002\u001f \t\u0002\u0002\u0002 \"\u0007\u0004\u0002\u0002!", - "\u001b\u0003\u0002\u0002\u0002!\u001e\u0003\u0002\u0002\u0002\"\u0007", - "\u0003\u0002\u0002\u0002\u0006\u000e\u0016\u0018!"].join(""); - +import antlr4 from "antlr4"; +import PolicyListener from "./PolicyListener.js"; + +const serializedATN = [ + "\u0003\u608b\ua72a\u8133\ub9ed\u417c\u3be7\u7786", + "\u5964\u0003\r$\u0004\u0002\t\u0002\u0004\u0003\t\u0003\u0004\u0004", + "\t\u0004\u0003\u0002\u0003\u0002\u0003\u0002\u0003\u0003\u0003\u0003", + "\u0003\u0003\u0005\u0003\u000f\n\u0003\u0003\u0003\u0003\u0003\u0003", + "\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0007\u0003\u0017\n\u0003", + "\f\u0003\u000e\u0003\u001a\u000b\u0003\u0003\u0004\u0003\u0004\u0003", + '\u0004\u0003\u0004\u0003\u0004\u0003\u0004\u0005\u0004"\n\u0004\u0003', + "\u0004\u0002\u0003\u0004\u0005\u0002\u0004\u0006\u0002\u0003\u0004\u0002", + "\b\t\u000b\f\u0002$\u0002\b\u0003\u0002\u0002\u0002\u0004\u000e\u0003", + "\u0002\u0002\u0002\u0006!\u0003\u0002\u0002\u0002\b\t\u0005\u0004\u0003", + "\u0002\t\n\u0007\u0002\u0002\u0003\n\u0003\u0003\u0002\u0002\u0002\u000b", + "\f\b\u0003\u0001\u0002\f\u000f\u0007\r\u0002\u0002\r\u000f\u0005\u0006", + "\u0004\u0002\u000e\u000b\u0003\u0002\u0002\u0002\u000e\r\u0003\u0002", + "\u0002\u0002\u000f\u0018\u0003\u0002\u0002\u0002\u0010\u0011\f\u0006", + "\u0002\u0002\u0011\u0012\u0007\u0006\u0002\u0002\u0012\u0017\u0005\u0004", + "\u0003\u0007\u0013\u0014\f\u0005\u0002\u0002\u0014\u0015\u0007\u0007", + "\u0002\u0002\u0015\u0017\u0005\u0004\u0003\u0006\u0016\u0010\u0003\u0002", + "\u0002\u0002\u0016\u0013\u0003\u0002\u0002\u0002\u0017\u001a\u0003\u0002", + "\u0002\u0002\u0018\u0016\u0003\u0002\u0002\u0002\u0018\u0019\u0003\u0002", + "\u0002\u0002\u0019\u0005\u0003\u0002\u0002\u0002\u001a\u0018\u0003\u0002", + "\u0002\u0002\u001b\u001c\u0007\u0004\u0002\u0002\u001c\u001d\t\u0002", + '\u0002\u0002\u001d"\u0007\u0005\u0002\u0002\u001e\u001f\u0007\u0005', + '\u0002\u0002\u001f \t\u0002\u0002\u0002 "\u0007\u0004\u0002\u0002!', + '\u001b\u0003\u0002\u0002\u0002!\u001e\u0003\u0002\u0002\u0002"\u0007', + "\u0003\u0002\u0002\u0002\u0006\u000e\u0016\u0018!", +].join(""); const atn = new antlr4.atn.ATNDeserializer().deserialize(serializedATN); -const decisionsToDFA = atn.decisionToState.map( (ds, index) => new antlr4.dfa.DFA(ds, index) ); +const decisionsToDFA = atn.decisionToState.map( + (ds, index) => new antlr4.dfa.DFA(ds, index), +); const sharedContextCache = new antlr4.PredictionContextCache(); export default class PolicyParser extends antlr4.Parser { - - static grammarFileName = "Policy.g4"; - static literalNames = [ null, null, "'count'", null, "'&&'", "'||'", - "'>'", "'<'", "'=='", "'>='", "'<='" ]; - static symbolicNames = [ null, "WS", "COUNT", "INTLIT", "AND", "OR", - "GREATER_THAN", "LESS_THAN", "EQUAL", "GREATER_THAN_EQUAL", - "LESS_THAN_EQUAL", "ID" ]; - static ruleNames = [ "root", "expression", "count_expression" ]; - - constructor(input) { - super(input); - this._interp = new antlr4.atn.ParserATNSimulator(this, atn, decisionsToDFA, sharedContextCache); - this.ruleNames = PolicyParser.ruleNames; - this.literalNames = PolicyParser.literalNames; - this.symbolicNames = PolicyParser.symbolicNames; + static grammarFileName = "Policy.g4"; + static literalNames = [ + null, + null, + "'count'", + null, + "'&&'", + "'||'", + "'>'", + "'<'", + "'=='", + "'>='", + "'<='", + ]; + static symbolicNames = [ + null, + "WS", + "COUNT", + "INTLIT", + "AND", + "OR", + "GREATER_THAN", + "LESS_THAN", + "EQUAL", + "GREATER_THAN_EQUAL", + "LESS_THAN_EQUAL", + "ID", + ]; + static ruleNames = ["root", "expression", "count_expression"]; + + constructor(input) { + super(input); + this._interp = new antlr4.atn.ParserATNSimulator( + this, + atn, + decisionsToDFA, + sharedContextCache, + ); + this.ruleNames = PolicyParser.ruleNames; + this.literalNames = PolicyParser.literalNames; + this.symbolicNames = PolicyParser.symbolicNames; + } + + get atn() { + return atn; + } + + sempred(localctx, ruleIndex, predIndex) { + switch (ruleIndex) { + case 1: + return this.expression_sempred(localctx, predIndex); + default: + throw "No predicate with index:" + ruleIndex; } - - get atn() { - return atn; + } + + expression_sempred(localctx, predIndex) { + switch (predIndex) { + case 0: + return this.precpred(this._ctx, 4); + case 1: + return this.precpred(this._ctx, 3); + default: + throw "No predicate with index:" + predIndex; } + } + + root() { + let localctx = new RootContext(this, this._ctx, this.state); + this.enterRule(localctx, 0, PolicyParser.RULE_root); + try { + this.enterOuterAlt(localctx, 1); + this.state = 6; + this.expression(0); + this.state = 7; + this.match(PolicyParser.EOF); + } catch (re) { + if (re instanceof antlr4.error.RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } - sempred(localctx, ruleIndex, predIndex) { - switch(ruleIndex) { - case 1: - return this.expression_sempred(localctx, predIndex); + expression(_p) { + if (_p === undefined) { + _p = 0; + } + const _parentctx = this._ctx; + const _parentState = this.state; + let localctx = new ExpressionContext(this, this._ctx, _parentState); + let _prevctx = localctx; + const _startState = 2; + this.enterRecursionRule(localctx, 2, PolicyParser.RULE_expression, _p); + try { + this.enterOuterAlt(localctx, 1); + this.state = 12; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case PolicyParser.ID: + localctx = new IdExpressionContext(this, localctx); + this._ctx = localctx; + _prevctx = localctx; + + this.state = 10; + this.match(PolicyParser.ID); + break; + case PolicyParser.COUNT: + case PolicyParser.INTLIT: + localctx = new CountExpressionContext(this, localctx); + this._ctx = localctx; + _prevctx = localctx; + this.state = 11; + this.count_expression(); + break; default: - throw "No predicate with index:" + ruleIndex; - } + throw new antlr4.error.NoViableAltException(this); + } + this._ctx.stop = this._input.LT(-1); + this.state = 22; + this._errHandler.sync(this); + let _alt = this._interp.adaptivePredict(this._input, 2, this._ctx); + while (_alt != 2 && _alt != antlr4.atn.ATN.INVALID_ALT_NUMBER) { + if (_alt === 1) { + if (this._parseListeners !== null) { + this.triggerExitRuleEvent(); + } + _prevctx = localctx; + this.state = 20; + this._errHandler.sync(this); + var la_ = this._interp.adaptivePredict(this._input, 1, this._ctx); + switch (la_) { + case 1: + localctx = new BooleanAndExpressionContext( + this, + new ExpressionContext(this, _parentctx, _parentState), + ); + this.pushNewRecursionContext( + localctx, + _startState, + PolicyParser.RULE_expression, + ); + this.state = 14; + if (!this.precpred(this._ctx, 4)) { + throw new antlr4.error.FailedPredicateException( + this, + "this.precpred(this._ctx, 4)", + ); + } + this.state = 15; + this.match(PolicyParser.AND); + this.state = 16; + this.expression(5); + break; + + case 2: + localctx = new BooleanOrExpressionContext( + this, + new ExpressionContext(this, _parentctx, _parentState), + ); + this.pushNewRecursionContext( + localctx, + _startState, + PolicyParser.RULE_expression, + ); + this.state = 17; + if (!this.precpred(this._ctx, 3)) { + throw new antlr4.error.FailedPredicateException( + this, + "this.precpred(this._ctx, 3)", + ); + } + this.state = 18; + this.match(PolicyParser.OR); + this.state = 19; + this.expression(4); + break; + } + } + this.state = 24; + this._errHandler.sync(this); + _alt = this._interp.adaptivePredict(this._input, 2, this._ctx); + } + } catch (error) { + if (error instanceof antlr4.error.RecognitionException) { + localctx.exception = error; + this._errHandler.reportError(this, error); + this._errHandler.recover(this, error); + } else { + throw error; + } + } finally { + this.unrollRecursionContexts(_parentctx); } - - expression_sempred(localctx, predIndex) { - switch(predIndex) { - case 0: - return this.precpred(this._ctx, 4); - case 1: - return this.precpred(this._ctx, 3); - default: - throw "No predicate with index:" + predIndex; - } - }; - - - - - root() { - let localctx = new RootContext(this, this._ctx, this.state); - this.enterRule(localctx, 0, PolicyParser.RULE_root); - try { - this.enterOuterAlt(localctx, 1); - this.state = 6; - this.expression(0); - this.state = 7; - this.match(PolicyParser.EOF); - } catch (re) { - if(re instanceof antlr4.error.RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - - - expression(_p) { - if(_p===undefined) { - _p = 0; - } - const _parentctx = this._ctx; - const _parentState = this.state; - let localctx = new ExpressionContext(this, this._ctx, _parentState); - let _prevctx = localctx; - const _startState = 2; - this.enterRecursionRule(localctx, 2, PolicyParser.RULE_expression, _p); - try { - this.enterOuterAlt(localctx, 1); - this.state = 12; - this._errHandler.sync(this); - switch(this._input.LA(1)) { - case PolicyParser.ID: - localctx = new IdExpressionContext(this, localctx); - this._ctx = localctx; - _prevctx = localctx; - - this.state = 10; - this.match(PolicyParser.ID); - break; - case PolicyParser.COUNT: - case PolicyParser.INTLIT: - localctx = new CountExpressionContext(this, localctx); - this._ctx = localctx; - _prevctx = localctx; - this.state = 11; - this.count_expression(); - break; - default: - throw new antlr4.error.NoViableAltException(this); - } - this._ctx.stop = this._input.LT(-1); - this.state = 22; - this._errHandler.sync(this); - let _alt = this._interp.adaptivePredict(this._input,2,this._ctx) - while(_alt!=2 && _alt!=antlr4.atn.ATN.INVALID_ALT_NUMBER) { - if(_alt===1) { - if(this._parseListeners!==null) { - this.triggerExitRuleEvent(); - } - _prevctx = localctx; - this.state = 20; - this._errHandler.sync(this); - var la_ = this._interp.adaptivePredict(this._input,1,this._ctx); - switch(la_) { - case 1: - localctx = new BooleanAndExpressionContext(this, new ExpressionContext(this, _parentctx, _parentState)); - this.pushNewRecursionContext(localctx, _startState, PolicyParser.RULE_expression); - this.state = 14; - if (!( this.precpred(this._ctx, 4))) { - throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 4)"); - } - this.state = 15; - this.match(PolicyParser.AND); - this.state = 16; - this.expression(5); - break; - - case 2: - localctx = new BooleanOrExpressionContext(this, new ExpressionContext(this, _parentctx, _parentState)); - this.pushNewRecursionContext(localctx, _startState, PolicyParser.RULE_expression); - this.state = 17; - if (!( this.precpred(this._ctx, 3))) { - throw new antlr4.error.FailedPredicateException(this, "this.precpred(this._ctx, 3)"); - } - this.state = 18; - this.match(PolicyParser.OR); - this.state = 19; - this.expression(4); - break; - - } - } - this.state = 24; - this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input,2,this._ctx); - } - - } catch( error) { - if(error instanceof antlr4.error.RecognitionException) { - localctx.exception = error; - this._errHandler.reportError(this, error); - this._errHandler.recover(this, error); - } else { - throw error; - } - } finally { - this.unrollRecursionContexts(_parentctx) - } - return localctx; - } - - - - count_expression() { - let localctx = new Count_expressionContext(this, this._ctx, this.state); - this.enterRule(localctx, 4, PolicyParser.RULE_count_expression); - var _la = 0; // Token type - try { - this.state = 31; - this._errHandler.sync(this); - switch(this._input.LA(1)) { - case PolicyParser.COUNT: - this.enterOuterAlt(localctx, 1); - this.state = 25; - this.match(PolicyParser.COUNT); - this.state = 26; - _la = this._input.LA(1); - if(!((((_la) & ~0x1f) == 0 && ((1 << _la) & ((1 << PolicyParser.GREATER_THAN) | (1 << PolicyParser.LESS_THAN) | (1 << PolicyParser.GREATER_THAN_EQUAL) | (1 << PolicyParser.LESS_THAN_EQUAL))) !== 0))) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - this.state = 27; - this.match(PolicyParser.INTLIT); - break; - case PolicyParser.INTLIT: - this.enterOuterAlt(localctx, 2); - this.state = 28; - this.match(PolicyParser.INTLIT); - this.state = 29; - _la = this._input.LA(1); - if(!((((_la) & ~0x1f) == 0 && ((1 << _la) & ((1 << PolicyParser.GREATER_THAN) | (1 << PolicyParser.LESS_THAN) | (1 << PolicyParser.GREATER_THAN_EQUAL) | (1 << PolicyParser.LESS_THAN_EQUAL))) !== 0))) { - this._errHandler.recoverInline(this); - } - else { - this._errHandler.reportMatch(this); - this.consume(); - } - this.state = 30; - this.match(PolicyParser.COUNT); - break; - default: - throw new antlr4.error.NoViableAltException(this); - } - } catch (re) { - if(re instanceof antlr4.error.RecognitionException) { - localctx.exception = re; - this._errHandler.reportError(this, re); - this._errHandler.recover(this, re); - } else { - throw re; - } - } finally { - this.exitRule(); - } - return localctx; - } - - + return localctx; + } + + count_expression() { + let localctx = new Count_expressionContext(this, this._ctx, this.state); + this.enterRule(localctx, 4, PolicyParser.RULE_count_expression); + var _la = 0; // Token type + try { + this.state = 31; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case PolicyParser.COUNT: + this.enterOuterAlt(localctx, 1); + this.state = 25; + this.match(PolicyParser.COUNT); + this.state = 26; + _la = this._input.LA(1); + if ( + !( + (_la & ~0x1f) == 0 && + ((1 << _la) & + ((1 << PolicyParser.GREATER_THAN) | + (1 << PolicyParser.LESS_THAN) | + (1 << PolicyParser.GREATER_THAN_EQUAL) | + (1 << PolicyParser.LESS_THAN_EQUAL))) !== + 0 + ) + ) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 27; + this.match(PolicyParser.INTLIT); + break; + case PolicyParser.INTLIT: + this.enterOuterAlt(localctx, 2); + this.state = 28; + this.match(PolicyParser.INTLIT); + this.state = 29; + _la = this._input.LA(1); + if ( + !( + (_la & ~0x1f) == 0 && + ((1 << _la) & + ((1 << PolicyParser.GREATER_THAN) | + (1 << PolicyParser.LESS_THAN) | + (1 << PolicyParser.GREATER_THAN_EQUAL) | + (1 << PolicyParser.LESS_THAN_EQUAL))) !== + 0 + ) + ) { + this._errHandler.recoverInline(this); + } else { + this._errHandler.reportMatch(this); + this.consume(); + } + this.state = 30; + this.match(PolicyParser.COUNT); + break; + default: + throw new antlr4.error.NoViableAltException(this); + } + } catch (re) { + if (re instanceof antlr4.error.RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } finally { + this.exitRule(); + } + return localctx; + } } PolicyParser.EOF = antlr4.Token.EOF; @@ -286,257 +343,229 @@ PolicyParser.RULE_expression = 1; PolicyParser.RULE_count_expression = 2; class RootContext extends antlr4.ParserRuleContext { - - constructor(parser, parent, invokingState) { - if(parent===undefined) { - parent = null; - } - if(invokingState===undefined || invokingState===null) { - invokingState = -1; - } - super(parent, invokingState); - this.parser = parser; - this.ruleIndex = PolicyParser.RULE_root; + constructor(parser, parent, invokingState) { + if (parent === undefined) { + parent = null; } + if (invokingState === undefined || invokingState === null) { + invokingState = -1; + } + super(parent, invokingState); + this.parser = parser; + this.ruleIndex = PolicyParser.RULE_root; + } + + expression() { + return this.getTypedRuleContext(ExpressionContext, 0); + } + + EOF() { + return this.getToken(PolicyParser.EOF, 0); + } + + enterRule(listener) { + if (listener instanceof PolicyListener) { + listener.enterRoot(this); + } + } - expression() { - return this.getTypedRuleContext(ExpressionContext,0); - }; - - EOF() { - return this.getToken(PolicyParser.EOF, 0); - }; - - enterRule(listener) { - if(listener instanceof PolicyListener ) { - listener.enterRoot(this); - } - } - - exitRule(listener) { - if(listener instanceof PolicyListener ) { - listener.exitRoot(this); - } - } - - + exitRule(listener) { + if (listener instanceof PolicyListener) { + listener.exitRoot(this); + } + } } - - class ExpressionContext extends antlr4.ParserRuleContext { - - constructor(parser, parent, invokingState) { - if(parent===undefined) { - parent = null; - } - if(invokingState===undefined || invokingState===null) { - invokingState = -1; - } - super(parent, invokingState); - this.parser = parser; - this.ruleIndex = PolicyParser.RULE_expression; + constructor(parser, parent, invokingState) { + if (parent === undefined) { + parent = null; } - - - - copyFrom(ctx) { - super.copyFrom(ctx); - } - + if (invokingState === undefined || invokingState === null) { + invokingState = -1; + } + super(parent, invokingState); + this.parser = parser; + this.ruleIndex = PolicyParser.RULE_expression; + } + + copyFrom(ctx) { + super.copyFrom(ctx); + } } - class IdExpressionContext extends ExpressionContext { - - constructor(parser, ctx) { - super(parser); - super.copyFrom(ctx); + constructor(parser, ctx) { + super(parser); + super.copyFrom(ctx); + } + + ID() { + return this.getToken(PolicyParser.ID, 0); + } + + enterRule(listener) { + if (listener instanceof PolicyListener) { + listener.enterIdExpression(this); } + } - ID() { - return this.getToken(PolicyParser.ID, 0); - }; - - enterRule(listener) { - if(listener instanceof PolicyListener ) { - listener.enterIdExpression(this); - } - } - - exitRule(listener) { - if(listener instanceof PolicyListener ) { - listener.exitIdExpression(this); - } - } - - + exitRule(listener) { + if (listener instanceof PolicyListener) { + listener.exitIdExpression(this); + } + } } PolicyParser.IdExpressionContext = IdExpressionContext; class BooleanOrExpressionContext extends ExpressionContext { - - constructor(parser, ctx) { - super(parser); - super.copyFrom(ctx); + constructor(parser, ctx) { + super(parser); + super.copyFrom(ctx); + } + + expression = function (i) { + if (i === undefined) { + i = null; + } + if (i === null) { + return this.getTypedRuleContexts(ExpressionContext); + } else { + return this.getTypedRuleContext(ExpressionContext, i); } + }; - expression = function(i) { - if(i===undefined) { - i = null; - } - if(i===null) { - return this.getTypedRuleContexts(ExpressionContext); - } else { - return this.getTypedRuleContext(ExpressionContext,i); - } - }; - - OR() { - return this.getToken(PolicyParser.OR, 0); - }; - - enterRule(listener) { - if(listener instanceof PolicyListener ) { - listener.enterBooleanOrExpression(this); - } - } - - exitRule(listener) { - if(listener instanceof PolicyListener ) { - listener.exitBooleanOrExpression(this); - } - } + OR() { + return this.getToken(PolicyParser.OR, 0); + } + enterRule(listener) { + if (listener instanceof PolicyListener) { + listener.enterBooleanOrExpression(this); + } + } + exitRule(listener) { + if (listener instanceof PolicyListener) { + listener.exitBooleanOrExpression(this); + } + } } PolicyParser.BooleanOrExpressionContext = BooleanOrExpressionContext; class CountExpressionContext extends ExpressionContext { - - constructor(parser, ctx) { - super(parser); - super.copyFrom(ctx); + constructor(parser, ctx) { + super(parser); + super.copyFrom(ctx); + } + + count_expression() { + return this.getTypedRuleContext(Count_expressionContext, 0); + } + + enterRule(listener) { + if (listener instanceof PolicyListener) { + listener.enterCountExpression(this); } + } - count_expression() { - return this.getTypedRuleContext(Count_expressionContext,0); - }; - - enterRule(listener) { - if(listener instanceof PolicyListener ) { - listener.enterCountExpression(this); - } - } - - exitRule(listener) { - if(listener instanceof PolicyListener ) { - listener.exitCountExpression(this); - } - } - - + exitRule(listener) { + if (listener instanceof PolicyListener) { + listener.exitCountExpression(this); + } + } } PolicyParser.CountExpressionContext = CountExpressionContext; class BooleanAndExpressionContext extends ExpressionContext { - - constructor(parser, ctx) { - super(parser); - super.copyFrom(ctx); + constructor(parser, ctx) { + super(parser); + super.copyFrom(ctx); + } + + expression = function (i) { + if (i === undefined) { + i = null; } + if (i === null) { + return this.getTypedRuleContexts(ExpressionContext); + } else { + return this.getTypedRuleContext(ExpressionContext, i); + } + }; - expression = function(i) { - if(i===undefined) { - i = null; - } - if(i===null) { - return this.getTypedRuleContexts(ExpressionContext); - } else { - return this.getTypedRuleContext(ExpressionContext,i); - } - }; - - AND() { - return this.getToken(PolicyParser.AND, 0); - }; - - enterRule(listener) { - if(listener instanceof PolicyListener ) { - listener.enterBooleanAndExpression(this); - } - } - - exitRule(listener) { - if(listener instanceof PolicyListener ) { - listener.exitBooleanAndExpression(this); - } - } + AND() { + return this.getToken(PolicyParser.AND, 0); + } + enterRule(listener) { + if (listener instanceof PolicyListener) { + listener.enterBooleanAndExpression(this); + } + } + exitRule(listener) { + if (listener instanceof PolicyListener) { + listener.exitBooleanAndExpression(this); + } + } } PolicyParser.BooleanAndExpressionContext = BooleanAndExpressionContext; class Count_expressionContext extends antlr4.ParserRuleContext { - - constructor(parser, parent, invokingState) { - if(parent===undefined) { - parent = null; - } - if(invokingState===undefined || invokingState===null) { - invokingState = -1; - } - super(parent, invokingState); - this.parser = parser; - this.ruleIndex = PolicyParser.RULE_count_expression; + constructor(parser, parent, invokingState) { + if (parent === undefined) { + parent = null; } + if (invokingState === undefined || invokingState === null) { + invokingState = -1; + } + super(parent, invokingState); + this.parser = parser; + this.ruleIndex = PolicyParser.RULE_count_expression; + } + + COUNT() { + return this.getToken(PolicyParser.COUNT, 0); + } + + INTLIT() { + return this.getToken(PolicyParser.INTLIT, 0); + } + + GREATER_THAN() { + return this.getToken(PolicyParser.GREATER_THAN, 0); + } + + GREATER_THAN_EQUAL() { + return this.getToken(PolicyParser.GREATER_THAN_EQUAL, 0); + } + + LESS_THAN() { + return this.getToken(PolicyParser.LESS_THAN, 0); + } + + LESS_THAN_EQUAL() { + return this.getToken(PolicyParser.LESS_THAN_EQUAL, 0); + } + + enterRule(listener) { + if (listener instanceof PolicyListener) { + listener.enterCount_expression(this); + } + } - COUNT() { - return this.getToken(PolicyParser.COUNT, 0); - }; - - INTLIT() { - return this.getToken(PolicyParser.INTLIT, 0); - }; - - GREATER_THAN() { - return this.getToken(PolicyParser.GREATER_THAN, 0); - }; - - GREATER_THAN_EQUAL() { - return this.getToken(PolicyParser.GREATER_THAN_EQUAL, 0); - }; - - LESS_THAN() { - return this.getToken(PolicyParser.LESS_THAN, 0); - }; - - LESS_THAN_EQUAL() { - return this.getToken(PolicyParser.LESS_THAN_EQUAL, 0); - }; - - enterRule(listener) { - if(listener instanceof PolicyListener ) { - listener.enterCount_expression(this); - } - } - - exitRule(listener) { - if(listener instanceof PolicyListener ) { - listener.exitCount_expression(this); - } - } - - + exitRule(listener) { + if (listener instanceof PolicyListener) { + listener.exitCount_expression(this); + } + } } - - - -PolicyParser.RootContext = RootContext; -PolicyParser.ExpressionContext = ExpressionContext; -PolicyParser.Count_expressionContext = Count_expressionContext; +PolicyParser.RootContext = RootContext; +PolicyParser.ExpressionContext = ExpressionContext; +PolicyParser.Count_expressionContext = Count_expressionContext; diff --git a/weaver/common/policy-dsl/test/Helper.js b/weaver/common/policy-dsl/test/Helper.js index 38f9517ec8..cc38d8030b 100644 --- a/weaver/common/policy-dsl/test/Helper.js +++ b/weaver/common/policy-dsl/test/Helper.js @@ -4,48 +4,48 @@ * SPDX-License-Identifier: Apache-2.0 */ -import antlr4 from "antlr4" +import antlr4 from "antlr4"; -import PolicyLexer from "../parser/PolicyLexer.js" -import PolicyParser from "../parser/PolicyParser.js" -import MyErrorListener from "./MyErrorListener.js" +import PolicyLexer from "../parser/PolicyLexer.js"; +import PolicyParser from "../parser/PolicyParser.js"; +import MyErrorListener from "./MyErrorListener.js"; export const parse = (source) => { - // create parser - const chars = new antlr4.InputStream(source) - const lexer = new PolicyLexer(chars) - const tokens = new antlr4.CommonTokenStream(lexer) - const parser = new PolicyParser(tokens) - parser.buildParseTrees = true - - // Add error handlers - lexer.removeErrorListeners() - parser.removeErrorListeners() - const errorListener = new MyErrorListener() - lexer.addErrorListener(errorListener) - parser.addErrorListener(errorListener) - - // parse the input - const res = parser.root() - - return { - parserResult: res, - errors: errorListener.result, - } -} + // create parser + const chars = new antlr4.InputStream(source); + const lexer = new PolicyLexer(chars); + const tokens = new antlr4.CommonTokenStream(lexer); + const parser = new PolicyParser(tokens); + parser.buildParseTrees = true; + + // Add error handlers + lexer.removeErrorListeners(); + parser.removeErrorListeners(); + const errorListener = new MyErrorListener(); + lexer.addErrorListener(errorListener); + parser.addErrorListener(errorListener); + + // parse the input + const res = parser.root(); + + return { + parserResult: res, + errors: errorListener.result, + }; +}; // helper function to print the parseTree, for debugging export const traverseParseTree = (rootCtx) => { - rootCtx.children?.forEach((c) => { - console.log( - c.constructor.name, - ":", - c.getText(), - c.symbol ? c.symbol.type : "" - ) - traverseParseTree(c) - console.log("leaving children of: ", c.getText()) - }) -} - -export default { parse, traverseParseTree } + rootCtx.children?.forEach((c) => { + console.log( + c.constructor.name, + ":", + c.getText(), + c.symbol ? c.symbol.type : "", + ); + traverseParseTree(c); + console.log("leaving children of: ", c.getText()); + }); +}; + +export default { parse, traverseParseTree }; diff --git a/weaver/common/policy-dsl/test/MyErrorListener.js b/weaver/common/policy-dsl/test/MyErrorListener.js index c59b43b998..3ee1ba3f42 100644 --- a/weaver/common/policy-dsl/test/MyErrorListener.js +++ b/weaver/common/policy-dsl/test/MyErrorListener.js @@ -9,11 +9,11 @@ * ANTLR and converting these to an array of messages */ export default class MyErrorListener { - constructor() { - this.result = []; - } + constructor() { + this.result = []; + } - syntaxError(recognizer, offendingSymbol, line, column, msg, e) { - this.result.push({message: msg, errorSrc: recognizer.constructor.name }); - } + syntaxError(recognizer, offendingSymbol, line, column, msg, e) { + this.result.push({ message: msg, errorSrc: recognizer.constructor.name }); + } } diff --git a/weaver/common/policy-dsl/test/MyParseTreeVisitor.js b/weaver/common/policy-dsl/test/MyParseTreeVisitor.js index df98c68e11..904f6088c4 100644 --- a/weaver/common/policy-dsl/test/MyParseTreeVisitor.js +++ b/weaver/common/policy-dsl/test/MyParseTreeVisitor.js @@ -8,23 +8,23 @@ // of parsing, and while walking the parser tree. It is a more abstract version of what is // parsed, which is more suitable for static analysis -import PolicyParser from "../parser/PolicyParser.js" +import PolicyParser from "../parser/PolicyParser.js"; // Generic Node object that all nodes are based off export class Node { - constructor() { - this.children = [] - this.value = undefined - } - - addChild(node) { - this.children.push(node) - } - - accept(visitor) { - visitor.visit(this) - this.children.forEach((c) => c.accept(visitor)) - } + constructor() { + this.children = []; + this.value = undefined; + } + + addChild(node) { + this.children.push(node); + } + + accept(visitor) { + visitor.visit(this); + this.children.forEach((c) => c.accept(visitor)); + } } export class RootNode extends Node {} @@ -36,171 +36,162 @@ export class CountOperatorNode extends Node {} export class IntNode extends Node {} export default class Visitor { - constructor() { - this.root = null - this.stack = [] - } - - printTreePreOrder(node) { - const output = [] - - // function to recursively traverse tree - const f = (node) => { - if (node.children) { - node.children.forEach((child) => { - output.push( - [ - child.constructor.name, - child.value ? child.value : "", - ].join(" ") - ) - f(child) - }) - } - } - f(node) - return output + constructor() { + this.root = null; + this.stack = []; + } + + printTreePreOrder(node) { + const output = []; + + // function to recursively traverse tree + const f = (node) => { + if (node.children) { + node.children.forEach((child) => { + output.push( + [child.constructor.name, child.value ? child.value : ""].join(" "), + ); + f(child); + }); + } + }; + f(node); + return output; + } + + pushNode(node) { + this.stack.push(node); + } + + popNode() { + return this.stack.pop(); + } + + peekNode() { + return this.stack[this.stack.length - 1]; + } + + visitChildren(ctx) { + if (!ctx) { + return; } - pushNode(node) { - this.stack.push(node) + // handle current node + if (ctx.constructor.name === "RootContext") { + // Add to the top of the stack + const rootNode = new RootNode(); + this.root = rootNode; + this.pushNode(rootNode); + } else if ( + ctx.constructor.name === "BooleanAndExpressionContext" || + ctx.constructor.name === "BooleanOrExpressionContext" + ) { + // check if a node needs to be popped off the stack. + // If the current nodes parent (node at end of stack) already has 1 child that + // is another BooleanExpression or CountExpression then that means we are going + // down a new branch and need to pop a node off the stack + const parentNode = this.peekNode(); + if ( + parentNode.children.length === 1 && + (parentNode.children[0].constructor.name === "BooleanExpressionNode" || + parentNode.children[0].constructor.name === "CountExpressionNode") + ) { + this.popNode(); + } + + // Add node as a child to the node at the top of the stack, + // this will either be the RootNode or another BooleanExpressionNode + const n = new BooleanExpressionNode(); + n.value = + ctx.constructor.name === "BooleanAndExpressionContext" ? "&&" : "||"; + this.stack[this.stack.length - 1].addChild(n); + + // Add to the top of the stack + this.pushNode(n); + } else if (ctx.constructor.name === "IdExpressionContext") { + // Add node as a child to the node at the top of the stack, + // this will always be a BooleanExpressionNode + const n = new IDNode(); + n.value = ctx.getText(); + this.stack[this.stack.length - 1].addChild(n); + } else if (ctx.constructor.name === "CountExpressionContext") { + // don't need to do anything here, since its all handled in + // Count_expressionContext + // return + } else if (ctx.constructor.name === "Count_expressionContext") { + // check if a node needs to be popped off the stack. + // If the current nodes parent (node at end of stack) already has 1 child that + // is another BooleanExpression or CountExpression then that means we are going + // down a new branch and need to pop a node off the stack + const parentNode = this.peekNode(); + if ( + parentNode.children.length === 1 && + (parentNode.children[0].constructor.name === "BooleanExpressionNode" || + parentNode.children[0].constructor.name === "CountExpressionNode") + ) { + this.popNode(); + } + + // Add node as a child to the node at the top of the stack, + // this will either be the RootNode or a BooleanExpressionNode + const n = new CountExpressionNode(); + // this value won't be used for static analysis, it's just set for printing/debugging + n.value = ctx.getText(); + this.stack[this.stack.length - 1].addChild(n); + + // Add to the top of the stack + this.pushNode(n); + } else { + console.error("UNKNOWN NODE TYPE"); + return; } - popNode() { - return this.stack.pop() - } - - peekNode() { - return this.stack[this.stack.length - 1] - } - - visitChildren(ctx) { - if (!ctx) { - return - } - - // handle current node - if (ctx.constructor.name === "RootContext") { - // Add to the top of the stack - const rootNode = new RootNode() - this.root = rootNode - this.pushNode(rootNode) - } else if ( - ctx.constructor.name === "BooleanAndExpressionContext" || - ctx.constructor.name === "BooleanOrExpressionContext" - ) { - // check if a node needs to be popped off the stack. - // If the current nodes parent (node at end of stack) already has 1 child that - // is another BooleanExpression or CountExpression then that means we are going - // down a new branch and need to pop a node off the stack - const parentNode = this.peekNode() - if ( - parentNode.children.length === 1 && - (parentNode.children[0].constructor.name === - "BooleanExpressionNode" || - parentNode.children[0].constructor.name === - "CountExpressionNode") - ) { - this.popNode() - } - - // Add node as a child to the node at the top of the stack, - // this will either be the RootNode or another BooleanExpressionNode - const n = new BooleanExpressionNode() - n.value = - ctx.constructor.name === "BooleanAndExpressionContext" - ? "&&" - : "||" - this.stack[this.stack.length - 1].addChild(n) - - // Add to the top of the stack - this.pushNode(n) - } else if (ctx.constructor.name === "IdExpressionContext") { - // Add node as a child to the node at the top of the stack, - // this will always be a BooleanExpressionNode - const n = new IDNode() - n.value = ctx.getText() - this.stack[this.stack.length - 1].addChild(n) - } else if (ctx.constructor.name === "CountExpressionContext") { - // don't need to do anything here, since its all handled in - // Count_expressionContext - // return - } else if (ctx.constructor.name === "Count_expressionContext") { - // check if a node needs to be popped off the stack. - // If the current nodes parent (node at end of stack) already has 1 child that - // is another BooleanExpression or CountExpression then that means we are going - // down a new branch and need to pop a node off the stack - const parentNode = this.peekNode() - if ( - parentNode.children.length === 1 && - (parentNode.children[0].constructor.name === - "BooleanExpressionNode" || - parentNode.children[0].constructor.name === - "CountExpressionNode") - ) { - this.popNode() - } - - // Add node as a child to the node at the top of the stack, - // this will either be the RootNode or a BooleanExpressionNode - const n = new CountExpressionNode() - // this value won't be used for static analysis, it's just set for printing/debugging - n.value = ctx.getText() - this.stack[this.stack.length - 1].addChild(n) - - // Add to the top of the stack - this.pushNode(n) - } else { - console.error("UNKNOWN NODE TYPE") - return - } - - // keep traversing tree - if (ctx.children) { - ctx.children.forEach((child) => { - child.accept(this) - }) - } - } - - visitTerminal(node) { - // only need to look at terminal nodes for a count expression. - // All other terminal nodes are duplicates since they are unique - // expression in the Policy grammar (i.e. Have alt labels that generate - // nodes) - if (node.symbol && node.symbol.type === PolicyParser.COUNT) { - // Add node as a child to the node at the top of the stack, - // this will always be a CountExpressionNode - const n = new CountNode() - n.value = node.getText() - this.stack[this.stack.length - 1].addChild(n) - } else if (node.symbol && node.symbol.type === PolicyParser.INTLIT) { - // Add node as a child to the node at the top of the stack, - // this will always be a CountExpressionNode - const n = new IntNode() - n.value = node.getText() - this.stack[this.stack.length - 1].addChild(n) - } else if ( - node.symbol && - (node.symbol.type === PolicyParser.GREATER_THAN || - node.symbol.type === PolicyParser.GREATER_THAN_EQUAL || - node.symbol.type === PolicyParser.LESS_THAN || - node.symbol.type === PolicyParser.LESS_THAN_EQUAL || - node.symbol.type === PolicyParser.EQUAL) - ) { - // Add node as a child to the node at the top of the stack, - // this will always be a CountExpressionNode - const n = new CountOperatorNode() - n.value = node.getText() - this.stack[this.stack.length - 1].addChild(n) - } - return - } - visitErrorNode(node) { - console.log("visiting error node") - return + // keep traversing tree + if (ctx.children) { + ctx.children.forEach((child) => { + child.accept(this); + }); } - visit(node) { - console.log("omg hi", node.getText()) + } + + visitTerminal(node) { + // only need to look at terminal nodes for a count expression. + // All other terminal nodes are duplicates since they are unique + // expression in the Policy grammar (i.e. Have alt labels that generate + // nodes) + if (node.symbol && node.symbol.type === PolicyParser.COUNT) { + // Add node as a child to the node at the top of the stack, + // this will always be a CountExpressionNode + const n = new CountNode(); + n.value = node.getText(); + this.stack[this.stack.length - 1].addChild(n); + } else if (node.symbol && node.symbol.type === PolicyParser.INTLIT) { + // Add node as a child to the node at the top of the stack, + // this will always be a CountExpressionNode + const n = new IntNode(); + n.value = node.getText(); + this.stack[this.stack.length - 1].addChild(n); + } else if ( + node.symbol && + (node.symbol.type === PolicyParser.GREATER_THAN || + node.symbol.type === PolicyParser.GREATER_THAN_EQUAL || + node.symbol.type === PolicyParser.LESS_THAN || + node.symbol.type === PolicyParser.LESS_THAN_EQUAL || + node.symbol.type === PolicyParser.EQUAL) + ) { + // Add node as a child to the node at the top of the stack, + // this will always be a CountExpressionNode + const n = new CountOperatorNode(); + n.value = node.getText(); + this.stack[this.stack.length - 1].addChild(n); } + return; + } + visitErrorNode(node) { + console.log("visiting error node"); + return; + } + visit(node) { + console.log("omg hi", node.getText()); + } } diff --git a/weaver/common/policy-dsl/test/ast.test.js b/weaver/common/policy-dsl/test/ast.test.js index 7c4ae8a9b6..cbdea876bf 100644 --- a/weaver/common/policy-dsl/test/ast.test.js +++ b/weaver/common/policy-dsl/test/ast.test.js @@ -6,42 +6,42 @@ // Tests to check that the AST is correctly generated from the parse tree // using MyParseTreeVisitor -import test from "ava" +import test from "ava"; -import { parse } from "./Helper.js" -import MyParseTreeVisitor from "./MyParseTreeVisitor.js" +import { parse } from "./Helper.js"; +import MyParseTreeVisitor from "./MyParseTreeVisitor.js"; test("AST: Boolean operators", (t) => { - const res = parse("org1 && org2 || org3") - t.true(res.errors.length === 0) - - const visitor = new MyParseTreeVisitor() - res.parserResult.accept(visitor) - const output = visitor.printTreePreOrder(visitor.root) - const expected = [ - "BooleanExpressionNode ||", - "BooleanExpressionNode &&", - "IDNode org1", - "IDNode org2", - "IDNode org3", - ] - - t.deepEqual(output, expected) -}) + const res = parse("org1 && org2 || org3"); + t.true(res.errors.length === 0); + + const visitor = new MyParseTreeVisitor(); + res.parserResult.accept(visitor); + const output = visitor.printTreePreOrder(visitor.root); + const expected = [ + "BooleanExpressionNode ||", + "BooleanExpressionNode &&", + "IDNode org1", + "IDNode org2", + "IDNode org3", + ]; + + t.deepEqual(output, expected); +}); test("AST: Count expression", (t) => { - const res = parse("count > 2") - t.true(res.errors.length === 0) - - const visitor = new MyParseTreeVisitor() - res.parserResult.accept(visitor) - const output = visitor.printTreePreOrder(visitor.root) - const expected = [ - "CountExpressionNode count>2", - "CountNode count", - "CountOperatorNode >", - "IntNode 2", - ] - - t.deepEqual(output, expected) -}) + const res = parse("count > 2"); + t.true(res.errors.length === 0); + + const visitor = new MyParseTreeVisitor(); + res.parserResult.accept(visitor); + const output = visitor.printTreePreOrder(visitor.root); + const expected = [ + "CountExpressionNode count>2", + "CountNode count", + "CountOperatorNode >", + "IntNode 2", + ]; + + t.deepEqual(output, expected); +}); diff --git a/weaver/common/policy-dsl/test/lexer.test.js b/weaver/common/policy-dsl/test/lexer.test.js index c04081c423..ef3b491709 100644 --- a/weaver/common/policy-dsl/test/lexer.test.js +++ b/weaver/common/policy-dsl/test/lexer.test.js @@ -4,56 +4,62 @@ * SPDX-License-Identifier: Apache-2.0 */ -import test from 'ava' -import antlr4 from 'antlr4' -import PolicyLexer from "../parser/PolicyLexer.js" -import MyErrorListener from "./MyErrorListener.js" - -test("Lexer: Basic boolean expression", t => { - const res = tokenize('org1 && org2') - t.deepEqual(res.tokens, [ "ID", "AND", "ID", "EOF"]) -}) - -test("Lexer: Expression with count", t => { - const res = tokenize('org1 || count > 2') - t.deepEqual(res.tokens, [ "ID", "OR", "COUNT", "GREATER_THAN", "INTLIT", "EOF"]) -}) - -test("Lexer: Chained expressions", t => { - const res = tokenize('org1 && org2 || org3') - t.deepEqual(res.tokens, [ "ID", "AND", "ID", "OR", "ID", "EOF"]) -}) - -test("Lexer: Invalid token", t => { - const res = tokenize('org1 & org2 || org3') - t.true(res.errors.length === 1) -}) +import test from "ava"; +import antlr4 from "antlr4"; +import PolicyLexer from "../parser/PolicyLexer.js"; +import MyErrorListener from "./MyErrorListener.js"; + +test("Lexer: Basic boolean expression", (t) => { + const res = tokenize("org1 && org2"); + t.deepEqual(res.tokens, ["ID", "AND", "ID", "EOF"]); +}); + +test("Lexer: Expression with count", (t) => { + const res = tokenize("org1 || count > 2"); + t.deepEqual(res.tokens, [ + "ID", + "OR", + "COUNT", + "GREATER_THAN", + "INTLIT", + "EOF", + ]); +}); + +test("Lexer: Chained expressions", (t) => { + const res = tokenize("org1 && org2 || org3"); + t.deepEqual(res.tokens, ["ID", "AND", "ID", "OR", "ID", "EOF"]); +}); + +test("Lexer: Invalid token", (t) => { + const res = tokenize("org1 & org2 || org3"); + t.true(res.errors.length === 1); +}); const tokenize = (input) => { - // create tokenizer - const chars = new antlr4.InputStream(input); - const lexer = new PolicyLexer(chars); - const tokens = new antlr4.CommonTokenStream(lexer); - - // Add error handler - lexer.removeErrorListeners() - const errorListener = new MyErrorListener() - lexer.addErrorListener(errorListener) - - // tokenize the input https://stackoverflow.com/a/30676622 - tokens.fill() - - const ts = tokens.tokens.map(tok => { - if (tok.type === -1) { - return "EOF" - } else { - return PolicyLexer.ruleNames[tok.type - 1] - } - }) - - return { - tokens: ts, - errors: errorListener.result + // create tokenizer + const chars = new antlr4.InputStream(input); + const lexer = new PolicyLexer(chars); + const tokens = new antlr4.CommonTokenStream(lexer); + + // Add error handler + lexer.removeErrorListeners(); + const errorListener = new MyErrorListener(); + lexer.addErrorListener(errorListener); + + // tokenize the input https://stackoverflow.com/a/30676622 + tokens.fill(); + + const ts = tokens.tokens.map((tok) => { + if (tok.type === -1) { + return "EOF"; + } else { + return PolicyLexer.ruleNames[tok.type - 1]; } -} + }); + return { + tokens: ts, + errors: errorListener.result, + }; +}; diff --git a/weaver/common/policy-dsl/test/parser.test.js b/weaver/common/policy-dsl/test/parser.test.js index 2ba1aedeb9..9565d1a817 100644 --- a/weaver/common/policy-dsl/test/parser.test.js +++ b/weaver/common/policy-dsl/test/parser.test.js @@ -4,30 +4,30 @@ * SPDX-License-Identifier: Apache-2.0 */ -import test from "ava" +import test from "ava"; -import { parse } from "./Helper.js" +import { parse } from "./Helper.js"; test("Parser: Boolean operators", (t) => { - const res = parse("org1 && org2 || org3") + const res = parse("org1 && org2 || org3"); - t.true(res.errors.length === 0) -}) + t.true(res.errors.length === 0); +}); test("Parser: All expressions", (t) => { - const res = parse("org1 && org2 && org3 || count > 3") + const res = parse("org1 && org2 && org3 || count > 3"); - t.true(res.errors.length === 0) -}) + t.true(res.errors.length === 0); +}); test("Parser: Count expression", (t) => { - const res = parse("count > 2") + const res = parse("count > 2"); - t.true(res.errors.length === 0) -}) + t.true(res.errors.length === 0); +}); test("Parser: Invalid syntax", (t) => { - const res = parse("org1 && count") + const res = parse("org1 && count"); - t.true(res.errors.length === 1) -}) + t.true(res.errors.length === 1); +}); diff --git a/weaver/core/drivers/fabric-driver/.eslintrc b/weaver/core/drivers/fabric-driver/.eslintrc deleted file mode 100644 index 7c492a1893..0000000000 --- a/weaver/core/drivers/fabric-driver/.eslintrc +++ /dev/null @@ -1,26 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", // Specifies the ESLint parser - "parserOptions": { - "ecmaVersion": 2020, // Allows for the parsing of modern ECMAScript features - "sourceType": "module", // Allows for the use of imports - "ecmaFeatures": { - "jsx": true // Allows for the parsing of JSX - } - }, - "settings": { - "react": { - "version": "detect" // Tells eslint-plugin-react to automatically detect the version of React to use - } - }, - "ignorePatterns": ["**/out/*.js", "**/protos-js/"], - "extends": [ - "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin - "prettier", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - "rules": { - "@typescript-eslint/ban-ts-comment": "off" - // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs - // e.g. "@typescript-eslint/explicit-function-return-type": "off", - } -} diff --git a/weaver/core/drivers/fabric-driver/.prettierrc b/weaver/core/drivers/fabric-driver/.prettierrc deleted file mode 100644 index 2f316681a1..0000000000 --- a/weaver/core/drivers/fabric-driver/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "semi": true, - "trailingComma": "all", - "singleQuote": true, - "printWidth": 120, - "tabWidth": 4 -} diff --git a/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile b/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile index 77a7b2a41b..83b55dbea9 100644 --- a/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile +++ b/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile @@ -19,8 +19,6 @@ RUN npm install --unsafe-perm ADD server /driver/fabric/server ADD constants /driver/fabric/constants ADD tsconfig.json . -ADD .eslintrc . -ADD .prettierrc . RUN npm run build diff --git a/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile.local b/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile.local index 0745258257..500ad885d0 100644 --- a/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile.local +++ b/weaver/core/drivers/fabric-driver/fabricDriver.dockerfile.local @@ -14,8 +14,6 @@ ADD server /driver/fabric/server ADD constants /driver/fabric/constants ADD config.json . ADD tsconfig.json . -ADD .eslintrc . -ADD .prettierrc . RUN npm run build diff --git a/weaver/core/drivers/fabric-driver/package-local.json b/weaver/core/drivers/fabric-driver/package-local.json index 87f2365a27..0a3e18caaf 100644 --- a/weaver/core/drivers/fabric-driver/package-local.json +++ b/weaver/core/drivers/fabric-driver/package-local.json @@ -12,7 +12,6 @@ "scripts": { "build": "npm run tsc", "dev": "nodemon out/server.js", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "start": "node out/server.js", "test": "echo \"Error: no test specified\" && exit 1", "tsc": "tsc", @@ -23,11 +22,7 @@ "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "file:./protos-js", "@hyperledger/cacti-weaver-sdk-fabric": "file:./cacti-weaver-sdk-fabric", - "@typescript-eslint/eslint-plugin": "5.62.0", - "@typescript-eslint/parser": "5.62.0", "dotenv": "8.6.0", - "eslint-config-prettier": "8.9.0", - "eslint-plugin-prettier": "5.0.0", "fabric-ca-client": "2.2.20", "fabric-common": "2.2.20", "fabric-network": "2.2.20", diff --git a/weaver/core/drivers/fabric-driver/package.json b/weaver/core/drivers/fabric-driver/package.json index 725c711ec8..b0a9ec8a6a 100644 --- a/weaver/core/drivers/fabric-driver/package.json +++ b/weaver/core/drivers/fabric-driver/package.json @@ -12,7 +12,6 @@ "scripts": { "build": "npm run tsc", "dev": "nodemon out/server.js", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "start": "node out/server.js", "test": "echo \"Error: no test specified\" && exit 1", "tsc": "tsc", @@ -23,11 +22,7 @@ "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "2.0.0-alpha.2", "@hyperledger/cacti-weaver-sdk-fabric": "2.0.0-alpha.2", - "@typescript-eslint/eslint-plugin": "5.62.0", - "@typescript-eslint/parser": "5.62.0", "dotenv": "8.6.0", - "eslint-config-prettier": "8.9.0", - "eslint-plugin-prettier": "5.0.0", "fabric-ca-client": "2.2.20", "fabric-common": "2.2.20", "fabric-network": "2.2.20", diff --git a/weaver/core/drivers/fabric-driver/server/dbConnector.ts b/weaver/core/drivers/fabric-driver/server/dbConnector.ts index 2db36bb0d8..e46b8fd765 100644 --- a/weaver/core/drivers/fabric-driver/server/dbConnector.ts +++ b/weaver/core/drivers/fabric-driver/server/dbConnector.ts @@ -4,245 +4,265 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Level } from 'level'; -import * as path from 'path'; -import logger from './logger'; -import { delay } from './utils'; +import { Level } from "level"; +import * as path from "path"; +import logger from "./logger"; +import { delay } from "./utils"; /* - * Interfaces for all database connectors to be used for event subscriptions + * Interfaces for all database connectors to be used for event subscriptions */ interface DBConnector { - // type of the DB (LevelDB, MongoDB, etc.) - DB_TYPE: string; - // name of the map - DB_NAME: string; - // connection to the DB - dbHandle: any; - - // open the database connection - open(): Promise; - // interface to add a pair to the database - insert(key: any, value: any): Promise; - // interface to read a key from the database - read(key: any): Promise; - // interface to update a key's value in the database - update(key: any, value: any): Promise; - // interface to delete a key from the database - delete(key: any): Promise; - // get iterator - filteredRead(keyFilterCallback : (key: any, targetKey: any) => boolean, targetKey: any): Promise>; - // get All keys - getAllKeys(): Promise>; - // close the database connection - close(): Promise; + // type of the DB (LevelDB, MongoDB, etc.) + DB_TYPE: string; + // name of the map + DB_NAME: string; + // connection to the DB + dbHandle: any; + + // open the database connection + open(): Promise; + // interface to add a pair to the database + insert(key: any, value: any): Promise; + // interface to read a key from the database + read(key: any): Promise; + // interface to update a key's value in the database + update(key: any, value: any): Promise; + // interface to delete a key from the database + delete(key: any): Promise; + // get iterator + filteredRead( + keyFilterCallback: (key: any, targetKey: any) => boolean, + targetKey: any, + ): Promise>; + // get All keys + getAllKeys(): Promise>; + // close the database connection + close(): Promise; } // Implementation of DBConnector for LevelDB class LevelDBConnector implements DBConnector { + DB_TYPE: string = "Level"; + DB_NAME: string; + dbHandle: any; + dbOpenMaxRetries: number; + dbRetryBackoffTime: number; - DB_TYPE: string = "Level"; - DB_NAME: string; - dbHandle: any; - dbOpenMaxRetries: number; - dbRetryBackoffTime: number; - - constructor( - dbName: string, - retryTimeout: number = 0 - ) { - if (!dbName || dbName.length == 0) { - dbName = "driverdb"; - } - this.DB_NAME = dbName; - this.dbHandle = new Level(path.join(process.env.DB_PATH ? process.env.DB_PATH : "./driverdbs", dbName), { valueEncoding: 'json' }); - // Retry max attempts, default 250, making it 5 seconds for retries - this.dbOpenMaxRetries = process.env.LEVELDB_LOCKED_MAX_RETRIES ? parseInt(process.env.LEVELDB_LOCKED_MAX_RETRIES) : 250; - // Retry back off time in ms, default 20ms - this.dbRetryBackoffTime = process.env.LEVELDB_LOCKED_RETRY_BACKOFF_MSEC ? parseInt(process.env.LEVELDB_LOCKED_RETRY_BACKOFF_MSEC) : 20; - if (retryTimeout > 0) { - this.dbOpenMaxRetries = Math.floor(retryTimeout / this.dbRetryBackoffTime); - } + constructor(dbName: string, retryTimeout: number = 0) { + if (!dbName || dbName.length == 0) { + dbName = "driverdb"; } + this.DB_NAME = dbName; + this.dbHandle = new Level( + path.join( + process.env.DB_PATH ? process.env.DB_PATH : "./driverdbs", + dbName, + ), + { + valueEncoding: "json", + }, + ); + // Retry max attempts, default 250, making it 5 seconds for retries + this.dbOpenMaxRetries = process.env.LEVELDB_LOCKED_MAX_RETRIES + ? parseInt(process.env.LEVELDB_LOCKED_MAX_RETRIES) + : 250; + // Retry back off time in ms, default 20ms + this.dbRetryBackoffTime = process.env.LEVELDB_LOCKED_RETRY_BACKOFF_MSEC + ? parseInt(process.env.LEVELDB_LOCKED_RETRY_BACKOFF_MSEC) + : 20; + if (retryTimeout > 0) { + this.dbOpenMaxRetries = Math.floor( + retryTimeout / this.dbRetryBackoffTime, + ); + } + } - async open( - i: number = 0 - ): Promise { - logger.debug(`attempt #${i} to open database ${this.DB_NAME}`) - try { - await this.dbHandle.open(); - } catch (error: any) { - if (i >= this.dbOpenMaxRetries) { - logger.error(`failed to open database connection with error: ${error.toString()}`); - if (error.code == 'LEVEL_DATABASE_NOT_OPEN' && error.cause && error.cause.code == 'LEVEL_LOCKED') { - throw new DBLockedError(error.toString()); - } else { - throw new DBNotOpenError(error.toString()); - } - } - else { - logger.debug(`failed to open database connection with error: ${error.toString()}`); - await delay(this.dbRetryBackoffTime); - await this.open(i+1); - } + async open(i: number = 0): Promise { + logger.debug(`attempt #${i} to open database ${this.DB_NAME}`); + try { + await this.dbHandle.open(); + } catch (error: any) { + if (i >= this.dbOpenMaxRetries) { + logger.error( + `failed to open database connection with error: ${error.toString()}`, + ); + if ( + error.code == "LEVEL_DATABASE_NOT_OPEN" && + error.cause && + error.cause.code == "LEVEL_LOCKED" + ) { + throw new DBLockedError(error.toString()); + } else { + throw new DBNotOpenError(error.toString()); } - - return true; + } else { + logger.debug( + `failed to open database connection with error: ${error.toString()}`, + ); + await delay(this.dbRetryBackoffTime); + await this.open(i + 1); + } } - async insert( - key: any, - value: any - ): Promise { - try { - await this.dbHandle.put(key, value); - } catch (error: any) { - logger.error(`failed to insert key ${JSON.stringify(key)} with error: ${error.toString()}`); - if (error.code == 'LEVEL_DATABASE_NOT_OPEN') { - throw new DBNotOpenError(error.toString()); - } else { - throw new DBError(error.toString()); - } - } + return true; + } - return true; + async insert(key: any, value: any): Promise { + try { + await this.dbHandle.put(key, value); + } catch (error: any) { + logger.error( + `failed to insert key ${JSON.stringify(key)} with error: ${error.toString()}`, + ); + if (error.code == "LEVEL_DATABASE_NOT_OPEN") { + throw new DBNotOpenError(error.toString()); + } else { + throw new DBError(error.toString()); + } } - async read( - key: any - ): Promise { - var value: any - try { - value = await this.dbHandle.get(key); - logger.debug(`read() got value: ${JSON.stringify(value)}`) - } catch (error: any) { - logger.error(`failed to read key ${JSON.stringify(key)} with error: ${error.toString()}`); - if (error.code == 'LEVEL_NOT_FOUND') { - throw new DBKeyNotFoundError(error.toString()); - } else if (error.code == 'LEVEL_DATABASE_NOT_OPEN') { - throw new DBNotOpenError(error.toString()); - } else { - throw new DBError(error.toString()); - } - } - - return value; + return true; + } + + async read(key: any): Promise { + let value: any; + try { + value = await this.dbHandle.get(key); + logger.debug(`read() got value: ${JSON.stringify(value)}`); + } catch (error: any) { + logger.error( + `failed to read key ${JSON.stringify(key)} with error: ${error.toString()}`, + ); + if (error.code == "LEVEL_NOT_FOUND") { + throw new DBKeyNotFoundError(error.toString()); + } else if (error.code == "LEVEL_DATABASE_NOT_OPEN") { + throw new DBNotOpenError(error.toString()); + } else { + throw new DBError(error.toString()); + } } - async update( - key: any, - value: any - ): Promise { - try { - await this.dbHandle.put(key, value); - } catch (error: any) { - logger.error(`failed to update key ${JSON.stringify(key)} with error: ${error.toString()}`); - if (error.code == 'LEVEL_DATABASE_NOT_OPEN') { - throw new DBNotOpenError(error.toString()); - } else { - throw new DBError(error.toString()); - } - } + return value; + } - return true; + async update(key: any, value: any): Promise { + try { + await this.dbHandle.put(key, value); + } catch (error: any) { + logger.error( + `failed to update key ${JSON.stringify(key)} with error: ${error.toString()}`, + ); + if (error.code == "LEVEL_DATABASE_NOT_OPEN") { + throw new DBNotOpenError(error.toString()); + } else { + throw new DBError(error.toString()); + } } - async delete( - key: any - ): Promise { - var value: any - try { - value = this.read(key); - await this.dbHandle.del(key); - } catch (error: any) { - logger.error(`failed to delete key ${JSON.stringify(key)} with error: ${error.toString()}`); - if (error.code == 'LEVEL_NOT_FOUND') { - throw new DBKeyNotFoundError(error.toString()); - } else if (error.code == 'LEVEL_DATABASE_NOT_OPEN') { - throw new DBNotOpenError(error.toString()); - } else { - throw new DBError(error.toString()); - } - } - - return value; - } + return true; + } - async filteredRead(keyFilterCallback : (key: any, targetKey: any) => boolean, targetKey: any): Promise> { - try { - let retVal = new Array(); - for await (const [key1, value1] of this.dbHandle.iterator()) { - if (keyFilterCallback(key1, targetKey)) { - retVal.push(value1); - } - } - - return retVal; - } catch (error: any) { - logger.error(`filteredRead error: ${error.toString()}`); - if (error.code == 'LEVEL_DATABASE_NOT_OPEN') { - throw new DBNotOpenError(error.toString()); - } else { - throw new DBError(error.toString()); - } - } + async delete(key: any): Promise { + let value: any; + try { + value = this.read(key); + await this.dbHandle.del(key); + } catch (error: any) { + logger.error( + `failed to delete key ${JSON.stringify(key)} with error: ${error.toString()}`, + ); + if (error.code == "LEVEL_NOT_FOUND") { + throw new DBKeyNotFoundError(error.toString()); + } else if (error.code == "LEVEL_DATABASE_NOT_OPEN") { + throw new DBNotOpenError(error.toString()); + } else { + throw new DBError(error.toString()); + } } - async close( - ): Promise { - try { - await this.dbHandle.close(); - } catch (error: any) { - logger.error(`failed to close database connection with error: ${error.toString()}`); - if (error.code == 'LEVEL_DATABASE_NOT_OPEN') { - throw new DBNotOpenError(error.toString()); - } else { - throw new DBError(error.toString()); - } + return value; + } + + async filteredRead( + keyFilterCallback: (key: any, targetKey: any) => boolean, + targetKey: any, + ): Promise> { + try { + const retVal = new Array(); + for await (const [key1, value1] of this.dbHandle.iterator()) { + if (keyFilterCallback(key1, targetKey)) { + retVal.push(value1); } + } - return true; + return retVal; + } catch (error: any) { + logger.error(`filteredRead error: ${error.toString()}`); + if (error.code == "LEVEL_DATABASE_NOT_OPEN") { + throw new DBNotOpenError(error.toString()); + } else { + throw new DBError(error.toString()); + } } + } - async getAllKeys():Promise> { - const keys = await this.dbHandle.keys().all(); - return keys; + async close(): Promise { + try { + await this.dbHandle.close(); + } catch (error: any) { + logger.error( + `failed to close database connection with error: ${error.toString()}`, + ); + if (error.code == "LEVEL_DATABASE_NOT_OPEN") { + throw new DBNotOpenError(error.toString()); + } else { + throw new DBError(error.toString()); + } } + + return true; + } + + async getAllKeys(): Promise> { + const keys = await this.dbHandle.keys().all(); + return keys; + } } class DBKeyNotFoundError extends Error { - constructor(msg: string) { - super(`key not found in database: ${msg}`); - Object.setPrototypeOf(this, DBKeyNotFoundError.prototype); - } + constructor(msg: string) { + super(`key not found in database: ${msg}`); + Object.setPrototypeOf(this, DBKeyNotFoundError.prototype); + } } class DBNotOpenError extends Error { - constructor(msg: string) { - super(`database is not open: ${msg}`); - Object.setPrototypeOf(this, DBNotOpenError.prototype); - } + constructor(msg: string) { + super(`database is not open: ${msg}`); + Object.setPrototypeOf(this, DBNotOpenError.prototype); + } } class DBLockedError extends Error { - constructor(msg: string) { - super(`database already in use: ${msg}`); - Object.setPrototypeOf(this, DBLockedError.prototype); - } + constructor(msg: string) { + super(`database already in use: ${msg}`); + Object.setPrototypeOf(this, DBLockedError.prototype); + } } class DBError extends Error { - constructor(msg: string) { - super(`database error: ${msg}`); - Object.setPrototypeOf(this, DBError.prototype); - } + constructor(msg: string) { + super(`database error: ${msg}`); + Object.setPrototypeOf(this, DBError.prototype); + } } export { - DBConnector, - LevelDBConnector, - DBLockedError, - DBKeyNotFoundError, - DBNotOpenError, - DBError -} + DBConnector, + LevelDBConnector, + DBLockedError, + DBKeyNotFoundError, + DBNotOpenError, + DBError, +}; diff --git a/weaver/core/drivers/fabric-driver/server/events.ts b/weaver/core/drivers/fabric-driver/server/events.ts index fb5879706d..b646028a18 100644 --- a/weaver/core/drivers/fabric-driver/server/events.ts +++ b/weaver/core/drivers/fabric-driver/server/events.ts @@ -4,470 +4,588 @@ * SPDX-License-Identifier: Apache-2.0 */ -import ack_pb from '@hyperledger/cacti-weaver-protos-js/common/ack_pb'; -import eventsPb from '@hyperledger/cacti-weaver-protos-js/common/events_pb'; -import events_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb'; -import queryPb from '@hyperledger/cacti-weaver-protos-js/common/query_pb'; -import { InteroperableHelper } from '@hyperledger/cacti-weaver-sdk-fabric'; +import ack_pb from "@hyperledger/cacti-weaver-protos-js/common/ack_pb"; +import eventsPb from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import events_grpc_pb from "@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb"; +import queryPb from "@hyperledger/cacti-weaver-protos-js/common/query_pb"; +import { InteroperableHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; import { getDriverKeyCert } from "./walletSetup"; -import { DBConnector, DBKeyNotFoundError, LevelDBConnector } from "./dbConnector"; +import { + DBConnector, + DBKeyNotFoundError, + LevelDBConnector, +} from "./dbConnector"; import { checkIfArraysAreEqual, handlePromise, relayCallback } from "./utils"; -import { registerListenerForEventSubscription, unregisterListenerForEventSubscription } from "./listener"; +import { + registerListenerForEventSubscription, + unregisterListenerForEventSubscription, +} from "./listener"; import { getNetworkGateway } from "./fabric-code"; import { Gateway, Network, Contract } from "fabric-network"; -import state_pb from '@hyperledger/cacti-weaver-protos-js/common/state_pb'; -import driverPb from '@hyperledger/cacti-weaver-protos-js/driver/driver_pb'; -import logger from './logger'; +import state_pb from "@hyperledger/cacti-weaver-protos-js/common/state_pb"; +import driverPb from "@hyperledger/cacti-weaver-protos-js/driver/driver_pb"; +import logger from "./logger"; -import fs from 'fs'; -import path from 'path'; +import fs from "fs"; +import path from "path"; const DB_NAME: string = "driverdb"; const DRIVER_ERROR_CONSTANTS = JSON.parse( - fs.readFileSync( - path.resolve(__dirname, '../constants/driver-error-constants.json'), - ).toString(), + fs + .readFileSync( + path.resolve(__dirname, "../constants/driver-error-constants.json"), + ) + .toString(), ); async function subscribeEventHelper( - call_request: eventsPb.EventSubscription, - client: events_grpc_pb.EventSubscribeClient, - network_name: string, + call_request: eventsPb.EventSubscription, + client: events_grpc_pb.EventSubscribeClient, + network_name: string, ) { - const newRequestId = call_request.getQuery()!.getRequestId(); - const [requestId, error] = await handlePromise(addEventSubscription(call_request)); - if (error) { - const errorString: string = `error (thrown as part of async processing while storing to DB during subscribeEvent): ${error.toString()}`; - logger.error(errorString); - const ack_send_error = new ack_pb.Ack(); - ack_send_error.setRequestId(newRequestId); - ack_send_error.setMessage(errorString); - ack_send_error.setStatus(ack_pb.Ack.STATUS.ERROR); - // gRPC response. - logger.info(`Sending to the relay the eventSubscription error Ack: ${JSON.stringify(ack_send_error.toObject())}`); - // Sending the fabric state to the relay. - client.sendDriverSubscriptionStatus(ack_send_error, relayCallback); - } else { - const ack_send = new ack_pb.Ack(); - logger.debug(`${newRequestId}, ${requestId}`); - if (newRequestId == requestId) { // event being subscribed for the first time - // Start an appropriate type of event listener for this event subscription if one is not already active - const [listenerHandle, error] = await handlePromise(registerListenerForEventSubscription(call_request.getEventMatcher()!, network_name)); - if (error) { - // Need to delete subscription in database too, for consistency - const [deletedSubscription, err] = - await handlePromise(deleteEventSubscription(call_request.getEventMatcher()!, newRequestId)); - if (err) { - const errorString: string = err.toString(); - logger.error(errorString); - } - const errorString2 = error.toString(); - logger.error(errorString2); - ack_send.setMessage(`Event subscription error: listener registration failed with error: ${errorString2}`); - ack_send.setStatus(ack_pb.Ack.STATUS.ERROR); - } else { - ack_send.setMessage('Event subscription is successful!'); - ack_send.setStatus(ack_pb.Ack.STATUS.OK); - } - } else { - // event being subscribed already exists - const subExistsErrorMsg = DRIVER_ERROR_CONSTANTS.SUB_EXISTS.replace("{0}", requestId); - ack_send.setMessage(subExistsErrorMsg); - ack_send.setStatus(ack_pb.Ack.STATUS.ERROR); - } - ack_send.setRequestId(newRequestId); - - // gRPC response. - logger.info(`Sending to the relay the eventSubscription Ack: ${JSON.stringify(ack_send.toObject())}`); - - if (!process.env.RELAY_ENDPOINT) { - throw new Error('RELAY_ENDPOINT is not set.'); + const newRequestId = call_request.getQuery()!.getRequestId(); + const [requestId, error] = await handlePromise( + addEventSubscription(call_request), + ); + if (error) { + const errorString: string = `error (thrown as part of async processing while storing to DB during subscribeEvent): ${error.toString()}`; + logger.error(errorString); + const ack_send_error = new ack_pb.Ack(); + ack_send_error.setRequestId(newRequestId); + ack_send_error.setMessage(errorString); + ack_send_error.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info( + `Sending to the relay the eventSubscription error Ack: ${JSON.stringify(ack_send_error.toObject())}`, + ); + // Sending the fabric state to the relay. + client.sendDriverSubscriptionStatus(ack_send_error, relayCallback); + } else { + const ack_send = new ack_pb.Ack(); + logger.debug(`${newRequestId}, ${requestId}`); + if (newRequestId == requestId) { + // event being subscribed for the first time + // Start an appropriate type of event listener for this event subscription if one is not already active + const [listenerHandle, error] = await handlePromise( + registerListenerForEventSubscription( + call_request.getEventMatcher()!, + network_name, + ), + ); + if (error) { + // Need to delete subscription in database too, for consistency + const [deletedSubscription, err] = await handlePromise( + deleteEventSubscription( + call_request.getEventMatcher()!, + newRequestId, + ), + ); + if (err) { + const errorString: string = err.toString(); + logger.error(errorString); } - - // Sending the fabric state to the relay. - client.sendDriverSubscriptionStatus(ack_send, relayCallback); + const errorString2 = error.toString(); + logger.error(errorString2); + ack_send.setMessage( + `Event subscription error: listener registration failed with error: ${errorString2}`, + ); + ack_send.setStatus(ack_pb.Ack.STATUS.ERROR); + } else { + ack_send.setMessage("Event subscription is successful!"); + ack_send.setStatus(ack_pb.Ack.STATUS.OK); + } + } else { + // event being subscribed already exists + const subExistsErrorMsg = DRIVER_ERROR_CONSTANTS.SUB_EXISTS.replace( + "{0}", + requestId, + ); + ack_send.setMessage(subExistsErrorMsg); + ack_send.setStatus(ack_pb.Ack.STATUS.ERROR); + } + ack_send.setRequestId(newRequestId); + + // gRPC response. + logger.info( + `Sending to the relay the eventSubscription Ack: ${JSON.stringify(ack_send.toObject())}`, + ); + + if (!process.env.RELAY_ENDPOINT) { + throw new Error("RELAY_ENDPOINT is not set."); } + + // Sending the fabric state to the relay. + client.sendDriverSubscriptionStatus(ack_send, relayCallback); + } } async function unsubscribeEventHelper( - call_request: eventsPb.EventSubscription, - client: events_grpc_pb.EventSubscribeClient, - network_name: string, + call_request: eventsPb.EventSubscription, + client: events_grpc_pb.EventSubscribeClient, + network_name: string, ) { - const [unregister, err] = - await handlePromise(unregisterListenerForEventSubscription(call_request.getEventMatcher()!, network_name)); - if (!unregister) { // Just log a warning. This is not critical. - logger.warn('No listener running for the given subscription or unable to stop listener'); - } - if (err) { // Just log the error. This is not critical. - const errorString: string = err.toString(); - logger.error(errorString); - } - const newRequestId = call_request.getQuery()!.getRequestId(); - const [deletedSubscription, error] = - await handlePromise(deleteEventSubscription(call_request.getEventMatcher()!, newRequestId)); - if (error) { - const errorString: string = `error (thrown as part of async processing while deleting from DB during unsubscribeEvent): ${error.toString()}`; - logger.error(errorString); - const ack_send_error = new ack_pb.Ack(); - ack_send_error.setRequestId(newRequestId); - ack_send_error.setMessage(errorString); - ack_send_error.setStatus(ack_pb.Ack.STATUS.ERROR); - // gRPC response. - logger.info(`Sending to the relay the eventSubscription error Ack: ${JSON.stringify(ack_send_error.toObject())}`); - // Sending the fabric state to the relay. - client.sendDriverSubscriptionStatus(ack_send_error, relayCallback); - } else { - const ack_send = new ack_pb.Ack(); - - // event got unsubscribed - ack_send.setMessage(`Event ${JSON.stringify(deletedSubscription.toObject())} unsubscription is successful!`); - ack_send.setStatus(ack_pb.Ack.STATUS.OK); - ack_send.setRequestId(newRequestId); - - // gRPC response. - logger.info(`Sending to the relay the eventSubscription Ack: ${JSON.stringify(ack_send.toObject())}`); - - if (!process.env.RELAY_ENDPOINT) { - throw new Error('RELAY_ENDPOINT is not set.'); - } - - // Sending the fabric state to the relay. - client.sendDriverSubscriptionStatus(ack_send, relayCallback); + const [unregister, err] = await handlePromise( + unregisterListenerForEventSubscription( + call_request.getEventMatcher()!, + network_name, + ), + ); + if (!unregister) { + // Just log a warning. This is not critical. + logger.warn( + "No listener running for the given subscription or unable to stop listener", + ); + } + if (err) { + // Just log the error. This is not critical. + const errorString: string = err.toString(); + logger.error(errorString); + } + const newRequestId = call_request.getQuery()!.getRequestId(); + const [deletedSubscription, error] = await handlePromise( + deleteEventSubscription(call_request.getEventMatcher()!, newRequestId), + ); + if (error) { + const errorString: string = `error (thrown as part of async processing while deleting from DB during unsubscribeEvent): ${error.toString()}`; + logger.error(errorString); + const ack_send_error = new ack_pb.Ack(); + ack_send_error.setRequestId(newRequestId); + ack_send_error.setMessage(errorString); + ack_send_error.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info( + `Sending to the relay the eventSubscription error Ack: ${JSON.stringify(ack_send_error.toObject())}`, + ); + // Sending the fabric state to the relay. + client.sendDriverSubscriptionStatus(ack_send_error, relayCallback); + } else { + const ack_send = new ack_pb.Ack(); + + // event got unsubscribed + ack_send.setMessage( + `Event ${JSON.stringify(deletedSubscription.toObject())} unsubscription is successful!`, + ); + ack_send.setStatus(ack_pb.Ack.STATUS.OK); + ack_send.setRequestId(newRequestId); + + // gRPC response. + logger.info( + `Sending to the relay the eventSubscription Ack: ${JSON.stringify(ack_send.toObject())}`, + ); + + if (!process.env.RELAY_ENDPOINT) { + throw new Error("RELAY_ENDPOINT is not set."); } + + // Sending the fabric state to the relay. + client.sendDriverSubscriptionStatus(ack_send, relayCallback); + } } async function addEventSubscription( - eventSub: eventsPb.EventSubscription + eventSub: eventsPb.EventSubscription, ): Promise { - logger.info(`adding to driver, subscription of the eventSub: ${JSON.stringify(eventSub.toObject())}`); - let db: DBConnector; + logger.info( + `adding to driver, subscription of the eventSub: ${JSON.stringify(eventSub.toObject())}`, + ); + let db: DBConnector; + try { + // Create connection to a database + db = new LevelDBConnector(DB_NAME!); + await db.open(); + + // eventMatcher need to be non-null, hence apply the NaN assertion operator '!' + const eventMatcher: eventsPb.EventMatcher = eventSub.getEventMatcher()!; + // the serialized protobuf for eventMatcher below can be decoded to other formats like 'utf8' [.toString('utf8')] + const key: string = Buffer.from(eventMatcher.serializeBinary()).toString( + "base64", + ); + + // query need to be non-null, hence apply the NaN assertion operator '!' + const query: queryPb.Query = eventSub.getQuery()!; + // the serialized protobuf for query below can be decoded to other formats like 'utf8' [.toString('utf8')] + const querySerialized: string = Buffer.from( + query.serializeBinary(), + ).toString("base64"); + // serialized content of subscriptions is the value present in the key/value LevelDB corresponding to the key + let subscriptions: Array; + try { - // Create connection to a database - db = new LevelDBConnector(DB_NAME!); - await db.open(); - - // eventMatcher need to be non-null, hence apply the NaN assertion operator '!' - var eventMatcher: eventsPb.EventMatcher = eventSub.getEventMatcher()!; - // the serialized protobuf for eventMatcher below can be decoded to other formats like 'utf8' [.toString('utf8')] - const key: string = Buffer.from(eventMatcher.serializeBinary()).toString('base64'); - - // query need to be non-null, hence apply the NaN assertion operator '!' - var query: queryPb.Query = eventSub.getQuery()!; - // the serialized protobuf for query below can be decoded to other formats like 'utf8' [.toString('utf8')] - var querySerialized: string = Buffer.from(query.serializeBinary()).toString('base64'); - // serialized content of subscriptions is the value present in the key/value LevelDB corresponding to the key - var subscriptions: Array; - - try { - // fetch the current values in the DB against the given key - var subscriptionsSerialized: string = await db.read(key) as string; - subscriptions = JSON.parse(subscriptionsSerialized); - - logger.debug(`existing subscriptions.length: ${subscriptions.length}`); - // check if the event to be subscribed is already present in the DB - for (const subscriptionSerialized of subscriptions) { - var subscription: queryPb.Query = queryPb.Query.deserializeBinary(Buffer.from(subscriptionSerialized, 'base64')); - if (checkIfArraysAreEqual(subscription.getPolicyList(), query.getPolicyList()) && - subscription.getAddress() == query.getAddress() && - subscription.getRequestingRelay() == query.getRequestingRelay() && - subscription.getRequestingNetwork() == query.getRequestingNetwork() && - subscription.getCertificate() == query.getCertificate() && - subscription.getRequestingOrg() == query.getRequestingOrg() && - subscription.getConfidential() == query.getConfidential()) { - - logger.info(`found subscription for query with requestId: ${subscription.getRequestId()}`); - await db.close(); - return subscription.getRequestId(); - } - } - - // case of key being present in the list - logger.debug(`eventMatcher: ${JSON.stringify(eventMatcher.toObject())} is already present in the database`); - subscriptions.push(querySerialized); - } catch (error: any) { - let errorString = error.toString(); - if (error instanceof DBKeyNotFoundError) { - // case of read failing due to key not found - logger.debug(`eventMatcher: ${JSON.stringify(eventMatcher.toObject())} is not present before in the database`); - subscriptions = new Array(); - subscriptions.push(querySerialized); - } else { - // case of read failing due to some other issue - logger.error(`re-throwing error: ${errorString}`); - await db.close(); - throw new Error(error); - } + // fetch the current values in the DB against the given key + var subscriptionsSerialized: string = (await db.read(key)) as string; + subscriptions = JSON.parse(subscriptionsSerialized); + + logger.debug(`existing subscriptions.length: ${subscriptions.length}`); + // check if the event to be subscribed is already present in the DB + for (const subscriptionSerialized of subscriptions) { + const subscription: queryPb.Query = queryPb.Query.deserializeBinary( + Buffer.from(subscriptionSerialized, "base64"), + ); + if ( + checkIfArraysAreEqual( + subscription.getPolicyList(), + query.getPolicyList(), + ) && + subscription.getAddress() == query.getAddress() && + subscription.getRequestingRelay() == query.getRequestingRelay() && + subscription.getRequestingNetwork() == query.getRequestingNetwork() && + subscription.getCertificate() == query.getCertificate() && + subscription.getRequestingOrg() == query.getRequestingOrg() && + subscription.getConfidential() == query.getConfidential() + ) { + logger.info( + `found subscription for query with requestId: ${subscription.getRequestId()}`, + ); + await db.close(); + return subscription.getRequestId(); } + } - logger.debug(`new subscriptions.length: ${subscriptions.length}`); - subscriptionsSerialized = JSON.stringify(subscriptions); - // insert the value against key in the DB (it can be the scenario of a new key addition, or update to the value of an existing key) - await db.insert(key, subscriptionsSerialized); + // case of key being present in the list + logger.debug( + `eventMatcher: ${JSON.stringify(eventMatcher.toObject())} is already present in the database`, + ); + subscriptions.push(querySerialized); + } catch (error: any) { + const errorString = error.toString(); + if (error instanceof DBKeyNotFoundError) { + // case of read failing due to key not found + logger.debug( + `eventMatcher: ${JSON.stringify(eventMatcher.toObject())} is not present before in the database`, + ); + subscriptions = new Array(); + subscriptions.push(querySerialized); + } else { + // case of read failing due to some other issue + logger.error(`re-throwing error: ${errorString}`); await db.close(); - - // TODO: register the event with fabric sdk - logger.debug(`end addEventSubscription() .. requestId: ${query.getRequestId()}`); - return query.getRequestId(); - - } catch(error: any) { - logger.error(`Error during addEventSubscription(): ${error.toString()}`); - await db?.close(); throw new Error(error); + } } + + logger.debug(`new subscriptions.length: ${subscriptions.length}`); + subscriptionsSerialized = JSON.stringify(subscriptions); + // insert the value against key in the DB (it can be the scenario of a new key addition, or update to the value of an existing key) + await db.insert(key, subscriptionsSerialized); + await db.close(); + + // TODO: register the event with fabric sdk + logger.debug( + `end addEventSubscription() .. requestId: ${query.getRequestId()}`, + ); + return query.getRequestId(); + } catch (error: any) { + logger.error(`Error during addEventSubscription(): ${error.toString()}`); + await db?.close(); + throw new Error(error); + } } const deleteEventSubscription = async ( - eventMatcher: eventsPb.EventMatcher, - requestId: string + eventMatcher: eventsPb.EventMatcher, + requestId: string, ): Promise => { - logger.info(`deleting from driver subscription of the eventMatcher: ${JSON.stringify(eventMatcher.toObject())} with requestId: ${requestId}`); - var subscriptions: Array; - var retVal: eventsPb.EventSubscription = new eventsPb.EventSubscription(); - retVal.setEventMatcher(eventMatcher); - let db: DBConnector; + logger.info( + `deleting from driver subscription of the eventMatcher: ${JSON.stringify(eventMatcher.toObject())} with requestId: ${requestId}`, + ); + let subscriptions: Array; + const retVal: eventsPb.EventSubscription = new eventsPb.EventSubscription(); + retVal.setEventMatcher(eventMatcher); + let db: DBConnector; + try { + // Create connection to a database + db = new LevelDBConnector(DB_NAME!); + await db.open(); + + const key: string = Buffer.from(eventMatcher.serializeBinary()).toString( + "base64", + ); try { - // Create connection to a database - db = new LevelDBConnector(DB_NAME!); - await db.open(); - - const key: string = Buffer.from(eventMatcher.serializeBinary()).toString('base64'); - try { - // fetch the current values in the DB against the given key - var subscriptionsSerialized: string = await db.read(key) as string; - subscriptions = JSON.parse(subscriptionsSerialized); - - logger.debug(`subscriptions.length: ${subscriptions.length}`); - var foundEntry: boolean = false; - for (var subscriptionSerialized of subscriptions) { - var subscription: queryPb.Query = queryPb.Query.deserializeBinary(Buffer.from(subscriptionSerialized, 'base64')); - if (subscription.getRequestId() == requestId) { - logger.debug(`deleting the subscription (with input requestId): ${JSON.stringify(subscription.toObject())}`); - subscriptions.splice(subscriptions.indexOf(subscriptionSerialized), 1); - retVal.setQuery(subscription); - foundEntry = true; - break; - } - } - - if (!foundEntry) { - throw new Error(`event subscription with requestId: ${requestId} is not found!`); - } - } catch (error: any) { - // error could be either due to key not being present in the database or some other issue with database access - logger.error(`re-throwing error: ${error.toString()}`); - await db.close(); - throw new Error(error); - } - - logger.debug(`subscriptions.length: ${subscriptions.length}`); - if (subscriptions.length == 0) { - await db.delete(key); - } else { - subscriptionsSerialized = JSON.stringify(subscriptions); - await db.insert(key, subscriptionsSerialized); + // fetch the current values in the DB against the given key + var subscriptionsSerialized: string = (await db.read(key)) as string; + subscriptions = JSON.parse(subscriptionsSerialized); + + logger.debug(`subscriptions.length: ${subscriptions.length}`); + let foundEntry: boolean = false; + for (const subscriptionSerialized of subscriptions) { + const subscription: queryPb.Query = queryPb.Query.deserializeBinary( + Buffer.from(subscriptionSerialized, "base64"), + ); + if (subscription.getRequestId() == requestId) { + logger.debug( + `deleting the subscription (with input requestId): ${JSON.stringify(subscription.toObject())}`, + ); + subscriptions.splice( + subscriptions.indexOf(subscriptionSerialized), + 1, + ); + retVal.setQuery(subscription); + foundEntry = true; + break; } + } - await db.close(); - logger.debug(`end deleteEventSubscription() .. retVal: ${JSON.stringify(retVal.toObject())}`); - return retVal; - } catch(error: any) { - logger.error(`Error during delete: ${error.toString()}`); - await db?.close(); - throw new Error(error); + if (!foundEntry) { + throw new Error( + `event subscription with requestId: ${requestId} is not found!`, + ); + } + } catch (error: any) { + // error could be either due to key not being present in the database or some other issue with database access + logger.error(`re-throwing error: ${error.toString()}`); + await db.close(); + throw new Error(error); } -} -function filterEventMatcher(keySerialized: string, eventMatcher: eventsPb.EventMatcher) : boolean { - var item: eventsPb.EventMatcher = eventsPb.EventMatcher.deserializeBinary(Buffer.from(keySerialized, 'base64')); - logger.debug(`eventMatcher from db: ${JSON.stringify(item.toObject())}`) - if ((eventMatcher.getEventClassId() == '*' || eventMatcher.getEventClassId() == item.getEventClassId()) && - (eventMatcher.getTransactionContractId() == '*' || eventMatcher.getTransactionContractId() == item.getTransactionContractId()) && - (eventMatcher.getTransactionLedgerId() == '*' || eventMatcher.getTransactionLedgerId() == item.getTransactionLedgerId()) && - (eventMatcher.getTransactionFunc() == '*' || eventMatcher.getTransactionFunc().toLowerCase() == item.getTransactionFunc().toLowerCase())) { - - return true; + logger.debug(`subscriptions.length: ${subscriptions.length}`); + if (subscriptions.length == 0) { + await db.delete(key); } else { - return false; + subscriptionsSerialized = JSON.stringify(subscriptions); + await db.insert(key, subscriptionsSerialized); } + + await db.close(); + logger.debug( + `end deleteEventSubscription() .. retVal: ${JSON.stringify(retVal.toObject())}`, + ); + return retVal; + } catch (error: any) { + logger.error(`Error during delete: ${error.toString()}`); + await db?.close(); + throw new Error(error); + } +}; + +function filterEventMatcher( + keySerialized: string, + eventMatcher: eventsPb.EventMatcher, +): boolean { + const item: eventsPb.EventMatcher = eventsPb.EventMatcher.deserializeBinary( + Buffer.from(keySerialized, "base64"), + ); + logger.debug(`eventMatcher from db: ${JSON.stringify(item.toObject())}`); + if ( + (eventMatcher.getEventClassId() == "*" || + eventMatcher.getEventClassId() == item.getEventClassId()) && + (eventMatcher.getTransactionContractId() == "*" || + eventMatcher.getTransactionContractId() == + item.getTransactionContractId()) && + (eventMatcher.getTransactionLedgerId() == "*" || + eventMatcher.getTransactionLedgerId() == item.getTransactionLedgerId()) && + (eventMatcher.getTransactionFunc() == "*" || + eventMatcher.getTransactionFunc().toLowerCase() == + item.getTransactionFunc().toLowerCase()) + ) { + return true; + } else { + return false; + } } async function lookupEventSubscriptions( - eventMatcher: eventsPb.EventMatcher + eventMatcher: eventsPb.EventMatcher, ): Promise> { - logger.debug(`finding the subscriptions with eventMatcher: ${JSON.stringify(eventMatcher.toObject())}`); - var subscriptions: Array; - var returnSubscriptions: Array = new Array(); - let db: DBConnector; - - try { - // Create connection to a database - db = new LevelDBConnector(DB_NAME!); - await db.open(); - - for (const subscriptionsSerialized of await db.filteredRead(filterEventMatcher, eventMatcher)) { - subscriptions = JSON.parse(subscriptionsSerialized) - for (const subscriptionSerialized of subscriptions) { - var subscription: queryPb.Query = queryPb.Query.deserializeBinary(Buffer.from(subscriptionSerialized, 'base64')); - logger.debug(`subscription: ${JSON.stringify(subscription.toObject())}`) - returnSubscriptions.push(subscription); - } - } - - logger.info(`found ${returnSubscriptions.length} matching subscriptions`); - logger.debug(`end lookupEventSubscriptions()`); - await db.close(); - return returnSubscriptions; + logger.debug( + `finding the subscriptions with eventMatcher: ${JSON.stringify(eventMatcher.toObject())}`, + ); + let subscriptions: Array; + let returnSubscriptions: Array = new Array(); + let db: DBConnector; + + try { + // Create connection to a database + db = new LevelDBConnector(DB_NAME!); + await db.open(); + + for (const subscriptionsSerialized of await db.filteredRead( + filterEventMatcher, + eventMatcher, + )) { + subscriptions = JSON.parse(subscriptionsSerialized); + for (const subscriptionSerialized of subscriptions) { + const subscription: queryPb.Query = queryPb.Query.deserializeBinary( + Buffer.from(subscriptionSerialized, "base64"), + ); + logger.debug( + `subscription: ${JSON.stringify(subscription.toObject())}`, + ); + returnSubscriptions.push(subscription); + } + } - } catch (error: any) { - let errorString: string = error.toString(); - await db?.close(); - if (error instanceof DBKeyNotFoundError) { - // case of read failing due to key not found - returnSubscriptions = new Array(); - logger.info(`found ${returnSubscriptions.length} matching subscriptions`); - return returnSubscriptions; - } else { - // case of read failing due to some other issue - logger.error(`Error during lookup: ${errorString}`); - throw new Error(error); - } + logger.info(`found ${returnSubscriptions.length} matching subscriptions`); + logger.debug(`end lookupEventSubscriptions()`); + await db.close(); + return returnSubscriptions; + } catch (error: any) { + const errorString: string = error.toString(); + await db?.close(); + if (error instanceof DBKeyNotFoundError) { + // case of read failing due to key not found + returnSubscriptions = new Array(); + logger.info(`found ${returnSubscriptions.length} matching subscriptions`); + return returnSubscriptions; + } else { + // case of read failing due to some other issue + logger.error(`Error during lookup: ${errorString}`); + throw new Error(error); } + } } async function readAllEventMatchers(): Promise> { - var returnMatchers = [] - let db: DBConnector; - logger.debug(`start readAllEventMatchers()`); - try { - // Create connection to a database - db = new LevelDBConnector(DB_NAME!); - await db.open(); - const keys = await db.getAllKeys() - for (const key of keys) { - const eventMatcher = eventsPb.EventMatcher.deserializeBinary(Uint8Array.from(Buffer.from(key, 'base64'))) - returnMatchers.push(eventMatcher) - } - logger.info(`found ${returnMatchers.length} eventMatchers`); - logger.debug(`end readAllEventMatchers()`); - await db.close(); - return returnMatchers; - - } catch (error: any) { - let errorString: string = error.toString(); - await db?.close(); - // case of read failing due to some other issue - logger.error(`Error during read: ${errorString}`); - throw new Error(error); + const returnMatchers = []; + let db: DBConnector; + logger.debug(`start readAllEventMatchers()`); + try { + // Create connection to a database + db = new LevelDBConnector(DB_NAME!); + await db.open(); + const keys = await db.getAllKeys(); + for (const key of keys) { + const eventMatcher = eventsPb.EventMatcher.deserializeBinary( + Uint8Array.from(Buffer.from(key, "base64")), + ); + returnMatchers.push(eventMatcher); } + logger.info(`found ${returnMatchers.length} eventMatchers`); + logger.debug(`end readAllEventMatchers()`); + await db.close(); + return returnMatchers; + } catch (error: any) { + const errorString: string = error.toString(); + await db?.close(); + // case of read failing due to some other issue + logger.error(`Error during read: ${errorString}`); + throw new Error(error); + } } async function signEventSubscriptionQuery( - inputQuery: queryPb.Query + inputQuery: queryPb.Query, ): Promise { - logger.info(`driver ready to provide sign on query: ${JSON.stringify(inputQuery.toObject())}`); - let signedQuery = new queryPb.Query(); + logger.info( + `driver ready to provide sign on query: ${JSON.stringify(inputQuery.toObject())}`, + ); + const signedQuery = new queryPb.Query(); + + try { + signedQuery.setPolicyList(inputQuery.getPolicyList()); + signedQuery.setAddress(inputQuery.getAddress()); + signedQuery.setRequestingRelay(inputQuery.getRequestingRelay()); + signedQuery.setRequestingOrg(inputQuery.getRequestingOrg()); + signedQuery.setRequestingNetwork(inputQuery.getRequestingNetwork()); + signedQuery.setNonce(inputQuery.getNonce()); + signedQuery.setRequestId(inputQuery.getRequestId()); + signedQuery.setConfidential(inputQuery.getConfidential()); - try { - signedQuery.setPolicyList(inputQuery.getPolicyList()); - signedQuery.setAddress(inputQuery.getAddress()); - signedQuery.setRequestingRelay(inputQuery.getRequestingRelay()); - signedQuery.setRequestingOrg(inputQuery.getRequestingOrg()); - signedQuery.setRequestingNetwork(inputQuery.getRequestingNetwork()); - signedQuery.setNonce(inputQuery.getNonce()); - signedQuery.setRequestId(inputQuery.getRequestId()); - signedQuery.setConfidential(inputQuery.getConfidential()); - - const keyCert = await getDriverKeyCert() - signedQuery.setCertificate(keyCert.cert); - signedQuery.setRequestorSignature( - InteroperableHelper.signMessage( - inputQuery.getAddress() + inputQuery.getNonce(), - keyCert.key.toBytes() - ) - ); - return signedQuery; - } catch (error: any) { - const errorString: string = `${error.toString()}`; - logger.error(`signing query failed with error: ${errorString}`); - throw new Error(error); - } + const keyCert = await getDriverKeyCert(); + signedQuery.setCertificate(keyCert.cert); + signedQuery.setRequestorSignature( + InteroperableHelper.signMessage( + inputQuery.getAddress() + inputQuery.getNonce(), + keyCert.key.toBytes(), + ), + ); + return signedQuery; + } catch (error: any) { + const errorString: string = `${error.toString()}`; + logger.error(`signing query failed with error: ${errorString}`); + throw new Error(error); + } } async function writeExternalStateHelper( - writeExternalStateMessage: driverPb.WriteExternalStateMessage, - networkName: string -) : Promise { - const viewPayload: state_pb.ViewPayload = writeExternalStateMessage.getViewPayload(); - const ctx: eventsPb.ContractTransaction = writeExternalStateMessage.getCtx(); - const keyCert = await getDriverKeyCert(); - - const requestId: string = viewPayload.getRequestId(); - if (!viewPayload.getError()) { - - let interopArgIndices = [], viewsSerializedBase64 = [], addresses = [], viewContentsBase64 = []; - const view: state_pb.View = viewPayload.getView(); - - const result = InteroperableHelper.getResponseDataFromView(view, keyCert.key.toBytes()); - if (result.contents) { - viewContentsBase64.push(result.contents); - } else { - viewContentsBase64.push([]); - } + writeExternalStateMessage: driverPb.WriteExternalStateMessage, + networkName: string, +): Promise { + const viewPayload: state_pb.ViewPayload = + writeExternalStateMessage.getViewPayload(); + const ctx: eventsPb.ContractTransaction = writeExternalStateMessage.getCtx(); + const keyCert = await getDriverKeyCert(); + + const requestId: string = viewPayload.getRequestId(); + if (!viewPayload.getError()) { + const interopArgIndices = [], + viewsSerializedBase64 = [], + addresses = [], + viewContentsBase64 = []; + const view: state_pb.View = viewPayload.getView(); + + const result = InteroperableHelper.getResponseDataFromView( + view, + keyCert.key.toBytes(), + ); + if (result.contents) { + viewContentsBase64.push(result.contents); + } else { + viewContentsBase64.push([]); + } - interopArgIndices.push(ctx.getReplaceArgIndex()); - addresses.push(result.viewAddress); - viewsSerializedBase64.push(Buffer.from(viewPayload.getView().serializeBinary()).toString("base64")); + interopArgIndices.push(ctx.getReplaceArgIndex()); + addresses.push(result.viewAddress); + viewsSerializedBase64.push( + Buffer.from(viewPayload.getView().serializeBinary()).toString("base64"), + ); - let ccArgsB64 = ctx.getArgsList(); - let ccArgsStr = []; - for (const ccArgB64 of ccArgsB64) { - ccArgsStr.push(Buffer.from(ccArgB64).toString('utf8')); - } + const ccArgsB64 = ctx.getArgsList(); + const ccArgsStr = []; + for (const ccArgB64 of ccArgsB64) { + ccArgsStr.push(Buffer.from(ccArgB64).toString("utf8")); + } - let gateway: Gateway = await getNetworkGateway(networkName); - const network: Network = await gateway.getNetwork(ctx.getLedgerId()); - const interopContract: Contract = network.getContract(process.env.INTEROP_CHAINCODE ? process.env.INTEROP_CHAINCODE : 'interop'); - - const endorsingOrgs = ctx.getMembersList(); - const invokeObject = { - channel: ctx.getLedgerId(), - ccFunc: ctx.getFunc(), - ccArgs: ccArgsStr, - contractName: ctx.getContractId() - } - logger.info(`writing external state to contract: ${ctx.getContractId()} with function: ${ctx.getFunc()}, and args: ${invokeObject.ccArgs} on channel: ${ctx.getLedgerId()}`); - - const [ response, responseError ] = await handlePromise(InteroperableHelper.submitTransactionWithRemoteViews( - interopContract, - invokeObject, - interopArgIndices, - addresses, - viewsSerializedBase64, - viewContentsBase64, - endorsingOrgs - )); - if (responseError) { - logger.error(`Failed writing to the ledger with error: ${responseError}`); - gateway.disconnect(); - throw responseError; - } - logger.debug(`write successful`); - gateway.disconnect(); - } else { - const errorString: string = `erroneous viewPayload identified in WriteExternalState processing`; - logger.error(`error viewPayload.getError(): ${JSON.stringify(viewPayload.getError())}`); - throw new Error(errorString); + const gateway: Gateway = await getNetworkGateway(networkName); + const network: Network = await gateway.getNetwork(ctx.getLedgerId()); + const interopContract: Contract = network.getContract( + process.env.INTEROP_CHAINCODE ? process.env.INTEROP_CHAINCODE : "interop", + ); + + const endorsingOrgs = ctx.getMembersList(); + const invokeObject = { + channel: ctx.getLedgerId(), + ccFunc: ctx.getFunc(), + ccArgs: ccArgsStr, + contractName: ctx.getContractId(), + }; + logger.info( + `writing external state to contract: ${ctx.getContractId()} with function: ${ctx.getFunc()}, and args: ${invokeObject.ccArgs} on channel: ${ctx.getLedgerId()}`, + ); + + const [response, responseError] = await handlePromise( + InteroperableHelper.submitTransactionWithRemoteViews( + interopContract, + invokeObject, + interopArgIndices, + addresses, + viewsSerializedBase64, + viewContentsBase64, + endorsingOrgs, + ), + ); + if (responseError) { + logger.error(`Failed writing to the ledger with error: ${responseError}`); + gateway.disconnect(); + throw responseError; } + logger.debug(`write successful`); + gateway.disconnect(); + } else { + const errorString: string = `erroneous viewPayload identified in WriteExternalState processing`; + logger.error( + `error viewPayload.getError(): ${JSON.stringify(viewPayload.getError())}`, + ); + throw new Error(errorString); + } } export { - subscribeEventHelper, - unsubscribeEventHelper, - addEventSubscription, - deleteEventSubscription, - lookupEventSubscriptions, - readAllEventMatchers, - signEventSubscriptionQuery, - writeExternalStateHelper -} + subscribeEventHelper, + unsubscribeEventHelper, + addEventSubscription, + deleteEventSubscription, + lookupEventSubscriptions, + readAllEventMatchers, + signEventSubscriptionQuery, + writeExternalStateHelper, +}; diff --git a/weaver/core/drivers/fabric-driver/server/fabric-code.ts b/weaver/core/drivers/fabric-driver/server/fabric-code.ts index a60f2c7b9f..a68b97d26d 100644 --- a/weaver/core/drivers/fabric-driver/server/fabric-code.ts +++ b/weaver/core/drivers/fabric-driver/server/fabric-code.ts @@ -4,70 +4,82 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Gateway, Wallets } from 'fabric-network'; -import { Endorser } from 'fabric-common'; -import * as path from 'path'; -import * as fs from 'fs'; -import query_pb from '@hyperledger/cacti-weaver-protos-js/common/query_pb'; -import view_data from '@hyperledger/cacti-weaver-protos-js/fabric/view_data_pb'; -import proposalResponse from '@hyperledger/cacti-weaver-protos-js/peer/proposal_response_pb'; -import interopPayload from '@hyperledger/cacti-weaver-protos-js/common/interop_payload_pb'; -import state_pb from '@hyperledger/cacti-weaver-protos-js/common/state_pb'; -import { Certificate } from '@fidm/x509'; -import { getConfig } from './walletSetup'; -import logger from './logger'; +import { Gateway, Wallets } from "fabric-network"; +import { Endorser } from "fabric-common"; +import * as path from "path"; +import * as fs from "fs"; +import query_pb from "@hyperledger/cacti-weaver-protos-js/common/query_pb"; +import view_data from "@hyperledger/cacti-weaver-protos-js/fabric/view_data_pb"; +import proposalResponse from "@hyperledger/cacti-weaver-protos-js/peer/proposal_response_pb"; +import interopPayload from "@hyperledger/cacti-weaver-protos-js/common/interop_payload_pb"; +import state_pb from "@hyperledger/cacti-weaver-protos-js/common/state_pb"; +import { Certificate } from "@fidm/x509"; +import { getConfig } from "./walletSetup"; +import logger from "./logger"; const parseAddress = (address: string) => { - const addressList = address.split('/'); - const fabricArgs = addressList[2].split(':'); - return { channel: fabricArgs[0], contract: fabricArgs[1], ccFunc: fabricArgs[2], args: fabricArgs.slice(3) }; + const addressList = address.split("/"); + const fabricArgs = addressList[2].split(":"); + return { + channel: fabricArgs[0], + contract: fabricArgs[1], + ccFunc: fabricArgs[2], + args: fabricArgs.slice(3), + }; }; const getWallet = (walletPath: string) => { - return Wallets.newFileSystemWallet(walletPath); + return Wallets.newFileSystemWallet(walletPath); }; // Get a handle to a network gateway using existing wallet credentials const getNetworkGateway = async (networkName: string): Promise => { - try { - // load the network configuration - const ccpPath = process.env.CONNECTION_PROFILE - ? path.resolve(__dirname, process.env.CONNECTION_PROFILE) - : path.resolve(__dirname, '../connection_profile.json'); - if (!fs.existsSync(ccpPath)) { - logger.error(`File does not exist at path: ${ccpPath}`); - logger.error( - 'Please check the CONNECTION_PROFILE environemnt variable in your .env. The path will default to the root of the fabric-driver folder if not supplied', - ); - throw new Error('No CONNECTION_PROFILE provided in .env'); - } - const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8')); - const config = getConfig(); - - // Create a new file system-based wallet for managing identities. - const walletPath = process.env.WALLET_PATH ? process.env.WALLET_PATH : path.join(process.cwd(), `wallet-${networkName}`); - const userName = config.relay.name; - const wallet = await getWallet(walletPath); - logger.debug(`Wallet path: ${walletPath}`); - // Check to see if we've already enrolled the user. - const identity = await wallet.get(userName); - if (!identity) { - logger.info(`An identity for the user "${userName}" does not exist in the wallet`); - logger.info('Run the registerUser.ts application before retrying'); - } - // Create a new gateway for connecting to our peer node. - const gateway = new Gateway(); - await gateway.connect(ccp, { - wallet, - identity: `${userName}`, - discovery: { enabled: true, asLocalhost: process.env.local === 'false' ? false : true }, - }); - return gateway; - } catch (error) { - logger.error(`Failed to instantiate network (channel): ${error}`); - throw error; + try { + // load the network configuration + const ccpPath = process.env.CONNECTION_PROFILE + ? path.resolve(__dirname, process.env.CONNECTION_PROFILE) + : path.resolve(__dirname, "../connection_profile.json"); + if (!fs.existsSync(ccpPath)) { + logger.error(`File does not exist at path: ${ccpPath}`); + logger.error( + "Please check the CONNECTION_PROFILE environemnt variable in your .env. The path will default to the root of the fabric-driver folder if not supplied", + ); + throw new Error("No CONNECTION_PROFILE provided in .env"); } -} + const ccp = JSON.parse(fs.readFileSync(ccpPath, "utf8")); + const config = getConfig(); + + // Create a new file system-based wallet for managing identities. + const walletPath = process.env.WALLET_PATH + ? process.env.WALLET_PATH + : path.join(process.cwd(), `wallet-${networkName}`); + const userName = config.relay.name; + const wallet = await getWallet(walletPath); + logger.debug(`Wallet path: ${walletPath}`); + // Check to see if we've already enrolled the user. + const identity = await wallet.get(userName); + if (!identity) { + logger.info( + `An identity for the user "${userName}" does not exist in the wallet`, + ); + logger.info("Run the registerUser.ts application before retrying"); + } + // Create a new gateway for connecting to our peer node. + const gateway = new Gateway(); + await gateway.connect(ccp, { + wallet, + identity: `${userName}`, + discovery: { + enabled: true, + asLocalhost: process.env.local === "false" ? false : true, + }, + }); + return gateway; + } catch (error) { + logger.error(`Failed to instantiate network (channel): ${error}`); + throw error; + } +}; // Main invoke function wtih logic to handle policy and turn response from chaincode into a view. // 1. Prepare credentials/gateway for communicating with fabric network @@ -75,141 +87,157 @@ const getNetworkGateway = async (networkName: string): Promise => { // 3. Set the endorser list for the transaction, this enforces that the list provided will endorse the proposed transaction // 4. Prepare the view and return. async function invoke( - query: query_pb.Query, - networkName: string, - funcName: string, - dynamicArg?: Buffer + query: query_pb.Query, + networkName: string, + funcName: string, + dynamicArg?: Buffer, ): Promise { - logger.info('Running query on fabric network'); - try { - // 1. Prepare credentials/gateway for communicating with fabric network - const gateway = await getNetworkGateway(networkName); - - // 2. Prepare info required for query (address/policy) - const parsedAddress = parseAddress(query.getAddress()); - // Get the network (channel) our contract is deployed to. - logger.debug(`Channel: ${parsedAddress.channel}`); - const network = await gateway.getNetwork(parsedAddress.channel); - const currentChannel = network.getChannel(); - const endorsers = currentChannel.getEndorsers(); - logger.info(`policy: ${query.getPolicyList()}`); - const chaincodeId = process.env.INTEROP_CHAINCODE ? process.env.INTEROP_CHAINCODE : 'interop'; - - // LOGIC for getting identities from the provided policy. If none can be found it will default to all. - const identities = query.getPolicyList(); - - logger.debug(`Message: ${query.getAddress() + query.getNonce()} ${identities}`); - const cert = Certificate.fromPEM(Buffer.from(query.getCertificate())); - const orgName = cert.issuer.organizationName; - logger.info( - `CC ARGS: + logger.info("Running query on fabric network"); + try { + // 1. Prepare credentials/gateway for communicating with fabric network + const gateway = await getNetworkGateway(networkName); + + // 2. Prepare info required for query (address/policy) + const parsedAddress = parseAddress(query.getAddress()); + // Get the network (channel) our contract is deployed to. + logger.debug(`Channel: ${parsedAddress.channel}`); + const network = await gateway.getNetwork(parsedAddress.channel); + const currentChannel = network.getChannel(); + const endorsers = currentChannel.getEndorsers(); + logger.info(`policy: ${query.getPolicyList()}`); + const chaincodeId = process.env.INTEROP_CHAINCODE + ? process.env.INTEROP_CHAINCODE + : "interop"; + + // LOGIC for getting identities from the provided policy. If none can be found it will default to all. + const identities = query.getPolicyList(); + + logger.debug( + `Message: ${query.getAddress() + query.getNonce()} ${identities}`, + ); + const cert = Certificate.fromPEM(Buffer.from(query.getCertificate())); + const orgName = cert.issuer.organizationName; + logger.info( + `CC ARGS: ${parsedAddress.ccFunc}, ${parsedAddress.args}, ${query.getRequestingNetwork()}, ${query.getRequestingOrg() ? query.getRequestingOrg() : orgName}, ${query.getCertificate()}, ${query.getRequestorSignature()}, - ${query.getAddress() + query.getNonce()}` - ); - const b64QueryBytes = Buffer.from(query.serializeBinary()).toString('base64'); - - const idx = gateway.identityContext.calculateTransactionId(); - const queryProposal = currentChannel.newQuery(chaincodeId); - let request; - if (funcName == 'HandleExternalRequest') { - request = { - fcn: funcName, - args: [b64QueryBytes], - generateTransactionId: false - }; - } else { - request = { - fcn: funcName, - args: [b64QueryBytes, dynamicArg ? dynamicArg.toString() : ""], - generateTransactionId: false - }; - } - queryProposal.build(idx, request); - queryProposal.sign(idx); - // 3. Set the endorser list for the transaction, this enforces that the list provided will endorse the proposed transaction - let proposalRequest; - if (identities.length > 0) { - const endorserList = endorsers.filter((endorser: Endorser) => { - //@ts-ignore - const cert = Certificate.fromPEM(endorser.options.pem); - const orgName = cert.issuer.organizationName; - return identities.includes(endorser.mspid) || identities.includes(orgName); - }); - logger.debug(`Set endorserList: ${endorserList}`); - proposalRequest = { - targets: endorserList, - requestTimeout: 30000 - }; - } else { - // When no identities provided it will default to all peers - logger.debug(`Set endorsers: ${endorsers}`); - proposalRequest = { - targets: endorsers, - requestTimeout: 30000 - }; - } - - // submit query transaction and get result from chaincode - const proposalResponseResult = await queryProposal.send(proposalRequest); - //logger.debug(`${JSON.stringify(proposalResponseResult, null, 2)}`) - - // 4. Prepare the view and return. - const viewPayload = new view_data.FabricView(); - const endorsedProposalResponses: view_data.FabricView.EndorsedProposalResponse[] = []; - //TODO Fix ts error + ${query.getAddress() + query.getNonce()}`, + ); + const b64QueryBytes = Buffer.from(query.serializeBinary()).toString( + "base64", + ); + + const idx = gateway.identityContext.calculateTransactionId(); + const queryProposal = currentChannel.newQuery(chaincodeId); + let request; + if (funcName == "HandleExternalRequest") { + request = { + fcn: funcName, + args: [b64QueryBytes], + generateTransactionId: false, + }; + } else { + request = { + fcn: funcName, + args: [b64QueryBytes, dynamicArg ? dynamicArg.toString() : ""], + generateTransactionId: false, + }; + } + queryProposal.build(idx, request); + queryProposal.sign(idx); + // 3. Set the endorser list for the transaction, this enforces that the list provided will endorse the proposed transaction + let proposalRequest; + if (identities.length > 0) { + const endorserList = endorsers.filter((endorser: Endorser) => { //@ts-ignore - let endorsementCounter = 0; - proposalResponseResult.responses.forEach((response) => { - const endorsement = new proposalResponse.Endorsement(); - endorsement.setSignature(response.endorsement.signature); - endorsement.setEndorser(response.endorsement.endorser); - - // Create EndorsedProposalResponse - const endorsedProposalResponse = new view_data.FabricView.EndorsedProposalResponse(); - endorsedProposalResponse.setPayload( - proposalResponse.ProposalResponsePayload.deserializeBinary(response.payload) - ); - endorsedProposalResponse.setEndorsement(endorsement); - - // Add to list of endorsedProposalResponses - endorsedProposalResponses.push(endorsedProposalResponse); - - logger.info(`InteropPayload: ${endorsementCounter}, ${Buffer.from(response.response.payload).toString('base64')}`); - logger.info(`Endorsement: ${endorsementCounter}, ${Buffer.from(endorsement.serializeBinary()).toString('base64')}`); - endorsementCounter++; - }); - viewPayload.setEndorsedProposalResponsesList(endorsedProposalResponses); - // Disconnect from the gateway. - gateway.disconnect(); - return viewPayload; - } catch (error) { - logger.error(`Failed to submit transaction: ${error}`); - throw error; + const cert = Certificate.fromPEM(endorser.options.pem); + const orgName = cert.issuer.organizationName; + return ( + identities.includes(endorser.mspid) || identities.includes(orgName) + ); + }); + logger.debug(`Set endorserList: ${endorserList}`); + proposalRequest = { + targets: endorserList, + requestTimeout: 30000, + }; + } else { + // When no identities provided it will default to all peers + logger.debug(`Set endorsers: ${endorsers}`); + proposalRequest = { + targets: endorsers, + requestTimeout: 30000, + }; } + + // submit query transaction and get result from chaincode + const proposalResponseResult = await queryProposal.send(proposalRequest); + //logger.debug(`${JSON.stringify(proposalResponseResult, null, 2)}`) + + // 4. Prepare the view and return. + const viewPayload = new view_data.FabricView(); + const endorsedProposalResponses: view_data.FabricView.EndorsedProposalResponse[] = + []; + //TODO Fix ts error + //@ts-ignore + let endorsementCounter = 0; + proposalResponseResult.responses.forEach((response) => { + const endorsement = new proposalResponse.Endorsement(); + endorsement.setSignature(response.endorsement.signature); + endorsement.setEndorser(response.endorsement.endorser); + + // Create EndorsedProposalResponse + const endorsedProposalResponse = + new view_data.FabricView.EndorsedProposalResponse(); + endorsedProposalResponse.setPayload( + proposalResponse.ProposalResponsePayload.deserializeBinary( + response.payload, + ), + ); + endorsedProposalResponse.setEndorsement(endorsement); + + // Add to list of endorsedProposalResponses + endorsedProposalResponses.push(endorsedProposalResponse); + + logger.info( + `InteropPayload: ${endorsementCounter}, ${Buffer.from(response.response.payload).toString("base64")}`, + ); + logger.info( + `Endorsement: ${endorsementCounter}, ${Buffer.from(endorsement.serializeBinary()).toString("base64")}`, + ); + endorsementCounter++; + }); + viewPayload.setEndorsedProposalResponsesList(endorsedProposalResponses); + // Disconnect from the gateway. + gateway.disconnect(); + return viewPayload; + } catch (error) { + logger.error(`Failed to submit transaction: ${error}`); + throw error; + } } // Package view and send to relay function packageFabricView( - query: query_pb.Query, - viewData: view_data.FabricView, + query: query_pb.Query, + viewData: view_data.FabricView, ) { - const meta = new state_pb.Meta(); - meta.setTimestamp(new Date().toISOString()); - meta.setProofType('Notarization'); - meta.setSerializationFormat('STRING'); - meta.setProtocol(state_pb.Meta.Protocol.FABRIC); - const view = new state_pb.View(); - view.setMeta(meta); - view.setData(viewData ? viewData.serializeBinary() : Buffer.from('')); - const viewPayload = new state_pb.ViewPayload(); - viewPayload.setView(view); - viewPayload.setRequestId(query.getRequestId()); - return viewPayload; + const meta = new state_pb.Meta(); + meta.setTimestamp(new Date().toISOString()); + meta.setProofType("Notarization"); + meta.setSerializationFormat("STRING"); + meta.setProtocol(state_pb.Meta.Protocol.FABRIC); + const view = new state_pb.View(); + view.setMeta(meta); + view.setData(viewData ? viewData.serializeBinary() : Buffer.from("")); + const viewPayload = new state_pb.ViewPayload(); + viewPayload.setView(view); + viewPayload.setRequestId(query.getRequestId()); + return viewPayload; } export { getNetworkGateway, invoke, packageFabricView }; diff --git a/weaver/core/drivers/fabric-driver/server/listener.ts b/weaver/core/drivers/fabric-driver/server/listener.ts index 39d9a0e027..4014d47ebb 100644 --- a/weaver/core/drivers/fabric-driver/server/listener.ts +++ b/weaver/core/drivers/fabric-driver/server/listener.ts @@ -4,84 +4,123 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as fabproto6 from 'fabric-protos'; -import { BlockDecoder } from 'fabric-common/index'; -import { Gateway, Network, Contract, ContractEvent, BlockListener, ContractListener, BlockEvent, ListenerOptions } from 'fabric-network'; -import query_pb from '@hyperledger/cacti-weaver-protos-js/common/query_pb'; -import events_pb from '@hyperledger/cacti-weaver-protos-js/common/events_pb'; -import { lookupEventSubscriptions, readAllEventMatchers } from './events'; -import { invoke, getNetworkGateway, packageFabricView } from './fabric-code'; -import { handlePromise, relayCallback, getRelayClientForEventPublish, delay } from './utils'; -import { DBConnector, LevelDBConnector, DBLockedError, DBKeyNotFoundError } from './dbConnector'; -import logger from './logger'; +import * as fabproto6 from "fabric-protos"; +import { BlockDecoder } from "fabric-common/index"; +import { + Gateway, + Network, + Contract, + ContractEvent, + BlockListener, + ContractListener, + BlockEvent, + ListenerOptions, +} from "fabric-network"; +import query_pb from "@hyperledger/cacti-weaver-protos-js/common/query_pb"; +import events_pb from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import { lookupEventSubscriptions, readAllEventMatchers } from "./events"; +import { invoke, getNetworkGateway, packageFabricView } from "./fabric-code"; +import { + handlePromise, + relayCallback, + getRelayClientForEventPublish, + delay, +} from "./utils"; +import { + DBConnector, + LevelDBConnector, + DBLockedError, + DBKeyNotFoundError, +} from "./dbConnector"; +import logger from "./logger"; -let networkGatewayMap = new Map(); -let networkChannelMap = new Map(); -let channelBlockListenerMap = new Map(); -let channelContractListenerMap = new Map(); -let globalLedgerListenerCount = new Map(); +const networkGatewayMap = new Map(); +const networkChannelMap = new Map(); +const channelBlockListenerMap = new Map(); +const channelContractListenerMap = new Map(); +const globalLedgerListenerCount = new Map(); const DB_NAME: string = "BLOCKCHAIN_DB"; const DB_OPEN_TIMEOUT = 20000; const BH_KEY = "LAST_BLOCK_HEIGHT"; function getChannelContractKey(channelId: string, contractId: string) { - return channelId + ':' + contractId; + return channelId + ":" + contractId; } function getBHKey(channelId: string) { - return BH_KEY + ':' + channelId + return BH_KEY + ":" + channelId; } -async function setLastReadBlockNumber(db: DBConnector, channelId: string, blockNum: number) { - logger.debug(`Set last read block number ${blockNum} on channel: ${channelId}`); - await db.insert(getBHKey(channelId), blockNum); +async function setLastReadBlockNumber( + db: DBConnector, + channelId: string, + blockNum: number, +) { + logger.debug( + `Set last read block number ${blockNum} on channel: ${channelId}`, + ); + await db.insert(getBHKey(channelId), blockNum); } -async function getLastReadBlockNumber(db: DBConnector, channelId: string): Promise { - try { - const blockNum = await db.read(getBHKey(channelId)); - return blockNum; - } catch(error: any) { - logger.error(`Error during GET block number in db: ${error.toString()}`); - throw error; - } +async function getLastReadBlockNumber( + db: DBConnector, + channelId: string, +): Promise { + try { + const blockNum = await db.read(getBHKey(channelId)); + return blockNum; + } catch (error: any) { + logger.error(`Error during GET block number in db: ${error.toString()}`); + throw error; + } } function createEventMatcher(eventName, channelId, chaincodeId, functionName) { - let eventMatcher = new events_pb.EventMatcher(); - eventMatcher.setEventType(events_pb.EventType.LEDGER_STATE); - eventMatcher.setEventClassId(eventName); - eventMatcher.setTransactionLedgerId(channelId); - eventMatcher.setTransactionContractId(chaincodeId); - eventMatcher.setTransactionFunc(functionName); - return eventMatcher; + const eventMatcher = new events_pb.EventMatcher(); + eventMatcher.setEventType(events_pb.EventType.LEDGER_STATE); + eventMatcher.setEventClassId(eventName); + eventMatcher.setTransactionLedgerId(channelId); + eventMatcher.setTransactionContractId(chaincodeId); + eventMatcher.setTransactionFunc(functionName); + return eventMatcher; } -async function eventHandler(eventMatcher: events_pb.EventMatcher, eventPayload: Buffer, networkName: string, loggerName: string) { - logger.info(`${loggerName}: Trying to find subscriptions for ${JSON.stringify(eventMatcher.toObject())}`); - // Find all matching event subscriptions stored in the database - const eventSubscriptionQueries = await lookupEventSubscriptions(eventMatcher); - // Iterate through the view requests in the matching event subscriptions - eventSubscriptionQueries.forEach(async (eventSubscriptionQuery: query_pb.Query) => { - logger.info(`${loggerName}: Generating view and collecting proof for event matcher: ${JSON.stringify(eventMatcher.toObject())} with event payload: ${eventPayload.toString()}`); - // Trigger proof collection - const [result, invokeError] = await handlePromise( - invoke( - eventSubscriptionQuery, - networkName, - 'HandleEventRequest', - eventPayload - ), - ); - if (!invokeError) { - // Package view and send to relay - const client = getRelayClientForEventPublish(); - const viewPayload = packageFabricView(eventSubscriptionQuery, result); +async function eventHandler( + eventMatcher: events_pb.EventMatcher, + eventPayload: Buffer, + networkName: string, + loggerName: string, +) { + logger.info( + `${loggerName}: Trying to find subscriptions for ${JSON.stringify(eventMatcher.toObject())}`, + ); + // Find all matching event subscriptions stored in the database + const eventSubscriptionQueries = await lookupEventSubscriptions(eventMatcher); + // Iterate through the view requests in the matching event subscriptions + eventSubscriptionQueries.forEach( + async (eventSubscriptionQuery: query_pb.Query) => { + logger.info( + `${loggerName}: Generating view and collecting proof for event matcher: ${JSON.stringify(eventMatcher.toObject())} with event payload: ${eventPayload.toString()}`, + ); + // Trigger proof collection + const [result, invokeError] = await handlePromise( + invoke( + eventSubscriptionQuery, + networkName, + "HandleEventRequest", + eventPayload, + ), + ); + if (!invokeError) { + // Package view and send to relay + const client = getRelayClientForEventPublish(); + const viewPayload = packageFabricView(eventSubscriptionQuery, result); - logger.info(`${loggerName}: Sending event`); - // Sending the Fabric event to the relay. - client.sendDriverState(viewPayload, relayCallback); - } - }) + logger.info(`${loggerName}: Sending event`); + // Sending the Fabric event to the relay. + client.sendDriverState(viewPayload, relayCallback); + } + }, + ); } /* @@ -90,290 +129,393 @@ async function eventHandler(eventMatcher: events_pb.EventMatcher, eventPayload: * 2. Emits all subscribed Contract Events */ const processBlockForEvents = async ( - block: any, - channelId: string, - networkName: string, - loggerName: string = "" + block: any, + channelId: string, + networkName: string, + loggerName: string = "", ) => { - // Parse the block data; typically there is only one element in this array but we will interate over it just to be safe - const blockNum = block.header.number; - const blockData = ((block as fabproto6.common.Block).data as fabproto6.common.BlockData).data; - const blockMetadata = ((block as fabproto6.common.Block).metadata as fabproto6.common.BlockMetadata).metadata; - const txFilterIndex = fabproto6.common.BlockMetadataIndex.TRANSACTIONS_FILTER; - const txValid = blockMetadata[txFilterIndex]; - logger.debug(`Event ${loggerName}: block #${blockNum}, #Transactions: ${blockData.length}`); - logger.debug(`Event ${loggerName}: block #${blockNum}, TxValidity: ${JSON.stringify(txValid)}`); - - blockData.forEach((item, index) => { - const payload = item['payload']; - const transactions = payload['data'].actions; - const tx_id = payload['header'].channel_header.tx_id; - logger.debug(`Event ${loggerName}: Transaction with TxId: ${tx_id}, index: ${index}`); - - if (txValid[index] === fabproto6.protos.TxValidationCode.VALID) { - // Iterate through the transaction list - transactions.forEach(async (transaction: any) => { - // Check if block subscription and then call handle block event - if (channelBlockListenerMap.has(channelId)) { - if (transaction.payload.chaincode_proposal_payload.input.chaincode_spec.input.args.length > 0) { - // Get transaction chaincode ID - const chaincodeId = transaction.payload.chaincode_proposal_payload.input.chaincode_spec.chaincode_id.name; - // below way of fetching payload requires that the response has been set by the chaincode function via return value - const responsePayload = transaction.payload.action.proposal_response_payload.extension.response.payload; - // Get transaction function name: first argument according to convention - const chaincodeFunc = transaction.payload.chaincode_proposal_payload.input.chaincode_spec.input.args[0].toString(); - const eventMatcher = createEventMatcher('', channelId, chaincodeId, chaincodeFunc); - eventHandler(eventMatcher, responsePayload, networkName, `BlockEvent ${loggerName}`); - } - } - - // Check if contract subscription and then call handle contract event - // Get transaction chaincode ID - const chaincodeId = transaction.payload.chaincode_proposal_payload.input.chaincode_spec.chaincode_id.name; - if (channelContractListenerMap.has(getChannelContractKey(channelId, chaincodeId))) { - // below way of fetching payload is similar to ContractEventListener in which we fetch event.payload - const eventPayload = transaction.payload.action.proposal_response_payload.extension.events.payload; - const eventName = transaction.payload.action.proposal_response_payload.extension.events.event_name; - const eventMatcher = createEventMatcher(eventName, channelId, chaincodeId, '*'); - eventHandler(eventMatcher, eventPayload, networkName, `ContractEvent ${loggerName}`); - } - }) - } else { - logger.error(`Event ${loggerName}: Transaction with TxId: ${tx_id} is invalid with code ${txValid[index]}:${fabproto6.protos.TxValidationCode[txValid[index]]}. Discarding.`); + // Parse the block data; typically there is only one element in this array but we will interate over it just to be safe + const blockNum = block.header.number; + const blockData = ( + (block as fabproto6.common.Block).data as fabproto6.common.BlockData + ).data; + const blockMetadata = ( + (block as fabproto6.common.Block).metadata as fabproto6.common.BlockMetadata + ).metadata; + const txFilterIndex = fabproto6.common.BlockMetadataIndex.TRANSACTIONS_FILTER; + const txValid = blockMetadata[txFilterIndex]; + logger.debug( + `Event ${loggerName}: block #${blockNum}, #Transactions: ${blockData.length}`, + ); + logger.debug( + `Event ${loggerName}: block #${blockNum}, TxValidity: ${JSON.stringify(txValid)}`, + ); + + blockData.forEach((item, index) => { + const payload = item["payload"]; + const transactions = payload["data"].actions; + const tx_id = payload["header"].channel_header.tx_id; + logger.debug( + `Event ${loggerName}: Transaction with TxId: ${tx_id}, index: ${index}`, + ); + + if (txValid[index] === fabproto6.protos.TxValidationCode.VALID) { + // Iterate through the transaction list + transactions.forEach(async (transaction: any) => { + // Check if block subscription and then call handle block event + if (channelBlockListenerMap.has(channelId)) { + if ( + transaction.payload.chaincode_proposal_payload.input.chaincode_spec + .input.args.length > 0 + ) { + // Get transaction chaincode ID + const chaincodeId = + transaction.payload.chaincode_proposal_payload.input + .chaincode_spec.chaincode_id.name; + // below way of fetching payload requires that the response has been set by the chaincode function via return value + const responsePayload = + transaction.payload.action.proposal_response_payload.extension + .response.payload; + // Get transaction function name: first argument according to convention + const chaincodeFunc = + transaction.payload.chaincode_proposal_payload.input.chaincode_spec.input.args[0].toString(); + const eventMatcher = createEventMatcher( + "", + channelId, + chaincodeId, + chaincodeFunc, + ); + eventHandler( + eventMatcher, + responsePayload, + networkName, + `BlockEvent ${loggerName}`, + ); + } } - }) -} + + // Check if contract subscription and then call handle contract event + // Get transaction chaincode ID + const chaincodeId = + transaction.payload.chaincode_proposal_payload.input.chaincode_spec + .chaincode_id.name; + if ( + channelContractListenerMap.has( + getChannelContractKey(channelId, chaincodeId), + ) + ) { + // below way of fetching payload is similar to ContractEventListener in which we fetch event.payload + const eventPayload = + transaction.payload.action.proposal_response_payload.extension + .events.payload; + const eventName = + transaction.payload.action.proposal_response_payload.extension + .events.event_name; + const eventMatcher = createEventMatcher( + eventName, + channelId, + chaincodeId, + "*", + ); + eventHandler( + eventMatcher, + eventPayload, + networkName, + `ContractEvent ${loggerName}`, + ); + } + }); + } else { + logger.error( + `Event ${loggerName}: Transaction with TxId: ${tx_id} is invalid with code ${txValid[index]}:${fabproto6.protos.TxValidationCode[txValid[index]]}. Discarding.`, + ); + } + }); +}; /** * Register a block listener with a callback **/ const initBlockEventListenerForChannel = async ( - network: Network, - networkName: string, - channelId: string, + network: Network, + networkName: string, + channelId: string, ): Promise => { - const listener: BlockListener = async (event: BlockEvent) => { - let bh_db: DBConnector; - bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); - await bh_db.open(); - try { - const lastBlockNum = await getLastReadBlockNumber(bh_db, channelId); - const currBlockNum = event.blockNumber.toNumber(); - // Log failed events for debugging purpose - event.getTransactionEvents().forEach((txEvent) => { - logger.info(`BlockEvent Listener: Block #${currBlockNum} event; LastReadBlock #${lastBlockNum}\n + const listener: BlockListener = async (event: BlockEvent) => { + let bh_db: DBConnector; + bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); + await bh_db.open(); + try { + const lastBlockNum = await getLastReadBlockNumber(bh_db, channelId); + const currBlockNum = event.blockNumber.toNumber(); + // Log failed events for debugging purpose + event.getTransactionEvents().forEach((txEvent) => { + logger.info(`BlockEvent Listener: Block #${currBlockNum} event; LastReadBlock #${lastBlockNum}\n TxId: ${txEvent.transactionId}, TxStatus: ${txEvent.status}, - isTxValid: ${txEvent.isValid}\n`) - }); - if (currBlockNum === lastBlockNum + 1) { - await processBlockForEvents(event.blockData, channelId, networkName, 'Listener'); - // Set current block number as listener block height - await setLastReadBlockNumber(bh_db, channelId, currBlockNum); - } - } catch(error: any) { - logger.error(`BlockEvent Listener: ${error.toString()}`); - } finally { - await bh_db.close(); - } - }; - await network.addBlockListener(listener); - channelBlockListenerMap.set(channelId, listener); - logger.info(`Added block listener for channel ${channelId}`); - return listener; -} + isTxValid: ${txEvent.isValid}\n`); + }); + if (currBlockNum === lastBlockNum + 1) { + await processBlockForEvents( + event.blockData, + channelId, + networkName, + "Listener", + ); + // Set current block number as listener block height + await setLastReadBlockNumber(bh_db, channelId, currBlockNum); + } + } catch (error: any) { + logger.error(`BlockEvent Listener: ${error.toString()}`); + } finally { + await bh_db.close(); + } + }; + await network.addBlockListener(listener); + channelBlockListenerMap.set(channelId, listener); + logger.info(`Added block listener for channel ${channelId}`); + return listener; +}; /** * Start an appropriate listener if there is currently none for the channel (or chaincode) this event subscription refers to. **/ const registerListenerForEventSubscription = async ( - eventMatcher: events_pb.EventMatcher, - networkName: string, + eventMatcher: events_pb.EventMatcher, + networkName: string, ): Promise => { - const channelId = eventMatcher.getTransactionLedgerId(); - const chaincodeId = eventMatcher.getTransactionContractId(); - let gateway: Gateway, network: Network; - if (networkGatewayMap.has(networkName)) { - gateway = networkGatewayMap.get(networkName); - network = networkChannelMap.get(channelId); - if (!network) { - throw new Error('No network/channel handle found for existing gateway and channel ID: ' + channelId); - } - } else { - gateway = await getNetworkGateway(networkName); - networkGatewayMap.set(networkName, gateway); - network = await gateway.getNetwork(channelId); - networkChannelMap.set(channelId, network); + const channelId = eventMatcher.getTransactionLedgerId(); + const chaincodeId = eventMatcher.getTransactionContractId(); + let gateway: Gateway, network: Network; + if (networkGatewayMap.has(networkName)) { + gateway = networkGatewayMap.get(networkName); + network = networkChannelMap.get(channelId); + if (!network) { + throw new Error( + "No network/channel handle found for existing gateway and channel ID: " + + channelId, + ); } - let listener = null; - if (globalLedgerListenerCount.has(channelId)) { - globalLedgerListenerCount.set(channelId, globalLedgerListenerCount.get(channelId) + 1); - } else { - let bh_db: DBConnector; - bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); - await bh_db.open(); - try { - const currBlockNum = await getCurrBlockNumber(network, channelId); - await setLastReadBlockNumber(bh_db, channelId, currBlockNum); - listener = await initBlockEventListenerForChannel(network, networkName, channelId); - if (eventMatcher.getEventClassId().length > 0) { - channelContractListenerMap.set(getChannelContractKey(channelId, chaincodeId), true); - } - globalLedgerListenerCount.set(channelId, 1); - } catch(error: any) { - logger.error(`registerListenerForEventSubscription: ${error.toString()}`); - throw error - } finally { - await bh_db.close(); - } + } else { + gateway = await getNetworkGateway(networkName); + networkGatewayMap.set(networkName, gateway); + network = await gateway.getNetwork(channelId); + networkChannelMap.set(channelId, network); + } + let listener = null; + if (globalLedgerListenerCount.has(channelId)) { + globalLedgerListenerCount.set( + channelId, + globalLedgerListenerCount.get(channelId) + 1, + ); + } else { + let bh_db: DBConnector; + bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); + await bh_db.open(); + try { + const currBlockNum = await getCurrBlockNumber(network, channelId); + await setLastReadBlockNumber(bh_db, channelId, currBlockNum); + listener = await initBlockEventListenerForChannel( + network, + networkName, + channelId, + ); + if (eventMatcher.getEventClassId().length > 0) { + channelContractListenerMap.set( + getChannelContractKey(channelId, chaincodeId), + true, + ); + } + globalLedgerListenerCount.set(channelId, 1); + } catch (error: any) { + logger.error(`registerListenerForEventSubscription: ${error.toString()}`); + throw error; + } finally { + await bh_db.close(); } - return listener; // If null, Listener was already running. Nothing to do. -} + } + return listener; // If null, Listener was already running. Nothing to do. +}; /** * Decrement subscription count against an active listener. Stop the listener if the count is 0. **/ const unregisterListenerForEventSubscription = async ( - eventMatcher: events_pb.EventMatcher, - networkName: string, + eventMatcher: events_pb.EventMatcher, + networkName: string, ): Promise => { - const channelId = eventMatcher.getTransactionLedgerId(); - const chaincodeId = eventMatcher.getTransactionContractId(); - let gateway: Gateway, network: Network; - if (networkGatewayMap.has(networkName)) { - gateway = networkGatewayMap.get(networkName); - network = networkChannelMap.get(channelId); - if (!network) { - throw new Error('No network/channel handle found for existing gateway and channel ID: ' + channelId); - } - } else { - gateway = await getNetworkGateway(networkName); - networkGatewayMap.set(networkName, gateway); - network = await gateway.getNetwork(channelId); - networkChannelMap.set(channelId, network); - } - if (!channelBlockListenerMap.has(channelId)) { - return false; + const channelId = eventMatcher.getTransactionLedgerId(); + const chaincodeId = eventMatcher.getTransactionContractId(); + let gateway: Gateway, network: Network; + if (networkGatewayMap.has(networkName)) { + gateway = networkGatewayMap.get(networkName); + network = networkChannelMap.get(channelId); + if (!network) { + throw new Error( + "No network/channel handle found for existing gateway and channel ID: " + + channelId, + ); } - // Update Global Listener count for the ledger - if (globalLedgerListenerCount.get(channelId) > 1) { - globalLedgerListenerCount.set(channelId, globalLedgerListenerCount.get(channelId) - 1); - return true; - } else { - let bh_db: DBConnector; - bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); - await bh_db.open(); - try { - // Set DB Height to -1 if no listener running - await setLastReadBlockNumber(bh_db, channelId, -1); - network.removeBlockListener(channelBlockListenerMap.get(channelId)); - if (eventMatcher.getEventClassId().length > 0) { - channelContractListenerMap.delete(getChannelContractKey(channelId, chaincodeId)); - } - channelBlockListenerMap.delete(channelId); - globalLedgerListenerCount.set(channelId, 0); - return true; - } catch(error: any) { - logger.error(`unregisterListenerForEventSubscription: ${error.toString()}`) - return false; - } finally { - await bh_db.close(); - } + } else { + gateway = await getNetworkGateway(networkName); + networkGatewayMap.set(networkName, gateway); + network = await gateway.getNetwork(channelId); + networkChannelMap.set(channelId, network); + } + if (!channelBlockListenerMap.has(channelId)) { + return false; + } + // Update Global Listener count for the ledger + if (globalLedgerListenerCount.get(channelId) > 1) { + globalLedgerListenerCount.set( + channelId, + globalLedgerListenerCount.get(channelId) - 1, + ); + return true; + } else { + let bh_db: DBConnector; + bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); + await bh_db.open(); + try { + // Set DB Height to -1 if no listener running + await setLastReadBlockNumber(bh_db, channelId, -1); + network.removeBlockListener(channelBlockListenerMap.get(channelId)); + if (eventMatcher.getEventClassId().length > 0) { + channelContractListenerMap.delete( + getChannelContractKey(channelId, chaincodeId), + ); + } + channelBlockListenerMap.delete(channelId); + globalLedgerListenerCount.set(channelId, 0); + return true; + } catch (error: any) { + logger.error( + `unregisterListenerForEventSubscription: ${error.toString()}`, + ); + return false; + } finally { + await bh_db.close(); } -} + } +}; /** * Load event subscriptions from the driver database. * Start a listener for each channel from which one of the subscribed events originate. **/ -const loadEventSubscriptionsFromStorage = async (networkName: string): Promise => { - logger.info('Starting event listeners for subscribed events in database...') - try { - const eventMatchers = await readAllEventMatchers(); - for (const eventMatcher of eventMatchers) { - try { - const listenerHandle = await registerListenerForEventSubscription( - eventMatcher, - networkName - ) - } catch(error) { - logger.error(`Error: Could not start event listener for ${JSON.stringify(eventMatcher.toObject())} with error: ${error}`) - return false - } - } - } catch(error) { - logger.error(`Error: event matcher read error: ${error}`) - return false +const loadEventSubscriptionsFromStorage = async ( + networkName: string, +): Promise => { + logger.info("Starting event listeners for subscribed events in database..."); + try { + const eventMatchers = await readAllEventMatchers(); + for (const eventMatcher of eventMatchers) { + try { + const listenerHandle = await registerListenerForEventSubscription( + eventMatcher, + networkName, + ); + } catch (error) { + logger.error( + `Error: Could not start event listener for ${JSON.stringify(eventMatcher.toObject())} with error: ${error}`, + ); + return false; + } } - return true -} + } catch (error) { + logger.error(`Error: event matcher read error: ${error}`); + return false; + } + return true; +}; /* * Get block by block number using query to QSCC */ -async function getBlockByNum(network: Network, channelId: string, blockNum: number): Promise { - const contract = network.getContract("qscc"); +async function getBlockByNum( + network: Network, + channelId: string, + blockNum: number, +): Promise { + const contract = network.getContract("qscc"); - let [result, invokeError] = await handlePromise( - contract.evaluateTransaction("GetBlockByNumber", channelId, `${blockNum}`) - ); - if (invokeError) { - throw invokeError - } - const block = BlockDecoder.decode(result); - return block; + const [result, invokeError] = await handlePromise( + contract.evaluateTransaction("GetBlockByNumber", channelId, `${blockNum}`), + ); + if (invokeError) { + throw invokeError; + } + const block = BlockDecoder.decode(result); + return block; } /* * Get latest block number using query to QSCC */ -async function getCurrBlockNumber(network: Network, channelId: string): Promise { - const contract = network.getContract("qscc"); +async function getCurrBlockNumber( + network: Network, + channelId: string, +): Promise { + const contract = network.getContract("qscc"); - let [result, invokeError] = await handlePromise( - contract.evaluateTransaction("GetChainInfo", channelId) - ); - if (invokeError) { - throw invokeError - } - const blockHeight = fabproto6.common.BlockchainInfo.decode(Buffer.from(result)).height as number; - const blockNum = blockHeight - 1; - logger.debug(`getCurrBlockNumber: Get current block number: ${blockNum}`); - return blockNum; + const [result, invokeError] = await handlePromise( + contract.evaluateTransaction("GetChainInfo", channelId), + ); + if (invokeError) { + throw invokeError; + } + const blockHeight = fabproto6.common.BlockchainInfo.decode( + Buffer.from(result), + ).height as number; + const blockNum = blockHeight - 1; + logger.debug(`getCurrBlockNumber: Get current block number: ${blockNum}`); + return blockNum; } /* * Monitor to handle block events that were missed/discarded by listener. */ const monitorBlockForMissedEvents = async (networkName: string) => { - logger.debug("############### Monitor Begin #################") - // Create connection to a database - let bh_db: DBConnector; - bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); - await bh_db.open(); - try { - if (networkGatewayMap.has(networkName)) { - const gateway = networkGatewayMap.get(networkName); - // Handle Block Events - for (let [channelId, network] of networkChannelMap) { - const currBlockNum = await getCurrBlockNumber(network, channelId); - const lastBlockNum = await getLastReadBlockNumber(bh_db, channelId); - logger.debug(`Monitor: Current Block #${currBlockNum}; LastReadBlock #${lastBlockNum}`); - if (currBlockNum > lastBlockNum) { - for (let bnum=lastBlockNum+1; bnum<=currBlockNum; bnum++) { - const block = await getBlockByNum(network, channelId, bnum); - await processBlockForEvents(block, channelId, networkName, "Monitor"); - } - // Update block number in DB - await setLastReadBlockNumber(bh_db, channelId, currBlockNum); - } - } + logger.debug("############### Monitor Begin #################"); + // Create connection to a database + let bh_db: DBConnector; + bh_db = new LevelDBConnector(DB_NAME!, DB_OPEN_TIMEOUT); + await bh_db.open(); + try { + if (networkGatewayMap.has(networkName)) { + const gateway = networkGatewayMap.get(networkName); + // Handle Block Events + for (const [channelId, network] of networkChannelMap) { + const currBlockNum = await getCurrBlockNumber(network, channelId); + const lastBlockNum = await getLastReadBlockNumber(bh_db, channelId); + logger.debug( + `Monitor: Current Block #${currBlockNum}; LastReadBlock #${lastBlockNum}`, + ); + if (currBlockNum > lastBlockNum) { + for (let bnum = lastBlockNum + 1; bnum <= currBlockNum; bnum++) { + const block = await getBlockByNum(network, channelId, bnum); + await processBlockForEvents( + block, + channelId, + networkName, + "Monitor", + ); + } + // Update block number in DB + await setLastReadBlockNumber(bh_db, channelId, currBlockNum); } - } catch(error: any) { - logger.error(`Monitor Error: ${error}`) + } } - await bh_db.close(); - logger.debug("############### Monitor End ###################"); -} + } catch (error: any) { + logger.error(`Monitor Error: ${error}`); + } + await bh_db.close(); + logger.debug("############### Monitor End ###################"); +}; -export { registerListenerForEventSubscription, unregisterListenerForEventSubscription, loadEventSubscriptionsFromStorage, monitorBlockForMissedEvents }; +export { + registerListenerForEventSubscription, + unregisterListenerForEventSubscription, + loadEventSubscriptionsFromStorage, + monitorBlockForMissedEvents, +}; diff --git a/weaver/core/drivers/fabric-driver/server/logger.ts b/weaver/core/drivers/fabric-driver/server/logger.ts index 7b14c5a377..a961d85d56 100644 --- a/weaver/core/drivers/fabric-driver/server/logger.ts +++ b/weaver/core/drivers/fabric-driver/server/logger.ts @@ -4,26 +4,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as winston from 'winston' -import * as path from 'path' -const { format, transports } = winston +import * as winston from "winston"; +import * as path from "path"; +const { format, transports } = winston; const logFormat = format.printf( - info => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}` -) + (info) => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`, +); const logger = winston.createLogger({ format: format.combine( format.label({ label: path.basename(process.mainModule.filename) }), - format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }) + format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] }), ), transports: [ new transports.Console({ - format: format.combine(format.colorize(), logFormat) - }) + format: format.combine(format.colorize(), logFormat), + }), ], - exitOnError: false -}) + exitOnError: false, +}); -export default logger +export default logger; diff --git a/weaver/core/drivers/fabric-driver/server/server.ts b/weaver/core/drivers/fabric-driver/server/server.ts index c645caece3..9d0fafbd3c 100644 --- a/weaver/core/drivers/fabric-driver/server/server.ts +++ b/weaver/core/drivers/fabric-driver/server/server.ts @@ -4,295 +4,384 @@ * SPDX-License-Identifier: Apache-2.0 */ -import fs from 'fs'; -import { Server, ServerCredentials, credentials } from '@grpc/grpc-js'; -import ack_pb from '@hyperledger/cacti-weaver-protos-js/common/ack_pb'; -import query_pb from '@hyperledger/cacti-weaver-protos-js/common/query_pb'; -import fabricViewPb from '@hyperledger/cacti-weaver-protos-js/fabric/view_data_pb'; -import eventsPb from '@hyperledger/cacti-weaver-protos-js/common/events_pb'; -import driver_pb_grpc from '@hyperledger/cacti-weaver-protos-js/driver/driver_grpc_pb'; -import datatransfer_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/datatransfer_grpc_pb'; -import events_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb'; -import state_pb from '@hyperledger/cacti-weaver-protos-js/common/state_pb'; -import { invoke, packageFabricView } from './fabric-code'; -import 'dotenv/config'; -import { loadEventSubscriptionsFromStorage, monitorBlockForMissedEvents } from './listener' -import { walletSetup } from './walletSetup'; -import { subscribeEventHelper, unsubscribeEventHelper, signEventSubscriptionQuery, writeExternalStateHelper } from "./events" -import * as path from 'path'; -import { handlePromise, relayCallback, getRelayClientForQueryResponse, getRelayClientForEventSubscription, delay } from './utils'; -import { dbConnectionTest, eventSubscriptionTest } from "./tests" -import driverPb from '@hyperledger/cacti-weaver-protos-js/driver/driver_pb'; -import logger from './logger'; +import fs from "fs"; +import { Server, ServerCredentials, credentials } from "@grpc/grpc-js"; +import ack_pb from "@hyperledger/cacti-weaver-protos-js/common/ack_pb"; +import query_pb from "@hyperledger/cacti-weaver-protos-js/common/query_pb"; +import fabricViewPb from "@hyperledger/cacti-weaver-protos-js/fabric/view_data_pb"; +import eventsPb from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import driver_pb_grpc from "@hyperledger/cacti-weaver-protos-js/driver/driver_grpc_pb"; +import datatransfer_grpc_pb from "@hyperledger/cacti-weaver-protos-js/relay/datatransfer_grpc_pb"; +import events_grpc_pb from "@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb"; +import state_pb from "@hyperledger/cacti-weaver-protos-js/common/state_pb"; +import { invoke, packageFabricView } from "./fabric-code"; +import "dotenv/config"; +import { + loadEventSubscriptionsFromStorage, + monitorBlockForMissedEvents, +} from "./listener"; +import { walletSetup } from "./walletSetup"; +import { + subscribeEventHelper, + unsubscribeEventHelper, + signEventSubscriptionQuery, + writeExternalStateHelper, +} from "./events"; +import * as path from "path"; +import { + handlePromise, + relayCallback, + getRelayClientForQueryResponse, + getRelayClientForEventSubscription, + delay, +} from "./utils"; +import { dbConnectionTest, eventSubscriptionTest } from "./tests"; +import driverPb from "@hyperledger/cacti-weaver-protos-js/driver/driver_pb"; +import logger from "./logger"; -if (process.env.DEBUG === 'true') { - logger.level = 'debug' +if (process.env.DEBUG === "true") { + logger.level = "debug"; } const server = new Server(); -logger.info('driver def', JSON.stringify(driver_pb_grpc)); -logger.debug('Debug Logs ON'); - +logger.info("driver def", JSON.stringify(driver_pb_grpc)); +logger.debug("Debug Logs ON"); const mockedB64Data = - 'CkIIyAEaPRI7bG9jYWxob3N0OjkwODAvbmV0d29yazEvbXljaGFubmVsOnNpbXBsZXN0YXRlOlJlYWQ6QXJjdHVydXMa/AIKIFhDpf9CYfrxPkEtSWR8Kf+K5pBkSbx7VNYsAzijB+pnEtcCCoICEmYKCl9saWZlY3ljbGUSWAooCiJuYW1lc3BhY2VzL2ZpZWxkcy9pbnRlcm9wL1NlcXVlbmNlEgIIAwosCiZuYW1lc3BhY2VzL2ZpZWxkcy9zaW1wbGVzdGF0ZS9TZXF1ZW5jZRICCAYSYwoHaW50ZXJvcBJYCh4KGABhY2Nlc3NDb250cm9sAG5ldHdvcmsxABICCAsKHgoYAHNlY3VyaXR5R3JvdXAAbmV0d29yazEAEgIIDQoWChAA9I+/v2luaXRpYWxpemVkEgIIBBIzCgtzaW1wbGVzdGF0ZRIkChYKEAD0j7+/aW5pdGlhbGl6ZWQSAggHCgoKCEFyY3R1cnVzGkIIyAEaPRI7bG9jYWxob3N0OjkwODAvbmV0d29yazEvbXljaGFubmVsOnNpbXBsZXN0YXRlOlJlYWQ6QXJjdHVydXMiDBIHaW50ZXJvcBoBMSK1CArpBwoHT3JnMU1TUBLdBy0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlDckRDQ0FsT2dBd0lCQWdJVVdNUkUyTEJwdnY1TkdSRi9hMy82cWZTcE9TNHdDZ1lJS29aSXpqMEVBd0l3CmNqRUxNQWtHQTFVRUJoTUNWVk14RnpBVkJnTlZCQWdURGs1dmNuUm9JRU5oY205c2FXNWhNUTh3RFFZRFZRUUgKRXdaRWRYSm9ZVzB4R2pBWUJnTlZCQW9URVc5eVp6RXVibVYwZDI5eWF6RXVZMjl0TVIwd0d3WURWUVFERXhSagpZUzV2Y21jeExtNWxkSGR2Y21zeExtTnZiVEFlRncweU1EQTNNamt3TkRNMk1EQmFGdzB5TVRBM01qa3dORFF4Ck1EQmFNRnN4Q3pBSkJnTlZCQVlUQWxWVE1SY3dGUVlEVlFRSUV3NU9iM0owYUNCRFlYSnZiR2x1WVRFVU1CSUcKQTFVRUNoTUxTSGx3WlhKc1pXUm5aWEl4RFRBTEJnTlZCQXNUQkhCbFpYSXhEakFNQmdOVkJBTVRCWEJsWlhJdwpNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUU1RlFrSDgzRVdnYW9DZ2U5azhISU1Jd0NUVGVZCnFCR25xNFAzWHJCUGZQSFdXeE1oWGhBaDNvUHNUOXdna1dHcFVmYWlybkd0bmRBQ3ZrSitNQi9nMUtPQjNUQ0IKMmpBT0JnTlZIUThCQWY4RUJBTUNCNEF3REFZRFZSMFRBUUgvQkFJd0FEQWRCZ05WSFE0RUZnUVVLMkFuM3RCTAprMVQyRGord0hHZ1RIQ3NiYmlZd0h3WURWUjBqQkJnd0ZvQVUxZyt0UG5naDJ3OGc5OXoxbXdzVmJrS2pBS2t3CklnWURWUjBSQkJzd0dZSVhjR1ZsY2pBdWIzSm5NUzV1WlhSM2IzSnJNUzVqYjIwd1ZnWUlLZ01FQlFZSENBRUUKU25zaVlYUjBjbk1pT25zaWFHWXVRV1ptYVd4cFlYUnBiMjRpT2lJaUxDSm9aaTVGYm5KdmJHeHRaVzUwU1VRaQpPaUp3WldWeU1DSXNJbWhtTGxSNWNHVWlPaUp3WldWeUluMTlNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJQmFRCjhoTmRXd2xYeUhxY2htQzdzVUpWaER6Mkg2enh3M1BQS1I5M3lCL3NBaUJKMnpnQlhzL1lsMGZubnJNUXVCQUQKcDFBS1RKTkpsMVYwWUVHMFhiNXFwZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KEkcwRQIhAMyyvrcjHVc1oQmCNqZpH6nc0O+8wssXjwRcfmgxlhQAAiAqa0C8pSFNZNXiSVJHe948dJ0NU/y+7i5A55O0Frkz2Q=='; + "CkIIyAEaPRI7bG9jYWxob3N0OjkwODAvbmV0d29yazEvbXljaGFubmVsOnNpbXBsZXN0YXRlOlJlYWQ6QXJjdHVydXMa/AIKIFhDpf9CYfrxPkEtSWR8Kf+K5pBkSbx7VNYsAzijB+pnEtcCCoICEmYKCl9saWZlY3ljbGUSWAooCiJuYW1lc3BhY2VzL2ZpZWxkcy9pbnRlcm9wL1NlcXVlbmNlEgIIAwosCiZuYW1lc3BhY2VzL2ZpZWxkcy9zaW1wbGVzdGF0ZS9TZXF1ZW5jZRICCAYSYwoHaW50ZXJvcBJYCh4KGABhY2Nlc3NDb250cm9sAG5ldHdvcmsxABICCAsKHgoYAHNlY3VyaXR5R3JvdXAAbmV0d29yazEAEgIIDQoWChAA9I+/v2luaXRpYWxpemVkEgIIBBIzCgtzaW1wbGVzdGF0ZRIkChYKEAD0j7+/aW5pdGlhbGl6ZWQSAggHCgoKCEFyY3R1cnVzGkIIyAEaPRI7bG9jYWxob3N0OjkwODAvbmV0d29yazEvbXljaGFubmVsOnNpbXBsZXN0YXRlOlJlYWQ6QXJjdHVydXMiDBIHaW50ZXJvcBoBMSK1CArpBwoHT3JnMU1TUBLdBy0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlDckRDQ0FsT2dBd0lCQWdJVVdNUkUyTEJwdnY1TkdSRi9hMy82cWZTcE9TNHdDZ1lJS29aSXpqMEVBd0l3CmNqRUxNQWtHQTFVRUJoTUNWVk14RnpBVkJnTlZCQWdURGs1dmNuUm9JRU5oY205c2FXNWhNUTh3RFFZRFZRUUgKRXdaRWRYSm9ZVzB4R2pBWUJnTlZCQW9URVc5eVp6RXVibVYwZDI5eWF6RXVZMjl0TVIwd0d3WURWUVFERXhSagpZUzV2Y21jeExtNWxkSGR2Y21zeExtTnZiVEFlRncweU1EQTNNamt3TkRNMk1EQmFGdzB5TVRBM01qa3dORFF4Ck1EQmFNRnN4Q3pBSkJnTlZCQVlUQWxWVE1SY3dGUVlEVlFRSUV3NU9iM0owYUNCRFlYSnZiR2x1WVRFVU1CSUcKQTFVRUNoTUxTSGx3WlhKc1pXUm5aWEl4RFRBTEJnTlZCQXNUQkhCbFpYSXhEakFNQmdOVkJBTVRCWEJsWlhJdwpNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUU1RlFrSDgzRVdnYW9DZ2U5azhISU1Jd0NUVGVZCnFCR25xNFAzWHJCUGZQSFdXeE1oWGhBaDNvUHNUOXdna1dHcFVmYWlybkd0bmRBQ3ZrSitNQi9nMUtPQjNUQ0IKMmpBT0JnTlZIUThCQWY4RUJBTUNCNEF3REFZRFZSMFRBUUgvQkFJd0FEQWRCZ05WSFE0RUZnUVVLMkFuM3RCTAprMVQyRGord0hHZ1RIQ3NiYmlZd0h3WURWUjBqQkJnd0ZvQVUxZyt0UG5naDJ3OGc5OXoxbXdzVmJrS2pBS2t3CklnWURWUjBSQkJzd0dZSVhjR1ZsY2pBdWIzSm5NUzV1WlhSM2IzSnJNUzVqYjIwd1ZnWUlLZ01FQlFZSENBRUUKU25zaVlYUjBjbk1pT25zaWFHWXVRV1ptYVd4cFlYUnBiMjRpT2lJaUxDSm9aaTVGYm5KdmJHeHRaVzUwU1VRaQpPaUp3WldWeU1DSXNJbWhtTGxSNWNHVWlPaUp3WldWeUluMTlNQW9HQ0NxR1NNNDlCQU1DQTBjQU1FUUNJQmFRCjhoTmRXd2xYeUhxY2htQzdzVUpWaER6Mkg2enh3M1BQS1I5M3lCL3NBaUJKMnpnQlhzL1lsMGZubnJNUXVCQUQKcDFBS1RKTkpsMVYwWUVHMFhiNXFwZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KEkcwRQIhAMyyvrcjHVc1oQmCNqZpH6nc0O+8wssXjwRcfmgxlhQAAiAqa0C8pSFNZNXiSVJHe948dJ0NU/y+7i5A55O0Frkz2Q=="; // Mocked fabric communication function function mockCommunication(query: query_pb.Query) { - logger.info('Mock Communication'); - // Query object from requestor - logger.info(`query ${query.getRequestId()}`); - setTimeout(() => { - logger.info('Sending state'); - const meta = new state_pb.Meta(); - meta.setTimestamp(new Date().toISOString()); - meta.setProofType('Notarization'); - meta.setSerializationFormat('STRING'); - meta.setProtocol(state_pb.Meta.Protocol.FABRIC); - const view = new state_pb.View(); - view.setMeta(meta); + logger.info("Mock Communication"); + // Query object from requestor + logger.info(`query ${query.getRequestId()}`); + setTimeout(() => { + logger.info("Sending state"); + const meta = new state_pb.Meta(); + meta.setTimestamp(new Date().toISOString()); + meta.setProofType("Notarization"); + meta.setSerializationFormat("STRING"); + meta.setProtocol(state_pb.Meta.Protocol.FABRIC); + const view = new state_pb.View(); + view.setMeta(meta); + const viewDataBinary = + fabricViewPb.FabricView.deserializeBinary( //@ts-ignore - const viewDataBinary = fabricViewPb.FabricView.deserializeBinary(mockedB64Data).serializeBinary(); - logger.info(`viewData ${viewDataBinary}`); - view.setData(viewDataBinary); - const viewPayload = new state_pb.ViewPayload(); - viewPayload.setView(view); - viewPayload.setRequestId(query.getRequestId()); - if (!process.env.RELAY_ENDPOINT) { - throw new Error('RELAY_ENDPOINT is not set.'); - } - const client = new datatransfer_grpc_pb.DataTransferClient( - process.env.RELAY_ENDPOINT, - credentials.createInsecure(), - ); - client.sendDriverState(viewPayload, relayCallback); - }, 3000); + mockedB64Data, + ).serializeBinary(); + logger.info(`viewData ${viewDataBinary}`); + view.setData(viewDataBinary); + const viewPayload = new state_pb.ViewPayload(); + viewPayload.setView(view); + viewPayload.setRequestId(query.getRequestId()); + if (!process.env.RELAY_ENDPOINT) { + throw new Error("RELAY_ENDPOINT is not set."); + } + const client = new datatransfer_grpc_pb.DataTransferClient( + process.env.RELAY_ENDPOINT, + credentials.createInsecure(), + ); + client.sendDriverState(viewPayload, relayCallback); + }, 3000); } // Handles communication with fabric network and sends resulting data to the relay -const fabricCommunication = async (query: query_pb.Query, networkName: string) => { - // Query object from requestor - logger.info(`query ${query.getRequestId()}`); +const fabricCommunication = async ( + query: query_pb.Query, + networkName: string, +) => { + // Query object from requestor + logger.info(`query ${query.getRequestId()}`); - // Client created using the relay_endpoint in the env. - // TODO: need credentials here to ensure the local relay is only communicating with local drivers - if (!process.env.RELAY_ENDPOINT) { - throw new Error('RELAY_ENDPOINT is not set.'); - } - // Invokes the fabric network - const [result, invokeError] = await handlePromise( - invoke( - query, - networkName, - 'HandleExternalRequest' - ), - ); - const client = getRelayClientForQueryResponse(); - if (invokeError) { - logger.error('Invoke Error'); - const errorViewPayload = new state_pb.ViewPayload(); - errorViewPayload.setError(`Error: ${invokeError.toString()}`); - errorViewPayload.setRequestId(query.getRequestId()); - // Send the error state to the relay - client.sendDriverState(errorViewPayload, relayCallback); - } else { - // Process response from invoke to send to relay - logger.info(`Result of fabric invoke ${result}`); - logger.info('Sending state'); - const viewPayload: state_pb.ViewPayload = packageFabricView(query, result); + // Client created using the relay_endpoint in the env. + // TODO: need credentials here to ensure the local relay is only communicating with local drivers + if (!process.env.RELAY_ENDPOINT) { + throw new Error("RELAY_ENDPOINT is not set."); + } + // Invokes the fabric network + const [result, invokeError] = await handlePromise( + invoke(query, networkName, "HandleExternalRequest"), + ); + const client = getRelayClientForQueryResponse(); + if (invokeError) { + logger.error("Invoke Error"); + const errorViewPayload = new state_pb.ViewPayload(); + errorViewPayload.setError(`Error: ${invokeError.toString()}`); + errorViewPayload.setRequestId(query.getRequestId()); + // Send the error state to the relay + client.sendDriverState(errorViewPayload, relayCallback); + } else { + // Process response from invoke to send to relay + logger.info(`Result of fabric invoke ${result}`); + logger.info("Sending state"); + const viewPayload: state_pb.ViewPayload = packageFabricView(query, result); - logger.info('Sending state'); - // Sending the fabric state to the relay. - client.sendDriverState(viewPayload, relayCallback); - } + logger.info("Sending state"); + // Sending the fabric state to the relay. + client.sendDriverState(viewPayload, relayCallback); + } }; -const spawnSubscribeEventHelper = async (request: eventsPb.EventSubscription, newRequestId: string) => { - const subscriptionOp: eventsPb.EventSubOperation = request.getOperation(); - const client = getRelayClientForEventSubscription() - if (subscriptionOp == eventsPb.EventSubOperation.SUBSCRIBE) { - subscribeEventHelper(request, client, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'); - } else if (subscriptionOp == eventsPb.EventSubOperation.UNSUBSCRIBE) { - unsubscribeEventHelper(request, client, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'); - } else { - const errorString: string = `Error: subscribe operation ${subscriptionOp.toString()} not supported`; - logger.error(errorString); - const ack_send_error = new ack_pb.Ack(); - ack_send_error.setRequestId(newRequestId); - ack_send_error.setMessage(errorString); - ack_send_error.setStatus(ack_pb.Ack.STATUS.ERROR); - // gRPC response. - logger.info(`Sending to the relay the eventSubscription error Ack: ${JSON.stringify(ack_send_error.toObject())}`); - // Sending the fabric state to the relay. - client.sendDriverSubscriptionStatus(ack_send_error, relayCallback); - } -} +const spawnSubscribeEventHelper = async ( + request: eventsPb.EventSubscription, + newRequestId: string, +) => { + const subscriptionOp: eventsPb.EventSubOperation = request.getOperation(); + const client = getRelayClientForEventSubscription(); + if (subscriptionOp == eventsPb.EventSubOperation.SUBSCRIBE) { + subscribeEventHelper( + request, + client, + process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1", + ); + } else if (subscriptionOp == eventsPb.EventSubOperation.UNSUBSCRIBE) { + unsubscribeEventHelper( + request, + client, + process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1", + ); + } else { + const errorString: string = `Error: subscribe operation ${subscriptionOp.toString()} not supported`; + logger.error(errorString); + const ack_send_error = new ack_pb.Ack(); + ack_send_error.setRequestId(newRequestId); + ack_send_error.setMessage(errorString); + ack_send_error.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info( + `Sending to the relay the eventSubscription error Ack: ${JSON.stringify(ack_send_error.toObject())}`, + ); + // Sending the fabric state to the relay. + client.sendDriverSubscriptionStatus(ack_send_error, relayCallback); + } +}; // Service for receiving communication from a relay. Will communicate with the network and respond with an ack to the relay while the fabric communication is being completed. //@ts-ignore server.addService(driver_pb_grpc.DriverCommunicationService, { - requestDriverState: (call: { request: query_pb.Query }, callback: (_: any, object: ack_pb.Ack) => void) => { - const ack_response = new ack_pb.Ack(); - try { - if (process.env.MOCK === 'true') { - mockCommunication(call.request); - } else { - fabricCommunication(call.request, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'); - } - ack_response.setMessage(''); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - ack_response.setRequestId(call.request.getRequestId()); - // gRPC response. - logger.info('Responding to caller'); - callback(null, ack_response); - } catch (e) { - logger.error(e); - ack_response.setMessage(`Error: ${e}`); - ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); - ack_response.setRequestId(call.request.getRequestId()); - // gRPC response. - logger.info('Responding to caller'); - callback(null, ack_response); - } - }, - subscribeEvent: (call: { request: eventsPb.EventSubscription }, callback: (_: any, object: ack_pb.Ack) => void) => { - const newRequestId: string = call.request.getQuery()!.getRequestId() - logger.info(`newRequestId: ${newRequestId}`); - try { - if (process.env.MOCK !== 'true') { - spawnSubscribeEventHelper(call.request, newRequestId) - const ack_response = new ack_pb.Ack(); - ack_response.setRequestId(newRequestId); - ack_response.setMessage('Procesing addEventSubscription'); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - // gRPC response. - logger.info(`Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`); - callback(null, ack_response); - } else { - dbConnectionTest().then((dbConnectTestStatus) => { - if (dbConnectTestStatus == true) { - eventSubscriptionTest(call.request).then((eventSubscribeTestStatus) => { - if (eventSubscribeTestStatus == false) { - logger.error(`Failed eventSubscriptionTest()`); - } - // add code to support more functionalities here - }); - } else { - logger.error(`Failed dbConnectionTest()`); - } - }); - } - } catch (e) { - const errorString: string = e.toString(); - logger.error(`error: ${errorString}`); - const ack_error_response = new ack_pb.Ack(); - ack_error_response.setRequestId(newRequestId); - ack_error_response.setMessage(`Error: ${errorString}`); - ack_error_response.setStatus(ack_pb.Ack.STATUS.ERROR); - // gRPC response. - logger.error(`Responding to caller with Ack: ${JSON.stringify(ack_error_response.toObject())}`); - callback(null, ack_error_response); - } - }, - requestSignedEventSubscriptionQuery: (call: { request: eventsPb.EventSubscription }, callback: (_: any, object: query_pb.Query) => void) => { + requestDriverState: ( + call: { request: query_pb.Query }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const ack_response = new ack_pb.Ack(); + try { + if (process.env.MOCK === "true") { + mockCommunication(call.request); + } else { + fabricCommunication( + call.request, + process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1", + ); + } + ack_response.setMessage(""); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + ack_response.setRequestId(call.request.getRequestId()); + // gRPC response. + logger.info("Responding to caller"); + callback(null, ack_response); + } catch (e) { + logger.error(e); + ack_response.setMessage(`Error: ${e}`); + ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); + ack_response.setRequestId(call.request.getRequestId()); + // gRPC response. + logger.info("Responding to caller"); + callback(null, ack_response); + } + }, + subscribeEvent: ( + call: { request: eventsPb.EventSubscription }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const newRequestId: string = call.request.getQuery()!.getRequestId(); + logger.info(`newRequestId: ${newRequestId}`); + try { + if (process.env.MOCK !== "true") { + spawnSubscribeEventHelper(call.request, newRequestId); const ack_response = new ack_pb.Ack(); - - signEventSubscriptionQuery(call.request.getQuery()!).then((signedQuery) => { - // gRPC response. - logger.info(`Responding to caller with signedQuery: ${JSON.stringify(signedQuery.toObject())}`); - callback(null, signedQuery); - }).catch((error) => { - const errorString: string = error.toString(); - logger.error(`error: ${errorString}`); - var emptyQuery: query_pb.Query = new query_pb.Query(); - emptyQuery.setRequestorSignature(errorString); - // gRPC response. - logger.info(`Responding to caller with emptyQuery: ${JSON.stringify(emptyQuery.toObject())}`); - callback(null, emptyQuery); + ack_response.setRequestId(newRequestId); + ack_response.setMessage("Procesing addEventSubscription"); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + // gRPC response. + logger.info( + `Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`, + ); + callback(null, ack_response); + } else { + dbConnectionTest().then((dbConnectTestStatus) => { + if (dbConnectTestStatus == true) { + eventSubscriptionTest(call.request).then( + (eventSubscribeTestStatus) => { + if (eventSubscribeTestStatus == false) { + logger.error(`Failed eventSubscriptionTest()`); + } + // add code to support more functionalities here + }, + ); + } else { + logger.error(`Failed dbConnectionTest()`); + } }); - }, - writeExternalState: (call: { request: driverPb.WriteExternalStateMessage }, callback: (_: any, object: ack_pb.Ack) => void) => { - const viewPayload: state_pb.ViewPayload = call.request.getViewPayload(); - const requestId: string = viewPayload.getRequestId(); + } + } catch (e) { + const errorString: string = e.toString(); + logger.error(`error: ${errorString}`); + const ack_error_response = new ack_pb.Ack(); + ack_error_response.setRequestId(newRequestId); + ack_error_response.setMessage(`Error: ${errorString}`); + ack_error_response.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.error( + `Responding to caller with Ack: ${JSON.stringify(ack_error_response.toObject())}`, + ); + callback(null, ack_error_response); + } + }, + requestSignedEventSubscriptionQuery: ( + call: { request: eventsPb.EventSubscription }, + callback: (_: any, object: query_pb.Query) => void, + ) => { + const ack_response = new ack_pb.Ack(); - writeExternalStateHelper(call.request, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1').then(() => { - const ack_response = new ack_pb.Ack(); - ack_response.setRequestId(requestId); - ack_response.setMessage('Successfully written to the ledger'); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - // gRPC response. - logger.info(`Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`); - callback(null, ack_response); - }).catch((error) => { - const ack_err_response = new ack_pb.Ack(); - ack_err_response.setRequestId(requestId); - ack_err_response.setMessage(error.toString()); - ack_err_response.setStatus(ack_pb.Ack.STATUS.ERROR); - // gRPC response. - logger.info(`Responding to caller with error Ack: ${JSON.stringify(ack_err_response.toObject())}`); - callback(null, ack_err_response); - }); - }, + signEventSubscriptionQuery(call.request.getQuery()!) + .then((signedQuery) => { + // gRPC response. + logger.info( + `Responding to caller with signedQuery: ${JSON.stringify(signedQuery.toObject())}`, + ); + callback(null, signedQuery); + }) + .catch((error) => { + const errorString: string = error.toString(); + logger.error(`error: ${errorString}`); + const emptyQuery: query_pb.Query = new query_pb.Query(); + emptyQuery.setRequestorSignature(errorString); + // gRPC response. + logger.info( + `Responding to caller with emptyQuery: ${JSON.stringify(emptyQuery.toObject())}`, + ); + callback(null, emptyQuery); + }); + }, + writeExternalState: ( + call: { request: driverPb.WriteExternalStateMessage }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const viewPayload: state_pb.ViewPayload = call.request.getViewPayload(); + const requestId: string = viewPayload.getRequestId(); + + writeExternalStateHelper( + call.request, + process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1", + ) + .then(() => { + const ack_response = new ack_pb.Ack(); + ack_response.setRequestId(requestId); + ack_response.setMessage("Successfully written to the ledger"); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + // gRPC response. + logger.info( + `Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`, + ); + callback(null, ack_response); + }) + .catch((error) => { + const ack_err_response = new ack_pb.Ack(); + ack_err_response.setRequestId(requestId); + ack_err_response.setMessage(error.toString()); + ack_err_response.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info( + `Responding to caller with error Ack: ${JSON.stringify(ack_err_response.toObject())}`, + ); + callback(null, ack_err_response); + }); + }, }); // Prepares required crypto material for communication with the fabric network const configSetup = async () => { - // uses the network name to create a unique wallet path - const walletPath = process.env.WALLET_PATH ? process.env.WALLET_PATH : path.join(process.cwd(), `wallet-${process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'}`); - if (process.env.CONNECTION_PROFILE) { - await walletSetup( - walletPath, - process.env.CONNECTION_PROFILE, - process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1', - ); - } else { - logger.error('No CONNECTION_PROFILE provided in the .env'); - } - // Register all listeners again - const status = await loadEventSubscriptionsFromStorage(process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'); - logger.info(`Load Event Subscriptions Status: ${status}`); + // uses the network name to create a unique wallet path + const walletPath = process.env.WALLET_PATH + ? process.env.WALLET_PATH + : path.join( + process.cwd(), + `wallet-${process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1"}`, + ); + if (process.env.CONNECTION_PROFILE) { + await walletSetup( + walletPath, + process.env.CONNECTION_PROFILE, + process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1", + ); + } else { + logger.error("No CONNECTION_PROFILE provided in the .env"); + } + // Register all listeners again + const status = await loadEventSubscriptionsFromStorage( + process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1", + ); + logger.info(`Load Event Subscriptions Status: ${status}`); }; const monitorService = async () => { - const delayTime: number = parseInt(process.env.MONITOR_SYNC_PERIOD ? process.env.MONITOR_SYNC_PERIOD : '30'); - const networkName = process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'; - const flagEnable = process.env.ENABLE_MONITOR === 'false' ? false : true; - if (flagEnable) { - logger.info("Starting monitor..."); - logger.info(`Monitor sync period: ${delayTime}`); - } else { - logger.info("Monitor disabled."); - } - while (flagEnable) { - await monitorBlockForMissedEvents(networkName); - await delay(delayTime * 1000); - } -} + const delayTime: number = parseInt( + process.env.MONITOR_SYNC_PERIOD ? process.env.MONITOR_SYNC_PERIOD : "30", + ); + const networkName = process.env.NETWORK_NAME + ? process.env.NETWORK_NAME + : "network1"; + const flagEnable = process.env.ENABLE_MONITOR === "false" ? false : true; + if (flagEnable) { + logger.info("Starting monitor..."); + logger.info(`Monitor sync period: ${delayTime}`); + } else { + logger.info("Monitor disabled."); + } + while (flagEnable) { + await monitorBlockForMissedEvents(networkName); + await delay(delayTime * 1000); + } +}; // SERVER: Start the server with the provided url. // TODO: We should have credentials locally to ensure that the driver can only communicate with the local relay. -if (process.env.DRIVER_TLS === 'true') { - if (!(process.env.DRIVER_TLS_CERT_PATH && fs.existsSync(process.env.DRIVER_TLS_CERT_PATH) && - (process.env.DRIVER_TLS_KEY_PATH && fs.existsSync(process.env.DRIVER_TLS_KEY_PATH)))) { - throw new Error("Missing or invalid Driver TLS credentials"); - } - const keyCertPair = { - cert_chain: fs.readFileSync(process.env.DRIVER_TLS_CERT_PATH), - private_key: fs.readFileSync(process.env.DRIVER_TLS_KEY_PATH) - }; - server.bindAsync(`${process.env.DRIVER_ENDPOINT}`, ServerCredentials.createSsl(null, [ keyCertPair ], false), (cb) => { - configSetup().then(() => { - logger.info('Starting server with TLS'); - server.start(); - monitorService(); - }); - }); +if (process.env.DRIVER_TLS === "true") { + if ( + !( + process.env.DRIVER_TLS_CERT_PATH && + fs.existsSync(process.env.DRIVER_TLS_CERT_PATH) && + process.env.DRIVER_TLS_KEY_PATH && + fs.existsSync(process.env.DRIVER_TLS_KEY_PATH) + ) + ) { + throw new Error("Missing or invalid Driver TLS credentials"); + } + const keyCertPair = { + cert_chain: fs.readFileSync(process.env.DRIVER_TLS_CERT_PATH), + private_key: fs.readFileSync(process.env.DRIVER_TLS_KEY_PATH), + }; + server.bindAsync( + `${process.env.DRIVER_ENDPOINT}`, + ServerCredentials.createSsl(null, [keyCertPair], false), + (cb) => { + configSetup().then(() => { + logger.info("Starting server with TLS"); + server.start(); + monitorService(); + }); + }, + ); } else { - server.bindAsync(`${process.env.DRIVER_ENDPOINT}`, ServerCredentials.createInsecure(), (cb) => { - configSetup().then(() => { - logger.info('Starting server without TLS'); - server.start(); - monitorService(); - }); - }); + server.bindAsync( + `${process.env.DRIVER_ENDPOINT}`, + ServerCredentials.createInsecure(), + (cb) => { + configSetup().then(() => { + logger.info("Starting server without TLS"); + server.start(); + monitorService(); + }); + }, + ); } diff --git a/weaver/core/drivers/fabric-driver/server/tests.ts b/weaver/core/drivers/fabric-driver/server/tests.ts index a73b1fea72..42fde47f44 100644 --- a/weaver/core/drivers/fabric-driver/server/tests.ts +++ b/weaver/core/drivers/fabric-driver/server/tests.ts @@ -5,121 +5,136 @@ */ import eventsPb from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; -import queryPb from '@hyperledger/cacti-weaver-protos-js/common/query_pb'; -import { addEventSubscription, deleteEventSubscription, lookupEventSubscriptions } from "./events" -import { LevelDBConnector, DBConnector, DBNotOpenError, DBKeyNotFoundError, DBLockedError } from "./dbConnector" -import logger from './logger'; +import queryPb from "@hyperledger/cacti-weaver-protos-js/common/query_pb"; +import { + addEventSubscription, + deleteEventSubscription, + lookupEventSubscriptions, +} from "./events"; +import { + LevelDBConnector, + DBConnector, + DBNotOpenError, + DBKeyNotFoundError, + DBLockedError, +} from "./dbConnector"; +import logger from "./logger"; // test the LevelDB basic operations -async function dbConnectionTest( -): Promise { - logger.info(`Start testing LevelDBConnector()`) - let db: DBConnector; +async function dbConnectionTest(): Promise { + logger.info(`Start testing LevelDBConnector()`); + let db: DBConnector; + try { + // Create connection to a database + db = new LevelDBConnector(""); + + const key: string = "key"; + let value: string = "insert"; + + // Add the entry to the database + await db.insert(key, value); + + // Fetch the value of the key + value = await db.read(key); + logger.info(`obtained : <${key}, ${value}>`); + + // Close the database connection + await db.close(); + + // Try to update the key before opening the database connection try { - // Create connection to a database - db = new LevelDBConnector(""); - - const key: string = 'key'; - var value: string = 'insert'; - - // Add the entry to the database - await db.insert(key, value); - - // Fetch the value of the key - value = await db.read(key); - logger.info(`obtained : <${key}, ${value}>`); - - // Close the database connection - await db.close(); - - // Try to update the key before opening the database connection - try { - value = 'update'; - await db.update(key, value); - } catch (error: any) { - const errorString: string = `${error.toString()}`; - if (error instanceof DBNotOpenError) { - logger.info(`test success for DBNotOpenError`); - // open the database connection - await db.open(); - // try to update again the key - await db.update(key, value); - } else { - logger.error(`re-throwing the error: ${errorString}`); - db.close(); - throw new Error(error); - } - } - - // Delete the key - await db.delete(key); - - // Try to read key that is already deleted - try { - await db.read(key); - } catch (error: any) { - const errorString: string = `${error.toString()}`; - if (error instanceof DBKeyNotFoundError) { - logger.info(`test success for DBKeyNotFoundError`); - } else { - logger.error(`re-throwing the error: ${errorString}`); - db.close(); - throw new Error(error); - } - } - - // Try to open another connection which should fail - try { - let db2 = new LevelDBConnector(""); - await db2.open(); - } catch (error: any) { - const errorString: string = `${error.toString()}`; - if (error instanceof DBLockedError) { - logger.info(`test success for DBLockedError`); - } else { - logger.error(`re-throwing the error: ${errorString}`); - throw new Error(error); - } - } - - await db.close(); - } catch (error) { - logger.error(`Failed testing LevelDBConnector, with error: ${error.toString()}`); + value = "update"; + await db.update(key, value); + } catch (error: any) { + const errorString: string = `${error.toString()}`; + if (error instanceof DBNotOpenError) { + logger.info(`test success for DBNotOpenError`); + // open the database connection + await db.open(); + // try to update again the key + await db.update(key, value); + } else { + logger.error(`re-throwing the error: ${errorString}`); db.close(); - return false; + throw new Error(error); + } } - logger.info(`End testing LevelDBConnector()`); - return true; + // Delete the key + await db.delete(key); + + // Try to read key that is already deleted + try { + await db.read(key); + } catch (error: any) { + const errorString: string = `${error.toString()}`; + if (error instanceof DBKeyNotFoundError) { + logger.info(`test success for DBKeyNotFoundError`); + } else { + logger.error(`re-throwing the error: ${errorString}`); + db.close(); + throw new Error(error); + } + } + + // Try to open another connection which should fail + try { + const db2 = new LevelDBConnector(""); + await db2.open(); + } catch (error: any) { + const errorString: string = `${error.toString()}`; + if (error instanceof DBLockedError) { + logger.info(`test success for DBLockedError`); + } else { + logger.error(`re-throwing the error: ${errorString}`); + throw new Error(error); + } + } + + await db.close(); + } catch (error) { + logger.error( + `Failed testing LevelDBConnector, with error: ${error.toString()}`, + ); + db.close(); + return false; + } + + logger.info(`End testing LevelDBConnector()`); + return true; } // test the event subscription operations: subscribeEvent, listEvents, deleteEvent async function eventSubscriptionTest( - eventSub: eventsPb.EventSubscription + eventSub: eventsPb.EventSubscription, ): Promise { - logger.info(`Start eventSubscriptionTest()`); - - try { - var eventMatcher: eventsPb.EventMatcher = eventSub.getEventMatcher()!; - await addEventSubscription(eventSub); - var subscriptions: Array = await lookupEventSubscriptions(eventMatcher) as Array; - - for (const subscription of subscriptions) { - if (subscription.getRequestId() == eventSub.getQuery()!.getRequestId()) { - await deleteEventSubscription(eventMatcher, subscription.getRequestId()); - break; - } - } - } catch (error) { - logger.error(`Failed testing event subscription operations, with error: ${error.toString()}`); - return false; + logger.info(`Start eventSubscriptionTest()`); + + try { + const eventMatcher: eventsPb.EventMatcher = eventSub.getEventMatcher()!; + await addEventSubscription(eventSub); + const subscriptions: Array = (await lookupEventSubscriptions( + eventMatcher, + )) as Array; + + for (const subscription of subscriptions) { + if (subscription.getRequestId() == eventSub.getQuery()!.getRequestId()) { + await deleteEventSubscription( + eventMatcher, + subscription.getRequestId(), + ); + break; + } } - - logger.info(`End eventSubscriptionTest()`); - return true; + } catch (error) { + logger.error( + `Failed testing event subscription operations, with error: ${error.toString()}`, + ); + return false; + } + + logger.info(`End eventSubscriptionTest()`); + return true; } -export { - dbConnectionTest, - eventSubscriptionTest -} \ No newline at end of file +export { dbConnectionTest, eventSubscriptionTest }; diff --git a/weaver/core/drivers/fabric-driver/server/utils.ts b/weaver/core/drivers/fabric-driver/server/utils.ts index 8030bb2b9c..25c14203a5 100644 --- a/weaver/core/drivers/fabric-driver/server/utils.ts +++ b/weaver/core/drivers/fabric-driver/server/utils.ts @@ -4,152 +4,186 @@ * SPDX-License-Identifier: Apache-2.0 */ -import fs from 'fs'; -import { credentials } from '@grpc/grpc-js'; -import datatransfer_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/datatransfer_grpc_pb'; -import events_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb'; -import logger from './logger'; +import fs from "fs"; +import { credentials } from "@grpc/grpc-js"; +import datatransfer_grpc_pb from "@hyperledger/cacti-weaver-protos-js/relay/datatransfer_grpc_pb"; +import events_grpc_pb from "@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb"; +import logger from "./logger"; function checkIfArraysAreEqual(x: Array, y: Array): boolean { - if (x == y) { - return true; - } else if (x == null || y == null || (x.length != y.length)) { + if (x == y) { + return true; + } else if (x == null || y == null || x.length != y.length) { + return false; + } else { + // check if all elements of x are present in y + for (const element of x) { + const index = y.indexOf(element); + if (index == -1) { return false; - } else { - // check if all elements of x are present in y - for (const element of x) { - const index = y.indexOf(element); - if (index == -1) { - return false; - } else { - y.splice(index, 1); - } - } - - // return false if y has additional elements not in x - if (y.length != 0) { - return false; - } + } else { + y.splice(index, 1); + } } - return true; + // return false if y has additional elements not in x + if (y.length != 0) { + return false; + } + } + + return true; } // handle callback function relayCallback(err: any, response: any) { - if (response) { - logger.info(`Relay Callback Response: ${JSON.stringify(response.toObject())}`); - } else if (err) { - logger.error(`Relay Callback Error: ${err}`); - } + if (response) { + logger.info( + `Relay Callback Response: ${JSON.stringify(response.toObject())}`, + ); + } else if (err) { + logger.error(`Relay Callback Error: ${err}`); + } } // A better way to handle errors for promises function handlePromise(promise: Promise): Promise<[T?, Error?]> { - const result: Promise<[T?, Error?]> = promise - .then(data => { - const response: [T?, Error?] = [data, undefined] - return response - }) - .catch(error => Promise.resolve([undefined, error])) - return result + const result: Promise<[T?, Error?]> = promise + .then((data) => { + const response: [T?, Error?] = [data, undefined]; + return response; + }) + .catch((error) => Promise.resolve([undefined, error])); + return result; } function getRelayClientForQueryResponse() { - let client: datatransfer_grpc_pb.DataTransferClient; - if (process.env.RELAY_TLS === 'true') { - if (!process.env.RELAY_TLSCA_CERT_PATH || process.env.RELAY_TLSCA_CERT_PATH == "") { - client = new datatransfer_grpc_pb.DataTransferClient( - process.env.RELAY_ENDPOINT, - credentials.createSsl() - ); - } else { - if (!(process.env.RELAY_TLSCA_CERT_PATH && fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH))) { - throw new Error("Missing or invalid RELAY_TLSCA_CERT_PATH: " + process.env.RELAY_TLSCA_CERT_PATH); - } - const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); - client = new datatransfer_grpc_pb.DataTransferClient( - process.env.RELAY_ENDPOINT, - credentials.createSsl(rootCert) - ); - } + let client: datatransfer_grpc_pb.DataTransferClient; + if (process.env.RELAY_TLS === "true") { + if ( + !process.env.RELAY_TLSCA_CERT_PATH || + process.env.RELAY_TLSCA_CERT_PATH == "" + ) { + client = new datatransfer_grpc_pb.DataTransferClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(), + ); } else { - client = new datatransfer_grpc_pb.DataTransferClient( - process.env.RELAY_ENDPOINT, - credentials.createInsecure() + if ( + !( + process.env.RELAY_TLSCA_CERT_PATH && + fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH) + ) + ) { + throw new Error( + "Missing or invalid RELAY_TLSCA_CERT_PATH: " + + process.env.RELAY_TLSCA_CERT_PATH, ); + } + const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); + client = new datatransfer_grpc_pb.DataTransferClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(rootCert), + ); } - return client; + } else { + client = new datatransfer_grpc_pb.DataTransferClient( + process.env.RELAY_ENDPOINT, + credentials.createInsecure(), + ); + } + return client; } - // If the events_grpc_pb.EventSubscribeClient() failes, then it throws an error which will be caught by the caller function getRelayClientForEventSubscription() { - let client: events_grpc_pb.EventSubscribeClient; + let client: events_grpc_pb.EventSubscribeClient; - if (process.env.RELAY_TLS === 'true') { - if (!process.env.RELAY_TLSCA_CERT_PATH || process.env.RELAY_TLSCA_CERT_PATH == "") { - client = new events_grpc_pb.EventSubscribeClient( - process.env.RELAY_ENDPOINT, - credentials.createSsl() - ); - } else { - if (!(process.env.RELAY_TLSCA_CERT_PATH && fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH))) { - throw new Error("Missing or invalid RELAY_TLSCA_CERT_PATH: " + process.env.RELAY_TLSCA_CERT_PATH); - } - const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); - client = new events_grpc_pb.EventSubscribeClient( - process.env.RELAY_ENDPOINT, - credentials.createSsl(rootCert) - ); - } + if (process.env.RELAY_TLS === "true") { + if ( + !process.env.RELAY_TLSCA_CERT_PATH || + process.env.RELAY_TLSCA_CERT_PATH == "" + ) { + client = new events_grpc_pb.EventSubscribeClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(), + ); } else { - client = new events_grpc_pb.EventSubscribeClient( - process.env.RELAY_ENDPOINT, - credentials.createInsecure() + if ( + !( + process.env.RELAY_TLSCA_CERT_PATH && + fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH) + ) + ) { + throw new Error( + "Missing or invalid RELAY_TLSCA_CERT_PATH: " + + process.env.RELAY_TLSCA_CERT_PATH, ); + } + const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); + client = new events_grpc_pb.EventSubscribeClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(rootCert), + ); } + } else { + client = new events_grpc_pb.EventSubscribeClient( + process.env.RELAY_ENDPOINT, + credentials.createInsecure(), + ); + } - return client; + return client; } function getRelayClientForEventPublish() { - let client: events_grpc_pb.EventPublishClient; - if (process.env.RELAY_TLS === 'true') { - if (!process.env.RELAY_TLSCA_CERT_PATH || process.env.RELAY_TLSCA_CERT_PATH == "") { - client = new events_grpc_pb.EventPublishClient( - process.env.RELAY_ENDPOINT, - credentials.createSsl() - ); - } else { - if (!(process.env.RELAY_TLSCA_CERT_PATH && fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH))) { - throw new Error("Missing or invalid RELAY_TLSCA_CERT_PATH: " + process.env.RELAY_TLSCA_CERT_PATH); - } - const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); - client = new events_grpc_pb.EventPublishClient( - process.env.RELAY_ENDPOINT, - credentials.createSsl(rootCert) - ); - } + let client: events_grpc_pb.EventPublishClient; + if (process.env.RELAY_TLS === "true") { + if ( + !process.env.RELAY_TLSCA_CERT_PATH || + process.env.RELAY_TLSCA_CERT_PATH == "" + ) { + client = new events_grpc_pb.EventPublishClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(), + ); } else { - client = new events_grpc_pb.EventPublishClient( - process.env.RELAY_ENDPOINT, - credentials.createInsecure() + if ( + !( + process.env.RELAY_TLSCA_CERT_PATH && + fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH) + ) + ) { + throw new Error( + "Missing or invalid RELAY_TLSCA_CERT_PATH: " + + process.env.RELAY_TLSCA_CERT_PATH, ); + } + const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); + client = new events_grpc_pb.EventPublishClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(rootCert), + ); } - return client; + } else { + client = new events_grpc_pb.EventPublishClient( + process.env.RELAY_ENDPOINT, + credentials.createInsecure(), + ); + } + return client; } async function delay(ms: number) { - await new Promise(f => setTimeout(f, ms)); + await new Promise((f) => setTimeout(f, ms)); } export { - checkIfArraysAreEqual, - handlePromise, - relayCallback, - getRelayClientForQueryResponse, - getRelayClientForEventSubscription, - getRelayClientForEventPublish, - delay -} + checkIfArraysAreEqual, + handlePromise, + relayCallback, + getRelayClientForQueryResponse, + getRelayClientForEventSubscription, + getRelayClientForEventPublish, + delay, +}; diff --git a/weaver/core/drivers/fabric-driver/server/walletSetup.ts b/weaver/core/drivers/fabric-driver/server/walletSetup.ts index ead3ba4092..aeba3ac1cb 100644 --- a/weaver/core/drivers/fabric-driver/server/walletSetup.ts +++ b/weaver/core/drivers/fabric-driver/server/walletSetup.ts @@ -4,128 +4,150 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Wallets } from 'fabric-network'; -import FabricCAServices from 'fabric-ca-client'; -import { handlePromise } from './utils'; -import { InteroperableHelper } from '@hyperledger/cacti-weaver-sdk-fabric' -import * as path from 'path'; -import * as fs from 'fs'; -import logger from './logger'; +import { Wallets } from "fabric-network"; +import FabricCAServices from "fabric-ca-client"; +import { handlePromise } from "./utils"; +import { InteroperableHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; +import * as path from "path"; +import * as fs from "fs"; +import logger from "./logger"; const getConfig = () => { - const config = JSON.parse( - fs - .readFileSync( - path.resolve(__dirname, process.env.DRIVER_CONFIG ? process.env.DRIVER_CONFIG : '../config.json'), - ) - .toString(), - ); - return config; + const config = JSON.parse( + fs + .readFileSync( + path.resolve( + __dirname, + process.env.DRIVER_CONFIG + ? process.env.DRIVER_CONFIG + : "../config.json", + ), + ) + .toString(), + ); + return config; }; -const walletSetup = async (walletPath: string, conn_profile_path: string, networkName: string): Promise => { - const ccpPath = conn_profile_path - ? path.resolve(__dirname, conn_profile_path) - : path.resolve(__dirname, '../', 'connection_profile.json'); - if (!fs.existsSync(ccpPath)) { - logger.error(`File does not exist at path: ${ccpPath}`); - logger.error( - 'Please check the CONNECTION_PROFILE environemnt variable in your .env. The path will default to the root of the fabric-driver folder if not supplied', - ); - return; - } - const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8')); - const config = getConfig(); - // Create a new CA client for interacting with the CA. - const org = ccp.client["organization"]; - logger.debug(`Org ${org}`); - const caName = ccp.organizations[org]["certificateAuthorities"][0]; - logger.debug(`CA Name ${caName}`); - const caURL = config.caUrl ? config.caUrl : ccp.certificateAuthorities[caName].url; - logger.debug(`CA URL ${caURL}`); - const ca = new FabricCAServices(caURL); - const ident = ca.newIdentityService(); +const walletSetup = async ( + walletPath: string, + conn_profile_path: string, + networkName: string, +): Promise => { + const ccpPath = conn_profile_path + ? path.resolve(__dirname, conn_profile_path) + : path.resolve(__dirname, "../", "connection_profile.json"); + if (!fs.existsSync(ccpPath)) { + logger.error(`File does not exist at path: ${ccpPath}`); + logger.error( + "Please check the CONNECTION_PROFILE environemnt variable in your .env. The path will default to the root of the fabric-driver folder if not supplied", + ); + return; + } + const ccp = JSON.parse(fs.readFileSync(ccpPath, "utf8")); + const config = getConfig(); + // Create a new CA client for interacting with the CA. + const org = ccp.client["organization"]; + logger.debug(`Org ${org}`); + const caName = ccp.organizations[org]["certificateAuthorities"][0]; + logger.debug(`CA Name ${caName}`); + const caURL = config.caUrl + ? config.caUrl + : ccp.certificateAuthorities[caName].url; + logger.debug(`CA URL ${caURL}`); + const ca = new FabricCAServices(caURL); + const ident = ca.newIdentityService(); - const wallet = await Wallets.newFileSystemWallet(walletPath); - const adminName = config.admin.name; - const adminSecret = config.admin.secret; - // build a user object for authenticating with the CA // Check to see if we've already enrolled the admin user. - let adminIdentity = await wallet.get(adminName); + const wallet = await Wallets.newFileSystemWallet(walletPath); + const adminName = config.admin.name; + const adminSecret = config.admin.secret; + // build a user object for authenticating with the CA // Check to see if we've already enrolled the admin user. + let adminIdentity = await wallet.get(adminName); - if (adminIdentity) { - logger.info('An identity for the admin user "admin" already exists in the wallet'); + if (adminIdentity) { + logger.info( + 'An identity for the admin user "admin" already exists in the wallet', + ); + } else { + // Enroll the admin user, and import the new identity into the wallet. + logger.debug(`Enrolling Admin... ${adminName}, ${adminSecret}`); + const enrollment = await ca.enroll({ + enrollmentID: adminName, + enrollmentSecret: adminSecret, + }); + const x509Identity = { + credentials: { + certificate: enrollment.certificate, + privateKey: enrollment.key.toBytes(), + }, + mspId: config.mspId, + type: "X.509", + }; + await wallet.put(adminName, x509Identity); + adminIdentity = await wallet.get(adminName); + } + if (adminIdentity) { + logger.info(`Creating ${config.relay.name} Identity`); + const provider = wallet + .getProviderRegistry() + .getProvider(adminIdentity.type); + const adminUser = await provider.getUserContext(adminIdentity, adminName); + const identity = await wallet.get(config.relay.name); + if (!identity) { + const secret = await ca.register( + { + affiliation: config.relay.affiliation, + enrollmentID: config.relay.name, + role: config.relay.role, + attrs: config.relay.attrs, + }, + adminUser, + ); + const enrollment = await ca.enroll({ + enrollmentID: config.relay.name, + enrollmentSecret: secret, + }); + const x509Identity = { + credentials: { + certificate: enrollment.certificate, + privateKey: enrollment.key.toBytes(), + }, + mspId: config.mspId, + type: "X.509", + }; + await wallet.put(config.relay.name, x509Identity); + logger.info(`${config.relay.name} Identity Created`); } else { - // Enroll the admin user, and import the new identity into the wallet. - logger.debug(`Enrolling Admin... ${adminName}, ${adminSecret}`); - const enrollment = await ca.enroll({ - enrollmentID: adminName, - enrollmentSecret: adminSecret, - }); - const x509Identity = { - credentials: { - certificate: enrollment.certificate, - privateKey: enrollment.key.toBytes(), - }, - mspId: config.mspId, - type: 'X.509', - }; - await wallet.put(adminName, x509Identity); - adminIdentity = await wallet.get(adminName); + logger.info(`${config.relay.name} Identity Already exists`); } - if (adminIdentity) { - logger.info(`Creating ${config.relay.name} Identity`); - const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type); - const adminUser = await provider.getUserContext(adminIdentity, adminName); - const identity = await wallet.get(config.relay.name); - if (!identity) { - const secret = await ca.register( - { - affiliation: config.relay.affiliation, - enrollmentID: config.relay.name, - role: config.relay.role, - attrs: config.relay.attrs, - }, - adminUser, - ); - const enrollment = await ca.enroll({ - enrollmentID: config.relay.name, - enrollmentSecret: secret, - }); - const x509Identity = { - credentials: { - certificate: enrollment.certificate, - privateKey: enrollment.key.toBytes(), - }, - mspId: config.mspId, - type: 'X.509', - }; - await wallet.put(config.relay.name, x509Identity); - logger.info(`${config.relay.name} Identity Created`); - } else { - logger.info(`${config.relay.name} Identity Already exists`); - } - return wallet; - } else { - logger.error('Admin was not registered'); - throw new Error('Admin was not registered'); - } + return wallet; + } else { + logger.error("Admin was not registered"); + throw new Error("Admin was not registered"); + } }; const getDriverKeyCert = async (): Promise => { + const walletPath = process.env.WALLET_PATH + ? process.env.WALLET_PATH + : path.join( + process.cwd(), + `wallet-${process.env.NETWORK_NAME ? process.env.NETWORK_NAME : "network1"}`, + ); + const config = getConfig(); + const wallet = await Wallets.newFileSystemWallet(walletPath); + logger.info(`Wallet path: ${walletPath}, relay id: ${config.relay.name}`); - const walletPath = process.env.WALLET_PATH ? process.env.WALLET_PATH : path.join(process.cwd(), `wallet-${process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1'}`); - const config = getConfig(); - const wallet = await Wallets.newFileSystemWallet(walletPath); - logger.info(`Wallet path: ${walletPath}, relay id: ${config.relay.name}`); - - const [keyCert, keyCertError] = await handlePromise( - InteroperableHelper.getKeyAndCertForRemoteRequestbyUserName(wallet, config.relay.name) - ) - if (keyCertError) { - throw new Error(`Error getting key and cert ${keyCertError}`) - } - return keyCert; -} + const [keyCert, keyCertError] = await handlePromise( + InteroperableHelper.getKeyAndCertForRemoteRequestbyUserName( + wallet, + config.relay.name, + ), + ); + if (keyCertError) { + throw new Error(`Error getting key and cert ${keyCertError}`); + } + return keyCert; +}; export { walletSetup, getConfig, getDriverKeyCert }; diff --git a/weaver/core/identity-management/iin-agent/package-local.json b/weaver/core/identity-management/iin-agent/package-local.json index 4d0d8b00e4..89c1753942 100644 --- a/weaver/core/identity-management/iin-agent/package-local.json +++ b/weaver/core/identity-management/iin-agent/package-local.json @@ -12,7 +12,6 @@ "scripts": { "build": "npm run tsc", "dev": "nodemon out/server.js", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "start": "node out/server.js", "test": "nyc mocha -r ts-node/register --exclude 'test/data/**/*.js' --recursive -t 10000", "tsc": "tsc", @@ -23,11 +22,7 @@ "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "file:./protos-js", "@hyperledger/cacti-weaver-sdk-fabric": "file:./cacti-weaver-sdk-fabric", - "@typescript-eslint/eslint-plugin": "3.10.1", - "@typescript-eslint/parser": "3.10.1", "dotenv": "8.6.0", - "eslint-config-prettier": "6.15.0", - "eslint-plugin-prettier": "3.4.1", "fabric-ca-client": "2.2.20", "fabric-common": "2.2.20", "fabric-network": "2.2.20", diff --git a/weaver/core/identity-management/iin-agent/package.json b/weaver/core/identity-management/iin-agent/package.json index 523eefd681..1c979cb51e 100644 --- a/weaver/core/identity-management/iin-agent/package.json +++ b/weaver/core/identity-management/iin-agent/package.json @@ -12,7 +12,6 @@ "scripts": { "build": "npm run tsc", "dev": "nodemon out/server.js", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "start": "node out/server.js", "test": "nyc mocha -r ts-node/register --exclude 'test/data/**/*.js' --recursive -t 10000", "tsc": "tsc", @@ -23,11 +22,7 @@ "@grpc/grpc-js": "1.9.5", "@hyperledger/cacti-weaver-protos-js": "2.0.0-alpha.2", "@hyperledger/cacti-weaver-sdk-fabric": "2.0.0-alpha.2", - "@typescript-eslint/eslint-plugin": "3.10.1", - "@typescript-eslint/parser": "3.10.1", "dotenv": "8.6.0", - "eslint-config-prettier": "6.15.0", - "eslint-plugin-prettier": "5.0.0", "fabric-ca-client": "2.2.20", "fabric-common": "2.2.20", "fabric-network": "2.2.20", diff --git a/weaver/core/identity-management/iin-agent/src/common/ledgerBase.ts b/weaver/core/identity-management/iin-agent/src/common/ledgerBase.ts index db216009a6..4341df96c8 100644 --- a/weaver/core/identity-management/iin-agent/src/common/ledgerBase.ts +++ b/weaver/core/identity-management/iin-agent/src/common/ledgerBase.ts @@ -4,59 +4,66 @@ * SPDX-License-Identifier: Apache-2.0 */ -import iin_agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; +import iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; export class LedgerBase { - ledgerId: string; // Unique ID of a ledger in which the Weaver interoperation module is installed - memberId: string; // Unique ID of Member to which this IIN Agent belongs - contractId: string; // Unique ID of the contract corresponding to the Weaver interoperation module installed in 'ledgerId' - - constructor(ledgerId: string, memberId: string, contractId: string) { - this.ledgerId = ledgerId; - this.memberId = memberId; - this.contractId = contractId; - } - - /* To initialise ledgerBase - * E.g. for Fabric: Setup a user (with wallet and one or more identities) with contract invocation credentials - */ - async init() { - } - - getLedgerID(): string { - return this.ledgerId; - } - - getMemberID(): string { - return this.memberId; - } - - getContractID(): string { - return this.contractId; - } - - // Collect security domain membership info - async getAttestedMembership(securityDomain: string, nonce: string): Promise { - return new iin_agent_pb.AttestedMembership(); - } - - // Collect security domain membership info - async counterAttestMembership(attestedMembershipSetSerialized64: string, securityDomain: string, nonce: string): Promise { - return new iin_agent_pb.CounterAttestedMembership(); - } - - // record Membership - async recordMembershipInLedger(counterAttestedMembership: iin_agent_pb.CounterAttestedMembership): Promise { - return ""; - } - - // Invoke a contract to drive a transaction - // TODO: Add parameters corresponding to the output of a flow among IIN agents - async invokeContract() { - } - - // Query a contract to fetch information from the ledger - async queryContract(): Promise { - return ""; - } + ledgerId: string; // Unique ID of a ledger in which the Weaver interoperation module is installed + memberId: string; // Unique ID of Member to which this IIN Agent belongs + contractId: string; // Unique ID of the contract corresponding to the Weaver interoperation module installed in 'ledgerId' + + constructor(ledgerId: string, memberId: string, contractId: string) { + this.ledgerId = ledgerId; + this.memberId = memberId; + this.contractId = contractId; + } + + /* To initialise ledgerBase + * E.g. for Fabric: Setup a user (with wallet and one or more identities) with contract invocation credentials + */ + async init() {} + + getLedgerID(): string { + return this.ledgerId; + } + + getMemberID(): string { + return this.memberId; + } + + getContractID(): string { + return this.contractId; + } + + // Collect security domain membership info + async getAttestedMembership( + securityDomain: string, + nonce: string, + ): Promise { + return new iin_agent_pb.AttestedMembership(); + } + + // Collect security domain membership info + async counterAttestMembership( + attestedMembershipSetSerialized64: string, + securityDomain: string, + nonce: string, + ): Promise { + return new iin_agent_pb.CounterAttestedMembership(); + } + + // record Membership + async recordMembershipInLedger( + counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, + ): Promise { + return ""; + } + + // Invoke a contract to drive a transaction + // TODO: Add parameters corresponding to the output of a flow among IIN agents + async invokeContract() {} + + // Query a contract to fetch information from the ledger + async queryContract(): Promise { + return ""; + } } diff --git a/weaver/core/identity-management/iin-agent/src/common/utils.ts b/weaver/core/identity-management/iin-agent/src/common/utils.ts index fd9acdccea..a008164b44 100644 --- a/weaver/core/identity-management/iin-agent/src/common/utils.ts +++ b/weaver/core/identity-management/iin-agent/src/common/utils.ts @@ -5,123 +5,154 @@ */ // Other Packages -import * as path from 'path'; -import * as fs from 'fs'; -import { credentials } from '@grpc/grpc-js'; -import crypto from 'crypto'; -const { X509Certificate } = require('crypto'); +import * as path from "path"; +import * as fs from "fs"; +import { credentials } from "@grpc/grpc-js"; +import crypto from "crypto"; +const { X509Certificate } = require("crypto"); // Weaver Packages -import agent_grpc_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_grpc_pb'; -import agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; -import membership_pb from '@hyperledger/cacti-weaver-protos-js/common/membership_pb'; -import { InteroperableHelper } from '@hyperledger/cacti-weaver-sdk-fabric' +import agent_grpc_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_grpc_pb"; +import agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; +import membership_pb from "@hyperledger/cacti-weaver-protos-js/common/membership_pb"; +import { InteroperableHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; // Local modules -import { LedgerBase } from './ledgerBase'; -import { FabricConnector } from '../fabric-ledger/connector'; +import { LedgerBase } from "./ledgerBase"; +import { FabricConnector } from "../fabric-ledger/connector"; // A better way to handle errors for promises export function handlePromise(promise: Promise): Promise<[T?, Error?]> { - const result: Promise<[T?, Error?]> = promise - .then((data) => { - const response: [T?, Error?] = [data, undefined]; - return response; - }) - .catch((error) => Promise.resolve([undefined, error])); - return result; + const result: Promise<[T?, Error?]> = promise + .then((data) => { + const response: [T?, Error?] = [data, undefined]; + return response; + }) + .catch((error) => Promise.resolve([undefined, error])); + return result; } -export function getIINAgentClient(securityDomain: string, participantId: string, securityDomainDNS?: Object): agent_grpc_pb.IINAgentClient { - if (!securityDomainDNS) { - securityDomainDNS = getSecurityDomainDNS(securityDomain); - } - if (!(participantId in securityDomainDNS)) { - throw new Error(`DNS for member: ${participantId} of ${securityDomain} not defined in DNS Config`) - } - const iinAgent = securityDomainDNS[participantId]; - let client: agent_grpc_pb.IINAgentClient; - if (iinAgent.tls === 'true') { - if (!iinAgent.tlsCACertPath || iinAgent.tlsCACertPath == "") { - client = new agent_grpc_pb.IINAgentClient( - iinAgent.endpoint, - credentials.createSsl() - ); - } else { - if (!(iinAgent.tlsCACertPath && fs.existsSync(iinAgent.tlsCACertPath))) { - throw new Error("Missing or invalid IIN Agent's tlsCACertPaths: " + iinAgent.tlsCACertPath); - } - const rootCert = fs.readFileSync(iinAgent.tlsCACertPath); - client = new agent_grpc_pb.IINAgentClient( - iinAgent.endpoint, - credentials.createSsl(rootCert) - ); - } +export function getIINAgentClient( + securityDomain: string, + participantId: string, + securityDomainDNS?: Object, +): agent_grpc_pb.IINAgentClient { + if (!securityDomainDNS) { + securityDomainDNS = getSecurityDomainDNS(securityDomain); + } + if (!(participantId in securityDomainDNS)) { + throw new Error( + `DNS for member: ${participantId} of ${securityDomain} not defined in DNS Config`, + ); + } + const iinAgent = securityDomainDNS[participantId]; + let client: agent_grpc_pb.IINAgentClient; + if (iinAgent.tls === "true") { + if (!iinAgent.tlsCACertPath || iinAgent.tlsCACertPath == "") { + client = new agent_grpc_pb.IINAgentClient( + iinAgent.endpoint, + credentials.createSsl(), + ); } else { - client = new agent_grpc_pb.IINAgentClient( - iinAgent.endpoint, - credentials.createInsecure() + if (!(iinAgent.tlsCACertPath && fs.existsSync(iinAgent.tlsCACertPath))) { + throw new Error( + "Missing or invalid IIN Agent's tlsCACertPaths: " + + iinAgent.tlsCACertPath, ); + } + const rootCert = fs.readFileSync(iinAgent.tlsCACertPath); + client = new agent_grpc_pb.IINAgentClient( + iinAgent.endpoint, + credentials.createSsl(rootCert), + ); } - return client; + } else { + client = new agent_grpc_pb.IINAgentClient( + iinAgent.endpoint, + credentials.createInsecure(), + ); + } + return client; } -export function getLedgerBase(securityDomain: string, memberId: string): LedgerBase { - const ledgerId = getLedgerId(securityDomain); - if(!process.env.DLT_TYPE) { - throw new Error(`Env DLT_TYPE not defined`); - } - const dltType = process.env.DLT_TYPE!.toLowerCase(); - if(dltType == 'fabric') { - const ledgerBase = new FabricConnector(ledgerId, process.env.WEAVER_CONTRACT_ID, securityDomain, process.env.CONFIG_PATH); - return ledgerBase; - } else { - throw new Error(`DLT Type ${process.env.DLT_TYPE} not implemented`); - } +export function getLedgerBase( + securityDomain: string, + memberId: string, +): LedgerBase { + const ledgerId = getLedgerId(securityDomain); + if (!process.env.DLT_TYPE) { + throw new Error(`Env DLT_TYPE not defined`); + } + const dltType = process.env.DLT_TYPE!.toLowerCase(); + if (dltType == "fabric") { + const ledgerBase = new FabricConnector( + ledgerId, + process.env.WEAVER_CONTRACT_ID, + securityDomain, + process.env.CONFIG_PATH, + ); + return ledgerBase; + } else { + throw new Error(`DLT Type ${process.env.DLT_TYPE} not implemented`); + } } export function getLedgerId(securityDomain: string): any { - const secDomConfigPath = process.env.SECURITY_DOMAIN_CONFIG_PATH ? process.env.SECURITY_DOMAIN_CONFIG_PATH : path.resolve(__dirname, "../", "../", "security-domain-config.json"); - if (!fs.existsSync(secDomConfigPath)) { - throw new Error('Security Domain config does not exist at path: ' + secDomConfigPath); - } - const secDomConfig = JSON.parse(fs.readFileSync(secDomConfigPath, 'utf8').toString()); - return secDomConfig[securityDomain]; + const secDomConfigPath = process.env.SECURITY_DOMAIN_CONFIG_PATH + ? process.env.SECURITY_DOMAIN_CONFIG_PATH + : path.resolve(__dirname, "../", "../", "security-domain-config.json"); + if (!fs.existsSync(secDomConfigPath)) { + throw new Error( + "Security Domain config does not exist at path: " + secDomConfigPath, + ); + } + const secDomConfig = JSON.parse( + fs.readFileSync(secDomConfigPath, "utf8").toString(), + ); + return secDomConfig[securityDomain]; } export function getSecurityDomainDNS(securityDomain: string): any { - const dnsConfigPath = process.env.DNS_CONFIG_PATH ? process.env.DNS_CONFIG_PATH : path.resolve(__dirname, "../", "../", "dnsconfig.json"); - if (!fs.existsSync(dnsConfigPath)) { - throw new Error('DNS config does not exist at path: ' + dnsConfigPath); - } - const dnsConfig = JSON.parse(fs.readFileSync(dnsConfigPath, 'utf8').toString()); - return dnsConfig[securityDomain]; + const dnsConfigPath = process.env.DNS_CONFIG_PATH + ? process.env.DNS_CONFIG_PATH + : path.resolve(__dirname, "../", "../", "dnsconfig.json"); + if (!fs.existsSync(dnsConfigPath)) { + throw new Error("DNS config does not exist at path: " + dnsConfigPath); + } + const dnsConfig = JSON.parse( + fs.readFileSync(dnsConfigPath, "utf8").toString(), + ); + return dnsConfig[securityDomain]; } -export function getAllRemoteSecurityDomainDNS(localSecurityDomain: string): any { - const dnsConfigPath = process.env.DNS_CONFIG_PATH ? process.env.DNS_CONFIG_PATH : path.resolve(__dirname, "../", "../", "dnsconfig.json"); - if (!fs.existsSync(dnsConfigPath)) { - throw new Error('DNS config does not exist at path: ' + dnsConfigPath); - } - const dnsConfig = JSON.parse(fs.readFileSync(dnsConfigPath, 'utf8').toString()); - if (localSecurityDomain in dnsConfig) { - delete dnsConfig [localSecurityDomain] - } - return dnsConfig; +export function getAllRemoteSecurityDomainDNS( + localSecurityDomain: string, +): any { + const dnsConfigPath = process.env.DNS_CONFIG_PATH + ? process.env.DNS_CONFIG_PATH + : path.resolve(__dirname, "../", "../", "dnsconfig.json"); + if (!fs.existsSync(dnsConfigPath)) { + throw new Error("DNS config does not exist at path: " + dnsConfigPath); + } + const dnsConfig = JSON.parse( + fs.readFileSync(dnsConfigPath, "utf8").toString(), + ); + if (localSecurityDomain in dnsConfig) { + delete dnsConfig[localSecurityDomain]; + } + return dnsConfig; } - - export function defaultCallback(err: any, response: any) { - if (response) { - console.log(`IIN Agent Response: ${JSON.stringify(response.toObject())}`); - } else if (err) { - console.log(`IIN Agent Error: ${JSON.stringify(err)}`); - } + if (response) { + console.log(`IIN Agent Response: ${JSON.stringify(response.toObject())}`); + } else if (err) { + console.log(`IIN Agent Error: ${JSON.stringify(err)}`); + } } export async function delay(ms: number) { - await new Promise(f => setTimeout(f, ms)); + await new Promise((f) => setTimeout(f, ms)); } /** @@ -129,10 +160,10 @@ export async function delay(ms: number) { * message: string * privateKey: pem string * returns: signature in base64 string -**/ + **/ export function signMessage(message, privateKey, algorithm: string = "SHA256") { - return InteroperableHelper.signMessage(message, privateKey, algorithm); -}; + return InteroperableHelper.signMessage(message, privateKey, algorithm); +} /** * Verifies a signature over message using SHA256 * message: string @@ -140,123 +171,171 @@ export function signMessage(message, privateKey, algorithm: string = "SHA256") { * signature: base64 string * returns: True/False **/ -export function verifySignature(message, certificate, signature, algorithm: string = "SHA256") { - return InteroperableHelper.verifySignature(message, certificate, signature, algorithm); -}; +export function verifySignature( + message, + certificate, + signature, + algorithm: string = "SHA256", +) { + return InteroperableHelper.verifySignature( + message, + certificate, + signature, + algorithm, + ); +} -export function deserializeMembership64(dataSerialized64: string): membership_pb.Membership { - return membership_pb.Membership.deserializeBinary(Uint8Array.from(Buffer.from(dataSerialized64, 'base64'))); +export function deserializeMembership64( + dataSerialized64: string, +): membership_pb.Membership { + return membership_pb.Membership.deserializeBinary( + Uint8Array.from(Buffer.from(dataSerialized64, "base64")), + ); } -export function deserializeAttestedMembershipSet64(dataSerialized64: string): agent_pb.CounterAttestedMembership.AttestedMembershipSet { - return agent_pb.CounterAttestedMembership.AttestedMembershipSet.deserializeBinary(Uint8Array.from(Buffer.from(dataSerialized64, 'base64'))); +export function deserializeAttestedMembershipSet64( + dataSerialized64: string, +): agent_pb.CounterAttestedMembership.AttestedMembershipSet { + return agent_pb.CounterAttestedMembership.AttestedMembershipSet.deserializeBinary( + Uint8Array.from(Buffer.from(dataSerialized64, "base64")), + ); } -export function validateAttestedMembership(membershipSerialized64: string, nonce: string, attestation: agent_pb.Attestation) { - const membership = deserializeMembership64(membershipSerialized64); - const nonce_attestation = attestation.getNonce(); - if (nonce !== nonce_attestation) { - console.error(`Error: Nonce doesn't match. Expected: ${nonce}, received: ${nonce_attestation}`); - return false; - } - const signature = attestation.getSignature(); - const certificate = attestation.getCertificate(); - const message = membershipSerialized64 + nonce; - if (!verifySignature(message, certificate, signature)) { - console.error(`Error: Fail to verify signature on membership`); - return false; - } - return verifyMemberInMembership(membership, attestation); +export function validateAttestedMembership( + membershipSerialized64: string, + nonce: string, + attestation: agent_pb.Attestation, +) { + const membership = deserializeMembership64(membershipSerialized64); + const nonce_attestation = attestation.getNonce(); + if (nonce !== nonce_attestation) { + console.error( + `Error: Nonce doesn't match. Expected: ${nonce}, received: ${nonce_attestation}`, + ); + return false; + } + const signature = attestation.getSignature(); + const certificate = attestation.getCertificate(); + const message = membershipSerialized64 + nonce; + if (!verifySignature(message, certificate, signature)) { + console.error(`Error: Fail to verify signature on membership`); + return false; + } + return verifyMemberInMembership(membership, attestation); } -export function verifyMemberInMembership(membership: membership_pb.Membership, attestation: agent_pb.Attestation) { - const unitIdentity = attestation.getUnitIdentity(); - const securityDomain = unitIdentity.getSecurityDomain(); - if (securityDomain !== membership.getSecuritydomain()) { - console.error(`Error: Security domain of attestor doesn't match. Expected: ${membership.getSecuritydomain()}, Attestor's: ${securityDomain}`); +export function verifyMemberInMembership( + membership: membership_pb.Membership, + attestation: agent_pb.Attestation, +) { + const unitIdentity = attestation.getUnitIdentity(); + const securityDomain = unitIdentity.getSecurityDomain(); + if (securityDomain !== membership.getSecuritydomain()) { + console.error( + `Error: Security domain of attestor doesn't match. Expected: ${membership.getSecuritydomain()}, Attestor's: ${securityDomain}`, + ); + return false; + } + const memberId = unitIdentity.getMemberId(); + const certificate = attestation.getCertificate(); + const member = membership.getMembersMap().get(memberId); + let isSignerRoot = false; + let leafCACertPEM = ""; + if (member.getType() === "ca") { + leafCACertPEM = member.getValue(); + isSignerRoot = true; + } else if (member.getType() == "certificate") { + const chain = member.getChainList(); + let parentCert = chain[0]; + for (let i = 1; i < chain.length; i++) { + const caCert = chain[i]; + isSignerRoot = i == 1; + if (!validateCertificateUsingCA(caCert, parentCert, isSignerRoot)) { + console.error("Certificate link invalid"); return false; + } + parentCert = caCert; } - const memberId = unitIdentity.getMemberId(); - const certificate = attestation.getCertificate() - const member = membership.getMembersMap().get(memberId); - let isSignerRoot = false; - let leafCACertPEM = ""; - if (member.getType() === "ca") { - leafCACertPEM = member.getValue(); - isSignerRoot = true; - } else if (member.getType() == "certificate") { - const chain = member.getChainList(); - let parentCert = chain[0]; - for (let i=1; i= validFrom); + const validFrom = new Date(x509Cert.validFrom).valueOf(); + const validTo = new Date(x509Cert.validTo).valueOf(); + const currTime = Date.now(); + return currTime <= validTo && currTime >= validFrom; } -export function generateErrorAttestation(errorMsg, securityDomain, memberId, nonce) { - const unitId = new agent_pb.SecurityDomainMemberIdentity(); - unitId.setSecurityDomain(securityDomain); - unitId.setMemberId(memberId); - - const attestation = new agent_pb.Attestation(); - attestation.setUnitIdentity(unitId); - attestation.setNonce(nonce); - attestation.setTimestamp(Date.now()); - - const errorAttestedMembership = new agent_pb.AttestedMembership(); - errorAttestedMembership.setError(errorMsg); - errorAttestedMembership.setAttestation(attestation); - return errorAttestedMembership; +export function generateErrorAttestation( + errorMsg, + securityDomain, + memberId, + nonce, +) { + const unitId = new agent_pb.SecurityDomainMemberIdentity(); + unitId.setSecurityDomain(securityDomain); + unitId.setMemberId(memberId); + + const attestation = new agent_pb.Attestation(); + attestation.setUnitIdentity(unitId); + attestation.setNonce(nonce); + attestation.setTimestamp(Date.now()); + + const errorAttestedMembership = new agent_pb.AttestedMembership(); + errorAttestedMembership.setError(errorMsg); + errorAttestedMembership.setAttestation(attestation); + return errorAttestedMembership; } -export function generateErrorCounterAttestation(errorMsg, securityDomain, memberId, nonce) { - const unitId = new agent_pb.SecurityDomainMemberIdentity(); - unitId.setSecurityDomain(securityDomain); - unitId.setMemberId(memberId); - - const attestation = new agent_pb.Attestation(); - attestation.setUnitIdentity(unitId); - attestation.setNonce(nonce); - attestation.setTimestamp(Date.now()); - - const errorCounterAttestedMembership = new agent_pb.CounterAttestedMembership(); - errorCounterAttestedMembership.setError(errorMsg); - errorCounterAttestedMembership.setAttestationsList([attestation]); - return errorCounterAttestedMembership; +export function generateErrorCounterAttestation( + errorMsg, + securityDomain, + memberId, + nonce, +) { + const unitId = new agent_pb.SecurityDomainMemberIdentity(); + unitId.setSecurityDomain(securityDomain); + unitId.setMemberId(memberId); + + const attestation = new agent_pb.Attestation(); + attestation.setUnitIdentity(unitId); + attestation.setNonce(nonce); + attestation.setTimestamp(Date.now()); + + const errorCounterAttestedMembership = + new agent_pb.CounterAttestedMembership(); + errorCounterAttestedMembership.setError(errorMsg); + errorCounterAttestedMembership.setAttestationsList([attestation]); + return errorCounterAttestedMembership; } diff --git a/weaver/core/identity-management/iin-agent/src/fabric-ledger/connector.ts b/weaver/core/identity-management/iin-agent/src/fabric-ledger/connector.ts index f4012ca3b3..a3d6723d9d 100644 --- a/weaver/core/identity-management/iin-agent/src/fabric-ledger/connector.ts +++ b/weaver/core/identity-management/iin-agent/src/fabric-ledger/connector.ts @@ -4,123 +4,209 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Contract } from 'fabric-network'; -import * as path from 'path'; -import * as fs from 'fs'; - -import iin_agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; -import { InteroperableHelper } from '@hyperledger/cacti-weaver-sdk-fabric' - -import { LedgerBase } from '../common/ledgerBase'; -import { handlePromise, signMessage } from '../common/utils'; -import { walletSetup, getWallet } from './walletUtils'; -import { getAllMSPConfigurations, invokeFabricChaincode, queryFabricChaincode } from './networkUtils'; +import { Contract } from "fabric-network"; +import * as path from "path"; +import * as fs from "fs"; + +import iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; +import { InteroperableHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; + +import { LedgerBase } from "../common/ledgerBase"; +import { handlePromise, signMessage } from "../common/utils"; +import { walletSetup, getWallet } from "./walletUtils"; +import { + getAllMSPConfigurations, + invokeFabricChaincode, + queryFabricChaincode, +} from "./networkUtils"; export class FabricConnector extends LedgerBase { - connectionProfilePath: string; - configFilePath: string; - networkId: string; - walletPath: string; - iinAgentUserName: string; - - constructor(ledgerId: string, contractId: string, networkId: string, configFilePath: string) { - const weaverCCId = contractId ? contractId : 'interop'; - configFilePath = configFilePath ? configFilePath : path.resolve(__dirname, './', 'config.json'); - if (!fs.existsSync(configFilePath)) { - throw new Error('Config does not exist at path: ' + configFilePath); - } - const config = JSON.parse(fs.readFileSync(configFilePath, 'utf8').toString()); - super(ledgerId, config.mspId, weaverCCId); - - this.configFilePath = configFilePath; - this.networkId = networkId ? networkId : 'network1'; - this.iinAgentUserName = config.agent.name; - this.connectionProfilePath = (config.ccpPath && config.ccpPath.length>0) ? config.ccpPath : path.resolve(__dirname, './', 'connection_profile.json'); - if (!fs.existsSync(this.connectionProfilePath)) { - throw new Error('Connection profile does not exist at path: ' + this.connectionProfilePath); - } - this.walletPath = (config.walletPath && config.walletPath.length>0) ? config.walletPath : path.join(process.cwd(), `wallet-${this.networkId}-${this.memberId}`); - } - - async init() { - await walletSetup(this.walletPath, this.connectionProfilePath, this.configFilePath); - } - - // Collect security domain membership info - async getAttestedMembership(securityDomain: string, nonce: string): Promise { - const membership = await getAllMSPConfigurations(this.walletPath, this.connectionProfilePath, this.configFilePath, this.ledgerId); - membership.setSecuritydomain(securityDomain); - const membershipSerializedBase64 = Buffer.from(membership.serializeBinary()).toString('base64'); - const certAndSign = await this.agentSignMessage(membershipSerializedBase64 + nonce); - - const unitId = new iin_agent_pb.SecurityDomainMemberIdentity(); - unitId.setSecurityDomain(securityDomain); - unitId.setMemberId(this.memberId); - - const attestation = new iin_agent_pb.Attestation(); - attestation.setUnitIdentity(unitId); - attestation.setCertificate(certAndSign.certificate); - attestation.setSignature(certAndSign.signature); - attestation.setNonce(nonce); - attestation.setTimestamp(Date.now()); - - const attestedMembership = new iin_agent_pb.AttestedMembership(); - attestedMembership.setMembership(membershipSerializedBase64); - attestedMembership.setAttestation(attestation); - return attestedMembership; - } - - // Collect security domain membership info - async counterAttestMembership(attestedMembershipSetSerialized64: string, securityDomain: string, nonce: string): Promise { - const certAndSign = await this.agentSignMessage(attestedMembershipSetSerialized64 + nonce); - - const unitId = new iin_agent_pb.SecurityDomainMemberIdentity(); - unitId.setSecurityDomain(securityDomain); - unitId.setMemberId(this.memberId); - - const attestation = new iin_agent_pb.Attestation(); - attestation.setUnitIdentity(unitId); - attestation.setCertificate(certAndSign.certificate); - attestation.setSignature(certAndSign.signature); - attestation.setNonce(nonce); - attestation.setTimestamp(Date.now()); - - const counterAttestedMembership = new iin_agent_pb.CounterAttestedMembership(); - counterAttestedMembership.setAttestedMembershipSet(attestedMembershipSetSerialized64); - counterAttestedMembership.setAttestationsList([attestation]); - return counterAttestedMembership; - } - - // record Membership - async recordMembershipInLedger(counterAttestedMembership: iin_agent_pb.CounterAttestedMembership): Promise { - const counterAttestedMembershipSerialized64 = Buffer.from(counterAttestedMembership.serializeBinary()).toString('base64'); - try { - const res = await invokeFabricChaincode(this.walletPath, this.connectionProfilePath, this.configFilePath, this.ledgerId, this.contractId, "CreateMembership", [counterAttestedMembershipSerialized64]); - return res; - } catch (e) { - return await invokeFabricChaincode(this.walletPath, this.connectionProfilePath, this.configFilePath, this.ledgerId, this.contractId, "UpdateMembership", [counterAttestedMembershipSerialized64]); - } + connectionProfilePath: string; + configFilePath: string; + networkId: string; + walletPath: string; + iinAgentUserName: string; + + constructor( + ledgerId: string, + contractId: string, + networkId: string, + configFilePath: string, + ) { + const weaverCCId = contractId ? contractId : "interop"; + configFilePath = configFilePath + ? configFilePath + : path.resolve(__dirname, "./", "config.json"); + if (!fs.existsSync(configFilePath)) { + throw new Error("Config does not exist at path: " + configFilePath); } - - // Invoke a contract to drive a transaction - // TODO: Add parameters corresponding to the output of a flow among IIN agents - async invokeContract(): Promise { - return await invokeFabricChaincode(this.walletPath, this.connectionProfilePath, this.configFilePath, this.ledgerId, this.contractId, "", []); + const config = JSON.parse( + fs.readFileSync(configFilePath, "utf8").toString(), + ); + super(ledgerId, config.mspId, weaverCCId); + + this.configFilePath = configFilePath; + this.networkId = networkId ? networkId : "network1"; + this.iinAgentUserName = config.agent.name; + this.connectionProfilePath = + config.ccpPath && config.ccpPath.length > 0 + ? config.ccpPath + : path.resolve(__dirname, "./", "connection_profile.json"); + if (!fs.existsSync(this.connectionProfilePath)) { + throw new Error( + "Connection profile does not exist at path: " + + this.connectionProfilePath, + ); } - - // Query a contract to fetch information from the ledger - async queryContract(): Promise { - return await queryFabricChaincode(this.walletPath, this.connectionProfilePath, this.configFilePath, this.ledgerId, this.contractId, "", []); - } - - private async agentSignMessage(message): Promise<{ certificate: string, signature: string }> { - const wallet = await getWallet(this.walletPath); - type KeyCert = { key: any, cert: any } - const keyCert = await InteroperableHelper.getKeyAndCertForRemoteRequestbyUserName(wallet, this.iinAgentUserName); - const signature = signMessage( - message, - keyCert.key.toBytes() - ); - return { certificate: keyCert.cert, signature: signature}; + this.walletPath = + config.walletPath && config.walletPath.length > 0 + ? config.walletPath + : path.join(process.cwd(), `wallet-${this.networkId}-${this.memberId}`); + } + + async init() { + await walletSetup( + this.walletPath, + this.connectionProfilePath, + this.configFilePath, + ); + } + + // Collect security domain membership info + async getAttestedMembership( + securityDomain: string, + nonce: string, + ): Promise { + const membership = await getAllMSPConfigurations( + this.walletPath, + this.connectionProfilePath, + this.configFilePath, + this.ledgerId, + ); + membership.setSecuritydomain(securityDomain); + const membershipSerializedBase64 = Buffer.from( + membership.serializeBinary(), + ).toString("base64"); + const certAndSign = await this.agentSignMessage( + membershipSerializedBase64 + nonce, + ); + + const unitId = new iin_agent_pb.SecurityDomainMemberIdentity(); + unitId.setSecurityDomain(securityDomain); + unitId.setMemberId(this.memberId); + + const attestation = new iin_agent_pb.Attestation(); + attestation.setUnitIdentity(unitId); + attestation.setCertificate(certAndSign.certificate); + attestation.setSignature(certAndSign.signature); + attestation.setNonce(nonce); + attestation.setTimestamp(Date.now()); + + const attestedMembership = new iin_agent_pb.AttestedMembership(); + attestedMembership.setMembership(membershipSerializedBase64); + attestedMembership.setAttestation(attestation); + return attestedMembership; + } + + // Collect security domain membership info + async counterAttestMembership( + attestedMembershipSetSerialized64: string, + securityDomain: string, + nonce: string, + ): Promise { + const certAndSign = await this.agentSignMessage( + attestedMembershipSetSerialized64 + nonce, + ); + + const unitId = new iin_agent_pb.SecurityDomainMemberIdentity(); + unitId.setSecurityDomain(securityDomain); + unitId.setMemberId(this.memberId); + + const attestation = new iin_agent_pb.Attestation(); + attestation.setUnitIdentity(unitId); + attestation.setCertificate(certAndSign.certificate); + attestation.setSignature(certAndSign.signature); + attestation.setNonce(nonce); + attestation.setTimestamp(Date.now()); + + const counterAttestedMembership = + new iin_agent_pb.CounterAttestedMembership(); + counterAttestedMembership.setAttestedMembershipSet( + attestedMembershipSetSerialized64, + ); + counterAttestedMembership.setAttestationsList([attestation]); + return counterAttestedMembership; + } + + // record Membership + async recordMembershipInLedger( + counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, + ): Promise { + const counterAttestedMembershipSerialized64 = Buffer.from( + counterAttestedMembership.serializeBinary(), + ).toString("base64"); + try { + const res = await invokeFabricChaincode( + this.walletPath, + this.connectionProfilePath, + this.configFilePath, + this.ledgerId, + this.contractId, + "CreateMembership", + [counterAttestedMembershipSerialized64], + ); + return res; + } catch (e) { + return await invokeFabricChaincode( + this.walletPath, + this.connectionProfilePath, + this.configFilePath, + this.ledgerId, + this.contractId, + "UpdateMembership", + [counterAttestedMembershipSerialized64], + ); } + } + + // Invoke a contract to drive a transaction + // TODO: Add parameters corresponding to the output of a flow among IIN agents + async invokeContract(): Promise { + return await invokeFabricChaincode( + this.walletPath, + this.connectionProfilePath, + this.configFilePath, + this.ledgerId, + this.contractId, + "", + [], + ); + } + + // Query a contract to fetch information from the ledger + async queryContract(): Promise { + return await queryFabricChaincode( + this.walletPath, + this.connectionProfilePath, + this.configFilePath, + this.ledgerId, + this.contractId, + "", + [], + ); + } + + private async agentSignMessage( + message, + ): Promise<{ certificate: string; signature: string }> { + const wallet = await getWallet(this.walletPath); + type KeyCert = { key: any; cert: any }; + const keyCert = + await InteroperableHelper.getKeyAndCertForRemoteRequestbyUserName( + wallet, + this.iinAgentUserName, + ); + const signature = signMessage(message, keyCert.key.toBytes()); + return { certificate: keyCert.cert, signature: signature }; + } } diff --git a/weaver/core/identity-management/iin-agent/src/fabric-ledger/networkUtils.ts b/weaver/core/identity-management/iin-agent/src/fabric-ledger/networkUtils.ts index 2dd8a0c873..c2c2d3a6a4 100644 --- a/weaver/core/identity-management/iin-agent/src/fabric-ledger/networkUtils.ts +++ b/weaver/core/identity-management/iin-agent/src/fabric-ledger/networkUtils.ts @@ -4,180 +4,231 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Gateway } from 'fabric-network'; -import { Channel } from 'fabric-common'; -import * as path from 'path'; -import * as fs from 'fs'; +import { Gateway } from "fabric-network"; +import { Channel } from "fabric-common"; +import * as path from "path"; +import * as fs from "fs"; -import membershipPb from '@hyperledger/cacti-weaver-protos-js/common/membership_pb'; -import { MembershipManager } from '@hyperledger/cacti-weaver-sdk-fabric' +import membershipPb from "@hyperledger/cacti-weaver-protos-js/common/membership_pb"; +import { MembershipManager } from "@hyperledger/cacti-weaver-sdk-fabric"; -import { getWallet } from './walletUtils'; +import { getWallet } from "./walletUtils"; import * as utils from "../common/utils"; // Get a handle to a network gateway using existing wallet credentials const getNetworkGateway = async ( - walletPath: string, - connectionProfilePath: string, - configFilePath: string + walletPath: string, + connectionProfilePath: string, + configFilePath: string, ): Promise => { - try { - // load the network configuration - if (!fs.existsSync(connectionProfilePath)) { - throw new Error('Connection profile does not exist at path: ' + connectionProfilePath); - } - const ccp = JSON.parse(fs.readFileSync(connectionProfilePath, 'utf8').toString()); - if (!fs.existsSync(configFilePath)) { - throw new Error('Config does not exist at path: ' + configFilePath); - } - const config = JSON.parse(fs.readFileSync(configFilePath, 'utf8').toString()); + try { + // load the network configuration + if (!fs.existsSync(connectionProfilePath)) { + throw new Error( + "Connection profile does not exist at path: " + connectionProfilePath, + ); + } + const ccp = JSON.parse( + fs.readFileSync(connectionProfilePath, "utf8").toString(), + ); + if (!fs.existsSync(configFilePath)) { + throw new Error("Config does not exist at path: " + configFilePath); + } + const config = JSON.parse( + fs.readFileSync(configFilePath, "utf8").toString(), + ); - // Create a new file system-based wallet for managing identities. - const userName = config.agent.name; - const wallet = await getWallet(walletPath); - console.log(`Wallet path: ${walletPath}`); - // Check to see if we've already enrolled the user. - const identity = await wallet.get(userName); - if (!identity) { - console.log(`An identity for the user "${userName}.com" does not exist in the wallet`); - console.log('Run the registerUser.ts application before retrying'); - } - // Create a new gateway for connecting to our peer node. - const gateway = new Gateway(); - await gateway.connect(ccp, { - wallet, - identity: `${userName}`, - discovery: { enabled: true, asLocalhost: config.local === 'false' ? false : true }, - }); - return gateway; - } catch (error) { - console.error(`Failed to instantiate network (channel): ${error}`); - throw error; + // Create a new file system-based wallet for managing identities. + const userName = config.agent.name; + const wallet = await getWallet(walletPath); + console.log(`Wallet path: ${walletPath}`); + // Check to see if we've already enrolled the user. + const identity = await wallet.get(userName); + if (!identity) { + console.log( + `An identity for the user "${userName}.com" does not exist in the wallet`, + ); + console.log("Run the registerUser.ts application before retrying"); } -} + // Create a new gateway for connecting to our peer node. + const gateway = new Gateway(); + await gateway.connect(ccp, { + wallet, + identity: `${userName}`, + discovery: { + enabled: true, + asLocalhost: config.local === "false" ? false : true, + }, + }); + return gateway; + } catch (error) { + console.error(`Failed to instantiate network (channel): ${error}`); + throw error; + } +}; // Get a handle to a network gateway using existing wallet credentials const getNetworkContract = async ( - walletPath: string, - connectionProfilePath: string, - configFilePath: string, - channelId: string, - chaincodeId: string, + walletPath: string, + connectionProfilePath: string, + configFilePath: string, + channelId: string, + chaincodeId: string, ): Promise => { - try { - const gateway = await getNetworkGateway(walletPath, connectionProfilePath, configFilePath); - if (!gateway) { - throw new Error('Unable to connect to the ledger!'); - } - const network = await gateway.getNetwork(channelId); - const contract = network.getContract(chaincodeId); - return { gateway: gateway, contract: contract }; - } catch (error) { - console.error(`Failed to connect to contract: ${error}`); - throw error; + try { + const gateway = await getNetworkGateway( + walletPath, + connectionProfilePath, + configFilePath, + ); + if (!gateway) { + throw new Error("Unable to connect to the ledger!"); } -} + const network = await gateway.getNetwork(channelId); + const contract = network.getContract(chaincodeId); + return { gateway: gateway, contract: contract }; + } catch (error) { + console.error(`Failed to connect to contract: ${error}`); + throw error; + } +}; async function getMSPConfiguration( - walletPath: string, - connectionProfilePath: string, - configFilePath: string, - channelId: string, + walletPath: string, + connectionProfilePath: string, + configFilePath: string, + channelId: string, ): Promise { - console.log('Running invocation on Fabric channel and chaincode'); - try { - const gateway = await getNetworkGateway(walletPath, connectionProfilePath, configFilePath); - if (!gateway) { - throw new Error('Unable to connect to the ledger!'); - } - const network = await gateway.getNetwork(channelId); - const config = JSON.parse(fs.readFileSync(configFilePath, 'utf8').toString()); - const membership = MembershipManager.getMSPConfigurations(network, [config.mspId]); - // Disconnect from the gateway. - gateway.disconnect(); - return membership; - } catch (error) { - console.error(`Failed to submit transaction: ${error}`); - throw error; + console.log("Running invocation on Fabric channel and chaincode"); + try { + const gateway = await getNetworkGateway( + walletPath, + connectionProfilePath, + configFilePath, + ); + if (!gateway) { + throw new Error("Unable to connect to the ledger!"); } + const network = await gateway.getNetwork(channelId); + const config = JSON.parse( + fs.readFileSync(configFilePath, "utf8").toString(), + ); + const membership = MembershipManager.getMSPConfigurations(network, [ + config.mspId, + ]); + // Disconnect from the gateway. + gateway.disconnect(); + return membership; + } catch (error) { + console.error(`Failed to submit transaction: ${error}`); + throw error; + } } async function getAllMSPConfigurations( - walletPath: string, - connectionProfilePath: string, - configFilePath: string, - channelId: string, + walletPath: string, + connectionProfilePath: string, + configFilePath: string, + channelId: string, ): Promise { - console.log('Running invocation on Fabric channel and chaincode'); - try { - const gateway = await getNetworkGateway(walletPath, connectionProfilePath, configFilePath); - if (!gateway) { - throw new Error('Unable to connect to the ledger!'); - } - const network = await gateway.getNetwork(channelId); - const config = JSON.parse(fs.readFileSync(configFilePath, 'utf8').toString()); - const membership = MembershipManager.getAllMSPConfigurations(network, config.ordererMspIds); - // Disconnect from the gateway. - gateway.disconnect(); - return membership; - } catch (error) { - console.error(`Failed to submit transaction: ${error}`); - throw error; + console.log("Running invocation on Fabric channel and chaincode"); + try { + const gateway = await getNetworkGateway( + walletPath, + connectionProfilePath, + configFilePath, + ); + if (!gateway) { + throw new Error("Unable to connect to the ledger!"); } + const network = await gateway.getNetwork(channelId); + const config = JSON.parse( + fs.readFileSync(configFilePath, "utf8").toString(), + ); + const membership = MembershipManager.getAllMSPConfigurations( + network, + config.ordererMspIds, + ); + // Disconnect from the gateway. + gateway.disconnect(); + return membership; + } catch (error) { + console.error(`Failed to submit transaction: ${error}`); + throw error; + } } async function invokeFabricChaincode( - walletPath: string, - connectionProfilePath: string, - configFilePath: string, - channelId: string, - chaincodeId: string, - functionName: string, - args: Array, + walletPath: string, + connectionProfilePath: string, + configFilePath: string, + channelId: string, + chaincodeId: string, + functionName: string, + args: Array, ): Promise { - console.log('Running invocation on Fabric channel and chaincode'); - try { - const gatewayAndContract = await getNetworkContract(walletPath, connectionProfilePath, configFilePath, channelId, chaincodeId); - const [result, submitError] = await utils.handlePromise( - gatewayAndContract.contract.submitTransaction(functionName, ...args), - ); - if (submitError) { - throw new Error(`submitTransaction Error: ${submitError}`); - } - // Disconnect from the gateway. - gatewayAndContract.gateway.disconnect(); - return result; - } catch (error) { - console.error(`Failed to submit transaction: ${error}`); - throw error; + console.log("Running invocation on Fabric channel and chaincode"); + try { + const gatewayAndContract = await getNetworkContract( + walletPath, + connectionProfilePath, + configFilePath, + channelId, + chaincodeId, + ); + const [result, submitError] = await utils.handlePromise( + gatewayAndContract.contract.submitTransaction(functionName, ...args), + ); + if (submitError) { + throw new Error(`submitTransaction Error: ${submitError}`); } + // Disconnect from the gateway. + gatewayAndContract.gateway.disconnect(); + return result; + } catch (error) { + console.error(`Failed to submit transaction: ${error}`); + throw error; + } } async function queryFabricChaincode( - walletPath: string, - connectionProfilePath: string, - configFilePath: string, - channelId: string, - chaincodeId: string, - functionName: string, - args: Array, + walletPath: string, + connectionProfilePath: string, + configFilePath: string, + channelId: string, + chaincodeId: string, + functionName: string, + args: Array, ): Promise { - console.log('Running query on Fabric channel and chaincode'); - try { - const gatewayAndContract = await getNetworkContract(walletPath, connectionProfilePath, configFilePath, channelId, chaincodeId); - const [result, evalError] = await utils.handlePromise( - gatewayAndContract.contract.evaluateTransaction(functionName, ...args), - ); - if (evalError) { - throw new Error(`evaluateTransaction Error: ${evalError}`); - } - // Disconnect from the gateway. - gatewayAndContract.gateway.disconnect(); - return result; - } catch (error) { - console.error(`Failed to submit query: ${error}`); - throw error; + console.log("Running query on Fabric channel and chaincode"); + try { + const gatewayAndContract = await getNetworkContract( + walletPath, + connectionProfilePath, + configFilePath, + channelId, + chaincodeId, + ); + const [result, evalError] = await utils.handlePromise( + gatewayAndContract.contract.evaluateTransaction(functionName, ...args), + ); + if (evalError) { + throw new Error(`evaluateTransaction Error: ${evalError}`); } + // Disconnect from the gateway. + gatewayAndContract.gateway.disconnect(); + return result; + } catch (error) { + console.error(`Failed to submit query: ${error}`); + throw error; + } } -export { getNetworkGateway, getNetworkContract, getMSPConfiguration, getAllMSPConfigurations, invokeFabricChaincode, queryFabricChaincode }; +export { + getNetworkGateway, + getNetworkContract, + getMSPConfiguration, + getAllMSPConfigurations, + invokeFabricChaincode, + queryFabricChaincode, +}; diff --git a/weaver/core/identity-management/iin-agent/src/fabric-ledger/walletUtils.ts b/weaver/core/identity-management/iin-agent/src/fabric-ledger/walletUtils.ts index 46bc059329..25ce4f97f9 100644 --- a/weaver/core/identity-management/iin-agent/src/fabric-ledger/walletUtils.ts +++ b/weaver/core/identity-management/iin-agent/src/fabric-ledger/walletUtils.ts @@ -4,98 +4,112 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Wallets } from 'fabric-network'; -import FabricCAServices from 'fabric-ca-client'; -import * as path from 'path'; -import * as fs from 'fs'; +import { Wallets } from "fabric-network"; +import FabricCAServices from "fabric-ca-client"; +import * as path from "path"; +import * as fs from "fs"; const getWallet = async (walletPath: string) => { - return await Wallets.newFileSystemWallet(walletPath); + return await Wallets.newFileSystemWallet(walletPath); }; -const walletSetup = async (walletPath: string, conn_profile_path: string, config_file_path: string): Promise => { - if (!fs.existsSync(conn_profile_path)) { - throw new Error('Connection profile does not exist at path: ' + conn_profile_path); - } - const ccp = JSON.parse(fs.readFileSync(conn_profile_path, 'utf8').toString()); - if (!fs.existsSync(config_file_path)) { - throw new Error('Config does not exist at path: ' + config_file_path); - } - const config = JSON.parse(fs.readFileSync(config_file_path, 'utf8').toString()); - // Create a new CA client for interacting with the CA. - const org = ccp.client["organization"]; - console.log('Org', org); - const caName = ccp.organizations[org]["certificateAuthorities"][0]; - console.log('CA Name', caName); - const caURL = config.caUrl ? config.caUrl : ccp.certificateAuthorities[caName].url; - console.log('CA URL', caURL); - const ca = new FabricCAServices(caURL); - const ident = ca.newIdentityService(); +const walletSetup = async ( + walletPath: string, + conn_profile_path: string, + config_file_path: string, +): Promise => { + if (!fs.existsSync(conn_profile_path)) { + throw new Error( + "Connection profile does not exist at path: " + conn_profile_path, + ); + } + const ccp = JSON.parse(fs.readFileSync(conn_profile_path, "utf8").toString()); + if (!fs.existsSync(config_file_path)) { + throw new Error("Config does not exist at path: " + config_file_path); + } + const config = JSON.parse( + fs.readFileSync(config_file_path, "utf8").toString(), + ); + // Create a new CA client for interacting with the CA. + const org = ccp.client["organization"]; + console.log("Org", org); + const caName = ccp.organizations[org]["certificateAuthorities"][0]; + console.log("CA Name", caName); + const caURL = config.caUrl + ? config.caUrl + : ccp.certificateAuthorities[caName].url; + console.log("CA URL", caURL); + const ca = new FabricCAServices(caURL); + const ident = ca.newIdentityService(); - const wallet = await getWallet(walletPath); - const adminName = config.admin.name; - const adminSecret = config.admin.secret; - // build a user object for authenticating with the CA // Check to see if we've already enrolled the admin user. - let adminIdentity = await wallet.get(adminName); + const wallet = await getWallet(walletPath); + const adminName = config.admin.name; + const adminSecret = config.admin.secret; + // build a user object for authenticating with the CA // Check to see if we've already enrolled the admin user. + let adminIdentity = await wallet.get(adminName); - if (adminIdentity) { - console.log('An identity for the admin user "admin" already exists in the wallet'); + if (adminIdentity) { + console.log( + 'An identity for the admin user "admin" already exists in the wallet', + ); + } else { + // Enroll the admin user, and import the new identity into the wallet. + console.log("Enrolling Admin...", adminName, adminSecret); + const enrollment = await ca.enroll({ + enrollmentID: adminName, + enrollmentSecret: adminSecret, + }); + const x509Identity = { + credentials: { + certificate: enrollment.certificate, + privateKey: enrollment.key.toBytes(), + }, + mspId: config.mspId, + type: "X.509", + }; + await wallet.put(adminName, x509Identity); + adminIdentity = await wallet.get(adminName); + } + if (adminIdentity) { + console.log(`Creating ${config.agent.name} Identity`); + const provider = wallet + .getProviderRegistry() + .getProvider(adminIdentity.type); + const adminUser = await provider.getUserContext(adminIdentity, adminName); + const identity = await wallet.get(config.agent.name); + if (!identity) { + const secret = await ca.register( + { + affiliation: config.agent.affiliation, + enrollmentID: config.agent.name, + role: config.agent.role, + attrs: config.agent.attrs, + }, + adminUser, + ); + const enrollment = await ca.enroll({ + enrollmentID: config.agent.name, + enrollmentSecret: secret, + }); + const x509Identity = { + credentials: { + certificate: enrollment.certificate, + privateKey: enrollment.key.toBytes(), + }, + mspId: config.mspId, + type: "X.509", + }; + await wallet.put(config.agent.name, x509Identity); + console.log(`${config.agent.name} Identity Created`); } else { - // Enroll the admin user, and import the new identity into the wallet. - console.log('Enrolling Admin...', adminName, adminSecret); - const enrollment = await ca.enroll({ - enrollmentID: adminName, - enrollmentSecret: adminSecret, - }); - const x509Identity = { - credentials: { - certificate: enrollment.certificate, - privateKey: enrollment.key.toBytes(), - }, - mspId: config.mspId, - type: 'X.509', - }; - await wallet.put(adminName, x509Identity); - adminIdentity = await wallet.get(adminName); + console.log(`${config.agent.name} Identity Already exists`); } - if (adminIdentity) { - console.log(`Creating ${config.agent.name} Identity`); - const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type); - const adminUser = await provider.getUserContext(adminIdentity, adminName); - const identity = await wallet.get(config.agent.name); - if (!identity) { - const secret = await ca.register( - { - affiliation: config.agent.affiliation, - enrollmentID: config.agent.name, - role: config.agent.role, - attrs: config.agent.attrs, - }, - adminUser, - ); - const enrollment = await ca.enroll({ - enrollmentID: config.agent.name, - enrollmentSecret: secret, - }); - const x509Identity = { - credentials: { - certificate: enrollment.certificate, - privateKey: enrollment.key.toBytes(), - }, - mspId: config.mspId, - type: 'X.509', - }; - await wallet.put(config.agent.name, x509Identity); - console.log(`${config.agent.name} Identity Created`); - } else { - console.log(`${config.agent.name} Identity Already exists`); - } - return wallet; - } else { - console.error('Admin was not registered'); - throw new Error('Admin was not registered'); - } + return wallet; + } else { + console.error("Admin was not registered"); + throw new Error("Admin was not registered"); + } }; export { getWallet, walletSetup }; diff --git a/weaver/core/identity-management/iin-agent/src/protocols/externalOperations.ts b/weaver/core/identity-management/iin-agent/src/protocols/externalOperations.ts index a7b107b289..aa989bf934 100644 --- a/weaver/core/identity-management/iin-agent/src/protocols/externalOperations.ts +++ b/weaver/core/identity-management/iin-agent/src/protocols/externalOperations.ts @@ -4,247 +4,422 @@ * SPDX-License-Identifier: Apache-2.0 */ -import iin_agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; -import * as utils from '../common/utils'; -import { LedgerBase } from '../common/ledgerBase'; +import iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; +import * as utils from "../common/utils"; +import { LedgerBase } from "../common/ledgerBase"; import { v4 as uuidv4 } from "uuid"; // key: get using function "getSecurityDomainMapKey" -export let securityDomainMap = new Map(); -export let counterAttestationsMap = new Map(); +export const securityDomainMap = new Map< + string, + string | iin_agent_pb.AttestedMembership +>(); +export const counterAttestationsMap = new Map< + string, + string | iin_agent_pb.CounterAttestedMembership +>(); // key: Nonce -export let foreignAgentResponseCount = new Map(); -export let localAgentResponseCount = new Map(); +export const foreignAgentResponseCount = new Map< + string, + { current: number; total: number } +>(); +export const localAgentResponseCount = new Map< + string, + { current: number; total: number } +>(); -export function getSecurityDomainMapKey(securityDomain: string, iinAgent: string, nonce?: string | undefined) { - if (nonce) { - return 'SEC_DOM_MAP:' + securityDomain + ':' + iinAgent + ':' + nonce; - } else { - return 'SEC_DOM_MAP:' + securityDomain + ':' + iinAgent; - } +export function getSecurityDomainMapKey( + securityDomain: string, + iinAgent: string, + nonce?: string | undefined, +) { + if (nonce) { + return "SEC_DOM_MAP:" + securityDomain + ":" + iinAgent + ":" + nonce; + } else { + return "SEC_DOM_MAP:" + securityDomain + ":" + iinAgent; + } } -export function syncExternalStateFromIINAgent(remoteSecurityDomainUnit: iin_agent_pb.SecurityDomainMemberIdentity, securityDomain: string, memberId: string) { - const nonce = uuidv4(); - const remoteSecurityDomain = remoteSecurityDomainUnit.getSecurityDomain(); - const remoteSecurityDomainDNS = utils.getSecurityDomainDNS(remoteSecurityDomain); - if (!remoteSecurityDomainDNS) { - const errorMsg = `no security domain: ${remoteSecurityDomain} found in SecurityDomain DNS config` - console.error("Error:", errorMsg) - throw new Error(errorMsg) - } - syncExternalStateFromIINAgentHelper(remoteSecurityDomainUnit, securityDomain, memberId, nonce, remoteSecurityDomainDNS).then().catch((error) => { - console.error("SyncExternalStateFromIINAgentHelper Error:", error); +export function syncExternalStateFromIINAgent( + remoteSecurityDomainUnit: iin_agent_pb.SecurityDomainMemberIdentity, + securityDomain: string, + memberId: string, +) { + const nonce = uuidv4(); + const remoteSecurityDomain = remoteSecurityDomainUnit.getSecurityDomain(); + const remoteSecurityDomainDNS = + utils.getSecurityDomainDNS(remoteSecurityDomain); + if (!remoteSecurityDomainDNS) { + const errorMsg = `no security domain: ${remoteSecurityDomain} found in SecurityDomain DNS config`; + console.error("Error:", errorMsg); + throw new Error(errorMsg); + } + syncExternalStateFromIINAgentHelper( + remoteSecurityDomainUnit, + securityDomain, + memberId, + nonce, + remoteSecurityDomainDNS, + ) + .then() + .catch((error) => { + console.error("SyncExternalStateFromIINAgentHelper Error:", error); }); - return nonce + return nonce; } // Handles communication with foreign IIN agents -const syncExternalStateFromIINAgentHelper = async (remoteSecurityDomainUnit: iin_agent_pb.SecurityDomainMemberIdentity, securityDomain: string, memberId: string, nonce: string, remoteSecurityDomainDNS: any) => { - const remoteSecurityDomain = remoteSecurityDomainUnit.getSecurityDomain(); - console.log('syncExternalStateFromIINAgent:', remoteSecurityDomain, '-', remoteSecurityDomainUnit.getMemberId(), ' nonce:', nonce); - - const requestingSecurityDomain = new iin_agent_pb.SecurityDomainMemberIdentity(); - requestingSecurityDomain.setSecurityDomain(securityDomain); - requestingSecurityDomain.setMemberId(memberId); - - const request = new iin_agent_pb.SecurityDomainMemberIdentityRequest(); - request.setRequestingNetwork(requestingSecurityDomain); - request.setNonce(nonce); - - // Request Attested Membership from all members of remote security_domain - let totalAttesterCount = 0; - for (const iinAgent in remoteSecurityDomainDNS) { - const iinAgentClient = utils.getIINAgentClient(remoteSecurityDomain, iinAgent, remoteSecurityDomainDNS); - remoteSecurityDomainUnit.setMemberId(iinAgent); - request.setSourceNetwork(remoteSecurityDomainUnit); - console.log(`Requesting attested memberships from: ${remoteSecurityDomain} - ${iinAgent}`); - iinAgentClient.requestIdentityConfiguration(request, utils.defaultCallback); - totalAttesterCount++; - } - foreignAgentResponseCount.set(nonce, { current:0, total: totalAttesterCount }); +const syncExternalStateFromIINAgentHelper = async ( + remoteSecurityDomainUnit: iin_agent_pb.SecurityDomainMemberIdentity, + securityDomain: string, + memberId: string, + nonce: string, + remoteSecurityDomainDNS: any, +) => { + const remoteSecurityDomain = remoteSecurityDomainUnit.getSecurityDomain(); + console.log( + "syncExternalStateFromIINAgent:", + remoteSecurityDomain, + "-", + remoteSecurityDomainUnit.getMemberId(), + " nonce:", + nonce, + ); + + const requestingSecurityDomain = + new iin_agent_pb.SecurityDomainMemberIdentity(); + requestingSecurityDomain.setSecurityDomain(securityDomain); + requestingSecurityDomain.setMemberId(memberId); + + const request = new iin_agent_pb.SecurityDomainMemberIdentityRequest(); + request.setRequestingNetwork(requestingSecurityDomain); + request.setNonce(nonce); + + // Request Attested Membership from all members of remote security_domain + let totalAttesterCount = 0; + for (const iinAgent in remoteSecurityDomainDNS) { + const iinAgentClient = utils.getIINAgentClient( + remoteSecurityDomain, + iinAgent, + remoteSecurityDomainDNS, + ); + remoteSecurityDomainUnit.setMemberId(iinAgent); + request.setSourceNetwork(remoteSecurityDomainUnit); + console.log( + `Requesting attested memberships from: ${remoteSecurityDomain} - ${iinAgent}`, + ); + iinAgentClient.requestIdentityConfiguration(request, utils.defaultCallback); + totalAttesterCount++; + } + foreignAgentResponseCount.set(nonce, { + current: 0, + total: totalAttesterCount, + }); }; // Generates security domain unit's state/configuration -export const requestIdentityConfiguration = async (request: iin_agent_pb.SecurityDomainMemberIdentityRequest) => { - const sourceSecurityDomain = request.getSourceNetwork()!.getSecurityDomain(); - const sourceMemberId = request.getSourceNetwork()!.getMemberId(); - console.log('requestIdentityConfiguration:', sourceSecurityDomain, '-', sourceMemberId); - - const ledgerBase = utils.getLedgerBase(sourceSecurityDomain, sourceMemberId); - if (ledgerBase.memberId != sourceMemberId) { - throw new Error(`This IIN Agent's member Id: ${ledgerBase.memberId} doesn't match with provided member Id: ${sourceMemberId} in request.`); - } - const [attestedMembership, error] = await utils.handlePromise(ledgerBase.getAttestedMembership(sourceSecurityDomain, request.getNonce())); - const iinAgentClient = utils.getIINAgentClient(request.getRequestingNetwork()!.getSecurityDomain(), request.getRequestingNetwork()!.getMemberId()); - if (error) { - iinAgentClient.sendIdentityConfiguration( - utils.generateErrorAttestation( - error.toString(), - sourceSecurityDomain, - sourceMemberId, - request.getNonce() - ), - utils.defaultCallback - ); - } else { - iinAgentClient.sendIdentityConfiguration(attestedMembership, utils.defaultCallback); - } +export const requestIdentityConfiguration = async ( + request: iin_agent_pb.SecurityDomainMemberIdentityRequest, +) => { + const sourceSecurityDomain = request.getSourceNetwork()!.getSecurityDomain(); + const sourceMemberId = request.getSourceNetwork()!.getMemberId(); + console.log( + "requestIdentityConfiguration:", + sourceSecurityDomain, + "-", + sourceMemberId, + ); + + const ledgerBase = utils.getLedgerBase(sourceSecurityDomain, sourceMemberId); + if (ledgerBase.memberId != sourceMemberId) { + throw new Error( + `This IIN Agent's member Id: ${ledgerBase.memberId} doesn't match with provided member Id: ${sourceMemberId} in request.`, + ); + } + const [attestedMembership, error] = await utils.handlePromise( + ledgerBase.getAttestedMembership(sourceSecurityDomain, request.getNonce()), + ); + const iinAgentClient = utils.getIINAgentClient( + request.getRequestingNetwork()!.getSecurityDomain(), + request.getRequestingNetwork()!.getMemberId(), + ); + if (error) { + iinAgentClient.sendIdentityConfiguration( + utils.generateErrorAttestation( + error.toString(), + sourceSecurityDomain, + sourceMemberId, + request.getNonce(), + ), + utils.defaultCallback, + ); + } else { + iinAgentClient.sendIdentityConfiguration( + attestedMembership, + utils.defaultCallback, + ); + } }; -export function sendIdentityConfiguration(attestedMembership: iin_agent_pb.AttestedMembership, securityDomain: string, memberId: string) { - const attestation = attestedMembership.getAttestation()!; - if (!attestation.hasUnitIdentity()) { - const errorMsg = `attestation has no SecurityDomainMemberIdentity associated with it`; - console.error('Error: ' + errorMsg); - throw new Error(errorMsg); - } - const nonce = attestation.getNonce(); - if (!foreignAgentResponseCount.has(nonce)) { - const errorMsg = `not expecting any response with received nonce: ${nonce}`; - console.error('Error: ' + errorMsg); - throw new Error(errorMsg); - } - sendIdentityConfigurationHelper(attestedMembership, securityDomain, memberId, nonce).then().catch((error) => { - console.error("SendIdentityConfigurationHelper Error:", error); +export function sendIdentityConfiguration( + attestedMembership: iin_agent_pb.AttestedMembership, + securityDomain: string, + memberId: string, +) { + const attestation = attestedMembership.getAttestation()!; + if (!attestation.hasUnitIdentity()) { + const errorMsg = `attestation has no SecurityDomainMemberIdentity associated with it`; + console.error("Error: " + errorMsg); + throw new Error(errorMsg); + } + const nonce = attestation.getNonce(); + if (!foreignAgentResponseCount.has(nonce)) { + const errorMsg = `not expecting any response with received nonce: ${nonce}`; + console.error("Error: " + errorMsg); + throw new Error(errorMsg); + } + sendIdentityConfigurationHelper( + attestedMembership, + securityDomain, + memberId, + nonce, + ) + .then() + .catch((error) => { + console.error("SendIdentityConfigurationHelper Error:", error); }); } // Processes foreign security domain unit's state/configuration received from a foreign IIN agent -const sendIdentityConfigurationHelper = async (attestedMembership: iin_agent_pb.AttestedMembership, securityDomain: string, memberId: string, nonce: string) => { - const attestation = attestedMembership.getAttestation()!; - const securityDomainUnit = attestation.getUnitIdentity()!; - const remoteSecurityDomain = securityDomainUnit.getSecurityDomain(); - const remoteMemberId = securityDomainUnit.getMemberId(); - const secDomMapKey = getSecurityDomainMapKey(remoteSecurityDomain, remoteMemberId, nonce); - console.log('sendIdentityConfiguration:', remoteSecurityDomain, '-', remoteMemberId, '-', nonce); - try { - if (attestedMembership.hasError()) { - throw new Error(attestedMembership.getError()); - } - if (attestation.getCertificate().length == 0) { - throw new Error('attestation has no certificate'); - } - if (attestation.getSignature().length == 0) { - throw new Error('attestation has no signature'); - } - // store response with nonce for the protocol flow - securityDomainMap.set(secDomMapKey, attestedMembership); - // Cache response without nonce for later use - securityDomainMap.set(getSecurityDomainMapKey(remoteSecurityDomain, remoteMemberId), attestedMembership); - } catch (e) { - const errorMsg = `${e} from SecurityDomain: ${remoteSecurityDomain}, Member: ${remoteMemberId}, Nonce: ${nonce}`; - console.error(errorMsg); - securityDomainMap.set(secDomMapKey, errorMsg); +const sendIdentityConfigurationHelper = async ( + attestedMembership: iin_agent_pb.AttestedMembership, + securityDomain: string, + memberId: string, + nonce: string, +) => { + const attestation = attestedMembership.getAttestation()!; + const securityDomainUnit = attestation.getUnitIdentity()!; + const remoteSecurityDomain = securityDomainUnit.getSecurityDomain(); + const remoteMemberId = securityDomainUnit.getMemberId(); + const secDomMapKey = getSecurityDomainMapKey( + remoteSecurityDomain, + remoteMemberId, + nonce, + ); + console.log( + "sendIdentityConfiguration:", + remoteSecurityDomain, + "-", + remoteMemberId, + "-", + nonce, + ); + try { + if (attestedMembership.hasError()) { + throw new Error(attestedMembership.getError()); } - const currForeignAgentResponsesCount = foreignAgentResponseCount.get(nonce).current; - const totalForeignAgentResponsesCount = foreignAgentResponseCount.get(nonce).total; - foreignAgentResponseCount.set(nonce, { current: currForeignAgentResponsesCount + 1, total: totalForeignAgentResponsesCount}); - - if (currForeignAgentResponsesCount + 1 < totalForeignAgentResponsesCount) { - // Pending respones from other foreign iin-agents; - return; + if (attestation.getCertificate().length == 0) { + throw new Error("attestation has no certificate"); } - if (currForeignAgentResponsesCount + 1 > totalForeignAgentResponsesCount) { - console.warn('Warning: Received extra response.'); + if (attestation.getSignature().length == 0) { + throw new Error("attestation has no signature"); } - - // All attesations received, Group Attestations; - let attestations = []; - let membership = ""; - let errorMsg = ""; - const remoteSecurityDomainDNS = utils.getSecurityDomainDNS(remoteSecurityDomain); - for (const remoteAgent in remoteSecurityDomainDNS) { - const key = getSecurityDomainMapKey(remoteSecurityDomain, remoteAgent, nonce); - if (!securityDomainMap.has(key)) { - // count completed but still some foreign agents haven't responded. - console.log(`Waiting for response from ${remoteAgent}`); - return; - } - let attestedMembershipOrError = securityDomainMap.get(key); - if (typeof attestedMembershipOrError === "string") { - errorMsg = attestedMembershipOrError as string; - } - attestedMembershipOrError = attestedMembershipOrError as iin_agent_pb.AttestedMembership; - const attestation = attestedMembershipOrError.getAttestation()!; - if (membership === "") { - membership = attestedMembershipOrError.getMembership(); - } else if (membership !== attestedMembershipOrError.getMembership()) { - errorMsg = `received different membership from ${remoteAgent}`; - } - if (!utils.validateAttestedMembership(membership, nonce, attestation)) { - errorMsg = `attested membership from ${remoteAgent} invalid.`; - } - attestations.push(attestation); + // store response with nonce for the protocol flow + securityDomainMap.set(secDomMapKey, attestedMembership); + // Cache response without nonce for later use + securityDomainMap.set( + getSecurityDomainMapKey(remoteSecurityDomain, remoteMemberId), + attestedMembership, + ); + } catch (e) { + const errorMsg = `${e} from SecurityDomain: ${remoteSecurityDomain}, Member: ${remoteMemberId}, Nonce: ${nonce}`; + console.error(errorMsg); + securityDomainMap.set(secDomMapKey, errorMsg); + } + const currForeignAgentResponsesCount = + foreignAgentResponseCount.get(nonce).current; + const totalForeignAgentResponsesCount = + foreignAgentResponseCount.get(nonce).total; + foreignAgentResponseCount.set(nonce, { + current: currForeignAgentResponsesCount + 1, + total: totalForeignAgentResponsesCount, + }); + + if (currForeignAgentResponsesCount + 1 < totalForeignAgentResponsesCount) { + // Pending respones from other foreign iin-agents; + return; + } + if (currForeignAgentResponsesCount + 1 > totalForeignAgentResponsesCount) { + console.warn("Warning: Received extra response."); + } + + // All attesations received, Group Attestations; + const attestations = []; + let membership = ""; + let errorMsg = ""; + const remoteSecurityDomainDNS = + utils.getSecurityDomainDNS(remoteSecurityDomain); + for (const remoteAgent in remoteSecurityDomainDNS) { + const key = getSecurityDomainMapKey( + remoteSecurityDomain, + remoteAgent, + nonce, + ); + if (!securityDomainMap.has(key)) { + // count completed but still some foreign agents haven't responded. + console.log(`Waiting for response from ${remoteAgent}`); + return; } - - const ledgerBase = utils.getLedgerBase(securityDomain, memberId); - - const localResponderKey = getSecurityDomainMapKey('LOCAL_COUNTER_ATTESTATION_REQUEST', '', nonce); - if (counterAttestationsMap.has(localResponderKey)) { - const requestingMemberCounterAttestation = counterAttestationsMap.get(localResponderKey) as iin_agent_pb.CounterAttestedMembership; - const requestingMember = requestingMemberCounterAttestation.getAttestationsList()[0].getUnitIdentity()!; - const attestedMembershipSetSerialized64 = requestingMemberCounterAttestation.getAttestedMembershipSet(); - - let counterAttestedMembership; - if (errorMsg.length === 0) { - counterAttestedMembership = await ledgerBase.counterAttestMembership(attestedMembershipSetSerialized64, securityDomain, nonce); - } else { - counterAttestedMembership = utils.generateErrorCounterAttestation(errorMsg, securityDomain, memberId, nonce); - } - - const iinAgentClient = utils.getIINAgentClient(requestingMember.getSecurityDomain(), requestingMember.getMemberId()); - iinAgentClient.sendAttestation(counterAttestedMembership, utils.defaultCallback); - counterAttestationsMap.delete(localResponderKey); + let attestedMembershipOrError = securityDomainMap.get(key); + if (typeof attestedMembershipOrError === "string") { + errorMsg = attestedMembershipOrError as string; + } + attestedMembershipOrError = + attestedMembershipOrError as iin_agent_pb.AttestedMembership; + const attestation = attestedMembershipOrError.getAttestation()!; + if (membership === "") { + membership = attestedMembershipOrError.getMembership(); + } else if (membership !== attestedMembershipOrError.getMembership()) { + errorMsg = `received different membership from ${remoteAgent}`; + } + if (!utils.validateAttestedMembership(membership, nonce, attestation)) { + errorMsg = `attested membership from ${remoteAgent} invalid.`; + } + attestations.push(attestation); + } + + const ledgerBase = utils.getLedgerBase(securityDomain, memberId); + + const localResponderKey = getSecurityDomainMapKey( + "LOCAL_COUNTER_ATTESTATION_REQUEST", + "", + nonce, + ); + if (counterAttestationsMap.has(localResponderKey)) { + const requestingMemberCounterAttestation = counterAttestationsMap.get( + localResponderKey, + ) as iin_agent_pb.CounterAttestedMembership; + const requestingMember = requestingMemberCounterAttestation + .getAttestationsList()[0] + .getUnitIdentity()!; + const attestedMembershipSetSerialized64 = + requestingMemberCounterAttestation.getAttestedMembershipSet(); + + let counterAttestedMembership; + if (errorMsg.length === 0) { + counterAttestedMembership = await ledgerBase.counterAttestMembership( + attestedMembershipSetSerialized64, + securityDomain, + nonce, + ); } else { - // Else if Initiator, request counter attestation from other local iin-agents - - if (errorMsg.length === 0) { - const attestedMembershipSet = new iin_agent_pb.CounterAttestedMembership.AttestedMembershipSet(); - attestedMembershipSet.setMembership(membership); - attestedMembershipSet.setAttestationsList(attestations); - const attestedMembershipSetSerialized64 = Buffer.from(attestedMembershipSet.serializeBinary()).toString('base64'); - - console.log('Received Attested Membership Set', JSON.stringify(attestedMembershipSet.toObject())); - - const myCounterAttestedMembership = await ledgerBase.counterAttestMembership(attestedMembershipSetSerialized64, securityDomain, nonce); - - let totalCounterAttesterCount = 0; - const securityDomainDNS = utils.getSecurityDomainDNS(securityDomain); - for (const iinAgent in securityDomainDNS) { - if (iinAgent === memberId) { - continue; - } - const iinAgentClient = utils.getIINAgentClient(securityDomain, iinAgent); - console.log(`Requesting counter attested memberships from: ${securityDomain} - ${iinAgent}`); - iinAgentClient.requestAttestation(myCounterAttestedMembership, utils.defaultCallback); - totalCounterAttesterCount++; - } - if (totalCounterAttesterCount===0) { - const [result, resultError] = await utils.handlePromise( - ledgerBase.recordMembershipInLedger(myCounterAttestedMembership) - ); - - if (resultError) { - console.error('Error submitting counter attested membership to ledger:', resultError); - } else { - console.log(`Succesfully recorded membership of ${remoteSecurityDomain} with result: ${result}`); - } - } else { - localAgentResponseCount.set(nonce, { current:0, total: totalCounterAttesterCount}); - counterAttestationsMap.set(getSecurityDomainMapKey('LOCAL_COUNTER_ATTESTATION_RESPONSE', memberId, nonce), myCounterAttestedMembership); - } + counterAttestedMembership = utils.generateErrorCounterAttestation( + errorMsg, + securityDomain, + memberId, + nonce, + ); + } + + const iinAgentClient = utils.getIINAgentClient( + requestingMember.getSecurityDomain(), + requestingMember.getMemberId(), + ); + iinAgentClient.sendAttestation( + counterAttestedMembership, + utils.defaultCallback, + ); + counterAttestationsMap.delete(localResponderKey); + } else { + // Else if Initiator, request counter attestation from other local iin-agents + + if (errorMsg.length === 0) { + const attestedMembershipSet = + new iin_agent_pb.CounterAttestedMembership.AttestedMembershipSet(); + attestedMembershipSet.setMembership(membership); + attestedMembershipSet.setAttestationsList(attestations); + const attestedMembershipSetSerialized64 = Buffer.from( + attestedMembershipSet.serializeBinary(), + ).toString("base64"); + + console.log( + "Received Attested Membership Set", + JSON.stringify(attestedMembershipSet.toObject()), + ); + + const myCounterAttestedMembership = + await ledgerBase.counterAttestMembership( + attestedMembershipSetSerialized64, + securityDomain, + nonce, + ); + + let totalCounterAttesterCount = 0; + const securityDomainDNS = utils.getSecurityDomainDNS(securityDomain); + for (const iinAgent in securityDomainDNS) { + if (iinAgent === memberId) { + continue; + } + const iinAgentClient = utils.getIINAgentClient( + securityDomain, + iinAgent, + ); + console.log( + `Requesting counter attested memberships from: ${securityDomain} - ${iinAgent}`, + ); + iinAgentClient.requestAttestation( + myCounterAttestedMembership, + utils.defaultCallback, + ); + totalCounterAttesterCount++; + } + if (totalCounterAttesterCount === 0) { + const [result, resultError] = await utils.handlePromise( + ledgerBase.recordMembershipInLedger(myCounterAttestedMembership), + ); + + if (resultError) { + console.error( + "Error submitting counter attested membership to ledger:", + resultError, + ); } else { - console.error('Error while fetching attested membership from foreign network:', errorMsg); - return; + console.log( + `Succesfully recorded membership of ${remoteSecurityDomain} with result: ${result}`, + ); } + } else { + localAgentResponseCount.set(nonce, { + current: 0, + total: totalCounterAttesterCount, + }); + counterAttestationsMap.set( + getSecurityDomainMapKey( + "LOCAL_COUNTER_ATTESTATION_RESPONSE", + memberId, + nonce, + ), + myCounterAttestedMembership, + ); + } + } else { + console.error( + "Error while fetching attested membership from foreign network:", + errorMsg, + ); + return; } - - // Cleanup maps - foreignAgentResponseCount.delete(nonce); - for (const remoteAgent in remoteSecurityDomainDNS) { - const key = getSecurityDomainMapKey(remoteSecurityDomain, remoteAgent, nonce); - securityDomainMap.delete(key); - } + } + + // Cleanup maps + foreignAgentResponseCount.delete(nonce); + for (const remoteAgent in remoteSecurityDomainDNS) { + const key = getSecurityDomainMapKey( + remoteSecurityDomain, + remoteAgent, + nonce, + ); + securityDomainMap.delete(key); + } }; diff --git a/weaver/core/identity-management/iin-agent/src/protocols/localOperations.ts b/weaver/core/identity-management/iin-agent/src/protocols/localOperations.ts index 6413e7e431..b4b8d82f34 100644 --- a/weaver/core/identity-management/iin-agent/src/protocols/localOperations.ts +++ b/weaver/core/identity-management/iin-agent/src/protocols/localOperations.ts @@ -4,35 +4,46 @@ * SPDX-License-Identifier: Apache-2.0 */ -import iin_agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; -import * as utils from '../common/utils'; -import { localAgentResponseCount, counterAttestationsMap, getSecurityDomainMapKey, securityDomainMap, foreignAgentResponseCount} from './externalOperations'; +import iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; +import * as utils from "../common/utils"; +import { + localAgentResponseCount, + counterAttestationsMap, + getSecurityDomainMapKey, + securityDomainMap, + foreignAgentResponseCount, +} from "./externalOperations"; // import { handlePromise, getLedgerBase, getIINAgentClient, getSecurityDomainDNS, defaultCallback, delay } from '../common/utils'; -import { LedgerBase } from '../common/ledgerBase'; +import { LedgerBase } from "../common/ledgerBase"; import { v4 as uuidv4 } from "uuid"; - // Generates attestations on a foreign security domain unit's state -export const requestAttestation = async (counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, localSecurityDomain: string, localMemberId: string, refreshTime: number) => { - +export const requestAttestation = async ( + counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, + localSecurityDomain: string, + localMemberId: string, + refreshTime: number, +) => { // create local security domain - const localSecurityDomainUnit = new iin_agent_pb.SecurityDomainMemberIdentity(); + const localSecurityDomainUnit = + new iin_agent_pb.SecurityDomainMemberIdentity(); localSecurityDomainUnit.setSecurityDomain(localSecurityDomain); localSecurityDomainUnit.setMemberId(localMemberId); // get counterattestations from requester const counterAttestations = counterAttestedMembership.getAttestationsList(); const nonce = counterAttestations[0].getNonce(); - const attestedMembershipSet = utils.deserializeAttestedMembershipSet64(counterAttestedMembership.getAttestedMembershipSet()); + const attestedMembershipSet = utils.deserializeAttestedMembershipSet64( + counterAttestedMembership.getAttestedMembershipSet(), + ); const membership = attestedMembershipSet.getMembership(); const attestations = attestedMembershipSet.getAttestationsList(); - let counter = 0; let errorMsg = ""; - for(const attestation of attestations){ + for (const attestation of attestations) { // validate foreign attestation - if(!(utils.validateAttestedMembership(membership, nonce, attestation))){ + if (!utils.validateAttestedMembership(membership, nonce, attestation)) { errorMsg = "Invalid attestation by foreign member on the membership"; break; } @@ -41,13 +52,17 @@ export const requestAttestation = async (counterAttestedMembership: iin_agent_pb const remoteSecurityDomainUnit = attestation.getUnitIdentity(); const remoteSecurityDomain = remoteSecurityDomainUnit.getSecurityDomain(); const remoteMemberID = remoteSecurityDomainUnit.getMemberId(); - const remoteSecurityDomainDNS = utils.getSecurityDomainDNS(remoteSecurityDomain); + const remoteSecurityDomainDNS = + utils.getSecurityDomainDNS(remoteSecurityDomain); // fetch cached membership info of foreign IIN agent from local cache - let key = getSecurityDomainMapKey(remoteSecurityDomain, remoteMemberID); + const key = getSecurityDomainMapKey(remoteSecurityDomain, remoteMemberID); const attestedMembershipOrError = securityDomainMap.get(key); // if membership info is not in cache - if (!attestedMembershipOrError || typeof attestedMembershipOrError === "string"){ + if ( + !attestedMembershipOrError || + typeof attestedMembershipOrError === "string" + ) { // fetch fresh membership info (move to a separate function) // create a request const request = new iin_agent_pb.SecurityDomainMemberIdentityRequest(); @@ -55,18 +70,26 @@ export const requestAttestation = async (counterAttestedMembership: iin_agent_pb request.setRequestingNetwork(localSecurityDomainUnit); request.setNonce(nonce); // get remote iinagentclient - const remoteIINAgentClient = utils.getIINAgentClient(remoteSecurityDomain, remoteMemberID, remoteSecurityDomainDNS); + const remoteIINAgentClient = utils.getIINAgentClient( + remoteSecurityDomain, + remoteMemberID, + remoteSecurityDomainDNS, + ); // request identity configuration from remote iinagentclient - remoteIINAgentClient.requestIdentityConfiguration(request, utils.defaultCallback); + remoteIINAgentClient.requestIdentityConfiguration( + request, + utils.defaultCallback, + ); counter++; - } - else{ + } else { // get timestamp corresponding to cached membership info const attestationCached = attestedMembershipOrError.getAttestation(); const timeStampCached = attestationCached.getTimestamp(); const timeStampCurrent = Date.now(); // if cached timestamp is outdated - if (Math.floor((timeStampCurrent - timeStampCached)/1000) > refreshTime){ + if ( + Math.floor((timeStampCurrent - timeStampCached) / 1000) > refreshTime + ) { // fetch fresh membership info (move to a separate function) // create a request const request = new iin_agent_pb.SecurityDomainMemberIdentityRequest(); @@ -74,173 +97,290 @@ export const requestAttestation = async (counterAttestedMembership: iin_agent_pb request.setRequestingNetwork(localSecurityDomainUnit); request.setNonce(nonce); // get remote iinagentclient - const remoteIINAgentClient = utils.getIINAgentClient(remoteSecurityDomain, remoteMemberID, remoteSecurityDomainDNS); + const remoteIINAgentClient = utils.getIINAgentClient( + remoteSecurityDomain, + remoteMemberID, + remoteSecurityDomainDNS, + ); // request identity configuration from remote iinagentclient - remoteIINAgentClient.requestIdentityConfiguration(request, utils.defaultCallback); + remoteIINAgentClient.requestIdentityConfiguration( + request, + utils.defaultCallback, + ); counter++; - } - else{ + } else { // match membership - if(membership != attestedMembershipOrError.getMembership()){ + if (membership != attestedMembershipOrError.getMembership()) { errorMsg = "Membership mismatch"; break; } } } } - const requesterMemberID = counterAttestations[0].getUnitIdentity()!.getMemberId(); - if(counter > 0){ - foreignAgentResponseCount.set(nonce, { current:0, total: counter}); - const key = getSecurityDomainMapKey('LOCAL_COUNTER_ATTESTATION_REQUEST', '', nonce); + const requesterMemberID = counterAttestations[0] + .getUnitIdentity()! + .getMemberId(); + if (counter > 0) { + foreignAgentResponseCount.set(nonce, { current: 0, total: counter }); + const key = getSecurityDomainMapKey( + "LOCAL_COUNTER_ATTESTATION_REQUEST", + "", + nonce, + ); counterAttestationsMap.set(key, counterAttestedMembership); console.log("Requested fresh membership from foreign agent"); return; } // get iinagentclient for the requester - const requesterSecurityDomain = counterAttestations[0].getUnitIdentity()!.getSecurityDomain(); - const requesterSecurityDomainDNS = utils.getSecurityDomainDNS(requesterSecurityDomain); - const requesterIINAgentClient = utils.getIINAgentClient(requesterSecurityDomain, requesterMemberID, requesterSecurityDomainDNS); - if(errorMsg != ""){ + const requesterSecurityDomain = counterAttestations[0] + .getUnitIdentity()! + .getSecurityDomain(); + const requesterSecurityDomainDNS = utils.getSecurityDomainDNS( + requesterSecurityDomain, + ); + const requesterIINAgentClient = utils.getIINAgentClient( + requesterSecurityDomain, + requesterMemberID, + requesterSecurityDomainDNS, + ); + if (errorMsg != "") { // send the error back to the requester - const errorCounterAttestedMembership = utils.generateErrorCounterAttestation(errorMsg, localSecurityDomain, localMemberId, nonce); - requesterIINAgentClient.sendAttestation(errorCounterAttestedMembership, utils.defaultCallback); - } - else{ + const errorCounterAttestedMembership = + utils.generateErrorCounterAttestation( + errorMsg, + localSecurityDomain, + localMemberId, + nonce, + ); + requesterIINAgentClient.sendAttestation( + errorCounterAttestedMembership, + utils.defaultCallback, + ); + } else { // create new attestations on foreign security domain's state info sent by requester - const localLedgerBase = utils.getLedgerBase(localSecurityDomain, localMemberId); - const localCounterAttestedMembership = await localLedgerBase.counterAttestMembership(counterAttestedMembership.getAttestedMembershipSet(), localSecurityDomain, nonce); + const localLedgerBase = utils.getLedgerBase( + localSecurityDomain, + localMemberId, + ); + const localCounterAttestedMembership = + await localLedgerBase.counterAttestMembership( + counterAttestedMembership.getAttestedMembershipSet(), + localSecurityDomain, + nonce, + ); // send attestation back to requester - requesterIINAgentClient.sendAttestation(localCounterAttestedMembership, utils.defaultCallback); + requesterIINAgentClient.sendAttestation( + localCounterAttestedMembership, + utils.defaultCallback, + ); } }; -export function sendAttestation(counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, securityDomain: string, memberId: string) { - // Assuming only one counter attestation in the list - const attestation = counterAttestedMembership.getAttestationsList()[0]; - if (!attestation.hasUnitIdentity()) { - const errorMsg = 'attestation has no SecurityDomainMemberIdentity associated with it'; - console.error('Error: ' + errorMsg); - throw new Error(errorMsg); - } +export function sendAttestation( + counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, + securityDomain: string, + memberId: string, +) { + // Assuming only one counter attestation in the list + const attestation = counterAttestedMembership.getAttestationsList()[0]; + if (!attestation.hasUnitIdentity()) { + const errorMsg = + "attestation has no SecurityDomainMemberIdentity associated with it"; + console.error("Error: " + errorMsg); + throw new Error(errorMsg); + } - const securityDomainUnit = attestation.getUnitIdentity()!; - const peerAgentMemberId = securityDomainUnit.getMemberId(); - if (securityDomain !== securityDomainUnit.getSecurityDomain()) { - const errorMsg = `received counter attestation from different security domain's member '${peerAgentMemberId}'. Expected: ${securityDomain}, Received: ${securityDomainUnit.getSecurityDomain()}`; - console.error('Error: ' + errorMsg); - throw new Error(errorMsg); - } + const securityDomainUnit = attestation.getUnitIdentity()!; + const peerAgentMemberId = securityDomainUnit.getMemberId(); + if (securityDomain !== securityDomainUnit.getSecurityDomain()) { + const errorMsg = `received counter attestation from different security domain's member '${peerAgentMemberId}'. Expected: ${securityDomain}, Received: ${securityDomainUnit.getSecurityDomain()}`; + console.error("Error: " + errorMsg); + throw new Error(errorMsg); + } - const nonce = attestation.getNonce(); - const localKey = getSecurityDomainMapKey('LOCAL_COUNTER_ATTESTATION_RESPONSE', memberId, nonce); - if (!(counterAttestationsMap.has(localKey) && localAgentResponseCount.has(nonce))) { - const errorMsg = `not expecting any response with received nonce: ${nonce}`; - console.error('Error: ' + errorMsg); - throw new Error(errorMsg); - } - sendAttestationHelper(counterAttestedMembership, securityDomain, memberId, peerAgentMemberId, nonce).then().catch((error) => { - console.error("SendAttestationHelper Error:", error); + const nonce = attestation.getNonce(); + const localKey = getSecurityDomainMapKey( + "LOCAL_COUNTER_ATTESTATION_RESPONSE", + memberId, + nonce, + ); + if ( + !( + counterAttestationsMap.has(localKey) && localAgentResponseCount.has(nonce) + ) + ) { + const errorMsg = `not expecting any response with received nonce: ${nonce}`; + console.error("Error: " + errorMsg); + throw new Error(errorMsg); + } + sendAttestationHelper( + counterAttestedMembership, + securityDomain, + memberId, + peerAgentMemberId, + nonce, + ) + .then() + .catch((error) => { + console.error("SendAttestationHelper Error:", error); }); } // Processes attestations on a foreign security domain unit's state received from a local IIN agent -const sendAttestationHelper = async (counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, securityDomain: string, memberId: string, peerAgentMemberId: string, nonce: string) => { - const attestation = counterAttestedMembership.getAttestationsList()[0]; - - const localKey = getSecurityDomainMapKey('LOCAL_COUNTER_ATTESTATION_RESPONSE', memberId, nonce); - const myCounterAttestedMembership = counterAttestationsMap.get(localKey) as iin_agent_pb.CounterAttestedMembership; - const attestedMembershipSet64 = myCounterAttestedMembership.getAttestedMembershipSet(); - const attestedMembershipSet = iin_agent_pb.CounterAttestedMembership.AttestedMembershipSet.deserializeBinary( - Buffer.from(attestedMembershipSet64, 'base64') +const sendAttestationHelper = async ( + counterAttestedMembership: iin_agent_pb.CounterAttestedMembership, + securityDomain: string, + memberId: string, + peerAgentMemberId: string, + nonce: string, +) => { + const attestation = counterAttestedMembership.getAttestationsList()[0]; + + const localKey = getSecurityDomainMapKey( + "LOCAL_COUNTER_ATTESTATION_RESPONSE", + memberId, + nonce, + ); + const myCounterAttestedMembership = counterAttestationsMap.get( + localKey, + ) as iin_agent_pb.CounterAttestedMembership; + const attestedMembershipSet64 = + myCounterAttestedMembership.getAttestedMembershipSet(); + const attestedMembershipSet = + iin_agent_pb.CounterAttestedMembership.AttestedMembershipSet.deserializeBinary( + Buffer.from(attestedMembershipSet64, "base64"), ); - const remoteSecurityDomain = attestedMembershipSet.getAttestationsList()[0].getUnitIdentity()!.getSecurityDomain(); + const remoteSecurityDomain = attestedMembershipSet + .getAttestationsList()[0] + .getUnitIdentity()! + .getSecurityDomain(); - const counterAttestationsMapKey = getSecurityDomainMapKey(remoteSecurityDomain, peerAgentMemberId, nonce); - console.log('sendAttestation:', peerAgentMemberId, '-', nonce, 'for remote security domain', remoteSecurityDomain); - try { - if (counterAttestedMembership.hasError()) { - throw new Error(counterAttestedMembership.getError()); - } - if (attestation.getCertificate().length == 0) { - throw new Error('attestation has no certificate'); - } - if (attestation.getSignature().length == 0) { - throw new Error('attestation has no signature'); - } - counterAttestationsMap.set(counterAttestationsMapKey, counterAttestedMembership); - } catch (e) { - const errorMsg = `${e} from Local iin-agent with MemberId: ${peerAgentMemberId}, Nonce: ${nonce}`; - console.error(errorMsg); - counterAttestationsMap.set(counterAttestationsMapKey, errorMsg); + const counterAttestationsMapKey = getSecurityDomainMapKey( + remoteSecurityDomain, + peerAgentMemberId, + nonce, + ); + console.log( + "sendAttestation:", + peerAgentMemberId, + "-", + nonce, + "for remote security domain", + remoteSecurityDomain, + ); + try { + if (counterAttestedMembership.hasError()) { + throw new Error(counterAttestedMembership.getError()); } - const currLocalAgentResponsesCount = localAgentResponseCount.get(nonce).current; - const totalLocalAgentResponsesCount = localAgentResponseCount.get(nonce).total; - localAgentResponseCount.set(nonce, { current: currLocalAgentResponsesCount + 1, total: totalLocalAgentResponsesCount }); - - if (currLocalAgentResponsesCount + 1 < totalLocalAgentResponsesCount) { - // Pending respones from other foreign iin-agents - return; + if (attestation.getCertificate().length == 0) { + throw new Error("attestation has no certificate"); } - if (currLocalAgentResponsesCount + 1 > totalLocalAgentResponsesCount) { - console.warn('Warning: Received extra responses.'); + if (attestation.getSignature().length == 0) { + throw new Error("attestation has no signature"); } + counterAttestationsMap.set( + counterAttestationsMapKey, + counterAttestedMembership, + ); + } catch (e) { + const errorMsg = `${e} from Local iin-agent with MemberId: ${peerAgentMemberId}, Nonce: ${nonce}`; + console.error(errorMsg); + counterAttestationsMap.set(counterAttestationsMapKey, errorMsg); + } + const currLocalAgentResponsesCount = + localAgentResponseCount.get(nonce).current; + const totalLocalAgentResponsesCount = + localAgentResponseCount.get(nonce).total; + localAgentResponseCount.set(nonce, { + current: currLocalAgentResponsesCount + 1, + total: totalLocalAgentResponsesCount, + }); - // Group Counter Attestations - let counterAttestations = myCounterAttestedMembership.getAttestationsList(); - const securityDomainDNS = utils.getSecurityDomainDNS(securityDomain); - let errorMsg = ''; - for (const localAgent in securityDomainDNS) { - if (localAgent === memberId) { - continue; - } - const key = getSecurityDomainMapKey(remoteSecurityDomain, localAgent, nonce); - if (!counterAttestationsMap.has(key)) { - // count completed but still some foreign agents haven't responded. - console.log(`Waiting for response from ${localAgent}`); - return; - } - let counterAttestedMembershipOrError = counterAttestationsMap.get(key); - if (typeof counterAttestedMembershipOrError === "string") { - errorMsg = counterAttestedMembershipOrError as string; - } - counterAttestedMembershipOrError = counterAttestedMembershipOrError as iin_agent_pb.CounterAttestedMembership; - const attestation = counterAttestedMembershipOrError.getAttestationsList()[0]; - if (nonce !== attestation.getNonce()) { - errorMsg = `received different nonce value in attestation from ${localAgent}. Expected: ${nonce}, Received: ${attestation.getNonce()}`; - } - if (attestedMembershipSet64 !== counterAttestedMembershipOrError.getAttestedMembershipSet()) { - errorMsg = `received different attested membership set from ${memberId}`; - } - counterAttestations.push(attestation); + if (currLocalAgentResponsesCount + 1 < totalLocalAgentResponsesCount) { + // Pending respones from other foreign iin-agents + return; + } + if (currLocalAgentResponsesCount + 1 > totalLocalAgentResponsesCount) { + console.warn("Warning: Received extra responses."); + } + + // Group Counter Attestations + const counterAttestations = myCounterAttestedMembership.getAttestationsList(); + const securityDomainDNS = utils.getSecurityDomainDNS(securityDomain); + let errorMsg = ""; + for (const localAgent in securityDomainDNS) { + if (localAgent === memberId) { + continue; + } + const key = getSecurityDomainMapKey( + remoteSecurityDomain, + localAgent, + nonce, + ); + if (!counterAttestationsMap.has(key)) { + // count completed but still some foreign agents haven't responded. + console.log(`Waiting for response from ${localAgent}`); + return; } + let counterAttestedMembershipOrError = counterAttestationsMap.get(key); + if (typeof counterAttestedMembershipOrError === "string") { + errorMsg = counterAttestedMembershipOrError as string; + } + counterAttestedMembershipOrError = + counterAttestedMembershipOrError as iin_agent_pb.CounterAttestedMembership; + const attestation = + counterAttestedMembershipOrError.getAttestationsList()[0]; + if (nonce !== attestation.getNonce()) { + errorMsg = `received different nonce value in attestation from ${localAgent}. Expected: ${nonce}, Received: ${attestation.getNonce()}`; + } + if ( + attestedMembershipSet64 !== + counterAttestedMembershipOrError.getAttestedMembershipSet() + ) { + errorMsg = `received different attested membership set from ${memberId}`; + } + counterAttestations.push(attestation); + } - if (errorMsg.length===0) { - myCounterAttestedMembership.setAttestationsList(counterAttestations); - console.log('Received Counter Attested Membership', JSON.stringify(counterAttestedMembership.toObject())); + if (errorMsg.length === 0) { + myCounterAttestedMembership.setAttestationsList(counterAttestations); + console.log( + "Received Counter Attested Membership", + JSON.stringify(counterAttestedMembership.toObject()), + ); - // Submit record membership tx to ledger - const ledgerBase = utils.getLedgerBase(securityDomain, memberId); - const [result, resultError] = await utils.handlePromise( - ledgerBase.recordMembershipInLedger(myCounterAttestedMembership) - ); + // Submit record membership tx to ledger + const ledgerBase = utils.getLedgerBase(securityDomain, memberId); + const [result, resultError] = await utils.handlePromise( + ledgerBase.recordMembershipInLedger(myCounterAttestedMembership), + ); - if (resultError) { - console.error('Error submitting counter attested membership to ledger:', resultError); - } else { - console.log(`Succesfully recorded membership of ${remoteSecurityDomain} with result: ${result}`); - } + if (resultError) { + console.error( + "Error submitting counter attested membership to ledger:", + resultError, + ); } else { - console.error(`Sync Remote Membership Failed with error: ${errorMsg}`); + console.log( + `Succesfully recorded membership of ${remoteSecurityDomain} with result: ${result}`, + ); } + } else { + console.error(`Sync Remote Membership Failed with error: ${errorMsg}`); + } - // End of protocol for iin-agents: Map cleanup - counterAttestationsMap.delete(localKey); - localAgentResponseCount.delete(nonce); - for (const localAgent in securityDomainDNS) { - if (localAgent === memberId) { - continue; - } - const key = getSecurityDomainMapKey(remoteSecurityDomain, localAgent, nonce); - counterAttestationsMap.delete(key); + // End of protocol for iin-agents: Map cleanup + counterAttestationsMap.delete(localKey); + localAgentResponseCount.delete(nonce); + for (const localAgent in securityDomainDNS) { + if (localAgent === memberId) { + continue; } + const key = getSecurityDomainMapKey( + remoteSecurityDomain, + localAgent, + nonce, + ); + counterAttestationsMap.delete(key); + } }; diff --git a/weaver/core/identity-management/iin-agent/src/server.ts b/weaver/core/identity-management/iin-agent/src/server.ts index 888ceb43de..b097a415df 100644 --- a/weaver/core/identity-management/iin-agent/src/server.ts +++ b/weaver/core/identity-management/iin-agent/src/server.ts @@ -4,222 +4,316 @@ * SPDX-License-Identifier: Apache-2.0 */ -import fs from 'fs'; -import { Server, ServerCredentials, credentials } from '@grpc/grpc-js'; -import ack_pb from '@hyperledger/cacti-weaver-protos-js/common/ack_pb'; -import iin_agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; -import iin_agent_pb_grpc from '@hyperledger/cacti-weaver-protos-js/identity/agent_grpc_pb'; -import 'dotenv/config'; -import { Certificate } from '@fidm/x509'; -import * as path from 'path'; -import { syncExternalStateFromIINAgent, requestIdentityConfiguration, sendIdentityConfiguration } from './protocols/externalOperations'; -import { requestAttestation, sendAttestation } from './protocols/localOperations'; -import { getLedgerBase, delay, getAllRemoteSecurityDomainDNS } from './common/utils' - +import fs from "fs"; +import { Server, ServerCredentials, credentials } from "@grpc/grpc-js"; +import ack_pb from "@hyperledger/cacti-weaver-protos-js/common/ack_pb"; +import iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; +import iin_agent_pb_grpc from "@hyperledger/cacti-weaver-protos-js/identity/agent_grpc_pb"; +import "dotenv/config"; +import { Certificate } from "@fidm/x509"; +import * as path from "path"; +import { + syncExternalStateFromIINAgent, + requestIdentityConfiguration, + sendIdentityConfiguration, +} from "./protocols/externalOperations"; +import { + requestAttestation, + sendAttestation, +} from "./protocols/localOperations"; +import { + getLedgerBase, + delay, + getAllRemoteSecurityDomainDNS, +} from "./common/utils"; const iinAgentServer = new Server(); -console.log('iin agent def', JSON.stringify(iin_agent_pb_grpc)); +console.log("iin agent def", JSON.stringify(iin_agent_pb_grpc)); //@ts-ignore iinAgentServer.addService(iin_agent_pb_grpc.IINAgentService, { - // Service for syncing foreign security domain unit's state from its IIN agent. Will communicate with the user/agent triggering this process and respond with an ack to the caller while the sync is occurring. - syncExternalState: (call: { request: iin_agent_pb.SecurityDomainMemberIdentity }, callback: (_: any, object: ack_pb.Ack) => void) => { - const ack_response = new ack_pb.Ack(); - try { - const securityDomain = process.env.SECURITY_DOMAIN ? process.env.SECURITY_DOMAIN : 'network1'; - const memberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : 'Org1MSP'; - const nonce = syncExternalStateFromIINAgent(call.request, securityDomain, memberId); - ack_response.setMessage(''); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - ack_response.setRequestId(nonce); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } catch (e) { - console.log(e); - ack_response.setMessage(`Error: ${e}`); - ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); - ack_response.setRequestId(''); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } - }, - // Service for receiving requests for one's security domain unit's state from foreign IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being generated. - requestIdentityConfiguration: (call: { request: iin_agent_pb.SecurityDomainMemberIdentityRequest }, callback: (_: any, object: ack_pb.Ack) => void) => { - const ack_response = new ack_pb.Ack(); - try { - if (!call.request.hasSourceNetwork()) { - throw new Error('request does not have source network'); - } - if (!call.request.hasRequestingNetwork()) { - throw new Error('request does not have requesting network'); - } - if (call.request.getNonce().length == 0) { - throw new Error('request has empty nonce'); - } - requestIdentityConfiguration(call.request).then().catch((error) => { - console.error("Error:", error); - }); - ack_response.setMessage(''); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - ack_response.setRequestId(call.request.getNonce()); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } catch (e) { - console.log(e); - ack_response.setMessage(`Error: ${e}`); - ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); - ack_response.setRequestId(call.request.getNonce()); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } - }, - // Service for receiving security domain unit states from foreign IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being processed. - sendIdentityConfiguration: (call: { request: iin_agent_pb.AttestedMembership }, callback: (_: any, object: ack_pb.Ack) => void) => { - const ack_response = new ack_pb.Ack(); - let nonce = ''; - try { - const securityDomain = process.env.SECURITY_DOMAIN ? process.env.SECURITY_DOMAIN : 'network1'; - const memberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : 'Org1MSP'; - if (!call.request.hasAttestation()) { - throw new Error('no attestation provided'); - } - nonce = call.request.getAttestation().getNonce(); - sendIdentityConfiguration(call.request, securityDomain, memberId); - ack_response.setMessage(''); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - ack_response.setRequestId(nonce); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } catch (e) { - console.log(e); - ack_response.setMessage(`Error: ${e}`); - ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); - ack_response.setRequestId(nonce); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } - }, - // Service for receiving requests for attestations on foreign security domain unit states from local IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being generated. - requestAttestation: (call: { request: iin_agent_pb.CounterAttestedMembership }, callback: (_: any, object: ack_pb.Ack) => void) => { - const ack_response = new ack_pb.Ack(); - try { - const securityDomain = process.env.SECURITY_DOMAIN ? process.env.SECURITY_DOMAIN : 'network1'; - const memberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : 'Org1MSP'; - const attestationValidityTime = process.env.ATTESTATION_VALIDITY_TIME ? parseInt(process.env.ATTESTATION_VALIDITY_TIME) : 3600; - requestAttestation(call.request, securityDomain, memberId, attestationValidityTime); - ack_response.setMessage(''); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - ack_response.setRequestId(''); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } catch (e) { - console.log(e); - ack_response.setMessage(`Error: ${e}`); - ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); - ack_response.setRequestId(''); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } - }, - // Service for receiving attestations on foreign security domain unit states from local IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being processed. - sendAttestation: (call: { request: iin_agent_pb.CounterAttestedMembership }, callback: (_: any, object: ack_pb.Ack) => void) => { - const ack_response = new ack_pb.Ack(); - let nonce = ''; - try { - const securityDomain = process.env.SECURITY_DOMAIN ? process.env.SECURITY_DOMAIN : 'network1'; - const memberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : 'Org1MSP'; - if (call.request.getAttestationsList().length === 0) { - throw new Error('no counter attestation provided'); - } - nonce = call.request.getAttestationsList()[0].getNonce(); - sendAttestation(call.request, securityDomain, memberId); - ack_response.setMessage(''); - ack_response.setStatus(ack_pb.Ack.STATUS.OK); - ack_response.setRequestId(nonce); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } catch (e) { - console.log(e); - ack_response.setMessage(`Error: ${e}`); - ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); - ack_response.setRequestId(nonce); - // gRPC response. - console.log('Responding to caller'); - callback(null, ack_response); - } - }, + // Service for syncing foreign security domain unit's state from its IIN agent. Will communicate with the user/agent triggering this process and respond with an ack to the caller while the sync is occurring. + syncExternalState: ( + call: { request: iin_agent_pb.SecurityDomainMemberIdentity }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const ack_response = new ack_pb.Ack(); + try { + const securityDomain = process.env.SECURITY_DOMAIN + ? process.env.SECURITY_DOMAIN + : "network1"; + const memberId = process.env.MEMBER_ID + ? process.env.MEMBER_ID + : "Org1MSP"; + const nonce = syncExternalStateFromIINAgent( + call.request, + securityDomain, + memberId, + ); + ack_response.setMessage(""); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + ack_response.setRequestId(nonce); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } catch (e) { + console.log(e); + ack_response.setMessage(`Error: ${e}`); + ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); + ack_response.setRequestId(""); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } + }, + // Service for receiving requests for one's security domain unit's state from foreign IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being generated. + requestIdentityConfiguration: ( + call: { request: iin_agent_pb.SecurityDomainMemberIdentityRequest }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const ack_response = new ack_pb.Ack(); + try { + if (!call.request.hasSourceNetwork()) { + throw new Error("request does not have source network"); + } + if (!call.request.hasRequestingNetwork()) { + throw new Error("request does not have requesting network"); + } + if (call.request.getNonce().length == 0) { + throw new Error("request has empty nonce"); + } + requestIdentityConfiguration(call.request) + .then() + .catch((error) => { + console.error("Error:", error); + }); + ack_response.setMessage(""); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + ack_response.setRequestId(call.request.getNonce()); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } catch (e) { + console.log(e); + ack_response.setMessage(`Error: ${e}`); + ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); + ack_response.setRequestId(call.request.getNonce()); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } + }, + // Service for receiving security domain unit states from foreign IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being processed. + sendIdentityConfiguration: ( + call: { request: iin_agent_pb.AttestedMembership }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const ack_response = new ack_pb.Ack(); + let nonce = ""; + try { + const securityDomain = process.env.SECURITY_DOMAIN + ? process.env.SECURITY_DOMAIN + : "network1"; + const memberId = process.env.MEMBER_ID + ? process.env.MEMBER_ID + : "Org1MSP"; + if (!call.request.hasAttestation()) { + throw new Error("no attestation provided"); + } + nonce = call.request.getAttestation().getNonce(); + sendIdentityConfiguration(call.request, securityDomain, memberId); + ack_response.setMessage(""); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + ack_response.setRequestId(nonce); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } catch (e) { + console.log(e); + ack_response.setMessage(`Error: ${e}`); + ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); + ack_response.setRequestId(nonce); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } + }, + // Service for receiving requests for attestations on foreign security domain unit states from local IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being generated. + requestAttestation: ( + call: { request: iin_agent_pb.CounterAttestedMembership }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const ack_response = new ack_pb.Ack(); + try { + const securityDomain = process.env.SECURITY_DOMAIN + ? process.env.SECURITY_DOMAIN + : "network1"; + const memberId = process.env.MEMBER_ID + ? process.env.MEMBER_ID + : "Org1MSP"; + const attestationValidityTime = process.env.ATTESTATION_VALIDITY_TIME + ? parseInt(process.env.ATTESTATION_VALIDITY_TIME) + : 3600; + requestAttestation( + call.request, + securityDomain, + memberId, + attestationValidityTime, + ); + ack_response.setMessage(""); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + ack_response.setRequestId(""); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } catch (e) { + console.log(e); + ack_response.setMessage(`Error: ${e}`); + ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); + ack_response.setRequestId(""); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } + }, + // Service for receiving attestations on foreign security domain unit states from local IIN agents. Will communicate with the IIN agent caller and respond with an ack while the attestation is being processed. + sendAttestation: ( + call: { request: iin_agent_pb.CounterAttestedMembership }, + callback: (_: any, object: ack_pb.Ack) => void, + ) => { + const ack_response = new ack_pb.Ack(); + let nonce = ""; + try { + const securityDomain = process.env.SECURITY_DOMAIN + ? process.env.SECURITY_DOMAIN + : "network1"; + const memberId = process.env.MEMBER_ID + ? process.env.MEMBER_ID + : "Org1MSP"; + if (call.request.getAttestationsList().length === 0) { + throw new Error("no counter attestation provided"); + } + nonce = call.request.getAttestationsList()[0].getNonce(); + sendAttestation(call.request, securityDomain, memberId); + ack_response.setMessage(""); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + ack_response.setRequestId(nonce); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } catch (e) { + console.log(e); + ack_response.setMessage(`Error: ${e}`); + ack_response.setStatus(ack_pb.Ack.STATUS.ERROR); + ack_response.setRequestId(nonce); + // gRPC response. + console.log("Responding to caller"); + callback(null, ack_response); + } + }, }); // Bootstrapping const configSetup = async () => { - // Initiate agent's ledger - const securityDomain = process.env.SECURITY_DOMAIN ? process.env.SECURITY_DOMAIN : 'network1'; - const memberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : 'Org1MSP'; - const ledgerBase = getLedgerBase(securityDomain, memberId); - await ledgerBase.init(); - console.log("Setup compelete."); + // Initiate agent's ledger + const securityDomain = process.env.SECURITY_DOMAIN + ? process.env.SECURITY_DOMAIN + : "network1"; + const memberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : "Org1MSP"; + const ledgerBase = getLedgerBase(securityDomain, memberId); + await ledgerBase.init(); + console.log("Setup compelete."); - // TODO + // TODO }; const loopSyncExternalState = async () => { - const delayTime: number = parseInt(process.env.SYNC_PERIOD ? process.env.SYNC_PERIOD : '3600'); - console.log("SYNC PERIOD: ", delayTime); - const localSecurityDomain = process.env.SECURITY_DOMAIN ? process.env.SECURITY_DOMAIN : 'network1'; - const localMemberId = process.env.MEMBER_ID ? process.env.MEMBER_ID : 'Org1MSP'; - const flagSync = process.env.AUTO_SYNC === 'false' ? false : true; - if (flagSync) { - console.log("Starting auto sync..."); - } else { - console.log("Auto sync off."); + const delayTime: number = parseInt( + process.env.SYNC_PERIOD ? process.env.SYNC_PERIOD : "3600", + ); + console.log("SYNC PERIOD: ", delayTime); + const localSecurityDomain = process.env.SECURITY_DOMAIN + ? process.env.SECURITY_DOMAIN + : "network1"; + const localMemberId = process.env.MEMBER_ID + ? process.env.MEMBER_ID + : "Org1MSP"; + const flagSync = process.env.AUTO_SYNC === "false" ? false : true; + if (flagSync) { + console.log("Starting auto sync..."); + } else { + console.log("Auto sync off."); + } + while (flagSync) { + const secDomDNS = getAllRemoteSecurityDomainDNS(localSecurityDomain); + for (const securityDomain in secDomDNS) { + const foreignSecurityDomain = + new iin_agent_pb.SecurityDomainMemberIdentity(); + foreignSecurityDomain.setSecurityDomain(securityDomain); + syncExternalStateFromIINAgent( + foreignSecurityDomain, + localSecurityDomain, + localMemberId, + ); } - while (flagSync) { - const secDomDNS = getAllRemoteSecurityDomainDNS(localSecurityDomain); - for (const securityDomain in secDomDNS) { - const foreignSecurityDomain = new iin_agent_pb.SecurityDomainMemberIdentity(); - foreignSecurityDomain.setSecurityDomain(securityDomain); - syncExternalStateFromIINAgent(foreignSecurityDomain, localSecurityDomain, localMemberId); - } - await delay(delayTime * 1000); - } -} + await delay(delayTime * 1000); + } +}; // SERVER: Start the IIN agent server with the provided url. -if (process.env.IIN_AGENT_TLS === 'true') { - if (!(process.env.IIN_AGENT_TLS_CERT_PATH && fs.existsSync(process.env.IIN_AGENT_TLS_CERT_PATH) && - (process.env.IIN_AGENT_TLS_KEY_PATH && fs.existsSync(process.env.IIN_AGENT_TLS_KEY_PATH)))) { - throw new Error("Missing or invalid IIN agent TLS credentials on " + process.env.IIN_AGENT_ENDPOINT); - } - const keyCertPair = { - cert_chain: fs.readFileSync(process.env.IIN_AGENT_TLS_CERT_PATH), - private_key: fs.readFileSync(process.env.IIN_AGENT_TLS_KEY_PATH) - }; - iinAgentServer.bindAsync(`${process.env.IIN_AGENT_ENDPOINT}`, ServerCredentials.createSsl(null, [ keyCertPair ], false), (cb) => { - configSetup().then(() => { - console.log('Starting IIN agent server with TLS on', process.env.IIN_AGENT_ENDPOINT); - iinAgentServer.start(); - loopSyncExternalState(); - }).catch((error) => { - console.error("Could not setup iin-agent due to error:", error); +if (process.env.IIN_AGENT_TLS === "true") { + if ( + !( + process.env.IIN_AGENT_TLS_CERT_PATH && + fs.existsSync(process.env.IIN_AGENT_TLS_CERT_PATH) && + process.env.IIN_AGENT_TLS_KEY_PATH && + fs.existsSync(process.env.IIN_AGENT_TLS_KEY_PATH) + ) + ) { + throw new Error( + "Missing or invalid IIN agent TLS credentials on " + + process.env.IIN_AGENT_ENDPOINT, + ); + } + const keyCertPair = { + cert_chain: fs.readFileSync(process.env.IIN_AGENT_TLS_CERT_PATH), + private_key: fs.readFileSync(process.env.IIN_AGENT_TLS_KEY_PATH), + }; + iinAgentServer.bindAsync( + `${process.env.IIN_AGENT_ENDPOINT}`, + ServerCredentials.createSsl(null, [keyCertPair], false), + (cb) => { + configSetup() + .then(() => { + console.log( + "Starting IIN agent server with TLS on", + process.env.IIN_AGENT_ENDPOINT, + ); + iinAgentServer.start(); + loopSyncExternalState(); + }) + .catch((error) => { + console.error("Could not setup iin-agent due to error:", error); }); - }); + }, + ); } else { - iinAgentServer.bindAsync(`${process.env.IIN_AGENT_ENDPOINT}`, ServerCredentials.createInsecure(), (cb) => { - configSetup().then(() => { - console.log('Starting IIN agent server without TLS on', process.env.IIN_AGENT_ENDPOINT); - iinAgentServer.start(); - loopSyncExternalState(); - }).catch((error) => { - console.error("Could not setup iin-agent due to error:", error); + iinAgentServer.bindAsync( + `${process.env.IIN_AGENT_ENDPOINT}`, + ServerCredentials.createInsecure(), + (cb) => { + configSetup() + .then(() => { + console.log( + "Starting IIN agent server without TLS on", + process.env.IIN_AGENT_ENDPOINT, + ); + iinAgentServer.start(); + loopSyncExternalState(); + }) + .catch((error) => { + console.error("Could not setup iin-agent due to error:", error); }); - }); + }, + ); } diff --git a/weaver/core/identity-management/iin-agent/test/membershipTest.js b/weaver/core/identity-management/iin-agent/test/membershipTest.js index 094cb2e398..f44b20d8b7 100644 --- a/weaver/core/identity-management/iin-agent/test/membershipTest.js +++ b/weaver/core/identity-management/iin-agent/test/membershipTest.js @@ -19,54 +19,53 @@ chai.should(); const { Wallets } = require("fabric-network"); const { ContractImpl } = require("fabric-network/lib/contract"); const { NetworkImpl } = require("fabric-network/lib/network"); -const membershipPb = require('@hyperledger/cacti-weaver-protos-js/common/membership_pb'); - +const membershipPb = require("@hyperledger/cacti-weaver-protos-js/common/membership_pb"); describe("Membership", () => { - const mspId = "mspId"; - const foreignNetworkId = "foreignNetworkId"; - const userName = "user_name"; + const mspId = "mspId"; + const foreignNetworkId = "foreignNetworkId"; + const userName = "user_name"; - let wallet; - // Initialize wallet with a single user identity - async function initializeWallet() { - const privKeyFile = `${__dirname}/data/privKey.pem`; - const signCertFile = `${__dirname}/data/signCert.pem`; - const privateKeyStr = fs.readFileSync(privKeyFile).toString(); - const signCert = fs.readFileSync(signCertFile).toString(); - lockerECert = signCert; - wallet = await Wallets.newInMemoryWallet(); - const userIdentity = { - credentials: { certificate: signCert, privateKey: privateKeyStr }, - mspId, - type: "X.509", - }; - await wallet.put(userName, userIdentity); - return userIdentity; - } - - describe("serialize membership", () => { + let wallet; + // Initialize wallet with a single user identity + async function initializeWallet() { + const privKeyFile = `${__dirname}/data/privKey.pem`; + const signCertFile = `${__dirname}/data/signCert.pem`; + const privateKeyStr = fs.readFileSync(privKeyFile).toString(); + const signCert = fs.readFileSync(signCertFile).toString(); + lockerECert = signCert; + wallet = await Wallets.newInMemoryWallet(); + const userIdentity = { + credentials: { certificate: signCert, privateKey: privateKeyStr }, + mspId, + type: "X.509", + }; + await wallet.put(userName, userIdentity); + return userIdentity; + } - it("test 1", async () => { - const membership = new membershipPb.Membership() - membership.setSecuritydomain('2345') - - const member = new membershipPb.Member() - member.setValue('') - member.setType('certificate') - member.setChainList(['chain1-cert1', 'chain1-cert2', 'chain1-cert3']) - membership.getMembersMap().set('member1', member) - - const member2 = new membershipPb.Member() - member2.setValue('') - member2.setType('certificate') - member2.setChainList(['chain2-cert1', 'chain2-cert2', 'chain2-cert3']) - membership.getMembersMap().set('member2', member2) - - const ms64 = Buffer.from(membership.serializeBinary()).toString('base64') - console.log(ms64) - expect(ms64).to.equal('CgQyMzQ1EkIKB21lbWJlcjESNxILY2VydGlmaWNhdGUaDGNoYWluMS1jZXJ0MRoMY2hhaW4xLWNlcnQyGgxjaGFpbjEtY2VydDMSQgoHbWVtYmVyMhI3EgtjZXJ0aWZpY2F0ZRoMY2hhaW4yLWNlcnQxGgxjaGFpbjItY2VydDIaDGNoYWluMi1jZXJ0Mw=='); - }); - }); + describe("serialize membership", () => { + it("test 1", async () => { + const membership = new membershipPb.Membership(); + membership.setSecuritydomain("2345"); + + const member = new membershipPb.Member(); + member.setValue(""); + member.setType("certificate"); + member.setChainList(["chain1-cert1", "chain1-cert2", "chain1-cert3"]); + membership.getMembersMap().set("member1", member); + const member2 = new membershipPb.Member(); + member2.setValue(""); + member2.setType("certificate"); + member2.setChainList(["chain2-cert1", "chain2-cert2", "chain2-cert3"]); + membership.getMembersMap().set("member2", member2); + + const ms64 = Buffer.from(membership.serializeBinary()).toString("base64"); + console.log(ms64); + expect(ms64).to.equal( + "CgQyMzQ1EkIKB21lbWJlcjESNxILY2VydGlmaWNhdGUaDGNoYWluMS1jZXJ0MRoMY2hhaW4xLWNlcnQyGgxjaGFpbjEtY2VydDMSQgoHbWVtYmVyMhI3EgtjZXJ0aWZpY2F0ZRoMY2hhaW4yLWNlcnQxGgxjaGFpbjItY2VydDIaDGNoYWluMi1jZXJ0Mw==", + ); + }); + }); }); diff --git a/weaver/core/identity-management/iin-agent/test/utilsTest.js b/weaver/core/identity-management/iin-agent/test/utilsTest.js index 10b0e84086..b279139c3e 100644 --- a/weaver/core/identity-management/iin-agent/test/utilsTest.js +++ b/weaver/core/identity-management/iin-agent/test/utilsTest.js @@ -19,141 +19,171 @@ chai.should(); const { Wallets } = require("fabric-network"); const { ContractImpl } = require("fabric-network/lib/contract"); const { NetworkImpl } = require("fabric-network/lib/network"); -const membershipPb = require('@hyperledger/cacti-weaver-protos-js/common/membership_pb'); -const agent_pb = require('@hyperledger/cacti-weaver-protos-js/identity/agent_pb'); +const membershipPb = require("@hyperledger/cacti-weaver-protos-js/common/membership_pb"); +const agent_pb = require("@hyperledger/cacti-weaver-protos-js/identity/agent_pb"); -const utils = require('../out/common/utils.js') +const utils = require("../out/common/utils.js"); describe("Membership", () => { - const fabricMemberId = "Org1MSP"; - const cordaMemberId = 'PartyA' - const securityDomain = "network1"; - const foreignSecurityDomain = "network2"; - const userName = "user1"; - const cert = fs.readFileSync(`${__dirname}/data/anotherSignCert.pem`).toString(); - const cordaCert = fs.readFileSync(`${__dirname}/data/cordaCert.pem`).toString(); - const cert2 = fs.readFileSync(`${__dirname}/data/signCert.pem`).toString(); - const pkey2 = fs.readFileSync(`${__dirname}/data/privKey.pem`).toString(); - const nonce = '123' - const fabricAttestedMembership = getForeignAttestedMembership(`${__dirname}/data/fabricMembership.json`, fabricMemberId) - const cordaAttestedMembership = getForeignAttestedMembership(`${__dirname}/data/cordaMembership.json`, cordaMemberId) - - function getForeignAttestedMembership(filename, memberId) { - const membershipJSON = JSON.parse(fs.readFileSync(filename).toString()); - const member = new membershipPb.Member() - member.setValue(membershipJSON.members[memberId].value) - member.setType(membershipJSON.members[memberId].type) - if (membershipJSON.members[memberId].chain) { - for (const cacert of membershipJSON.members[memberId].chain) { - member.addChain(cacert) - } - } - const membership = new membershipPb.Membership() - membership.setSecuritydomain(membershipJSON.securityDomain) - membership.getMembersMap().set(memberId, member) - - const membershipSerialized64 = Buffer.from(membership.serializeBinary()).toString('base64') - const sign = utils.signMessage(membershipSerialized64+nonce, pkey2) - const unitIdentity = new agent_pb.SecurityDomainMemberIdentity() - unitIdentity.setSecurityDomain(membershipJSON.securityDomain) - unitIdentity.setMemberId(memberId) - const attestation = new agent_pb.Attestation() - attestation.setUnitIdentity(unitIdentity) - attestation.setSignature(sign) - attestation.setCertificate(cert2) - attestation.setNonce(nonce) - attestation.setTimestamp(Date.now()) - - const attestedMembership = new agent_pb.AttestedMembership() - attestedMembership.setMembership(membershipSerialized64) - attestedMembership.setAttestation(attestation) - - return attestedMembership - } + const fabricMemberId = "Org1MSP"; + const cordaMemberId = "PartyA"; + const securityDomain = "network1"; + const foreignSecurityDomain = "network2"; + const userName = "user1"; + const cert = fs + .readFileSync(`${__dirname}/data/anotherSignCert.pem`) + .toString(); + const cordaCert = fs + .readFileSync(`${__dirname}/data/cordaCert.pem`) + .toString(); + const cert2 = fs.readFileSync(`${__dirname}/data/signCert.pem`).toString(); + const pkey2 = fs.readFileSync(`${__dirname}/data/privKey.pem`).toString(); + const nonce = "123"; + const fabricAttestedMembership = getForeignAttestedMembership( + `${__dirname}/data/fabricMembership.json`, + fabricMemberId, + ); + const cordaAttestedMembership = getForeignAttestedMembership( + `${__dirname}/data/cordaMembership.json`, + cordaMemberId, + ); - let wallet; - // Initialize wallet with a single user identity - async function initializeWallet() { - const privKeyFile = `${__dirname}/data/privKey.pem`; - const signCertFile = `${__dirname}/data/signCert.pem`; - const privateKeyStr = fs.readFileSync(privKeyFile).toString(); - const signCert = fs.readFileSync(signCertFile).toString(); - lockerECert = signCert; - wallet = await Wallets.newInMemoryWallet(); - const userIdentity = { - credentials: { certificate: signCert, privateKey: privateKeyStr }, - mspId, - type: "X.509", - }; - await wallet.put(userName, userIdentity); - return userIdentity; + function getForeignAttestedMembership(filename, memberId) { + const membershipJSON = JSON.parse(fs.readFileSync(filename).toString()); + const member = new membershipPb.Member(); + member.setValue(membershipJSON.members[memberId].value); + member.setType(membershipJSON.members[memberId].type); + if (membershipJSON.members[memberId].chain) { + for (const cacert of membershipJSON.members[memberId].chain) { + member.addChain(cacert); + } } + const membership = new membershipPb.Membership(); + membership.setSecuritydomain(membershipJSON.securityDomain); + membership.getMembersMap().set(memberId, member); - async function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - // - // beforeEach(async () => { - // await initializeWallet(); - // const network = sinon.createStubInstance(NetworkImpl); - // amc = new ContractImpl(network, "amc", "AssetManager"); - // }); - // - // afterEach(() => { - // sinon.restore(); - // }); - - describe("test signature creation and verification", () => { - const message = "hello123" - it("test success", async () => { - const signature = utils.signMessage(message, pkey2) - const verify = utils.verifySignature(message, cert2, signature) - expect(verify).to.equal(true) - }); - it("test fail 1", async () => { - const signature = utils.signMessage(message, pkey2) - const verify = utils.verifySignature('hello12', cert2, signature) - expect(verify).to.equal(false) - }); - it("test fail 2", async () => { - const signature = utils.signMessage(message, pkey2) - const verify = utils.verifySignature(message, cert, signature) - expect(verify).to.equal(false) - }); + const membershipSerialized64 = Buffer.from( + membership.serializeBinary(), + ).toString("base64"); + const sign = utils.signMessage(membershipSerialized64 + nonce, pkey2); + const unitIdentity = new agent_pb.SecurityDomainMemberIdentity(); + unitIdentity.setSecurityDomain(membershipJSON.securityDomain); + unitIdentity.setMemberId(memberId); + const attestation = new agent_pb.Attestation(); + attestation.setUnitIdentity(unitIdentity); + attestation.setSignature(sign); + attestation.setCertificate(cert2); + attestation.setNonce(nonce); + attestation.setTimestamp(Date.now()); + + const attestedMembership = new agent_pb.AttestedMembership(); + attestedMembership.setMembership(membershipSerialized64); + attestedMembership.setAttestation(attestation); + + return attestedMembership; + } + + let wallet; + // Initialize wallet with a single user identity + async function initializeWallet() { + const privKeyFile = `${__dirname}/data/privKey.pem`; + const signCertFile = `${__dirname}/data/signCert.pem`; + const privateKeyStr = fs.readFileSync(privKeyFile).toString(); + const signCert = fs.readFileSync(signCertFile).toString(); + lockerECert = signCert; + wallet = await Wallets.newInMemoryWallet(); + const userIdentity = { + credentials: { certificate: signCert, privateKey: privateKeyStr }, + mspId, + type: "X.509", + }; + await wallet.put(userName, userIdentity); + return userIdentity; + } + + async function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + // + // beforeEach(async () => { + // await initializeWallet(); + // const network = sinon.createStubInstance(NetworkImpl); + // amc = new ContractImpl(network, "amc", "AssetManager"); + // }); + // + // afterEach(() => { + // sinon.restore(); + // }); + + describe("test signature creation and verification", () => { + const message = "hello123"; + it("test success", async () => { + const signature = utils.signMessage(message, pkey2); + const verify = utils.verifySignature(message, cert2, signature); + expect(verify).to.equal(true); + }); + it("test fail 1", async () => { + const signature = utils.signMessage(message, pkey2); + const verify = utils.verifySignature("hello12", cert2, signature); + expect(verify).to.equal(false); + }); + it("test fail 2", async () => { + const signature = utils.signMessage(message, pkey2); + const verify = utils.verifySignature(message, cert, signature); + expect(verify).to.equal(false); }); - - describe("verify attestation", () => { - it("test success", async () => { - const verify = utils.validateAttestedMembership(fabricAttestedMembership.getMembership(), nonce, fabricAttestedMembership.getAttestation()) - expect(verify).to.equal(true) - }); - it("test fail 1", async () => { - const verify = utils.validateAttestedMembership(fabricAttestedMembership.getMembership(), '1', fabricAttestedMembership.getAttestation()) - expect(verify).to.equal(false) - }); - it("test fail 2", async () => { - const attestation = fabricAttestedMembership.getAttestation() - attestation.setNonce('1') - const verify = utils.validateAttestedMembership(fabricAttestedMembership.getMembership(), '1', attestation) - expect(verify).to.equal(false) - }); + }); + + describe("verify attestation", () => { + it("test success", async () => { + const verify = utils.validateAttestedMembership( + fabricAttestedMembership.getMembership(), + nonce, + fabricAttestedMembership.getAttestation(), + ); + expect(verify).to.equal(true); }); - - describe("verify Fabric Member In Membership", () => { - it("test success", async () => { - const membership = utils.deserializeMembership64(fabricAttestedMembership.getMembership()) - const verify = utils.verifyMemberInMembership(membership, fabricAttestedMembership.getAttestation()) - expect(verify).to.equal(true) - }); + it("test fail 1", async () => { + const verify = utils.validateAttestedMembership( + fabricAttestedMembership.getMembership(), + "1", + fabricAttestedMembership.getAttestation(), + ); + expect(verify).to.equal(false); }); - describe("verify Corda Member In Membership", () => { - it("test success", async () => { - const membership = utils.deserializeMembership64(cordaAttestedMembership.getMembership()) - const attestation = cordaAttestedMembership.getAttestation() - attestation.setCertificate(cordaCert) - const verify = utils.verifyMemberInMembership(membership, attestation) - expect(verify).to.equal(true) - }); + it("test fail 2", async () => { + const attestation = fabricAttestedMembership.getAttestation(); + attestation.setNonce("1"); + const verify = utils.validateAttestedMembership( + fabricAttestedMembership.getMembership(), + "1", + attestation, + ); + expect(verify).to.equal(false); }); + }); + describe("verify Fabric Member In Membership", () => { + it("test success", async () => { + const membership = utils.deserializeMembership64( + fabricAttestedMembership.getMembership(), + ); + const verify = utils.verifyMemberInMembership( + membership, + fabricAttestedMembership.getAttestation(), + ); + expect(verify).to.equal(true); + }); + }); + describe("verify Corda Member In Membership", () => { + it("test success", async () => { + const membership = utils.deserializeMembership64( + cordaAttestedMembership.getMembership(), + ); + const attestation = cordaAttestedMembership.getAttestation(); + attestation.setCertificate(cordaCert); + const verify = utils.verifyMemberInMembership(membership, attestation); + expect(verify).to.equal(true); + }); + }); }); diff --git a/weaver/docs/babel.config.js b/weaver/docs/babel.config.js index 4d0c405762..276adddb44 100644 --- a/weaver/docs/babel.config.js +++ b/weaver/docs/babel.config.js @@ -5,5 +5,5 @@ */ module.exports = { - presets: [require.resolve('@docusaurus/core/lib/babel/preset')], + presets: [require.resolve("@docusaurus/core/lib/babel/preset")], }; diff --git a/weaver/docs/docusaurus.config.js b/weaver/docs/docusaurus.config.js index edf17cb5f6..7ac4e87694 100644 --- a/weaver/docs/docusaurus.config.js +++ b/weaver/docs/docusaurus.config.js @@ -5,63 +5,61 @@ */ module.exports = { - title: 'Weaver: DLT Interoperability Framework', - tagline: 'Documentation', - url: 'https://hyperledger.github.io', - baseUrl: '/cacti/', - onBrokenLinks: 'throw', - onBrokenMarkdownLinks: 'warn', - favicon: 'shared/favicon.ico', - organizationName: 'hyperledger', - projectName: 'hyperledger.github.io', + title: "Weaver: DLT Interoperability Framework", + tagline: "Documentation", + url: "https://hyperledger.github.io", + baseUrl: "/cacti/", + onBrokenLinks: "throw", + onBrokenMarkdownLinks: "warn", + favicon: "shared/favicon.ico", + organizationName: "hyperledger", + projectName: "hyperledger.github.io", themeConfig: { prism: { - additionalLanguages: ['java', 'kotlin', 'groovy', 'toml'], + additionalLanguages: ["java", "kotlin", "groovy", "toml"], }, navbar: { - title: 'Weaver', + title: "Weaver", logo: { - alt: 'Weaver', - src: 'shared/logo.svg', + alt: "Weaver", + src: "shared/logo.svg", }, items: [ { - to: 'docs/external/introduction', - activeBasePath: 'docs', - label: 'Docs', - position: 'left', + to: "docs/external/introduction", + activeBasePath: "docs", + label: "Docs", + position: "left", }, { - to: 'blog', - label: 'Blog', - position: 'left' + to: "blog", + label: "Blog", + position: "left", }, { - href: 'https://github.com/hyperledger/cacti', - label: 'GitHub', - position: 'right', + href: "https://github.com/hyperledger/cacti", + label: "GitHub", + position: "right", }, ], }, footer: { - style: 'light', - links: [ - ], + style: "light", + links: [], copyright: `Copyright © ${new Date().getFullYear()} Weaver Framework.`, }, }, presets: [ [ - '@docusaurus/preset-classic', + "@docusaurus/preset-classic", { docs: { - sidebarPath: require.resolve('./sidebars.js'), + sidebarPath: require.resolve("./sidebars.js"), // Please change this to your repo. - editUrl: - 'https://github.com/hyperledger/cacti/edit/main/', - }, + editUrl: "https://github.com/hyperledger/cacti/edit/main/", + }, theme: { - customCss: require.resolve('./src/css/custom.css'), + customCss: require.resolve("./src/css/custom.css"), }, }, ], diff --git a/weaver/docs/sidebars.js b/weaver/docs/sidebars.js index 282e32bba9..5779a0ac41 100644 --- a/weaver/docs/sidebars.js +++ b/weaver/docs/sidebars.js @@ -5,113 +5,113 @@ */ module.exports = { - Documentation: [ - "external/introduction", + Documentation: [ + "external/introduction", + { + type: "category", + label: "Getting Started", + items: [ + "external/getting-started/guide", { - type: "category", - label: "Getting Started", - items: [ - "external/getting-started/guide", - { - type: "category", - label: "Launching a Test Network", - items: [ - "external/getting-started/test-network/overview", - "external/getting-started/test-network/setup-local", - "external/getting-started/test-network/setup-local-docker", - "external/getting-started/test-network/setup-packages", - "external/getting-started/test-network/setup-packages-docker", - "external/getting-started/test-network/ledger-initialization", - "external/getting-started/test-network/advanced-configuration", - ], - }, - { - type: "category", - label: "Testing Interoperation Modes", - items: [ - "external/getting-started/interop/overview", - "external/getting-started/interop/data-sharing", - { - type: "category", - label: "Asset Exchange", - items: [ - "external/getting-started/interop/asset-exchange/overview", - "external/getting-started/interop/asset-exchange/fabric-fabric", - "external/getting-started/interop/asset-exchange/fabric-corda", - "external/getting-started/interop/asset-exchange/fabric-besu", - "external/getting-started/interop/asset-exchange/corda-corda", - "external/getting-started/interop/asset-exchange/corda-besu", - "external/getting-started/interop/asset-exchange/besu-besu", - ], - }, - "external/getting-started/interop/asset-transfer", - ], - }, - { - type: "category", - label: "Enabling Weaver in your Network and Application", - items: [ - "external/getting-started/enabling-weaver-network/overview", - "external/getting-started/enabling-weaver-network/fabric", - "external/getting-started/enabling-weaver-network/corda", - "external/getting-started/enabling-weaver-network/besu", - ], - }, - ], + type: "category", + label: "Launching a Test Network", + items: [ + "external/getting-started/test-network/overview", + "external/getting-started/test-network/setup-local", + "external/getting-started/test-network/setup-local-docker", + "external/getting-started/test-network/setup-packages", + "external/getting-started/test-network/setup-packages-docker", + "external/getting-started/test-network/ledger-initialization", + "external/getting-started/test-network/advanced-configuration", + ], }, { - type: "category", - label: "What is Interoperability?", - items: [ - "external/what-is-interoperability/understanding-interoperability", - "external/what-is-interoperability/levels-of-interoperability", - "external/what-is-interoperability/integration-patterns", - ], + type: "category", + label: "Testing Interoperation Modes", + items: [ + "external/getting-started/interop/overview", + "external/getting-started/interop/data-sharing", + { + type: "category", + label: "Asset Exchange", + items: [ + "external/getting-started/interop/asset-exchange/overview", + "external/getting-started/interop/asset-exchange/fabric-fabric", + "external/getting-started/interop/asset-exchange/fabric-corda", + "external/getting-started/interop/asset-exchange/fabric-besu", + "external/getting-started/interop/asset-exchange/corda-corda", + "external/getting-started/interop/asset-exchange/corda-besu", + "external/getting-started/interop/asset-exchange/besu-besu", + ], + }, + "external/getting-started/interop/asset-transfer", + ], }, - "external/interoperability-modes", - "external/design-principles", { - type: "category", - label: "User Stories", - items: [ - "external/user-stories/overview", - "external/user-stories/global-trade", - "external/user-stories/financial-markets", - "external/user-stories/legacy-integration", - ], + type: "category", + label: "Enabling Weaver in your Network and Application", + items: [ + "external/getting-started/enabling-weaver-network/overview", + "external/getting-started/enabling-weaver-network/fabric", + "external/getting-started/enabling-weaver-network/corda", + "external/getting-started/enabling-weaver-network/besu", + ], }, - { - type: "category", - label: "Architecture and Design", - items: [ - "external/architecture-and-design/overview", - "external/architecture-and-design/relay", - "external/architecture-and-design/drivers", - "external/architecture-and-design/weaver-dapps", - "external/architecture-and-design/decentralized-identity", - ], - }, - { - type: "category", - label: "Security Model", - items: [ - "external/security-model/authentication", - "external/security-model/access-control", - "external/security-model/proofs-and-verification", - "external/security-model/end-to-end-security", - ], - }, - { - type: "category", - label: "Deployment Considerations", - items: [ - "external/deployment-considerations/deployment-patterns", - "external/deployment-considerations/governance-and-policies", - "external/deployment-considerations/legal-and-regulation", - ], - }, - "external/specifications", - "external/roadmap", - "external/publications", - ], -} + ], + }, + { + type: "category", + label: "What is Interoperability?", + items: [ + "external/what-is-interoperability/understanding-interoperability", + "external/what-is-interoperability/levels-of-interoperability", + "external/what-is-interoperability/integration-patterns", + ], + }, + "external/interoperability-modes", + "external/design-principles", + { + type: "category", + label: "User Stories", + items: [ + "external/user-stories/overview", + "external/user-stories/global-trade", + "external/user-stories/financial-markets", + "external/user-stories/legacy-integration", + ], + }, + { + type: "category", + label: "Architecture and Design", + items: [ + "external/architecture-and-design/overview", + "external/architecture-and-design/relay", + "external/architecture-and-design/drivers", + "external/architecture-and-design/weaver-dapps", + "external/architecture-and-design/decentralized-identity", + ], + }, + { + type: "category", + label: "Security Model", + items: [ + "external/security-model/authentication", + "external/security-model/access-control", + "external/security-model/proofs-and-verification", + "external/security-model/end-to-end-security", + ], + }, + { + type: "category", + label: "Deployment Considerations", + items: [ + "external/deployment-considerations/deployment-patterns", + "external/deployment-considerations/governance-and-policies", + "external/deployment-considerations/legal-and-regulation", + ], + }, + "external/specifications", + "external/roadmap", + "external/publications", + ], +}; diff --git a/weaver/docs/src/pages/index.js b/weaver/docs/src/pages/index.js index 994a74bb13..3c3743609b 100644 --- a/weaver/docs/src/pages/index.js +++ b/weaver/docs/src/pages/index.js @@ -4,49 +4,51 @@ * SPDX-License-Identifier: Apache-2.0 */ -import React from 'react'; -import clsx from 'clsx'; -import Layout from '@theme/Layout'; -import Link from '@docusaurus/Link'; -import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import useBaseUrl from '@docusaurus/useBaseUrl'; -import styles from './styles.module.css'; +import React from "react"; +import clsx from "clsx"; +import Layout from "@theme/Layout"; +import Link from "@docusaurus/Link"; +import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; +import useBaseUrl from "@docusaurus/useBaseUrl"; +import styles from "./styles.module.css"; const features = [ { - title: 'Network Neutral', - imageUrl: 'shared/undraw_docusaurus_mountain.svg', + title: "Network Neutral", + imageUrl: "shared/undraw_docusaurus_mountain.svg", description: ( <> - Weaver is designed to be agnostic to the underlying distributed ledger - protocol and is based on a set of standard specifications. + Weaver is designed to be agnostic to the underlying distributed ledger + protocol and is based on a set of standard specifications. ), }, { - title: 'Secure', - imageUrl: 'shared/undraw_docusaurus_tree.svg', + title: "Secure", + imageUrl: "shared/undraw_docusaurus_tree.svg", description: ( <> - Verifiable state proofs and secure communication ensures integrity and confidentiality. + Verifiable state proofs and secure communication ensures integrity and + confidentiality. ), }, { - title: 'Enterprise Grade', - imageUrl: 'shared/undraw_docusaurus_react.svg', + title: "Enterprise Grade", + imageUrl: "shared/undraw_docusaurus_react.svg", description: ( <> - A high availability architecture with flexible deployment models meets the needs of enterprises deploying Weaver. + A high availability architecture with flexible deployment models meets + the needs of enterprises deploying Weaver. ), }, ]; -function Feature({imageUrl, title, description}) { +function Feature({ imageUrl, title, description }) { const imgUrl = useBaseUrl(imageUrl); return ( -
+
{imgUrl && (
{title} @@ -60,22 +62,24 @@ function Feature({imageUrl, title, description}) { function Home() { const context = useDocusaurusContext(); - const {siteConfig = {}} = context; + const { siteConfig = {} } = context; return ( -
+ description="Description will go into a meta tag in " + > +

{siteConfig.title}

{siteConfig.tagline}

+ to={useBaseUrl("docs/external/introduction")} + > Get Started
diff --git a/weaver/samples/besu/besu-cli/__tests__/cli-integration.test.ts b/weaver/samples/besu/besu-cli/__tests__/cli-integration.test.ts index deef4f2aff..15f7f28b76 100644 --- a/weaver/samples/besu/besu-cli/__tests__/cli-integration.test.ts +++ b/weaver/samples/besu/besu-cli/__tests__/cli-integration.test.ts @@ -4,32 +4,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { system, filesystem } = require('gluegun') +const { system, filesystem } = require("gluegun"); -const src = filesystem.path(__dirname, '..') +const src = filesystem.path(__dirname, ".."); -const cli = async cmd => - system.run('node ' + filesystem.path(src, 'bin', 'besu-cli') + ` ${cmd}`) +const cli = async (cmd) => + system.run("node " + filesystem.path(src, "bin", "besu-cli") + ` ${cmd}`); -test('outputs version', async () => { - const output = await cli('--version') - expect(output).toContain('0.0.1') -}) +test("outputs version", async () => { + const output = await cli("--version"); + expect(output).toContain("0.0.1"); +}); -test('outputs help', async () => { - const output = await cli('--help') - expect(output).toContain('0.0.1') -}) +test("outputs help", async () => { + const output = await cli("--help"); + expect(output).toContain("0.0.1"); +}); -test('generates file', async () => { - const output = await cli('generate foo') +test("generates file", async () => { + const output = await cli("generate foo"); - expect(output).toContain('Generated file at models/foo-model.ts') - const foomodel = filesystem.read('models/foo-model.ts') + expect(output).toContain("Generated file at models/foo-model.ts"); + const foomodel = filesystem.read("models/foo-model.ts"); - expect(foomodel).toContain(`module.exports = {`) - expect(foomodel).toContain(`name: 'foo'`) + expect(foomodel).toContain(`module.exports = {`); + expect(foomodel).toContain(`name: 'foo'`); // cleanup artifact - filesystem.remove('models') -}) + filesystem.remove("models"); +}); diff --git a/weaver/samples/besu/besu-cli/package-local.json b/weaver/samples/besu/besu-cli/package-local.json index 77a3214762..49c1e50d58 100644 --- a/weaver/samples/besu/besu-cli/package-local.json +++ b/weaver/samples/besu/besu-cli/package-local.json @@ -22,17 +22,12 @@ "compile": "tsc -p .", "copy-templates": "if [ -e ./src/templates ]; then cp -a ./src/templates ./build/; fi", "coverage": "jest --coverage", - "format": "prettier --write **/*.{js,ts,tsx,json}", "lint": "tslint -p .", "prepublishOnly": "yarn build", "snapupdate": "jest --updateSnapshot", "test": "jest", "watch": "jest --watch" }, - "prettier": { - "semi": false, - "singleQuote": true - }, "jest": { "preset": "ts-jest", "testEnvironment": "node" @@ -49,12 +44,8 @@ "@types/jest": "29.5.3", "@types/node": "16.18.41", "jest": "29.6.2", - "prettier": "1.19.1", "ts-jest": "29.1.1", "ts-node": "10.9.1", - "tslint": "5.20.1", - "tslint-config-prettier": "1.18.0", - "tslint-config-standard": "8.0.1", "typescript": "5.3.3" }, "engines": { diff --git a/weaver/samples/besu/besu-cli/package.json b/weaver/samples/besu/besu-cli/package.json index d944e9b45e..ce5164b784 100644 --- a/weaver/samples/besu/besu-cli/package.json +++ b/weaver/samples/besu/besu-cli/package.json @@ -22,17 +22,12 @@ "compile": "tsc -p .", "copy-templates": "if [ -e ./src/templates ]; then cp -a ./src/templates ./build/; fi", "coverage": "jest --coverage", - "format": "prettier --write **/*.{js,ts,tsx,json}", "lint": "tslint -p .", "prepublishOnly": "yarn build", "snapupdate": "jest --updateSnapshot", "test": "jest", "watch": "jest --watch" }, - "prettier": { - "semi": false, - "singleQuote": true - }, "jest": { "preset": "ts-jest", "testEnvironment": "node" @@ -49,12 +44,8 @@ "@types/jest": "29.5.3", "@types/node": "16.18.41", "jest": "29.6.2", - "prettier": "1.19.1", "ts-jest": "29.1.1", "ts-node": "10.9.1", - "tslint": "5.20.1", - "tslint-config-prettier": "1.18.0", - "tslint-config-standard": "8.0.1", "typescript": "5.3.3" }, "engines": { diff --git a/weaver/samples/besu/besu-cli/src/cli.ts b/weaver/samples/besu/besu-cli/src/cli.ts index befdafdf32..04ab013a30 100644 --- a/weaver/samples/besu/besu-cli/src/cli.ts +++ b/weaver/samples/besu/besu-cli/src/cli.ts @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { build } = require('gluegun') +const { build } = require("gluegun"); /** * Create the cli and kick it off @@ -12,20 +12,20 @@ const { build } = require('gluegun') async function run(argv) { // create a CLI runtime const cli = build() - .brand('besu-cli') + .brand("besu-cli") .src(__dirname) - .plugins('./node_modules', { matching: 'besu-cli-*', hidden: true }) + .plugins("./node_modules", { matching: "besu-cli-*", hidden: true }) .help() // provides default for help, h, --help, -h .version() // provides default for version, v, --version, -v - .create() + .create(); // enable the following method if you'd like to skip loading one of these core extensions // this can improve performance if they're not necessary for your project: // .exclude(['meta', 'strings', 'print', 'filesystem', 'semver', 'system', 'prompt', 'http', 'template', 'patching', 'package-manager']) // and run it - const toolbox = await cli.run(argv) + const toolbox = await cli.run(argv); // send it back (for testing, mostly) - return toolbox + return toolbox; } -module.exports = { run } +module.exports = { run }; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset-helper.ts b/weaver/samples/besu/besu-cli/src/commands/asset-helper.ts index 82d432b0d2..280b5f5d65 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset-helper.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset-helper.ts @@ -4,21 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helper/helper' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helper/helper"; const command: GluegunCommand = { - name: 'asset', - alias: ['a'], - description: 'Asset Management', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'besu-cli asset', '', [], command, [ - 'asset' - ]) - return - } -} + name: "asset", + alias: ["a"], + description: "Asset Management", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "besu-cli asset", "", [], command, ["asset"]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/claim.ts b/weaver/samples/besu/besu-cli/src/commands/asset/claim.ts index fa5d70b336..52aa583c37 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/claim.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/claim.ts @@ -4,186 +4,194 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -import { AssetManager } from '@hyperledger/cacti-weaver-sdk-besu' +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +import { AssetManager } from "@hyperledger/cacti-weaver-sdk-besu"; import { HashFunctions } from "@hyperledger/cacti-weaver-sdk-besu"; -const Web3 = require('web3') +const Web3 = require("web3"); async function getBalances(tokenContract, address, token_id = 0) { try { - var balance = await tokenContract.balanceOf(address, token_id) + var balance = await tokenContract.balanceOf(address, token_id); } catch { - var balance = null + var balance = null; } - if (!balance) return await tokenContract.balanceOf(address) - else return balance + if (!balance) return await tokenContract.balanceOf(address); + else return balance; } const command: GluegunCommand = { - name: 'claim', - description: 'Claim assets (fungible assets for now)', + name: "claim", + description: "Claim assets (fungible assets for now)", - run: async toolbox => { + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset claim --network=network1 --lock_contract_id=lockContractID --recipient_account=2 --preimage=preimage`, - 'besu-cli asset claim --network= --lock_contract_id= --recipient_account=<2|1> --preimage= --recipient_account_address= --network_port= --network_host=', + "besu-cli asset claim --network= --lock_contract_id= --recipient_account=<2|1> --preimage= --recipient_account_address= --network_port= --network_host=", [ { - name: '--network', - description: 'network for command. ' + name: "--network", + description: "network for command. ", }, { - name: '--lock_contract_id', - description: 'The address / ID of the lock contract.' + name: "--lock_contract_id", + description: "The address / ID of the lock contract.", }, { - name: '--recipient_account', + name: "--recipient_account", description: - 'The index of the account of the recipient of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.' + "The index of the account of the recipient of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.", }, { - name: '--preimage', + name: "--preimage", description: - 'The preimage of hash with which the asset was locked with.' + "The preimage of hash with which the asset was locked with.", }, { - name: '--recipient_account_address', + name: "--recipient_account_address", description: - 'The address of the recipient account. We can set this parameter if we want to use account address instead of account index ' + "The address of the recipient account. We can set this parameter if we want to use account address instead of account index ", }, { - name: '--token_id', + name: "--token_id", description: - 'token ID for issuing tokens. Only applicable for ERC721 and ERC1155. Default: 0' + "token ID for issuing tokens. Only applicable for ERC721 and ERC1155. Default: 0", }, { - name: '--network_host', + name: "--network_host", description: - 'The network host. Default value is taken from config.json' + "The network host. Default value is taken from config.json", }, { - name: '--network_port', + name: "--network_port", description: - 'The network port. Default value is taken from config.json' - } + "The network port. Default value is taken from config.json", + }, ], command, - ['asset', 'claim'] - ) - return + ["asset", "claim"], + ); + return; } - print.info('Claim assets') + print.info("Claim assets"); // Retrieving networkConfig if (!options.network) { - print.error('Network ID not provided.') - return + print.error("Network ID not provided."); + return; } if (!options.token_id) { - options.token_id=0 + options.token_id = 0; } - const networkConfig = getNetworkConfig(options.network) + const networkConfig = getNetworkConfig(options.network); - var networkPort = networkConfig.networkPort + let networkPort = networkConfig.networkPort; if (options.network_port) { - networkPort = options.network_port - console.log('Use network port : ', networkPort) + networkPort = options.network_port; + console.log("Use network port : ", networkPort); } - var networkHost = networkConfig.networkHost + let networkHost = networkConfig.networkHost; if (options.network_host) { - networkHost = options.network_host - console.log('Use network host : ', networkHost) + networkHost = options.network_host; + console.log("Use network host : ", networkHost); } const provider = new Web3.providers.HttpProvider( - 'http://' + networkHost + ':' + networkPort - ) + "http://" + networkHost + ":" + networkPort, + ); - const web3N = new Web3(provider) + const web3N = new Web3(provider); const interopContract = await getContractInstance( provider, - networkConfig.interopContract + networkConfig.interopContract, ).catch(function () { - console.log('Failed getting interopContract!') - }) + console.log("Failed getting interopContract!"); + }); const tokenContract = await getContractInstance( provider, - networkConfig.tokenContract + networkConfig.tokenContract, ).catch(function () { - console.log('Failed getting tokenContract!') - }) - const accounts = await web3N.eth.getAccounts() + console.log("Failed getting tokenContract!"); + }); + const accounts = await web3N.eth.getAccounts(); // Receiving the input parameters - var recipient + let recipient; if (options.recipient_account) { - recipient = accounts[options.recipient_account] + recipient = accounts[options.recipient_account]; } else if (options.recipient_account_address) { - recipient = '0x' + options.recipient_account_address + recipient = "0x" + options.recipient_account_address; } else { print.info( - 'Recipient account index not provided. Taking from networkConfig..' - ) - recipient = accounts[networkConfig.recipientAccountIndex] + "Recipient account index not provided. Taking from networkConfig..", + ); + recipient = accounts[networkConfig.recipientAccountIndex]; } if (!options.lock_contract_id) { - print.error('Lock contract ID not provided.') - return + print.error("Lock contract ID not provided."); + return; } - const lockContractId = '0x' + options.lock_contract_id + const lockContractId = "0x" + options.lock_contract_id; if (!options.preimage) { - print.error('Preimage not provided.') - return + print.error("Preimage not provided."); + return; } - console.log('Parameters') - console.log('networkConfig', networkConfig) - console.log('Receiver', recipient) - console.log('Lock Contract ID', lockContractId) - console.log('Preimage', options.preimage) + console.log("Parameters"); + console.log("networkConfig", networkConfig); + console.log("Receiver", recipient); + console.log("Lock Contract ID", lockContractId); + console.log("Preimage", options.preimage); - const preimage_bytes = web3N.utils.utf8ToHex(options.preimage) - console.log('Preimage bytes:', preimage_bytes) + const preimage_bytes = web3N.utils.utf8ToHex(options.preimage); + console.log("Preimage bytes:", preimage_bytes); // Balance of the recipient before claiming - var recipientBalance = await getBalances(tokenContract, recipient, options.token_id) + var recipientBalance = await getBalances( + tokenContract, + recipient, + options.token_id, + ); console.log( - `Account balance of the recipient in Network ${options.network - } before claiming: ${recipientBalance.toString()}` - ) - - const hash = new HashFunctions.SHA256() - hash.setPreimage(options.preimage) - await AssetManager - .claimAssetInHTLC( - interopContract, - lockContractId, - recipient, - hash, - ) - .catch(error => { - console.log('claimAsset threw an error:', error) - }) + `Account balance of the recipient in Network ${ + options.network + } before claiming: ${recipientBalance.toString()}`, + ); + + const hash = new HashFunctions.SHA256(); + hash.setPreimage(options.preimage); + await AssetManager.claimAssetInHTLC( + interopContract, + lockContractId, + recipient, + hash, + ).catch((error) => { + console.log("claimAsset threw an error:", error); + }); // Balance of the recipient after claiming - var recipientBalance = await getBalances(tokenContract, recipient, options.token_id) + var recipientBalance = await getBalances( + tokenContract, + recipient, + options.token_id, + ); console.log( - `Account balance of the recipient in Network ${options.network - } after claiming: ${recipientBalance.toString()}` - ) - process.exit() - } -} - -module.exports = command + `Account balance of the recipient in Network ${ + options.network + } after claiming: ${recipientBalance.toString()}`, + ); + process.exit(); + }, +}; + +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/exchange.ts b/weaver/samples/besu/besu-cli/src/commands/asset/exchange.ts index 9308444630..ae9b683ddd 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/exchange.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/exchange.ts @@ -4,263 +4,260 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance, getBalances } from '../../helper/besu-functions' -const Web3 = require('web3') -const crypto = require('crypto') +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance, getBalances } from "../../helper/besu-functions"; +const Web3 = require("web3"); +const crypto = require("crypto"); const command: GluegunCommand = { - name: 'exchange', - description: 'Cross-network exchange of assets (fungible assets for now)', + name: "exchange", + description: "Cross-network exchange of assets (fungible assets for now)", - run: async toolbox => { + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset exchange --network1=network1 --network2=network2 --amount=5 --timeout=20`, - 'besu-cli asset exchange --local-network= --user= ', + "besu-cli asset exchange --local-network= --user= ", [ { - name: '--network1', + name: "--network1", description: - 'network 1 for command. In our case, ' + "network 1 for command. In our case, ", }, { - name: '--network2', + name: "--network2", description: - 'network 2 for command. In our case, ' + "network 2 for command. In our case, ", }, { - name: '--amount', + name: "--amount", description: - 'The amount of fungible assets to be locked from the sender account specified on the network' + "The amount of fungible assets to be locked from the sender account specified on the network", }, { - name: '--timeout', + name: "--timeout", description: - 'Time in seconds for which the asset will be locked. The asset will be locked till Date.now() + the timeout provided' + "Time in seconds for which the asset will be locked. The asset will be locked till Date.now() + the timeout provided", }, { - name: '--hash', + name: "--hash", description: - 'The hash value with which the asset will be locked i.e., providing its pre-image will enable unlocking the asset. This is an optional parameter. If not provided, we will generate a fresh hash pair with a randomly generated pre-image and output the corresponding pre-image.' - } + "The hash value with which the asset will be locked i.e., providing its pre-image will enable unlocking the asset. This is an optional parameter. If not provided, we will generate a fresh hash pair with a randomly generated pre-image and output the corresponding pre-image.", + }, ], command, - ['asset', 'exchange'] - ) - return + ["asset", "exchange"], + ); + return; } - print.info('Cross-network exchange of assets (fungible assets for now)') + print.info("Cross-network exchange of assets (fungible assets for now)"); // Checking the receipt of inputs if (!options.network1) { - print.error('Network1 ID not provided.') - return + print.error("Network1 ID not provided."); + return; } if (!options.network2) { - print.error('Network2 ID not provided.') - return + print.error("Network2 ID not provided."); + return; } if (!options.amount) { - print.error('Amount not provided.') - return + print.error("Amount not provided."); + return; } if (!options.timeout) { - print.error('Timeout not provided.') - return + print.error("Timeout not provided."); + return; } // Retrieving networkConfigs - const network1Config = getNetworkConfig(options.network1) - console.log(network1Config) - const network2Config = getNetworkConfig(options.network2) - console.log(network2Config) - console.log('Token contract 1', network1Config.tokenContract) + const network1Config = getNetworkConfig(options.network1); + console.log(network1Config); + const network2Config = getNetworkConfig(options.network2); + console.log(network2Config); + console.log("Token contract 1", network1Config.tokenContract); - console.log('Interop contract 1', network1Config.interopContract) - console.log('Sender 1', network1Config.senderAccountIndex) - console.log('Receiver 1', network1Config.recipientAccountIndex) - console.log('Token contract 2', network2Config.tokenContract) - console.log('Interop contract 2', network2Config.interopContract) - console.log('Sender 2', network2Config.senderAccountIndex) - console.log('Receiver 2', network2Config.recipientAccountIndex) - console.log('Amount', options.amount) - console.log('Timeout', options.timeout) + console.log("Interop contract 1", network1Config.interopContract); + console.log("Sender 1", network1Config.senderAccountIndex); + console.log("Receiver 1", network1Config.recipientAccountIndex); + console.log("Token contract 2", network2Config.tokenContract); + console.log("Interop contract 2", network2Config.interopContract); + console.log("Sender 2", network2Config.senderAccountIndex); + console.log("Receiver 2", network2Config.recipientAccountIndex); + console.log("Amount", options.amount); + console.log("Timeout", options.timeout); const provider1 = new Web3.providers.HttpProvider( - 'http://' + network1Config.networkHost + ':' + network1Config.networkPort - ) - var web3N = new Web3(provider1) + "http://" + network1Config.networkHost + ":" + network1Config.networkPort, + ); + var web3N = new Web3(provider1); const interopContract1 = await getContractInstance( provider1, - network1Config.interopContract - ).catch(function() { - console.log('Failed getting interopContract1!') - return - }) + network1Config.interopContract, + ).catch(function () { + console.log("Failed getting interopContract1!"); + return; + }); const tokenContract1 = await getContractInstance( provider1, - network1Config.tokenContract - ).catch(function() { - console.log('Failed getting tokenContract1!') - return - }) - const accounts1 = await web3N.eth.getAccounts() + network1Config.tokenContract, + ).catch(function () { + console.log("Failed getting tokenContract1!"); + return; + }); + const accounts1 = await web3N.eth.getAccounts(); const provider2 = new Web3.providers.HttpProvider( - 'http://' + network2Config.networkHost + ':' + network2Config.networkPort - ) - var web3N = new Web3(provider2) + "http://" + network2Config.networkHost + ":" + network2Config.networkPort, + ); + var web3N = new Web3(provider2); const interopContract2 = await getContractInstance( provider2, - network2Config.interopContract - ).catch(function() { - console.log('Failed getting interopContract2!') - return - }) + network2Config.interopContract, + ).catch(function () { + console.log("Failed getting interopContract2!"); + return; + }); const tokenContract2 = await getContractInstance( provider2, - network2Config.tokenContract - ).catch(function() { - console.log('Failed getting tokenContract2!') - return - }) - const accounts2 = await web3N.eth.getAccounts() + network2Config.tokenContract, + ).catch(function () { + console.log("Failed getting tokenContract2!"); + return; + }); + const accounts2 = await web3N.eth.getAccounts(); // Receving the input parameters - const amount = options.amount - const sender1 = accounts1[network1Config.senderAccountIndex] - const recipient1 = accounts1[network1Config.recipientAccountIndex] - const sender2 = accounts2[network2Config.senderAccountIndex] - const recipient2 = accounts2[network2Config.recipientAccountIndex] - const timeLock = Math.floor(Date.now() / 1000) + options.timeout - var hash = options.hash - var preimage + const amount = options.amount; + const sender1 = accounts1[network1Config.senderAccountIndex]; + const recipient1 = accounts1[network1Config.recipientAccountIndex]; + const sender2 = accounts2[network2Config.senderAccountIndex]; + const recipient2 = accounts2[network2Config.recipientAccountIndex]; + const timeLock = Math.floor(Date.now() / 1000) + options.timeout; + let hash = options.hash; + let preimage; // Generate a hash pair if not provided as an input parameter if (!hash) { - preimage = crypto.randomBytes(32) - hash = crypto - .createHash('sha256') - .update(preimage) - .digest() - console.log('Preimage: ', preimage) - console.log('Hash: ', hash) + preimage = crypto.randomBytes(32); + hash = crypto.createHash("sha256").update(preimage).digest(); + console.log("Preimage: ", preimage); + console.log("Hash: ", hash); } // ------------ Locking in Network 1 ------------- // Balances of sender and receiver before locking in Network 1 - console.log(`Account balances before locking in Network 1`) - await getBalances(tokenContract1, sender1, recipient1) + console.log(`Account balances before locking in Network 1`); + await getBalances(tokenContract1, sender1, recipient1); // Locking the asset (works only for ERC20 at this point) await tokenContract1 .approve(interopContract1.address, amount, { from: sender1 }) - .catch(function() { - console.log('Token1 approval failed!!!') - return - }) + .catch(function () { + console.log("Token1 approval failed!!!"); + return; + }); const lockTx1 = await interopContract1 .lockAsset(recipient1, tokenContract1.address, amount, hash, timeLock, { - from: sender1 - }) - .catch(function() { - console.log('lockAsset threw an error in Network 1') - return + from: sender1, }) - const lockContractId1 = lockTx1.logs[0].args.lockContractId - console.log('Lock contract1 ID: ', lockContractId1) + .catch(function () { + console.log("lockAsset threw an error in Network 1"); + return; + }); + const lockContractId1 = lockTx1.logs[0].args.lockContractId; + console.log("Lock contract1 ID: ", lockContractId1); // Balances of sender and receiver after locking in Network 1 - console.log(`Account balances after locking in Network 1`) - await getBalances(tokenContract1, sender1, recipient1) + console.log(`Account balances after locking in Network 1`); + await getBalances(tokenContract1, sender1, recipient1); // ------------ Locking in Network 2 ------------- // Balances of sender and receiver before locking in Network 2 - console.log(`Account balances before locking in Network 2`) - await getBalances(tokenContract2, sender2, recipient2) + console.log(`Account balances before locking in Network 2`); + await getBalances(tokenContract2, sender2, recipient2); // Locking the asset (works only for ERC20 at this point) await tokenContract2 .approve(interopContract2.address, amount, { from: sender2 }) - .catch(async function() { - console.log('Token2 approval failed!!!') + .catch(async function () { + console.log("Token2 approval failed!!!"); await interopContract1 .unlockAsset(lockContractId1, { - from: sender1 + from: sender1, }) - .catch(function() { - console.log('unlockAsset threw an error in Network 1') - }) - return - }) + .catch(function () { + console.log("unlockAsset threw an error in Network 1"); + }); + return; + }); const lockTx2 = await interopContract2 .lockAsset(recipient2, tokenContract2.address, amount, hash, timeLock, { - from: sender2 + from: sender2, }) - .catch(async function() { - console.log('lockAsset threw an error in Network 2') + .catch(async function () { + console.log("lockAsset threw an error in Network 2"); await interopContract1 .unlockAsset(lockContractId1, { - from: sender1 - }) - .catch(function() { - console.log('unlockAsset threw an error in Network 1') + from: sender1, }) - return - }) - const lockContractId2 = lockTx2.logs[0].args.lockContractId - console.log(`Lock contract2 ID: ${lockContractId2}`) + .catch(function () { + console.log("unlockAsset threw an error in Network 1"); + }); + return; + }); + const lockContractId2 = lockTx2.logs[0].args.lockContractId; + console.log(`Lock contract2 ID: ${lockContractId2}`); // Balances of sender and receiver after locking in Network 2 - console.log(`Account balances after locking in Network 2`) - await getBalances(tokenContract2, sender2, recipient2) + console.log(`Account balances after locking in Network 2`); + await getBalances(tokenContract2, sender2, recipient2); // ------------ Withdrawal in Network 1 ------------- await interopContract1 .claimAsset(lockContractId1, preimage, { from: recipient1 }) - .catch(async function() { - console.log('claimAsset threw an error in Network 1') + .catch(async function () { + console.log("claimAsset threw an error in Network 1"); await interopContract1 .unlockAsset(lockContractId1, { - from: sender1 - }) - .catch(function() { - console.log('unlockAsset threw an error in Network 1') + from: sender1, }) + .catch(function () { + console.log("unlockAsset threw an error in Network 1"); + }); await interopContract2 .unlockAsset(lockContractId2, { - from: sender2 - }) - .catch(function() { - console.log('unlockAsset threw an error in Network 2') + from: sender2, }) - return - }) - console.log(`Account balances after withdrawal in Network 1`) - await getBalances(tokenContract1, sender1, recipient1) + .catch(function () { + console.log("unlockAsset threw an error in Network 2"); + }); + return; + }); + console.log(`Account balances after withdrawal in Network 1`); + await getBalances(tokenContract1, sender1, recipient1); // ------------ Withdrawal in Network 2 ------------- await interopContract2 .claimAsset(lockContractId2, preimage, { from: recipient2 }) - .catch(function() { - console.log('claimAsset threw an error in Network 2') - return - }) - console.log(`Account balances after withdrawal in Network 2`) - await getBalances(tokenContract2, sender2, recipient2) + .catch(function () { + console.log("claimAsset threw an error in Network 2"); + return; + }); + console.log(`Account balances after withdrawal in Network 2`); + await getBalances(tokenContract2, sender2, recipient2); // TODO: check whether the claim is successful - process.exit() - } -} + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/get-balance.ts b/weaver/samples/besu/besu-cli/src/commands/asset/get-balance.ts index d4914d3232..09d62eb5f1 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/get-balance.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/get-balance.ts @@ -4,106 +4,106 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -const Web3 = require('web3') +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +const Web3 = require("web3"); const command: GluegunCommand = { - name: 'get-balance', - description: 'Get account balance of tokens', + name: "get-balance", + description: "Get account balance of tokens", - run: async toolbox => { + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset get-balance --network=network1 --account=1`, - 'besu-cli asset get-balance --network= --account=<1|2> --account_address= --network_port= --network_host=', + "besu-cli asset get-balance --network= --account=<1|2> --account_address= --network_port= --network_host=", [ { - name: '--network', - description: 'network for command. ' + name: "--network", + description: "network for command. ", }, { - name: '--account', + name: "--account", description: - 'The index of the account from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.' + "The index of the account from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.", }, { - name: '--account_address', + name: "--account_address", description: - 'The address of the account. We can set this parameter if we want to use account address instead of account index ' + "The address of the account. We can set this parameter if we want to use account address instead of account index ", }, { - name: '--network_host', + name: "--network_host", description: - 'The network host. Default value is taken from config.json' + "The network host. Default value is taken from config.json", }, { - name: '--network_port', + name: "--network_port", description: - 'The network port. Default value is taken from config.json' - } + "The network port. Default value is taken from config.json", + }, ], command, - ['asset', 'get-balance'] - ) - return + ["asset", "get-balance"], + ); + return; } - print.info('Get account balance of tokens') - const networkConfig = getNetworkConfig(options.network) + print.info("Get account balance of tokens"); + const networkConfig = getNetworkConfig(options.network); - var networkPort = networkConfig.networkPort + let networkPort = networkConfig.networkPort; if (options.network_port) { - networkPort = options.network_port - console.log('Use network port : ', networkPort) + networkPort = options.network_port; + console.log("Use network port : ", networkPort); } - var networkHost = networkConfig.networkHost + let networkHost = networkConfig.networkHost; if (options.network_host) { - networkHost = options.network_host - console.log('Use network host : ', networkHost) + networkHost = options.network_host; + console.log("Use network host : ", networkHost); } const provider = new Web3.providers.HttpProvider( - 'http://' + networkHost + ':' + networkPort - ) - const web3N = new Web3(provider) - const accounts = await web3N.eth.getAccounts() + "http://" + networkHost + ":" + networkPort, + ); + const web3N = new Web3(provider); + const accounts = await web3N.eth.getAccounts(); - console.log(networkConfig.tokenContract) + console.log(networkConfig.tokenContract); const tokenContract = await getContractInstance( provider, - networkConfig.tokenContract - ).catch(function() { - console.log('Failed getting tokenContract!') - }) + networkConfig.tokenContract, + ).catch(function () { + console.log("Failed getting tokenContract!"); + }); - var accountAddress + let accountAddress; if (options.account) { - accountAddress = accounts[options.account] + accountAddress = accounts[options.account]; } else if (options.account_address) { - accountAddress = '0x' + options.account_address + accountAddress = "0x" + options.account_address; } else { - print.error('Account index not provided') - return + print.error("Account index not provided"); + return; } - console.log('Parameters') - console.log('networkConfig', networkConfig) - console.log('Account', accountAddress) - var balance = await tokenContract.balanceOf(accountAddress) + console.log("Parameters"); + console.log("networkConfig", networkConfig); + console.log("Account", accountAddress); + const balance = await tokenContract.balanceOf(accountAddress); console.log( `Account balance of ${accountAddress} in Network ${ options.network - }: ${balance.toString()}` - ) - process.exit() - } -} + }: ${balance.toString()}`, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/is-locked.ts b/weaver/samples/besu/besu-cli/src/commands/asset/is-locked.ts index 6932bf2540..493c3f4a26 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/is-locked.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/is-locked.ts @@ -4,99 +4,100 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -import { AssetManager } from '@hyperledger/cacti-weaver-sdk-besu' -const Web3 = require('web3') +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +import { AssetManager } from "@hyperledger/cacti-weaver-sdk-besu"; +const Web3 = require("web3"); const command: GluegunCommand = { - name: 'is-locked', + name: "is-locked", description: - 'Check if a contract exists, which also checks if an asset is locked', + "Check if a contract exists, which also checks if an asset is locked", - run: async toolbox => { + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset is-locked --network=network1 --lock_contract_id=lockContractID`, - 'besu-cli asset is-locked --network= --lock_contract_id= --network_port= --network_host=', + "besu-cli asset is-locked --network= --lock_contract_id= --network_port= --network_host=", [ { - name: '--network', - description: 'network for command. ' + name: "--network", + description: "network for command. ", }, { - name: '--lock-contract-id', - description: 'The address / ID of the lock contract.' + name: "--lock-contract-id", + description: "The address / ID of the lock contract.", }, { - name: '--network_host', + name: "--network_host", description: - 'The network host. Default value is taken from config.json' + "The network host. Default value is taken from config.json", }, { - name: '--network_port', + name: "--network_port", description: - 'The network port. Default value is taken from config.json' - } + "The network port. Default value is taken from config.json", + }, ], command, - ['asset', 'is-locked'] - ) - return + ["asset", "is-locked"], + ); + return; } print.info( - 'Check if a contract exists, which also checks if an asset is locked' - ) - const networkConfig = getNetworkConfig(options.network) + "Check if a contract exists, which also checks if an asset is locked", + ); + const networkConfig = getNetworkConfig(options.network); if (!options.lock_contract_id) { - print.error('Lock contract ID not provided.') - return + print.error("Lock contract ID not provided."); + return; } - const lockContractId = '0x' + options.lock_contract_id + const lockContractId = "0x" + options.lock_contract_id; - console.log('Parameters') - console.log('networkConfig', networkConfig) - console.log('Lock Contract ID', lockContractId) + console.log("Parameters"); + console.log("networkConfig", networkConfig); + console.log("Lock Contract ID", lockContractId); - var networkPort = networkConfig.networkPort + let networkPort = networkConfig.networkPort; if (options.network_port) { - networkPort = options.network_port - console.log('Use network port : ', networkPort) + networkPort = options.network_port; + console.log("Use network port : ", networkPort); } - var networkHost = networkConfig.networkHost + let networkHost = networkConfig.networkHost; if (options.network_host) { - networkHost = options.network_host - console.log('Use network host : ', networkHost) + networkHost = options.network_host; + console.log("Use network host : ", networkHost); } const provider = new Web3.providers.HttpProvider( - 'http://' + networkHost + ':' + networkPort - ) + "http://" + networkHost + ":" + networkPort, + ); // const web3N = new Web3(provider) const interopContract = await getContractInstance( provider, - networkConfig.interopContract - ) + networkConfig.interopContract, + ); // const accounts = await web3N.eth.getAccounts() // var sender = accounts[networkConfig.senderAccountIndex] - var isLocked = await AssetManager - .isAssetLockedInHTLC(interopContract, lockContractId) - .catch(function() { - console.log('isAssetLocked threw an error') - }) + const isLocked = await AssetManager.isAssetLockedInHTLC( + interopContract, + lockContractId, + ).catch(function () { + console.log("isAssetLocked threw an error"); + }); console.log( - `Is there an asset locked in ${lockContractId} in Network ${options.network}: ${isLocked}` - ) //Todo: Debug. isLocked is not printing correctly. - process.exit() - } -} + `Is there an asset locked in ${lockContractId} in Network ${options.network}: ${isLocked}`, + ); //Todo: Debug. isLocked is not printing correctly. + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/issue.ts b/weaver/samples/besu/besu-cli/src/commands/asset/issue.ts index 2056c364cb..9ffa054dba 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/issue.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/issue.ts @@ -4,189 +4,191 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -const Web3 = require('web3') +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +const Web3 = require("web3"); const command: GluegunCommand = { - name: 'issue', - description: 'Issuance of tokens', - run: async toolbox => { + name: "issue", + description: "Issuance of tokens", + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset issue --network=network1 --account=1 --amount=10`, - 'besu-cli asset issue --network= --account= --account_address= --contract_owner_address= --amount= --network_port= --network_host= ', + "besu-cli asset issue --network= --account= --account_address= --contract_owner_address= --amount= --network_port= --network_host= ", [ { - name: '--network', - description: 'network for command. ' + name: "--network", + description: "network for command. ", }, { - name: '--account', + name: "--account", description: - 'The index of the account from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.' + "The index of the account from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.", }, { - name: '--account_address', + name: "--account_address", description: - 'The address of the account. We can set this parameter if we want to use account address instead of account index ' + "The address of the account. We can set this parameter if we want to use account address instead of account index ", }, { - name: '--contract_owner_address', + name: "--contract_owner_address", description: - 'The address of the contract owner. The default value is accounts[0] ' + "The address of the contract owner. The default value is accounts[0] ", }, { - name: '--amount', + name: "--amount", description: - 'The amount to be added to the account specified on the network' + "The amount to be added to the account specified on the network", }, { - name: '--network_host', + name: "--network_host", description: - 'The network host. Default value is taken from config.json' + "The network host. Default value is taken from config.json", }, { - name: '--network_port', + name: "--network_port", description: - 'The network port. Default value is taken from config.json' + "The network port. Default value is taken from config.json", }, { - name: '--asset_type', + name: "--asset_type", description: - 'Asset type for issuing tokens. Default value is ERC20, other options are ERC721, ERC1155' + "Asset type for issuing tokens. Default value is ERC20, other options are ERC721, ERC1155", }, { - name: '--token_id', + name: "--token_id", description: - 'token ID for issuing tokens. Only applicable for ERC721, ERC1155' + "token ID for issuing tokens. Only applicable for ERC721, ERC1155", }, { - name: '--token_data', + name: "--token_data", description: - 'token data for issuing tokens. Only applicable for ERC1155' - } + "token data for issuing tokens. Only applicable for ERC1155", + }, ], command, - ['asset', 'issue'] - ) - return + ["asset", "issue"], + ); + return; } - print.info('Issuance of tokens') + print.info("Issuance of tokens"); if (!options.network) { - print.error('Network ID not provided.') - return + print.error("Network ID not provided."); + return; } - const networkConfig = getNetworkConfig(options.network) - console.log('networkConfig', networkConfig) + const networkConfig = getNetworkConfig(options.network); + console.log("networkConfig", networkConfig); - var networkPort = networkConfig.networkPort + let networkPort = networkConfig.networkPort; if (options.network_port) { - networkPort = options.network_port - console.log('Use network port : ', networkPort) + networkPort = options.network_port; + console.log("Use network port : ", networkPort); } - var networkHost = networkConfig.networkHost + let networkHost = networkConfig.networkHost; if (options.network_host) { - networkHost = options.network_host - console.log('Use network host : ', networkHost) + networkHost = options.network_host; + console.log("Use network host : ", networkHost); } const provider = new Web3.providers.HttpProvider( - 'http://' + networkHost + ':' + networkPort - ) - const web3N = new Web3(provider) + "http://" + networkHost + ":" + networkPort, + ); + const web3N = new Web3(provider); const tokenContract = await getContractInstance( provider, - networkConfig.tokenContract - ).catch(function() { - console.log('Failed getting tokenContract!') - }) - const accounts = await web3N.eth.getAccounts() + networkConfig.tokenContract, + ).catch(function () { + console.log("Failed getting tokenContract!"); + }); + const accounts = await web3N.eth.getAccounts(); - var contractOwner = accounts[0] + let contractOwner = accounts[0]; if (options.contract_owner_address) { - contractOwner = '0x' + options.contract_owner_address + contractOwner = "0x" + options.contract_owner_address; } - var account + let account; if (options.account) { - account = accounts[options.account] + account = accounts[options.account]; } else if (options.account_address) { - account = '0x' + options.account_address + account = "0x" + options.account_address; } else { - account = accounts[networkConfig.senderAccountIndex] + account = accounts[networkConfig.senderAccountIndex]; } if (!options.amount) { - print.error('Amount not provided') - options.amount = 1 + print.error("Amount not provided"); + options.amount = 1; } if (!options.asset_type) { - options.asset_type = 'ERC20' + options.asset_type = "ERC20"; } if (!options.token_id) { - options.token_id = 0 + options.token_id = 0; } if (!options.token_data) { - options.token_data = 0 + options.token_data = 0; } - console.log(`Contract owner address is ${contractOwner} `) - console.log(`Receiver address is ${account} `) - console.log(`Token contract is ${tokenContract.address} `) + console.log(`Contract owner address is ${contractOwner} `); + console.log(`Receiver address is ${account} `); + console.log(`Token contract is ${tokenContract.address} `); // Transfer from the contract owner to the account specified - if (options.asset_type == 'ERC20') { + if (options.asset_type == "ERC20") { await tokenContract .transfer(account, options.amount, { from: contractOwner }) - .catch(function() { + .catch(function () { console.log( - 'tokenContract transfer threw an error; Probably the token supply is used up!' - ) - }) - } else if (options.asset_type == 'ERC721') { + "tokenContract transfer threw an error; Probably the token supply is used up!", + ); + }); + } else if (options.asset_type == "ERC721") { const response = await tokenContract .mint(account, { from: contractOwner }) - .catch(function() { + .catch(function () { console.log( - 'tokenContract transfer threw an error; Probably the token supply is used up!' - ) - }) - console.log(`New ERC721 token minted with id ${response.logs[0].args.tokenId}`) - } else if (options.asset_type == 'ERC1155') { + "tokenContract transfer threw an error; Probably the token supply is used up!", + ); + }); + console.log( + `New ERC721 token minted with id ${response.logs[0].args.tokenId}`, + ); + } else if (options.asset_type == "ERC1155") { await tokenContract .mint( account, options.token_id, options.amount, Web3.utils.utf8ToHex(options.token_data), - { from: contractOwner } + { from: contractOwner }, ) - .catch(function() { + .catch(function () { console.log( - 'tokenContract transfer threw an error; Probably the token supply is used up!' - ) - }) + "tokenContract transfer threw an error; Probably the token supply is used up!", + ); + }); } - if (options.asset_type == 'ERC1155') { - var balance = await tokenContract.balanceOf(account, options.token_id) - } else var balance = await tokenContract.balanceOf(account) + if (options.asset_type == "ERC1155") { + var balance = await tokenContract.balanceOf(account, options.token_id); + } else var balance = await tokenContract.balanceOf(account); console.log( `Account balance of ${account} in Network ${ options.network - }: ${balance.toString()}` - ) - process.exit() - } -} + }: ${balance.toString()}`, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/lock.ts b/weaver/samples/besu/besu-cli/src/commands/asset/lock.ts index cea53996e0..0e0f168cac 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/lock.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/lock.ts @@ -4,338 +4,347 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -import { AssetManager } from '@hyperledger/cacti-weaver-sdk-besu' +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +import { AssetManager } from "@hyperledger/cacti-weaver-sdk-besu"; import { HashFunctions } from "@hyperledger/cacti-weaver-sdk-besu"; -const Web3 = require('web3') -const crypto = require('crypto') +const Web3 = require("web3"); +const crypto = require("crypto"); async function getBalances( tokenContract, address, token_id = 0, - asset_type = 'ERC20' + asset_type = "ERC20", ) { - if (asset_type == 'ERC1155') return tokenContract.balanceOf(address, token_id) - return tokenContract.balanceOf(address) + if (asset_type == "ERC1155") + return tokenContract.balanceOf(address, token_id); + return tokenContract.balanceOf(address); } const command: GluegunCommand = { - name: 'lock', - description: 'Lock assets', + name: "lock", + description: "Lock assets", - run: async toolbox => { + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --amount=5 --timeout=1000`, - 'besu-cli asset lock --network= --sender_account=<1|2> --recipient_account=<2|1> --amount= --timeout= --hash_base64= --recipient_account_address= --sender_account_address= --network_port= --network_host= ', + "besu-cli asset lock --network= --sender_account=<1|2> --recipient_account=<2|1> --amount= --timeout= --hash_base64= --recipient_account_address= --sender_account_address= --network_port= --network_host= ", [ { - name: '--network', - description: 'network for command. ' + name: "--network", + description: "network for command. ", }, { - name: '--sender_account', + name: "--sender_account", description: - 'The index of the account of the sender/owner of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.' + "The index of the account of the sender/owner of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.", }, { - name: '--sender_account_address', + name: "--sender_account_address", description: - 'The address of the sender account. We can set this parameter if we want to use account address instead of account index ' + "The address of the sender account. We can set this parameter if we want to use account address instead of account index ", }, { - name: '--recipient_account', + name: "--recipient_account", description: - 'The index of the account of the recipient of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.' + "The index of the account of the recipient of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.", }, { - name: '--recipient_account_address', + name: "--recipient_account_address", description: - 'The address of the recipient account. We can set this parameter if we want to use account address instead of account index ' + "The address of the recipient account. We can set this parameter if we want to use account address instead of account index ", }, { - name: '--amount', + name: "--amount", description: - 'The amount of fungible assets to be locked from the sender account specified on the network' + "The amount of fungible assets to be locked from the sender account specified on the network", }, { - name: '--timeout', + name: "--timeout", description: - 'Time in seconds for which the asset will be locked. The asset will be locked till Date.now() + the timeout provided' + "Time in seconds for which the asset will be locked. The asset will be locked till Date.now() + the timeout provided", }, { - name: '--hash_base64', + name: "--hash_base64", description: - 'The hash value with which the asset will be locked i.e., providing its pre-image will enable unlocking the asset. This is an optional parameter. If not provided, we will generate a fresh hash pair with a randomly generated pre-image and output the corresponding pre-image.' + "The hash value with which the asset will be locked i.e., providing its pre-image will enable unlocking the asset. This is an optional parameter. If not provided, we will generate a fresh hash pair with a randomly generated pre-image and output the corresponding pre-image.", }, { - name: '--network_host', + name: "--network_host", description: - 'The network host. Default value is taken from config.json' + "The network host. Default value is taken from config.json", }, { - name: '--network_port', + name: "--network_port", description: - 'The network port. Default value is taken from config.json' + "The network port. Default value is taken from config.json", }, { - name: '--token_id', + name: "--token_id", description: - 'Specify the token id for which the asset is to be locked. This is an optional parameter only for ERC721 & ERC1155.' + "Specify the token id for which the asset is to be locked. This is an optional parameter only for ERC721 & ERC1155.", }, { - name: '--data', + name: "--data", description: - 'Specify the data for ERC1155 token. This is an optional parameter only for ERC1155.' + "Specify the data for ERC1155 token. This is an optional parameter only for ERC1155.", }, { - name: '--asset_type', + name: "--asset_type", description: - 'Specify the asset type. This is an optional parameter only for ERC721 & ERC1155.' - } + "Specify the asset type. This is an optional parameter only for ERC721 & ERC1155.", + }, ], command, - ['asset', 'lock'] - ) - return + ["asset", "lock"], + ); + return; } - print.info('Lock assets') + print.info("Lock assets"); // Retrieving networkConfig if (!options.network) { - print.error('Network ID not provided.') - return + print.error("Network ID not provided."); + return; } - const networkConfig = getNetworkConfig(options.network) + const networkConfig = getNetworkConfig(options.network); - var networkPort = networkConfig.networkPort + let networkPort = networkConfig.networkPort; if (options.network_port) { - networkPort = options.network_port - console.log('Use network port : ', networkPort) + networkPort = options.network_port; + console.log("Use network port : ", networkPort); } - var networkHost = networkConfig.networkHost + let networkHost = networkConfig.networkHost; if (options.network_host) { - networkHost = options.network_host - console.log('Use network host : ', networkHost) + networkHost = options.network_host; + console.log("Use network host : ", networkHost); } if (!options.asset_type) { - options.asset_type = 'ERC20' + options.asset_type = "ERC20"; } const provider = new Web3.providers.HttpProvider( - 'http://' + networkHost + ':' + networkPort - ) - const web3N = new Web3(provider) + "http://" + networkHost + ":" + networkPort, + ); + const web3N = new Web3(provider); const interopContract = await getContractInstance( provider, - networkConfig.interopContract + networkConfig.interopContract, ).catch(function () { - console.log('Failed getting interopContract!') - }) + console.log("Failed getting interopContract!"); + }); const tokenContract = await getContractInstance( provider, - networkConfig.tokenContract + networkConfig.tokenContract, ).catch(function () { - console.log('Failed getting tokenContract!') - }) - const accounts = await web3N.eth.getAccounts() + console.log("Failed getting tokenContract!"); + }); + const accounts = await web3N.eth.getAccounts(); // Receving the input parameters if (!options.amount) { - print.error('Amount not provided.') - options.amount = 1 + print.error("Amount not provided."); + options.amount = 1; } - const amount = options.amount - var sender + const amount = options.amount; + let sender; if (options.sender_account) { - sender = accounts[options.sender_account] + sender = accounts[options.sender_account]; } else if (options.sender_account_address) { - sender = '0x' + options.sender_account_address + sender = "0x" + options.sender_account_address; } else { print.info( - 'Sender account index not provided. Taking from networkConfig..' - ) - sender = accounts[networkConfig.senderAccountIndex] + "Sender account index not provided. Taking from networkConfig..", + ); + sender = accounts[networkConfig.senderAccountIndex]; } - var recipient + let recipient; if (options.recipient_account) { - recipient = accounts[options.recipient_account] + recipient = accounts[options.recipient_account]; } else if (options.recipient_account_address) { - recipient = '0x' + options.recipient_account_address + recipient = "0x" + options.recipient_account_address; } else { print.info( - 'Recipient account index not provided. Taking from networkConfig..' - ) - recipient = accounts[networkConfig.recipientAccountIndex] + "Recipient account index not provided. Taking from networkConfig..", + ); + recipient = accounts[networkConfig.recipientAccountIndex]; } if (!options.timeout) { - print.error('Timeout not provided.') - return + print.error("Timeout not provided."); + return; } if (!options.token_id) { - options.token_id = 0 + options.token_id = 0; } if (!options.data) { - options.data = '' + options.data = ""; } - const timeLock = Math.floor(Date.now() / 1000) + options.timeout + const timeLock = Math.floor(Date.now() / 1000) + options.timeout; // The hash input has to be dealt with care. The smart contracts take in bytes as input. But the cli takes in strings as input. So to handle that, we take in the hash in its base64 version as input and then obtain the byte array from this. If a hash is not provided, we generate a base 64 encoding and then generate its corresponding byte array from it. This byte array will be input to generate the hash. - var preimage - var hash_base64 - var preimage_bytes + let preimage; + let hash_base64; + let preimage_bytes; if (options.hash_base64) { - hash_base64 = options.hash_base64 + hash_base64 = options.hash_base64; } else { // Generate a hash pair if not provided as an input parameter - preimage = crypto.randomBytes(22).toString('base64') + preimage = crypto.randomBytes(22).toString("base64"); hash_base64 = crypto - .createHash('sha256') + .createHash("sha256") .update(preimage) - .digest('base64') - preimage_bytes = Buffer.from(preimage) - console.log('Length of preimage byte array', preimage_bytes.length) + .digest("base64"); + preimage_bytes = Buffer.from(preimage); + console.log("Length of preimage byte array", preimage_bytes.length); } - console.log('Parameters:') - console.log('networkConfig', networkConfig) - console.log('Sender', sender) - console.log('Receiver', recipient) - console.log('Amount', options.amount) - console.log('Timeout', timeLock) - console.log('Hash (base64): ', hash_base64) - console.log('Preimage: ', preimage) - + console.log("Parameters:"); + console.log("networkConfig", networkConfig); + console.log("Sender", sender); + console.log("Receiver", recipient); + console.log("Amount", options.amount); + console.log("Timeout", timeLock); + console.log("Hash (base64): ", hash_base64); + console.log("Preimage: ", preimage); + const hash = new HashFunctions.SHA256(); - hash.setSerializedHashBase64(hash_base64) + hash.setSerializedHashBase64(hash_base64); // Balances of sender and receiver before locking - console.log(`Account balances before locking`) + console.log(`Account balances before locking`); var senderBalance = await getBalances( tokenContract, sender, options.token_id, - options.asset_type - ) + options.asset_type, + ); console.log( - `Account balance of the sender in Network ${options.network - }: ${senderBalance.toString()}` - ) + `Account balance of the sender in Network ${ + options.network + }: ${senderBalance.toString()}`, + ); var recipientBalance = await getBalances( tokenContract, recipient, options.token_id, - options.asset_type - ) + options.asset_type, + ); console.log( - `Account balance of the recipient in Network ${options.network - }: ${recipientBalance.toString()}` - ) + `Account balance of the recipient in Network ${ + options.network + }: ${recipientBalance.toString()}`, + ); let lockTx; // Locking the asset (works only for ERC20 at this point) - if (options.asset_type == 'ERC721') { - await tokenContract - .approve(tokenContract.address, options.token_id, { from: sender }) - try { - lockTx = await AssetManager.createHTLC( - interopContract, - tokenContract, - options.asset_type, - String(options.token_id), - sender, - recipient, - timeLock, - hash - ) - } catch(e) { - console.log(e) - console.log('createHTLC threw an error', e) - return - } - } else if (options.asset_type == 'ERC1155') { - await tokenContract - .setApprovalForAll(tokenContract.address, true, { from: sender }) - try { - lockTx = await AssetManager.createHybridHTLC( - interopContract, - tokenContract, - options.asset_type, - String(options.token_id), - Web3.utils.utf8ToHex(options.data), - amount, - sender, - recipient, - timeLock, - hash - ) - } catch(e) { - console.log(e) - console.log('createHybridHTLC threw an error', e) - return - } + if (options.asset_type == "ERC721") { + await tokenContract.approve(tokenContract.address, options.token_id, { + from: sender, + }); + try { + lockTx = await AssetManager.createHTLC( + interopContract, + tokenContract, + options.asset_type, + String(options.token_id), + sender, + recipient, + timeLock, + hash, + ); + } catch (e) { + console.log(e); + console.log("createHTLC threw an error", e); + return; + } + } else if (options.asset_type == "ERC1155") { + await tokenContract.setApprovalForAll(tokenContract.address, true, { + from: sender, + }); + try { + lockTx = await AssetManager.createHybridHTLC( + interopContract, + tokenContract, + options.asset_type, + String(options.token_id), + Web3.utils.utf8ToHex(options.data), + amount, + sender, + recipient, + timeLock, + hash, + ); + } catch (e) { + console.log(e); + console.log("createHybridHTLC threw an error", e); + return; + } } else { - await tokenContract - .approve(tokenContract.address, amount, { from: sender }) - try { - lockTx = await AssetManager.createFungibleHTLC( - interopContract, - tokenContract, - options.asset_type, - amount, - sender, - recipient, - timeLock, - hash - ) - } catch(e) { - console.log(e) - console.log('createFungibleHTLC threw an error', e) - return - } + await tokenContract.approve(tokenContract.address, amount, { + from: sender, + }); + try { + lockTx = await AssetManager.createFungibleHTLC( + interopContract, + tokenContract, + options.asset_type, + amount, + sender, + recipient, + timeLock, + hash, + ); + } catch (e) { + console.log(e); + console.log("createFungibleHTLC threw an error", e); + return; + } } // const newHash = crypto.createHash('sha256').update(preimage).digest() - - + if (lockTx && lockTx.result) { - const lockContractId = lockTx.result.logs[0].args.lockContractId - console.log(`Lock contract ID: ${lockContractId.toString().substring(2)}`) + const lockContractId = lockTx.result.logs[0].args.lockContractId; + console.log( + `Lock contract ID: ${lockContractId.toString().substring(2)}`, + ); } // Balances of sender and receiver after locking - console.log(`Account balances after locking`) + console.log(`Account balances after locking`); var senderBalance = await getBalances( tokenContract, sender, options.token_id, - options.asset_type - ) + options.asset_type, + ); console.log( - `Account balance of the sender in Network ${options.network - }: ${senderBalance.toString()}` - ) + `Account balance of the sender in Network ${ + options.network + }: ${senderBalance.toString()}`, + ); var recipientBalance = await getBalances( tokenContract, recipient, options.token_id, - options.asset_type - ) + options.asset_type, + ); console.log( - `Account balance of the recipient in Network ${options.network - }: ${recipientBalance.toString()}` - ) - process.exit() - } -} + `Account balance of the recipient in Network ${ + options.network + }: ${recipientBalance.toString()}`, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/asset/unlock.ts b/weaver/samples/besu/besu-cli/src/commands/asset/unlock.ts index f7df0b1e44..0bc5cece0a 100644 --- a/weaver/samples/besu/besu-cli/src/commands/asset/unlock.ts +++ b/weaver/samples/besu/besu-cli/src/commands/asset/unlock.ts @@ -4,181 +4,183 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -import { AssetManager } from '@hyperledger/cacti-weaver-sdk-besu' +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +import { AssetManager } from "@hyperledger/cacti-weaver-sdk-besu"; // import { send } from 'process' -const Web3 = require('web3') +const Web3 = require("web3"); async function getBalances( tokenContract, address, token_id = 0, - asset_type = 'ERC20' + asset_type = "ERC20", ) { try { - var balance = await tokenContract.balanceOf(address, token_id) + var balance = await tokenContract.balanceOf(address, token_id); } catch { - var balance = null + var balance = null; } - if (!balance) return await tokenContract.balanceOf(address) - else return balance + if (!balance) return await tokenContract.balanceOf(address); + else return balance; } const command: GluegunCommand = { - name: 'unlock', + name: "unlock", description: - 'Unlock and reclaim assets after timeout (fungible assets for now)', + "Unlock and reclaim assets after timeout (fungible assets for now)", - run: async toolbox => { + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli asset unlock --network=network1 --lock_contract_id=lockContractID --sender_account=1`, - 'besu-cli asset unlock --network= --lock_contract_id= --sender_account=<1|2> --sender_account_address= --network_port= --network_host= ', + "besu-cli asset unlock --network= --lock_contract_id= --sender_account=<1|2> --sender_account_address= --network_port= --network_host= ", [ { - name: '--network', - description: 'network for command. ' + name: "--network", + description: "network for command. ", }, { - name: '--lock_contract_id', - description: 'The address / ID of the lock contract.' + name: "--lock_contract_id", + description: "The address / ID of the lock contract.", }, { - name: '--sender_account', + name: "--sender_account", description: - 'The index of the account of the sender of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.' + "The index of the account of the sender of the asset from the list obtained through web3.eth.getAccounts(). For example, we can set Alice as accounts[1] and hence value of this parameter for Alice can be 1.", }, { - name: '--sender_account_address', + name: "--sender_account_address", description: - 'The address of the sender account. We can set this parameter if we want to use account address instead of account index ' + "The address of the sender account. We can set this parameter if we want to use account address instead of account index ", }, { - name: '--network_host', + name: "--network_host", description: - 'The network host. Default value is taken from config.json' + "The network host. Default value is taken from config.json", }, { - name: '--network_port', + name: "--network_port", description: - 'The network port. Default value is taken from config.json' + "The network port. Default value is taken from config.json", }, { - name: '--token_id', + name: "--token_id", description: - 'token ID for issuing tokens. Only applicable for ERC721 and ERC1155. Default: 0' - } + "token ID for issuing tokens. Only applicable for ERC721 and ERC1155. Default: 0", + }, ], command, - ['asset', 'unlock'] - ) - return + ["asset", "unlock"], + ); + return; } print.info( - 'Unlock and reclaim assets after timeout (fungible assets for now)' - ) + "Unlock and reclaim assets after timeout (fungible assets for now)", + ); // Retrieving networkConfig if (!options.network) { - print.error('Network ID not provided.') - return + print.error("Network ID not provided."); + return; } if (!options.token_id) { - options.token_id=0 + options.token_id = 0; } - const networkConfig = getNetworkConfig(options.network) + const networkConfig = getNetworkConfig(options.network); - var networkPort = networkConfig.networkPort + let networkPort = networkConfig.networkPort; if (options.network_port) { - networkPort = options.network_port - console.log('Use network port : ', networkPort) + networkPort = options.network_port; + console.log("Use network port : ", networkPort); } - var networkHost = networkConfig.networkHost + let networkHost = networkConfig.networkHost; if (options.network_host) { - networkHost = options.network_host - console.log('Use network host : ', networkHost) + networkHost = options.network_host; + console.log("Use network host : ", networkHost); } const provider = new Web3.providers.HttpProvider( - 'http://' + networkHost + ':' + networkPort - ) - const web3N = new Web3(provider) + "http://" + networkHost + ":" + networkPort, + ); + const web3N = new Web3(provider); const interopContract = await getContractInstance( provider, - networkConfig.interopContract - ).catch(function() { - console.log('Failed getting interopContract!') - }) + networkConfig.interopContract, + ).catch(function () { + console.log("Failed getting interopContract!"); + }); const tokenContract = await getContractInstance( provider, - networkConfig.tokenContract - ).catch(function() { - console.log('Failed getting tokenContract!') - }) - const accounts = await web3N.eth.getAccounts() + networkConfig.tokenContract, + ).catch(function () { + console.log("Failed getting tokenContract!"); + }); + const accounts = await web3N.eth.getAccounts(); // Receiving the input parameters - var sender + let sender; if (options.sender_account) { - sender = accounts[options.sender_account] + sender = accounts[options.sender_account]; } else if (options.sender_account_address) { - sender = '0x' + options.sender_account_address + sender = "0x" + options.sender_account_address; } else { print.info( - 'Sender account index not provided. Taking from networkConfig..' - ) - sender = accounts[networkConfig.senderAccountIndex] + "Sender account index not provided. Taking from networkConfig..", + ); + sender = accounts[networkConfig.senderAccountIndex]; } if (!options.lock_contract_id) { - print.error('Lock contract ID not provided.') - return + print.error("Lock contract ID not provided."); + return; } - const lockContractId = '0x' + options.lock_contract_id + const lockContractId = "0x" + options.lock_contract_id; - console.log('Parameters') - console.log('networkConfig', networkConfig) - console.log('Sender', sender) - console.log('Lock Contract ID', lockContractId) + console.log("Parameters"); + console.log("networkConfig", networkConfig); + console.log("Sender", sender); + console.log("Lock Contract ID", lockContractId); // Balance of the recipient before claiming var senderBalance = await getBalances( tokenContract, sender, - options.token_id - ) + options.token_id, + ); console.log( `Account balance of the sender in Network ${ options.network - } before unlocking: ${senderBalance.toString()}` - ) + } before unlocking: ${senderBalance.toString()}`, + ); - await AssetManager - .reclaimAssetInHTLC(interopContract, lockContractId, sender) - .catch(function(e) { - console.log(e) - console.log('unlockAsset threw an error') - }) + await AssetManager.reclaimAssetInHTLC( + interopContract, + lockContractId, + sender, + ).catch(function (e) { + console.log(e); + console.log("unlockAsset threw an error"); + }); // Balance of the recipient after claiming var senderBalance = await getBalances( tokenContract, sender, - options.token_id - ) + options.token_id, + ); console.log( `Account balance of the sender in Network ${ options.network - } after unlocking: ${senderBalance.toString()}` - ) - process.exit() - } -} + } after unlocking: ${senderBalance.toString()}`, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/besu-cli.ts b/weaver/samples/besu/besu-cli/src/commands/besu-cli.ts index e8cc2aecf9..5e48b5f38c 100644 --- a/weaver/samples/besu/besu-cli/src/commands/besu-cli.ts +++ b/weaver/samples/besu/besu-cli/src/commands/besu-cli.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' +import { GluegunCommand } from "gluegun"; const command: GluegunCommand = { - name: 'besu-cli', - run: async toolbox => { - const { print } = toolbox + name: "besu-cli", + run: async (toolbox) => { + const { print } = toolbox; - print.info('Welcome to your CLI') - } -} + print.info("Welcome to your CLI"); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/generate.ts b/weaver/samples/besu/besu-cli/src/commands/generate.ts index d78accbb5c..4f85baa3f5 100644 --- a/weaver/samples/besu/besu-cli/src/commands/generate.ts +++ b/weaver/samples/besu/besu-cli/src/commands/generate.ts @@ -4,26 +4,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunToolbox } from 'gluegun' +import { GluegunToolbox } from "gluegun"; module.exports = { - name: 'generate', - alias: ['g'], + name: "generate", + alias: ["g"], run: async (toolbox: GluegunToolbox) => { const { parameters, template: { generate }, - print: { info } - } = toolbox + print: { info }, + } = toolbox; - const name = parameters.first + const name = parameters.first; await generate({ - template: 'model.ts.ejs', + template: "model.ts.ejs", target: `models/${name}-model.ts`, - props: { name } - }) + props: { name }, + }); - info(`Generated file at models/${name}-model.ts`) - } -} + info(`Generated file at models/${name}-model.ts`); + }, +}; diff --git a/weaver/samples/besu/besu-cli/src/commands/hash-helper.ts b/weaver/samples/besu/besu-cli/src/commands/hash-helper.ts index 9aea31e915..f698877e47 100644 --- a/weaver/samples/besu/besu-cli/src/commands/hash-helper.ts +++ b/weaver/samples/besu/besu-cli/src/commands/hash-helper.ts @@ -4,76 +4,78 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import logger from '../helper/logger' -import { commandHelp } from '../helper/helper' -import { HashFunctions } from '@hyperledger/cacti-weaver-sdk-besu' +import { GluegunCommand } from "gluegun"; +import logger from "../helper/logger"; +import { commandHelp } from "../helper/helper"; +import { HashFunctions } from "@hyperledger/cacti-weaver-sdk-besu"; const command: GluegunCommand = { - name: 'hash', - description: 'Get Hash for given pre image in base64', - run: async toolbox => { + name: "hash", + description: "Get Hash for given pre image in base64", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `besu-cli hash --hash_fn=SHA256 abc`, - 'besu-cli hash --hash_fn= --random ', + "besu-cli hash --hash_fn= --random ", [ { - name: '--hash_fn', + name: "--hash_fn", description: - 'hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)' + "hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)", }, { - name: '--random', + name: "--random", description: - 'Flag to generate random preimage with hash. (Array of preimage is not required if random is set)' + "Flag to generate random preimage with hash. (Array of preimage is not required if random is set)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['hash'] - ) - return + ["hash"], + ); + return; + } + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (!options["random"] && array.length == 0) { + print.error( + `Either set random flag, or provide preimage as array of strings, at end, separated by space`, + ); + return; } - if (!options['random'] && array.length==0) { - print.error(`Either set random flag, or provide preimage as array of strings, at end, separated by space`) - return - } // Hash - let hash: HashFunctions.Hash - if(options['hash_fn'] == 'SHA512') { - hash = new HashFunctions.SHA512() - if(!options['random']) { - hash.setPreimage(array[0]) - } + let hash: HashFunctions.Hash; + if (options["hash_fn"] == "SHA512") { + hash = new HashFunctions.SHA512(); + if (!options["random"]) { + hash.setPreimage(array[0]); + } } else { - hash = new HashFunctions.SHA256() - if(!options['random']) { - hash.setPreimage(array[0]) - } + hash = new HashFunctions.SHA256(); + if (!options["random"]) { + hash.setPreimage(array[0]); + } } - if(options['random']) - hash.generateRandomPreimage(22) - - console.log(`HashValue: ${hash.getSerializedHashBase64()} \nPreimage: ${hash.getPreimage()}`) + if (options["random"]) hash.generateRandomPreimage(22); - process.exit() - } -} + console.log( + `HashValue: ${hash.getSerializedHashBase64()} \nPreimage: ${hash.getPreimage()}`, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/state-helper.ts b/weaver/samples/besu/besu-cli/src/commands/state-helper.ts index 3799a2dee1..2d66e21469 100644 --- a/weaver/samples/besu/besu-cli/src/commands/state-helper.ts +++ b/weaver/samples/besu/besu-cli/src/commands/state-helper.ts @@ -4,21 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helper/helper' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helper/helper"; const command: GluegunCommand = { - name: 'state', - alias: ['s'], - description: 'Simple State Management', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'besu-cli state', '', [], command, [ - 'state' - ]) - return - } -} + name: "state", + alias: ["s"], + description: "Simple State Management", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "besu-cli state", "", [], command, ["state"]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/state/get.ts b/weaver/samples/besu/besu-cli/src/commands/state/get.ts index 413e6ed35e..a1571e035d 100644 --- a/weaver/samples/besu/besu-cli/src/commands/state/get.ts +++ b/weaver/samples/besu/besu-cli/src/commands/state/get.ts @@ -4,84 +4,88 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -const Web3 = require ("web3") +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +const Web3 = require("web3"); const command: GluegunCommand = { - name: 'get', - description: 'Get value of key', - run: async toolbox => { - const { - print, - parameters: { options, array } - } = toolbox - if (options.help || options.h) { - commandHelp( - print, - toolbox, - `besu-cli state get --network=network1 a`, - 'besu-cli state get --network= ' , - [ - { - name: '--network', - description: - 'network for command. ' - }, - { - name: '--network_host', - description: - 'The network host. Default value is taken from config.json' - }, - { - name: '--network_port', - description: - 'The network port. Default value is taken from config.json' - } - ], - command, - ['state', 'get'] - ) - return - } - print.info('Get value for key stored in simple state') - if(!options.network){ - print.error('Network ID not provided.') - return - } - if(array.length != 1) { - print.error('Not enough arguments provided.') - return - } - const networkConfig = getNetworkConfig(options.network) - console.log('networkConfig', networkConfig) + name: "get", + description: "Get value of key", + run: async (toolbox) => { + const { + print, + parameters: { options, array }, + } = toolbox; + if (options.help || options.h) { + commandHelp( + print, + toolbox, + `besu-cli state get --network=network1 a`, + "besu-cli state get --network= ", + [ + { + name: "--network", + description: "network for command. ", + }, + { + name: "--network_host", + description: + "The network host. Default value is taken from config.json", + }, + { + name: "--network_port", + description: + "The network port. Default value is taken from config.json", + }, + ], + command, + ["state", "get"], + ); + return; + } + print.info("Get value for key stored in simple state"); + if (!options.network) { + print.error("Network ID not provided."); + return; + } + if (array.length != 1) { + print.error("Not enough arguments provided."); + return; + } + const networkConfig = getNetworkConfig(options.network); + console.log("networkConfig", networkConfig); - var networkPort = networkConfig.networkPort - if(options.network_port){ - networkPort = options.network_port - console.log('Use network port : ', networkPort) - } - var networkHost = networkConfig.networkHost - if(options.network_host){ - networkHost = options.network_host - console.log('Use network host : ', networkHost) - } + let networkPort = networkConfig.networkPort; + if (options.network_port) { + networkPort = options.network_port; + console.log("Use network port : ", networkPort); + } + let networkHost = networkConfig.networkHost; + if (options.network_host) { + networkHost = options.network_host; + console.log("Use network host : ", networkHost); + } - const provider = new Web3.providers.HttpProvider('http://'+networkHost+':'+networkPort) - //const web3N = new Web3(provider) - const simpleStateContract = await getContractInstance(provider, networkConfig.tokenContract).catch(function () { - console.log("Failed getting appContract!"); - }) - const key = array[0] + const provider = new Web3.providers.HttpProvider( + "http://" + networkHost + ":" + networkPort, + ); + //const web3N = new Web3(provider) + const simpleStateContract = await getContractInstance( + provider, + networkConfig.tokenContract, + ).catch(function () { + console.log("Failed getting appContract!"); + }); + const key = array[0]; - // Transfer from the contract owner to the account specified - const value = await simpleStateContract.get(key) - //console.log(`${JSON.stringify(txRcpt)}`) - //const value = web3N.eth.abi.decodeLog(['string'], txRcpt.logs[0].args[0]) - console.log(`Value for key: ${key} = ${value}`) - process.exit() - } -} + // Transfer from the contract owner to the account specified + const value = await simpleStateContract.get(key); + //console.log(`${JSON.stringify(txRcpt)}`) + //const value = web3N.eth.abi.decodeLog(['string'], txRcpt.logs[0].args[0]) + console.log(`Value for key: ${key} = ${value}`); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/commands/state/set.ts b/weaver/samples/besu/besu-cli/src/commands/state/set.ts index b3162db51f..5c85e34473 100644 --- a/weaver/samples/besu/besu-cli/src/commands/state/set.ts +++ b/weaver/samples/besu/besu-cli/src/commands/state/set.ts @@ -4,87 +4,93 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { getNetworkConfig, commandHelp } from '../../helper/helper' -import { getContractInstance } from '../../helper/besu-functions' -const Web3 = require ("web3") +import { GluegunCommand } from "gluegun"; +import { getNetworkConfig, commandHelp } from "../../helper/helper"; +import { getContractInstance } from "../../helper/besu-functions"; +const Web3 = require("web3"); const command: GluegunCommand = { - name: 'set', - description: 'Set value of key', - run: async toolbox => { - const { - print, - parameters: { options, array } - } = toolbox - if (options.help || options.h) { - commandHelp( - print, - toolbox, - `besu-cli state set --network=network1 a 10`, - 'besu-cli state set --network= ' , - [ - { - name: '--network', - description: - 'network for command. ' - }, - { - name: '--network_host', - description: - 'The network host. Default value is taken from config.json' - }, - { - name: '--network_port', - description: - 'The network port. Default value is taken from config.json' - } - ], - command, - ['state', 'set'] - ) - return - } - print.info('Set key, value in simple state') - if(!options.network){ - print.error('Network ID not provided.') - return - } - if(array.length != 2) { - print.error('Not enough arguments provided.') - return - } - const networkConfig = getNetworkConfig(options.network) - console.log('networkConfig', networkConfig) + name: "set", + description: "Set value of key", + run: async (toolbox) => { + const { + print, + parameters: { options, array }, + } = toolbox; + if (options.help || options.h) { + commandHelp( + print, + toolbox, + `besu-cli state set --network=network1 a 10`, + "besu-cli state set --network= ", + [ + { + name: "--network", + description: "network for command. ", + }, + { + name: "--network_host", + description: + "The network host. Default value is taken from config.json", + }, + { + name: "--network_port", + description: + "The network port. Default value is taken from config.json", + }, + ], + command, + ["state", "set"], + ); + return; + } + print.info("Set key, value in simple state"); + if (!options.network) { + print.error("Network ID not provided."); + return; + } + if (array.length != 2) { + print.error("Not enough arguments provided."); + return; + } + const networkConfig = getNetworkConfig(options.network); + console.log("networkConfig", networkConfig); - var networkPort = networkConfig.networkPort - if(options.network_port){ - networkPort = options.network_port - console.log('Use network port : ', networkPort) - } - var networkHost = networkConfig.networkHost - if(options.network_host){ - networkHost = options.network_host - console.log('Use network host : ', networkHost) - } + let networkPort = networkConfig.networkPort; + if (options.network_port) { + networkPort = options.network_port; + console.log("Use network port : ", networkPort); + } + let networkHost = networkConfig.networkHost; + if (options.network_host) { + networkHost = options.network_host; + console.log("Use network host : ", networkHost); + } - const provider = new Web3.providers.HttpProvider('http://'+networkHost+':'+networkPort) - const web3N = new Web3(provider) - const accounts = await web3N.eth.getAccounts() - var contractOwner = accounts[0] - const simpleStateContract = await getContractInstance(provider, networkConfig.tokenContract).catch(function () { - console.log("Failed getting appContract!"); - process.exit() - }) - const key = array[0] - const value = array[1].toString() + const provider = new Web3.providers.HttpProvider( + "http://" + networkHost + ":" + networkPort, + ); + const web3N = new Web3(provider); + const accounts = await web3N.eth.getAccounts(); + const contractOwner = accounts[0]; + const simpleStateContract = await getContractInstance( + provider, + networkConfig.tokenContract, + ).catch(function () { + console.log("Failed getting appContract!"); + process.exit(); + }); + const key = array[0]; + const value = array[1].toString(); - // Transfer from the contract owner to the account specified - await simpleStateContract.set(key, value, {from: contractOwner}).catch(function () { - console.log("Failed setting key, value in simplestate!"); - }) - process.exit() - } -} + // Transfer from the contract owner to the account specified + await simpleStateContract + .set(key, value, { from: contractOwner }) + .catch(function () { + console.log("Failed setting key, value in simplestate!"); + }); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/besu/besu-cli/src/extensions/cli-extension.ts b/weaver/samples/besu/besu-cli/src/extensions/cli-extension.ts index 9ec241ecfe..4cb38ae167 100644 --- a/weaver/samples/besu/besu-cli/src/extensions/cli-extension.ts +++ b/weaver/samples/besu/besu-cli/src/extensions/cli-extension.ts @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunToolbox } from 'gluegun' +import { GluegunToolbox } from "gluegun"; // add your CLI-specific functionality here, which will then be accessible // to your commands module.exports = (toolbox: GluegunToolbox) => { toolbox.foo = () => { - toolbox.print.info('called foo extension') - } + toolbox.print.info("called foo extension"); + }; // enable this if you want to read configuration in from // the current folder's package.json (in a "besu-cli" property), @@ -20,4 +20,4 @@ module.exports = (toolbox: GluegunToolbox) => { // ...toolbox.config, // ...toolbox.config.loadConfig("besu-cli", process.cwd()) // } -} +}; diff --git a/weaver/samples/besu/besu-cli/src/helper/besu-functions.ts b/weaver/samples/besu/besu-cli/src/helper/besu-functions.ts index 0ea10235f8..aa633525d7 100644 --- a/weaver/samples/besu/besu-cli/src/helper/besu-functions.ts +++ b/weaver/samples/besu/besu-cli/src/helper/besu-functions.ts @@ -4,38 +4,35 @@ * SPDX-License-Identifier: Apache-2.0 */ -const fs = require('fs') +const fs = require("fs"); const contract = require("@truffle/contract"); -const path = require('path') - +const path = require("path"); // Function to obtain an instance of a smart contract when provided // as input the path to its JSON file output by 'truffle compile'. // (Assuming that the current folder is a sibling folder to build, // the path to json would be ../build/contracts/ContractName.json) -async function getContractInstance(provider, pathToJson){ - const jsonFile = path.resolve(pathToJson) - var jsonFileContents = fs.readFileSync(jsonFile) - var contractName = contract(JSON.parse(jsonFileContents)) - contractName.setProvider(provider) - var instance = await contractName.deployed().catch(function () { - console.log("Failed getting the contractName!"); - }) +async function getContractInstance(provider, pathToJson) { + const jsonFile = path.resolve(pathToJson); + const jsonFileContents = fs.readFileSync(jsonFile); + const contractName = contract(JSON.parse(jsonFileContents)); + contractName.setProvider(provider); + const instance = await contractName.deployed().catch(function () { + console.log("Failed getting the contractName!"); + }); - return instance + return instance; } -// Function to obtain the account balances of sender and recipient for +// Function to obtain the account balances of sender and recipient for // the specified token type and print them them to the console -async function getBalances(tokenContract, sender, recipient){ - var senderBalance = await tokenContract.balanceOf(sender) - console.log(`Account balance of the sender: ${senderBalance.toString()}`) - var recipientBalance = await tokenContract.balanceOf(recipient) - console.log(`Account balance of the recipient: ${recipientBalance.toString()}`) +async function getBalances(tokenContract, sender, recipient) { + const senderBalance = await tokenContract.balanceOf(sender); + console.log(`Account balance of the sender: ${senderBalance.toString()}`); + const recipientBalance = await tokenContract.balanceOf(recipient); + console.log( + `Account balance of the recipient: ${recipientBalance.toString()}`, + ); } - -export { - getContractInstance, - getBalances -} +export { getContractInstance, getBalances }; diff --git a/weaver/samples/besu/besu-cli/src/helper/helper.ts b/weaver/samples/besu/besu-cli/src/helper/helper.ts index 57c7a320e0..536246de77 100644 --- a/weaver/samples/besu/besu-cli/src/helper/helper.ts +++ b/weaver/samples/besu/besu-cli/src/helper/helper.ts @@ -4,35 +4,58 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as fs from 'fs' -import * as path from 'path' -import { GluegunCommand } from 'gluegun' -import { Toolbox } from 'gluegun/build/types/domain/toolbox' -import { GluegunPrint } from 'gluegun/build/types/toolbox/print-types' -import logger from './logger' +import * as fs from "fs"; +import * as path from "path"; +import { GluegunCommand } from "gluegun"; +import { Toolbox } from "gluegun/build/types/domain/toolbox"; +import { GluegunPrint } from "gluegun/build/types/toolbox/print-types"; +import logger from "./logger"; // Used for getting network configuration from config.json file. const getNetworkConfig = ( - networkId: string - ): { networkHost: string; networkPort: string; tokenContract: string; interopContract: string; senderAccountIndex: string; recipientAccountIndex: string } => { - const configPath = process.env.CONFIG_PATH - ? path.join(process.env.CONFIG_PATH) - : path.join(__dirname, '../../config.json') - try { - const configJSON = JSON.parse(fs.readFileSync(configPath).toString()) - if (!configJSON[networkId]) { - logger.error( - `Network: ${networkId} does not exist in the config.json file` - ) - return { networkHost: '', networkPort: '', tokenContract: '', interopContract: '', senderAccountIndex: '', recipientAccountIndex: '' } - } - // console.log(configJSON[networkId]) - return configJSON[networkId] - } catch (err) { - logger.error(`Network: ${networkId} does not exist in the config.json file`) - return { networkHost: '', networkPort: '', tokenContract: '', interopContract: '', senderAccountIndex: '', recipientAccountIndex: '' } - } -} + networkId: string, +): { + networkHost: string; + networkPort: string; + tokenContract: string; + interopContract: string; + senderAccountIndex: string; + recipientAccountIndex: string; +} => { + const configPath = process.env.CONFIG_PATH + ? path.join(process.env.CONFIG_PATH) + : path.join(__dirname, "../../config.json"); + try { + const configJSON = JSON.parse(fs.readFileSync(configPath).toString()); + if (!configJSON[networkId]) { + logger.error( + `Network: ${networkId} does not exist in the config.json file`, + ); + return { + networkHost: "", + networkPort: "", + tokenContract: "", + interopContract: "", + senderAccountIndex: "", + recipientAccountIndex: "", + }; + } + // console.log(configJSON[networkId]) + return configJSON[networkId]; + } catch (err) { + logger.error( + `Network: ${networkId} does not exist in the config.json file`, + ); + return { + networkHost: "", + networkPort: "", + tokenContract: "", + interopContract: "", + senderAccountIndex: "", + recipientAccountIndex: "", + }; + } +}; // Custom Command help is to generate the help text used when running --help on a command. // 1. If usage string is provided print usage section @@ -41,62 +64,58 @@ const getNetworkConfig = ( // 4. If there are subcommands it will print subcommands, this uses the commandRoot array where each item are the commands in order. // Logic is also in place to fix spacing based on length. const commandHelp = ( - print: GluegunPrint, - toolbox: Toolbox, - exampleString: string, - usageString: string, - optionsList: { name: string; description: string }[], - command: GluegunCommand, - commandRoot: string[] + print: GluegunPrint, + toolbox: Toolbox, + exampleString: string, + usageString: string, + optionsList: { name: string; description: string }[], + command: GluegunCommand, + commandRoot: string[], ): void => { - print.info(command.description) - print.info('') - // 1 - if (usageString) { - print.info(toolbox.print.colors.bold('USAGE')) - print.info('') - print.info(usageString) - print.info('') - } - // 2 - if (exampleString) { - print.info(toolbox.print.colors.bold('EXAMPLE')) - print.info('') - print.info(`$ ${exampleString}`) - print.info('') - } - // 3 - if (optionsList.length > 0) { - // To calculate how long each title should be to make the formatting consistent - const spaces = optionsList.reduce((acc, val) => { - const stringLength = val.name.length - if (stringLength > acc) { - return stringLength - } else { - return acc - } - }, 0) - print.info(toolbox.print.colors.bold('OPTIONS')) - print.info('') - optionsList.forEach(command => { - const val = spaces - command.name.length - const numberOfSpaces = val > 0 ? val : 0 - toolbox.print.info( - `${command.name} ${Array(numberOfSpaces) - .fill('\xa0') - .join('')} ${command.description}` - ) - }) - print.info('') - } - // 4 - toolbox.print.info(toolbox.print.colors.bold('COMMANDS')) - toolbox.print.printCommands(toolbox, commandRoot) - toolbox.print.info('') -} + print.info(command.description); + print.info(""); + // 1 + if (usageString) { + print.info(toolbox.print.colors.bold("USAGE")); + print.info(""); + print.info(usageString); + print.info(""); + } + // 2 + if (exampleString) { + print.info(toolbox.print.colors.bold("EXAMPLE")); + print.info(""); + print.info(`$ ${exampleString}`); + print.info(""); + } + // 3 + if (optionsList.length > 0) { + // To calculate how long each title should be to make the formatting consistent + const spaces = optionsList.reduce((acc, val) => { + const stringLength = val.name.length; + if (stringLength > acc) { + return stringLength; + } else { + return acc; + } + }, 0); + print.info(toolbox.print.colors.bold("OPTIONS")); + print.info(""); + optionsList.forEach((command) => { + const val = spaces - command.name.length; + const numberOfSpaces = val > 0 ? val : 0; + toolbox.print.info( + `${command.name} ${Array(numberOfSpaces) + .fill("\xa0") + .join("")} ${command.description}`, + ); + }); + print.info(""); + } + // 4 + toolbox.print.info(toolbox.print.colors.bold("COMMANDS")); + toolbox.print.printCommands(toolbox, commandRoot); + toolbox.print.info(""); +}; - -export { - getNetworkConfig, - commandHelp -} +export { getNetworkConfig, commandHelp }; diff --git a/weaver/samples/besu/besu-cli/src/helper/logger.ts b/weaver/samples/besu/besu-cli/src/helper/logger.ts index 7b14c5a377..a961d85d56 100644 --- a/weaver/samples/besu/besu-cli/src/helper/logger.ts +++ b/weaver/samples/besu/besu-cli/src/helper/logger.ts @@ -4,26 +4,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as winston from 'winston' -import * as path from 'path' -const { format, transports } = winston +import * as winston from "winston"; +import * as path from "path"; +const { format, transports } = winston; const logFormat = format.printf( - info => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}` -) + (info) => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`, +); const logger = winston.createLogger({ format: format.combine( format.label({ label: path.basename(process.mainModule.filename) }), - format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }) + format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] }), ), transports: [ new transports.Console({ - format: format.combine(format.colorize(), logFormat) - }) + format: format.combine(format.colorize(), logFormat), + }), ], - exitOnError: false -}) + exitOnError: false, +}); -export default logger +export default logger; diff --git a/weaver/samples/besu/simpleasset/app/AssetExchangeERC1155_20.js b/weaver/samples/besu/simpleasset/app/AssetExchangeERC1155_20.js index 4c8ea6da97..c38013665f 100644 --- a/weaver/samples/besu/simpleasset/app/AssetExchangeERC1155_20.js +++ b/weaver/samples/besu/simpleasset/app/AssetExchangeERC1155_20.js @@ -4,271 +4,395 @@ * SPDX-License-Identifier: Apache-2.0 */ -const promisify = require('util').promisify -const sleep = promisify(require('timers').setTimeout) -const fs = require('fs') -const path = require('path') +const promisify = require("util").promisify; +const sleep = promisify(require("timers").setTimeout); +const fs = require("fs"); +const path = require("path"); const contract = require("@truffle/contract"); -const Web3 = require ("web3") -const crypto = require('crypto') +const Web3 = require("web3"); +const crypto = require("crypto"); -const networkHost1 = "localhost" -const networkPort1 = "8545" -const networkHost2 = "localhost" -const networkPort2 = "9544" +const networkHost1 = "localhost"; +const networkPort1 = "8545"; +const networkHost2 = "localhost"; +const networkPort2 = "9544"; +const AliceERC1155TokenContract = require("../build/contracts/AliceERC1155.json"); +const BobERC20TokenContract = require("../build/contracts/BobERC20.json"); -const AliceERC1155TokenContract = require('../build/contracts/AliceERC1155.json') -const BobERC20TokenContract = require('../build/contracts/BobERC20.json') +let interopContract1; +let interopContract2; +let AliceERC1155; +let BobERC20; -let interopContract1 -let interopContract2 -let AliceERC1155 -let BobERC20 - - -// Function to obtain an instance of a smart contract when provided +// Function to obtain an instance of a smart contract when provided // as input the path to its JSON file output by 'truffle compile'. -// (Assuming that the current folder is a sibling folder to build, +// (Assuming that the current folder is a sibling folder to build, // the path to json would be ../build/contracts/ContractName.json) -async function getContractInstance(provider, pathToJson){ - const jsonFile = path.resolve(__dirname, pathToJson) - var jsonFileContents = fs.readFileSync(jsonFile) - var contractName = contract(JSON.parse(jsonFileContents)) - contractName.setProvider(provider) - var instance = await contractName.deployed().catch(function () { - console.log("Failed getting the contractName!"); - }) - return instance +async function getContractInstance(provider, pathToJson) { + const jsonFile = path.resolve(__dirname, pathToJson); + var jsonFileContents = fs.readFileSync(jsonFile); + var contractName = contract(JSON.parse(jsonFileContents)); + contractName.setProvider(provider); + var instance = await contractName.deployed().catch(function () { + console.log("Failed getting the contractName!"); + }); + return instance; } - // Initialization of the parameters -async function init(provider1, provider2, contractOwner1, contractOwner2, Alice1, Bob2, tokenSupply, senderInitialBalance) { - interopContract1 = await getContractInstance(provider1,'../build/contracts/AssetExchangeContract.json').catch(function () { - console.log("Failed getting interopContract1!"); - }) - interopContract2 = await getContractInstance(provider2,'../build/contracts/AssetExchangeContract.json').catch(function () { - console.log("Failed getting interopContract2!"); - }) - - AliceERC1155 = await getContractInstance(provider1, '../build/contracts/AliceERC1155.json').catch(function () { - console.log("Failed getting AliceERC1155 token contract!"); - }) - BobERC20 = await getContractInstance(provider2, '../build/contracts/BobERC20.json').catch(function () { - console.log("Failed getting BobERC20 token contract!"); - }) - - // Issue AliceERC1155 tokens to Alice in Network 1 and BobERC20 tokens - // to Bob in Network 2. A minimal number of tokens equal to the - // number of token being exchanged is issued to Alice and Bob to - // ensure that the exchange in this test application does not fail - // due to insufficient funds. - await AliceERC1155.safeTransferFrom(contractOwner1, Alice1, 1, 1, Web3.utils.utf8ToHex(""), {from: contractOwner1}).catch(function (e) { - console.log(e); - console.log("AliceERC1155 transfer threw an error; Probably the token supply is used up!"); - }) - await BobERC20.transfer(Bob2, senderInitialBalance, {from: contractOwner2}).catch(function () { - console.log("BobERC20 transfer threw an error; Probably the token supply is used up!"); - }) - +async function init( + provider1, + provider2, + contractOwner1, + contractOwner2, + Alice1, + Bob2, + tokenSupply, + senderInitialBalance, +) { + interopContract1 = await getContractInstance( + provider1, + "../build/contracts/AssetExchangeContract.json", + ).catch(function () { + console.log("Failed getting interopContract1!"); + }); + interopContract2 = await getContractInstance( + provider2, + "../build/contracts/AssetExchangeContract.json", + ).catch(function () { + console.log("Failed getting interopContract2!"); + }); + + AliceERC1155 = await getContractInstance( + provider1, + "../build/contracts/AliceERC1155.json", + ).catch(function () { + console.log("Failed getting AliceERC1155 token contract!"); + }); + BobERC20 = await getContractInstance( + provider2, + "../build/contracts/BobERC20.json", + ).catch(function () { + console.log("Failed getting BobERC20 token contract!"); + }); + + // Issue AliceERC1155 tokens to Alice in Network 1 and BobERC20 tokens + // to Bob in Network 2. A minimal number of tokens equal to the + // number of token being exchanged is issued to Alice and Bob to + // ensure that the exchange in this test application does not fail + // due to insufficient funds. + await AliceERC1155.safeTransferFrom( + contractOwner1, + Alice1, + 1, + 1, + Web3.utils.utf8ToHex(""), + { from: contractOwner1 }, + ).catch(function (e) { + console.log(e); + console.log( + "AliceERC1155 transfer threw an error; Probably the token supply is used up!", + ); + }); + await BobERC20.transfer(Bob2, senderInitialBalance, { + from: contractOwner2, + }).catch(function () { + console.log( + "BobERC20 transfer threw an error; Probably the token supply is used up!", + ); + }); } - -// Claim function of a fungible asset/token of type tokenContractId -// and amount tokenAmount locked using contractId for a receiver. -// preimage is the secret to unlock the asset corresponding to the commitment +// Claim function of a fungible asset/token of type tokenContractId +// and amount tokenAmount locked using contractId for a receiver. +// preimage is the secret to unlock the asset corresponding to the commitment // used when locking it -async function claimToken(interopContract, lockContractId, recipient, preimage) { - console.log("\n Claiming %s using preimage: %o", lockContractId, preimage) - // console.log(JSON.parse(JSON.stringify(preimage)).data.toString('utf8')) - var claimStatus = await interopContract.claimAsset(lockContractId, preimage, { - from: recipient - }).catch(function (err) { - console.log(err) - console.log("claimAsset threw an error"); - claimStatus = false - }) - - return claimStatus +async function claimToken( + interopContract, + lockContractId, + recipient, + preimage, +) { + console.log("\n Claiming %s using preimage: %o", lockContractId, preimage); + // console.log(JSON.parse(JSON.stringify(preimage)).data.toString('utf8')) + var claimStatus = await interopContract + .claimAsset(lockContractId, preimage, { + from: recipient, + }) + .catch(function (err) { + console.log(err); + console.log("claimAsset threw an error"); + claimStatus = false; + }); + + return claimStatus; } - -// Unlock function of a locked fungible asset/token +// Unlock function of a locked fungible asset/token async function unlockToken(interopContract, lockContractId, sender) { - var unlockStatus = await interopContract.unlockAsset(lockContractId, { - from: sender - }).catch(function () { - console.log("unlockAsset threw an error"); - unlockStatus = false - }) - - return unlockStatus + var unlockStatus = await interopContract + .unlockAsset(lockContractId, { + from: sender, + }) + .catch(function () { + console.log("unlockAsset threw an error"); + unlockStatus = false; + }); + + return unlockStatus; } - // Function to create a new smart contract for locking asset // 'sender' locks 'tokenAmount' number of tokens of type 'tokenContract' // for 'recipient' using the contract constructs of 'interopContract' // with hashLock and timeLock providing the conditions for claiming/unlocking -async function lockToken(sender, recipient, tokenContract, tokenAmount, interopContract, hashLock, timeLock, type, tokenID, data) { - // initiator of the swap has to first designate the swap contract as a spender of his/her money - // with allowance matching the swap amount - if(type == "ERC1155"){ - await tokenContract.setApprovalForAll(tokenContract.address, true, {from: sender}).catch(function () { - console.log("Token approval failed!!!"); - return false - }) - }else{ - await tokenContract.approve(tokenContract.address, tokenAmount, {from: sender}).catch(function () { - console.log("Token approval failed!!!"); - return false - })} - var lockStatus = interopContract.lockAsset( - recipient, - tokenContract.address, - tokenAmount, - hashLock, - timeLock, - tokenID, - Web3.utils.utf8ToHex(data), - { - from: sender - } - ).catch(function (e) { - console.log(e) - console.log("lockAsset threw an error"); - lockStatus = false - }) - - return lockStatus +async function lockToken( + sender, + recipient, + tokenContract, + tokenAmount, + interopContract, + hashLock, + timeLock, + type, + tokenID, + data, +) { + // initiator of the swap has to first designate the swap contract as a spender of his/her money + // with allowance matching the swap amount + if (type == "ERC1155") { + await tokenContract + .setApprovalForAll(tokenContract.address, true, { from: sender }) + .catch(function () { + console.log("Token approval failed!!!"); + return false; + }); + } else { + await tokenContract + .approve(tokenContract.address, tokenAmount, { from: sender }) + .catch(function () { + console.log("Token approval failed!!!"); + return false; + }); + } + var lockStatus = interopContract + .lockAsset( + recipient, + tokenContract.address, + tokenAmount, + hashLock, + timeLock, + tokenID, + Web3.utils.utf8ToHex(data), + { + from: sender, + }, + ) + .catch(function (e) { + console.log(e); + console.log("lockAsset threw an error"); + lockStatus = false; + }); + + return lockStatus; } - -// A function to obtain and print the account balances of a pair +// A function to obtain and print the account balances of a pair // of accounts in the two participating networks. -// Designed for printing the account balances of the sender and +// Designed for printing the account balances of the sender and // recipient at various stages of the exchange. async function getBalances(Alice1, Bob1, Alice2, Bob2) { - var AliceAliceERC1155Balance = await AliceERC1155.balanceOf(Alice1,1) - console.log("Alice balance of AliceERC1155 in Network 1", AliceAliceERC1155Balance.toString()) - - var BobAliceERC1155Balance = await AliceERC1155.balanceOf(Bob1,1) - console.log("Bob balance of AliceERC1155 in Network 1", await BobAliceERC1155Balance.toString()) - - var AliceBobERC20Balance = await BobERC20.balanceOf(Alice2) - console.log("Alice balance of BobERC20 in Network 2", AliceBobERC20Balance.toString()) - - var BobBobERC20Balance = await BobERC20.balanceOf(Bob2) - console.log("Bob balance of BobERC20 in Network 2", await BobBobERC20Balance.toString()) + var AliceAliceERC1155Balance = await AliceERC1155.balanceOf(Alice1, 1); + console.log( + "Alice balance of AliceERC1155 in Network 1", + AliceAliceERC1155Balance.toString(), + ); + + var BobAliceERC1155Balance = await AliceERC1155.balanceOf(Bob1, 1); + console.log( + "Bob balance of AliceERC1155 in Network 1", + await BobAliceERC1155Balance.toString(), + ); + + var AliceBobERC20Balance = await BobERC20.balanceOf(Alice2); + console.log( + "Alice balance of BobERC20 in Network 2", + AliceBobERC20Balance.toString(), + ); + + var BobBobERC20Balance = await BobERC20.balanceOf(Bob2); + console.log( + "Bob balance of BobERC20 in Network 2", + await BobBobERC20Balance.toString(), + ); } - // Main entry point to the app async function main() { - // Network 1 - const provider1 = new Web3.providers.HttpProvider('http://'+networkHost1+':'+networkPort1) - const web3N1 = new Web3(provider1) - const accounts1 = await web3N1.eth.getAccounts() - - const Alice1 = accounts1[1] // owner of AliceERC1155 and wants swap for BobERC20 - const Bob1 = accounts1[2] // owner of BobERC20 and wants to swap for AliceERC1155 - console.log("Alice address in Network 1", Alice1) - console.log("Bob address in Network 1", Bob1) - - const contractOwner1 = accounts1[0] // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed - - // Network 2 - const provider2 = new Web3.providers.HttpProvider('http://'+networkHost2+':'+networkPort2) - const web3N2 = new Web3(provider2) - const accounts2 = await web3N2.eth.getAccounts() - - const Alice2 = accounts2[1] // owner of AliceERC1155 and wants swap for BobERC20 - const Bob2 = accounts2[2] // owner of BobERC20 and wants to swap for AliceERC1155 - console.log("Alice address in Network 2", Alice2) - console.log("Bob address in Network 2", Bob2) - - const contractOwner2 = accounts2[0] // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed - - // Initialization - const tokenSupply = 1000 - const tokenAmount = 10 // Number of tokens to be exchanged - const tokenId = 1; - const senderInitialBalance = tokenAmount - - await init(provider1, provider2, contractOwner1, contractOwner2, Alice1, Bob2, tokenSupply, senderInitialBalance) - - console.log("\n Balances after init():") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - preimage = crypto.randomBytes(32) // to sample a preimage for the hash - hash = crypto.createHash('sha256').update(preimage).digest() - console.log("Hash: ", hash) - - let timeOut = 15 - let timeLockSeconds = Math.floor(Date.now() / 1000) + 2*timeOut - - // Creating a HTLC contract for Alice locking her AliceERC1155 tokens for Bob - let lockTx1 = await lockToken(Alice1, Bob1, AliceERC1155, 1, interopContract1, hash, timeLockSeconds, "ERC1155", 1, "") - if (!lockTx1) { - console.log("\n !!! Locking of Alice's tokens failed in Netowrk 1. Aborting here !!!") - return - } - let lockContractId1 = lockTx1.logs[0].args.lockContractId - console.log("lockContractID1: ", lockContractId1) - - console.log("\n Balances after Alice locks her tokens in Network 1:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // After he observes this lockContract created in Network 1, - // Bob creates a similar contract in Network 2 using the same - // hash to transfer the agreed upon amount of BobERC20 to Alice. - // Bob sets the timeLock such that he will have enough time to - // claim Alice's tokens in Network 1 after she claims Bob's - // tokens in Network 2. - timeLockSeconds = Math.floor(Date.now() / 1000) + timeOut - let lockTx2 = await lockToken(Bob2, Alice2, BobERC20, tokenAmount, interopContract2, hash, timeLockSeconds, "ERC20", 1, "") - if (!lockTx2) { - console.log("\n !!! Locking of Bob's tokens failed in Netowrk 2. Aborting here !!!") - return - } - let lockContractId2 = lockTx2.logs[0].args.lockContractId - console.log("lockContractID2: ", lockContractId2) - - console.log("\n Balances after creating Bob locks his tokens in Network 2:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // Alice withdrawing Bob's BobERC20 token from lockContractId2 - let claimSuccess2 = await claimToken(interopContract2, lockContractId2, Alice2, preimage) - - console.log("\n Balances after Alice's attempt to claim in Network 2:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // If Alice's claim is not successfull, then Alice and Bob unlock their locked tokens - if(!claimSuccess2){ - sleep(2*timeOut*1000) - console.log("\n !!! Claim by Alice not successfull !!! \n Unlocking and refunding tokens to Alice and Bob") - - let unlockSuccess2 = await unlockToken(interopContract2, lockContractId2, Bob2) - let unlockSuccess1 = await unlockToken(interopContract1, lockContractId1, Alice1) - - if(!unlockSuccess2) - console.log("\n !!! Unlocking Bob's tokens not successfull !!!") - if(!unlockSuccess1) - console.log("\n !!! Unlocking Alice's tokens not successfull !!!") - } - else{ - // If Alice's withdrawal is successful, Bob goes ahead and claims Alice's - // AliceERC1155 tokens locked in the lockContractId1 - let claimSuccess1 = await claimToken(interopContract1, lockContractId1, Bob1, preimage) // we assume Bob's claim to be successful if Alice's claim is successful - - if(!claimSuccess1){ - console.log("\n !!! Claim by Bob not successfull !!! \n We had assumed Bob's claim will be successful if Alice's claim is successful") - } - } - - console.log("\n Balances after Bob's attempt to claim in Network 1:") - await getBalances(Alice1, Bob1, Alice2, Bob2) + // Network 1 + const provider1 = new Web3.providers.HttpProvider( + "http://" + networkHost1 + ":" + networkPort1, + ); + const web3N1 = new Web3(provider1); + const accounts1 = await web3N1.eth.getAccounts(); + + const Alice1 = accounts1[1]; // owner of AliceERC1155 and wants swap for BobERC20 + const Bob1 = accounts1[2]; // owner of BobERC20 and wants to swap for AliceERC1155 + console.log("Alice address in Network 1", Alice1); + console.log("Bob address in Network 1", Bob1); + + const contractOwner1 = accounts1[0]; // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed + + // Network 2 + const provider2 = new Web3.providers.HttpProvider( + "http://" + networkHost2 + ":" + networkPort2, + ); + const web3N2 = new Web3(provider2); + const accounts2 = await web3N2.eth.getAccounts(); + + const Alice2 = accounts2[1]; // owner of AliceERC1155 and wants swap for BobERC20 + const Bob2 = accounts2[2]; // owner of BobERC20 and wants to swap for AliceERC1155 + console.log("Alice address in Network 2", Alice2); + console.log("Bob address in Network 2", Bob2); + + const contractOwner2 = accounts2[0]; // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed + + // Initialization + const tokenSupply = 1000; + const tokenAmount = 10; // Number of tokens to be exchanged + const tokenId = 1; + const senderInitialBalance = tokenAmount; + + await init( + provider1, + provider2, + contractOwner1, + contractOwner2, + Alice1, + Bob2, + tokenSupply, + senderInitialBalance, + ); + + console.log("\n Balances after init():"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + preimage = crypto.randomBytes(32); // to sample a preimage for the hash + hash = crypto.createHash("sha256").update(preimage).digest(); + console.log("Hash: ", hash); + + let timeOut = 15; + let timeLockSeconds = Math.floor(Date.now() / 1000) + 2 * timeOut; + + // Creating a HTLC contract for Alice locking her AliceERC1155 tokens for Bob + let lockTx1 = await lockToken( + Alice1, + Bob1, + AliceERC1155, + 1, + interopContract1, + hash, + timeLockSeconds, + "ERC1155", + 1, + "", + ); + if (!lockTx1) { + console.log( + "\n !!! Locking of Alice's tokens failed in Netowrk 1. Aborting here !!!", + ); + return; + } + let lockContractId1 = lockTx1.logs[0].args.lockContractId; + console.log("lockContractID1: ", lockContractId1); + + console.log("\n Balances after Alice locks her tokens in Network 1:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // After he observes this lockContract created in Network 1, + // Bob creates a similar contract in Network 2 using the same + // hash to transfer the agreed upon amount of BobERC20 to Alice. + // Bob sets the timeLock such that he will have enough time to + // claim Alice's tokens in Network 1 after she claims Bob's + // tokens in Network 2. + timeLockSeconds = Math.floor(Date.now() / 1000) + timeOut; + let lockTx2 = await lockToken( + Bob2, + Alice2, + BobERC20, + tokenAmount, + interopContract2, + hash, + timeLockSeconds, + "ERC20", + 1, + "", + ); + if (!lockTx2) { + console.log( + "\n !!! Locking of Bob's tokens failed in Netowrk 2. Aborting here !!!", + ); + return; + } + let lockContractId2 = lockTx2.logs[0].args.lockContractId; + console.log("lockContractID2: ", lockContractId2); + + console.log("\n Balances after creating Bob locks his tokens in Network 2:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // Alice withdrawing Bob's BobERC20 token from lockContractId2 + let claimSuccess2 = await claimToken( + interopContract2, + lockContractId2, + Alice2, + preimage, + ); + + console.log("\n Balances after Alice's attempt to claim in Network 2:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // If Alice's claim is not successfull, then Alice and Bob unlock their locked tokens + if (!claimSuccess2) { + sleep(2 * timeOut * 1000); + console.log( + "\n !!! Claim by Alice not successfull !!! \n Unlocking and refunding tokens to Alice and Bob", + ); + + let unlockSuccess2 = await unlockToken( + interopContract2, + lockContractId2, + Bob2, + ); + let unlockSuccess1 = await unlockToken( + interopContract1, + lockContractId1, + Alice1, + ); + + if (!unlockSuccess2) + console.log("\n !!! Unlocking Bob's tokens not successfull !!!"); + if (!unlockSuccess1) + console.log("\n !!! Unlocking Alice's tokens not successfull !!!"); + } else { + // If Alice's withdrawal is successful, Bob goes ahead and claims Alice's + // AliceERC1155 tokens locked in the lockContractId1 + let claimSuccess1 = await claimToken( + interopContract1, + lockContractId1, + Bob1, + preimage, + ); // we assume Bob's claim to be successful if Alice's claim is successful + + if (!claimSuccess1) { + console.log( + "\n !!! Claim by Bob not successfull !!! \n We had assumed Bob's claim will be successful if Alice's claim is successful", + ); + } + } + + console.log("\n Balances after Bob's attempt to claim in Network 1:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); } -main() +main(); diff --git a/weaver/samples/besu/simpleasset/app/AssetExchangeERC20.js b/weaver/samples/besu/simpleasset/app/AssetExchangeERC20.js index 5edeb922ab..697f6aaeb0 100644 --- a/weaver/samples/besu/simpleasset/app/AssetExchangeERC20.js +++ b/weaver/samples/besu/simpleasset/app/AssetExchangeERC20.js @@ -4,257 +4,369 @@ * SPDX-License-Identifier: Apache-2.0 */ -const promisify = require('util').promisify -const sleep = promisify(require('timers').setTimeout) -const fs = require('fs') -const path = require('path') +const promisify = require("util").promisify; +const sleep = promisify(require("timers").setTimeout); +const fs = require("fs"); +const path = require("path"); const contract = require("@truffle/contract"); -const Web3 = require ("web3") -const crypto = require('crypto') +const Web3 = require("web3"); +const crypto = require("crypto"); -const networkHost1 = "localhost" -const networkPort1 = "8545" -const networkHost2 = "localhost" -const networkPort2 = "9544" +const networkHost1 = "localhost"; +const networkPort1 = "8545"; +const networkHost2 = "localhost"; +const networkPort2 = "9544"; +let interopContract1; +let interopContract2; +let AliceERC20; +let BobERC20; -let interopContract1 -let interopContract2 -let AliceERC20 -let BobERC20 - - -// Function to obtain an instance of a smart contract when provided +// Function to obtain an instance of a smart contract when provided // as input the path to its JSON file output by 'truffle compile'. -// (Assuming that the current folder is a sibling folder to build, +// (Assuming that the current folder is a sibling folder to build, // the path to json would be ../build/contracts/ContractName.json) -async function getContractInstance(provider, pathToJson){ - const jsonFile = path.resolve(__dirname, pathToJson) - var jsonFileContents = fs.readFileSync(jsonFile) - var contractName = contract(JSON.parse(jsonFileContents)) - contractName.setProvider(provider) - var instance = await contractName.deployed().catch(function () { - console.log("Failed getting the contractName!"); - }) - return instance +async function getContractInstance(provider, pathToJson) { + const jsonFile = path.resolve(__dirname, pathToJson); + var jsonFileContents = fs.readFileSync(jsonFile); + var contractName = contract(JSON.parse(jsonFileContents)); + contractName.setProvider(provider); + var instance = await contractName.deployed().catch(function () { + console.log("Failed getting the contractName!"); + }); + return instance; } - // Initialization of the parameters -async function init(provider1, provider2, contractOwner1, contractOwner2, Alice1, Bob2, tokenSupply, senderInitialBalance) { - interopContract1 = await getContractInstance(provider1,'../build/contracts/AssetExchangeContract.json').catch(function () { - console.log("Failed getting interopContract1!"); - }) - interopContract2 = await getContractInstance(provider2,'../build/contracts/AssetExchangeContract.json').catch(function () { - console.log("Failed getting interopContract2!"); - }) - - AliceERC20 = await getContractInstance(provider1, '../build/contracts/AliceERC20.json').catch(function () { - console.log("Failed getting AliceERC20 token contract!"); - }) - BobERC20 = await getContractInstance(provider2, '../build/contracts/BobERC20.json').catch(function () { - console.log("Failed getting BobERC20 token contract!"); - }) - - // Issue AliceERC20 tokens to Alice in Network 1 and BobERC20 tokens - // to Bob in Network 2. A minimal number of tokens equal to the - // number of token being exchanged is issued to Alice and Bob to - // ensure that the exchange in this test application does not fail - // due to insufficient funds. - await AliceERC20.transferFrom(contractOwner1, Alice1, 1, {from: contractOwner1}).catch(function (e) { - console.log("AliceERC20 transfer threw an error; Probably the token supply is used up!"); - }) - await BobERC20.transfer(Bob2, senderInitialBalance, {from: contractOwner2}).catch(function () { - console.log("BobERC20 transfer threw an error; Probably the token supply is used up!"); - }) +async function init( + provider1, + provider2, + contractOwner1, + contractOwner2, + Alice1, + Bob2, + tokenSupply, + senderInitialBalance, +) { + interopContract1 = await getContractInstance( + provider1, + "../build/contracts/AssetExchangeContract.json", + ).catch(function () { + console.log("Failed getting interopContract1!"); + }); + interopContract2 = await getContractInstance( + provider2, + "../build/contracts/AssetExchangeContract.json", + ).catch(function () { + console.log("Failed getting interopContract2!"); + }); + + AliceERC20 = await getContractInstance( + provider1, + "../build/contracts/AliceERC20.json", + ).catch(function () { + console.log("Failed getting AliceERC20 token contract!"); + }); + BobERC20 = await getContractInstance( + provider2, + "../build/contracts/BobERC20.json", + ).catch(function () { + console.log("Failed getting BobERC20 token contract!"); + }); + + // Issue AliceERC20 tokens to Alice in Network 1 and BobERC20 tokens + // to Bob in Network 2. A minimal number of tokens equal to the + // number of token being exchanged is issued to Alice and Bob to + // ensure that the exchange in this test application does not fail + // due to insufficient funds. + await AliceERC20.transferFrom(contractOwner1, Alice1, 1, { + from: contractOwner1, + }).catch(function (e) { + console.log( + "AliceERC20 transfer threw an error; Probably the token supply is used up!", + ); + }); + await BobERC20.transfer(Bob2, senderInitialBalance, { + from: contractOwner2, + }).catch(function () { + console.log( + "BobERC20 transfer threw an error; Probably the token supply is used up!", + ); + }); } - -// Claim function of a fungible asset/token of type tokenContractId -// and amount tokenAmount locked using contractId for a receiver. -// preimage is the secret to unlock the asset corresponding to the commitment +// Claim function of a fungible asset/token of type tokenContractId +// and amount tokenAmount locked using contractId for a receiver. +// preimage is the secret to unlock the asset corresponding to the commitment // used when locking it -async function claimToken(interopContract, lockContractId, recipient, preimage) { - console.log("\n Claiming %s using preimage: %o", lockContractId, preimage) - // console.log(JSON.parse(JSON.stringify(preimage)).data.toString('utf8')) - var claimStatus = await interopContract.claimAsset(lockContractId, preimage, { - from: recipient - }).catch(function (err) { - console.log(err) - console.log("claimAsset threw an error"); - claimStatus = false - }) - - return claimStatus +async function claimToken( + interopContract, + lockContractId, + recipient, + preimage, +) { + console.log("\n Claiming %s using preimage: %o", lockContractId, preimage); + // console.log(JSON.parse(JSON.stringify(preimage)).data.toString('utf8')) + var claimStatus = await interopContract + .claimAsset(lockContractId, preimage, { + from: recipient, + }) + .catch(function (err) { + console.log(err); + console.log("claimAsset threw an error"); + claimStatus = false; + }); + + return claimStatus; } - -// Unlock function of a locked fungible asset/token +// Unlock function of a locked fungible asset/token async function unlockToken(interopContract, lockContractId, sender) { - var unlockStatus = await interopContract.unlockAsset(lockContractId, { - from: sender - }).catch(function () { - console.log("unlockAsset threw an error"); - unlockStatus = false - }) - - return unlockStatus + var unlockStatus = await interopContract + .unlockAsset(lockContractId, { + from: sender, + }) + .catch(function () { + console.log("unlockAsset threw an error"); + unlockStatus = false; + }); + + return unlockStatus; } - // Function to create a new smart contract for locking asset // 'sender' locks 'tokenAmount' number of tokens of type 'tokenContract' // for 'recipient' using the contract constructs of 'interopContract' // with hashLock and timeLock providing the conditions for claiming/unlocking -async function lockToken(sender, recipient, tokenContract, tokenAmount, interopContract, hashLock, timeLock, tokenId=0, data="") { - // initiator of the swap has to first designate the swap contract as a spender of his/her money - // with allowance matching the swap amount - await tokenContract.approve(tokenContract.address, tokenAmount, {from: sender}).catch(function () { - console.log("Token approval failed!!!"); - return false - }) - var lockStatus = interopContract.lockAsset( - recipient, - tokenContract.address, - tokenAmount, - hashLock, - timeLock, - tokenId, - Web3.utils.utf8ToHex(data), - { - from: sender - } - ).catch(function () { - console.log("lockAsset threw an error"); - lockStatus = false - }) - - return lockStatus +async function lockToken( + sender, + recipient, + tokenContract, + tokenAmount, + interopContract, + hashLock, + timeLock, + tokenId = 0, + data = "", +) { + // initiator of the swap has to first designate the swap contract as a spender of his/her money + // with allowance matching the swap amount + await tokenContract + .approve(tokenContract.address, tokenAmount, { from: sender }) + .catch(function () { + console.log("Token approval failed!!!"); + return false; + }); + var lockStatus = interopContract + .lockAsset( + recipient, + tokenContract.address, + tokenAmount, + hashLock, + timeLock, + tokenId, + Web3.utils.utf8ToHex(data), + { + from: sender, + }, + ) + .catch(function () { + console.log("lockAsset threw an error"); + lockStatus = false; + }); + + return lockStatus; } - -// A function to obtain and print the account balances of a pair +// A function to obtain and print the account balances of a pair // of accounts in the two participating networks. -// Designed for printing the account balances of the sender and +// Designed for printing the account balances of the sender and // recipient at various stages of the exchange. async function getBalances(Alice1, Bob1, Alice2, Bob2) { - var AliceAliceERC20Balance = await AliceERC20.balanceOf(Alice1) - console.log("Alice balance of AliceERC20 in Network 1", AliceAliceERC20Balance.toString()) - - var BobAliceERC20Balance = await AliceERC20.balanceOf(Bob1) - console.log("Bob balance of AliceERC20 in Network 1", await BobAliceERC20Balance.toString()) - - var AliceBobERC20Balance = await BobERC20.balanceOf(Alice2) - console.log("Alice balance of BobERC20 in Network 2", AliceBobERC20Balance.toString()) - - var BobBobERC20Balance = await BobERC20.balanceOf(Bob2) - console.log("Bob balance of BobERC20 in Network 2", await BobBobERC20Balance.toString()) + var AliceAliceERC20Balance = await AliceERC20.balanceOf(Alice1); + console.log( + "Alice balance of AliceERC20 in Network 1", + AliceAliceERC20Balance.toString(), + ); + + var BobAliceERC20Balance = await AliceERC20.balanceOf(Bob1); + console.log( + "Bob balance of AliceERC20 in Network 1", + await BobAliceERC20Balance.toString(), + ); + + var AliceBobERC20Balance = await BobERC20.balanceOf(Alice2); + console.log( + "Alice balance of BobERC20 in Network 2", + AliceBobERC20Balance.toString(), + ); + + var BobBobERC20Balance = await BobERC20.balanceOf(Bob2); + console.log( + "Bob balance of BobERC20 in Network 2", + await BobBobERC20Balance.toString(), + ); } - // Main entry point to the app async function main() { - // Network 1 - const provider1 = new Web3.providers.HttpProvider('http://'+networkHost1+':'+networkPort1) - const web3N1 = new Web3(provider1) - const accounts1 = await web3N1.eth.getAccounts() - - const Alice1 = accounts1[1] // owner of AliceERC20 and wants swap for BobERC20 - const Bob1 = accounts1[2] // owner of BobERC20 and wants to swap for AliceERC20 - console.log("Alice address in Network 1", Alice1) - console.log("Bob address in Network 1", Bob1) - - const contractOwner1 = accounts1[0] // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed - - // Network 2 - const provider2 = new Web3.providers.HttpProvider('http://'+networkHost2+':'+networkPort2) - const web3N2 = new Web3(provider2) - const accounts2 = await web3N2.eth.getAccounts() - - const Alice2 = accounts2[1] // owner of AliceERC20 and wants swap for BobERC20 - const Bob2 = accounts2[2] // owner of BobERC20 and wants to swap for AliceERC20 - console.log("Alice address in Network 2", Alice2) - console.log("Bob address in Network 2", Bob2) - - const contractOwner2 = accounts2[0] // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed - - // Initialization - const tokenSupply = 1000 - const tokenAmount = 10 // Number of tokens to be exchanged - const tokenId = 1; - const senderInitialBalance = tokenAmount - - await init(provider1, provider2, contractOwner1, contractOwner2, Alice1, Bob2, tokenSupply, senderInitialBalance) - - console.log("\n Balances after init():") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - preimage = crypto.randomBytes(32) // to sample a preimage for the hash - hash = crypto.createHash('sha256').update(preimage).digest() - console.log("Hash: ", hash) - - let timeOut = 15 - let timeLockSeconds = Math.floor(Date.now() / 1000) + 2*timeOut - - // Creating a HTLC contract for Alice locking her AliceERC20 tokens for Bob - let lockTx1 = await lockToken(Alice1, Bob1, AliceERC20, 1, interopContract1, hash, timeLockSeconds, tokenId) - if (!lockTx1) { - console.log("\n !!! Locking of Alice's tokens failed in Netowrk 1. Aborting here !!!") - return - } - let lockContractId1 = lockTx1.logs[0].args.lockContractId - - console.log("\n Balances after Alice locks her tokens in Network 1:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // After he observes this lockContract created in Network 1, - // Bob creates a similar contract in Network 2 using the same - // hash to transfer the agreed upon amount of BobERC20 to Alice. - // Bob sets the timeLock such that he will have enough time to - // claim Alice's tokens in Network 1 after she claims Bob's - // tokens in Network 2. - timeLockSeconds = Math.floor(Date.now() / 1000) + timeOut - let lockTx2 = await lockToken(Bob2, Alice2, BobERC20, tokenAmount, interopContract2, hash, timeLockSeconds, tokenId) - if (!lockTx2) { - console.log("\n !!! Locking of Bob's tokens failed in Netowrk 2. Aborting here !!!") - return - } - let lockContractId2 = lockTx2.logs[0].args.lockContractId - - console.log("\n Balances after creating Bob locks his tokens in Network 2:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // Alice withdrawing Bob's BobERC20 token from lockContractId2 - let claimSuccess2 = await claimToken(interopContract2, lockContractId2, Alice2, preimage) - - console.log("\n Balances after Alice's attempt to claim in Network 2:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // If Alice's claim is not successfull, then Alice and Bob unlock their locked tokens - if(!claimSuccess2){ - sleep(2*timeOut*1000) - console.log("\n !!! Claim by Alice not successfull !!! \n Unlocking and refunding tokens to Alice and Bob") - - let unlockSuccess2 = await unlockToken(interopContract2, lockContractId2, Bob2) - let unlockSuccess1 = await unlockToken(interopContract1, lockContractId1, Alice1) - - if(!unlockSuccess2) - console.log("\n !!! Unlocking Bob's tokens not successfull !!!") - if(!unlockSuccess1) - console.log("\n !!! Unlocking Alice's tokens not successfull !!!") - } - else{ - // If Alice's withdrawal is successful, Bob goes ahead and claims Alice's - // AliceERC20 tokens locked in the lockContractId1 - let claimSuccess1 = await claimToken(interopContract1, lockContractId1, Bob1, preimage) // we assume Bob's claim to be successful if Alice's claim is successful - - if(!claimSuccess1){ - console.log("\n !!! Claim by Bob not successfull !!! \n We had assumed Bob's claim will be successful if Alice's claim is successful") - } - } - - console.log("\n Balances after Bob's attempt to claim in Network 1:") - await getBalances(Alice1, Bob1, Alice2, Bob2) + // Network 1 + const provider1 = new Web3.providers.HttpProvider( + "http://" + networkHost1 + ":" + networkPort1, + ); + const web3N1 = new Web3(provider1); + const accounts1 = await web3N1.eth.getAccounts(); + + const Alice1 = accounts1[1]; // owner of AliceERC20 and wants swap for BobERC20 + const Bob1 = accounts1[2]; // owner of BobERC20 and wants to swap for AliceERC20 + console.log("Alice address in Network 1", Alice1); + console.log("Bob address in Network 1", Bob1); + + const contractOwner1 = accounts1[0]; // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed + + // Network 2 + const provider2 = new Web3.providers.HttpProvider( + "http://" + networkHost2 + ":" + networkPort2, + ); + const web3N2 = new Web3(provider2); + const accounts2 = await web3N2.eth.getAccounts(); + + const Alice2 = accounts2[1]; // owner of AliceERC20 and wants swap for BobERC20 + const Bob2 = accounts2[2]; // owner of BobERC20 and wants to swap for AliceERC20 + console.log("Alice address in Network 2", Alice2); + console.log("Bob address in Network 2", Bob2); + + const contractOwner2 = accounts2[0]; // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed + + // Initialization + const tokenSupply = 1000; + const tokenAmount = 10; // Number of tokens to be exchanged + const tokenId = 1; + const senderInitialBalance = tokenAmount; + + await init( + provider1, + provider2, + contractOwner1, + contractOwner2, + Alice1, + Bob2, + tokenSupply, + senderInitialBalance, + ); + + console.log("\n Balances after init():"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + preimage = crypto.randomBytes(32); // to sample a preimage for the hash + hash = crypto.createHash("sha256").update(preimage).digest(); + console.log("Hash: ", hash); + + let timeOut = 15; + let timeLockSeconds = Math.floor(Date.now() / 1000) + 2 * timeOut; + + // Creating a HTLC contract for Alice locking her AliceERC20 tokens for Bob + let lockTx1 = await lockToken( + Alice1, + Bob1, + AliceERC20, + 1, + interopContract1, + hash, + timeLockSeconds, + tokenId, + ); + if (!lockTx1) { + console.log( + "\n !!! Locking of Alice's tokens failed in Netowrk 1. Aborting here !!!", + ); + return; + } + let lockContractId1 = lockTx1.logs[0].args.lockContractId; + + console.log("\n Balances after Alice locks her tokens in Network 1:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // After he observes this lockContract created in Network 1, + // Bob creates a similar contract in Network 2 using the same + // hash to transfer the agreed upon amount of BobERC20 to Alice. + // Bob sets the timeLock such that he will have enough time to + // claim Alice's tokens in Network 1 after she claims Bob's + // tokens in Network 2. + timeLockSeconds = Math.floor(Date.now() / 1000) + timeOut; + let lockTx2 = await lockToken( + Bob2, + Alice2, + BobERC20, + tokenAmount, + interopContract2, + hash, + timeLockSeconds, + tokenId, + ); + if (!lockTx2) { + console.log( + "\n !!! Locking of Bob's tokens failed in Netowrk 2. Aborting here !!!", + ); + return; + } + let lockContractId2 = lockTx2.logs[0].args.lockContractId; + + console.log("\n Balances after creating Bob locks his tokens in Network 2:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // Alice withdrawing Bob's BobERC20 token from lockContractId2 + let claimSuccess2 = await claimToken( + interopContract2, + lockContractId2, + Alice2, + preimage, + ); + + console.log("\n Balances after Alice's attempt to claim in Network 2:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // If Alice's claim is not successfull, then Alice and Bob unlock their locked tokens + if (!claimSuccess2) { + sleep(2 * timeOut * 1000); + console.log( + "\n !!! Claim by Alice not successfull !!! \n Unlocking and refunding tokens to Alice and Bob", + ); + + let unlockSuccess2 = await unlockToken( + interopContract2, + lockContractId2, + Bob2, + ); + let unlockSuccess1 = await unlockToken( + interopContract1, + lockContractId1, + Alice1, + ); + + if (!unlockSuccess2) + console.log("\n !!! Unlocking Bob's tokens not successfull !!!"); + if (!unlockSuccess1) + console.log("\n !!! Unlocking Alice's tokens not successfull !!!"); + } else { + // If Alice's withdrawal is successful, Bob goes ahead and claims Alice's + // AliceERC20 tokens locked in the lockContractId1 + let claimSuccess1 = await claimToken( + interopContract1, + lockContractId1, + Bob1, + preimage, + ); // we assume Bob's claim to be successful if Alice's claim is successful + + if (!claimSuccess1) { + console.log( + "\n !!! Claim by Bob not successfull !!! \n We had assumed Bob's claim will be successful if Alice's claim is successful", + ); + } + } + + console.log("\n Balances after Bob's attempt to claim in Network 1:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); } -main() +main(); diff --git a/weaver/samples/besu/simpleasset/app/AssetExchangeERC721_20.js b/weaver/samples/besu/simpleasset/app/AssetExchangeERC721_20.js index d02a9bde23..7b135c9111 100644 --- a/weaver/samples/besu/simpleasset/app/AssetExchangeERC721_20.js +++ b/weaver/samples/besu/simpleasset/app/AssetExchangeERC721_20.js @@ -4,256 +4,369 @@ * SPDX-License-Identifier: Apache-2.0 */ -const promisify = require('util').promisify -const sleep = promisify(require('timers').setTimeout) -const fs = require('fs') -const path = require('path') +const promisify = require("util").promisify; +const sleep = promisify(require("timers").setTimeout); +const fs = require("fs"); +const path = require("path"); const contract = require("@truffle/contract"); -const Web3 = require("web3") -const crypto = require('crypto') +const Web3 = require("web3"); +const crypto = require("crypto"); -const networkHost1 = "localhost" -const networkPort1 = "8545" -const networkHost2 = "localhost" -const networkPort2 = "9544" +const networkHost1 = "localhost"; +const networkPort1 = "8545"; +const networkHost2 = "localhost"; +const networkPort2 = "9544"; -let interopContract1 -let interopContract2 -let AliceERC721 -let BobERC20 +let interopContract1; +let interopContract2; +let AliceERC721; +let BobERC20; - -// Function to obtain an instance of a smart contract when provided +// Function to obtain an instance of a smart contract when provided // as input the path to its JSON file output by 'truffle compile'. -// (Assuming that the current folder is a sibling folder to build, +// (Assuming that the current folder is a sibling folder to build, // the path to json would be ../build/contracts/ContractName.json) async function getContractInstance(provider, pathToJson) { - const jsonFile = path.resolve(__dirname, pathToJson) - var jsonFileContents = fs.readFileSync(jsonFile) - var contractName = contract(JSON.parse(jsonFileContents)) - contractName.setProvider(provider) - var instance = await contractName.deployed().catch(function () { - console.log("Failed getting the contractName!"); - }) - return instance + const jsonFile = path.resolve(__dirname, pathToJson); + var jsonFileContents = fs.readFileSync(jsonFile); + var contractName = contract(JSON.parse(jsonFileContents)); + contractName.setProvider(provider); + var instance = await contractName.deployed().catch(function () { + console.log("Failed getting the contractName!"); + }); + return instance; } - // Initialization of the parameters -async function init(provider1, provider2, contractOwner1, contractOwner2, Alice1, Bob2, tokenSupply, senderInitialBalance) { - interopContract1 = await getContractInstance(provider1, '../build/contracts/AssetExchangeContract.json').catch(function () { - console.log("Failed getting interopContract1!"); - }) - interopContract2 = await getContractInstance(provider2, '../build/contracts/AssetExchangeContract.json').catch(function () { - console.log("Failed getting interopContract2!"); - }) - - AliceERC721 = await getContractInstance(provider1, '../build/contracts/AliceERC721.json').catch(function () { - console.log("Failed getting AliceERC721 token contract!"); - }) - BobERC20 = await getContractInstance(provider2, '../build/contracts/BobERC20.json').catch(function () { - console.log("Failed getting BobERC20 token contract!"); - }) - - // Issue AliceERC721 tokens to Alice in Network 1 and BobERC20 tokens - // to Bob in Network 2. A minimal number of tokens equal to the - // number of token being exchanged is issued to Alice and Bob to - // ensure that the exchange in this test application does not fail - // due to insufficient funds. - await AliceERC721.transferFrom(contractOwner1, Alice1, 1, { from: contractOwner1 }).catch(function (e) { - console.log("AliceERC721 transfer threw an error; Probably the token supply is used up!"); - }) - await BobERC20.transfer(Bob2, senderInitialBalance, { from: contractOwner2 }).catch(function () { - console.log("BobERC20 transfer threw an error; Probably the token supply is used up!"); - }) +async function init( + provider1, + provider2, + contractOwner1, + contractOwner2, + Alice1, + Bob2, + tokenSupply, + senderInitialBalance, +) { + interopContract1 = await getContractInstance( + provider1, + "../build/contracts/AssetExchangeContract.json", + ).catch(function () { + console.log("Failed getting interopContract1!"); + }); + interopContract2 = await getContractInstance( + provider2, + "../build/contracts/AssetExchangeContract.json", + ).catch(function () { + console.log("Failed getting interopContract2!"); + }); + + AliceERC721 = await getContractInstance( + provider1, + "../build/contracts/AliceERC721.json", + ).catch(function () { + console.log("Failed getting AliceERC721 token contract!"); + }); + BobERC20 = await getContractInstance( + provider2, + "../build/contracts/BobERC20.json", + ).catch(function () { + console.log("Failed getting BobERC20 token contract!"); + }); + + // Issue AliceERC721 tokens to Alice in Network 1 and BobERC20 tokens + // to Bob in Network 2. A minimal number of tokens equal to the + // number of token being exchanged is issued to Alice and Bob to + // ensure that the exchange in this test application does not fail + // due to insufficient funds. + await AliceERC721.transferFrom(contractOwner1, Alice1, 1, { + from: contractOwner1, + }).catch(function (e) { + console.log( + "AliceERC721 transfer threw an error; Probably the token supply is used up!", + ); + }); + await BobERC20.transfer(Bob2, senderInitialBalance, { + from: contractOwner2, + }).catch(function () { + console.log( + "BobERC20 transfer threw an error; Probably the token supply is used up!", + ); + }); } - -// Claim function of a fungible asset/token of type tokenContractId -// and amount tokenAmount locked using contractId for a receiver. -// preimage is the secret to unlock the asset corresponding to the commitment +// Claim function of a fungible asset/token of type tokenContractId +// and amount tokenAmount locked using contractId for a receiver. +// preimage is the secret to unlock the asset corresponding to the commitment // used when locking it -async function claimToken(interopContract, lockContractId, recipient, preimage) { - console.log("\n Claiming %s using preimage: %o", lockContractId, preimage) - // console.log(JSON.parse(JSON.stringify(preimage)).data.toString('utf8')) - var claimStatus = await interopContract.claimAsset(lockContractId, preimage, { - from: recipient - }).catch(function (err) { - console.log(err) - console.log("claimAsset threw an error"); - claimStatus = false - }) - - return claimStatus +async function claimToken( + interopContract, + lockContractId, + recipient, + preimage, +) { + console.log("\n Claiming %s using preimage: %o", lockContractId, preimage); + // console.log(JSON.parse(JSON.stringify(preimage)).data.toString('utf8')) + var claimStatus = await interopContract + .claimAsset(lockContractId, preimage, { + from: recipient, + }) + .catch(function (err) { + console.log(err); + console.log("claimAsset threw an error"); + claimStatus = false; + }); + + return claimStatus; } - -// Unlock function of a locked fungible asset/token +// Unlock function of a locked fungible asset/token async function unlockToken(interopContract, lockContractId, sender) { - var unlockStatus = await interopContract.unlockAsset(lockContractId, { - from: sender - }).catch(function () { - console.log("unlockAsset threw an error"); - unlockStatus = false - }) - - return unlockStatus + var unlockStatus = await interopContract + .unlockAsset(lockContractId, { + from: sender, + }) + .catch(function () { + console.log("unlockAsset threw an error"); + unlockStatus = false; + }); + + return unlockStatus; } - // Function to create a new smart contract for locking asset // 'sender' locks 'tokenAmount' number of tokens of type 'tokenContract' // for 'recipient' using the contract constructs of 'interopContract' // with hashLock and timeLock providing the conditions for claiming/unlocking -async function lockToken(sender, recipient, tokenContract, tokenAmount, interopContract, hashLock, timeLock, tokenId = 0, data = "") { - // initiator of the swap has to first designate the swap contract as a spender of his/her money - // with allowance matching the swap amount - await tokenContract.approve(tokenContract.address, tokenAmount, { from: sender }).catch(function () { - console.log("Token approval failed!!!"); - return false - }) - var lockStatus = interopContract.lockAsset( - recipient, - tokenContract.address, - tokenAmount, - hashLock, - timeLock, - tokenId, - Web3.utils.utf8ToHex(data), - { - from: sender - } - ).catch(function () { - console.log("lockAsset threw an error"); - lockStatus = false - }) - - return lockStatus +async function lockToken( + sender, + recipient, + tokenContract, + tokenAmount, + interopContract, + hashLock, + timeLock, + tokenId = 0, + data = "", +) { + // initiator of the swap has to first designate the swap contract as a spender of his/her money + // with allowance matching the swap amount + await tokenContract + .approve(tokenContract.address, tokenAmount, { from: sender }) + .catch(function () { + console.log("Token approval failed!!!"); + return false; + }); + var lockStatus = interopContract + .lockAsset( + recipient, + tokenContract.address, + tokenAmount, + hashLock, + timeLock, + tokenId, + Web3.utils.utf8ToHex(data), + { + from: sender, + }, + ) + .catch(function () { + console.log("lockAsset threw an error"); + lockStatus = false; + }); + + return lockStatus; } - -// A function to obtain and print the account balances of a pair +// A function to obtain and print the account balances of a pair // of accounts in the two participating networks. -// Designed for printing the account balances of the sender and +// Designed for printing the account balances of the sender and // recipient at various stages of the exchange. async function getBalances(Alice1, Bob1, Alice2, Bob2) { - var AliceAliceERC721Balance = await AliceERC721.balanceOf(Alice1) - console.log("Alice balance of AliceERC721 in Network 1", AliceAliceERC721Balance.toString()) - - var BobAliceERC721Balance = await AliceERC721.balanceOf(Bob1) - console.log("Bob balance of AliceERC721 in Network 1", await BobAliceERC721Balance.toString()) - - var AliceBobERC20Balance = await BobERC20.balanceOf(Alice2) - console.log("Alice balance of BobERC20 in Network 2", AliceBobERC20Balance.toString()) - - var BobBobERC20Balance = await BobERC20.balanceOf(Bob2) - console.log("Bob balance of BobERC20 in Network 2", await BobBobERC20Balance.toString()) + var AliceAliceERC721Balance = await AliceERC721.balanceOf(Alice1); + console.log( + "Alice balance of AliceERC721 in Network 1", + AliceAliceERC721Balance.toString(), + ); + + var BobAliceERC721Balance = await AliceERC721.balanceOf(Bob1); + console.log( + "Bob balance of AliceERC721 in Network 1", + await BobAliceERC721Balance.toString(), + ); + + var AliceBobERC20Balance = await BobERC20.balanceOf(Alice2); + console.log( + "Alice balance of BobERC20 in Network 2", + AliceBobERC20Balance.toString(), + ); + + var BobBobERC20Balance = await BobERC20.balanceOf(Bob2); + console.log( + "Bob balance of BobERC20 in Network 2", + await BobBobERC20Balance.toString(), + ); } - // Main entry point to the app async function main() { - // Network 1 - const provider1 = new Web3.providers.HttpProvider('http://' + networkHost1 + ':' + networkPort1) - const web3N1 = new Web3(provider1) - const accounts1 = await web3N1.eth.getAccounts() - - const Alice1 = accounts1[1] // owner of AliceERC721 and wants swap for BobERC20 - const Bob1 = accounts1[2] // owner of BobERC20 and wants to swap for AliceERC721 - console.log("Alice address in Network 1", Alice1) - console.log("Bob address in Network 1", Bob1) - - const contractOwner1 = accounts1[0] // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed - - // Network 2 - const provider2 = new Web3.providers.HttpProvider('http://' + networkHost2 + ':' + networkPort2) - const web3N2 = new Web3(provider2) - const accounts2 = await web3N2.eth.getAccounts() - - const Alice2 = accounts2[1] // owner of AliceERC721 and wants swap for BobERC20 - const Bob2 = accounts2[2] // owner of BobERC20 and wants to swap for AliceERC721 - console.log("Alice address in Network 2", Alice2) - console.log("Bob address in Network 2", Bob2) - - const contractOwner2 = accounts2[0] // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed - - // Initialization - const tokenSupply = 1000 - const tokenAmount = 10 // Number of tokens to be exchanged - const tokenId = 1; - const senderInitialBalance = tokenAmount - - await init(provider1, provider2, contractOwner1, contractOwner2, Alice1, Bob2, tokenSupply, senderInitialBalance) - - console.log("\n Balances after init():") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - preimage = crypto.randomBytes(32) // to sample a preimage for the hash - hash = crypto.createHash('sha256').update(preimage).digest() - console.log("Hash: ", hash) - - let timeOut = 15 - let timeLockSeconds = Math.floor(Date.now() / 1000) + 2 * timeOut - - // Creating a HTLC contract for Alice locking her AliceERC721 tokens for Bob - let lockTx1 = await lockToken(Alice1, Bob1, AliceERC721, 1, interopContract1, hash, timeLockSeconds, tokenId) - if (!lockTx1) { - console.log("\n !!! Locking of Alice's tokens failed in Netowrk 1. Aborting here !!!") - return - } - let lockContractId1 = lockTx1.logs[0].args.lockContractId - - console.log("\n Balances after Alice locks her tokens in Network 1:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // After he observes this lockContract created in Network 1, - // Bob creates a similar contract in Network 2 using the same - // hash to transfer the agreed upon amount of BobERC20 to Alice. - // Bob sets the timeLock such that he will have enough time to - // claim Alice's tokens in Network 1 after she claims Bob's - // tokens in Network 2. - timeLockSeconds = Math.floor(Date.now() / 1000) + timeOut - let lockTx2 = await lockToken(Bob2, Alice2, BobERC20, tokenAmount, interopContract2, hash, timeLockSeconds, tokenId) - if (!lockTx2) { - console.log("\n !!! Locking of Bob's tokens failed in Netowrk 2. Aborting here !!!") - return - } - let lockContractId2 = lockTx2.logs[0].args.lockContractId - - console.log("\n Balances after creating Bob locks his tokens in Network 2:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // Alice withdrawing Bob's BobERC20 token from lockContractId2 - let claimSuccess2 = await claimToken(interopContract2, lockContractId2, Alice2, preimage) - - console.log("\n Balances after Alice's attempt to claim in Network 2:") - await getBalances(Alice1, Bob1, Alice2, Bob2) - - // If Alice's claim is not successfull, then Alice and Bob unlock their locked tokens - if (!claimSuccess2) { - sleep(2 * timeOut * 1000) - console.log("\n !!! Claim by Alice not successfull !!! \n Unlocking and refunding tokens to Alice and Bob") - - let unlockSuccess2 = await unlockToken(interopContract2, lockContractId2, Bob2) - let unlockSuccess1 = await unlockToken(interopContract1, lockContractId1, Alice1) - - if (!unlockSuccess2) - console.log("\n !!! Unlocking Bob's tokens not successfull !!!") - if (!unlockSuccess1) - console.log("\n !!! Unlocking Alice's tokens not successfull !!!") - } - else { - // If Alice's withdrawal is successful, Bob goes ahead and claims Alice's - // AliceERC721 tokens locked in the lockContractId1 - let claimSuccess1 = await claimToken(interopContract1, lockContractId1, Bob1, preimage) // we assume Bob's claim to be successful if Alice's claim is successful - - if (!claimSuccess1) { - console.log("\n !!! Claim by Bob not successfull !!! \n We had assumed Bob's claim will be successful if Alice's claim is successful") - } - } - - console.log("\n Balances after Bob's attempt to claim in Network 1:") - await getBalances(Alice1, Bob1, Alice2, Bob2) + // Network 1 + const provider1 = new Web3.providers.HttpProvider( + "http://" + networkHost1 + ":" + networkPort1, + ); + const web3N1 = new Web3(provider1); + const accounts1 = await web3N1.eth.getAccounts(); + + const Alice1 = accounts1[1]; // owner of AliceERC721 and wants swap for BobERC20 + const Bob1 = accounts1[2]; // owner of BobERC20 and wants to swap for AliceERC721 + console.log("Alice address in Network 1", Alice1); + console.log("Bob address in Network 1", Bob1); + + const contractOwner1 = accounts1[0]; // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed + + // Network 2 + const provider2 = new Web3.providers.HttpProvider( + "http://" + networkHost2 + ":" + networkPort2, + ); + const web3N2 = new Web3(provider2); + const accounts2 = await web3N2.eth.getAccounts(); + + const Alice2 = accounts2[1]; // owner of AliceERC721 and wants swap for BobERC20 + const Bob2 = accounts2[2]; // owner of BobERC20 and wants to swap for AliceERC721 + console.log("Alice address in Network 2", Alice2); + console.log("Bob address in Network 2", Bob2); + + const contractOwner2 = accounts2[0]; // owner of all the minted tokens when the contract was created, given how truffleconfig.js is composed + + // Initialization + const tokenSupply = 1000; + const tokenAmount = 10; // Number of tokens to be exchanged + const tokenId = 1; + const senderInitialBalance = tokenAmount; + + await init( + provider1, + provider2, + contractOwner1, + contractOwner2, + Alice1, + Bob2, + tokenSupply, + senderInitialBalance, + ); + + console.log("\n Balances after init():"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + preimage = crypto.randomBytes(32); // to sample a preimage for the hash + hash = crypto.createHash("sha256").update(preimage).digest(); + console.log("Hash: ", hash); + + let timeOut = 15; + let timeLockSeconds = Math.floor(Date.now() / 1000) + 2 * timeOut; + + // Creating a HTLC contract for Alice locking her AliceERC721 tokens for Bob + let lockTx1 = await lockToken( + Alice1, + Bob1, + AliceERC721, + 1, + interopContract1, + hash, + timeLockSeconds, + tokenId, + ); + if (!lockTx1) { + console.log( + "\n !!! Locking of Alice's tokens failed in Netowrk 1. Aborting here !!!", + ); + return; + } + let lockContractId1 = lockTx1.logs[0].args.lockContractId; + + console.log("\n Balances after Alice locks her tokens in Network 1:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // After he observes this lockContract created in Network 1, + // Bob creates a similar contract in Network 2 using the same + // hash to transfer the agreed upon amount of BobERC20 to Alice. + // Bob sets the timeLock such that he will have enough time to + // claim Alice's tokens in Network 1 after she claims Bob's + // tokens in Network 2. + timeLockSeconds = Math.floor(Date.now() / 1000) + timeOut; + let lockTx2 = await lockToken( + Bob2, + Alice2, + BobERC20, + tokenAmount, + interopContract2, + hash, + timeLockSeconds, + tokenId, + ); + if (!lockTx2) { + console.log( + "\n !!! Locking of Bob's tokens failed in Netowrk 2. Aborting here !!!", + ); + return; + } + let lockContractId2 = lockTx2.logs[0].args.lockContractId; + + console.log("\n Balances after creating Bob locks his tokens in Network 2:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // Alice withdrawing Bob's BobERC20 token from lockContractId2 + let claimSuccess2 = await claimToken( + interopContract2, + lockContractId2, + Alice2, + preimage, + ); + + console.log("\n Balances after Alice's attempt to claim in Network 2:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); + + // If Alice's claim is not successfull, then Alice and Bob unlock their locked tokens + if (!claimSuccess2) { + sleep(2 * timeOut * 1000); + console.log( + "\n !!! Claim by Alice not successfull !!! \n Unlocking and refunding tokens to Alice and Bob", + ); + + let unlockSuccess2 = await unlockToken( + interopContract2, + lockContractId2, + Bob2, + ); + let unlockSuccess1 = await unlockToken( + interopContract1, + lockContractId1, + Alice1, + ); + + if (!unlockSuccess2) + console.log("\n !!! Unlocking Bob's tokens not successfull !!!"); + if (!unlockSuccess1) + console.log("\n !!! Unlocking Alice's tokens not successfull !!!"); + } else { + // If Alice's withdrawal is successful, Bob goes ahead and claims Alice's + // AliceERC721 tokens locked in the lockContractId1 + let claimSuccess1 = await claimToken( + interopContract1, + lockContractId1, + Bob1, + preimage, + ); // we assume Bob's claim to be successful if Alice's claim is successful + + if (!claimSuccess1) { + console.log( + "\n !!! Claim by Bob not successfull !!! \n We had assumed Bob's claim will be successful if Alice's claim is successful", + ); + } + } + + console.log("\n Balances after Bob's attempt to claim in Network 1:"); + await getBalances(Alice1, Bob1, Alice2, Bob2); } -main() +main(); diff --git a/weaver/samples/besu/simpleasset/get-network-details.js b/weaver/samples/besu/simpleasset/get-network-details.js index 0f5e85fb38..405f7765d7 100644 --- a/weaver/samples/besu/simpleasset/get-network-details.js +++ b/weaver/samples/besu/simpleasset/get-network-details.js @@ -4,75 +4,78 @@ * SPDX-License-Identifier: Apache-2.0 */ -require('dotenv').config(); -const fs = require("fs") -const readline = require('readline') -const promisify = require('util').promisify -const sleep = promisify(require('timers').setTimeout) -const Web3 = require ("web3") - -const networkHost = process.env.BESU_NETWORK_HOST ? process.env.BESU_NETWORK_HOST : "localhost" -const networkPort = process.env.BESU_NETWORK_PORT ? process.env.BESU_NETWORK_PORT : "8545" - -const web3 = new Web3(new Web3.providers.HttpProvider('http://'+networkHost+':'+networkPort)) +require("dotenv").config(); +const fs = require("fs"); +const readline = require("readline"); +const promisify = require("util").promisify; +const sleep = promisify(require("timers").setTimeout); +const Web3 = require("web3"); + +const networkHost = process.env.BESU_NETWORK_HOST + ? process.env.BESU_NETWORK_HOST + : "localhost"; +const networkPort = process.env.BESU_NETWORK_PORT + ? process.env.BESU_NETWORK_PORT + : "8545"; + +const web3 = new Web3( + new Web3.providers.HttpProvider("http://" + networkHost + ":" + networkPort), +); async function getNetworkDetails() { + // Get the accounts linked + accounts = await web3.eth.getAccounts(); - // Get the accounts linked - accounts = await web3.eth.getAccounts() + // Get the network ID + networkId = await web3.eth.net.getId(); - // Get the network ID - networkId = await web3.eth.net.getId() - - return { - accounts, - networkId - } + return { + accounts, + networkId, + }; } - async function main() { - - truffleConfigTemplateString = fs.readFileSync('truffle-config.js').toString().split('\n') - truffleConfigFileString = '' - - let networkDetails = await getNetworkDetails() - let accounts = networkDetails.accounts, - networkId = networkDetails.networkId - - for (const line of truffleConfigTemplateString) { - // Each line in the file will be successively available here as `line`. - str = line; - - if(str.trim().startsWith("host:")) { - str = "\t\t\thost: \""+networkHost+"\"," - } - - if(str.trim().startsWith("port:")) { - str = "\t\t\tport: "+networkPort+", // 7545 - default for Ganache" - } - - if(str.trim().startsWith("network_id:")) { - str = "\t\t\tnetwork_id: \""+networkId+"\", // 4447 - default for Ganache" - } - - if(str.trim().startsWith("from:")) { - str = "\t\t\tfrom: \""+accounts[0]+"\"," - } - - if(!str.startsWith("}")) { - str = str + "\n" - } - - truffleConfigFileString += str - } - - // Writing the updated content to truffle-config - fs.writeFileSync( - 'truffle-config.js', - truffleConfigFileString - ) - + truffleConfigTemplateString = fs + .readFileSync("truffle-config.js") + .toString() + .split("\n"); + truffleConfigFileString = ""; + + let networkDetails = await getNetworkDetails(); + let accounts = networkDetails.accounts, + networkId = networkDetails.networkId; + + for (const line of truffleConfigTemplateString) { + // Each line in the file will be successively available here as `line`. + str = line; + + if (str.trim().startsWith("host:")) { + str = '\t\t\thost: "' + networkHost + '",'; + } + + if (str.trim().startsWith("port:")) { + str = "\t\t\tport: " + networkPort + ", // 7545 - default for Ganache"; + } + + if (str.trim().startsWith("network_id:")) { + str = + '\t\t\tnetwork_id: "' + networkId + '", // 4447 - default for Ganache'; + } + + if (str.trim().startsWith("from:")) { + str = '\t\t\tfrom: "' + accounts[0] + '",'; + } + + if (!str.startsWith("}")) { + str = str + "\n"; + } + + truffleConfigFileString += str; + } + + // Writing the updated content to truffle-config + fs.writeFileSync("truffle-config.js", truffleConfigFileString); } -main() +main(); diff --git a/weaver/samples/besu/simpleasset/migrations/1_initial_migration.js b/weaver/samples/besu/simpleasset/migrations/1_initial_migration.js index ee70df2af5..75f155447c 100644 --- a/weaver/samples/besu/simpleasset/migrations/1_initial_migration.js +++ b/weaver/samples/besu/simpleasset/migrations/1_initial_migration.js @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -var Migrations = artifacts.require("./Migrations.sol") +var Migrations = artifacts.require("./Migrations.sol"); module.exports = function (deployer) { - deployer.deploy(Migrations) -} + deployer.deploy(Migrations); +}; diff --git a/weaver/samples/besu/simpleasset/migrations/2_deploy_contracts.js b/weaver/samples/besu/simpleasset/migrations/2_deploy_contracts.js index f04d0b9f74..b7334e6a93 100644 --- a/weaver/samples/besu/simpleasset/migrations/2_deploy_contracts.js +++ b/weaver/samples/besu/simpleasset/migrations/2_deploy_contracts.js @@ -4,17 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ -const AliceERC20 = artifacts.require('./AliceERC20.sol') -const BobERC20 = artifacts.require('./BobERC20.sol') -const AliceERC721 = artifacts.require('./AliceERC721.sol') -const AssetExchangeContract = artifacts.require('AssetExchangeContract') -const AliceERC1155 = artifacts.require('./AliceERC1155.sol') - +const AliceERC20 = artifacts.require("./AliceERC20.sol"); +const BobERC20 = artifacts.require("./BobERC20.sol"); +const AliceERC721 = artifacts.require("./AliceERC721.sol"); +const AssetExchangeContract = artifacts.require("AssetExchangeContract"); +const AliceERC1155 = artifacts.require("./AliceERC1155.sol"); module.exports = function (deployer) { - deployer.deploy(AliceERC20, 1000) // Change intialSupply from 1000 as required - deployer.deploy(BobERC20, 1000) // Change intialSupply from 1000 as required - deployer.deploy(AliceERC721) - deployer.deploy(AssetExchangeContract) - deployer.deploy(AliceERC1155) -} + deployer.deploy(AliceERC20, 1000); // Change intialSupply from 1000 as required + deployer.deploy(BobERC20, 1000); // Change intialSupply from 1000 as required + deployer.deploy(AliceERC721); + deployer.deploy(AssetExchangeContract); + deployer.deploy(AliceERC1155); +}; diff --git a/weaver/samples/besu/simpleasset/truffle-config.js b/weaver/samples/besu/simpleasset/truffle-config.js index bf2fd57755..f59d419a47 100644 --- a/weaver/samples/besu/simpleasset/truffle-config.js +++ b/weaver/samples/besu/simpleasset/truffle-config.js @@ -5,43 +5,41 @@ */ module.exports = { - networks: { - development: { - host: "localhost", - port: 9544, // 7545 - default for Ganache - network_id: "1338", // 4447 - default for Ganache - //type: "fabric-evm", - from: "0x35D99e41ce0Aa49d1B2B62f286b9F4189df7B7ae", - gasPrice: 0, - gas: "0x1ffffffffffffe", - verbose: true, // helps with debugging contract deployment issues - } - }, - compilers: { - solc: { - // Unless this is pinned to 0.8.8, some breaking changes that solc - // has snuck in [1][2] around 0.8.15 (for IR) are breaking the contract - // deployment in a way that opcodes end up in the migration contract's - // constructor that Besu does not recognize ("opcode INVALID") in - // the Besu logs and then sends back an "internal error" message - // via the JSON-RPC response, which is a bug IMO it should state - // that the user input was invalid (user input being the contract) - // - // [1]: https://docs.soliditylang.org/en/v0.8.15/ir-breaking-changes.html#semantic-only-changes - // [2]: https://github.com/ethereum/solidity/issues/13311#issuecomment-1199274310 - version: "0.8.8", - settings: { - optimizer: { - enabled: true, - runs: 1500 - }, - // If set to true, then the following error occurs: - // > Compiling ./contracts/transferInterface.sol - // YulException: Variable var_amount_3290 is 9 slot(s) too deep inside the stack. - viaIR: false, - } - - }, - - } -} + networks: { + development: { + host: "localhost", + port: 9544, // 7545 - default for Ganache + network_id: "1338", // 4447 - default for Ganache + //type: "fabric-evm", + from: "0x35D99e41ce0Aa49d1B2B62f286b9F4189df7B7ae", + gasPrice: 0, + gas: "0x1ffffffffffffe", + verbose: true, // helps with debugging contract deployment issues + }, + }, + compilers: { + solc: { + // Unless this is pinned to 0.8.8, some breaking changes that solc + // has snuck in [1][2] around 0.8.15 (for IR) are breaking the contract + // deployment in a way that opcodes end up in the migration contract's + // constructor that Besu does not recognize ("opcode INVALID") in + // the Besu logs and then sends back an "internal error" message + // via the JSON-RPC response, which is a bug IMO it should state + // that the user input was invalid (user input being the contract) + // + // [1]: https://docs.soliditylang.org/en/v0.8.15/ir-breaking-changes.html#semantic-only-changes + // [2]: https://github.com/ethereum/solidity/issues/13311#issuecomment-1199274310 + version: "0.8.8", + settings: { + optimizer: { + enabled: true, + runs: 1500, + }, + // If set to true, then the following error occurs: + // > Compiling ./contracts/transferInterface.sol + // YulException: Variable var_amount_3290 is 9 slot(s) too deep inside the stack. + viaIR: false, + }, + }, + }, +}; diff --git a/weaver/samples/besu/simplestate/get-network-details.js b/weaver/samples/besu/simplestate/get-network-details.js index 0f5e85fb38..405f7765d7 100644 --- a/weaver/samples/besu/simplestate/get-network-details.js +++ b/weaver/samples/besu/simplestate/get-network-details.js @@ -4,75 +4,78 @@ * SPDX-License-Identifier: Apache-2.0 */ -require('dotenv').config(); -const fs = require("fs") -const readline = require('readline') -const promisify = require('util').promisify -const sleep = promisify(require('timers').setTimeout) -const Web3 = require ("web3") - -const networkHost = process.env.BESU_NETWORK_HOST ? process.env.BESU_NETWORK_HOST : "localhost" -const networkPort = process.env.BESU_NETWORK_PORT ? process.env.BESU_NETWORK_PORT : "8545" - -const web3 = new Web3(new Web3.providers.HttpProvider('http://'+networkHost+':'+networkPort)) +require("dotenv").config(); +const fs = require("fs"); +const readline = require("readline"); +const promisify = require("util").promisify; +const sleep = promisify(require("timers").setTimeout); +const Web3 = require("web3"); + +const networkHost = process.env.BESU_NETWORK_HOST + ? process.env.BESU_NETWORK_HOST + : "localhost"; +const networkPort = process.env.BESU_NETWORK_PORT + ? process.env.BESU_NETWORK_PORT + : "8545"; + +const web3 = new Web3( + new Web3.providers.HttpProvider("http://" + networkHost + ":" + networkPort), +); async function getNetworkDetails() { + // Get the accounts linked + accounts = await web3.eth.getAccounts(); - // Get the accounts linked - accounts = await web3.eth.getAccounts() + // Get the network ID + networkId = await web3.eth.net.getId(); - // Get the network ID - networkId = await web3.eth.net.getId() - - return { - accounts, - networkId - } + return { + accounts, + networkId, + }; } - async function main() { - - truffleConfigTemplateString = fs.readFileSync('truffle-config.js').toString().split('\n') - truffleConfigFileString = '' - - let networkDetails = await getNetworkDetails() - let accounts = networkDetails.accounts, - networkId = networkDetails.networkId - - for (const line of truffleConfigTemplateString) { - // Each line in the file will be successively available here as `line`. - str = line; - - if(str.trim().startsWith("host:")) { - str = "\t\t\thost: \""+networkHost+"\"," - } - - if(str.trim().startsWith("port:")) { - str = "\t\t\tport: "+networkPort+", // 7545 - default for Ganache" - } - - if(str.trim().startsWith("network_id:")) { - str = "\t\t\tnetwork_id: \""+networkId+"\", // 4447 - default for Ganache" - } - - if(str.trim().startsWith("from:")) { - str = "\t\t\tfrom: \""+accounts[0]+"\"," - } - - if(!str.startsWith("}")) { - str = str + "\n" - } - - truffleConfigFileString += str - } - - // Writing the updated content to truffle-config - fs.writeFileSync( - 'truffle-config.js', - truffleConfigFileString - ) - + truffleConfigTemplateString = fs + .readFileSync("truffle-config.js") + .toString() + .split("\n"); + truffleConfigFileString = ""; + + let networkDetails = await getNetworkDetails(); + let accounts = networkDetails.accounts, + networkId = networkDetails.networkId; + + for (const line of truffleConfigTemplateString) { + // Each line in the file will be successively available here as `line`. + str = line; + + if (str.trim().startsWith("host:")) { + str = '\t\t\thost: "' + networkHost + '",'; + } + + if (str.trim().startsWith("port:")) { + str = "\t\t\tport: " + networkPort + ", // 7545 - default for Ganache"; + } + + if (str.trim().startsWith("network_id:")) { + str = + '\t\t\tnetwork_id: "' + networkId + '", // 4447 - default for Ganache'; + } + + if (str.trim().startsWith("from:")) { + str = '\t\t\tfrom: "' + accounts[0] + '",'; + } + + if (!str.startsWith("}")) { + str = str + "\n"; + } + + truffleConfigFileString += str; + } + + // Writing the updated content to truffle-config + fs.writeFileSync("truffle-config.js", truffleConfigFileString); } -main() +main(); diff --git a/weaver/samples/besu/simplestate/migrations/1_initial_migration.js b/weaver/samples/besu/simplestate/migrations/1_initial_migration.js index ee70df2af5..75f155447c 100644 --- a/weaver/samples/besu/simplestate/migrations/1_initial_migration.js +++ b/weaver/samples/besu/simplestate/migrations/1_initial_migration.js @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -var Migrations = artifacts.require("./Migrations.sol") +var Migrations = artifacts.require("./Migrations.sol"); module.exports = function (deployer) { - deployer.deploy(Migrations) -} + deployer.deploy(Migrations); +}; diff --git a/weaver/samples/besu/simplestate/migrations/2_deploy_contracts.js b/weaver/samples/besu/simplestate/migrations/2_deploy_contracts.js index 6da8256054..8b80812946 100644 --- a/weaver/samples/besu/simplestate/migrations/2_deploy_contracts.js +++ b/weaver/samples/besu/simplestate/migrations/2_deploy_contracts.js @@ -5,9 +5,9 @@ */ // const Interop = artifacts.require('Interop') // Update this for interop contract after implementing data-sharing in besu and uncomment -const SimpleState = artifacts.require('./SimpleState.sol') +const SimpleState = artifacts.require("./SimpleState.sol"); module.exports = function (deployer) { - // deployer.deploy(Interop) - deployer.deploy(SimpleState, 1000) // Change intialSupply from 1000 as required -} + // deployer.deploy(Interop) + deployer.deploy(SimpleState, 1000); // Change intialSupply from 1000 as required +}; diff --git a/weaver/samples/besu/simplestate/truffle-config.js b/weaver/samples/besu/simplestate/truffle-config.js index adf1652435..faf7c1e5ab 100644 --- a/weaver/samples/besu/simplestate/truffle-config.js +++ b/weaver/samples/besu/simplestate/truffle-config.js @@ -5,21 +5,21 @@ */ module.exports = { - networks: { - development: { - host: "localhost", - port: 8545, // 7545 - default for Ganache - network_id: "1337", // 4447 - default for Ganache - //type: "fabric-evm", - from: "0x78e5A2632b4F0F53789533443787C647473dB66B", - gasPrice: 0, - gas: "0x1ffffffffffffe" - } - }, - - compilers: { - solc: { - version: "^0.8.8" - } - } -} + networks: { + development: { + host: "localhost", + port: 8545, // 7545 - default for Ganache + network_id: "1337", // 4447 - default for Ganache + //type: "fabric-evm", + from: "0x78e5A2632b4F0F53789533443787C647473dB66B", + gasPrice: 0, + gas: "0x1ffffffffffffe", + }, + }, + + compilers: { + solc: { + version: "^0.8.8", + }, + }, +}; diff --git a/weaver/samples/fabric/fabric-cli/.eslintrc b/weaver/samples/fabric/fabric-cli/.eslintrc deleted file mode 100644 index f9b051db73..0000000000 --- a/weaver/samples/fabric/fabric-cli/.eslintrc +++ /dev/null @@ -1,18 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", // Specifies the ESLint parser - "parserOptions": { - "ecmaVersion": 2020, // Allows for the parsing of modern ECMAScript features - "sourceType": "module" // Allows for the use of imports - }, - "ignorePatterns": ["**/out/*.js", "**/protos-js/"], - "extends": [ - "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin - "prettier", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - "rules": { - "@typescript-eslint/ban-ts-comment": "off" - // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs - // e.g. "@typescript-eslint/explicit-function-return-type": "off", - } -} diff --git a/weaver/samples/fabric/fabric-cli/.prettierrc b/weaver/samples/fabric/fabric-cli/.prettierrc deleted file mode 100644 index b0b784694f..0000000000 --- a/weaver/samples/fabric/fabric-cli/.prettierrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "semi": true, - "trailingComma": "all", - "singleQuote": true, - "printWidth": 120, - "tabWidth": 4 - } - \ No newline at end of file diff --git a/weaver/samples/fabric/fabric-cli/__tests__/cli-integration.test.ts b/weaver/samples/fabric/fabric-cli/__tests__/cli-integration.test.ts index 27e910119f..65d25457bf 100644 --- a/weaver/samples/fabric/fabric-cli/__tests__/cli-integration.test.ts +++ b/weaver/samples/fabric/fabric-cli/__tests__/cli-integration.test.ts @@ -4,32 +4,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { system, filesystem } from 'gluegun' +import { system, filesystem } from "gluegun"; -const src = filesystem.path(__dirname, '..') +const src = filesystem.path(__dirname, ".."); -const cli = async cmd => - system.run('node ' + filesystem.path(src, 'bin', 'fabric-cli') + ` ${cmd}`) +const cli = async (cmd) => + system.run("node " + filesystem.path(src, "bin", "fabric-cli") + ` ${cmd}`); -test('outputs version', async () => { - const output = await cli('--version') - expect(output).toContain('0.0.1') -}) +test("outputs version", async () => { + const output = await cli("--version"); + expect(output).toContain("0.0.1"); +}); -test('outputs help', async () => { - const output = await cli('--help') - expect(output).toContain('0.0.1') -}) +test("outputs help", async () => { + const output = await cli("--help"); + expect(output).toContain("0.0.1"); +}); -test('generates file', async () => { - const output = await cli('generate foo') +test("generates file", async () => { + const output = await cli("generate foo"); - expect(output).toContain('Generated file at models/foo-model.ts') - const foomodel = filesystem.read('models/foo-model.ts') + expect(output).toContain("Generated file at models/foo-model.ts"); + const foomodel = filesystem.read("models/foo-model.ts"); - expect(foomodel).toContain(`module.exports = {`) - expect(foomodel).toContain(`name: 'foo'`) + expect(foomodel).toContain(`module.exports = {`); + expect(foomodel).toContain(`name: 'foo'`); // cleanup artifact - filesystem.remove('models') -}) + filesystem.remove("models"); +}); diff --git a/weaver/samples/fabric/fabric-cli/package-local.json b/weaver/samples/fabric/fabric-cli/package-local.json index 5f6b509fce..d3423e5478 100644 --- a/weaver/samples/fabric/fabric-cli/package-local.json +++ b/weaver/samples/fabric/fabric-cli/package-local.json @@ -25,16 +25,11 @@ "copy-data": "if [ -e ./src/data ]; then cp -a ./src/data ./build/; fi", "copy-templates": "if [ -e ./src/templates ]; then cp -a ./src/templates ./build/; fi", "coverage": "jest --coverage", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "prepublishOnly": "yarn build", "snapupdate": "jest --updateSnapshot", "test": "jest", "watch": "jest --watch" }, - "prettier": { - "semi": false, - "singleQuote": true - }, "jest": { "preset": "ts-jest", "testEnvironment": "node" @@ -65,15 +60,9 @@ "@types/express": "4.17.19", "@types/jest": "29.5.3", "@types/node": "12.20.55", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", - "eslint": "7.32.0", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-prettier": "3.4.1", "google-protobuf": "3.21.2", "jest": "29.6.2", "pkg": "4.5.1", - "prettier": "1.19.1", "protobufjs": "7.2.5", "ts-jest": "29.1.1", "ts-node": "10.9.1", diff --git a/weaver/samples/fabric/fabric-cli/package.json b/weaver/samples/fabric/fabric-cli/package.json index 0b8d5dcfdf..fbc892a680 100644 --- a/weaver/samples/fabric/fabric-cli/package.json +++ b/weaver/samples/fabric/fabric-cli/package.json @@ -25,16 +25,11 @@ "copy-data": "if [ -e ./src/data ]; then cp -a ./src/data ./build/; fi", "copy-templates": "if [ -e ./src/templates ]; then cp -a ./src/templates ./build/; fi", "coverage": "jest --coverage", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "prepublishOnly": "yarn build", "snapupdate": "jest --updateSnapshot", "test": "jest", "watch": "jest --watch" }, - "prettier": { - "semi": false, - "singleQuote": true - }, "jest": { "preset": "ts-jest", "testEnvironment": "node" @@ -65,15 +60,9 @@ "@types/express": "4.17.19", "@types/jest": "29.5.3", "@types/node": "12.20.55", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", - "eslint": "7.32.0", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-prettier": "5.0.0", "google-protobuf": "3.21.2", "jest": "29.6.2", "pkg": "4.5.1", - "prettier": "1.19.1", "protobufjs": "7.2.5", "ts-jest": "29.1.1", "ts-node": "10.9.1", diff --git a/weaver/samples/fabric/fabric-cli/src/cli.ts b/weaver/samples/fabric/fabric-cli/src/cli.ts index 9dc268893d..77fb26916e 100644 --- a/weaver/samples/fabric/fabric-cli/src/cli.ts +++ b/weaver/samples/fabric/fabric-cli/src/cli.ts @@ -4,59 +4,59 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { build } from 'gluegun/build' -import { customHelp } from './helpers/helpers' -import * as path from 'path' -import * as dotenv from 'dotenv' -import * as fs from 'fs' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { build } from "gluegun/build"; +import { customHelp } from "./helpers/helpers"; +import * as path from "path"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); declare global { // eslint-disable-next-line namespace NodeJS { interface Global { - __DEFAULT_MSPID__: string - __DEFAULT_MSPID_ORG2__: string + __DEFAULT_MSPID__: string; + __DEFAULT_MSPID_ORG2__: string; } } } -global.__DEFAULT_MSPID__ = process.env.DEFAULT_MSPID || 'Org1MSP' -global.__DEFAULT_MSPID_ORG2__ = process.env.DEFAULT_MSPID_ORG2 || 'Org2MSP' +global.__DEFAULT_MSPID__ = process.env.DEFAULT_MSPID || "Org1MSP"; +global.__DEFAULT_MSPID_ORG2__ = process.env.DEFAULT_MSPID_ORG2 || "Org2MSP"; /** * Create the cli and kick it off */ async function run(argv) { // create a CLI runtime const cli = build() - .exclude(['semver', 'prompt', 'http', 'template', 'patching', 'strings']) - .brand('fabric-cli') + .exclude(["semver", "prompt", "http", "template", "patching", "strings"]) + .brand("fabric-cli") .src(__dirname) - .plugins('./node_modules', { matching: 'fabric-cli-*', hidden: true }) + .plugins("./node_modules", { matching: "fabric-cli-*", hidden: true }) .help(customHelp) .version() // provides default for version, v, --version, -v .defaultCommand(customHelp) - .create() + .create(); // and run it - const toolbox = await cli.run(argv) - checkConfig() + const toolbox = await cli.run(argv); + checkConfig(); // send it back (for testing, mostly) - return toolbox + return toolbox; } const checkConfig = () => { const configPath = process.env.CONFIG_PATH ? path.join(process.env.CONFIG_PATH) - : path.join(__dirname, '../config.json') + : path.join(__dirname, "../config.json"); try { - const configJSON = JSON.parse(fs.readFileSync(configPath).toString()) + const configJSON = JSON.parse(fs.readFileSync(configPath).toString()); if (Object.keys(configJSON).length === 0) { console.error( - 'ERROR: config.json is not properly configured, no network configurations available. Update configuration file or use `fabric-cli config set-file ` to update it.' - ) + "ERROR: config.json is not properly configured, no network configurations available. Update configuration file or use `fabric-cli config set-file ` to update it.", + ); } } catch (e) { console.error( - 'ERROR: config.json is not properly configured. Update configuration file or use `fabric-cli config set-file ` to update it.' - ) + "ERROR: config.json is not properly configured. Update configuration file or use `fabric-cli config set-file ` to update it.", + ); } -} -module.exports = { run } +}; +module.exports = { run }; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset-helper.ts index 7cea25bc2c..b0cdb93550 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset-helper.ts @@ -4,21 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helpers/helpers"; const command: GluegunCommand = { - name: 'asset', - alias: ['a'], - description: 'Asset Exchange Or Transfer', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'fabric-cli asset', '', [], command, [ - 'asset' - ]) - return - } -} + name: "asset", + alias: ["a"], + description: "Asset Exchange Or Transfer", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "fabric-cli asset", "", [], command, ["asset"]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-all.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-all.ts index d7e5dcbcbf..420abf6b32 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-all.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-all.ts @@ -4,272 +4,319 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper, invoke } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { commandHelp, getNetworkConfig, handlePromise } from '../../helpers/helpers' -import { AssetManager, HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric' +import { GluegunCommand } from "gluegun"; +import { fabricHelper, invoke } from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../helpers/helpers"; +import { + AssetManager, + HashFunctions, +} from "@hyperledger/cacti-weaver-sdk-fabric"; -var crypto = require('crypto'); +const crypto = require("crypto"); const command: GluegunCommand = { - name: 'exchange-all', - alias: ['-eall'], - description: 'Asset Exchange All steps.', - run: async toolbox => { + name: "exchange-all", + alias: ["-eall"], + description: "Asset Exchange All steps.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli asset exchange --network1=network1 --network2=network2 --secret=secrettext --timeout-duration=100 bob:Type1:a04:alice:token1:100`, - 'fabric-cli asset exchange --network1= --network2= --secret= --timeout-epoch= --timeout-duration= ', + "fabric-cli asset exchange --network1= --network2= --secret= --timeout-epoch= --timeout-duration= ", [ { - name: '--network1', - description: - 'Asset network for command. ' + name: "--network1", + description: "Asset network for command. ", }, { - name: '--network2', + name: "--network2", description: - 'Fungible Asset network for command. ' + "Fungible Asset network for command. ", }, { - name: '--secret', - description: - 'secret text to be used Asset owner to hash lock' + name: "--secret", + description: "secret text to be used Asset owner to hash lock", }, { - name: '--timeout-epoch', + name: "--timeout-epoch", description: - 'Timeout in epoch in seconds. Use only one of the timeout options.' + "Timeout in epoch in seconds. Use only one of the timeout options.", }, { - name: '--timeout-duration', + name: "--timeout-duration", description: - 'Timeout duration in seconds. Use only one of the timeout options.' + "Timeout duration in seconds. Use only one of the timeout options.", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['asset', 'exchange-all'] - ) - return + ["asset", "exchange-all"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } if (array.length < 1) { - print.error('Not enough arguments supplied') - return + print.error("Not enough arguments supplied"); + return; } - if (!options['network1'] || !options['network2']) - { - print.error('--network1 and --network2 both needs to specified') - return + if (!options["network1"] || !options["network2"]) { + print.error("--network1 and --network2 both needs to specified"); + return; } // Hash - let hash = new HashFunctions.SHA256() - - if (options['secret']) - { - hash.setPreimage(options['secret']) + const hash = new HashFunctions.SHA256(); + + if (options["secret"]) { + hash.setPreimage(options["secret"]); } // Timeout - var timeout=0, timeout2=0; - const currTime = Math.floor(Date.now()/1000); - if (options['timeout-epoch']) { - let duration = options['timeout-epoch'] - currTime - timeout = options['timeout-epoch'] - timeout2 = options['timeout-epoch'] + duration - } - else if (options['timeout-duration']) { - timeout=currTime + options['timeout-duration'] - timeout2=currTime + 2 * options['timeout-duration'] + let timeout = 0, + timeout2 = 0; + const currTime = Math.floor(Date.now() / 1000); + if (options["timeout-epoch"]) { + const duration = options["timeout-epoch"] - currTime; + timeout = options["timeout-epoch"]; + timeout2 = options["timeout-epoch"] + duration; + } else if (options["timeout-duration"]) { + timeout = currTime + options["timeout-duration"]; + timeout2 = currTime + 2 * options["timeout-duration"]; } // Read params - const params = array[0].split(':') - const user1 = params[0] - const assetType = params[1] - const assetId = params[2] - const user2 = params[3] - const fungibleAssetType = params[4] - const fungibleAssetAmt = parseInt(params[5]) + const params = array[0].split(":"); + const user1 = params[0]; + const assetType = params[1]; + const assetId = params[2]; + const user2 = params[3]; + const fungibleAssetType = params[4]; + const fungibleAssetAmt = parseInt(params[5]); // For debugging purpose // console.log(secret, hash_secret, timeout) // console.log(user1, assetType, assetId) // console.log(user2, fungibleAssetType, fungibleAssetAmt) - const net1Config = getNetworkConfig(options['network1']) - const net2Config = getNetworkConfig(options['network2']) - if (!net1Config.connProfilePath || !net1Config.channelName || !net1Config.chaincode) { + const net1Config = getNetworkConfig(options["network1"]); + const net2Config = getNetworkConfig(options["network2"]); + if ( + !net1Config.connProfilePath || + !net1Config.channelName || + !net1Config.chaincode + ) { print.error( - `Please use a valid --network1. No valid environment found for ${options['network1']} ` - ) - return + `Please use a valid --network1. No valid environment found for ${options["network1"]} `, + ); + return; } - if (!net2Config.connProfilePath || !net2Config.channelName || !net2Config.chaincode) { + if ( + !net2Config.connProfilePath || + !net2Config.channelName || + !net2Config.chaincode + ) { print.error( - `Please use a valid --network2. No valid environment found for ${options['network2']} ` - ) - return + `Please use a valid --network2. No valid environment found for ${options["network2"]} `, + ); + return; } const network1U1 = await fabricHelper({ channel: net1Config.channelName, contractName: net1Config.chaincode, connProfilePath: net1Config.connProfilePath, - networkName: options['network1'], + networkName: options["network1"], mspId: net1Config.mspId, - userString: user1 - }) + userString: user1, + }); const network1U2 = await fabricHelper({ channel: net1Config.channelName, contractName: net1Config.chaincode, connProfilePath: net1Config.connProfilePath, - networkName: options['network1'], + networkName: options["network1"], mspId: net1Config.mspId, - userString: user2 - }) + userString: user2, + }); const network2U1 = await fabricHelper({ channel: net2Config.channelName, contractName: net2Config.chaincode, connProfilePath: net2Config.connProfilePath, - networkName: options['network2'], + networkName: options["network2"], mspId: net2Config.mspId, - userString: user1 - }) + userString: user1, + }); const network2U2 = await fabricHelper({ channel: net2Config.channelName, contractName: net2Config.chaincode, connProfilePath: net2Config.connProfilePath, - networkName: options['network2'], + networkName: options["network2"], mspId: net2Config.mspId, - userString: user2 - }) - + userString: user2, + }); - const user1IdN1 = await network1U1.wallet.get(user1) - const user1CertN1 = Buffer.from((user1IdN1).credentials.certificate).toString('base64') - const user1IdN2 = await network2U1.wallet.get(user1) - const user1CertN2 = Buffer.from((user1IdN2).credentials.certificate).toString('base64') + const user1IdN1 = await network1U1.wallet.get(user1); + const user1CertN1 = Buffer.from(user1IdN1.credentials.certificate).toString( + "base64", + ); + const user1IdN2 = await network2U1.wallet.get(user1); + const user1CertN2 = Buffer.from(user1IdN2.credentials.certificate).toString( + "base64", + ); - const user2IdN1 = await network1U2.wallet.get(user2) - const user2CertN1 = Buffer.from((user2IdN1).credentials.certificate).toString('base64') - const user2IdN2 = await network2U2.wallet.get(user2) - const user2CertN2 = Buffer.from((user2IdN2).credentials.certificate).toString('base64') + const user2IdN1 = await network1U2.wallet.get(user2); + const user2CertN1 = Buffer.from(user2IdN1.credentials.certificate).toString( + "base64", + ); + const user2IdN2 = await network2U2.wallet.get(user2); + const user2CertN2 = Buffer.from(user2IdN2.credentials.certificate).toString( + "base64", + ); // console.log(user1CertN2) // console.log(user2CertN1) - const spinner = print.spin(`Asset Exchange:\n`) + const spinner = print.spin(`Asset Exchange:\n`); - var res - var contractId + let res; + let contractId; try { - spinner.info(`Trying Asset Lock: ${assetType}, ${assetId}`) - res = await AssetManager.createHTLC(network1U1.contract, - assetType, - assetId, - user2CertN1, - hash, - timeout2, - null) + spinner.info(`Trying Asset Lock: ${assetType}, ${assetId}`); + res = await AssetManager.createHTLC( + network1U1.contract, + assetType, + assetId, + user2CertN1, + hash, + timeout2, + null, + ); if (!res.result) { - throw new Error() + throw new Error(); } - spinner.info(`Asset Locked: ${res.result}`) - } catch(error) { - print.error(`Could not Lock Asset in ${options['network1']}`) - spinner.fail(`Error`) - process.exit() + spinner.info(`Asset Locked: ${res.result}`); + } catch (error) { + print.error(`Could not Lock Asset in ${options["network1"]}`); + spinner.fail(`Error`); + process.exit(); } try { - spinner.info(`Trying Fungible Asset Lock: ${fungibleAssetType}, ${fungibleAssetAmt}`) - res = await AssetManager.createFungibleHTLC(network2U2.contract, - fungibleAssetType, - fungibleAssetAmt, - user1CertN2, - hash, - timeout, - null) + spinner.info( + `Trying Fungible Asset Lock: ${fungibleAssetType}, ${fungibleAssetAmt}`, + ); + res = await AssetManager.createFungibleHTLC( + network2U2.contract, + fungibleAssetType, + fungibleAssetAmt, + user1CertN2, + hash, + timeout, + null, + ); if (!res.result) { - throw new Error() + throw new Error(); } - contractId = res.result - spinner.info(`Fungible Asset Locked: ${res.result}`) - } catch(error) { - print.error(`Could not Lock Fungible Asset in ${options['network2']}`) - res = await AssetManager.reclaimAssetInHTLC(network1U1.contract, assetType, assetId, user2CertN1); - spinner.fail(`Error`) - process.exit() + contractId = res.result; + spinner.info(`Fungible Asset Locked: ${res.result}`); + } catch (error) { + print.error(`Could not Lock Fungible Asset in ${options["network2"]}`); + res = await AssetManager.reclaimAssetInHTLC( + network1U1.contract, + assetType, + assetId, + user2CertN1, + ); + spinner.fail(`Error`); + process.exit(); } try { - spinner.info(`Trying Fungible Asset Claim: ${contractId}`) - res = await AssetManager.claimFungibleAssetInHTLC(network2U1.contract, - contractId, - hash) + spinner.info(`Trying Fungible Asset Claim: ${contractId}`); + res = await AssetManager.claimFungibleAssetInHTLC( + network2U1.contract, + contractId, + hash, + ); if (!res) { - throw new Error() + throw new Error(); } - spinner.info(`Fungible Asset Claimed: ${res}`) - } catch(error) { - print.error(`Could not claim fungible asset in ${options['network2']}`) - res = await AssetManager.reclaimFungibleAssetInHTLC(network2U2.contract, contractId); - res = await AssetManager.reclaimAssetInHTLC(network1U1.contract, assetType, assetId, user2CertN1); - spinner.fail(`Error`) - process.exit() + spinner.info(`Fungible Asset Claimed: ${res}`); + } catch (error) { + print.error(`Could not claim fungible asset in ${options["network2"]}`); + res = await AssetManager.reclaimFungibleAssetInHTLC( + network2U2.contract, + contractId, + ); + res = await AssetManager.reclaimAssetInHTLC( + network1U1.contract, + assetType, + assetId, + user2CertN1, + ); + spinner.fail(`Error`); + process.exit(); } - try { - spinner.info(`Trying Asset Claim: ${assetType} ${assetId}`) - res = await AssetManager.claimAssetInHTLC(network1U2.contract, - assetType, - assetId, - user1CertN1, - hash) + spinner.info(`Trying Asset Claim: ${assetType} ${assetId}`); + res = await AssetManager.claimAssetInHTLC( + network1U2.contract, + assetType, + assetId, + user1CertN1, + hash, + ); if (!res) { - throw new Error() + throw new Error(); } - spinner.info(`Asset Claimed: ${res}`) - } catch(error) { - print.error(`Could not claim asset in ${options['network1']}`) - res = await AssetManager.reclaimFungibleAssetInHTLC(network2U2.contract, contractId); - res = await AssetManager.reclaimAssetInHTLC(network1U1.contract, assetType, assetId, user2CertN1); - spinner.fail(`Error`) - process.exit() + spinner.info(`Asset Claimed: ${res}`); + } catch (error) { + print.error(`Could not claim asset in ${options["network1"]}`); + res = await AssetManager.reclaimFungibleAssetInHTLC( + network2U2.contract, + contractId, + ); + res = await AssetManager.reclaimAssetInHTLC( + network1U1.contract, + assetType, + assetId, + user2CertN1, + ); + spinner.fail(`Error`); + process.exit(); } - spinner.succeed('Asset Exchange Complete.') - - await network1U1.gateway.disconnect() - await network1U2.gateway.disconnect() - await network2U1.gateway.disconnect() - await network2U2.gateway.disconnect() + spinner.succeed("Asset Exchange Complete."); - console.log('Gateways disconnected.') - process.exit() - } -} + await network1U1.gateway.disconnect(); + await network1U2.gateway.disconnect(); + await network2U1.gateway.disconnect(); + await network2U2.gateway.disconnect(); + console.log("Gateways disconnected."); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-helper.ts index d48164f6b5..68379ab92d 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange-helper.ts @@ -4,22 +4,22 @@ * SPDX-License-Identifier: Apache-2.0 */ - import { GluegunCommand } from 'gluegun' - import { commandHelp } from '../../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'exchange', - alias: ['-e'], - description: 'Asset Exchange Step by Step.', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'fabric-cli asset exchange', '', [], command, [ - 'asset', 'exchange' - ]) - return - } -} + name: "exchange", + alias: ["-e"], + description: "Asset Exchange Step by Step.", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "fabric-cli asset exchange", "", [], command, [ + "asset", + "exchange", + ]); + return; + }, +}; - -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/claim.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/claim.ts index 9a8e9fd4d4..7b80bf93c0 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/claim.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/claim.ts @@ -4,192 +4,207 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper } from '../../../helpers/fabric-functions' -import logger from '../../../helpers/logger' -import { commandHelp, getNetworkConfig, handlePromise } from '../../../helpers/helpers' -import { AssetManager, HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric' +import { GluegunCommand } from "gluegun"; +import { fabricHelper } from "../../../helpers/fabric-functions"; +import logger from "../../../helpers/logger"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../../helpers/helpers"; +import { + AssetManager, + HashFunctions, +} from "@hyperledger/cacti-weaver-sdk-fabric"; const command: GluegunCommand = { - name: 'claim', - alias: ['-c'], - description: 'Asset Claim for HTLC', - run: async toolbox => { + name: "claim", + alias: ["-c"], + description: "Asset Claim for HTLC", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli asset exchange claim --target-network=network1 --secret=secrettext --recipient=alice --contract-id=abc01`, - 'fabric-cli asset exchange claim --fungible --target-network= --hash_fn= --secret= --recipient= --contract-id= --locker= --param=', + "fabric-cli asset exchange claim --fungible --target-network= --hash_fn= --secret= --recipient= --contract-id= --locker= --param=", [ { - name: '--fungible', - description: - 'Flag to indicate fungible asset or non-fungible.' + name: "--fungible", + description: "Flag to indicate fungible asset or non-fungible.", }, { - name: '--target-network', - description: - 'Target network for command. ' + name: "--target-network", + description: "Target network for command. ", }, { - name: '--hash_fn', + name: "--hash_fn", description: - 'hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)' + "hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)", }, { - name: '--secret', - description: - 'secret text to be used by Asset owner to hash lock' + name: "--secret", + description: "secret text to be used by Asset owner to hash lock", }, { - name: '--recipient', + name: "--recipient", description: - 'Recipient User Id: Must be already registered in target-network' + "Recipient User Id: Must be already registered in target-network", }, { - name: '--contract-id', - description: - 'Contract Id generated in Lock.' + name: "--contract-id", + description: "Contract Id generated in Lock.", }, { - name: '--locker', + name: "--locker", description: - 'Locker User Id: (Required only for non-fungible asset, if not passing contractID)' + "Locker User Id: (Required only for non-fungible asset, if not passing contractID)", }, { - name: '--param', + name: "--param", description: - 'Param: AssetType:AssetId used during lock (Required only for non-fungible asset, if not passing contractID)' + "Param: AssetType:AssetId used during lock (Required only for non-fungible asset, if not passing contractID)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['asset', 'exchange', 'claim'] - ) - return + ["asset", "exchange", "claim"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['target-network']) - { - print.error('--target-network needs to specified') - return + if (!options["target-network"]) { + print.error("--target-network needs to specified"); + return; } - if (!options['recipient']) - { - print.error('Recipient needs to be specified') - return + if (!options["recipient"]) { + print.error("Recipient needs to be specified"); + return; } - if (options['fungible'] && !options['contract-id']) { - print.error('Required contractId for fungible assets') - return + if (options["fungible"] && !options["contract-id"]) { + print.error("Required contractId for fungible assets"); + return; } - if (!options['contract-id'] && (!options['param'] || options['param'].split(':').length!=2 || !options['locker'])) { - print.error(`Required either --contract-id or both locker userid in --locker, and asset type:id in --param for non-fungible assets`) - return + if ( + !options["contract-id"] && + (!options["param"] || + options["param"].split(":").length != 2 || + !options["locker"]) + ) { + print.error( + `Required either --contract-id or both locker userid in --locker, and asset type:id in --param for non-fungible assets`, + ); + return; } - if (!options['secret']) { - print.error(`Required hash preimage in --secret`) - return + if (!options["secret"]) { + print.error(`Required hash preimage in --secret`); + return; } // Hash - let hash: HashFunctions.Hash - if(options['hash_fn'] == 'SHA512') { - hash = new HashFunctions.SHA512() + let hash: HashFunctions.Hash; + if (options["hash_fn"] == "SHA512") { + hash = new HashFunctions.SHA512(); } else { - hash = new HashFunctions.SHA256() + hash = new HashFunctions.SHA256(); } - hash.setPreimage(options['secret']) - - let contractId: string = null, params - if (options['contract-id']) { - contractId = options['contract-id'] - } - else { - params = options['param'].split(':') + hash.setPreimage(options["secret"]); + + let contractId: string = null, + params; + if (options["contract-id"]) { + contractId = options["contract-id"]; + } else { + params = options["param"].split(":"); } - const netConfig = getNetworkConfig(options['target-network']) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + const netConfig = getNetworkConfig(options["target-network"]); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --target-network. No valid environment found for ${options['target-network']} ` - ) - return + `Please use a valid --target-network. No valid environment found for ${options["target-network"]} `, + ); + return; } const network = await fabricHelper({ channel: netConfig.channelName, contractName: netConfig.chaincode, connProfilePath: netConfig.connProfilePath, - networkName: options['target-network'], + networkName: options["target-network"], mspId: netConfig.mspId, - userString: options['recipient'] - }) - - var funcToCall = AssetManager.claimAssetInHTLCusingContractId - var asset = 'Asset' - - if (options['fungible']) { - funcToCall = AssetManager.claimFungibleAssetInHTLC - asset = 'Fungible Asset' + userString: options["recipient"], + }); + + let funcToCall = AssetManager.claimAssetInHTLCusingContractId; + let asset = "Asset"; + + if (options["fungible"]) { + funcToCall = AssetManager.claimFungibleAssetInHTLC; + asset = "Fungible Asset"; } - const spinner = print.spin(`Asset Exchange: Claim ${asset}:\n`) + const spinner = print.spin(`Asset Exchange: Claim ${asset}:\n`); - if (options['contract-id']) { - try { - spinner.info(`Trying ${asset} Claim with Contract ID: ${contractId}`) - const res = await funcToCall(network.contract, - contractId, - hash) - if (!res) { - throw new Error() - } - spinner.info(`${asset} Claimed: ${res}`) - spinner.succeed('Asset Exchange: Claim Complete.') - } catch(error) { - print.error(`Could not claim ${asset} in ${options['target-network']}`) - spinner.fail(`Error`) + if (options["contract-id"]) { + try { + spinner.info(`Trying ${asset} Claim with Contract ID: ${contractId}`); + const res = await funcToCall(network.contract, contractId, hash); + if (!res) { + throw new Error(); } + spinner.info(`${asset} Claimed: ${res}`); + spinner.succeed("Asset Exchange: Claim Complete."); + } catch (error) { + print.error(`Could not claim ${asset} in ${options["target-network"]}`); + spinner.fail(`Error`); + } } else { - try { - const lockerId = await network.wallet.get(options['locker']) - const lockerCert = Buffer.from((lockerId).credentials.certificate).toString('base64') - spinner.info(`Trying ${asset} Claim with params: ${params[0]}, ${params[1]} locked by ${options.locker} for ${options.recipient}`) - const res = await AssetManager.claimAssetInHTLC(network.contract, - params[0], - params[1], - lockerCert, - hash) - if (!res) { - throw new Error() - } - spinner.info(`${asset} Claimed: ${res}`) - spinner.succeed('Asset Exchange: Claim Complete.') - } catch(error) { - print.error(`Could not claim ${asset} in ${options['target-network']}`) - spinner.fail(`Error`) + try { + const lockerId = await network.wallet.get(options["locker"]); + const lockerCert = Buffer.from( + lockerId.credentials.certificate, + ).toString("base64"); + spinner.info( + `Trying ${asset} Claim with params: ${params[0]}, ${params[1]} locked by ${options.locker} for ${options.recipient}`, + ); + const res = await AssetManager.claimAssetInHTLC( + network.contract, + params[0], + params[1], + lockerCert, + hash, + ); + if (!res) { + throw new Error(); } + spinner.info(`${asset} Claimed: ${res}`); + spinner.succeed("Asset Exchange: Claim Complete."); + } catch (error) { + print.error(`Could not claim ${asset} in ${options["target-network"]}`); + spinner.fail(`Error`); + } } - - await network.gateway.disconnect() - console.log('Gateways disconnected.') + await network.gateway.disconnect(); - process.exit() - } -} + console.log("Gateways disconnected."); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/is-locked.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/is-locked.ts index 50e49b6374..e3030e3d1b 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/is-locked.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/is-locked.ts @@ -4,173 +4,194 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper } from '../../../helpers/fabric-functions' -import logger from '../../../helpers/logger' -import { commandHelp, getNetworkConfig, handlePromise } from '../../../helpers/helpers' -import { AssetManager } from '@hyperledger/cacti-weaver-sdk-fabric' +import { GluegunCommand } from "gluegun"; +import { fabricHelper } from "../../../helpers/fabric-functions"; +import logger from "../../../helpers/logger"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../../helpers/helpers"; +import { AssetManager } from "@hyperledger/cacti-weaver-sdk-fabric"; const command: GluegunCommand = { - name: 'is-locked', - alias: ['-il'], - description: 'Asset Is Locked Query for HTLC', - run: async toolbox => { + name: "is-locked", + alias: ["-il"], + description: "Asset Is Locked Query for HTLC", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli asset exchange is-locked --target-network=network1 --locker=alice --contract-id=abc01`, - 'fabric-cli asset exchange is-locked --fungible --target-network= --locker= --contract-id= --recipient= --param=', + "fabric-cli asset exchange is-locked --fungible --target-network= --locker= --contract-id= --recipient= --param=", [ { - name: '--fungible', - description: - 'Flag to indicate fungible asset or non-fungible.' + name: "--fungible", + description: "Flag to indicate fungible asset or non-fungible.", }, { - name: '--target-network', - description: - 'Target network for command. ' + name: "--target-network", + description: "Target network for command. ", }, { - name: '--secret', - description: - 'secret text to be used by Asset owner to hash lock.' + name: "--secret", + description: "secret text to be used by Asset owner to hash lock.", }, { - name: '--locker', + name: "--locker", description: - 'Locker User Id: Must be already registered in target-network' + "Locker User Id: Must be already registered in target-network", }, { - name: '--contract-id', - description: - 'Contract Id generated in Lock.' + name: "--contract-id", + description: "Contract Id generated in Lock.", }, { - name: '--recipient', + name: "--recipient", description: - 'Recipient User Id: (Required only for non-fungible asset, if not passing contractID)' + "Recipient User Id: (Required only for non-fungible asset, if not passing contractID)", }, { - name: '--param', + name: "--param", description: - 'Param: AssetType:AssetId used during lock (Required only for non-fungible asset, if not passing contractID)' + "Param: AssetType:AssetId used during lock (Required only for non-fungible asset, if not passing contractID)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['asset', 'exchange', 'is-locked'] - ) - return - } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + ["asset", "exchange", "is-locked"], + ); + return; } - if (!options['target-network']) - { - print.error('--target-network needs to specified') - return + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['locker']) - { - print.error('Locker needs to be specified') - return + if (!options["target-network"]) { + print.error("--target-network needs to specified"); + return; } - if (options['fungible'] && !options['contract-id']) { - print.error('Required contractId for fungible assets') - return + if (!options["locker"]) { + print.error("Locker needs to be specified"); + return; } - if (!options['contract-id'] && (!options['param'] || options['param'].split(':').length!=2 || !options['recipient'])) { - print.error(`Required either --contract-id or both recipient userid in --recipient, and asset type:id in --param for non-fungible assets`) - return + if (options["fungible"] && !options["contract-id"]) { + print.error("Required contractId for fungible assets"); + return; } - - let contractId: string = null, params - if (options['contract-id']) { - contractId = options['contract-id'] + if ( + !options["contract-id"] && + (!options["param"] || + options["param"].split(":").length != 2 || + !options["recipient"]) + ) { + print.error( + `Required either --contract-id or both recipient userid in --recipient, and asset type:id in --param for non-fungible assets`, + ); + return; } - else { - params = options['param'].split(':') + + let contractId: string = null, + params; + if (options["contract-id"]) { + contractId = options["contract-id"]; + } else { + params = options["param"].split(":"); } - const netConfig = getNetworkConfig(options['target-network']) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + const netConfig = getNetworkConfig(options["target-network"]); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --target-network. No valid environment found for ${options['target-network']} ` - ) - return + `Please use a valid --target-network. No valid environment found for ${options["target-network"]} `, + ); + return; } const network = await fabricHelper({ channel: netConfig.channelName, contractName: netConfig.chaincode, connProfilePath: netConfig.connProfilePath, - networkName: options['target-network'], + networkName: options["target-network"], mspId: netConfig.mspId, - userString: options['locker'] - }) - - var funcToCall = AssetManager.isAssetLockedInHTLCqueryUsingContractId - var asset = 'Asset' - - if (options['fungible']) { - funcToCall = AssetManager.isFungibleAssetLockedInHTLC - asset = 'Fungible Asset' + userString: options["locker"], + }); + + let funcToCall = AssetManager.isAssetLockedInHTLCqueryUsingContractId; + let asset = "Asset"; + + if (options["fungible"]) { + funcToCall = AssetManager.isFungibleAssetLockedInHTLC; + asset = "Fungible Asset"; } - const spinner = print.spin(`Asset Exchange: Query ${asset} Is Locked:\n`) + const spinner = print.spin(`Asset Exchange: Query ${asset} Is Locked:\n`); - if (options['contract-id']) { - try { - spinner.info(`Querying ${asset} Is Locked with ContractId: ${contractId}`) - const res = await funcToCall(network.contract, - contractId) - if (!res) { - throw new Error() - } - spinner.info(`${asset} Is Locked Response: ${res}`) - spinner.succeed('Asset Exchange: Query Complete.') - } catch(error) { - print.error(`Could not query ${asset} is-locked in ${options['target-network']}`) - spinner.fail(`Error`) + if (options["contract-id"]) { + try { + spinner.info( + `Querying ${asset} Is Locked with ContractId: ${contractId}`, + ); + const res = await funcToCall(network.contract, contractId); + if (!res) { + throw new Error(); } + spinner.info(`${asset} Is Locked Response: ${res}`); + spinner.succeed("Asset Exchange: Query Complete."); + } catch (error) { + print.error( + `Could not query ${asset} is-locked in ${options["target-network"]}`, + ); + spinner.fail(`Error`); + } } else { - try { - const lockerId = await network.wallet.get(options['locker']) - const lockerCert = Buffer.from((lockerId).credentials.certificate).toString('base64') - const recipientId = await network.wallet.get(options['recipient']) - const recipientCert = Buffer.from((recipientId).credentials.certificate).toString('base64') - spinner.info(`Querying ${asset} Is Locked with params: ${params[0]}, ${params[1]} locked by ${options.locker} for ${options.recipient}`) - const res = await AssetManager.isAssetLockedInHTLC(network.contract, - params[0], - params[1], - recipientCert, - lockerCert) - spinner.info(`${asset} Is Locked Response: ${res}`) - spinner.succeed('Asset Exchange: Query Complete.') - } catch(error) { - print.error(`Could not query ${asset} is-locked in ${options['target-network']}, error: ${error}`) - spinner.fail(`Error`) - } + try { + const lockerId = await network.wallet.get(options["locker"]); + const lockerCert = Buffer.from( + lockerId.credentials.certificate, + ).toString("base64"); + const recipientId = await network.wallet.get(options["recipient"]); + const recipientCert = Buffer.from( + recipientId.credentials.certificate, + ).toString("base64"); + spinner.info( + `Querying ${asset} Is Locked with params: ${params[0]}, ${params[1]} locked by ${options.locker} for ${options.recipient}`, + ); + const res = await AssetManager.isAssetLockedInHTLC( + network.contract, + params[0], + params[1], + recipientCert, + lockerCert, + ); + spinner.info(`${asset} Is Locked Response: ${res}`); + spinner.succeed("Asset Exchange: Query Complete."); + } catch (error) { + print.error( + `Could not query ${asset} is-locked in ${options["target-network"]}, error: ${error}`, + ); + spinner.fail(`Error`); + } } - - await network.gateway.disconnect() - console.log('Gateways disconnected.') + await network.gateway.disconnect(); - process.exit() - } -} + console.log("Gateways disconnected."); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/lock.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/lock.ts index d851fd99b9..e3cd53bf2b 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/lock.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/lock.ts @@ -4,204 +4,220 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper } from '../../../helpers/fabric-functions' -import logger from '../../../helpers/logger' -import { commandHelp, getNetworkConfig, handlePromise } from '../../../helpers/helpers' -import { AssetManager, HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric' +import { GluegunCommand } from "gluegun"; +import { fabricHelper } from "../../../helpers/fabric-functions"; +import logger from "../../../helpers/logger"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../../helpers/helpers"; +import { + AssetManager, + HashFunctions, +} from "@hyperledger/cacti-weaver-sdk-fabric"; const command: GluegunCommand = { - name: 'lock', - alias: ['-l'], - description: 'Asset Lock for HTLC.', - run: async toolbox => { + name: "lock", + alias: ["-l"], + description: "Asset Lock for HTLC.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli asset exchange lock --target-network=network1 --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout-duration=100 --locker=bob --recipient=alice --param=Type1:a04`, - 'fabric-cli asset exchange lock --fungible --target-network= --hash_fn= --hashBase64= --timeout-epoch= --timeout-duration= --locker= --recipient= --param=', + "fabric-cli asset exchange lock --fungible --target-network= --hash_fn= --hashBase64= --timeout-epoch= --timeout-duration= --locker= --recipient= --param=", [ { - name: '--fungible', - description: - 'Flag to indicate fungible asset or non-fungible.' + name: "--fungible", + description: "Flag to indicate fungible asset or non-fungible.", }, { - name: '--target-network', - description: - 'Target network for command. ' + name: "--target-network", + description: "Target network for command. ", }, { - name: '--hash_fn', + name: "--hash_fn", description: - 'hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)' + "hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)", }, { - name: '--hashBase64', + name: "--hashBase64", description: - 'Serialized Hash value in base64 to be used for HTLC. (use only one of secret or hash, do not use both options)' + "Serialized Hash value in base64 to be used for HTLC. (use only one of secret or hash, do not use both options)", }, { - name: '--timeout-epoch', + name: "--timeout-epoch", description: - 'Timeout in epoch in seconds. Use only one of the timeout options.' + "Timeout in epoch in seconds. Use only one of the timeout options.", }, { - name: '--timeout-duration', + name: "--timeout-duration", description: - 'Timeout duration in seconds. Use only one of the timeout options.' + "Timeout duration in seconds. Use only one of the timeout options.", }, { - name: '--locker', + name: "--locker", description: - 'Locker User Id: Must be already registered in target-network' + "Locker User Id: Must be already registered in target-network", }, { - name: '--recipient', + name: "--recipient", description: - 'Recipient User Id: Must be already registered in target-network' + "Recipient User Id: Must be already registered in target-network", }, { - name: '--param', + name: "--param", description: - 'Param: AssetType:AssetId for Non-Fungible Assets \nFungibleAssetType:NumUnits for Fungible Assets' + "Param: AssetType:AssetId for Non-Fungible Assets \nFungibleAssetType:NumUnits for Fungible Assets", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['asset', 'exchange', 'lock'] - ) - return + ["asset", "exchange", "lock"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['target-network']) - { - print.error('--target-network needs to specified') - return + if (!options["target-network"]) { + print.error("--target-network needs to specified"); + return; } - if (!options['locker'] || !options['recipient']) - { - print.error('Locker and Recipient both needs to be specified') - return + if (!options["locker"] || !options["recipient"]) { + print.error("Locker and Recipient both needs to be specified"); + return; } - if (!options['param'] || options['param'].split(':').length!=2) { - var param2Msg = 'id' - if(options['fungible']) { - param2Msg = 'quantity' + if (!options["param"] || options["param"].split(":").length != 2) { + let param2Msg = "id"; + if (options["fungible"]) { + param2Msg = "quantity"; } - print.error(`Required asset type and ${param2Msg} in --param separated by colon`) - return + print.error( + `Required asset type and ${param2Msg} in --param separated by colon`, + ); + return; } // Locker and Recipient - const locker = options['locker'] - const recipient = options['recipient'] + const locker = options["locker"]; + const recipient = options["recipient"]; // Hash - let hash: HashFunctions.Hash - if(options['hash_fn'] == 'SHA512') { - hash = new HashFunctions.SHA512() + let hash: HashFunctions.Hash; + if (options["hash_fn"] == "SHA512") { + hash = new HashFunctions.SHA512(); } else { - hash = new HashFunctions.SHA256() + hash = new HashFunctions.SHA256(); } - - if (options['hashBase64']) - { - hash.setSerializedHashBase64(options['hashBase64']) - } - else { - print.info(`No hash provided, using random preimage`) + + if (options["hashBase64"]) { + hash.setSerializedHashBase64(options["hashBase64"]); + } else { + print.info(`No hash provided, using random preimage`); } // Timeout - var timeout=0, timeout2=0; - const currTime = Math.floor(Date.now()/1000); - if (options['timeout-epoch']) { - let duration = options['timeout-epoch'] - currTime - timeout = options['timeout-epoch'] - timeout2 = options['timeout-epoch'] + duration - } - else if (options['timeout-duration']) { - timeout=currTime + options['timeout-duration'] - timeout2=currTime + 2 * options['timeout-duration'] + let timeout = 0, + timeout2 = 0; + const currTime = Math.floor(Date.now() / 1000); + if (options["timeout-epoch"]) { + const duration = options["timeout-epoch"] - currTime; + timeout = options["timeout-epoch"]; + timeout2 = options["timeout-epoch"] + duration; + } else if (options["timeout-duration"]) { + timeout = currTime + options["timeout-duration"]; + timeout2 = currTime + 2 * options["timeout-duration"]; } - const params = options['param'].split(':') + const params = options["param"].split(":"); - const netConfig = getNetworkConfig(options['target-network']) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + const netConfig = getNetworkConfig(options["target-network"]); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --target-network. No valid environment found for ${options['target-network']} ` - ) - return + `Please use a valid --target-network. No valid environment found for ${options["target-network"]} `, + ); + return; } const network = await fabricHelper({ channel: netConfig.channelName, contractName: netConfig.chaincode, connProfilePath: netConfig.connProfilePath, - networkName: options['target-network'], + networkName: options["target-network"], mspId: netConfig.mspId, - userString: locker - }) - - const lockerId = await network.wallet.get(locker) - const lockerCert = Buffer.from((lockerId).credentials.certificate).toString('base64') - - const recipientId = await network.wallet.get(recipient) - const recipientCert = Buffer.from((recipientId).credentials.certificate).toString('base64') - - var funcToCall, asset - - if (options['fungible']) { - funcToCall = AssetManager.createFungibleHTLC - asset = 'Fungible Asset' + userString: locker, + }); + + const lockerId = await network.wallet.get(locker); + const lockerCert = Buffer.from(lockerId.credentials.certificate).toString( + "base64", + ); + + const recipientId = await network.wallet.get(recipient); + const recipientCert = Buffer.from( + recipientId.credentials.certificate, + ).toString("base64"); + + let funcToCall, asset; + + if (options["fungible"]) { + funcToCall = AssetManager.createFungibleHTLC; + asset = "Fungible Asset"; } else { - funcToCall = AssetManager.createHTLC - asset = 'Asset' + funcToCall = AssetManager.createHTLC; + asset = "Asset"; } - const spinner = print.spin(`Asset Exchange: Lock ${asset}:\n`) + const spinner = print.spin(`Asset Exchange: Lock ${asset}:\n`); try { - spinner.info(`Trying ${asset} Lock: ${params[0]}, ${params[1]} by ${locker} for ${recipient}`) - const res = await funcToCall(network.contract, - params[0], - params[1], - recipientCert, - hash, - timeout, - null) - if (!res.result) { - throw new Error() - } - spinner.info(`${asset} Locked with Contract Id: ${res.result}, preimage: ${res.hash.getPreimage()}, hashvalue: ${res.hash.getSerializedHashBase64()}`) - spinner.succeed('Asset Exchange: Lock Complete.') - } catch(error) { - print.error(`Could not Lock ${asset} in ${options['target-network']}`) - spinner.fail(`Error`) + spinner.info( + `Trying ${asset} Lock: ${params[0]}, ${params[1]} by ${locker} for ${recipient}`, + ); + const res = await funcToCall( + network.contract, + params[0], + params[1], + recipientCert, + hash, + timeout, + null, + ); + if (!res.result) { + throw new Error(); + } + spinner.info( + `${asset} Locked with Contract Id: ${res.result}, preimage: ${res.hash.getPreimage()}, hashvalue: ${res.hash.getSerializedHashBase64()}`, + ); + spinner.succeed("Asset Exchange: Lock Complete."); + } catch (error) { + print.error(`Could not Lock ${asset} in ${options["target-network"]}`); + spinner.fail(`Error`); } // await new Promise(f => setTimeout(f, options['timeout-duration'] * 1000 + 3000)); - await network.gateway.disconnect() - console.log('Gateways disconnected.') - - process.exit() - } -} + await network.gateway.disconnect(); + console.log("Gateways disconnected."); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/unlock.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/unlock.ts index a7624ed74b..baffaeae10 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/unlock.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/exchange/unlock.ts @@ -4,168 +4,186 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper } from '../../../helpers/fabric-functions' -import logger from '../../../helpers/logger' -import { commandHelp, getNetworkConfig, handlePromise } from '../../../helpers/helpers' -import { AssetManager } from '@hyperledger/cacti-weaver-sdk-fabric' +import { GluegunCommand } from "gluegun"; +import { fabricHelper } from "../../../helpers/fabric-functions"; +import logger from "../../../helpers/logger"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../../helpers/helpers"; +import { AssetManager } from "@hyperledger/cacti-weaver-sdk-fabric"; const command: GluegunCommand = { - name: 'unlock', - alias: ['-u'], - description: 'Asset Unlock for HTLC', - run: async toolbox => { + name: "unlock", + alias: ["-u"], + description: "Asset Unlock for HTLC", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli asset exchange unlock --target-network=network1 --locker=alice --contract-id=abc01`, - 'fabric-cli asset exchange unlock --fungible --target-network= --locker= --contract-id= --recipient= --param=', + "fabric-cli asset exchange unlock --fungible --target-network= --locker= --contract-id= --recipient= --param=", [ { - name: '--fungible', - description: - 'Flag to indicate fungible asset or non-fungible.' + name: "--fungible", + description: "Flag to indicate fungible asset or non-fungible.", }, { - name: '--target-network', - description: - 'Target network for command. ' + name: "--target-network", + description: "Target network for command. ", }, { - name: '--locker', + name: "--locker", description: - 'Locker User Id: Must be already registered in target-network' + "Locker User Id: Must be already registered in target-network", }, { - name: '--contract-id', - description: - 'Contract Id generated in Lock.' + name: "--contract-id", + description: "Contract Id generated in Lock.", }, { - name: '--recipient', + name: "--recipient", description: - 'Recipient User Id: (Required only for non-fungible asset, if not passing contractID)' + "Recipient User Id: (Required only for non-fungible asset, if not passing contractID)", }, { - name: '--param', + name: "--param", description: - 'Param: AssetType:AssetId used during lock (Required only for non-fungible asset, if not passing contractID)' + "Param: AssetType:AssetId used during lock (Required only for non-fungible asset, if not passing contractID)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['asset', 'exchange', 'unlock'] - ) - return - } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + ["asset", "exchange", "unlock"], + ); + return; } - if (!options['target-network']) - { - print.error('--target-network needs to specified') - return + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['locker']) - { - print.error('Locker needs to be specified') - return + if (!options["target-network"]) { + print.error("--target-network needs to specified"); + return; } - if (options['fungible'] && !options['contract-id']) { - print.error('Required contractId for fungible assets') - return + if (!options["locker"]) { + print.error("Locker needs to be specified"); + return; } - if (!options['contract-id'] && (!options['param'] || options['param'].split(':').length!=2 || !options['recipient'])) { - print.error(`Required either --contract-id or both recipient userid in --recipient, and asset type:id in --param for non-fungible assets`) - return + if (options["fungible"] && !options["contract-id"]) { + print.error("Required contractId for fungible assets"); + return; } - - let contractId: string = null, params - if (options['contract-id']) { - contractId = options['contract-id'] + if ( + !options["contract-id"] && + (!options["param"] || + options["param"].split(":").length != 2 || + !options["recipient"]) + ) { + print.error( + `Required either --contract-id or both recipient userid in --recipient, and asset type:id in --param for non-fungible assets`, + ); + return; } - else { - params = options['param'].split(':') + + let contractId: string = null, + params; + if (options["contract-id"]) { + contractId = options["contract-id"]; + } else { + params = options["param"].split(":"); } - const netConfig = getNetworkConfig(options['target-network']) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + const netConfig = getNetworkConfig(options["target-network"]); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --target-network. No valid environment found for ${options['target-network']} ` - ) - return + `Please use a valid --target-network. No valid environment found for ${options["target-network"]} `, + ); + return; } const network = await fabricHelper({ channel: netConfig.channelName, contractName: netConfig.chaincode, connProfilePath: netConfig.connProfilePath, - networkName: options['target-network'], + networkName: options["target-network"], mspId: netConfig.mspId, - userString: options['locker'] - }) - - var funcToCall = AssetManager.reclaimAssetInHTLCusingContractId - var asset = 'Asset' - - if (options['fungible']) { - funcToCall = AssetManager.reclaimFungibleAssetInHTLC - asset = 'Fungible Asset' + userString: options["locker"], + }); + + let funcToCall = AssetManager.reclaimAssetInHTLCusingContractId; + let asset = "Asset"; + + if (options["fungible"]) { + funcToCall = AssetManager.reclaimFungibleAssetInHTLC; + asset = "Fungible Asset"; } - const spinner = print.spin(`Asset Exchange: Unlock ${asset}:\n`) + const spinner = print.spin(`Asset Exchange: Unlock ${asset}:\n`); - if (options['contract-id']) { - try { - spinner.info(`Trying ${asset} Unlock with Contract ID: ${contractId}`) - const res = await funcToCall(network.contract, - contractId) - if (!res) { - throw new Error() - } - spinner.info(`${asset} Unlocked: ${res}`) - spinner.succeed('Asset Exchange: Unlock Complete.') - } catch(error) { - print.error(`Could not unlock ${asset} in ${options['target-network']}`) - spinner.fail(`Error`) + if (options["contract-id"]) { + try { + spinner.info(`Trying ${asset} Unlock with Contract ID: ${contractId}`); + const res = await funcToCall(network.contract, contractId); + if (!res) { + throw new Error(); } + spinner.info(`${asset} Unlocked: ${res}`); + spinner.succeed("Asset Exchange: Unlock Complete."); + } catch (error) { + print.error( + `Could not unlock ${asset} in ${options["target-network"]}`, + ); + spinner.fail(`Error`); + } } else { - try { - const recipientId = await network.wallet.get(options['recipient']) - const recipientCert = Buffer.from((recipientId).credentials.certificate).toString('base64') - spinner.info(`Trying ${asset} Unlock with params: ${params[0]}, ${params[1]} locked by ${options.locker} for ${options.recipient}`) - const res = await AssetManager.reclaimAssetInHTLC(network.contract, - params[0], - params[1], - recipientCert) - if (!res) { - throw new Error() - } - spinner.info(`${asset} Unlocked: ${res}`) - spinner.succeed('Asset Exchange: Unlock Complete.') - } catch(error) { - print.error(`Could not unlock ${asset} in ${options['target-network']}`) - spinner.fail(`Error`) + try { + const recipientId = await network.wallet.get(options["recipient"]); + const recipientCert = Buffer.from( + recipientId.credentials.certificate, + ).toString("base64"); + spinner.info( + `Trying ${asset} Unlock with params: ${params[0]}, ${params[1]} locked by ${options.locker} for ${options.recipient}`, + ); + const res = await AssetManager.reclaimAssetInHTLC( + network.contract, + params[0], + params[1], + recipientCert, + ); + if (!res) { + throw new Error(); } + spinner.info(`${asset} Unlocked: ${res}`); + spinner.succeed("Asset Exchange: Unlock Complete."); + } catch (error) { + print.error( + `Could not unlock ${asset} in ${options["target-network"]}`, + ); + spinner.fail(`Error`); + } } - - await network.gateway.disconnect() - console.log('Gateways disconnected.') + await network.gateway.disconnect(); - process.exit() - } -} + console.log("Gateways disconnected."); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer-helper.ts index 5772d2246e..4a2fdd394b 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer-helper.ts @@ -4,21 +4,22 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'transfer', - alias: ['-t'], - description: 'Asset Transfer', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'fabric-cli asset transfer', '', [], command, [ - 'asset', 'transfer' - ]) - return - } -} + name: "transfer", + alias: ["-t"], + description: "Asset Transfer", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "fabric-cli asset transfer", "", [], command, [ + "asset", + "transfer", + ]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/claim.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/claim.ts index d06895435c..100f0d2ea8 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/claim.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/claim.ts @@ -4,231 +4,253 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import * as path from "path"; import { - commandHelp, - pledgeAsset, - getNetworkConfig, - getLocalAssetPledgeDetails, - getUserCertFromFile, - getChaincodeConfig, - handlePromise, - generateViewAddressFromRemoteConfig, - interopHelper -} from '../../../helpers/helpers' + commandHelp, + pledgeAsset, + getNetworkConfig, + getLocalAssetPledgeDetails, + getUserCertFromFile, + getChaincodeConfig, + handlePromise, + generateViewAddressFromRemoteConfig, + interopHelper, +} from "../../../helpers/helpers"; import { - fabricHelper, - getUserCertBase64 -} from '../../../helpers/fabric-functions' + fabricHelper, + getUserCertBase64, +} from "../../../helpers/fabric-functions"; -import logger from '../../../helpers/logger' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }) +import logger from "../../../helpers/logger"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../../.env") }); -const delay = ms => new Promise(res => setTimeout(res, ms)) +const delay = (ms) => new Promise((res) => setTimeout(res, ms)); const command: GluegunCommand = { - name: 'claim', - description: - 'Claims pledged asset in destination network', - run: async toolbox => { + name: "claim", + description: "Claims pledged asset in destination network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, 'fabric-cli asset transfer claim --source-network=network1 --dest-network=network2 --user=alice --type=bond --pledge-id="pledgeid" --param=bond01:a03\r\nfabric-cli asset transfer claim --source-network=network1 --dest-network=network2 --user=alice --type=token --param=token1:50', - 'fabric-cli asset transfer claim --source-network= --dest-network= --user= --type= --pledge-id= --param=:', + "fabric-cli asset transfer claim --source-network= --dest-network= --user= --type= --pledge-id= --param=:", [ { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--source-network', + name: "--source-network", description: - 'Network where the asset is currently present. ' + "Network where the asset is currently present. ", }, { - name: '--dest-network', + name: "--dest-network", description: - 'Network where the asset is currently present. ' + "Network where the asset is currently present. ", }, { - name: '--user', - description: - 'User (wallet) ID of the claimer' + name: "--user", + description: "User (wallet) ID of the claimer", }, { - name: '--owner', + name: "--owner", description: - 'Owner (User ID) of the Asset who pledged in source Network' + "Owner (User ID) of the Asset who pledged in source Network", }, { - name: '--type', - description: - 'Type of network ' + name: "--type", + description: "Type of network ", }, { - name: '--pledge-id', - description: - 'Pledge Id associated with asset transfer.' + name: "--pledge-id", + description: "Pledge Id associated with asset transfer.", }, { - name: '--param', + name: "--param", description: - 'Colon separated Asset Type and Asset ID or Asset Type and Num of Units.' + "Colon separated Asset Type and Asset ID or Asset Type and Num of Units.", }, { - name: '--relay-tls', - description: 'Flag indicating whether or not the relay is TLS-enabled.' + name: "--relay-tls", + description: + "Flag indicating whether or not the relay is TLS-enabled.", }, { - name: '--relay-tls-ca-files', - description: 'Colon-separated list of root CA certificate paths used to connect to the relay over TLS.' + name: "--relay-tls-ca-files", + description: + "Colon-separated list of root CA certificate paths used to connect to the relay over TLS.", }, { - name: '--e2e-confidentiality', - description: 'Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).' - } + name: "--e2e-confidentiality", + description: + "Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).", + }, ], command, - ['asset', 'transfer', 'claim'] - ) - return + ["asset", "transfer", "claim"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['source-network']) - { - print.error('--source-network needs to be specified') - return + if (!options["source-network"]) { + print.error("--source-network needs to be specified"); + return; } - if (!options['dest-network']) - { - print.error('--source-network needs to be specified') - return + if (!options["dest-network"]) { + print.error("--source-network needs to be specified"); + return; } - if (!options['user']) - { - print.error('--user needs to be specified') - return + if (!options["user"]) { + print.error("--user needs to be specified"); + return; } - if (!options['owner']) - { - print.error('--owner needs to be specified') - return + if (!options["owner"]) { + print.error("--owner needs to be specified"); + return; } - if (!options['type']) - { - print.error('--type of asset transfer needs to be specified in the format: \'asset_type.remote_network_type\'.' + - ' \'asset_type\' can be either \'bond\', \'token\' or \'house-token\'.' + - ' \'remote_network_type\' can be either \'fabric\', \'corda\' or \'besu\'.') - return + if (!options["type"]) { + print.error( + "--type of asset transfer needs to be specified in the format: 'asset_type.remote_network_type'." + + " 'asset_type' can be either 'bond', 'token' or 'house-token'." + + " 'remote_network_type' can be either 'fabric', 'corda' or 'besu'.", + ); + return; } - if (!options['param']) - { - print.error('--param needs to be specified') - return + if (!options["param"]) { + print.error("--param needs to be specified"); + return; } - - const params = options['param'].split(':') - const assetType = params[0] - const transferCategory = options['type'] - - if (transferCategory.includes('bond') && !params[1]) - { - print.error('assetId needs to be specified for "bond" type') - return + + const params = options["param"].split(":"); + const assetType = params[0]; + const transferCategory = options["type"]; + + if (transferCategory.includes("bond") && !params[1]) { + print.error('assetId needs to be specified for "bond" type'); + return; } - if (transferCategory.includes('token') && !params[1]) - { - print.error('num of units needs to be specified for "token" type') - return + if (transferCategory.includes("token") && !params[1]) { + print.error('num of units needs to be specified for "token" type'); + return; } - if (transferCategory.includes('token') && isNaN(parseInt(params[1]))) - { - print.error('num of units must be an integer for "token" type') - return + if (transferCategory.includes("token") && isNaN(parseInt(params[1]))) { + print.error('num of units must be an integer for "token" type'); + return; } - - const assetIdOrQuantity = (transferCategory.includes('token')) ? parseInt(params[1]) : params[1] - - const netConfig = getNetworkConfig(options['dest-network']) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + + const assetIdOrQuantity = transferCategory.includes("token") + ? parseInt(params[1]) + : params[1]; + + const netConfig = getNetworkConfig(options["dest-network"]); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --dest-network. No valid environment found for ${options['dest-network']} ` - ) - return + `Please use a valid --dest-network. No valid environment found for ${options["dest-network"]} `, + ); + return; } - + try { - const userCert = await getUserCertBase64(options['dest-network'], options['user']) - const { viewAddress, ownerCert } = await getClaimViewAddress(transferCategory, options['pledge-id'], - options['owner'], options['source-network'], userCert, options['dest-network'] - ) - - const applicationFunction = (transferCategory.includes('token')) ? 'ClaimRemoteTokenAsset' : 'ClaimRemoteAsset' - var { args, replaceIndices } = getChaincodeConfig(netConfig.chaincode, applicationFunction) - args[args.indexOf('')] = options['pledge-id'] - args[args.indexOf('')] = assetType - args[args.indexOf('')] = ownerCert - args[args.indexOf('network1')] = options['source-network'] - const assetIdOrQuantityIndex = (applicationFunction == 'ClaimRemoteTokenAsset') ? args.indexOf('') : args.indexOf('') - args[assetIdOrQuantityIndex] = `${assetIdOrQuantity}` - + const userCert = await getUserCertBase64( + options["dest-network"], + options["user"], + ); + const { viewAddress, ownerCert } = await getClaimViewAddress( + transferCategory, + options["pledge-id"], + options["owner"], + options["source-network"], + userCert, + options["dest-network"], + ); + + const applicationFunction = transferCategory.includes("token") + ? "ClaimRemoteTokenAsset" + : "ClaimRemoteAsset"; + const { args, replaceIndices } = getChaincodeConfig( + netConfig.chaincode, + applicationFunction, + ); + args[args.indexOf("")] = options["pledge-id"]; + args[args.indexOf("")] = assetType; + args[args.indexOf("")] = ownerCert; + args[args.indexOf("network1")] = options["source-network"]; + const assetIdOrQuantityIndex = + applicationFunction == "ClaimRemoteTokenAsset" + ? args.indexOf("") + : args.indexOf(""); + args[assetIdOrQuantityIndex] = `${assetIdOrQuantity}`; + await interopHelper( - options['dest-network'], + options["dest-network"], viewAddress, netConfig.chaincode, applicationFunction, args, replaceIndices, options, - print - ) - process.exit() + print, + ); + process.exit(); } catch (error) { - print.error(`Error Asset Transfer Claim: ${error}`) + print.error(`Error Asset Transfer Claim: ${error}`); } - } -} - + }, +}; -async function getClaimViewAddress(transferCategory, pledgeId, owner, sourceNetwork, - recipientCert, destNetwork +async function getClaimViewAddress( + transferCategory, + pledgeId, + owner, + sourceNetwork, + recipientCert, + destNetwork, ) { - let funcName = "", funcArgs = [] - let ownerCert = await getUserCertFromFile(owner, sourceNetwork) - - if (transferCategory == "token.corda") { - funcName = "GetAssetPledgeStatusByPledgeId" - funcArgs = [pledgeId, destNetwork] - } else if (transferCategory === "bond.fabric") { - funcName = "GetAssetPledgeStatus" - funcArgs = [pledgeId, ownerCert, destNetwork, recipientCert] - } else if (transferCategory === "token.fabric") { - funcName = "GetTokenAssetPledgeStatus" - funcArgs = [pledgeId, ownerCert, destNetwork, recipientCert] - } else if (transferCategory.includes("house-token.corda")) { - funcName = "GetAssetPledgeStatusByPledgeId" - funcArgs = [pledgeId, destNetwork] - } else { - throw new Error(`Unecognized transfer category: ${transferCategory}`) - } + let funcName = "", + funcArgs = []; + const ownerCert = await getUserCertFromFile(owner, sourceNetwork); - const viewAddress = generateViewAddressFromRemoteConfig(sourceNetwork, funcName, funcArgs) + if (transferCategory == "token.corda") { + funcName = "GetAssetPledgeStatusByPledgeId"; + funcArgs = [pledgeId, destNetwork]; + } else if (transferCategory === "bond.fabric") { + funcName = "GetAssetPledgeStatus"; + funcArgs = [pledgeId, ownerCert, destNetwork, recipientCert]; + } else if (transferCategory === "token.fabric") { + funcName = "GetTokenAssetPledgeStatus"; + funcArgs = [pledgeId, ownerCert, destNetwork, recipientCert]; + } else if (transferCategory.includes("house-token.corda")) { + funcName = "GetAssetPledgeStatusByPledgeId"; + funcArgs = [pledgeId, destNetwork]; + } else { + throw new Error(`Unecognized transfer category: ${transferCategory}`); + } - return { viewAddress: viewAddress, ownerCert: ownerCert } -} + const viewAddress = generateViewAddressFromRemoteConfig( + sourceNetwork, + funcName, + funcArgs, + ); -module.exports = command + return { viewAddress: viewAddress, ownerCert: ownerCert }; +} +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/pledge.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/pledge.ts index 0ba1711153..177e71bccd 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/pledge.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/pledge.ts @@ -4,174 +4,165 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as path from 'path' -import { commandHelp, pledgeAsset, getNetworkConfig } from '../../../helpers/helpers' -import { fabricHelper } from '../../../helpers/fabric-functions' +import { GluegunCommand } from "gluegun"; +import * as path from "path"; +import { + commandHelp, + pledgeAsset, + getNetworkConfig, +} from "../../../helpers/helpers"; +import { fabricHelper } from "../../../helpers/fabric-functions"; -import logger from '../../../helpers/logger' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }) +import logger from "../../../helpers/logger"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../../.env") }); -const delay = ms => new Promise(res => setTimeout(res, ms)) +const delay = (ms) => new Promise((res) => setTimeout(res, ms)); const command: GluegunCommand = { - name: 'pledge', - description: - 'Pledges asset in one asset network to another', - run: async toolbox => { + name: "pledge", + description: "Pledges asset in one asset network to another", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=3600 --type=bond --ref=a03 --data-file=src/data/assets.json\r\nfabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=3600 --type=token --owner=alice --units=50 --data-file=src/data/assets.json', - 'fabric-cli asset transfer pledge --source-network= --dest-network= --recipient= --expiry-secs= --type= [--owner=] [--ref=] [--units=] --data-file=>', + "fabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=3600 --type=bond --ref=a03 --data-file=src/data/assets.json\r\nfabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=3600 --type=token --owner=alice --units=50 --data-file=src/data/assets.json", + "fabric-cli asset transfer pledge --source-network= --dest-network= --recipient= --expiry-secs= --type= [--owner=] [--ref=] [--units=] --data-file=>", [ { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--source-network', + name: "--source-network", description: - 'Network where the asset is currently present. ' + "Network where the asset is currently present. ", }, { - name: '--dest-network', + name: "--dest-network", description: - 'Network where the asset is to be transferred. ' + "Network where the asset is to be transferred. ", }, { - name: '--recipient', + name: "--recipient", description: - 'User (wallet) ID of asset recipient in the destination network' + "User (wallet) ID of asset recipient in the destination network", }, { - name: '--expiry-secs', - description: - 'How long (in seconds) is the pledge valid for' + name: "--expiry-secs", + description: "How long (in seconds) is the pledge valid for", }, { - name: '--type', - description: - 'Type of network ' + name: "--type", + description: "Type of network ", }, { - name: '--owner', - description: - 'Asset owner ID used as key in the asset data file' + name: "--owner", + description: "Asset owner ID used as key in the asset data file", }, { - name: '--ref', - description: - 'Asset ID used as key in the asset data file' + name: "--ref", + description: "Asset ID used as key in the asset data file", }, { - name: '--units', - description: - 'Number of units of fungible asset' + name: "--units", + description: "Number of units of fungible asset", }, { - name: '--data-file', - description: - 'Path to data file which stores assets in json format' - } + name: "--data-file", + description: "Path to data file which stores assets in json format", + }, ], command, - ['asset', 'transfer', 'pledge'] - ) - return + ["asset", "transfer", "pledge"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['source-network']) - { - print.error('--source-network needs to be specified') - return + if (!options["source-network"]) { + print.error("--source-network needs to be specified"); + return; } - if (!options['dest-network']) - { - print.error('--dest-network needs to be specified') - return + if (!options["dest-network"]) { + print.error("--dest-network needs to be specified"); + return; } - if (!options['recipient']) - { - print.error('--recipient needs to be specified') - return + if (!options["recipient"]) { + print.error("--recipient needs to be specified"); + return; } - if (!options['expiry-secs']) - { - print.error('--expiry-secs needs to be specified') - return + if (!options["expiry-secs"]) { + print.error("--expiry-secs needs to be specified"); + return; } - if (!options['type']) - { - print.error('--type of network needs to be specified') - return + if (!options["type"]) { + print.error("--type of network needs to be specified"); + return; } - if (options['type'] === 'bond' && !options['ref']) - { - print.error('--ref needs to be specified for "bond" type') - return + if (options["type"] === "bond" && !options["ref"]) { + print.error('--ref needs to be specified for "bond" type'); + return; } - if (options['type'] === 'token' && !options['owner']) - { - print.error('--owner needs to be specified for "token" type') - return + if (options["type"] === "token" && !options["owner"]) { + print.error('--owner needs to be specified for "token" type'); + return; } - if (options['type'] === 'token' && !options['units']) - { - print.error('--units needs to be specified for "token" type') - return + if (options["type"] === "token" && !options["units"]) { + print.error('--units needs to be specified for "token" type'); + return; } - if (options['units'] && isNaN(options['units'])) - { - print.error('--units must be an integer') - return + if (options["units"] && isNaN(options["units"])) { + print.error("--units must be an integer"); + return; } - if (!options['data-file']) - { - print.error('--data-file needs to be specified') - return + if (!options["data-file"]) { + print.error("--data-file needs to be specified"); + return; } - const netConfig = getNetworkConfig(options['source-network']) + const netConfig = getNetworkConfig(options["source-network"]); - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --source-network. No valid environment found for ${options['source-network']} ` - ) - return + `Please use a valid --source-network. No valid environment found for ${options["source-network"]} `, + ); + return; } const pledgeResult = await pledgeAsset({ - dataFilePath: options['data-file'], - sourceNetworkName: options['source-network'], - destNetworkName: options['dest-network'], - recipient: options['recipient'], - expirySecs: parseInt(options['expirySecs']), + dataFilePath: options["data-file"], + sourceNetworkName: options["source-network"], + destNetworkName: options["dest-network"], + recipient: options["recipient"], + expirySecs: parseInt(options["expirySecs"]), connProfilePath: netConfig.connProfilePath, mspId: netConfig.mspId, channelName: netConfig.channelName, contractName: netConfig.chaincode, - ccType: options['type'], - assetOwner: options['owner'], - assetRef: options['ref'], - assetUnits: parseInt(options['units']), - logger: logger - }) + ccType: options["type"], + assetOwner: options["owner"], + assetRef: options["ref"], + assetUnits: parseInt(options["units"]), + logger: logger, + }); if (pledgeResult) { - console.log('Asset pledged with ID', pledgeResult) + console.log("Asset pledged with ID", pledgeResult); } - } -} + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/reclaim.ts b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/reclaim.ts index 44778b47cd..fee591b7e8 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/reclaim.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/asset/transfer/reclaim.ts @@ -4,216 +4,251 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import * as path from "path"; import { - commandHelp, - pledgeAsset, - getNetworkConfig, - getLocalAssetPledgeDetails, - getChaincodeConfig, - handlePromise, - generateViewAddressFromRemoteConfig, - interopHelper -} from '../../../helpers/helpers' + commandHelp, + pledgeAsset, + getNetworkConfig, + getLocalAssetPledgeDetails, + getChaincodeConfig, + handlePromise, + generateViewAddressFromRemoteConfig, + interopHelper, +} from "../../../helpers/helpers"; import { - fabricHelper, - getUserCertBase64 -} from '../../../helpers/fabric-functions' + fabricHelper, + getUserCertBase64, +} from "../../../helpers/fabric-functions"; -import logger from '../../../helpers/logger' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }) +import logger from "../../../helpers/logger"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../../.env") }); -const delay = ms => new Promise(res => setTimeout(res, ms)) +const delay = (ms) => new Promise((res) => setTimeout(res, ms)); const command: GluegunCommand = { - name: 'reclaim', - description: - 'Reclaims pledged asset in source network', - run: async toolbox => { + name: "reclaim", + description: "Reclaims pledged asset in source network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, 'fabric-cli asset transfer reclaim --source-network=network1 --user=alice --type=bond --pledge-id="pledgeid" --param=bond01:a03\r\nfabric-cli asset transfer reclaim --source-network=network1 --user=alice --type=token --param=token1:50', - 'fabric-cli asset transfer reclaim --source-network= --user= --type= --pledge-id= --param=:', + "fabric-cli asset transfer reclaim --source-network= --user= --type= --pledge-id= --param=:", [ { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--source-network', + name: "--source-network", description: - 'Network where the asset is currently present. ' + "Network where the asset is currently present. ", }, { - name: '--user', - description: - 'User (wallet) ID of the reclaimer' + name: "--user", + description: "User (wallet) ID of the reclaimer", }, { - name: '--type', - description: - 'Type of network ' + name: "--type", + description: "Type of network ", }, { - name: '--pledge-id', - description: - 'Pledge Id associated with asset transfer.' + name: "--pledge-id", + description: "Pledge Id associated with asset transfer.", }, { - name: '--param', + name: "--param", description: - 'Colon separated Asset Type and Asset ID or Asset Type and Num of Units.' + "Colon separated Asset Type and Asset ID or Asset Type and Num of Units.", }, { - name: '--relay-tls', - description: 'Flag indicating whether or not the relay is TLS-enabled.' + name: "--relay-tls", + description: + "Flag indicating whether or not the relay is TLS-enabled.", }, { - name: '--relay-tls-ca-files', - description: 'Colon-separated list of root CA certificate paths used to connect to the relay over TLS.' + name: "--relay-tls-ca-files", + description: + "Colon-separated list of root CA certificate paths used to connect to the relay over TLS.", }, { - name: '--e2e-confidentiality', - description: 'Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).' - } + name: "--e2e-confidentiality", + description: + "Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).", + }, ], command, - ['asset', 'transfer', 'reclaim'] - ) - return + ["asset", "transfer", "reclaim"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['source-network']) - { - print.error('--source-network needs to be specified') - return + if (!options["source-network"]) { + print.error("--source-network needs to be specified"); + return; } - if (!options['user']) - { - print.error('--user needs to be specified') - return + if (!options["user"]) { + print.error("--user needs to be specified"); + return; } - if (!options['type']) - { - print.error('--type of asset transfer needs to be specified in the format: \'asset_type.remote_network_type\'.' + - ' \'asset_type\' can be either \'bond\', \'token\' or \'house-token\'.' + - ' \'remote_network_type\' can be either \'fabric\', \'corda\' or \'besu\'.') - return + if (!options["type"]) { + print.error( + "--type of asset transfer needs to be specified in the format: 'asset_type.remote_network_type'." + + " 'asset_type' can be either 'bond', 'token' or 'house-token'." + + " 'remote_network_type' can be either 'fabric', 'corda' or 'besu'.", + ); + return; } - if (!options['param']) - { - print.error('--param needs to be specified') - return + if (!options["param"]) { + print.error("--param needs to be specified"); + return; } - - const params = options['param'].split(':') - const assetType = params[0] - const transferCategory = options['type'] - - if (transferCategory && !params[1]) - { - print.error('assetId needs to be specified for "bond" type') - return + + const params = options["param"].split(":"); + const assetType = params[0]; + const transferCategory = options["type"]; + + if (transferCategory && !params[1]) { + print.error('assetId needs to be specified for "bond" type'); + return; } - if (transferCategory && !params[1]) - { - print.error('num of units needs to be specified for "token" type') - return + if (transferCategory && !params[1]) { + print.error('num of units needs to be specified for "token" type'); + return; } - if (transferCategory.includes('token') && isNaN(parseInt(params[1]))) - { - print.error('num of units must be an integer for "token" type') - return + if (transferCategory.includes("token") && isNaN(parseInt(params[1]))) { + print.error('num of units must be an integer for "token" type'); + return; } - - const assetIdOrQuantity = (transferCategory.includes('token')) ? parseInt(params[1]) : params[1] - - const netConfig = getNetworkConfig(options['source-network']) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { - print.error( - `Please use a valid --source-network. No valid environment found for ${options['source-network']} ` - ) - return + + const assetIdOrQuantity = transferCategory.includes("token") + ? parseInt(params[1]) + : params[1]; + + const netConfig = getNetworkConfig(options["source-network"]); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { + print.error( + `Please use a valid --source-network. No valid environment found for ${options["source-network"]} `, + ); + return; } - + try { - const userCert = await getUserCertBase64(options['source-network'], options['user']) + const userCert = await getUserCertBase64( + options["source-network"], + options["user"], + ); const pledgeAssetDetails = await getLocalAssetPledgeDetails({ - sourceNetworkName: options['source-network'], - pledgeId: options['pledge-id'], - caller: options['user'], + sourceNetworkName: options["source-network"], + pledgeId: options["pledge-id"], + caller: options["user"], ccType: transferCategory, - logger: logger - }) - - const viewAddress = getReclaimViewAddress(transferCategory, assetType, assetIdOrQuantity, - options['pledge-id'], userCert, options['source-network'], pledgeAssetDetails.getRecipient(), - pledgeAssetDetails.getRemotenetworkid(), pledgeAssetDetails.getExpirytimesecs() - ) - - const appChaincodeId = netConfig.chaincode - const applicationFunction = (transferCategory.includes('token')) ? 'ReclaimTokenAsset' : 'ReclaimAsset' - var { args, replaceIndices } = getChaincodeConfig(appChaincodeId, applicationFunction) - args[args.indexOf('')] = options['pledge-id'] - args[args.indexOf('')] = pledgeAssetDetails.getRecipient() - args[args.indexOf('network2')] = pledgeAssetDetails.getRemotenetworkid() - + logger: logger, + }); + + const viewAddress = getReclaimViewAddress( + transferCategory, + assetType, + assetIdOrQuantity, + options["pledge-id"], + userCert, + options["source-network"], + pledgeAssetDetails.getRecipient(), + pledgeAssetDetails.getRemotenetworkid(), + pledgeAssetDetails.getExpirytimesecs(), + ); + + const appChaincodeId = netConfig.chaincode; + const applicationFunction = transferCategory.includes("token") + ? "ReclaimTokenAsset" + : "ReclaimAsset"; + const { args, replaceIndices } = getChaincodeConfig( + appChaincodeId, + applicationFunction, + ); + args[args.indexOf("")] = options["pledge-id"]; + args[args.indexOf("")] = pledgeAssetDetails.getRecipient(); + args[args.indexOf("network2")] = pledgeAssetDetails.getRemotenetworkid(); + await interopHelper( - options['source-network'], + options["source-network"], viewAddress, netConfig.chaincode, applicationFunction, args, replaceIndices, options, - print - ) - process.exit() + print, + ); + process.exit(); } catch (error) { - print.error(`Error Asset Transfer ReClaim: ${error}`) + print.error(`Error Asset Transfer ReClaim: ${error}`); } - } -} - + }, +}; -function getReclaimViewAddress(transferCategory, assetType, assetIdOrQuantity, - pledgeId, pledgerCert, sourceNetwork, recipientCert, - destNetwork, pledgeExpiryTimeSecs +function getReclaimViewAddress( + transferCategory, + assetType, + assetIdOrQuantity, + pledgeId, + pledgerCert, + sourceNetwork, + recipientCert, + destNetwork, + pledgeExpiryTimeSecs, ) { - let funcName = "", funcArgs = [] - if (transferCategory == "token.corda") { - funcName = "GetAssetClaimStatusByPledgeId" - funcArgs = [pledgeId, pledgeExpiryTimeSecs] - } else if (transferCategory === "bond.fabric") { - funcName = "GetAssetClaimStatus" - funcArgs = [pledgeId, assetType, assetIdOrQuantity, recipientCert, - pledgerCert, sourceNetwork, pledgeExpiryTimeSecs] - } else if (transferCategory === "token.fabric") { - funcName = "GetTokenAssetClaimStatus" - funcArgs = [pledgeId, assetType, assetIdOrQuantity, recipientCert, - pledgerCert, sourceNetwork, pledgeExpiryTimeSecs] - } else if (transferCategory.includes("house-token.corda")) { - funcName = "GetAssetClaimStatusByPledgeId" - funcArgs = [pledgeId, pledgeExpiryTimeSecs] - } else { - throw new Error(`Unecognized transfer category: ${transferCategory}`) - } - - return generateViewAddressFromRemoteConfig(destNetwork, funcName, funcArgs) -} + let funcName = "", + funcArgs = []; + if (transferCategory == "token.corda") { + funcName = "GetAssetClaimStatusByPledgeId"; + funcArgs = [pledgeId, pledgeExpiryTimeSecs]; + } else if (transferCategory === "bond.fabric") { + funcName = "GetAssetClaimStatus"; + funcArgs = [ + pledgeId, + assetType, + assetIdOrQuantity, + recipientCert, + pledgerCert, + sourceNetwork, + pledgeExpiryTimeSecs, + ]; + } else if (transferCategory === "token.fabric") { + funcName = "GetTokenAssetClaimStatus"; + funcArgs = [ + pledgeId, + assetType, + assetIdOrQuantity, + recipientCert, + pledgerCert, + sourceNetwork, + pledgeExpiryTimeSecs, + ]; + } else if (transferCategory.includes("house-token.corda")) { + funcName = "GetAssetClaimStatusByPledgeId"; + funcArgs = [pledgeId, pledgeExpiryTimeSecs]; + } else { + throw new Error(`Unecognized transfer category: ${transferCategory}`); + } -module.exports = command + return generateViewAddressFromRemoteConfig(destNetwork, funcName, funcArgs); +} +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/chaincode-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/chaincode-helper.ts index c64851b743..c9202d8579 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/chaincode-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/chaincode-helper.ts @@ -4,21 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helpers/helpers"; const command: GluegunCommand = { - name: 'chaincode', - alias: ['c'], - description: 'Operate on a chaincode: invoke|query', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'fabric-cli chaincode query', '', [], command, [ - 'chaincode' - ]) - return - } -} + name: "chaincode", + alias: ["c"], + description: "Operate on a chaincode: invoke|query", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "fabric-cli chaincode query", "", [], command, [ + "chaincode", + ]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/chaincode/invoke.ts b/weaver/samples/fabric/fabric-cli/src/commands/chaincode/invoke.ts index c537189858..4055db84d3 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/chaincode/invoke.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/chaincode/invoke.ts @@ -4,96 +4,96 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as fs from 'fs' -import { invoke } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { commandHelp, getNetworkConfig } from '../../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import * as fs from "fs"; +import { invoke } from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { commandHelp, getNetworkConfig } from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'invoke', - alias: ['inv'], - description: 'Invoke chaincode with data.', - run: async toolbox => { + name: "invoke", + alias: ["inv"], + description: "Invoke chaincode with data.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli chaincode invoke --local-network=network1 mychannel interop Create '["test", "teststate"]'`, - 'fabric-cli chaincode invoke --local-network= --user= ', + "fabric-cli chaincode invoke --local-network= --user= ", [ { - name: '--local-network', + name: "--local-network", description: - 'local-network network for command. ' + "local-network network for command. ", }, { - name: '--user', + name: "--user", description: - 'user for chaincode invoke. (Optional: Default user is used)' + "user for chaincode invoke. (Optional: Default user is used)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['chaincode', 'invoke'] - ) - return + ["chaincode", "invoke"], + ); + return; } if (array.length < 4) { - print.error('Not enough arguments supplied') - return + print.error("Not enough arguments supplied"); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - let userid = '' - if (options['user']) { - userid = options['user'] + let userid = ""; + if (options["user"]) { + userid = options["user"]; } - const spinner = print.spin(`Invoking chaincode`) + const spinner = print.spin(`Invoking chaincode`); - const netConfig = getNetworkConfig(options['local-network']) - const connProfilePath = netConfig.connProfilePath - const mspId = netConfig.mspId + const netConfig = getNetworkConfig(options["local-network"]); + const connProfilePath = netConfig.connProfilePath; + const mspId = netConfig.mspId; if (!connProfilePath || !mspId) { print.error( - `Please use a valid --local-network. No valid environment found for ${options['local-network']} ` - ) - spinner.fail(`Error invoking chaincode`) - return + `Please use a valid --local-network. No valid environment found for ${options["local-network"]} `, + ); + spinner.fail(`Error invoking chaincode`); + return; } try { - const arrayArgs = JSON.parse(array[3]) + const arrayArgs = JSON.parse(array[3]); const result = await invoke( { contractName: array[1], channel: array[0], ccFunc: array[2], - args: arrayArgs + args: arrayArgs, }, connProfilePath, - options['local-network'], + options["local-network"], mspId, logger, userid, - true - ) - spinner.succeed(`Response from network: ${JSON.stringify(result)} `) + true, + ); + spinner.succeed(`Response from network: ${JSON.stringify(result)} `); } catch (err) { - spinner.fail(`Error invoking chaincode`) - logger.error(`Error invoking chaincode: ${err}`) + spinner.fail(`Error invoking chaincode`); + logger.error(`Error invoking chaincode: ${err}`); } - process.exit() - } -} + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/chaincode/query.ts b/weaver/samples/fabric/fabric-cli/src/commands/chaincode/query.ts index d3dbee3c21..9cf9afe55a 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/chaincode/query.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/chaincode/query.ts @@ -4,96 +4,98 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as fs from 'fs' -import { query } from '../../helpers/fabric-functions' -import { commandHelp, getNetworkConfig } from '../../helpers/helpers' -import logger from '../../helpers/logger' +import { GluegunCommand } from "gluegun"; +import * as fs from "fs"; +import { query } from "../../helpers/fabric-functions"; +import { commandHelp, getNetworkConfig } from "../../helpers/helpers"; +import logger from "../../helpers/logger"; const command: GluegunCommand = { - name: 'query', - alias: ['q'], - description: 'query chaincode with data.', - run: async toolbox => { + name: "query", + alias: ["q"], + description: "query chaincode with data.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli chaincode query --local-network=network1 mychannel interop Read '["56612afd-6730-4206-b25e-6d5d592789d3"]'`, - 'fabric-cli chaincode --local-network= --user= query ', + "fabric-cli chaincode --local-network= --user= query ", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--user', + name: "--user", description: - 'user for chaincode invoke. (Optional: Default user is used)' + "user for chaincode invoke. (Optional: Default user is used)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['chaincode', 'query'] - ) - return + ["chaincode", "query"], + ); + return; } if (array.length < 4) { - print.error('Not enough arguments supplied') - return + print.error("Not enough arguments supplied"); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - let userid = '' - if (options['user']) { - userid = options['user'] + let userid = ""; + if (options["user"]) { + userid = options["user"]; } - const netConfig = getNetworkConfig(options['local-network']) - const connProfilePath = netConfig.connProfilePath - const mspId = netConfig.mspId + const netConfig = getNetworkConfig(options["local-network"]); + const connProfilePath = netConfig.connProfilePath; + const mspId = netConfig.mspId; if (!connProfilePath) { print.error( - `Please use a valid --local-network. No valid environment found for ${options['local-networks']} ` - ) - return + `Please use a valid --local-network. No valid environment found for ${options["local-networks"]} `, + ); + return; } try { - const arrayArgs = JSON.parse(array[3]) + const arrayArgs = JSON.parse(array[3]); const result = await query( { contractName: array[1], channel: array[0], ccFunc: array[2], - args: arrayArgs + args: arrayArgs, }, connProfilePath, - options['local-network'], + options["local-network"], mspId, logger, userid, - true - ) - try { // If the result is a JSON - const resultJSON = JSON.stringify(JSON.parse(result), null, 4) - logger.info(`Result from network query: ${resultJSON}`) - } catch(err) { // If the result is not a JSON - logger.info(`Result from network query: ${result}`) + true, + ); + try { + // If the result is a JSON + const resultJSON = JSON.stringify(JSON.parse(result), null, 4); + logger.info(`Result from network query: ${resultJSON}`); + } catch (err) { + // If the result is not a JSON + logger.info(`Result from network query: ${result}`); } } catch (err) { - logger.error(`Error during fabric query: ${JSON.stringify(err)}`) + logger.error(`Error during fabric query: ${JSON.stringify(err)}`); } - process.exit() - } -} + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/config-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/config-helper.ts index 22e3b4453d..73742b4bb4 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/config-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/config-helper.ts @@ -4,48 +4,48 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, configKeys } from '../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp, configKeys } from "../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'config', + name: "config", description: - 'Interact with config file for the fabric-cli. The config file is used to store network information', - run: async toolbox => { + "Interact with config file for the fabric-cli. The config file is used to store network information", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli config set network1 connProfilePath path/dlt-interoperability/fabric-testnet/organizations`, - `fabric-cli config set <${configKeys.join('|')}> `, + `fabric-cli config set <${configKeys.join("|")}> `, [], command, - ['config'] - ) - return + ["config"], + ); + return; } commandHelp( print, toolbox, `fabric-cli config set network1 connProfilePath path/dlt-interoperability/fabric-testnet/organizations`, - `fabric-cli config set <${configKeys.join('|')}> `, + `fabric-cli config set <${configKeys.join("|")}> `, [], command, - ['config'] - ) - console.log('CONFIG FILE') - const configPath = path.resolve(__dirname, '..', '..', 'config.json') + ["config"], + ); + console.log("CONFIG FILE"); + const configPath = path.resolve(__dirname, "..", "..", "config.json"); !fs.existsSync(configPath) && - fs.writeFileSync(configPath, '', { flag: 'wx' }) - const file = fs.readFileSync(configPath).toString() - console.log(file) - } -} + fs.writeFileSync(configPath, "", { flag: "wx" }); + const file = fs.readFileSync(configPath).toString(); + console.log(file); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/config/get.ts b/weaver/samples/fabric/fabric-cli/src/commands/config/get.ts index 28998ed24e..0f8e166b8c 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/config/get.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/config/get.ts @@ -4,19 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'get', - description: 'Get specific network configuration from the config.', - run: async toolbox => { + name: "get", + description: "Get specific network configuration from the config.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, @@ -25,32 +25,28 @@ const command: GluegunCommand = { `fabric-cli config get `, [], command, - ['config', 'get'] - ) - return + ["config", "get"], + ); + return; } if (array.length < 1 || array.length > 1) { - print.error('Incorrect number of arguments') - return + print.error("Incorrect number of arguments"); + return; } - print.info('Reading config.json file') + print.info("Reading config.json file"); const configPath = path.resolve( - process.env.CONFIG_PATH ? process.env.CONFIG_PATH : path.join( - __dirname, - '..', - '..', - '..', - 'config.json' - ) - ) + process.env.CONFIG_PATH + ? process.env.CONFIG_PATH + : path.join(__dirname, "..", "..", "..", "config.json"), + ); !fs.existsSync(configPath) && - fs.writeFileSync(configPath, '', { flag: 'wx' }) - const file = JSON.parse(fs.readFileSync(configPath).toString()) + fs.writeFileSync(configPath, "", { flag: "wx" }); + const file = JSON.parse(fs.readFileSync(configPath).toString()); if (file[array[0]]) { - console.log('Key: ', array[0], 'Value: ', file[array[0]]) + console.log("Key: ", array[0], "Value: ", file[array[0]]); } - } -} + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/config/set-file.ts b/weaver/samples/fabric/fabric-cli/src/commands/config/set-file.ts index 23db88aebe..31254f67c8 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/config/set-file.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/config/set-file.ts @@ -4,19 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'set-file', - description: 'Replace env file with contents from another env file', - run: async toolbox => { + name: "set-file", + description: "Replace env file with contents from another env file", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, @@ -25,37 +25,33 @@ const command: GluegunCommand = { `fabric-cli config set-file path/to/config.json`, [], command, - ['config', 'set-file'] - ) - return + ["config", "set-file"], + ); + return; } if (array.length < 1 || array.length > 1) { - print.error('Incorrect number of arguments') - return + print.error("Incorrect number of arguments"); + return; } - print.info('Reading config.json file') + print.info("Reading config.json file"); const configPath = path.resolve( - process.env.CONFIG_PATH ? process.env.CONFIG_PATH : path.join( - __dirname, - '..', - '..', - '..', - 'config.json' - ) - ) - const newConfigPath = path.resolve(array[0]) + process.env.CONFIG_PATH + ? process.env.CONFIG_PATH + : path.join(__dirname, "..", "..", "..", "config.json"), + ); + const newConfigPath = path.resolve(array[0]); !fs.existsSync(configPath) && - fs.writeFileSync(configPath, '', { flag: 'wx' }) + fs.writeFileSync(configPath, "", { flag: "wx" }); if (!fs.existsSync(newConfigPath)) { - print.error('Config path provided does not exist') - return + print.error("Config path provided does not exist"); + return; } // TODO: Currently no sanitisation is done on this file. - const file = fs.readFileSync(newConfigPath) - fs.writeFileSync(configPath, file) - print.info(`Updated File:\n${file}`) - } -} + const file = fs.readFileSync(newConfigPath); + fs.writeFileSync(configPath, file); + print.info(`Updated File:\n${file}`); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/config/set.ts b/weaver/samples/fabric/fabric-cli/src/commands/config/set.ts index ae8d00b5b5..52a1b0a153 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/config/set.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/config/set.ts @@ -4,68 +4,64 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, configKeys } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp, configKeys } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'set', - description: 'Set env variables for the fabric-cli', - run: async toolbox => { + name: "set", + description: "Set env variables for the fabric-cli", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli config set network1 relayEndpoint 127.0.0.1:9080`, - `fabric-cli config set <${configKeys.join('|')}> `, + `fabric-cli config set <${configKeys.join("|")}> `, [], command, - ['config', 'set'] - ) - return + ["config", "set"], + ); + return; } if (array.length < 3 || array.length > 3) { - print.error('Incorrect number of arguments') - return + print.error("Incorrect number of arguments"); + return; } if (!configKeys.includes(array[1])) { - print.error('Invalid config key') - print.info(`Valid keys: ${configKeys.join(', ')}`) - return + print.error("Invalid config key"); + print.info(`Valid keys: ${configKeys.join(", ")}`); + return; } - print.info('Reading config.json file') + print.info("Reading config.json file"); const configPath = path.resolve( - process.env.CONFIG_PATH ? process.env.CONFIG_PATH : path.join( - __dirname, - '..', - '..', - '..', - 'config.json' - ) - ) + process.env.CONFIG_PATH + ? process.env.CONFIG_PATH + : path.join(__dirname, "..", "..", "..", "config.json"), + ); !fs.existsSync(configPath) && - fs.writeFileSync(configPath, '', { flag: 'wx' }) - print.info(`Config path: ${configPath}`) - const file = JSON.parse(fs.readFileSync(configPath).toString()) + fs.writeFileSync(configPath, "", { flag: "wx" }); + print.info(`Config path: ${configPath}`); + const file = JSON.parse(fs.readFileSync(configPath).toString()); if (file[array[0]]) { - file[array[0]][array[1]] = array[2] + file[array[0]][array[1]] = array[2]; } else { file[array[0]] = { [array[0]]: { - [array[1]]: array[2] - } - } + [array[1]]: array[2], + }, + }; } - const outFile = JSON.stringify(file, null, 2) - fs.writeFileSync(configPath, outFile) - print.info(`Updated File:\n${outFile}`) - } -} + const outFile = JSON.stringify(file, null, 2); + fs.writeFileSync(configPath, outFile); + print.info(`Updated File:\n${outFile}`); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure-helper.ts index 16e236d26f..9e696137fa 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure-helper.ts @@ -4,21 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helpers/helpers"; const command: GluegunCommand = { - name: 'configure', - description: 'Commands to configure the fabric network', - run: async toolbox => { - const { print } = toolbox + name: "configure", + description: "Commands to configure the fabric network", + run: async (toolbox) => { + const { print } = toolbox; print.info( - `Command performs nothing by itelf, please refer to sub-commands and options.\n` - ) - commandHelp(print, toolbox, '', '', [], command, ['configure']) - } -} + `Command performs nothing by itelf, please refer to sub-commands and options.\n`, + ); + commandHelp(print, toolbox, "", "", [], command, ["configure"]); + }, +}; -module.exports = command +module.exports = command; // fabric-cli configure --source --remote-type:corda --phase:init-interop,init-app,init-relay|all // fabric-cli configure --destination --remote-type:corda diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/all.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/all.ts index 748b712cdd..660c74dbcd 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/all.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/all.ts @@ -4,81 +4,96 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as path from 'path' -import { commandHelp, addData, getNetworkConfig } from '../../helpers/helpers' -import { enrollAndRecordWalletIdentity } from '../../helpers/fabric-functions' +import { GluegunCommand } from "gluegun"; +import * as path from "path"; +import { commandHelp, addData, getNetworkConfig } from "../../helpers/helpers"; +import { enrollAndRecordWalletIdentity } from "../../helpers/fabric-functions"; import { generateMembership, generateAccessControl, - generateVerificationPolicy -} from '../../helpers/fabric-functions' + generateVerificationPolicy, +} from "../../helpers/fabric-functions"; -import { configureNetwork } from '../../helpers/interop-setup/configure-network' -import logger from '../../helpers/logger' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { configureNetwork } from "../../helpers/interop-setup/configure-network"; +import logger from "../../helpers/logger"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); -const delay = ms => new Promise(res => setTimeout(res, ms)) +const delay = (ms) => new Promise((res) => setTimeout(res, ms)); const command: GluegunCommand = { - name: 'all', + name: "all", description: - 'Populates network with data, generates network config and loads interop chaincode', - run: async toolbox => { + "Populates network with data, generates network config and loads interop chaincode", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure all network1 network2', - 'fabric-cli configure all [--iin-agent] (space seperated network names matching config file)', + "fabric-cli configure all network1 network2", + "fabric-cli configure all [--iin-agent] (space seperated network names matching config file)", [ { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--iin-agent', + name: "--iin-agent", description: - 'Optional flag to indicate if iin-agent is recording attested membership.' + "Optional flag to indicate if iin-agent is recording attested membership.", }, { - name: '--num-orgs', - description: - 'Optional flag to indicate the number of orgs. Default = 1' - } - + name: "--num-orgs", + description: + "Optional flag to indicate the number of orgs. Default = 1", + }, ], command, - ['configure', 'all'] - ) - return + ["configure", "all"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - let members = [global.__DEFAULT_MSPID__] - if (options["num-orgs"] === 2){ - members = [global.__DEFAULT_MSPID__, global.__DEFAULT_MSPID_ORG2__] + let members = [global.__DEFAULT_MSPID__]; + if (options["num-orgs"] === 2) { + members = [global.__DEFAULT_MSPID__, global.__DEFAULT_MSPID_ORG2__]; } // for each network, generate network admin identity and IIN Agent identity (there's only one org per network) - const networkAdminUser = 'networkadmin' - const iinAgentUser = 'iinagent' + const networkAdminUser = "networkadmin"; + const iinAgentUser = "iinagent"; for (const network of array) { // Create a network admin - print.info(`Creating network admin wallet identity for network: ${network}`) - await enrollAndRecordWalletIdentity(networkAdminUser, null, network, true, false) - if (options['iin-agent']===true) { - // Create an IIN Agent - print.info(`Creating IIN Agent wallet identity for network: ${network}`) - await enrollAndRecordWalletIdentity(iinAgentUser, null, network, false, true) + print.info( + `Creating network admin wallet identity for network: ${network}`, + ); + await enrollAndRecordWalletIdentity( + networkAdminUser, + null, + network, + true, + false, + ); + if (options["iin-agent"] === true) { + // Create an IIN Agent + print.info( + `Creating IIN Agent wallet identity for network: ${network}`, + ); + await enrollAndRecordWalletIdentity( + iinAgentUser, + null, + network, + false, + true, + ); } } // for each network it @@ -87,112 +102,122 @@ const command: GluegunCommand = { // 3. Loads configs from other networks in the credentials folder for (const network of array) { // GET NETWORK-CONFIGS - const { connProfilePath, username: currusername, aclPolicyPrincipalType } = getNetworkConfig( - network - ) + const { + connProfilePath, + username: currusername, + aclPolicyPrincipalType, + } = getNetworkConfig(network); if (!connProfilePath) { print.error( - `Please use a valid network. No valid environment found for ${network} ` - ) - return + `Please use a valid network. No valid environment found for ${network} `, + ); + return; } - const username = currusername || `user1` - print.info(`Generating membership for network: ${network}`) + const username = currusername || `user1`; + print.info(`Generating membership for network: ${network}`); // 1. Generate network configs (membership, access control, and verification policy) await generateMembership( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", connProfilePath, network, global.__DEFAULT_MSPID__, logger, - options['iin-agent'] - ) - const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE ? process.env.DEFAULT_APPLICATION_CHAINCODE : 'simplestate' + options["iin-agent"], + ); + const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE + ? process.env.DEFAULT_APPLICATION_CHAINCODE + : "simplestate"; await generateAccessControl( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", connProfilePath, network, path.resolve( __dirname, - '../../data/interop/' + appccid + '/accessControlTemplate_' + aclPolicyPrincipalType + '.json' + "../../data/interop/" + + appccid + + "/accessControlTemplate_" + + aclPolicyPrincipalType + + ".json", ), username, global.__DEFAULT_MSPID__, - logger - ) + logger, + ); await generateVerificationPolicy( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", connProfilePath, network, path.resolve( __dirname, - '../../data/interop/' + appccid + '/verificationPolicyTemplate.json' + "../../data/interop/" + appccid + "/verificationPolicyTemplate.json", ), global.__DEFAULT_MSPID__, - logger - ) + logger, + ); } - print.info('Generated Network maps for networks') + print.info("Generated Network maps for networks"); // 2. Add default data for (const network of array) { // ADD DATA - const connProfilePath = getNetworkConfig(network).connProfilePath + const connProfilePath = getNetworkConfig(network).connProfilePath; if (!connProfilePath) { print.error( - `Please use a valid --local-network. No valid environment found for ${network} ` - ) - return + `Please use a valid --local-network. No valid environment found for ${network} `, + ); + return; } - print.info(`Populating ${network} chaincode with data`) - if (network !== 'network2') { + print.info(`Populating ${network} chaincode with data`); + if (network !== "network2") { addData({ - filename: 'stars.json', + filename: "stars.json", connProfilePath, networkName: network, - logger - }) + logger, + }); } - await delay(3000) - if (network !== 'network1') { + await delay(3000); + if (network !== "network1") { addData({ - filename: 'starSize.json', + filename: "starSize.json", connProfilePath, networkName: network, - logger - }) + logger, + }); } - await delay(5000) + await delay(5000); // 3. Loads configs from other networks in the credentials folder // LOAD-CHAINCODE - print.info(`Loading chaincode for network: ${network} ${connProfilePath}`) + print.info( + `Loading chaincode for network: ${network} ${connProfilePath}`, + ); const spinner = toolbox.print.spin( - `Loading Chaincode for network: ${network}` - ) - if (options.debug === 'true') { - spinner.stop() + `Loading Chaincode for network: ${network}`, + ); + if (options.debug === "true") { + spinner.stop(); } try { - await configureNetwork(network, members, logger, options['iin-agent']) - spinner.succeed(`Loaded Chaincode for network: ${network}`) + await configureNetwork(network, members, logger, options["iin-agent"]); + spinner.succeed(`Loaded Chaincode for network: ${network}`); } catch (err) { - spinner.fail('Loading Chaincode failed') - print.error(`Error: ${JSON.stringify(err)}`) - process.exit(1) + spinner.fail("Loading Chaincode failed"); + print.error(`Error: ${JSON.stringify(err)}`); + process.exit(1); } } - print.info(`Finished configuring networks: ${JSON.stringify(array)}`) - process.exit() - } -} + print.info(`Finished configuring networks: ${JSON.stringify(array)}`); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/asset-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/asset-helper.ts index 683ffd80bc..eafd3939a6 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/asset-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/asset-helper.ts @@ -4,32 +4,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'asset', + name: "asset", alias: [], - description: 'Configure for asset networks', - run: async toolbox => { + description: "Configure for asset networks", + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure asset add --target-network=network1 --type=bond', - 'fabric-cli configure asset ', + "fabric-cli configure asset add --target-network=network1 --type=bond", + "fabric-cli configure asset ", [], command, - ['configure', 'asset'] - ) - return + ["configure", "asset"], + ); + return; } - print.info('Command does nothing by itself') - } -} + print.info("Command does nothing by itself"); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/asset/add.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/asset/add.ts index 3e91195bec..e427e2511d 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/asset/add.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/asset/add.ts @@ -4,100 +4,102 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as path from 'path' -import { commandHelp, addAssets, getNetworkConfig } from '../../../helpers/helpers' -import { fabricHelper } from '../../../helpers/fabric-functions' +import { GluegunCommand } from "gluegun"; +import * as path from "path"; +import { + commandHelp, + addAssets, + getNetworkConfig, +} from "../../../helpers/helpers"; +import { fabricHelper } from "../../../helpers/fabric-functions"; -import logger from '../../../helpers/logger' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../../.env') }) +import logger from "../../../helpers/logger"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../../.env") }); -const delay = ms => new Promise(res => setTimeout(res, ms)) +const delay = (ms) => new Promise((res) => setTimeout(res, ms)); const command: GluegunCommand = { - name: 'add', - description: - 'Adds assets to asset network', - run: async toolbox => { + name: "add", + description: "Adds assets to asset network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure asset add --target-network=network1 --type=bond --data-file=src/data/assets.json', - 'fabric-cli configure asset add --target-network= --type= --data-file=>', + "fabric-cli configure asset add --target-network=network1 --type=bond --data-file=src/data/assets.json", + "fabric-cli configure asset add --target-network= --type= --data-file=>", [ { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--target-network', + name: "--target-network", description: - 'Network where asset is to be recorded. ' + "Network where asset is to be recorded. ", }, { - name: '--type', - description: - 'Type of network ' + name: "--type", + description: "Type of network ", }, { - name: '--data-file', - description: - 'Path to data file which stores assets in json format' - } + name: "--data-file", + description: "Path to data file which stores assets in json format", + }, ], command, - ['configure', 'asset', 'add'] - ) - return + ["configure", "asset", "add"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['target-network']) - { - print.error('--target-network needs to be specified') - return + if (!options["target-network"]) { + print.error("--target-network needs to be specified"); + return; } - if (!options['type']) - { - print.error('--type of network needs to be specified') - return + if (!options["type"]) { + print.error("--type of network needs to be specified"); + return; } - if (!options['data-file']) - { - print.error('--data-file needs to be specified') - return + if (!options["data-file"]) { + print.error("--data-file needs to be specified"); + return; } - const netConfig = getNetworkConfig(options['target-network']) + const netConfig = getNetworkConfig(options["target-network"]); - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { print.error( - `Please use a valid --target-network. No valid environment found for ${options['target-network']} ` - ) - return + `Please use a valid --target-network. No valid environment found for ${options["target-network"]} `, + ); + return; } addAssets({ - dataFilePath: options['data-file'], - networkName: options['target-network'], + dataFilePath: options["data-file"], + networkName: options["target-network"], connProfilePath: netConfig.connProfilePath, mspId: netConfig.mspId, channelName: netConfig.channelName, contractName: netConfig.chaincode, - ccType: options['type'], - logger: logger - }) - } -} + ccType: options["type"], + logger: logger, + }); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/create-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/create-helper.ts index 8f4e2b3121..d8045b7c9d 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/create-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/create-helper.ts @@ -4,32 +4,32 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'create', + name: "create", alias: [], - description: 'Various helper functions', - run: async toolbox => { + description: "Various helper functions", + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure create --local-network=network1 acccess-control', - 'fabric-cli configure create ', + "fabric-cli configure create --local-network=network1 acccess-control", + "fabric-cli configure create ", [], command, - ['configure', 'create'] - ) - return + ["configure", "create"], + ); + return; } - print.info('Command does nothing by itself') - } -} + print.info("Command does nothing by itself"); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/access-control.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/access-control.ts index df93c82baf..556c99c000 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/access-control.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/access-control.ts @@ -4,97 +4,100 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, getNetworkConfig } from '../../../helpers/helpers' -import logger from '../../../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { GluegunCommand } from "gluegun"; +import { commandHelp, getNetworkConfig } from "../../../helpers/helpers"; +import logger from "../../../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); import { generateAccessControl, - getCurrentNetworkCredentialPath -} from '../../../helpers/fabric-functions' + getCurrentNetworkCredentialPath, +} from "../../../helpers/fabric-functions"; const command: GluegunCommand = { - name: 'access-control', - description: 'Generates the access control for the local network', - run: async toolbox => { + name: "access-control", + description: "Generates the access control for the local network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure create --local-network=network1 acccess-control', - 'fabric-cli configure create --local-network= acccess-control', + "fabric-cli configure create --local-network=network1 acccess-control", + "fabric-cli configure create --local-network= acccess-control", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--template', - description: 'Path to file to use as a template' + name: "--template", + description: "Path to file to use as a template", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['configure', 'create'] - ) - return + ["configure", "create"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - const networkEnv = getNetworkConfig(options['local-network']) - logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`) + const networkEnv = getNetworkConfig(options["local-network"]); + logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`); if (!networkEnv.relayEndpoint || !networkEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } logger.info( - `Generating ${options['local-network']} network with access control` - ) - const username = - options.username || `user1` + `Generating ${options["local-network"]} network with access control`, + ); + const username = options.username || `user1`; - const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE ? process.env.DEFAULT_APPLICATION_CHAINCODE : 'simplestate' + const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE + ? process.env.DEFAULT_APPLICATION_CHAINCODE + : "simplestate"; const templatePath = options.template ? path.resolve(options.template) : path.resolve( __dirname, - '../../../data/interop/' + appccid + '/accessControlTemplate_' + networkEnv.aclPolicyPrincipalType + '.json' - ) - logger.info(`Template path: ${templatePath}`) + "../../../data/interop/" + + appccid + + "/accessControlTemplate_" + + networkEnv.aclPolicyPrincipalType + + ".json", + ); + logger.info(`Template path: ${templatePath}`); await generateAccessControl( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', - process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", + process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : "interop", networkEnv.connProfilePath, - options['local-network'], + options["local-network"], templatePath, username, global.__DEFAULT_MSPID__, - logger - ) + logger, + ); logger.info( - `Generated ${ - options['local-network'] - } access control at ${getCurrentNetworkCredentialPath( - options['local-network'] - )} ` - ) - process.exit() - } -} + `Generated ${options["local-network"]} access control at ${getCurrentNetworkCredentialPath( + options["local-network"], + )} `, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/all.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/all.ts index 5c795f1d1c..c133973075 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/all.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/all.ts @@ -4,165 +4,176 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, getNetworkConfig } from '../../../helpers/helpers' -import { getCredentialPath, enrollAndRecordWalletIdentity } from '../../../helpers/fabric-functions' -import logger from '../../../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -import * as fs from 'fs' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { GluegunCommand } from "gluegun"; +import { commandHelp, getNetworkConfig } from "../../../helpers/helpers"; +import { + getCredentialPath, + enrollAndRecordWalletIdentity, +} from "../../../helpers/fabric-functions"; +import logger from "../../../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); import { generateAccessControl, getCurrentNetworkCredentialPath, generateVerificationPolicy, - generateMembership -} from '../../../helpers/fabric-functions' + generateMembership, +} from "../../../helpers/fabric-functions"; const command: GluegunCommand = { - name: 'all', - description: 'Generates the access-control, membership, and verification-policy for the local network', - run: async toolbox => { + name: "all", + description: + "Generates the access-control, membership, and verification-policy for the local network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure create all --local-network=network1', - 'fabric-cli configure create all --local-network=', + "fabric-cli configure create all --local-network=network1", + "fabric-cli configure create all --local-network=", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--user', - description: 'User for interop.' + name: "--user", + description: "User for interop.", }, { - name: '--iin-agent', + name: "--iin-agent", description: - 'Optional flag to indicate if iin-agent is recording attested membership.' + "Optional flag to indicate if iin-agent is recording attested membership.", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['configure', 'create'] - ) - return + ["configure", "create"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - const networkEnv = getNetworkConfig(options['local-network']) - logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`) + const networkEnv = getNetworkConfig(options["local-network"]); + logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`); if (!networkEnv.relayEndpoint || !networkEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } // Create wallet credentials - const credentialFolderPath = getCredentialPath() + const credentialFolderPath = getCredentialPath(); const networkNames = fs .readdirSync(credentialFolderPath, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .filter(item => item.name.startsWith('network')) // HACK until we add IIN Agents for Corda networks - .map(item => item.name) + .filter((dirent) => dirent.isDirectory()) + .filter((item) => item.name.startsWith("network")) // HACK until we add IIN Agents for Corda networks + .map((item) => item.name); for (const networkName of networkNames) { - print.info(`Creating network admin wallet identity for network: ${networkName}`) - await enrollAndRecordWalletIdentity('networkadmin', null, networkName, true, false) // Create a network admin + print.info( + `Creating network admin wallet identity for network: ${networkName}`, + ); + await enrollAndRecordWalletIdentity( + "networkadmin", + null, + networkName, + true, + false, + ); // Create a network admin //print.info(`Creating IIN Agent wallet identity for network ${networkName}`) //await enrollAndRecordWalletIdentity('iinagent', null, networkName, false, true) // Create an IIN Agent } // Membership - logger.info(`Generating membership for ${options['local-network']}`) + logger.info(`Generating membership for ${options["local-network"]}`); await generateMembership( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', - process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", + process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : "interop", networkEnv.connProfilePath, - options['local-network'], + options["local-network"], global.__DEFAULT_MSPID__, logger, - options['iin-agent'] - ) + options["iin-agent"], + ); logger.info( - `Generated ${ - options['local-network'] - } secuirty group at ${getCurrentNetworkCredentialPath( - options['local-network'] - )} ` - ) + `Generated ${options["local-network"]} secuirty group at ${getCurrentNetworkCredentialPath( + options["local-network"], + )} `, + ); // Access Control logger.info( - `Generating ${options['local-network']} network with access control` - ) - const username = - options.username || `user1` + `Generating ${options["local-network"]} network with access control`, + ); + const username = options.username || `user1`; - const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE ? process.env.DEFAULT_APPLICATION_CHAINCODE : 'simplestate' + const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE + ? process.env.DEFAULT_APPLICATION_CHAINCODE + : "simplestate"; let templatePath = path.resolve( - __dirname, - '../../../data/interop/' + appccid + '/accessControlTemplate_' + networkEnv.aclPolicyPrincipalType + '.json' - ) - logger.info(`Template path: ${templatePath}`) + __dirname, + "../../../data/interop/" + + appccid + + "/accessControlTemplate_" + + networkEnv.aclPolicyPrincipalType + + ".json", + ); + logger.info(`Template path: ${templatePath}`); await generateAccessControl( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', - process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", + process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : "interop", networkEnv.connProfilePath, - options['local-network'], + options["local-network"], templatePath, username, global.__DEFAULT_MSPID__, - logger - ) + logger, + ); logger.info( - `Generated ${ - options['local-network'] - } access control at ${getCurrentNetworkCredentialPath( - options['local-network'] - )} ` - ) + `Generated ${options["local-network"]} access control at ${getCurrentNetworkCredentialPath( + options["local-network"], + )} `, + ); // Verification Policy logger.info( - `Generating ${options['local-network']} network with verification policy` - ) + `Generating ${options["local-network"]} network with verification policy`, + ); templatePath = path.resolve( - __dirname, - '../../../data/interop/' + appccid + '/verificationPolicyTemplate.json' - ) - logger.info(`Template path: ${templatePath}`) + __dirname, + "../../../data/interop/" + appccid + "/verificationPolicyTemplate.json", + ); + logger.info(`Template path: ${templatePath}`); await generateVerificationPolicy( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', - process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", + process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : "interop", networkEnv.connProfilePath, - options['local-network'], + options["local-network"], templatePath, global.__DEFAULT_MSPID__, - logger - ) + logger, + ); logger.info( - `Generated ${ - options['local-network'] - } verification policy at ${getCurrentNetworkCredentialPath( - options['local-network'] - )} ` - ) - process.exit() - } -} + `Generated ${options["local-network"]} verification policy at ${getCurrentNetworkCredentialPath( + options["local-network"], + )} `, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/membership.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/membership.ts index 41d55b3b82..f822c5ce36 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/membership.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/membership.ts @@ -4,84 +4,82 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, getNetworkConfig } from '../../../helpers/helpers' -import logger from '../../../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { GluegunCommand } from "gluegun"; +import { commandHelp, getNetworkConfig } from "../../../helpers/helpers"; +import logger from "../../../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); import { generateMembership, - getCurrentNetworkCredentialPath -} from '../../../helpers/fabric-functions' + getCurrentNetworkCredentialPath, +} from "../../../helpers/fabric-functions"; const command: GluegunCommand = { - name: 'membership', - description: 'Generates the membership for the local network', - run: async toolbox => { + name: "membership", + description: "Generates the membership for the local network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure --local-network=network1 membership', - 'fabric-cli configure --local-network= membership', + "fabric-cli configure --local-network=network1 membership", + "fabric-cli configure --local-network= membership", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--iin-agent', + name: "--iin-agent", description: - 'Optional flag to indicate if iin-agent is recording attested membership.' + "Optional flag to indicate if iin-agent is recording attested membership.", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['configure', 'create'] - ) - return + ["configure", "create"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - const networkEnv = getNetworkConfig(options['local-network']) - logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`) + const networkEnv = getNetworkConfig(options["local-network"]); + logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`); if (!networkEnv.relayEndpoint || !networkEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } - logger.info(`Generating membership for ${options['local-network']}`) + logger.info(`Generating membership for ${options["local-network"]}`); await generateMembership( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', - process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", + process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : "interop", networkEnv.connProfilePath, - options['local-network'], + options["local-network"], global.__DEFAULT_MSPID__, logger, - options['iin-agent'] - ) + options["iin-agent"], + ); logger.info( - `Generated ${ - options['local-network'] - } secuirty group at ${getCurrentNetworkCredentialPath( - options['local-network'] - )} ` - ) - process.exit() - } -} + `Generated ${options["local-network"]} secuirty group at ${getCurrentNetworkCredentialPath( + options["local-network"], + )} `, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/verification-policy.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/verification-policy.ts index 82fb742bb5..1e344b2c8c 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/create/verification-policy.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/create/verification-policy.ts @@ -4,93 +4,95 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, getNetworkConfig } from '../../../helpers/helpers' -import logger from '../../../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { GluegunCommand } from "gluegun"; +import { commandHelp, getNetworkConfig } from "../../../helpers/helpers"; +import logger from "../../../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); import { generateVerificationPolicy, - getCurrentNetworkCredentialPath -} from '../../../helpers/fabric-functions' + getCurrentNetworkCredentialPath, +} from "../../../helpers/fabric-functions"; const command: GluegunCommand = { - name: 'verification-policy', - description: 'Generates the verification policy for the local network', - run: async toolbox => { + name: "verification-policy", + description: "Generates the verification policy for the local network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure --local-network=network1 verification-policy', - 'fabric-cli configure --local-network= verification-policy', + "fabric-cli configure --local-network=network1 verification-policy", + "fabric-cli configure --local-network= verification-policy", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--template', - description: 'Path to file to use as a template' + name: "--template", + description: "Path to file to use as a template", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['configure', 'create'] - ) - return + ["configure", "create"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - const networkEnv = getNetworkConfig(options['local-network']) - logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`) + const networkEnv = getNetworkConfig(options["local-network"]); + logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`); if (!networkEnv.relayEndpoint || !networkEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } logger.info( - `Generating ${options['local-network']} network with verification policy` - ) - const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE ? process.env.DEFAULT_APPLICATION_CHAINCODE : 'simplestate' + `Generating ${options["local-network"]} network with verification policy`, + ); + const appccid = process.env.DEFAULT_APPLICATION_CHAINCODE + ? process.env.DEFAULT_APPLICATION_CHAINCODE + : "simplestate"; const templatePath = options.template ? path.resolve(options.template) : path.resolve( __dirname, - '../../../data/interop/' + appccid + '/verificationPolicyTemplate.json' - ) - logger.info(`Template path: ${templatePath}`) + "../../../data/interop/" + + appccid + + "/verificationPolicyTemplate.json", + ); + logger.info(`Template path: ${templatePath}`); await generateVerificationPolicy( - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', - process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", + process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : "interop", networkEnv.connProfilePath, - options['local-network'], + options["local-network"], templatePath, global.__DEFAULT_MSPID__, - logger - ) + logger, + ); logger.info( - `Generated ${ - options['local-network'] - } verification policy at ${getCurrentNetworkCredentialPath( - options['local-network'] - )} ` - ) - process.exit() - } -} + `Generated ${options["local-network"]} verification policy at ${getCurrentNetworkCredentialPath( + options["local-network"], + )} `, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/data.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/data.ts index 8b4f5c1d9b..20690d6cb8 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/data.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/data.ts @@ -4,52 +4,53 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, addData, getNetworkConfig } from '../../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp, addData, getNetworkConfig } from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'data', - description: 'Populates network with data.', - run: async toolbox => { + name: "data", + description: "Populates network with data.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure --local-network=network1 data', - 'fabric-cli configure --local-network= data (default: stars.json)', + "fabric-cli configure --local-network=network1 data", + "fabric-cli configure --local-network= data (default: stars.json)", [ { - name: '--local-network', + name: "--local-network", description: - 'local-network network for command. ' - } + "local-network network for command. ", + }, ], command, - ['configure'] - ) - return + ["configure"], + ); + return; } - const connProfilePath = getNetworkConfig(options['local-network']) - .connProfilePath + const connProfilePath = getNetworkConfig( + options["local-network"], + ).connProfilePath; if (!connProfilePath) { print.error( - `Please use a valid --local-network. No valid environment found for ${options['local-network']} ` - ) - return + `Please use a valid --local-network. No valid environment found for ${options["local-network"]} `, + ); + return; } - print.info(`Populating ${options['local-network']} chaincode with data`) + print.info(`Populating ${options["local-network"]} chaincode with data`); addData({ - filename: array[0] ? array[0] : 'stars.json', + filename: array[0] ? array[0] : "stars.json", connProfilePath, - networkName: options['local-network'] - }) - process.exit() - } -} + networkName: options["local-network"], + }); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/membership.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/membership.ts index f599dc6167..102ce5ad31 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/membership.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/membership.ts @@ -4,95 +4,97 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, handlePromise } from '../../helpers/helpers' -import logger from '../../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -import * as fs from 'fs' -import { MembershipManager } from '@hyperledger/cacti-weaver-sdk-fabric' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { GluegunCommand } from "gluegun"; +import { commandHelp, handlePromise } from "../../helpers/helpers"; +import logger from "../../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; +import { MembershipManager } from "@hyperledger/cacti-weaver-sdk-fabric"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); const command: GluegunCommand = { - name: 'membership', - description: - 'Configures network with the membership using iin agent', - run: async toolbox => { + name: "membership", + description: "Configures network with the membership using iin agent", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure network --local-network=network1 --target-network=network2 --iin-agent-endpoint=127.0.0.1:9500', - 'fabric-cli configure network --local-network=>', + "fabric-cli configure network --local-network=network1 --target-network=network2 --iin-agent-endpoint=127.0.0.1:9500", + "fabric-cli configure network --local-network=>", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--target-network', - description: 'Target network for command. ' + name: "--target-network", + description: "Target network for command. ", }, { - name: '--iin-agent-endpoint', - description: 'End point for iin-agent. ' + name: "--iin-agent-endpoint", + description: "End point for iin-agent. ", }, { - name: '--tls', - description: 'Flag indicating whether or not the relay is TLS-enabled.' + name: "--tls", + description: + "Flag indicating whether or not the relay is TLS-enabled.", }, { - name: '--tls-ca-files', - description: 'Colon-separated list of root CA certificate paths used to connect to the relay over TLS.' + name: "--tls-ca-files", + description: + "Colon-separated list of root CA certificate paths used to connect to the relay over TLS.", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['configure'] - ) - return + ["configure"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['target-network']) { - print.error('No target network specified.') - return + if (!options["target-network"]) { + print.error("No target network specified."); + return; } - if (!options['iin-agent-endpoint']) { - print.error('No IIN Agent endpoint specified.') - return + if (!options["iin-agent-endpoint"]) { + print.error("No IIN Agent endpoint specified."); + return; } - if (!options['iin-agent-endpoint'].includes(":")) { - print.error('IIN Agent endpoint does not contain port number.') - return + if (!options["iin-agent-endpoint"].includes(":")) { + print.error("IIN Agent endpoint does not contain port number."); + return; } - // Create wallet credentials - const [response, error] = await handlePromise(MembershipManager.syncMembershipFromIINAgent( - options['target-network'], - options['iin-agent-endpoint'], - options['tls'] === 'true', - options['tls-ca-files'] - )) + const [response, error] = await handlePromise( + MembershipManager.syncMembershipFromIINAgent( + options["target-network"], + options["iin-agent-endpoint"], + options["tls"] === "true", + options["tls-ca-files"], + ), + ); if (error) { - console.error("Error:", error) - process.exit(1) + console.error("Error:", error); + process.exit(1); } else { - console.log("Sync Request submitted succesfully.") + console.log("Sync Request submitted succesfully."); } - process.exit() - } -} + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/configure/network.ts b/weaver/samples/fabric/fabric-cli/src/commands/configure/network.ts index 766856a076..3bdf180a1b 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/configure/network.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/configure/network.ts @@ -4,85 +4,109 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' -import { getCredentialPath, enrollAndRecordWalletIdentity } from '../../helpers/fabric-functions' -import { configureNetwork } from '../../helpers/interop-setup/configure-network' -import logger from '../../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -import * as fs from 'fs' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; +import { + getCredentialPath, + enrollAndRecordWalletIdentity, +} from "../../helpers/fabric-functions"; +import { configureNetwork } from "../../helpers/interop-setup/configure-network"; +import logger from "../../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +import * as fs from "fs"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); const command: GluegunCommand = { - name: 'network', + name: "network", description: - 'Configures network with the membership, verification policy and access control for remote networks', - run: async toolbox => { + "Configures network with the membership, verification policy and access control for remote networks", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, - 'fabric-cli configure network --local-network=network1', - 'fabric-cli configure network --local-network=', + "fabric-cli configure network --local-network=network1", + "fabric-cli configure network --local-network=", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--iin-agent', + name: "--iin-agent", description: - 'Optional flag to indicate if iin-agent is recording attested membership.' + "Optional flag to indicate if iin-agent is recording attested membership.", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--num-orgs', - description: - 'Optional flag to indicate the number of orgs. Default = 1' - } + name: "--num-orgs", + description: + "Optional flag to indicate the number of orgs. Default = 1", + }, ], command, - ['configure'] - ) - return + ["configure"], + ); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - let members = [global.__DEFAULT_MSPID__] - if (options["num-orgs"] === 2){ - members = [global.__DEFAULT_MSPID__, global.__DEFAULT_MSPID_ORG2__] + let members = [global.__DEFAULT_MSPID__]; + if (options["num-orgs"] === 2) { + members = [global.__DEFAULT_MSPID__, global.__DEFAULT_MSPID_ORG2__]; } // Create wallet credentials - const credentialFolderPath = getCredentialPath() + const credentialFolderPath = getCredentialPath(); const networkNames = fs .readdirSync(credentialFolderPath, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .filter(item => item.name.startsWith('network')) // HACK until we add IIN Agents for Corda networks - .map(item => item.name) + .filter((dirent) => dirent.isDirectory()) + .filter((item) => item.name.startsWith("network")) // HACK until we add IIN Agents for Corda networks + .map((item) => item.name); for (const networkName of networkNames) { - print.info(`Creating network admin wallet identity for network: ${networkName}`) - await enrollAndRecordWalletIdentity('networkadmin', null, networkName, true, false) // Create a network admin - if (options['iin-agent']===true) { - print.info(`Creating IIN Agent wallet identity for network ${networkName}`) - await enrollAndRecordWalletIdentity('iinagent', null, networkName, false, true) // Create an IIN Agent + print.info( + `Creating network admin wallet identity for network: ${networkName}`, + ); + await enrollAndRecordWalletIdentity( + "networkadmin", + null, + networkName, + true, + false, + ); // Create a network admin + if (options["iin-agent"] === true) { + print.info( + `Creating IIN Agent wallet identity for network ${networkName}`, + ); + await enrollAndRecordWalletIdentity( + "iinagent", + null, + networkName, + false, + true, + ); // Create an IIN Agent } } - await configureNetwork(options['local-network'], members, logger, options['iin-agent']) - process.exit() - } -} + await configureNetwork( + options["local-network"], + members, + logger, + options["iin-agent"], + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/env-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/env-helper.ts index 04caa174ea..86371ac644 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/env-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/env-helper.ts @@ -4,49 +4,46 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, validKeys } from '../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp, validKeys } from "../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'env', - description: 'Interact with environment variables for the fabric-cli', - run: async toolbox => { + name: "env", + description: "Interact with environment variables for the fabric-cli", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli env set MEMBER_CREDENTIAL_FOLDER path/dlt-interoperability/fabric-testnet/organizations`, - `fabric-cli env set <${validKeys.join('|')}> `, + `fabric-cli env set <${validKeys.join("|")}> `, [], command, - ['env'] - ) - return + ["env"], + ); + return; } commandHelp( print, toolbox, `fabric-cli env set MEMBER_CREDENTIAL_FOLDER path/dlt-interoperability/fabric-testnet/organizations`, - `fabric-cli env set <${validKeys.join('|')}> `, + `fabric-cli env set <${validKeys.join("|")}> `, [], command, - ['env'] - ) - console.log('ENV FILE') - const envPath = path.resolve(__dirname, '..', '..', '.env') - !fs.existsSync(envPath) && fs.writeFileSync(envPath, '', { flag: 'wx' }) - const file = fs - .readFileSync(envPath) - .toString() - .split('\n') - console.log(file) - } -} + ["env"], + ); + console.log("ENV FILE"); + const envPath = path.resolve(__dirname, "..", "..", ".env"); + !fs.existsSync(envPath) && fs.writeFileSync(envPath, "", { flag: "wx" }); + const file = fs.readFileSync(envPath).toString().split("\n"); + console.log(file); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/env/get.ts b/weaver/samples/fabric/fabric-cli/src/commands/env/get.ts index 992c440c4e..3a1736f7c0 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/env/get.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/env/get.ts @@ -4,55 +4,52 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, validKeys } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp, validKeys } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'get', - description: 'get env variables for the fabric-cli', - run: async toolbox => { + name: "get", + description: "get env variables for the fabric-cli", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli env get MEMBER_CREDENTIAL_FOLDER`, - `fabric-cli env get <${validKeys.join('|')}>`, + `fabric-cli env get <${validKeys.join("|")}>`, [], command, - ['env', 'get'] - ) - return + ["env", "get"], + ); + return; } if (array.length < 1 || array.length > 1) { - print.error('Incorrect number of arguments') - return + print.error("Incorrect number of arguments"); + return; } if (!validKeys.includes(array[0])) { - print.error('Invalid env key') - print.info(`Valid keys: ${validKeys}`) - return + print.error("Invalid env key"); + print.info(`Valid keys: ${validKeys}`); + return; } - print.info('Reading .env file') - const envPath = path.resolve(__dirname, '..', '..', '..', '.env') - !fs.existsSync(envPath) && fs.writeFileSync(envPath, '', { flag: 'wx' }) - const file = fs - .readFileSync(envPath) - .toString() - .split('\n') - file.forEach(row => { - const [key, val] = row.split('=') + print.info("Reading .env file"); + const envPath = path.resolve(__dirname, "..", "..", "..", ".env"); + !fs.existsSync(envPath) && fs.writeFileSync(envPath, "", { flag: "wx" }); + const file = fs.readFileSync(envPath).toString().split("\n"); + file.forEach((row) => { + const [key, val] = row.split("="); if (key === array[0]) { - console.log('Key: ', key, 'Value: ', val) + console.log("Key: ", key, "Value: ", val); } - }) - } -} + }); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/env/set-file.ts b/weaver/samples/fabric/fabric-cli/src/commands/env/set-file.ts index 63537ec443..3b1b5f6c5a 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/env/set-file.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/env/set-file.ts @@ -4,19 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'set-file', - description: 'Replace env file with contents from another env file', - run: async toolbox => { + name: "set-file", + description: "Replace env file with contents from another env file", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, @@ -25,27 +25,27 @@ const command: GluegunCommand = { `fabric-cli env set-file path/to/env`, [], command, - ['env', 'set-file'] - ) - return + ["env", "set-file"], + ); + return; } if (array.length < 1 || array.length > 1) { - print.error('Incorrect number of arguments') - return + print.error("Incorrect number of arguments"); + return; } - print.info('Reading .env file') - const envPath = path.resolve(__dirname, '..', '..', '..', '.env') - const newEnvPath = path.resolve(array[0]) - !fs.existsSync(envPath) && fs.writeFileSync(envPath, '', { flag: 'wx' }) + print.info("Reading .env file"); + const envPath = path.resolve(__dirname, "..", "..", "..", ".env"); + const newEnvPath = path.resolve(array[0]); + !fs.existsSync(envPath) && fs.writeFileSync(envPath, "", { flag: "wx" }); if (!fs.existsSync(newEnvPath)) { - print.error('Env path provided does not exist') - return + print.error("Env path provided does not exist"); + return; } - const file = fs.readFileSync(newEnvPath) - fs.writeFileSync(envPath, file) - print.info(`Updated File:\n${file}`) - } -} + const file = fs.readFileSync(newEnvPath); + fs.writeFileSync(envPath, file); + print.info(`Updated File:\n${file}`); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/env/set.ts b/weaver/samples/fabric/fabric-cli/src/commands/env/set.ts index bf2d20baba..57e3218c30 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/env/set.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/env/set.ts @@ -4,68 +4,65 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, validKeys } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp, validKeys } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'set', - description: 'Set env variables for the fabric-cli', - run: async toolbox => { + name: "set", + description: "Set env variables for the fabric-cli", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli env set MEMBER_CREDENTIAL_FOLDER path/dlt-interoperability/fabric-testnet/organizations`, - `fabric-cli env set <${validKeys.join('|')}> `, + `fabric-cli env set <${validKeys.join("|")}> `, [], command, - ['env', 'set'] - ) - return + ["env", "set"], + ); + return; } if (array.length < 2 || array.length > 2) { - print.error('Incorrect number of arguments') - return + print.error("Incorrect number of arguments"); + return; } if (!validKeys.includes(array[0])) { - print.error('Invalid env key') - print.info(`Valid keys: ${validKeys}`) - return + print.error("Invalid env key"); + print.info(`Valid keys: ${validKeys}`); + return; } - print.info('Reading .env file') - const envPath = path.resolve(__dirname, '..', '..', '..', '.env') - !fs.existsSync(envPath) && fs.writeFileSync(envPath, '', { flag: 'wx' }) - const file = fs - .readFileSync(envPath) - .toString() - .split('\n') - let hasKey = false - const updatedFileArray = file.map(row => { - const [key, val] = row.split('=') + print.info("Reading .env file"); + const envPath = path.resolve(__dirname, "..", "..", "..", ".env"); + !fs.existsSync(envPath) && fs.writeFileSync(envPath, "", { flag: "wx" }); + const file = fs.readFileSync(envPath).toString().split("\n"); + let hasKey = false; + const updatedFileArray = file.map((row) => { + const [key, val] = row.split("="); if (key === array[0]) { - hasKey = true - return [key, array[1]].join('=') + hasKey = true; + return [key, array[1]].join("="); } if (key) { - return [key, val].join('=') + return [key, val].join("="); } - }) + }); if (!hasKey) { - updatedFileArray.push([array[0], array[1]].join('=')) - fs.writeFileSync(envPath, updatedFileArray.join('\n')) - print.info(`Updated File:\n${updatedFileArray.join('\n')}`) + updatedFileArray.push([array[0], array[1]].join("=")); + fs.writeFileSync(envPath, updatedFileArray.join("\n")); + print.info(`Updated File:\n${updatedFileArray.join("\n")}`); } else { - fs.writeFileSync(envPath, updatedFileArray.join('\n')) - print.info(`Updated File:\n${updatedFileArray.join('\n')}`) + fs.writeFileSync(envPath, updatedFileArray.join("\n")); + print.info(`Updated File:\n${updatedFileArray.join("\n")}`); } - } -} + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/event-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/event-helper.ts index 15f2d095df..fce50b9f8b 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/event-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/event-helper.ts @@ -4,21 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helpers/helpers"; const command: GluegunCommand = { - name: 'event', - alias: ['e'], - description: 'Event Subscription and receive', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'fabric-cli event', '', [], command, [ - 'event' - ]) - return - } -} + name: "event", + alias: ["e"], + description: "Event Subscription and receive", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "fabric-cli event", "", [], command, ["event"]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/event/get-all.ts b/weaver/samples/fabric/fabric-cli/src/commands/event/get-all.ts index 31db4d7aad..45d379f667 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/event/get-all.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/event/get-all.ts @@ -4,88 +4,97 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper, getKeyAndCertForRemoteRequestbyUserName } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { Utils, ICryptoKey } from 'fabric-common' -import { commandHelp, getNetworkConfig, handlePromise } from '../../helpers/helpers' -import { EventsManager } from '@hyperledger/cacti-weaver-sdk-fabric' -import { EventSubscriptionState, EventType } from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { + fabricHelper, + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { Utils, ICryptoKey } from "fabric-common"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../helpers/helpers"; +import { EventsManager } from "@hyperledger/cacti-weaver-sdk-fabric"; +import { + EventSubscriptionState, + EventType, +} from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'get-all', - alias: ['-gall'], - description: 'Get all received event states', - run: async toolbox => { + name: "get-all", + alias: ["-gall"], + description: "Get all received event states", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli event get-all --network= --request-id="abc123"`, - 'fabric-cli event get-all --network= --request-id=', + "fabric-cli event get-all --network= --request-id=", [ - { - name: '--network', - description: - 'Local network for command. ' - }, - { - name: '--request-id', - description: - 'Request ID received during subscription.' - }, - { - name: '--debug', - description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + { + name: "--network", + description: "Local network for command. ", + }, + { + name: "--request-id", + description: "Request ID received during subscription.", + }, + { + name: "--debug", + description: + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['event', 'get-all'] - ) - return + ["event", "get-all"], + ); + return; } - console.log("Get All Received Event States") - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + console.log("Get All Received Event States"); + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['network']) - { - print.error('--network needs to be specified') - return + if (!options["network"]) { + print.error("--network needs to be specified"); + return; } - if (!options['request-id']) - { - print.error('--request-id needs to be specified') - return + if (!options["request-id"]) { + print.error("--request-id needs to be specified"); + return; } - const networkName = options['network'] - const requestId = options['request-id'] - - const netConfig = getNetworkConfig(networkName) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { - throw new Error(`No valid config entry found for ${networkName}`) + const networkName = options["network"]; + const requestId = options["request-id"]; + + const netConfig = getNetworkConfig(networkName); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { + throw new Error(`No valid config entry found for ${networkName}`); } try { - const response = await EventsManager.getAllReceivedEvents( - requestId, - netConfig.relayEndpoint - ) - console.log("Event States:", JSON.stringify(response, null, 4)) - } catch(e) { - console.log("Error: ", e.toString()) + const response = await EventsManager.getAllReceivedEvents( + requestId, + netConfig.relayEndpoint, + ); + console.log("Event States:", JSON.stringify(response, null, 4)); + } catch (e) { + console.log("Error: ", e.toString()); } - process.exit() - } -} - + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/event/get-subscription-status.ts b/weaver/samples/fabric/fabric-cli/src/commands/event/get-subscription-status.ts index 52c65b2ef2..b54e871fd6 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/event/get-subscription-status.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/event/get-subscription-status.ts @@ -4,88 +4,97 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper, getKeyAndCertForRemoteRequestbyUserName } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { Utils, ICryptoKey } from 'fabric-common' -import { commandHelp, getNetworkConfig, handlePromise } from '../../helpers/helpers' -import { EventsManager } from '@hyperledger/cacti-weaver-sdk-fabric' -import { EventSubscriptionState, EventType } from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { + fabricHelper, + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { Utils, ICryptoKey } from "fabric-common"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../helpers/helpers"; +import { EventsManager } from "@hyperledger/cacti-weaver-sdk-fabric"; +import { + EventSubscriptionState, + EventType, +} from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'get-subscription-status', - alias: ['-g'], - description: 'Get event subscription status', - run: async toolbox => { + name: "get-subscription-status", + alias: ["-g"], + description: "Get event subscription status", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli event unsubscribe --network= --request-id="abc123"`, - 'fabric-cli event unsubscribe --network= --request-id=', + "fabric-cli event unsubscribe --network= --request-id=", [ - { - name: '--network', - description: - 'Local network for command. ' - }, - { - name: '--request-id', - description: - 'Request ID received during subscription.' - }, - { - name: '--debug', - description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + { + name: "--network", + description: "Local network for command. ", + }, + { + name: "--request-id", + description: "Request ID received during subscription.", + }, + { + name: "--debug", + description: + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['event', 'get-subscription-status'] - ) - return + ["event", "get-subscription-status"], + ); + return; } - console.log("Get Event Subscription Status") - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + console.log("Get Event Subscription Status"); + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['network']) - { - print.error('--network needs to be specified') - return + if (!options["network"]) { + print.error("--network needs to be specified"); + return; } - if (!options['request-id']) - { - print.error('--request-id needs to be specified') - return + if (!options["request-id"]) { + print.error("--request-id needs to be specified"); + return; } - const networkName = options['network'] - const requestId = options['request-id'] - - const netConfig = getNetworkConfig(networkName) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { - throw new Error(`No valid config entry found for ${networkName}`) + const networkName = options["network"]; + const requestId = options["request-id"]; + + const netConfig = getNetworkConfig(networkName); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { + throw new Error(`No valid config entry found for ${networkName}`); } try { - const response = await EventsManager.getSubscriptionStatus( - requestId, - netConfig.relayEndpoint - ) - console.log("Event subscription status:", JSON.stringify(response)) - } catch(e) { - console.log("Error: ", e.toString()) + const response = await EventsManager.getSubscriptionStatus( + requestId, + netConfig.relayEndpoint, + ); + console.log("Event subscription status:", JSON.stringify(response)); + } catch (e) { + console.log("Error: ", e.toString()); } - process.exit() - } -} - + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/event/receive.ts b/weaver/samples/fabric/fabric-cli/src/commands/event/receive.ts index c41e8d07a2..e1c257411b 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/event/receive.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/event/receive.ts @@ -4,86 +4,96 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper, getKeyAndCertForRemoteRequestbyUserName } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { Utils, ICryptoKey } from 'fabric-common' -import { commandHelp, getNetworkConfig, handlePromise } from '../../helpers/helpers' -import { EventsManager } from '@hyperledger/cacti-weaver-sdk-fabric' -import { EventSubscriptionState, EventType } from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; -import * as fs from 'fs' -import * as path from 'path' -import * as express from 'express'; -import * as bodyParser from 'body-parser'; +import { GluegunCommand } from "gluegun"; +import { + fabricHelper, + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { Utils, ICryptoKey } from "fabric-common"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../helpers/helpers"; +import { EventsManager } from "@hyperledger/cacti-weaver-sdk-fabric"; +import { + EventSubscriptionState, + EventType, +} from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import * as fs from "fs"; +import * as path from "path"; +import * as express from "express"; +import * as bodyParser from "body-parser"; const command: GluegunCommand = { - name: 'receive', - alias: ['-r'], - description: 'Start simple http server to receive event', - run: async toolbox => { + name: "receive", + alias: ["-r"], + description: "Start simple http server to receive event", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli event receive --port=8080"`, - 'fabric-cli event receive --port=', + "fabric-cli event receive --port=", [ - { - name: '--network', - description: - 'Local network for command. ' - }, - { - name: '--port', - description: - 'Port at which to start http server (Optional). Default: 8080' - }, - { - name: '--debug', - description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + { + name: "--network", + description: "Local network for command. ", + }, + { + name: "--port", + description: + "Port at which to start http server (Optional). Default: 8080", + }, + { + name: "--debug", + description: + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['event', 'receive'] - ) - return + ["event", "receive"], + ); + return; } - console.log("Start HTTP Server for handling events from remote network") - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + console.log("Start HTTP Server for handling events from remote network"); + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - var port = 8080 + let port = 8080; if (options.port) { - port = options.port + port = options.port; } const app = express(); app.use(bodyParser.json()); - app.use(bodyParser.urlencoded({ - extended: false - })); + app.use( + bodyParser.urlencoded({ + extended: false, + }), + ); - app.post('/simple-event-callback', (req, res) => { - console.log("Received Event State: ", req.body.state) - if (req.body.state) { - const data = Buffer.from(req.body.state.View.data).toString('utf8'); - console.log("Received Event Data:", data); - } else { - console.log("Received Error Event:", req.body.error); - } - res.status(200).send('Ok'); + app.post("/simple-event-callback", (req, res) => { + console.log("Received Event State: ", req.body.state); + if (req.body.state) { + const data = Buffer.from(req.body.state.View.data).toString("utf8"); + console.log("Received Event Data:", data); + } else { + console.log("Received Error Event:", req.body.error); + } + res.status(200).send("Ok"); }); console.log(`Server is running at https://127.0.0.1:${port}`); console.log(`Use endpoint '/simple-event-callback' for event publishing`); await app.listen(port); - } -} + }, +}; - -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/event/subscribe.ts b/weaver/samples/fabric/fabric-cli/src/commands/event/subscribe.ts index 695a5d96cd..64ce592433 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/event/subscribe.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/event/subscribe.ts @@ -4,129 +4,150 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper, getKeyAndCertForRemoteRequestbyUserName } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { Utils, ICryptoKey } from 'fabric-common' -import { commandHelp, getNetworkConfig, handlePromise } from '../../helpers/helpers' -import { EventsManager } from '@hyperledger/cacti-weaver-sdk-fabric' -import { EventSubscriptionState, EventType } from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { + fabricHelper, + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { Utils, ICryptoKey } from "fabric-common"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../helpers/helpers"; +import { EventsManager } from "@hyperledger/cacti-weaver-sdk-fabric"; +import { + EventSubscriptionState, + EventType, +} from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'subscribe', - alias: ['-s'], - description: 'Initiate event subscribe', - run: async toolbox => { + name: "subscribe", + alias: ["-s"], + description: "Initiate event subscribe", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli event subscribe --network= --user=user1 src/data/event_sub_sample.json`, - 'fabric-cli event subscribe --network= --user= ', + "fabric-cli event subscribe --network= --user= ", [ - { - name: '--network', - description: - 'Local network for command. ' - }, - { - name: '--user', - description: - 'User for subscription. Default: user1' - }, - { - name: '--debug', - description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + { + name: "--network", + description: "Local network for command. ", + }, + { + name: "--user", + description: "User for subscription. Default: user1", + }, + { + name: "--debug", + description: + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['event', 'subscribe'] - ) - return + ["event", "subscribe"], + ); + return; } - console.log("Event Subscription") - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + console.log("Event Subscription"); + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } if (array.length != 1) { - print.error('Not enough arguments supplied') - return + print.error("Not enough arguments supplied"); + return; } - if (!options['network']) - { - print.error('--network needs to be specified') - return + if (!options["network"]) { + print.error("--network needs to be specified"); + return; } - if (!options['user']) { - options['user'] = `user1` //Default user + if (!options["user"]) { + options["user"] = `user1`; //Default user } - - const networkName = options['network'] - const user = options['user'] - - const filepath = path.resolve(array[0]) - - const netConfig = getNetworkConfig(networkName) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { - throw new Error(`No valid config entry found for ${networkName}`) + + const networkName = options["network"]; + const user = options["user"]; + + const filepath = path.resolve(array[0]); + + const netConfig = getNetworkConfig(networkName); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { + throw new Error(`No valid config entry found for ${networkName}`); } - + const { gateway, wallet, contract } = await fabricHelper({ - channel: netConfig.channelName, - contractName: process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', - connProfilePath: netConfig.connProfilePath, - networkName, - mspId: netConfig.mspId, - logger, - discoveryEnabled: true, - userString: user - }) - + channel: netConfig.channelName, + contractName: process.env.DEFAULT_CHAINCODE + ? process.env.DEFAULT_CHAINCODE + : "interop", + connProfilePath: netConfig.connProfilePath, + networkName, + mspId: netConfig.mspId, + logger, + discoveryEnabled: true, + userString: user, + }); + const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, user) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, user), + ); if (keyCertError) { - throw new Error(`Error getting key and cert ${keyCertError}`) + throw new Error(`Error getting key and cert ${keyCertError}`); } - - const data = JSON.parse(fs.readFileSync(filepath).toString()) - for (let i = 0 ; i < data.length ; i++) { - const eventMatcher = EventsManager.createEventMatcher(data[i].event_matcher) - const eventPublicationSpec = EventsManager.createEventPublicationSpec(data[i].event_publication_spec) - try { - const response = await EventsManager.subscribeRemoteEvent( - contract, - eventMatcher, - eventPublicationSpec, - networkName, - netConfig.mspId, - netConfig.relayEndpoint, - { address: data[i].view_address, Sign: true }, - keyCert - ) + const data = JSON.parse(fs.readFileSync(filepath).toString()); + for (let i = 0; i < data.length; i++) { + const eventMatcher = EventsManager.createEventMatcher( + data[i].event_matcher, + ); + const eventPublicationSpec = EventsManager.createEventPublicationSpec( + data[i].event_publication_spec, + ); + + try { + const response = await EventsManager.subscribeRemoteEvent( + contract, + eventMatcher, + eventPublicationSpec, + networkName, + netConfig.mspId, + netConfig.relayEndpoint, + { address: data[i].view_address, Sign: true }, + keyCert, + ); - if (response.getStatus() == EventSubscriptionState.STATUS.SUBSCRIBED) { - console.log("Event Subscription Status Success with requestId:", response.getRequestId(), 'and event matcher:', JSON.stringify(eventMatcher.toObject())) - } else { - console.log("Unknown error") - } - } catch(e) { - console.log("Error: ", e.toString()) + if (response.getStatus() == EventSubscriptionState.STATUS.SUBSCRIBED) { + console.log( + "Event Subscription Status Success with requestId:", + response.getRequestId(), + "and event matcher:", + JSON.stringify(eventMatcher.toObject()), + ); + } else { + console.log("Unknown error"); } + } catch (e) { + console.log("Error: ", e.toString()); + } } - process.exit() - } -} - + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/event/unsubscribe.ts b/weaver/samples/fabric/fabric-cli/src/commands/event/unsubscribe.ts index 9876b2f57d..b7496c488a 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/event/unsubscribe.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/event/unsubscribe.ts @@ -4,151 +4,175 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { fabricHelper, getKeyAndCertForRemoteRequestbyUserName } from '../../helpers/fabric-functions' -import logger from '../../helpers/logger' -import { Utils, ICryptoKey } from 'fabric-common' -import { commandHelp, getNetworkConfig, handlePromise } from '../../helpers/helpers' -import { EventsManager } from '@hyperledger/cacti-weaver-sdk-fabric' -import { EventSubscriptionState, EventType } from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { + fabricHelper, + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +import logger from "../../helpers/logger"; +import { Utils, ICryptoKey } from "fabric-common"; +import { + commandHelp, + getNetworkConfig, + handlePromise, +} from "../../helpers/helpers"; +import { EventsManager } from "@hyperledger/cacti-weaver-sdk-fabric"; +import { + EventSubscriptionState, + EventType, +} from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'unsubscribe', - alias: ['-u'], - description: 'Initiate event unsubscribe', - run: async toolbox => { + name: "unsubscribe", + alias: ["-u"], + description: "Initiate event unsubscribe", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli event unsubscribe --network= --user=user1 --request-ids="abc123:efg456" src/data/event_sub_sample.json`, - 'fabric-cli event unsubscribe --network= --user= --request-ids= ', + "fabric-cli event unsubscribe --network= --user= --request-ids= ", [ - { - name: '--network', - description: - 'Local network for command. ' - }, - { - name: '--user', - description: - 'User for subscription. Default: user1' - }, - { - name: '--request-ids', - description: - 'Colon-separated list of request IDs received during subscriptions. A request ID can be left blank, indicating that the corresponding JSON (i.e., at the same index) in the file should not be unsubscribed' - }, - { - name: '--debug', - description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + { + name: "--network", + description: "Local network for command. ", + }, + { + name: "--user", + description: "User for subscription. Default: user1", + }, + { + name: "--request-ids", + description: + "Colon-separated list of request IDs received during subscriptions. A request ID can be left blank, indicating that the corresponding JSON (i.e., at the same index) in the file should not be unsubscribed", + }, + { + name: "--debug", + description: + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['event', 'unsubscribe'] - ) - return + ["event", "unsubscribe"], + ); + return; } - console.log("Event Unsubscription") - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + console.log("Event Unsubscription"); + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } if (array.length != 1) { - print.error('Not enough arguments supplied') - return + print.error("Not enough arguments supplied"); + return; } - if (!options['network']) - { - print.error('--network needs to be specified') - return + if (!options["network"]) { + print.error("--network needs to be specified"); + return; } - if (!options['request-ids']) - { - print.error('--request-ids needs to be specified') - return + if (!options["request-ids"]) { + print.error("--request-ids needs to be specified"); + return; } - if (!options['user']) { - options['user'] = `user1` //Default user + if (!options["user"]) { + options["user"] = `user1`; //Default user } - - const networkName = options['network'] - const user = options['user'] - const requestIds = options['request-ids'] - - const filepath = path.resolve(array[0]) - - const netConfig = getNetworkConfig(networkName) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { - throw new Error(`No valid config entry found for ${networkName}`) + + const networkName = options["network"]; + const user = options["user"]; + const requestIds = options["request-ids"]; + + const filepath = path.resolve(array[0]); + + const netConfig = getNetworkConfig(networkName); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { + throw new Error(`No valid config entry found for ${networkName}`); } - + const { gateway, wallet, contract } = await fabricHelper({ - channel: netConfig.channelName, - contractName: process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', - connProfilePath: netConfig.connProfilePath, - networkName, - mspId: netConfig.mspId, - logger, - discoveryEnabled: true, - userString: user - }) - + channel: netConfig.channelName, + contractName: process.env.DEFAULT_CHAINCODE + ? process.env.DEFAULT_CHAINCODE + : "interop", + connProfilePath: netConfig.connProfilePath, + networkName, + mspId: netConfig.mspId, + logger, + discoveryEnabled: true, + userString: user, + }); + const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, user) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, user), + ); if (keyCertError) { - throw new Error(`Error getting key and cert ${keyCertError}`) + throw new Error(`Error getting key and cert ${keyCertError}`); } - const requestIdList = requestIds.split(':') - const data = JSON.parse(fs.readFileSync(filepath).toString()) + const requestIdList = requestIds.split(":"); + const data = JSON.parse(fs.readFileSync(filepath).toString()); if (requestIdList.length !== data.length) { - throw new Error(`Mismatching request ID list and subscription JSON counts. #Request IDs = ${requestIdList.length}, #JSON items = ${data.length}.`) + throw new Error( + `Mismatching request ID list and subscription JSON counts. #Request IDs = ${requestIdList.length}, #JSON items = ${data.length}.`, + ); } - for (let i = 0 ; i < data.length ; i++) { - if (requestIdList[i] === '') { - // Don't unsubscribe - continue; - } + for (let i = 0; i < data.length; i++) { + if (requestIdList[i] === "") { + // Don't unsubscribe + continue; + } - // Unsubscribe - const eventMatcher = EventsManager.createEventMatcher(data[i].event_matcher) - const eventPublicationSpec = EventsManager.createEventPublicationSpec(data[i].event_publication_spec) + // Unsubscribe + const eventMatcher = EventsManager.createEventMatcher( + data[i].event_matcher, + ); + const eventPublicationSpec = EventsManager.createEventPublicationSpec( + data[i].event_publication_spec, + ); - try { - const response = await EventsManager.unsubscribeRemoteEvent( - contract, - eventMatcher, - eventPublicationSpec, - requestIdList[i], - networkName, - netConfig.mspId, - netConfig.relayEndpoint, - { address: data[i].view_address, Sign: true }, - keyCert - ) + try { + const response = await EventsManager.unsubscribeRemoteEvent( + contract, + eventMatcher, + eventPublicationSpec, + requestIdList[i], + networkName, + netConfig.mspId, + netConfig.relayEndpoint, + { address: data[i].view_address, Sign: true }, + keyCert, + ); - if (response.getStatus() == EventSubscriptionState.STATUS.UNSUBSCRIBED) { - console.log("Event Unsubscription Success for requestId:", response.getRequestId(), 'and event matcher:', JSON.stringify(eventMatcher.toObject())) - } else { - console.log("Unknown error") - } - } catch(e) { - console.log("Error: ", e.toString()) + if ( + response.getStatus() == EventSubscriptionState.STATUS.UNSUBSCRIBED + ) { + console.log( + "Event Unsubscription Success for requestId:", + response.getRequestId(), + "and event matcher:", + JSON.stringify(eventMatcher.toObject()), + ); + } else { + console.log("Unknown error"); } + } catch (e) { + console.log("Error: ", e.toString()); + } } - process.exit() - } -} - + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/hash-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/hash-helper.ts index ce91eb8962..df812c61f3 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/hash-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/hash-helper.ts @@ -4,77 +4,79 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import logger from '../helpers/logger' -import { commandHelp } from '../helpers/helpers' -import { HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric' +import { GluegunCommand } from "gluegun"; +import logger from "../helpers/logger"; +import { commandHelp } from "../helpers/helpers"; +import { HashFunctions } from "@hyperledger/cacti-weaver-sdk-fabric"; const command: GluegunCommand = { - name: 'hash', - description: 'Get Hash for given pre image in base64', - run: async toolbox => { + name: "hash", + description: "Get Hash for given pre image in base64", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli hash --hash_fn=SHA256 abc`, - 'fabric-cli hash --hash_fn= --random ', + "fabric-cli hash --hash_fn= --random ", [ { - name: '--hash_fn', + name: "--hash_fn", description: - 'hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)' + "hash function to be used for HTLC. Supported: SHA256, SHA512. (Optional: Default: SHA256)", }, { - name: '--random', + name: "--random", description: - 'Flag to generate random preimage with hash. (Array of preimage is not required if random is set)' + "Flag to generate random preimage with hash. (Array of preimage is not required if random is set)", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['hash'] - ) - return + ["hash"], + ); + return; + } + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (!options["random"] && array.length == 0) { + print.error( + `Either set random flag, or provide preimage as array of strings, at end, separated by space`, + ); + return; } - if (!options['random'] && array.length==0) { - print.error(`Either set random flag, or provide preimage as array of strings, at end, separated by space`) - return - } // Hash - let hash: HashFunctions.Hash - if(options['hash_fn'] == 'SHA512') { - hash = new HashFunctions.SHA512() - if(!options['random']) { - hash.setPreimage(array[0]) - } + let hash: HashFunctions.Hash; + if (options["hash_fn"] == "SHA512") { + hash = new HashFunctions.SHA512(); + if (!options["random"]) { + hash.setPreimage(array[0]); + } } else { - hash = new HashFunctions.SHA256() - if(!options['random']) { - hash.setPreimage(array[0]) - } + hash = new HashFunctions.SHA256(); + if (!options["random"]) { + hash.setPreimage(array[0]); + } } - if(options['random']) - hash.generateRandomPreimage(22) - - const hashValue = hash.getSerializedHashBase64() - console.log(`HashValue: ${hash.getSerializedHashBase64()} \nPreimage: ${hash.getPreimage()}`) + if (options["random"]) hash.generateRandomPreimage(22); - process.exit() - } -} + const hashValue = hash.getSerializedHashBase64(); + console.log( + `HashValue: ${hash.getSerializedHashBase64()} \nPreimage: ${hash.getPreimage()}`, + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/helper-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/helper-helper.ts index 39f9be74e5..849fc3f157 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/helper-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/helper-helper.ts @@ -4,30 +4,30 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helpers/helpers"; const command: GluegunCommand = { - name: 'helper', + name: "helper", alias: [], - description: '(DEV) Various helper functions', - run: async toolbox => { + description: "(DEV) Various helper functions", + run: async (toolbox) => { const { print, - parameters: { options } - } = toolbox + parameters: { options }, + } = toolbox; - print.info('Command does nothing by itself') + print.info("Command does nothing by itself"); commandHelp( print, toolbox, - 'fabric-cli helper getKeyAndCert --local-network=network1', - 'fabric-cli helper ', + "fabric-cli helper getKeyAndCert --local-network=network1", + "fabric-cli helper ", [], command, - ['helper'] - ) - } -} + ["helper"], + ); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/helper/getKeyAndCert.ts b/weaver/samples/fabric/fabric-cli/src/commands/helper/getKeyAndCert.ts index 7947aab214..81eda3eca2 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/helper/getKeyAndCert.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/helper/getKeyAndCert.ts @@ -4,96 +4,90 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' +import { GluegunCommand } from "gluegun"; import { fabricHelper, - getKeyAndCertForRemoteRequestbyUserName -} from '../../helpers/fabric-functions' + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; import { commandHelp, handlePromise, - getNetworkConfig -} from '../../helpers/helpers' + getNetworkConfig, +} from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'getKeyAndCert', + name: "getKeyAndCert", alias: [], - description: 'Get the key and certificate used by a specific user', - run: async toolbox => { + description: "Get the key and certificate used by a specific user", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli chaincode invoke --local-network=network1 mychannel interop Create '["test", "teststate"]'`, - 'fabric-cli chaincode invoke --local-network= ', + "fabric-cli chaincode invoke --local-network= ", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--channel', - description: 'Target channel for command.' + name: "--channel", + description: "Target channel for command.", }, { - name: '--contract', - description: 'Target contract for command.' + name: "--contract", + description: "Target contract for command.", }, { - name: '--mspId', - description: 'mspId for the local fabric network' + name: "--mspId", + description: "mspId for the local fabric network", }, { - name: '--username', - description: 'Target username for command.' - } + name: "--username", + description: "Target username for command.", + }, ], command, - ['helper', 'getKeyAndCert'] - ) - return + ["helper", "getKeyAndCert"], + ); + return; } - const channel = options.channel || 'mychannel' - const contractName = options.contract || 'interop' - const connProfilePath = getNetworkConfig(options['local-network']) - .connProfilePath + const channel = options.channel || "mychannel"; + const contractName = options.contract || "interop"; + const connProfilePath = getNetworkConfig( + options["local-network"], + ).connProfilePath; if (!connProfilePath) { print.error( - `Please use a valid --local-network. No valid environment found for ${options['local-network']} ` - ) - return + `Please use a valid --local-network. No valid environment found for ${options["local-network"]} `, + ); + return; } - const username = - options.username || `user1` + const username = options.username || `user1`; const helperObject = await fabricHelper({ channel, contractName, connProfilePath, mspId: options.mspId, - networkName: options['local-network'] - }) - const wallet = helperObject.wallet + networkName: options["local-network"], + }); + const wallet = helperObject.wallet; const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, username) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, username), + ); if (keyCertError) { - print.error(`Error getting key and cert ${keyCertError}`) - return + print.error(`Error getting key and cert ${keyCertError}`); + return; } - console.log(keyCert.cert) - console.log( - 'key', - keyCert.key - .toBytes() - .toString() - .replace(/\\n/g, '\n') - ) - } -} + console.log(keyCert.cert); + console.log("key", keyCert.key.toBytes().toString().replace(/\\n/g, "\n")); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/helper/signAddress.ts b/weaver/samples/fabric/fabric-cli/src/commands/helper/signAddress.ts index a9fa107ca0..9912bee754 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/helper/signAddress.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/helper/signAddress.ts @@ -4,88 +4,82 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' +import { GluegunCommand } from "gluegun"; import { fabricHelper, - getKeyAndCertForRemoteRequestbyUserName -} from '../../helpers/fabric-functions' + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; import { commandHelp, handlePromise, signMessage, - getNetworkConfig -} from '../../helpers/helpers' + getNetworkConfig, +} from "../../helpers/helpers"; const command: GluegunCommand = { - name: 'signAddress', + name: "signAddress", alias: [], - description: 'Signs a string value using the local-network networks key', - run: async toolbox => { + description: "Signs a string value using the local-network networks key", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli helper signAddress --local-network=network1 ;addressvalue`, - 'fabric-cli helper signAddress --local-network= ', + "fabric-cli helper signAddress --local-network= ", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--mspId', - description: 'mspId for the local fabric network' - } + name: "--mspId", + description: "mspId for the local fabric network", + }, ], command, - ['helper', 'getKeyAndCert'] - ) - return + ["helper", "getKeyAndCert"], + ); + return; } // TODO Make map for networks. - print.info(array) - const channel = options.channel || 'mychannel' - const contractName = options.contract || 'interop' - const connProfilePath = getNetworkConfig(options['local-network']) - .connProfilePath + print.info(array); + const channel = options.channel || "mychannel"; + const contractName = options.contract || "interop"; + const connProfilePath = getNetworkConfig( + options["local-network"], + ).connProfilePath; if (!connProfilePath) { print.error( - `Please use a valid --local-network. No valid environment found for ${options['local-network']} ` - ) - return + `Please use a valid --local-network. No valid environment found for ${options["local-network"]} `, + ); + return; } - const username = - options.username || `user1` + const username = options.username || `user1`; const helperObject = await fabricHelper({ channel, contractName, connProfilePath, mspId: options.mspId, - networkName: options['local-network'] - }) - const wallet = helperObject.wallet + networkName: options["local-network"], + }); + const wallet = helperObject.wallet; const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, username) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, username), + ); if (keyCertError) { - print.error(`Error getting key and cert ${keyCertError}`) - return + print.error(`Error getting key and cert ${keyCertError}`); + return; } - console.log( - 'key', - keyCert.key - .toBytes() - .toString() - .replace(/\\n/g, '\n') - ) - const signature = signMessage(array[0], keyCert.key.toBytes()) - console.log(signature.toString('base64')) - } -} + console.log("key", keyCert.key.toBytes().toString().replace(/\\n/g, "\n")); + const signature = signMessage(array[0], keyCert.key.toBytes()); + console.log(signature.toString("base64")); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/interop-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/interop-helper.ts index 602bb635f9..b9d7188e8c 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/interop-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/interop-helper.ts @@ -4,140 +4,149 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as fs from 'fs' -import { - fabricHelper -} from '../helpers/fabric-functions' +import { GluegunCommand } from "gluegun"; +import * as fs from "fs"; +import { fabricHelper } from "../helpers/fabric-functions"; import { commandHelp, getNetworkConfig, getChaincodeConfig, generateViewAddress, handlePromise, - interopHelper -} from '../helpers/helpers' -import { v4 as uuidv4 } from 'uuid' + interopHelper, +} from "../helpers/helpers"; +import { v4 as uuidv4 } from "uuid"; -import logger from '../helpers/logger' -import * as path from 'path' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) +import logger from "../helpers/logger"; +import * as path from "path"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); const command: GluegunCommand = { - name: 'interop', - description: 'Make an interop call to external network and invoke chaincode', - run: async toolbox => { + name: "interop", + description: "Make an interop call to external network and invoke chaincode", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli interop --local-network=network2 --requesting-org=Org1MSP 127.0.0.1:9080/network1/mychannel:interop:Read:a`, - 'fabric-cli interop
', + "fabric-cli interop
", [ { - name: '--local-network', - description: 'Local network for command. ' + name: "--local-network", + description: "Local network for command. ", }, { - name: '--remote-network', + name: "--remote-network", description: - 'Name of the remote network (Uses network name from address if not provided)' + "Name of the remote network (Uses network name from address if not provided)", }, { - name: '--requesting-org', + name: "--requesting-org", description: - 'Name of the requesting org, if not provided will use the cert' + "Name of the requesting org, if not provided will use the cert", }, { - name: '--mspId', - description: 'mspId for the local fabric network' + name: "--mspId", + description: "mspId for the local fabric network", }, { - name: '--sign', - description: 'Sends signature to relay, usage: --sign=true' + name: "--sign", + description: "Sends signature to relay, usage: --sign=true", }, { - name: '--user', - description: 'User for interop.' + name: "--user", + description: "User for interop.", }, { - name: '--relay-tls', - description: 'Flag indicating whether or not the relay is TLS-enabled.' + name: "--relay-tls", + description: + "Flag indicating whether or not the relay is TLS-enabled.", }, { - name: '--relay-tls-ca-files', - description: 'Colon-separated list of root CA certificate paths used to connect to the relay over TLS.' + name: "--relay-tls-ca-files", + description: + "Colon-separated list of root CA certificate paths used to connect to the relay over TLS.", }, { - name: '--e2e-confidentiality', - description: 'Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).' + name: "--e2e-confidentiality", + description: + "Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['interop'] - ) - return + ["interop"], + ); + return; } if (array.length != 1) { - print.error('Not enough arguments supplied') - return + print.error("Not enough arguments supplied"); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - if (!options['user']) { - options['user'] = `user1` //Default user + if (!options["user"]) { + options["user"] = `user1`; //Default user } // TEST: fabric-cli interop --local-network=network1 127.0.0.1:9081/Nick_Network/test // Making Interop Call using gRPC calls. - print.info('Making Interop Call using gRPC calls.') - const relayEnv = getNetworkConfig(options['local-network']) - logger.debug(`RelayEnv: ${JSON.stringify(relayEnv)}`) + print.info("Making Interop Call using gRPC calls."); + const relayEnv = getNetworkConfig(options["local-network"]); + logger.debug(`RelayEnv: ${JSON.stringify(relayEnv)}`); if (!relayEnv.relayEndpoint || !relayEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } try { - const appChaincodeId = process.env.DEFAULT_APPLICATION_CHAINCODE ? process.env.DEFAULT_APPLICATION_CHAINCODE : 'simplestate' - const applicationFunction = process.env.DEFAULT_APPLICATION_FUNC ? process.env.DEFAULT_APPLICATION_FUNC : 'Create' - const { args, replaceIndices } = getChaincodeConfig(appChaincodeId, applicationFunction) + const appChaincodeId = process.env.DEFAULT_APPLICATION_CHAINCODE + ? process.env.DEFAULT_APPLICATION_CHAINCODE + : "simplestate"; + const applicationFunction = process.env.DEFAULT_APPLICATION_FUNC + ? process.env.DEFAULT_APPLICATION_FUNC + : "Create"; + const { args, replaceIndices } = getChaincodeConfig( + appChaincodeId, + applicationFunction, + ); await interopHelper( - options['local-network'], - await generateViewAddress( // Typically a noop, but for some functions, we may want to do some extra processing + options["local-network"], + await generateViewAddress( + // Typically a noop, but for some functions, we may want to do some extra processing array[0], - options['local-network'], - options['remote-network'], - logger - ), + options["local-network"], + options["remote-network"], + logger, + ), appChaincodeId, applicationFunction, args, replaceIndices, options, - print - ) - process.exit() + print, + ); + process.exit(); } catch (error) { - print.error(`Error Interop Call: ${error}`) + print.error(`Error Interop Call: ${error}`); } - } -} + }, +}; // fabric-cli interop --local-network=network1 --sign=true 127.0.0.1:9081/Corda_Network/127.0.0.1:10006#com.cordaSimpleApplication.flow.GetStateByKey:H // fabric-cli interop --local-network=network2 --remote-network=network1 127.0.0.1:9080/Fabric_Network/mychannel:interop:Read:a -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/relay-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/relay-helper.ts index dfac5feb51..347c53dd31 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/relay-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/relay-helper.ts @@ -4,24 +4,24 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../helpers/helpers' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../helpers/helpers"; const command: GluegunCommand = { - name: 'relay', - description: '(DEV) Operate on local relay: send|get|poll', - run: async toolbox => { - const { print } = toolbox - print.info('Making Relay Call using gRPC calls.') + name: "relay", + description: "(DEV) Operate on local relay: send|get|poll", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Making Relay Call using gRPC calls."); commandHelp( print, toolbox, `fabric-cli relay send|get|poll`, - '', + "", [], command, - ['relay'] - ) - } -} + ["relay"], + ); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/relay/get.ts b/weaver/samples/fabric/fabric-cli/src/commands/relay/get.ts index 37aefa1e36..e3ef564882 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/relay/get.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/relay/get.ts @@ -4,72 +4,73 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { RelayHelper } from '@hyperledger/cacti-weaver-sdk-fabric' -import { commandHelp, getNetworkConfig } from '../../helpers/helpers' -import logger from '../../helpers/logger' +import { GluegunCommand } from "gluegun"; +import { RelayHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; +import { commandHelp, getNetworkConfig } from "../../helpers/helpers"; +import logger from "../../helpers/logger"; const command: GluegunCommand = { - name: 'get', - description: 'Get state of a request from the relay', - run: async toolbox => { + name: "get", + description: "Get state of a request from the relay", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli relay get `, - 'fabric-cli relay get 8b6fee38-053f-4c60-8a37-b07f0b57f3b8', + "fabric-cli relay get 8b6fee38-053f-4c60-8a37-b07f0b57f3b8", [ { - name: '--local-network', + name: "--local-network", description: - 'Local network for command. Takes preference over relayEndpoint. ' + "Local network for command. Takes preference over relayEndpoint. ", }, { - name: '--relayEndpoint', - description: 'Endpoint of relay to local-network' + name: "--relayEndpoint", + description: "Endpoint of relay to local-network", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' - } + "Shows debug logs when running. Disabled by default. To enable --debug=true", + }, ], command, - ['relay', 'get'] - ) - return + ["relay", "get"], + ); + return; } if (array.length != 1) { - print.error('Invalid input length') - return + print.error("Invalid input length"); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - const relayEndpoint = getNetworkConfig(options['local-network']) - .relayEndpoint - logger.debug(`Relay Endpoint: ${relayEndpoint} || ${options.RelayEndpoint}`) + const relayEndpoint = getNetworkConfig( + options["local-network"], + ).relayEndpoint; + logger.debug( + `Relay Endpoint: ${relayEndpoint} || ${options.RelayEndpoint}`, + ); if (!relayEndpoint && !options.relayEndpoint) { print.error( - 'No endpoint provoded for relay. Please use either --relayEndpoint or a valid --local-network' - ) - return + "No endpoint provoded for relay. Please use either --relayEndpoint or a valid --local-network", + ); + return; } - logger.info('Making Relay GetRequestStatus call using gRPC.') - const relay = new RelayHelper.Relay( - relayEndpoint || options.relayEndpoint - ) + logger.info("Making Relay GetRequestStatus call using gRPC."); + const relay = new RelayHelper.Relay(relayEndpoint || options.relayEndpoint); relay .GetRequest(array[0]) - .then(state => console.log('Return state: ', state)) - } -} + .then((state) => console.log("Return state: ", state)); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/relay/poll.ts b/weaver/samples/fabric/fabric-cli/src/commands/relay/poll.ts index 49c4aae546..15e6fa009a 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/relay/poll.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/relay/poll.ts @@ -4,146 +4,148 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as fs from 'fs' +import { GluegunCommand } from "gluegun"; +import * as fs from "fs"; import { commandHelp, getNetworkConfig, signMessage, - handlePromise -} from '../../helpers/helpers' + handlePromise, +} from "../../helpers/helpers"; import { fabricHelper, - getKeyAndCertForRemoteRequestbyUserName -} from '../../helpers/fabric-functions' -import { RelayHelper } from '@hyperledger/cacti-weaver-sdk-fabric' -import * as path from 'path' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +import { RelayHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; +import * as path from "path"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); const command: GluegunCommand = { - name: 'poll', - description: 'Polls relay for state of a request', - run: async toolbox => { + name: "poll", + description: "Polls relay for state of a request", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli Relay poll`, - '', + "", [ { - name: '--local-network', + name: "--local-network", description: - 'Local network for command. Takes preference over endpoint. ' + "Local network for command. Takes preference over endpoint. ", }, { - name: '--requesting-org', + name: "--requesting-org", description: - 'Name of the requesting org, if not provided will use the cert' + "Name of the requesting org, if not provided will use the cert", }, { - name: '--relayEndpoint', - description: 'Endpoint of relay for local network' + name: "--relayEndpoint", + description: "Endpoint of relay for local network", }, { - name: '--mspId', - description: 'mspId for the local fabric network' + name: "--mspId", + description: "mspId for the local fabric network", }, { - name: '--e2e-confidentiality', - description: 'Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).' - } + name: "--e2e-confidentiality", + description: + "Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).", + }, ], command, - ['relay', 'poll'] - ) - return + ["relay", "poll"], + ); + return; } if (array.length != 1) { - print.error('Invalid input length.') - return + print.error("Invalid input length."); + return; } - const relayEndpoint = getNetworkConfig(options['local-network']) - .relayEndpoint + const relayEndpoint = getNetworkConfig( + options["local-network"], + ).relayEndpoint; if (!relayEndpoint && !options.relayEndpoint) { print.error( - 'No endpoint provoded for relay. Please use either --relayEndpoint or a valid --local-network' - ) - return + "No endpoint provoded for relay. Please use either --relayEndpoint or a valid --local-network", + ); + return; } - let requestJson = { certificate: '', policy: '' } - if (options['request-path']) { - print.info(`Using path: ${options['request-path']}`) + let requestJson = { certificate: "", policy: "" }; + if (options["request-path"]) { + print.info(`Using path: ${options["request-path"]}`); requestJson = JSON.parse( - fs.readFileSync(options['request-path']).toString() - ) + fs.readFileSync(options["request-path"]).toString(), + ); if ( !requestJson.certificate || - !requestJson['requestor-signature'] || + !requestJson["requestor-signature"] || !requestJson.policy ) { print.error( - "Request object is missing a key/value. Requires 'certificate', 'requestor-signature' and 'policy'" - ) - return + "Request object is missing a key/value. Requires 'certificate', 'requestor-signature' and 'policy'", + ); + return; } } - const relayEnv = getNetworkConfig(options['local-network']) + const relayEnv = getNetworkConfig(options["local-network"]); if (!relayEnv.relayEndpoint || !relayEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } const { wallet } = await fabricHelper({ channel: process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL - : 'mychannel', + : "mychannel", contractName: process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", connProfilePath: relayEnv.connProfilePath, - networkName: options['local-network'], - mspId: options.mspId - }) - const username = `user1` - console.log(relayEnv.relayEndpoint, relayEnv.connProfilePath) + networkName: options["local-network"], + mspId: options.mspId, + }); + const username = `user1`; + console.log(relayEnv.relayEndpoint, relayEnv.connProfilePath); const relay = new RelayHelper.Relay( - relayEnv.relayEndpoint || options.relayEndpoint - ) + relayEnv.relayEndpoint || options.relayEndpoint, + ); const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, username) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, username), + ); if (keyCertError) { console.error( - 'Error fetching key and certificate from network', - keyCertError - ) + "Error fetching key and certificate from network", + keyCertError, + ); } - print.info('Making Relay Call using gRPC calls.') + print.info("Making Relay Call using gRPC calls."); relay .ProcessRequest( array[0], - requestJson?.policy || 'policy', - options['local-network'], + requestJson?.policy || "policy", + options["local-network"], requestJson?.certificate || keyCert.cert, options.sign - ? requestJson?.['requestor-signature'] || - signMessage(array[0], keyCert.key.toBytes()).toString('base64') - : '', - '', - options['requesting-org'] || '', - options['e2e-confidentiality'] === 'true' ? true : false + ? requestJson?.["requestor-signature"] || + signMessage(array[0], keyCert.key.toBytes()).toString("base64") + : "", + "", + options["requesting-org"] || "", + options["e2e-confidentiality"] === "true" ? true : false, ) - .then(result => { - console.log('Result: ', result.toObject()) - }) - } -} + .then((result) => { + console.log("Result: ", result.toObject()); + }); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/relay/send.ts b/weaver/samples/fabric/fabric-cli/src/commands/relay/send.ts index c1964968a4..1a06cdaf12 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/relay/send.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/relay/send.ts @@ -4,162 +4,163 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import * as fs from 'fs' -import * as path from 'path' -import * as dotenv from 'dotenv' +import { GluegunCommand } from "gluegun"; +import * as fs from "fs"; +import * as path from "path"; +import * as dotenv from "dotenv"; import { commandHelp, handlePromise, getNetworkConfig, - signMessage -} from '../../helpers/helpers' -import logger from '../../helpers/logger' + signMessage, +} from "../../helpers/helpers"; +import logger from "../../helpers/logger"; import { fabricHelper, - getKeyAndCertForRemoteRequestbyUserName -} from '../../helpers/fabric-functions' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) + getKeyAndCertForRemoteRequestbyUserName, +} from "../../helpers/fabric-functions"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); -import { RelayHelper } from '@hyperledger/cacti-weaver-sdk-fabric' +import { RelayHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; const command: GluegunCommand = { - name: 'send', - description: 'Sends a query to the local relay.', - run: async toolbox => { + name: "send", + description: "Sends a query to the local relay.", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, toolbox, `fabric-cli relay send 127.0.0.1:9081/Fabric_Network/mychannel:interop:Read:TestState`, - 'fabric-cli relay send ', + "fabric-cli relay send ", [ { - name: '--local-network', + name: "--local-network", description: - 'Local network for command. Takes preference over endpoint. (Which network the request will come from)' + "Local network for command. Takes preference over endpoint. (Which network the request will come from)", }, { - name: '--sign', - description: 'Sends signature to relay, usage: --sign=true' + name: "--sign", + description: "Sends signature to relay, usage: --sign=true", }, { - name: '--remote-network', + name: "--remote-network", description: - 'Name of the remote network (Uses network name from address if not provided)' + "Name of the remote network (Uses network name from address if not provided)", }, { - name: '--requesting-org', + name: "--requesting-org", description: - 'Name of the requesting org, if not provided will use the cert' + "Name of the requesting org, if not provided will use the cert", }, { - name: '--request-path', + name: "--request-path", description: - 'Path to JSON file to use as a request. See `network2-request.json` for an example' + "Path to JSON file to use as a request. See `network2-request.json` for an example", }, { - name: '--debug', + name: "--debug", description: - 'Shows debug logs when running. Disabled by default. To enable --debug=true' + "Shows debug logs when running. Disabled by default. To enable --debug=true", }, { - name: '--mspId', - description: 'mspId for the local fabric network' + name: "--mspId", + description: "mspId for the local fabric network", }, { - name: '--e2e-confidentiality', - description: 'Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).' - } + name: "--e2e-confidentiality", + description: + "Flag indicating whether or not the view contents are confidential end-to-end across networks (client-to-interop-module).", + }, ], command, - ['relay', 'send'] - ) - return + ["relay", "send"], + ); + return; } if (array.length != 1) { - print.error('Invalid input length.') - return + print.error("Invalid input length."); + return; } - if (options.debug === 'true') { - logger.level = 'debug' - logger.debug('Debugging is enabled') + if (options.debug === "true") { + logger.level = "debug"; + logger.debug("Debugging is enabled"); } - let requestJson = { certificate: '', policy: '' } - if (options['request-path']) { - print.info(`Using path: ${options['request-path']}`) + let requestJson = { certificate: "", policy: "" }; + if (options["request-path"]) { + print.info(`Using path: ${options["request-path"]}`); requestJson = JSON.parse( - fs.readFileSync(options['request-path']).toString() - ) + fs.readFileSync(options["request-path"]).toString(), + ); if ( !requestJson.certificate || - !requestJson['requestor-signature'] || + !requestJson["requestor-signature"] || !requestJson.policy ) { print.error( - "Request object is missing a key/value. Requires 'certificate', 'requestor-signature' and 'policy'" - ) - return + "Request object is missing a key/value. Requires 'certificate', 'requestor-signature' and 'policy'", + ); + return; } } - logger.debug(`REQUEST JSON: ${JSON.stringify(requestJson)}`) - const relayEnv = getNetworkConfig(options['local-network']) - logger.debug(`Environment: ${JSON.stringify(relayEnv)}`) + logger.debug(`REQUEST JSON: ${JSON.stringify(requestJson)}`); + const relayEnv = getNetworkConfig(options["local-network"]); + logger.debug(`Environment: ${JSON.stringify(relayEnv)}`); if (!relayEnv.relayEndpoint || !relayEnv.connProfilePath) { print.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } const { wallet } = await fabricHelper({ channel: process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL - : 'mychannel', + : "mychannel", contractName: process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", connProfilePath: relayEnv.connProfilePath, - networkName: options['local-network'], - mspId: options.mspId - }) - const username = `user1` - console.log(relayEnv.relayEndpoint, relayEnv.connProfilePath) + networkName: options["local-network"], + mspId: options.mspId, + }); + const username = `user1`; + console.log(relayEnv.relayEndpoint, relayEnv.connProfilePath); const relay = new RelayHelper.Relay( - relayEnv.relayEndpoint || options.relayEndpoint - ) + relayEnv.relayEndpoint || options.relayEndpoint, + ); const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, username) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, username), + ); if (keyCertError) { console.error( - 'Error fetching key and certificate from network', - keyCertError - ) + "Error fetching key and certificate from network", + keyCertError, + ); } - print.info('Making Relay Call using gRPC calls.') + print.info("Making Relay Call using gRPC calls."); relay .SendRequest( array[0], - requestJson?.policy || 'policy', - options['local-network'], + requestJson?.policy || "policy", + options["local-network"], requestJson?.certificate || keyCert.cert, options.sign - ? requestJson?.['requestor-signature'] || - signMessage(array[0], keyCert.key.toBytes()).toString('base64') - : '', - '', - options['requesting-org'] || '', - options['e2e-confidentiality'] === 'true' ? true : false + ? requestJson?.["requestor-signature"] || + signMessage(array[0], keyCert.key.toBytes()).toString("base64") + : "", + "", + options["requesting-org"] || "", + options["e2e-confidentiality"] === "true" ? true : false, ) - .then(test => { - console.log('Result: ', test) - }) - } -} + .then((test) => { + console.log("Result: ", test); + }); + }, +}; //127.0.0.1:9081/Corda_Network/127.0.0.1:10006#com.cordaSimpleApplication.flow.GetStateByKey:H -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/user-helper.ts b/weaver/samples/fabric/fabric-cli/src/commands/user-helper.ts index f334f8906f..a694bd35c5 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/user-helper.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/user-helper.ts @@ -4,23 +4,23 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp, validKeys } from '../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' +import { GluegunCommand } from "gluegun"; +import { commandHelp, validKeys } from "../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; const command: GluegunCommand = { - name: 'user', - alias: ['u'], - description: 'User utility for fabric-network', - run: async toolbox => { - const { print } = toolbox - print.info('Command does nothing by itself') - commandHelp(print, toolbox, 'fabric-cli user add', '', [], command, [ - 'user' - ]) - return - } -} + name: "user", + alias: ["u"], + description: "User utility for fabric-network", + run: async (toolbox) => { + const { print } = toolbox; + print.info("Command does nothing by itself"); + commandHelp(print, toolbox, "fabric-cli user add", "", [], command, [ + "user", + ]); + return; + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/commands/user/add.ts b/weaver/samples/fabric/fabric-cli/src/commands/user/add.ts index 2c4329c083..d6d23260f5 100644 --- a/weaver/samples/fabric/fabric-cli/src/commands/user/add.ts +++ b/weaver/samples/fabric/fabric-cli/src/commands/user/add.ts @@ -4,20 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { commandHelp } from '../../helpers/helpers' -import * as fs from 'fs' -import * as path from 'path' -import { enrollAndRecordWalletIdentity } from '../../helpers/fabric-functions' +import { GluegunCommand } from "gluegun"; +import { commandHelp } from "../../helpers/helpers"; +import * as fs from "fs"; +import * as path from "path"; +import { enrollAndRecordWalletIdentity } from "../../helpers/fabric-functions"; const command: GluegunCommand = { - name: 'add', - description: 'Register and enroll user to the fabric network', - run: async toolbox => { + name: "add", + description: "Register and enroll user to the fabric network", + run: async (toolbox) => { const { print, - parameters: { options, array } - } = toolbox + parameters: { options, array }, + } = toolbox; if (options.help || options.h) { commandHelp( print, @@ -26,46 +26,55 @@ const command: GluegunCommand = { `fabric-cli user add --target-network= --id= --secret= [--network-admin] [--iin-agent]`, [ { - name: '--target-network', + name: "--target-network", description: - 'target-network network for command. ' + "target-network network for command. ", }, { - name: '--id', - description: - 'username to be added to the network' + name: "--id", + description: "username to be added to the network", }, { - name: '--secret', + name: "--secret", description: - 'password for the username being added (Optional: random password is used)' + "password for the username being added (Optional: random password is used)", }, { - name: '--network-admin', + name: "--network-admin", description: - 'Flag to indicate whether this user should have a network admin attribute.' + "Flag to indicate whether this user should have a network admin attribute.", }, { - name: '--iin-agent', + name: "--iin-agent", description: - 'Flag to indicate whether this user should have an IIN agent attribute.' - } + "Flag to indicate whether this user should have an IIN agent attribute.", + }, ], command, - ['user', 'add'] - ) - return + ["user", "add"], + ); + return; } - if (!options['target-network']) { - print.error('--target-network is required arguement, please specify the network name here') + if (!options["target-network"]) { + print.error( + "--target-network is required arguement, please specify the network name here", + ); } - if (!options['id']) { - print.error('--id is required arguement, please specify the username here') + if (!options["id"]) { + print.error( + "--id is required arguement, please specify the username here", + ); } - await enrollAndRecordWalletIdentity(options['id'], options['secret'], options['target-network'], options['network-admin'], options['iin-agent']) - process.exit() - } -} + await enrollAndRecordWalletIdentity( + options["id"], + options["secret"], + options["target-network"], + options["network-admin"], + options["iin-agent"], + ); + process.exit(); + }, +}; -module.exports = command +module.exports = command; diff --git a/weaver/samples/fabric/fabric-cli/src/extensions/cli-extension.ts b/weaver/samples/fabric/fabric-cli/src/extensions/cli-extension.ts index c1b7bf2ab2..aaf3cdc542 100644 --- a/weaver/samples/fabric/fabric-cli/src/extensions/cli-extension.ts +++ b/weaver/samples/fabric/fabric-cli/src/extensions/cli-extension.ts @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunToolbox } from 'gluegun' +import { GluegunToolbox } from "gluegun"; // add your CLI-specific functionality here, which will then be accessible // to your commands module.exports = (toolbox: GluegunToolbox) => { toolbox.foo = () => { - toolbox.print.info('called foo extension') - } + toolbox.print.info("called foo extension"); + }; // enable this if you want to read configuration in from // the current folder's package.json (in a "fabric-cli" property), @@ -20,4 +20,4 @@ module.exports = (toolbox: GluegunToolbox) => { // ...toolbox.config, // ...toolbox.config.loadConfig(process.cwd(), "fabric-cli") // } -} +}; diff --git a/weaver/samples/fabric/fabric-cli/src/helpers/fabric-functions.ts b/weaver/samples/fabric/fabric-cli/src/helpers/fabric-functions.ts index db92df3693..570b3248c2 100644 --- a/weaver/samples/fabric/fabric-cli/src/helpers/fabric-functions.ts +++ b/weaver/samples/fabric/fabric-cli/src/helpers/fabric-functions.ts @@ -4,142 +4,160 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Gateway, Wallets, Contract, X509Identity } from 'fabric-network' -import { commandHelp, getNetworkConfig, saveUserCertToFile, handlePromise } from './helpers' -import * as FabricCAServices from 'fabric-ca-client' -import { Certificate } from '@fidm/x509' -import { Utils, ICryptoKey } from 'fabric-common' -import * as membership_pb from "@hyperledger/cacti-weaver-protos-js/common/membership_pb" -import * as iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb" -import { InteroperableHelper } from '@hyperledger/cacti-weaver-sdk-fabric' -import * as path from 'path' -import * as dotenv from 'dotenv' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) -import * as fs from 'fs' +import { Gateway, Wallets, Contract, X509Identity } from "fabric-network"; +import { + commandHelp, + getNetworkConfig, + saveUserCertToFile, + handlePromise, +} from "./helpers"; +import * as FabricCAServices from "fabric-ca-client"; +import { Certificate } from "@fidm/x509"; +import { Utils, ICryptoKey } from "fabric-common"; +import * as membership_pb from "@hyperledger/cacti-weaver-protos-js/common/membership_pb"; +import * as iin_agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; +import { InteroperableHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; +import * as path from "path"; +import * as dotenv from "dotenv"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); +import * as fs from "fs"; export type InvocationSpec = { - contractName: string - channel: string - args: string[] - ccFunc: string -} - -const getUserCertBase64 = async ( - networkName: string, - username: string -) => { - const wallet = await getWalletForNetwork(networkName) - const userId = await wallet.get(username) + contractName: string; + channel: string; + args: string[]; + ccFunc: string; +}; + +const getUserCertBase64 = async (networkName: string, username: string) => { + const wallet = await getWalletForNetwork(networkName); + const userId = await wallet.get(username); if (!userId) { - throw new Error(`User ${username} not present in wallet of ${networkName}.`) + throw new Error( + `User ${username} not present in wallet of ${networkName}.`, + ); } - return Buffer.from((userId as X509Identity).credentials.certificate).toString('base64') -} + return Buffer.from((userId as X509Identity).credentials.certificate).toString( + "base64", + ); +}; const walletSetup = async ( networkName: string, ccp: any, mspId: string, userName: string, - userPwd: string = '', + userPwd: string = "", isNetworkAdmin: boolean = false, isIINAgent: boolean = false, register: boolean = false, - logger: any = console + logger: any = console, ) => { // Create a new CA client for interacting with the CA. - const org = ccp.client['organization'] - const caName = ccp.organizations[org]['certificateAuthorities'][0] - const caURL = ccp.certificateAuthorities[caName].url - const ca = new FabricCAServices(caURL) - const ident = ca.newIdentityService() + const org = ccp.client["organization"]; + const caName = ccp.organizations[org]["certificateAuthorities"][0]; + const caURL = ccp.certificateAuthorities[caName].url; + const ca = new FabricCAServices(caURL); + const ident = ca.newIdentityService(); - const wallet = await getWalletForNetwork(networkName) + const wallet = await getWalletForNetwork(networkName); // build a user object for authenticating with the CA // Check to see if we've already enrolled the admin user. - let adminIdentity = await wallet.get('admin') + let adminIdentity = await wallet.get("admin"); if (adminIdentity) { logger.debug( - 'An identity for the admin user "admin" already exists in the wallet.' - ) + 'An identity for the admin user "admin" already exists in the wallet.', + ); } else { // Enroll the admin user, and import the new identity into the wallet. const enrollment = await ca.enroll({ - enrollmentID: 'admin', - enrollmentSecret: 'adminpw' - }) + enrollmentID: "admin", + enrollmentSecret: "adminpw", + }); const x509Identity = { credentials: { certificate: enrollment.certificate, - privateKey: enrollment.key.toBytes() + privateKey: enrollment.key.toBytes(), }, mspId: mspId, - type: 'X.509' - } - await wallet.put('admin', x509Identity) - adminIdentity = await wallet.get('admin') + type: "X.509", + }; + await wallet.put("admin", x509Identity); + adminIdentity = await wallet.get("admin"); } - const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type) - const adminUser = await provider.getUserContext(adminIdentity, 'admin') - const identity = await wallet.get(userName) - logger.debug(`user ${userName}`) + const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type); + const adminUser = await provider.getUserContext(adminIdentity, "admin"); + const identity = await wallet.get(userName); + logger.debug(`user ${userName}`); if (!identity) { // Register the user, enroll the user, and import the new identity into the wallet. if (!register) { - logger.error(`Identity ${userName} does not exist. Please add user in the network.\n`) - return + logger.error( + `Identity ${userName} does not exist. Please add user in the network.\n`, + ); + return; } - var secret, enrollment - var enrollmentDone = false - var attributes = [] + let secret, enrollment; + let enrollmentDone = false; + const attributes = []; if (isNetworkAdmin) { - attributes.push({ "name": "network-admin", "value": "true", "ecert": true }) + attributes.push({ name: "network-admin", value: "true", ecert: true }); } if (isIINAgent) { - attributes.push({ "name": "iin-agent", "value": "true", "ecert": true }) + attributes.push({ name: "iin-agent", value: "true", ecert: true }); } try { if (!userPwd) { secret = await ca.register( { - affiliation: 'org1.department1', + affiliation: "org1.department1", enrollmentID: userName, maxEnrollments: -1, - role: 'client', - attrs: attributes + role: "client", + attrs: attributes, }, - adminUser - ) - } - else { + adminUser, + ); + } else { secret = await ca.register( { - affiliation: 'org1.department1', + affiliation: "org1.department1", enrollmentID: userName, enrollmentSecret: userPwd, maxEnrollments: -1, - role: 'client', - attrs: attributes + role: "client", + attrs: attributes, }, - adminUser - ) + adminUser, + ); } - logger.info(`Wallet Setup: Sucessful ${secret}`) - } catch(error) { - const registeredUser = `Identity '${userName}' is already ` - if (!userPwd || !(error.message.includes("Identity ") && error.message.includes(userName) && error.message.includes(" is already registered"))) { - throw new Error(`user ${userName} registration with Fabric CA failed with error: ${error}`) + logger.info(`Wallet Setup: Sucessful ${secret}`); + } catch (error) { + const registeredUser = `Identity '${userName}' is already `; + if ( + !userPwd || + !( + error.message.includes("Identity ") && + error.message.includes(userName) && + error.message.includes(" is already registered") + ) + ) { + throw new Error( + `user ${userName} registration with Fabric CA failed with error: ${error}`, + ); } else { try { enrollment = await ca.enroll({ enrollmentID: userName, - enrollmentSecret: userPwd - }) - enrollmentDone = true + enrollmentSecret: userPwd, + }); + enrollmentDone = true; } catch (error) { - throw new Error(`user ${userName} registration/enrollment with Fabric CA failed with error: ${error}`) + throw new Error( + `user ${userName} registration/enrollment with Fabric CA failed with error: ${error}`, + ); } } } @@ -147,26 +165,25 @@ const walletSetup = async ( if (!enrollmentDone) { enrollment = await ca.enroll({ enrollmentID: userName, - enrollmentSecret: secret - }) + enrollmentSecret: secret, + }); } const x509Identity = { credentials: { certificate: enrollment.certificate, - privateKey: enrollment.key.toBytes() + privateKey: enrollment.key.toBytes(), }, mspId: mspId, - type: 'X.509' - } - await wallet.put(userName, x509Identity) - } - else { - logger.debug(`Identity ${userName} already exists.\n`) + type: "X.509", + }; + await wallet.put(userName, x509Identity); + } else { + logger.debug(`Identity ${userName} already exists.\n`); } - return wallet -} + return wallet; +}; const enrollAndRecordWalletIdentity = async ( userName: string, @@ -174,32 +191,41 @@ const enrollAndRecordWalletIdentity = async ( networkName: string, isNetworkAdmin: boolean = false, isIINAgent: boolean = false, - logger: any = console + logger: any = console, ) => { - const net = getNetworkConfig(networkName) - const ccpPath = path.resolve(__dirname, net.connProfilePath) - const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8')) - logger.info(net) - - const wallet = await walletSetup(networkName, ccp, net.mspId, userName, userPwd, isNetworkAdmin, isIINAgent, true) - saveUserCertToFile(userName, networkName) + const net = getNetworkConfig(networkName); + const ccpPath = path.resolve(__dirname, net.connProfilePath); + const ccp = JSON.parse(fs.readFileSync(ccpPath, "utf8")); + logger.info(net); - return wallet -} + const wallet = await walletSetup( + networkName, + ccp, + net.mspId, + userName, + userPwd, + isNetworkAdmin, + isIINAgent, + true, + ); + saveUserCertToFile(userName, networkName); + + return wallet; +}; const getCurrentNetworkCredentialPath = (networkName: string): string => { const credentialsPath = process.env.MEMBER_CREDENTIAL_FOLDER ? path.resolve(__dirname, process.env.MEMBER_CREDENTIAL_FOLDER, networkName) - : path.join(__dirname, '../data', 'credentials', networkName) - return credentialsPath -} + : path.join(__dirname, "../data", "credentials", networkName); + return credentialsPath; +}; const getCredentialPath = (): string => { const credentialsPath = process.env.MEMBER_CREDENTIAL_FOLDER ? path.resolve(__dirname, process.env.MEMBER_CREDENTIAL_FOLDER) - : path.join(__dirname, '../data', 'credentials') - return credentialsPath -} + : path.join(__dirname, "../data", "credentials"); + return credentialsPath; +}; const generateAccessControl = async ( channel: string, @@ -209,7 +235,7 @@ const generateAccessControl = async ( templatePath: string, username: string, mspId = global.__DEFAULT_MSPID__, - logger: any = console + logger: any = console, ): Promise => { const { wallet } = await fabricHelper({ channel, @@ -217,44 +243,42 @@ const generateAccessControl = async ( connProfilePath, networkName, logger, - mspId - }) + mspId, + }); const templateJSON = JSON.parse( - Buffer.from(fs.readFileSync(templatePath)).toString() - ) + Buffer.from(fs.readFileSync(templatePath)).toString(), + ); const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, username) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, username), + ); if (keyCertError) { logger.error( - 'Error fetching key and certificate from network', - keyCertError - ) + "Error fetching key and certificate from network", + keyCertError, + ); } - const updatedRules = templateJSON.rules.map(rule => { - if (rule.principalType == 'ca') { - rule.principal = mspId - } else if (rule.principalType == 'certificate') { - rule.principal = keyCert.cert + const updatedRules = templateJSON.rules.map((rule) => { + if (rule.principalType == "ca") { + rule.principal = mspId; + } else if (rule.principalType == "certificate") { + rule.principal = keyCert.cert; } else { - logger.error( - 'Error Invalid Principal Type in template file' - ) + logger.error("Error Invalid Principal Type in template file"); } - return rule - }) + return rule; + }); const accessControlJSON = { ...templateJSON, securityDomain: networkName, - rules: updatedRules - } - logger.debug(`AccessControlJSON ${JSON.stringify(accessControlJSON)}`) - const credentialsPath = getCurrentNetworkCredentialPath(networkName) + rules: updatedRules, + }; + logger.debug(`AccessControlJSON ${JSON.stringify(accessControlJSON)}`); + const credentialsPath = getCurrentNetworkCredentialPath(networkName); fs.writeFileSync( path.join(credentialsPath, `access-control.json`), - JSON.stringify(accessControlJSON) - ) -} + JSON.stringify(accessControlJSON), + ); +}; const generateVerificationPolicy = async ( channel, @@ -263,40 +287,40 @@ const generateVerificationPolicy = async ( networkName: string, templatePath: string, mspId = global.__DEFAULT_MSPID__, - logger: any = console + logger: any = console, ): Promise => { const templateJSON = JSON.parse( - Buffer.from(fs.readFileSync(templatePath)).toString() - ) + Buffer.from(fs.readFileSync(templatePath)).toString(), + ); const { gateway } = await fabricHelper({ channel, contractName, connProfilePath, networkName, mspId, - logger - }) - - const network = await gateway.getNetwork(channel) - const mspConfig = await getMspConfig(network, logger) - const criteria = Object.keys(formatMSP(mspConfig, networkName).members) - const newIdentifiers = templateJSON.identifiers.map(identifier => { - identifier.policy.criteria = criteria - return identifier - }) + logger, + }); + + const network = await gateway.getNetwork(channel); + const mspConfig = await getMspConfig(network, logger); + const criteria = Object.keys(formatMSP(mspConfig, networkName).members); + const newIdentifiers = templateJSON.identifiers.map((identifier) => { + identifier.policy.criteria = criteria; + return identifier; + }); const verificationPolicy = { ...templateJSON, identifiers: newIdentifiers, - securityDomain: networkName - } - logger.debug(`VerificationPolicyJSON ${JSON.stringify(verificationPolicy)}`) - const credentialsPath = getCurrentNetworkCredentialPath(networkName) - logger.debug('Credential Path', credentialsPath) + securityDomain: networkName, + }; + logger.debug(`VerificationPolicyJSON ${JSON.stringify(verificationPolicy)}`); + const credentialsPath = getCurrentNetworkCredentialPath(networkName); + logger.debug("Credential Path", credentialsPath); fs.writeFileSync( path.join(credentialsPath, `verification-policy.json`), - JSON.stringify(verificationPolicy) - ) -} + JSON.stringify(verificationPolicy), + ); +}; const generateMembership = async ( channel: string, @@ -305,7 +329,7 @@ const generateMembership = async ( networkName: string, mspId = global.__DEFAULT_MSPID__, logger: any = console, - iinAgent: boolean = false + iinAgent: boolean = false, ): Promise => { const { gateway } = await fabricHelper({ channel, @@ -313,211 +337,241 @@ const generateMembership = async ( connProfilePath, networkName, mspId, - logger - }) + logger, + }); - const network = await gateway.getNetwork(channel) - const mspConfig = await getMspConfig(network, logger) - const membershipJSON = formatMSP(mspConfig, networkName) - const membershipJSONStr = JSON.stringify(membershipJSON) - logger.debug(`membershipJSON: ${membershipJSONStr}`) + const network = await gateway.getNetwork(channel); + const mspConfig = await getMspConfig(network, logger); + const membershipJSON = formatMSP(mspConfig, networkName); + const membershipJSONStr = JSON.stringify(membershipJSON); + logger.debug(`membershipJSON: ${membershipJSONStr}`); - const credentialsPath = getCurrentNetworkCredentialPath(networkName) - logger.debug(`Credentials Path: ${credentialsPath}`) + const credentialsPath = getCurrentNetworkCredentialPath(networkName); + logger.debug(`Credentials Path: ${credentialsPath}`); if (!fs.existsSync(credentialsPath)) { - logger.debug(`Creating directory`) - fs.mkdirSync(credentialsPath, { recursive: true }) + logger.debug(`Creating directory`); + fs.mkdirSync(credentialsPath, { recursive: true }); } fs.writeFileSync( path.join(credentialsPath, `membership.json`), - membershipJSONStr - ) + membershipJSONStr, + ); if (iinAgent) { // Generate protobufs and attestations for all other networks that have IIN Agents - const credentialFolderPath = getCredentialPath() + const credentialFolderPath = getCredentialPath(); const otherNetworkNames = fs .readdirSync(credentialFolderPath, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .filter(item => item.name.startsWith('network')) // HACK until we add IIN Agents for Corda networks - .map(item => item.name) + .filter((dirent) => dirent.isDirectory()) + .filter((item) => item.name.startsWith("network")) // HACK until we add IIN Agents for Corda networks + .map((item) => item.name); // Reorder the array so that the local network is the first element // We need to record local membership before recording other networks' memberships - otherNetworkNames.splice(otherNetworkNames.indexOf(networkName), 1) + otherNetworkNames.splice(otherNetworkNames.indexOf(networkName), 1); if (otherNetworkNames.length > 0) { // Convert membership object to protobuf - let membershipProto = new membership_pb.Membership() - membershipProto.setSecuritydomain(membershipJSON.securityDomain) - Object.keys(membershipJSON.members).forEach( (memberName, index) => { - const certInfo = membershipJSON.members[memberName] - let memberProto = new membership_pb.Member() - memberProto.setType(certInfo.type) - memberProto.setValue(certInfo.value) - membershipProto.getMembersMap().set(memberName, memberProto) - }) + const membershipProto = new membership_pb.Membership(); + membershipProto.setSecuritydomain(membershipJSON.securityDomain); + Object.keys(membershipJSON.members).forEach((memberName, index) => { + const certInfo = membershipJSON.members[memberName]; + const memberProto = new membership_pb.Member(); + memberProto.setType(certInfo.type); + memberProto.setValue(certInfo.value); + membershipProto.getMembersMap().set(memberName, memberProto); + }); // For every other network, generate a counter attested membership set - const serializedMembership = membershipProto.serializeBinary() - const serializedMembershipBase64 = Buffer.from(serializedMembership).toString('base64') - const nonce = 'j849j94j40f440fkfjkld0e043' // Some random string - const membershipBase64WithNonce = serializedMembershipBase64 + nonce + const serializedMembership = membershipProto.serializeBinary(); + const serializedMembershipBase64 = + Buffer.from(serializedMembership).toString("base64"); + const nonce = "j849j94j40f440fkfjkld0e043"; // Some random string + const membershipBase64WithNonce = serializedMembershipBase64 + nonce; // Get wallet key and cert for this network's IIN Agent - const localWallet = await getWalletForNetwork(networkName) - const localKeyCert = await getKeyAndCertForRemoteRequestbyUserName(localWallet, 'iinagent') + const localWallet = await getWalletForNetwork(networkName); + const localKeyCert = await getKeyAndCertForRemoteRequestbyUserName( + localWallet, + "iinagent", + ); // Sign using wallet identity - let securityDomainMember = new iin_agent_pb.SecurityDomainMemberIdentity() - securityDomainMember.setSecurityDomain(membershipJSON.securityDomain) - securityDomainMember.setMemberId(Object.keys(membershipJSON.members)[0]) - let localAttestation = new iin_agent_pb.Attestation() - localAttestation.setUnitIdentity(securityDomainMember) - localAttestation.setCertificate(localKeyCert.cert) - const localSig = InteroperableHelper.signMessage(membershipBase64WithNonce, localKeyCert.key.toBytes()) - localAttestation.setSignature(localSig) - localAttestation.setNonce(nonce) - let attestedMembershipSet = new iin_agent_pb.CounterAttestedMembership.AttestedMembershipSet() - attestedMembershipSet.setMembership(serializedMembershipBase64) - attestedMembershipSet.setAttestationsList( [ localAttestation ] ) - const serializedAttestedMembershipSet = attestedMembershipSet.serializeBinary() - const serializedttestedMembershipSetBase64 = Buffer.from(serializedAttestedMembershipSet).toString('base64') - const serializedttestedMembershipSetBase64WithNonce = serializedttestedMembershipSetBase64 + nonce + const securityDomainMember = + new iin_agent_pb.SecurityDomainMemberIdentity(); + securityDomainMember.setSecurityDomain(membershipJSON.securityDomain); + securityDomainMember.setMemberId(Object.keys(membershipJSON.members)[0]); + const localAttestation = new iin_agent_pb.Attestation(); + localAttestation.setUnitIdentity(securityDomainMember); + localAttestation.setCertificate(localKeyCert.cert); + const localSig = InteroperableHelper.signMessage( + membershipBase64WithNonce, + localKeyCert.key.toBytes(), + ); + localAttestation.setSignature(localSig); + localAttestation.setNonce(nonce); + const attestedMembershipSet = + new iin_agent_pb.CounterAttestedMembership.AttestedMembershipSet(); + attestedMembershipSet.setMembership(serializedMembershipBase64); + attestedMembershipSet.setAttestationsList([localAttestation]); + const serializedAttestedMembershipSet = + attestedMembershipSet.serializeBinary(); + const serializedttestedMembershipSetBase64 = Buffer.from( + serializedAttestedMembershipSet, + ).toString("base64"); + const serializedttestedMembershipSetBase64WithNonce = + serializedttestedMembershipSetBase64 + nonce; for (const otherNetworkName of otherNetworkNames) { // Get wallet key and cert for other network's IIN Agent - const otherWallet = await getWalletForNetwork(otherNetworkName) - const otherKeyCert = await getKeyAndCertForRemoteRequestbyUserName(otherWallet, 'iinagent') + const otherWallet = await getWalletForNetwork(otherNetworkName); + const otherKeyCert = await getKeyAndCertForRemoteRequestbyUserName( + otherWallet, + "iinagent", + ); // Sign using wallet identity - let otherSecurityDomainMember = new iin_agent_pb.SecurityDomainMemberIdentity() - otherSecurityDomainMember.setSecurityDomain(otherNetworkName) - otherSecurityDomainMember.setMemberId(getNetworkConfig(otherNetworkName).mspId) - let otherAttestation = new iin_agent_pb.Attestation() - otherAttestation.setUnitIdentity(otherSecurityDomainMember) - otherAttestation.setCertificate(otherKeyCert.cert) - const otherSig = InteroperableHelper.signMessage(serializedttestedMembershipSetBase64WithNonce, otherKeyCert.key.toBytes()) - otherAttestation.setSignature(otherSig) - otherAttestation.setNonce(nonce) + const otherSecurityDomainMember = + new iin_agent_pb.SecurityDomainMemberIdentity(); + otherSecurityDomainMember.setSecurityDomain(otherNetworkName); + otherSecurityDomainMember.setMemberId( + getNetworkConfig(otherNetworkName).mspId, + ); + const otherAttestation = new iin_agent_pb.Attestation(); + otherAttestation.setUnitIdentity(otherSecurityDomainMember); + otherAttestation.setCertificate(otherKeyCert.cert); + const otherSig = InteroperableHelper.signMessage( + serializedttestedMembershipSetBase64WithNonce, + otherKeyCert.key.toBytes(), + ); + otherAttestation.setSignature(otherSig); + otherAttestation.setNonce(nonce); // Generate chaincode argument and save it in a file - let counterAttestedMembership = new iin_agent_pb.CounterAttestedMembership() - counterAttestedMembership.setAttestedMembershipSet(serializedttestedMembershipSetBase64) - counterAttestedMembership.setAttestationsList( [ otherAttestation ] ) + const counterAttestedMembership = + new iin_agent_pb.CounterAttestedMembership(); + counterAttestedMembership.setAttestedMembershipSet( + serializedttestedMembershipSetBase64, + ); + counterAttestedMembership.setAttestationsList([otherAttestation]); fs.writeFileSync( - path.join(credentialsPath, `attested-membership-${otherNetworkName}.proto.serialized`), - Buffer.from(counterAttestedMembership.serializeBinary()).toString('base64') - ) + path.join( + credentialsPath, + `attested-membership-${otherNetworkName}.proto.serialized`, + ), + Buffer.from(counterAttestedMembership.serializeBinary()).toString( + "base64", + ), + ); } } } - return membershipJSON -} + return membershipJSON; +}; const formatMSP = (mspConfig: MspConfig, networkId: string) => { - const memberObject = { members: {}, securityDomain: networkId } + const memberObject = { members: {}, securityDomain: networkId }; Object.entries(mspConfig).forEach(([name, value], _) => { // const cert = Certificate.fromPEM(Buffer.from(value.root_certs[0], 'base64')) memberObject.members[name] = { - type: 'ca', - value: Buffer.from(value.root_certs[0], 'base64').toString('utf8') - } - }) - return memberObject -} + type: "ca", + value: Buffer.from(value.root_certs[0], "base64").toString("utf8"), + }; + }); + return memberObject; +}; type MspConfig = { - [key: string]: { admins: any; root_certs: any; name: string } -} + [key: string]: { admins: any; root_certs: any; name: string }; +}; const getMspConfig = async ( network, - logger: any = console + logger: any = console, ): Promise => { - const mspConfigs = network.channel.getMspids() - const orgMspConfig = {} - logger.debug(mspConfigs) - logger.debug(network.channel.getMsp(mspConfigs[0])) - - mspConfigs.forEach(mspId => { - if (mspId !== 'OrdererMSP') { - logger.info('Getting MSP Info for org with MSP ID: ' + mspId + '.') - const mspConfig = network.getChannel().getMsp(mspId) - delete mspConfig.id + const mspConfigs = network.channel.getMspids(); + const orgMspConfig = {}; + logger.debug(mspConfigs); + logger.debug(network.channel.getMsp(mspConfigs[0])); + + mspConfigs.forEach((mspId) => { + if (mspId !== "OrdererMSP") { + logger.info("Getting MSP Info for org with MSP ID: " + mspId + "."); + const mspConfig = network.getChannel().getMsp(mspId); + delete mspConfig.id; if (Array.isArray(mspConfig.admins)) { for (let i = 0; i < mspConfig.admins.length; i++) { mspConfig.admins[i] = Buffer.from(mspConfig.admins[i]).toString( - 'base64' - ) + "base64", + ); } } else if (mspConfig.admins.length === 0) { - mspConfig.admins = [] + mspConfig.admins = []; } else { - mspConfig.admins = [Buffer.from(mspConfig.admins).toString('base64')] + mspConfig.admins = [Buffer.from(mspConfig.admins).toString("base64")]; } if (Array.isArray(mspConfig.rootCerts)) { for (let i = 0; i < mspConfig.rootCerts.length; i++) { mspConfig.rootCerts[i] = Buffer.from(mspConfig.rootCerts[i]).toString( - 'base64' - ) + "base64", + ); } } else if (mspConfig.rootCerts.length === 0) { - mspConfig.rootCerts = [] + mspConfig.rootCerts = []; } else { mspConfig.rootCerts = [ - Buffer.from(mspConfig.rootCerts).toString('base64') - ] + Buffer.from(mspConfig.rootCerts).toString("base64"), + ]; } - mspConfig.root_certs = mspConfig.rootCerts - delete mspConfig.rootCerts + mspConfig.root_certs = mspConfig.rootCerts; + delete mspConfig.rootCerts; if (Array.isArray(mspConfig.intermediateCerts)) { for (let i = 0; i < mspConfig.intermediateCerts.length; i++) { mspConfig.intermediateCerts[i] = Buffer.from( - mspConfig.intermediateCerts[i] - ).toString('base64') + mspConfig.intermediateCerts[i], + ).toString("base64"); } } else if (mspConfig.intermediateCerts.length === 0) { - mspConfig.intermediateCerts = [] + mspConfig.intermediateCerts = []; } else { mspConfig.intermediateCerts = [ - Buffer.from(mspConfig.intermediateCerts).toString('base64') - ] + Buffer.from(mspConfig.intermediateCerts).toString("base64"), + ]; } - mspConfig.intermediate_certs = mspConfig.intermediateCerts - delete mspConfig.intermediateCerts + mspConfig.intermediate_certs = mspConfig.intermediateCerts; + delete mspConfig.intermediateCerts; if (Array.isArray(mspConfig.tlsRootCerts)) { for (let i = 0; i < mspConfig.tlsRootCerts.length; i++) { mspConfig.tlsRootCerts[i] = Buffer.from( - mspConfig.tlsRootCerts[i] - ).toString('base64') + mspConfig.tlsRootCerts[i], + ).toString("base64"); } } else if (mspConfig.tlsRootCerts.length === 0) { - mspConfig.tlsRootCerts = [] + mspConfig.tlsRootCerts = []; } else { mspConfig.tlsRootCerts = [ - Buffer.from(mspConfig.tlsRootCerts).toString('base64') - ] + Buffer.from(mspConfig.tlsRootCerts).toString("base64"), + ]; } - mspConfig.tls_root_certs = mspConfig.tlsRootCerts - delete mspConfig.tlsRootCerts + mspConfig.tls_root_certs = mspConfig.tlsRootCerts; + delete mspConfig.tlsRootCerts; if (Array.isArray(mspConfig.tlsIntermediateCerts)) { for (let i = 0; i < mspConfig.tlsIntermediateCerts.length; i++) { mspConfig.tlsIntermediateCerts[i] = Buffer.from( - mspConfig.tlsIntermediateCerts[i] - ).toString('base64') + mspConfig.tlsIntermediateCerts[i], + ).toString("base64"); } } else if (mspConfig.tlsIntermediateCerts.length === 0) { - mspConfig.tlsIntermediateCerts = [] + mspConfig.tlsIntermediateCerts = []; } else { mspConfig.tlsIntermediateCerts = [ - Buffer.from(mspConfig.tlsIntermediateCerts).toString('base64') - ] + Buffer.from(mspConfig.tlsIntermediateCerts).toString("base64"), + ]; } - mspConfig.tls_intermediate_certs = mspConfig.tlsIntermediateCerts - delete mspConfig.tlsIntermediateCerts - orgMspConfig[mspId] = mspConfig + mspConfig.tls_intermediate_certs = mspConfig.tlsIntermediateCerts; + delete mspConfig.tlsIntermediateCerts; + orgMspConfig[mspId] = mspConfig; } - }) - return orgMspConfig -} + }); + return orgMspConfig; +}; async function fabricHelper({ channel, @@ -527,57 +581,67 @@ async function fabricHelper({ mspId = global.__DEFAULT_MSPID__, logger = console, discoveryEnabled = true, - userString = '', - userPwd = '', - registerUser = true + userString = "", + userPwd = "", + registerUser = true, }: { - channel: string - contractName: string - connProfilePath: string - networkName: string - mspId?: string - discoveryEnabled?: boolean - logger?: any - userString?: string - userPwd?: string - registerUser?: boolean + channel: string; + contractName: string; + connProfilePath: string; + networkName: string; + mspId?: string; + discoveryEnabled?: boolean; + logger?: any; + userString?: string; + userPwd?: string; + registerUser?: boolean; }): Promise<{ gateway: Gateway; contract: Contract; wallet: any }> { // load the network configuration - const ccpPath = path.resolve(__dirname, connProfilePath) - const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8')) + const ccpPath = path.resolve(__dirname, connProfilePath); + const ccp = JSON.parse(fs.readFileSync(ccpPath, "utf8")); // Create a new file system based wallet for managing identities. // const walletPath = process.env.WALLET_PATH // ? process.env.WALLET_PATH // : path.join(__dirname, '../', `wallet-${networkName}`) if (!userString) { - userString = `user1` - userPwd = `user1pw` + userString = `user1`; + userPwd = `user1pw`; } - const wallet = await walletSetup(networkName, ccp, mspId, userString, userPwd, false, false, registerUser, logger) + const wallet = await walletSetup( + networkName, + ccp, + mspId, + userString, + userPwd, + false, + false, + registerUser, + logger, + ); // Check to see if we've already enrolled the user. - const identity = await wallet.get(userString) + const identity = await wallet.get(userString); if (!identity) { logger.info( - `An identity for the user "${userString}" does not exist in the wallet` - ) - logger.info('Run the registerUser.ts application before retrying') + `An identity for the user "${userString}" does not exist in the wallet`, + ); + logger.info("Run the registerUser.ts application before retrying"); } // Create a new gateway for connecting to our peer node. - const gateway = new Gateway() + const gateway = new Gateway(); await gateway.connect(ccp, { wallet, identity: identity, discovery: { enabled: discoveryEnabled, - asLocalhost: process.env.LOCAL === 'false' ? false : true - } - }) - const network = await gateway.getNetwork(channel) + asLocalhost: process.env.LOCAL === "false" ? false : true, + }, + }); + const network = await gateway.getNetwork(channel); // Get the contract from the network. - const contract = network.getContract(contractName) - return { gateway, contract, wallet } + const contract = network.getContract(contractName); + return { gateway, contract, wallet }; } async function query( @@ -586,16 +650,14 @@ async function query( networkName: string, mspId = global.__DEFAULT_MSPID__, logger: any = console, - userString = '', - registerUser = true + userString = "", + registerUser = true, ): Promise { - logger.debug('Running invoke on fabric network') + logger.debug("Running invoke on fabric network"); try { logger.debug( - `QUERY: ${JSON.stringify( - invocationSpec - )} connProfilePath: ${connProfilePath} networkName ${networkName} ` - ) + `QUERY: ${JSON.stringify(invocationSpec)} connProfilePath: ${connProfilePath} networkName ${networkName} `, + ); const { contract, gateway } = await fabricHelper({ channel: invocationSpec.channel, contractName: invocationSpec.contractName, @@ -604,21 +666,24 @@ async function query( mspId: mspId, logger: logger, userString: userString, - registerUser: registerUser - }) - const read = await contract.evaluateTransaction(invocationSpec.ccFunc, ...invocationSpec.args) - const state = Buffer.from(read).toString() + registerUser: registerUser, + }); + const read = await contract.evaluateTransaction( + invocationSpec.ccFunc, + ...invocationSpec.args, + ); + const state = Buffer.from(read).toString(); if (state) { - logger.debug(`State From Network:`, state) + logger.debug(`State From Network:`, state); } else { - logger.debug(`No State from network`) + logger.debug(`No State from network`); } // Disconnect from the gateway. - await gateway.disconnect() - return state + await gateway.disconnect(); + return state; } catch (error) { - logger.error(`Failed to submit transaction: ${error}`) - throw new Error(error) + logger.error(`Failed to submit transaction: ${error}`); + throw new Error(error); } } @@ -628,10 +693,10 @@ async function invoke( networkName: string, mspId = global.__DEFAULT_MSPID__, logger: any = console, - userString = '', - registerUser = true + userString = "", + registerUser = true, ): Promise { - logger.debug('Running invoke on fabric network') + logger.debug("Running invoke on fabric network"); try { const { contract, gateway } = await fabricHelper({ channel: invocationSpec.channel, @@ -641,62 +706,62 @@ async function invoke( mspId: mspId, logger: logger, userString: userString, - registerUser: registerUser - }) + registerUser: registerUser, + }); logger.debug( - `CCFunc: ${invocationSpec.ccFunc} 'CCArgs: ${JSON.stringify(invocationSpec.args)}` - ) - const read = await contract.submitTransaction(invocationSpec.ccFunc, ...invocationSpec.args) - const state = Buffer.from(read).toString() + `CCFunc: ${invocationSpec.ccFunc} 'CCArgs: ${JSON.stringify(invocationSpec.args)}`, + ); + const read = await contract.submitTransaction( + invocationSpec.ccFunc, + ...invocationSpec.args, + ); + const state = Buffer.from(read).toString(); if (state) { - logger.debug(`Response From Network: ${state}`) + logger.debug(`Response From Network: ${state}`); } else { - logger.debug('No Response from network') + logger.debug("No Response from network"); } // Disconnect from the gateway. - await gateway.disconnect() - return state + await gateway.disconnect(); + return state; } catch (error) { - console.error(`Failed to submit transaction: ${error}`) - throw new Error(error) + console.error(`Failed to submit transaction: ${error}`); + throw new Error(error); } } const getKeyAndCertForRemoteRequestbyUserName = async ( wallet: any, - username: string + username: string, ): Promise<{ key: ICryptoKey; cert: any }> => { if (!wallet) { - throw new Error('No wallet passed') + throw new Error("No wallet passed"); } if (!username) { - throw new Error('No username passed') + throw new Error("No username passed"); } - const identity = await wallet.get(username) + const identity = await wallet.get(username); if (!identity) { throw new Error( - 'Identity for username ' + username + ' not present in wallet' - ) + "Identity for username " + username + " not present in wallet", + ); } // Assume the identity is of type 'fabric-network.X509Identity' const privKey = Utils.newCryptoSuite().createKeyFromRaw( - identity.credentials.privateKey - ) - return { key: privKey, cert: identity.credentials.certificate } -} + identity.credentials.privateKey, + ); + return { key: privKey, cert: identity.credentials.certificate }; +}; -const getWalletForNetwork = async ( - networkName: string, -) => { +const getWalletForNetwork = async (networkName: string) => { const walletPath = process.env.WALLET_PATH ? process.env.WALLET_PATH - : path.join(__dirname, '../', `wallet-${networkName}`) - - const wallet = await Wallets.newFileSystemWallet(walletPath) - return wallet -} + : path.join(__dirname, "../", `wallet-${networkName}`); + const wallet = await Wallets.newFileSystemWallet(walletPath); + return wallet; +}; export { getUserCertBase64, @@ -710,5 +775,5 @@ export { getKeyAndCertForRemoteRequestbyUserName, getCredentialPath, getCurrentNetworkCredentialPath, - generateVerificationPolicy -} + generateVerificationPolicy, +}; diff --git a/weaver/samples/fabric/fabric-cli/src/helpers/helpers.ts b/weaver/samples/fabric/fabric-cli/src/helpers/helpers.ts index e914a9aeba..ecf21d0e61 100644 --- a/weaver/samples/fabric/fabric-cli/src/helpers/helpers.ts +++ b/weaver/samples/fabric/fabric-cli/src/helpers/helpers.ts @@ -4,42 +4,54 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { GluegunCommand } from 'gluegun' -import { Toolbox } from 'gluegun/build/types/domain/toolbox' -import { GluegunPrint } from 'gluegun/build/types/toolbox/print-types' -import { getKeyAndCertForRemoteRequestbyUserName, fabricHelper, invoke, query, InvocationSpec } from './fabric-functions' -import { AssetPledge } from "@hyperledger/cacti-weaver-protos-js/common/asset_transfer_pb" -import { InteroperableHelper } from '@hyperledger/cacti-weaver-sdk-fabric' -import * as crypto from 'crypto' -import { promisify } from 'util' -import * as fs from 'fs' -import * as path from 'path' -import * as dotenv from 'dotenv' -import logger from './logger' -dotenv.config({ path: path.resolve(__dirname, '../../.env') }) - +import { GluegunCommand } from "gluegun"; +import { Toolbox } from "gluegun/build/types/domain/toolbox"; +import { GluegunPrint } from "gluegun/build/types/toolbox/print-types"; +import { + getKeyAndCertForRemoteRequestbyUserName, + fabricHelper, + invoke, + query, + InvocationSpec, +} from "./fabric-functions"; +import { AssetPledge } from "@hyperledger/cacti-weaver-protos-js/common/asset_transfer_pb"; +import { InteroperableHelper } from "@hyperledger/cacti-weaver-sdk-fabric"; +import * as crypto from "crypto"; +import { promisify } from "util"; +import * as fs from "fs"; +import * as path from "path"; +import * as dotenv from "dotenv"; +import logger from "./logger"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); // UPDATE Following if new env variable or config variable is added. // Valid keys for .env const validKeys = [ - 'DEFAULT_CHANNEL', - 'DEFAULT_CHAINCODE', - 'MEMBER_CREDENTIAL_FOLDER', - 'LOCAL', - 'DEFAULT_APPLICATION_CHAINCODE', - 'CONFIG_PATH', - 'REMOTE_CONFIG_PATH', - 'CHAINCODE_PATH' -] + "DEFAULT_CHANNEL", + "DEFAULT_CHAINCODE", + "MEMBER_CREDENTIAL_FOLDER", + "LOCAL", + "DEFAULT_APPLICATION_CHAINCODE", + "CONFIG_PATH", + "REMOTE_CONFIG_PATH", + "CHAINCODE_PATH", +]; // Valid keys for config -const configKeys = ['connProfilePath', 'relayEndpoint', 'mspId', 'channelName', 'chaincode', 'aclPolicyPrincipalType'] +const configKeys = [ + "connProfilePath", + "relayEndpoint", + "mspId", + "channelName", + "chaincode", + "aclPolicyPrincipalType", +]; const signMessage = (message, privateKey) => { - const sign = crypto.createSign('sha256') - sign.write(message) - sign.end() - return sign.sign(privateKey) -} + const sign = crypto.createSign("sha256"); + sign.write(message); + sign.end(); + return sign.sign(privateKey); +}; // Basic function to add assets to network, it assumes function is CreateAsset // TODO: Pass function name as parameter @@ -53,33 +65,31 @@ const addAssets = ({ contractName, ccFunc, ccType, - logger + logger, }: { - dataFilePath: string - networkName: string - connProfilePath: string - invocationSpec?: InvocationSpec - mspId?: string - channelName?: string - contractName?: string - ccFunc?: string - ccType: string - logger?: any + dataFilePath: string; + networkName: string; + connProfilePath: string; + invocationSpec?: InvocationSpec; + mspId?: string; + channelName?: string; + contractName?: string; + ccFunc?: string; + ccType: string; + logger?: any; }): void => { - const filepath = path.resolve(dataFilePath) - const data = JSON.parse(fs.readFileSync(filepath).toString()) - const valuesList = Object.entries(data) + const filepath = path.resolve(dataFilePath); + const data = JSON.parse(fs.readFileSync(filepath).toString()); + const valuesList = Object.entries(data); valuesList.forEach(async (item: [string, string]) => { const currentQuery = invocationSpec ? invocationSpec : { channel: channelName, - contractName: contractName - ? contractName - : 'simpleasset', - ccFunc: '', - args: [] - } + contractName: contractName ? contractName : "simpleasset", + ccFunc: "", + args: [], + }; const { gateway, contract, wallet } = await fabricHelper({ channel: channelName, @@ -87,41 +97,58 @@ const addAssets = ({ connProfilePath: connProfilePath, networkName: networkName, mspId: mspId, - userString: item[1]['owner'], - registerUser: false - }) - const userId = await wallet.get(item[1]['owner']) - const userCert = Buffer.from((userId).credentials.certificate).toString('base64') - - if (ccType == 'bond') { - currentQuery.ccFunc = 'CreateAsset' - currentQuery.args = [...currentQuery.args, item[1]['assetType'], item[1]['id'], userCert, item[1]['issuer'], item[1]['facevalue'], item[1]['maturitydate']] - } else if (ccType == 'token') { - currentQuery.ccFunc = 'IssueTokenAssets' - currentQuery.args = [...currentQuery.args, item[1]['tokenassettype'], item[1]['numunits'], userCert] + userString: item[1]["owner"], + registerUser: false, + }); + const userId = await wallet.get(item[1]["owner"]); + const userCert = Buffer.from(userId.credentials.certificate).toString( + "base64", + ); + + if (ccType == "bond") { + currentQuery.ccFunc = "CreateAsset"; + currentQuery.args = [ + ...currentQuery.args, + item[1]["assetType"], + item[1]["id"], + userCert, + item[1]["issuer"], + item[1]["facevalue"], + item[1]["maturitydate"], + ]; + } else if (ccType == "token") { + currentQuery.ccFunc = "IssueTokenAssets"; + currentQuery.args = [ + ...currentQuery.args, + item[1]["tokenassettype"], + item[1]["numunits"], + userCert, + ]; } else { - throw new Error(`Unrecognized asset category: ${ccType}`) + throw new Error(`Unrecognized asset category: ${ccType}`); } - console.log(currentQuery) + console.log(currentQuery); try { - const read = await contract.submitTransaction(currentQuery.ccFunc, ...currentQuery.args) - const state = Buffer.from(read).toString() + const read = await contract.submitTransaction( + currentQuery.ccFunc, + ...currentQuery.args, + ); + const state = Buffer.from(read).toString(); if (state) { - logger.debug(`Response From Network: ${state}`) + logger.debug(`Response From Network: ${state}`); } else { - logger.debug('No Response from network') + logger.debug("No Response from network"); } // Disconnect from the gateway. - await gateway.disconnect() - return state + await gateway.disconnect(); + return state; } catch (error) { - console.error(`Failed to submit transaction: ${error}`) - throw new Error(error) + console.error(`Failed to submit transaction: ${error}`); + throw new Error(error); } - }) -} - + }); +}; // Basic function to pledge an asset in one network to another, it assumes function is PledgeAsset // TODO: Pass function name as parameter @@ -141,51 +168,51 @@ const pledgeAsset = async ({ assetOwner, assetRef, assetUnits, - logger + logger, }: { - dataFilePath: string - sourceNetworkName: string - destNetworkName: string - recipient: string - expirySecs: number - connProfilePath: string - invocationSpec?: InvocationSpec - mspId?: string - channelName?: string - contractName?: string - ccFunc?: string - ccType: string - assetOwner: string - assetRef: string - assetUnits: number - logger?: any + dataFilePath: string; + sourceNetworkName: string; + destNetworkName: string; + recipient: string; + expirySecs: number; + connProfilePath: string; + invocationSpec?: InvocationSpec; + mspId?: string; + channelName?: string; + contractName?: string; + ccFunc?: string; + ccType: string; + assetOwner: string; + assetRef: string; + assetUnits: number; + logger?: any; }): Promise => { - const filepath = path.resolve(dataFilePath) - const data = JSON.parse(fs.readFileSync(filepath).toString()) - let item + const filepath = path.resolve(dataFilePath); + const data = JSON.parse(fs.readFileSync(filepath).toString()); + let item; if (assetRef) { - item = data[assetRef] + item = data[assetRef]; if (!item) { - throw new Error(`Cannot find asset ref ${assetRef} in file ${filepath}`) + throw new Error(`Cannot find asset ref ${assetRef} in file ${filepath}`); } } else if (assetOwner) { - item = data[assetOwner] + item = data[assetOwner]; if (!item) { - throw new Error(`Cannot find asset owner ${assetOwner} in file ${filepath}`) + throw new Error( + `Cannot find asset owner ${assetOwner} in file ${filepath}`, + ); } } else { - throw new Error(`Neither asset owner nor reference is supplied`) + throw new Error(`Neither asset owner nor reference is supplied`); } const currentQuery = invocationSpec ? invocationSpec : { channel: channelName, - contractName: contractName - ? contractName - : 'simpleasset', - ccFunc: '', - args: [] - } + contractName: contractName ? contractName : "simpleasset", + ccFunc: "", + args: [], + }; const { gateway, contract, wallet } = await fabricHelper({ channel: channelName, @@ -193,110 +220,141 @@ const pledgeAsset = async ({ connProfilePath: connProfilePath, networkName: sourceNetworkName, mspId: mspId, - userString: item['owner'], - registerUser: false - }) - const recipientCert = getUserCertFromFile(recipient, destNetworkName) - const expirationTime = (Math.floor(Date.now()/1000 + expirySecs)).toString() - - if (ccType == 'bond') { - currentQuery.ccFunc = 'PledgeAsset' - currentQuery.args = [...currentQuery.args, item['assetType'], item['id'], destNetworkName, recipientCert, expirationTime] - } else if (ccType == 'token') { - currentQuery.ccFunc = 'PledgeTokenAsset' - currentQuery.args = [...currentQuery.args, item['tokenassettype'], '' + assetUnits, destNetworkName, recipientCert, expirationTime] + userString: item["owner"], + registerUser: false, + }); + const recipientCert = getUserCertFromFile(recipient, destNetworkName); + const expirationTime = Math.floor(Date.now() / 1000 + expirySecs).toString(); + + if (ccType == "bond") { + currentQuery.ccFunc = "PledgeAsset"; + currentQuery.args = [ + ...currentQuery.args, + item["assetType"], + item["id"], + destNetworkName, + recipientCert, + expirationTime, + ]; + } else if (ccType == "token") { + currentQuery.ccFunc = "PledgeTokenAsset"; + currentQuery.args = [ + ...currentQuery.args, + item["tokenassettype"], + "" + assetUnits, + destNetworkName, + recipientCert, + expirationTime, + ]; } else { - throw new Error(`Unrecognized/unsupported asset category: ${ccType}`) + throw new Error(`Unrecognized/unsupported asset category: ${ccType}`); } - console.log(currentQuery) + console.log(currentQuery); try { - const read = await contract.submitTransaction(currentQuery.ccFunc, ...currentQuery.args) - const state = Buffer.from(read).toString() + const read = await contract.submitTransaction( + currentQuery.ccFunc, + ...currentQuery.args, + ); + const state = Buffer.from(read).toString(); if (state) { - logger.debug(`Response From Network: ${state}`) + logger.debug(`Response From Network: ${state}`); } else { - logger.debug('No Response from network') + logger.debug("No Response from network"); } // Disconnect from the gateway. - await gateway.disconnect() - return state + await gateway.disconnect(); + return state; } catch (error) { - console.error(`Failed to submit transaction: ${error}`) - throw new Error(error) + console.error(`Failed to submit transaction: ${error}`); + throw new Error(error); } -} +}; // Used to obtain remote network user certificate from '${networkId}_UsersAndCerts.json' file. // This is called during Pledge to get the recipientCert, and during Claim to get the pledgerCert. -const getUserCertFromFile = ( - remoteUser: string, - remoteNetworkId: string -) => { - const usersAndCertsFile = remoteNetworkId + '_UsersAndCerts.json' +const getUserCertFromFile = (remoteUser: string, remoteNetworkId: string) => { + const usersAndCertsFile = remoteNetworkId + "_UsersAndCerts.json"; const credentialsPath = process.env.MEMBER_CREDENTIAL_FOLDER - ? path.resolve(__dirname, process.env.MEMBER_CREDENTIAL_FOLDER, '..') - : path.join(__dirname, '../data', 'credentials', '..') + ? path.resolve(__dirname, process.env.MEMBER_CREDENTIAL_FOLDER, "..") + : path.join(__dirname, "../data", "credentials", ".."); try { - const dirPath = path.resolve(credentialsPath, 'remoteNetworkUsers') - const filepath = path.resolve(dirPath, usersAndCertsFile) - const usersAndCertsJSON = JSON.parse(fs.readFileSync(filepath).toString()) - logger.debug(`credentialsPath: ${credentialsPath} and usersAndCertsFile: ${usersAndCertsFile}`) + const dirPath = path.resolve(credentialsPath, "remoteNetworkUsers"); + const filepath = path.resolve(dirPath, usersAndCertsFile); + const usersAndCertsJSON = JSON.parse(fs.readFileSync(filepath).toString()); + logger.debug( + `credentialsPath: ${credentialsPath} and usersAndCertsFile: ${usersAndCertsFile}`, + ); if (!usersAndCertsJSON[remoteUser]) { logger.error( - `User: ${remoteUser} does not exist in the file ${usersAndCertsFile}.` - ) - return '' + `User: ${remoteUser} does not exist in the file ${usersAndCertsFile}.`, + ); + return ""; } - logger.debug(`remoteUser: ${remoteUser} and certificate: ${usersAndCertsJSON[remoteUser]}`) - return usersAndCertsJSON[remoteUser] + logger.debug( + `remoteUser: ${remoteUser} and certificate: ${usersAndCertsJSON[remoteUser]}`, + ); + return usersAndCertsJSON[remoteUser]; } catch (err) { - logger.error(`User: ${remoteUser} does not exist in the file ${usersAndCertsFile}.`) - return '' + logger.error( + `User: ${remoteUser} does not exist in the file ${usersAndCertsFile}.`, + ); + return ""; } -} +}; // Used to store the network user certificate to the file '${networkId}_UsersAndCerts.json'. // This is used during Pledge to get the recipientCert, and during Claim to get the pledgerCert. -const saveUserCertToFile = ( - remoteUser: string, - remoteNetworkId: string -) => { - const usersAndCertsFile = remoteNetworkId + '_UsersAndCerts.json' - let usersAndCertsJSON = {} +const saveUserCertToFile = (remoteUser: string, remoteNetworkId: string) => { + const usersAndCertsFile = remoteNetworkId + "_UsersAndCerts.json"; + let usersAndCertsJSON = {}; const credentialsPath = process.env.MEMBER_CREDENTIAL_FOLDER - ? path.resolve(__dirname, process.env.MEMBER_CREDENTIAL_FOLDER, '..') - : path.join(__dirname, '../data', 'credentials', '..') - // Don't create the directory 'remoteNetworkUsers' inside 'data/credentials' since each entry there represents - // a network. Instead, create this directory inside 'data' itself. + ? path.resolve(__dirname, process.env.MEMBER_CREDENTIAL_FOLDER, "..") + : path.join(__dirname, "../data", "credentials", ".."); + // Don't create the directory 'remoteNetworkUsers' inside 'data/credentials' since each entry there represents + // a network. Instead, create this directory inside 'data' itself. try { - const dirPath = path.resolve(credentialsPath, 'remoteNetworkUsers') - const filepath = path.resolve(dirPath, usersAndCertsFile) - logger.debug(`credentialsPath: ${credentialsPath} and usersAndCertsFile: ${usersAndCertsFile}`) + const dirPath = path.resolve(credentialsPath, "remoteNetworkUsers"); + const filepath = path.resolve(dirPath, usersAndCertsFile); + logger.debug( + `credentialsPath: ${credentialsPath} and usersAndCertsFile: ${usersAndCertsFile}`, + ); if (!fs.existsSync(dirPath)) { - logger.debug(`Creating directory ${dirPath}`) - fs.mkdirSync(dirPath, { recursive: true }) + logger.debug(`Creating directory ${dirPath}`); + fs.mkdirSync(dirPath, { recursive: true }); } if (fs.existsSync(filepath)) { - logger.debug(`Reading contents of the file ${filepath}`) - usersAndCertsJSON = JSON.parse(fs.readFileSync(filepath).toString()) + logger.debug(`Reading contents of the file ${filepath}`); + usersAndCertsJSON = JSON.parse(fs.readFileSync(filepath).toString()); } - const remoteUserId = JSON.parse(fs.readFileSync(__dirname + '/../wallet-' + remoteNetworkId + '/' + remoteUser + '.id').toString()) - const remoteUserCertBase64 = Buffer.from(remoteUserId.credentials.certificate).toString('base64') + const remoteUserId = JSON.parse( + fs + .readFileSync( + __dirname + + "/../wallet-" + + remoteNetworkId + + "/" + + remoteUser + + ".id", + ) + .toString(), + ); + const remoteUserCertBase64 = Buffer.from( + remoteUserId.credentials.certificate, + ).toString("base64"); - usersAndCertsJSON[remoteUser] = remoteUserCertBase64 - fs.writeFileSync( - path.resolve(filepath), - JSON.stringify(usersAndCertsJSON) - ) + usersAndCertsJSON[remoteUser] = remoteUserCertBase64; + fs.writeFileSync(path.resolve(filepath), JSON.stringify(usersAndCertsJSON)); } catch (err) { - logger.error(`User: ${remoteUser} certificate cannot be saved to the file ${usersAndCertsFile}.`) + logger.error( + `User: ${remoteUser} certificate cannot be saved to the file ${usersAndCertsFile}.`, + ); } -} +}; // Basic function to query asset pledge details from a network, it assumes function is GetAssetPledgeStatus // TODO: Pass function name as parameter @@ -311,32 +369,30 @@ const getAssetPledgeDetails = async ({ mspId = global.__DEFAULT_MSPID__, ccFunc, pledgeId, - logger + logger, }: { - sourceNetworkName: string - pledger: string - pledgerCert: string - destNetworkName: string - recipient: string - recipientCert: string - invocationSpec?: InvocationSpec - mspId?: string - ccFunc?: string - pledgeId: string - logger?: any + sourceNetworkName: string; + pledger: string; + pledgerCert: string; + destNetworkName: string; + recipient: string; + recipientCert: string; + invocationSpec?: InvocationSpec; + mspId?: string; + ccFunc?: string; + pledgeId: string; + logger?: any; }): Promise => { - const netConfig = getNetworkConfig(sourceNetworkName) + const netConfig = getNetworkConfig(sourceNetworkName); const currentQuery = invocationSpec ? invocationSpec : { channel: netConfig.channelName, - contractName: netConfig.chaincode - ? netConfig.chaincode - : 'simpleasset', - ccFunc: '', - args: [] - } + contractName: netConfig.chaincode ? netConfig.chaincode : "simpleasset", + ccFunc: "", + args: [], + }; const { gateway, contract, wallet } = await fabricHelper({ channel: netConfig.channelName, @@ -345,92 +401,116 @@ const getAssetPledgeDetails = async ({ networkName: sourceNetworkName, mspId: netConfig.mspId, userString: pledger, - registerUser: false - }) + registerUser: false, + }); if (!pledgerCert) { - const pledgerId = JSON.parse(fs.readFileSync(__dirname + '/../wallet-' + sourceNetworkName + '/' + pledger + '.id').toString()) - pledgerCert = Buffer.from(pledgerId.credentials.certificate).toString('base64') + const pledgerId = JSON.parse( + fs + .readFileSync( + __dirname + "/../wallet-" + sourceNetworkName + "/" + pledger + ".id", + ) + .toString(), + ); + pledgerCert = Buffer.from(pledgerId.credentials.certificate).toString( + "base64", + ); } if (!recipientCert) { - const recipientId = JSON.parse(fs.readFileSync(__dirname + '/../wallet-' + destNetworkName + '/' + recipient + '.id').toString()) - recipientCert = Buffer.from(recipientId.credentials.certificate).toString('base64') + const recipientId = JSON.parse( + fs + .readFileSync( + __dirname + "/../wallet-" + destNetworkName + "/" + recipient + ".id", + ) + .toString(), + ); + recipientCert = Buffer.from(recipientId.credentials.certificate).toString( + "base64", + ); } - currentQuery.ccFunc = 'GetAssetPledgeStatus' - currentQuery.args = [...currentQuery.args, pledgeId, pledgerCert, destNetworkName, recipientCert] - console.log(currentQuery) + currentQuery.ccFunc = "GetAssetPledgeStatus"; + currentQuery.args = [ + ...currentQuery.args, + pledgeId, + pledgerCert, + destNetworkName, + recipientCert, + ]; + console.log(currentQuery); try { - const read = await contract.evaluateTransaction(currentQuery.ccFunc, ...currentQuery.args) - const state = Buffer.from(read).toString() + const read = await contract.evaluateTransaction( + currentQuery.ccFunc, + ...currentQuery.args, + ); + const state = Buffer.from(read).toString(); if (state) { - logger.debug(`Response From Network: ${state}`) + logger.debug(`Response From Network: ${state}`); } else { - logger.debug('No Response from network') + logger.debug("No Response from network"); } // Disconnect from the gateway. - await gateway.disconnect() - return state + await gateway.disconnect(); + return state; } catch (error) { - console.error(`Failed to submit transaction: ${error}`) - throw new Error(error) + console.error(`Failed to submit transaction: ${error}`); + throw new Error(error); } -} +}; // Basic function to query asset pledge details from a network, it assumes function is GetAssetPledgeDetails // TODO: Pass function name as parameter const getLocalAssetPledgeDetails = async ({ - sourceNetworkName, - pledgeId, - caller, - ccType, - ccFunc, - logger + sourceNetworkName, + pledgeId, + caller, + ccType, + ccFunc, + logger, }: { - sourceNetworkName: string - pledgeId: string - caller: string - ccType?: string - ccFunc?: string - logger?: any + sourceNetworkName: string; + pledgeId: string; + caller: string; + ccType?: string; + ccFunc?: string; + logger?: any; }): Promise => { - const netConfig = getNetworkConfig(sourceNetworkName) + const netConfig = getNetworkConfig(sourceNetworkName); - const currentQuery = { - channel: netConfig.channelName, - contractName: netConfig.chaincode - ? netConfig.chaincode - : 'simpleasset', - ccFunc: '', - args: [] - } + const currentQuery = { + channel: netConfig.channelName, + contractName: netConfig.chaincode ? netConfig.chaincode : "simpleasset", + ccFunc: "", + args: [], + }; - if (ccFunc) { - currentQuery.ccFunc = ccFunc - } else if (ccType && ccType == 'token') { - currentQuery.ccFunc = 'GetTokenAssetPledgeDetails' - } else { - currentQuery.ccFunc = 'GetAssetPledgeDetails' - } - currentQuery.args = [...currentQuery.args, pledgeId] - console.log(currentQuery) - try { - const pledgeDetails = await query(currentQuery, - netConfig.connProfilePath, - sourceNetworkName, - netConfig.mspId, - logger, - caller, - false - ) - const pledgeDetailBytes = Buffer.from(pledgeDetails, 'base64') - const pledgeDetailsProto = AssetPledge.deserializeBinary(pledgeDetailBytes) - return pledgeDetailsProto - } catch (error) { - console.error(`Failed to get pledge details: ${error}`) - throw new Error(error) - } -} + if (ccFunc) { + currentQuery.ccFunc = ccFunc; + } else if (ccType && ccType == "token") { + currentQuery.ccFunc = "GetTokenAssetPledgeDetails"; + } else { + currentQuery.ccFunc = "GetAssetPledgeDetails"; + } + currentQuery.args = [...currentQuery.args, pledgeId]; + console.log(currentQuery); + try { + const pledgeDetails = await query( + currentQuery, + netConfig.connProfilePath, + sourceNetworkName, + netConfig.mspId, + logger, + caller, + false, + ); + const pledgeDetailBytes = Buffer.from(pledgeDetails, "base64"); + const pledgeDetailsProto = AssetPledge.deserializeBinary(pledgeDetailBytes); + return pledgeDetailsProto; + } catch (error) { + console.error(`Failed to get pledge details: ${error}`); + throw new Error(error); + } +}; // Basic function to add data to network, it assumes function is Create // TODO: Pass function name as parameter @@ -440,37 +520,37 @@ const addData = ({ connProfilePath, invocationSpec, mspId = global.__DEFAULT_MSPID__, - logger + logger, }: { - filename: string - networkName: string - connProfilePath: string - invocationSpec?: InvocationSpec - mspId?: string - logger?: any + filename: string; + networkName: string; + connProfilePath: string; + invocationSpec?: InvocationSpec; + mspId?: string; + logger?: any; }): void => { - const filepath = path.resolve(__dirname, '..', 'data', filename) - const data = JSON.parse(fs.readFileSync(filepath).toString()) - const valuesList = Object.entries(data) + const filepath = path.resolve(__dirname, "..", "data", filename); + const data = JSON.parse(fs.readFileSync(filepath).toString()); + const valuesList = Object.entries(data); valuesList.forEach((item: [string, string]) => { const currentQuery = invocationSpec ? invocationSpec : { channel: process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL - : 'mychannel', + : "mychannel", contractName: process.env.DEFAULT_APPLICATION_CHAINCODE ? process.env.DEFAULT_APPLICATION_CHAINCODE - : 'simplestate', + : "simplestate", ccFunc: process.env.DEFAULT_APPLICATION_FUNC ? process.env.DEFAULT_APPLICATION_FUNC - : 'Create', - args: [] - } - currentQuery.args = [...currentQuery.args, item[0], item[1]] - invoke(currentQuery, connProfilePath, networkName, mspId, logger) - }) -} + : "Create", + args: [], + }; + currentQuery.args = [...currentQuery.args, item[0], item[1]]; + invoke(currentQuery, connProfilePath, networkName, mspId, logger); + }); +}; // Custom Command help is to generate the help text used when running --help on a command. // 1. If usage string is provided print usage section @@ -485,290 +565,350 @@ const commandHelp = ( usageString: string, optionsList: { name: string; description: string }[], command: GluegunCommand, - commandRoot: string[] + commandRoot: string[], ): void => { - print.info(command.description) - print.info('') + print.info(command.description); + print.info(""); // 1 if (usageString) { - print.info(toolbox.print.colors.bold('USAGE')) - print.info('') - print.info(usageString) - print.info('') + print.info(toolbox.print.colors.bold("USAGE")); + print.info(""); + print.info(usageString); + print.info(""); } // 2 if (exampleString) { - print.info(toolbox.print.colors.bold('EXAMPLE')) - print.info('') - print.info(`$ ${exampleString}`) - print.info('') + print.info(toolbox.print.colors.bold("EXAMPLE")); + print.info(""); + print.info(`$ ${exampleString}`); + print.info(""); } // 3 if (optionsList.length > 0) { // To calculate how long each title should be to make the formatting consistent const spaces = optionsList.reduce((acc, val) => { - const stringLength = val.name.length + const stringLength = val.name.length; if (stringLength > acc) { - return stringLength + return stringLength; } else { - return acc + return acc; } - }, 0) - print.info(toolbox.print.colors.bold('OPTIONS')) - print.info('') - optionsList.forEach(command => { - const val = spaces - command.name.length - const numberOfSpaces = val > 0 ? val : 0 + }, 0); + print.info(toolbox.print.colors.bold("OPTIONS")); + print.info(""); + optionsList.forEach((command) => { + const val = spaces - command.name.length; + const numberOfSpaces = val > 0 ? val : 0; toolbox.print.info( - `${command.name} ${Array(numberOfSpaces) - .fill('\xa0') - .join('')} ${command.description}` - ) - }) - print.info('') + `${command.name} ${Array(numberOfSpaces).fill("\xa0").join("")} ${command.description}`, + ); + }); + print.info(""); } // 4 - toolbox.print.info(toolbox.print.colors.bold('COMMANDS')) - toolbox.print.printCommands(toolbox, commandRoot) - toolbox.print.info('') -} + toolbox.print.info(toolbox.print.colors.bold("COMMANDS")); + toolbox.print.printCommands(toolbox, commandRoot); + toolbox.print.info(""); +}; // Custom Help is used as the default help when running --help on no commands. // filters out subcommands by using the root of each toplevel command and filters them out. When adding a command it will need to be added to the array to filter out. const customHelp = (toolbox: Toolbox): void => { - toolbox.print.info(toolbox.print.colors.bold('VERSION')) - toolbox.print.info('') + toolbox.print.info(toolbox.print.colors.bold("VERSION")); + toolbox.print.info(""); toolbox.print.info( - toolbox.print.colors.cyan(` fabric-cli/${toolbox.meta.version()}`) - ) - toolbox.print.info('') - toolbox.print.info(toolbox.print.colors.bold('COMMANDS')) - toolbox.print.info('') + toolbox.print.colors.cyan(` fabric-cli/${toolbox.meta.version()}`), + ); + toolbox.print.info(""); + toolbox.print.info(toolbox.print.colors.bold("COMMANDS")); + toolbox.print.info(""); // Filter out commands that shouldn't be listed const commandList = toolbox.plugin.commands .filter( - command => - !command.commandPath.includes('chaincode') && - !command.commandPath.includes('interop') && - !command.commandPath.includes('relay') && - !command.commandPath.includes('configure') && - !command.commandPath.includes('fabric-cli') && - !command.commandPath.includes('env') && - !command.commandPath.includes('helper') && - !command.commandPath.includes('config') && - !command.commandPath.includes('asset') + (command) => + !command.commandPath.includes("chaincode") && + !command.commandPath.includes("interop") && + !command.commandPath.includes("relay") && + !command.commandPath.includes("configure") && + !command.commandPath.includes("fabric-cli") && + !command.commandPath.includes("env") && + !command.commandPath.includes("helper") && + !command.commandPath.includes("config") && + !command.commandPath.includes("asset"), ) // Maps commands to include alias in title - .map(command => { + .map((command) => { const aliasesString = - command.aliases.length > 0 ? `(${command.aliases.join(',')})` : '' - const commandTitle = ` ${command.name} ${aliasesString}` + command.aliases.length > 0 ? `(${command.aliases.join(",")})` : ""; + const commandTitle = ` ${command.name} ${aliasesString}`; return { commandTitle, - description: command.description ? command.description : '-' - } - }) + description: command.description ? command.description : "-", + }; + }); // To calculate how long each title should be to make the formatting consistent const spaces = commandList.reduce((acc, val) => { - const stringLength = val.commandTitle.length + const stringLength = val.commandTitle.length; if (stringLength > acc) { - return stringLength + return stringLength; } else { - return acc + return acc; } - }, 0) - commandList.forEach(command => { - const val = spaces - command.commandTitle.length - const numberOfSpaces = val > 0 ? val : 0 + }, 0); + commandList.forEach((command) => { + const val = spaces - command.commandTitle.length; + const numberOfSpaces = val > 0 ? val : 0; toolbox.print.info( - `${command.commandTitle} ${Array(numberOfSpaces) - .fill('\xa0') - .join('')} ${command.description}` - ) - }) - toolbox.print.info('') -} + `${command.commandTitle} ${Array(numberOfSpaces).fill("\xa0").join("")} ${command.description}`, + ); + }); + toolbox.print.info(""); +}; // A better way to handle errors for promises function handlePromise(promise: Promise): Promise<[T?, Error?]> { const result: Promise<[T?, Error?]> = promise - .then(data => { - const response: [T?, Error?] = [data, undefined] - return response + .then((data) => { + const response: [T?, Error?] = [data, undefined]; + return response; }) - .catch(error => Promise.resolve([undefined, error])) - return result + .catch((error) => Promise.resolve([undefined, error])); + return result; } // Necessary until gRPC provides a native async friendly solution https://github.com/grpc/grpc-node/issues/54 function promisifyAll(client): any { - const to = {} + const to = {}; for (const k in client) { - if (typeof client[k] != 'function') continue - to[k] = promisify(client[k].bind(client)) + if (typeof client[k] != "function") continue; + to[k] = promisify(client[k].bind(client)); } - return to + return to; } const readJSONFromFile = (jsonfile, logger = console) => { - let data = null - const filepath = path.resolve(jsonfile) - logger.debug('jsonfile is ' + jsonfile) - logger.debug('filepath is ' + filepath) + let data = null; + const filepath = path.resolve(jsonfile); + logger.debug("jsonfile is " + jsonfile); + logger.debug("filepath is " + filepath); try { - const contents = fs.readFileSync(filepath).toString() - logger.debug('contents ' + contents) - data = JSON.parse(contents) - logger.debug('data - ' + JSON.stringify(data)) + const contents = fs.readFileSync(filepath).toString(); + logger.debug("contents " + contents); + data = JSON.parse(contents); + logger.debug("data - " + JSON.stringify(data)); } catch (e) { - logger.debug('Error ' + e.message + ' while parsing JSON config file') - throw e + logger.debug("Error " + e.message + " while parsing JSON config file"); + throw e; } - return data -} + return data; +}; // Used for getting network configuration from config.json file. const getNetworkConfig = ( - networkId: string -): { relayEndpoint?: string; connProfilePath: string; username?: string; mspId?:string; aclPolicyPrincipalType?: string; channelName?: string; chaincode?: string } => { + networkId: string, +): { + relayEndpoint?: string; + connProfilePath: string; + username?: string; + mspId?: string; + aclPolicyPrincipalType?: string; + channelName?: string; + chaincode?: string; +} => { const configPath = process.env.CONFIG_PATH ? path.join(process.env.CONFIG_PATH) - : path.join(__dirname, '../../config.json') + : path.join(__dirname, "../../config.json"); try { - const configJSON = JSON.parse(fs.readFileSync(configPath).toString()) + const configJSON = JSON.parse(fs.readFileSync(configPath).toString()); if (!configJSON[networkId]) { logger.error( - `Network: ${networkId} does not exist in the config.json file` - ) - return { relayEndpoint: '', connProfilePath: '', username: '', mspId: '', aclPolicyPrincipalType: '', channelName: '', chaincode: '' } + `Network: ${networkId} does not exist in the config.json file`, + ); + return { + relayEndpoint: "", + connProfilePath: "", + username: "", + mspId: "", + aclPolicyPrincipalType: "", + channelName: "", + chaincode: "", + }; } - return configJSON[networkId] + return configJSON[networkId]; } catch (err) { - logger.error(`Network: ${networkId} does not exist in the config.json file`) - return { relayEndpoint: '', connProfilePath: '', username: '', mspId: '', aclPolicyPrincipalType: '', channelName: '', chaincode: '' } + logger.error( + `Network: ${networkId} does not exist in the config.json file`, + ); + return { + relayEndpoint: "", + connProfilePath: "", + username: "", + mspId: "", + aclPolicyPrincipalType: "", + channelName: "", + chaincode: "", + }; } -} +}; // Used for getting network configuration from config.json file. const getChaincodeConfig = ( chaincodeId: string, - chaincodeFunc: string + chaincodeFunc: string, ): { args: Array; replaceIndices: Array } => { const ccPath = process.env.CHAINCODE_PATH ? path.join(process.env.CHAINCODE_PATH) - : path.join(__dirname, '../../chaincode.json') + : path.join(__dirname, "../../chaincode.json"); try { - const ccJSON = JSON.parse(fs.readFileSync(ccPath).toString()) + const ccJSON = JSON.parse(fs.readFileSync(ccPath).toString()); if (!ccJSON[chaincodeId]) { logger.error( - `Chaincode: ${chaincodeId} does not exist in the chaincode.json file` - ) - return { args: [], replaceIndices: [] } + `Chaincode: ${chaincodeId} does not exist in the chaincode.json file`, + ); + return { args: [], replaceIndices: [] }; } if (!ccJSON[chaincodeId][chaincodeFunc]) { logger.error( - `Chaincode: ${chaincodeId} does not have a ${chaincodeFunc} function attribute in the chaincode.json file` - ) - return { args: [], replaceIndices: [] } + `Chaincode: ${chaincodeId} does not have a ${chaincodeFunc} function attribute in the chaincode.json file`, + ); + return { args: [], replaceIndices: [] }; } - return ccJSON[chaincodeId][chaincodeFunc] + return ccJSON[chaincodeId][chaincodeFunc]; } catch (err) { - logger.error(`Chaincode: ${chaincodeId} does not exist in the chaincode.json file`) - return { args: [], replaceIndices: [] } + logger.error( + `Chaincode: ${chaincodeId} does not exist in the chaincode.json file`, + ); + return { args: [], replaceIndices: [] }; } -} +}; // Update view address if needed const generateViewAddress = async ( viewAddress: string, sourceNetwork: string, destNetwork: string, - logger?: any + logger?: any, ): Promise => { if (!viewAddress || viewAddress.length === 0) { - throw new Error('Empty view address') + throw new Error("Empty view address"); } - if (viewAddress.indexOf('#') >= 0) { - return viewAddress + if (viewAddress.indexOf("#") >= 0) { + return viewAddress; } - if (viewAddress.indexOf('GetAssetClaimStatus') >= 0 || viewAddress.indexOf('GetTokenAssetClaimStatus') >= 0) { + if ( + viewAddress.indexOf("GetAssetClaimStatus") >= 0 || + viewAddress.indexOf("GetTokenAssetClaimStatus") >= 0 + ) { // Get asset pledge details - let ccFunc - if (viewAddress.indexOf('GetAssetClaimStatus') >= 0) { - ccFunc = 'GetAssetClaimStatus' + let ccFunc; + if (viewAddress.indexOf("GetAssetClaimStatus") >= 0) { + ccFunc = "GetAssetClaimStatus"; } else { - ccFunc = 'GetTokenAssetClaimStatus' + ccFunc = "GetTokenAssetClaimStatus"; } - const addressParts = viewAddress.substring(viewAddress.indexOf(ccFunc) + ccFunc.length + 1).split(':') + const addressParts = viewAddress + .substring(viewAddress.indexOf(ccFunc) + ccFunc.length + 1) + .split(":"); if (addressParts.length != 6) { - throw new Error(`Expected 6 arguments for ${ccFunc}; found ${addressParts.length}`) + throw new Error( + `Expected 6 arguments for ${ccFunc}; found ${addressParts.length}`, + ); } if (addressParts[5] != sourceNetwork) { - throw new Error(`Passed source network ID ${sourceNetwork} does not match last chaincode argument in view address ${addressParts[5]}`) + throw new Error( + `Passed source network ID ${sourceNetwork} does not match last chaincode argument in view address ${addressParts[5]}`, + ); } const pledgeDetails = await getAssetPledgeDetails({ sourceNetworkName: addressParts[5], - pledger: '', + pledger: "", pledgerCert: addressParts[4], destNetworkName: destNetwork, - recipient: '', + recipient: "", recipientCert: addressParts[3], pledgeId: addressParts[0], - logger: logger - }) - return viewAddress + ':' + deserializeAssetPledge(pledgeDetails).getExpirytimesecs() + logger: logger, + }); + return ( + viewAddress + + ":" + + deserializeAssetPledge(pledgeDetails).getExpirytimesecs() + ); } else { - return viewAddress + return viewAddress; } -} +}; function deserializeAssetPledge(pledgeDetails) { - const pledgeDetailBytes = Buffer.from(pledgeDetails, 'base64') - const pledgeDetailsProto = AssetPledge.deserializeBinary(pledgeDetailBytes) - return pledgeDetailsProto + const pledgeDetailBytes = Buffer.from(pledgeDetails, "base64"); + const pledgeDetailsProto = AssetPledge.deserializeBinary(pledgeDetailBytes); + return pledgeDetailsProto; } // Used for creating view address for interop call using remote-network-config.json const generateViewAddressFromRemoteConfig = ( networkId: string, funcName: string, - funcArgs: Array + funcArgs: Array, ): any => { const configPath = process.env.REMOTE_CONFIG_PATH ? path.join(process.env.REMOTE_CONFIG_PATH) - : path.join(__dirname, '../../remote-network-config.json') + : path.join(__dirname, "../../remote-network-config.json"); try { - const configJSON = JSON.parse(fs.readFileSync(configPath).toString()) + const configJSON = JSON.parse(fs.readFileSync(configPath).toString()); if (!configJSON[networkId]) { logger.error( - `Error: ${networkId} does not exist in the remote-network-config.json file` - ) - throw new Error(`Error: ${networkId} does not exist in the remote-network-config.json file`) + `Error: ${networkId} does not exist in the remote-network-config.json file`, + ); + throw new Error( + `Error: ${networkId} does not exist in the remote-network-config.json file`, + ); } - const remoteNetConfig = configJSON[networkId] - let address = remoteNetConfig.relayEndpoint + '/' + networkId + const remoteNetConfig = configJSON[networkId]; + let address = remoteNetConfig.relayEndpoint + "/" + networkId; if (remoteNetConfig.type == "fabric") { - address = address + '/' + remoteNetConfig.channelName + ':' + - remoteNetConfig.chaincode + ':' + funcName + ':' + funcArgs.join(':') + address = + address + + "/" + + remoteNetConfig.channelName + + ":" + + remoteNetConfig.chaincode + + ":" + + funcName + + ":" + + funcArgs.join(":"); } else if (remoteNetConfig.type == "corda") { - address = address + '/' + remoteNetConfig.partyEndPoint + '#' + - remoteNetConfig.flowPackage + "." + funcName + ":" + funcArgs.join(':') + address = + address + + "/" + + remoteNetConfig.partyEndPoint + + "#" + + remoteNetConfig.flowPackage + + "." + + funcName + + ":" + + funcArgs.join(":"); } else { - logger.error(`Error: remote network ${remoteNetConfig.type} not supported.`) - throw new Error(`Error: remote network ${remoteNetConfig.type} not supported.`) + logger.error( + `Error: remote network ${remoteNetConfig.type} not supported.`, + ); + throw new Error( + `Error: remote network ${remoteNetConfig.type} not supported.`, + ); } - console.log(`Interop query, funcName: ${funcName} \n funcArgs: ${funcArgs} \n and address: ${address}`) + console.log( + `Interop query, funcName: ${funcName} \n funcArgs: ${funcArgs} \n and address: ${address}`, + ); - return address + return address; } catch (err) { - logger.error(`Error: ${err}`) - throw new Error(err) + logger.error(`Error: ${err}`); + throw new Error(err); } -} - +}; // Used for creating view address for interop call using remote-network-config.json const interopHelper = async ( @@ -778,45 +918,51 @@ const interopHelper = async ( applicationFunction: string, applicationArgs: Array, replaceIndices: Array, - options: any, // For TLS - print: GluegunPrint // For logging + options: any, // For TLS + print: GluegunPrint, // For logging ): Promise => { - const netConfig = getNetworkConfig(networkName) - if (!netConfig.connProfilePath || !netConfig.channelName || !netConfig.chaincode) { - throw new Error(`No valid config entry found for ${networkName}`) + const netConfig = getNetworkConfig(networkName); + if ( + !netConfig.connProfilePath || + !netConfig.channelName || + !netConfig.chaincode + ) { + throw new Error(`No valid config entry found for ${networkName}`); } const { gateway, wallet, contract } = await fabricHelper({ - channel: netConfig.channelName, - contractName: process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE : 'interop', - connProfilePath: netConfig.connProfilePath, - networkName, - mspId: netConfig.mspId, - logger, - discoveryEnabled: true, - userString: options['user'] - }) + channel: netConfig.channelName, + contractName: process.env.DEFAULT_CHAINCODE + ? process.env.DEFAULT_CHAINCODE + : "interop", + connProfilePath: netConfig.connProfilePath, + networkName, + mspId: netConfig.mspId, + logger, + discoveryEnabled: true, + userString: options["user"], + }); const [keyCert, keyCertError] = await handlePromise( - getKeyAndCertForRemoteRequestbyUserName(wallet, options['user']) - ) + getKeyAndCertForRemoteRequestbyUserName(wallet, options["user"]), + ); if (keyCertError) { - throw new Error(`Error getting key and cert ${keyCertError}`) + throw new Error(`Error getting key and cert ${keyCertError}`); } - const spinner = print.spin(`Starting Interop Query`) + const spinner = print.spin(`Starting Interop Query`); - let relayTlsCAFiles = [] - if (options['relay-tls-ca-files']) { - relayTlsCAFiles = options['relay-tls-ca-files'].split(':') + let relayTlsCAFiles = []; + if (options["relay-tls-ca-files"]) { + relayTlsCAFiles = options["relay-tls-ca-files"].split(":"); } try { const invokeObject = { channel: netConfig.channelName, ccFunc: applicationFunction, ccArgs: applicationArgs, - contractName: appChaincodeId - } - console.log(invokeObject) + contractName: appChaincodeId, + }; + console.log(invokeObject); const interopFlowResponse = await InteroperableHelper.interopFlow( //@ts-ignore this comment can be removed after using published version of interop-sdk contract, @@ -825,44 +971,53 @@ const interopHelper = async ( netConfig.mspId, netConfig.relayEndpoint, replaceIndices, - [{ - address: viewAddress, - Sign: true - }], + [ + { + address: viewAddress, + Sign: true, + }, + ], keyCert, [], false, - options['relay-tls'] === 'true', + options["relay-tls"] === "true", relayTlsCAFiles, - options['e2e-confidentiality'] === 'true', - gateway - ) + options["e2e-confidentiality"] === "true", + gateway, + ); logger.info( `View from remote network: ${JSON.stringify( - interopFlowResponse.views[0].toObject() - )}. Interop Flow result: ${interopFlowResponse.result || 'successful'}` - ) - logger.debug(`ViewB64: ${Buffer.from(interopFlowResponse.views[0].serializeBinary()).toString('base64')}`) - const remoteValue = (options['e2e-confidentiality'] === 'true' ? - InteroperableHelper.getResponseDataFromView(interopFlowResponse.views[0], keyCert.key.toBytes()) : - InteroperableHelper.getResponseDataFromView(interopFlowResponse.views[0]) - ) + interopFlowResponse.views[0].toObject(), + )}. Interop Flow result: ${interopFlowResponse.result || "successful"}`, + ); + logger.debug( + `ViewB64: ${Buffer.from(interopFlowResponse.views[0].serializeBinary()).toString("base64")}`, + ); + const remoteValue = + options["e2e-confidentiality"] === "true" + ? InteroperableHelper.getResponseDataFromView( + interopFlowResponse.views[0], + keyCert.key.toBytes(), + ) + : InteroperableHelper.getResponseDataFromView( + interopFlowResponse.views[0], + ); if (remoteValue.contents) { - logger.debug(`ViewB64Contents: ${Buffer.from(remoteValue.contents).toString('base64')}`) + logger.debug( + `ViewB64Contents: ${Buffer.from(remoteValue.contents).toString("base64")}`, + ); } spinner.succeed( - `Called Function ${applicationFunction}. With Args: ${invokeObject.ccArgs} ${remoteValue.data}` - ) - await gateway.disconnect() - return remoteValue.data + `Called Function ${applicationFunction}. With Args: ${invokeObject.ccArgs} ${remoteValue.data}`, + ); + await gateway.disconnect(); + return remoteValue.data; } catch (e) { - spinner.fail(`Error verifying and storing state`) - logger.error(`Error verifying and storing state: ${e}`) - return "" + spinner.fail(`Error verifying and storing state`); + logger.error(`Error verifying and storing state: ${e}`); + return ""; } -} - - +}; export { commandHelp, @@ -884,5 +1039,5 @@ export { getLocalAssetPledgeDetails, generateViewAddress, generateViewAddressFromRemoteConfig, - interopHelper -} + interopHelper, +}; diff --git a/weaver/samples/fabric/fabric-cli/src/helpers/interop-setup/configure-network.ts b/weaver/samples/fabric/fabric-cli/src/helpers/interop-setup/configure-network.ts index 282a8e1aee..7cda60e98d 100644 --- a/weaver/samples/fabric/fabric-cli/src/helpers/interop-setup/configure-network.ts +++ b/weaver/samples/fabric/fabric-cli/src/helpers/interop-setup/configure-network.ts @@ -4,124 +4,130 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as fs from 'fs' -import * as path from 'path' +import * as fs from "fs"; +import * as path from "path"; import { invoke, getCurrentNetworkCredentialPath, getCredentialPath, - fabricHelper -} from '../fabric-functions' -import { handlePromise, getNetworkConfig } from '../helpers' -import { MembershipManager } from '@hyperledger/cacti-weaver-sdk-fabric' + fabricHelper, +} from "../fabric-functions"; +import { handlePromise, getNetworkConfig } from "../helpers"; +import { MembershipManager } from "@hyperledger/cacti-weaver-sdk-fabric"; const helperInvoke = async (userId, ccFunc, ccArg, ...args) => { - const [contractName, channelName, connProfilePath, networkName, logger] = args + const [contractName, channelName, connProfilePath, networkName, logger] = + args; const [invokeResponse, invokeError] = await handlePromise( invoke( { contractName, channel: channelName, ccFunc: ccFunc, - args: [ccArg] + args: [ccArg], }, connProfilePath, networkName, global.__DEFAULT_MSPID__, logger, userId, - (userId === '') - ) - ) - logger.debug(`${ccFunc} Invoke ${JSON.stringify(invokeResponse)}`) + userId === "", + ), + ); + logger.debug(`${ccFunc} Invoke ${JSON.stringify(invokeResponse)}`); if (invokeError) { - logger.error(`${ccFunc} Invoke Error: ${ccFunc}: ${ccArg}`) - throw new Error(`${ccFunc} Invoke Error ${invokeError}`) + logger.error(`${ccFunc} Invoke Error: ${ccFunc}: ${ccArg}`); + throw new Error(`${ccFunc} Invoke Error ${invokeError}`); } else { - logger.info(`Successfully invoked ${ccFunc}`) + logger.info(`Successfully invoked ${ccFunc}`); } -} +}; -const configureNetwork = async (mainNetwork: string, members: Array = [global.__DEFAULT_MSPID__], logger: any = console, iinAgent: boolean = false) => { - const networkEnv = getNetworkConfig(mainNetwork) - logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`) +const configureNetwork = async ( + mainNetwork: string, + members: Array = [global.__DEFAULT_MSPID__], + logger: any = console, + iinAgent: boolean = false, +) => { + const networkEnv = getNetworkConfig(mainNetwork); + logger.debug(`NetworkEnv: ${JSON.stringify(networkEnv)}`); if (!networkEnv.relayEndpoint || !networkEnv.connProfilePath) { logger.error( - 'Please use a valid --local-network. If valid network please check if your environment variables are configured properly' - ) - return + "Please use a valid --local-network. If valid network please check if your environment variables are configured properly", + ); + return; } - const credentialFolderPath = getCredentialPath() + const credentialFolderPath = getCredentialPath(); const networkFolders = fs .readdirSync(credentialFolderPath, { withFileTypes: true }) - .filter(dirent => dirent.isDirectory()) - .map(item => item.name) + .filter((dirent) => dirent.isDirectory()) + .map((item) => item.name); // Reorder the array so that the local network is the first element // We need to record local membership before recording other networks' memberships - networkFolders.splice(networkFolders.indexOf(mainNetwork), 1) - networkFolders.splice(0, 0, mainNetwork) + networkFolders.splice(networkFolders.indexOf(mainNetwork), 1); + networkFolders.splice(0, 0, mainNetwork); for (const index in networkFolders) { - const network = networkFolders[index] + const network = networkFolders[index]; if (network === mainNetwork) { // A network needs to load/record only other networks' credentials await loadLocalHelper( networkEnv.connProfilePath, mainNetwork, - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", members, - logger - ) + logger, + ); continue; } const accessControlPath = path.join( getCurrentNetworkCredentialPath(network), - 'access-control.json' - ) - let membershipPath = "" - if (!network.startsWith('network')) { - membershipPath = path.join( - getCurrentNetworkCredentialPath(network), - 'membership.json' - ) + "access-control.json", + ); + let membershipPath = ""; + if (!network.startsWith("network")) { + membershipPath = path.join( + getCurrentNetworkCredentialPath(network), + "membership.json", + ); } else if (iinAgent) { membershipPath = path.join( getCurrentNetworkCredentialPath(network), - 'attested-membership-' + mainNetwork + '.proto.serialized' - ) + "attested-membership-" + mainNetwork + ".proto.serialized", + ); } const verificationPolicyPath = path.join( getCurrentNetworkCredentialPath(network), - 'verification-policy.json' - ) + "verification-policy.json", + ); if ( !fs.existsSync(accessControlPath) || !fs.existsSync(verificationPolicyPath) || (membershipPath !== "" && !fs.existsSync(membershipPath)) ) { - logger.error(`Missing credential file for network: ${network}`) + logger.error(`Missing credential file for network: ${network}`); } else { await configureNetworkHelper( networkEnv.connProfilePath, mainNetwork, - process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : 'mychannel', + process.env.DEFAULT_CHANNEL ? process.env.DEFAULT_CHANNEL : "mychannel", process.env.DEFAULT_CHAINCODE ? process.env.DEFAULT_CHAINCODE - : 'interop', + : "interop", network, accessControlPath, membershipPath, verificationPolicyPath, logger, - iinAgent - ) + iinAgent, + ); } } -} +}; const loadLocalHelper = async ( connProfilePath: string, @@ -129,7 +135,7 @@ const loadLocalHelper = async ( channelName: string, contractName: string, members: Array, - logger: any = console + logger: any = console, ): Promise => { //const localMembership = Buffer.from(fs.readFileSync(localMembershipPath)).toString() const { gateway } = await fabricHelper({ @@ -138,19 +144,31 @@ const loadLocalHelper = async ( connProfilePath: connProfilePath, networkName: networkName, mspId: global.__DEFAULT_MSPID__, - userString: 'networkadmin', - registerUser: false - }) + userString: "networkadmin", + registerUser: false, + }); try { - const response = await MembershipManager.createLocalMembership(gateway, members, networkName, channelName, contractName) - logger.info('CreateLocalMembership Successful.') + const response = await MembershipManager.createLocalMembership( + gateway, + members, + networkName, + channelName, + contractName, + ); + logger.info("CreateLocalMembership Successful."); } catch (e) { - logger.error(e) - logger.info('CreateLocalMembership attempting Update') - const response = await MembershipManager.updateLocalMembership(gateway, members, networkName, channelName, contractName) - logger.info('UpdateLocalMembership response: success: ', response) + logger.error(e); + logger.info("CreateLocalMembership attempting Update"); + const response = await MembershipManager.updateLocalMembership( + gateway, + members, + networkName, + channelName, + contractName, + ); + logger.info("UpdateLocalMembership response: success: ", response); } -} +}; const configureNetworkHelper = async ( connProfilePath: string, @@ -162,69 +180,79 @@ const configureNetworkHelper = async ( membershipPath: string, verificationPolicyPath: string, logger: any = console, - iinAgent: boolean = false + iinAgent: boolean = false, ): Promise => { - logger.info(`Target Network: ${targetNetwork}`) + logger.info(`Target Network: ${targetNetwork}`); const accessControl = Buffer.from( - fs.readFileSync(accessControlPath) - ).toString() + fs.readFileSync(accessControlPath), + ).toString(); const verificationPolicy = Buffer.from( - fs.readFileSync(verificationPolicyPath) - ).toString() + fs.readFileSync(verificationPolicyPath), + ).toString(); const helperInvokeArgs = [ contractName, channelName, connProfilePath, networkName, - logger - ] + logger, + ]; - const adminUser = 'networkadmin' + const adminUser = "networkadmin"; try { await helperInvoke( adminUser, - 'CreateAccessControlPolicy', + "CreateAccessControlPolicy", accessControl, - ...helperInvokeArgs - ) + ...helperInvokeArgs, + ); } catch (e) { - logger.info('CreateAccessControlPolicy attempting Update') + logger.info("CreateAccessControlPolicy attempting Update"); await helperInvoke( adminUser, - 'UpdateAccessControlPolicy', + "UpdateAccessControlPolicy", accessControl, - ...helperInvokeArgs - ) + ...helperInvokeArgs, + ); } try { await helperInvoke( adminUser, - 'CreateVerificationPolicy', + "CreateVerificationPolicy", verificationPolicy, - ...helperInvokeArgs - ) + ...helperInvokeArgs, + ); } catch (e) { - logger.info('CreateVerificationPolicy attempting Update') + logger.info("CreateVerificationPolicy attempting Update"); await helperInvoke( adminUser, - 'UpdateVerificationPolicy', + "UpdateVerificationPolicy", verificationPolicy, - ...helperInvokeArgs - ) + ...helperInvokeArgs, + ); } - if (iinAgent || !targetNetwork.startsWith('network')) { - const membership = Buffer.from(fs.readFileSync(membershipPath)).toString() - const memberRecordingUser = iinAgent ? 'iinagent': adminUser // HACK until we add IIN Agents for Corda networks + if (iinAgent || !targetNetwork.startsWith("network")) { + const membership = Buffer.from(fs.readFileSync(membershipPath)).toString(); + const memberRecordingUser = iinAgent ? "iinagent" : adminUser; // HACK until we add IIN Agents for Corda networks try { - await helperInvoke(memberRecordingUser, 'CreateMembership', membership, ...helperInvokeArgs) + await helperInvoke( + memberRecordingUser, + "CreateMembership", + membership, + ...helperInvokeArgs, + ); } catch (e) { - logger.info('CreateMembership attempting Update') - await helperInvoke(memberRecordingUser, 'UpdateMembership', membership, ...helperInvokeArgs) + logger.info("CreateMembership attempting Update"); + await helperInvoke( + memberRecordingUser, + "UpdateMembership", + membership, + ...helperInvokeArgs, + ); } } -} +}; -export { configureNetworkHelper, configureNetwork } +export { configureNetworkHelper, configureNetwork }; diff --git a/weaver/samples/fabric/fabric-cli/src/helpers/logger.ts b/weaver/samples/fabric/fabric-cli/src/helpers/logger.ts index 7b14c5a377..a961d85d56 100644 --- a/weaver/samples/fabric/fabric-cli/src/helpers/logger.ts +++ b/weaver/samples/fabric/fabric-cli/src/helpers/logger.ts @@ -4,26 +4,26 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as winston from 'winston' -import * as path from 'path' -const { format, transports } = winston +import * as winston from "winston"; +import * as path from "path"; +const { format, transports } = winston; const logFormat = format.printf( - info => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}` -) + (info) => `${info.timestamp} ${info.level} [${info.label}]: ${info.message}`, +); const logger = winston.createLogger({ format: format.combine( format.label({ label: path.basename(process.mainModule.filename) }), - format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), - format.metadata({ fillExcept: ['message', 'level', 'timestamp', 'label'] }) + format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }), + format.metadata({ fillExcept: ["message", "level", "timestamp", "label"] }), ), transports: [ new transports.Console({ - format: format.combine(format.colorize(), logFormat) - }) + format: format.combine(format.colorize(), logFormat), + }), ], - exitOnError: false -}) + exitOnError: false, +}); -export default logger +export default logger; diff --git a/weaver/sdks/besu/node/package-local.json b/weaver/sdks/besu/node/package-local.json index 6a36ccc3cb..071eac08d0 100644 --- a/weaver/sdks/besu/node/package-local.json +++ b/weaver/sdks/besu/node/package-local.json @@ -21,19 +21,10 @@ }, "devDependencies": { "@types/node": "16.18.41", - "@typescript-eslint/eslint-plugin": "3.10.1", - "@typescript-eslint/parser": "3.10.1", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "eslint": "7.32.0", - "eslint-config-airbnb-base": "14.2.1", - "eslint-config-prettier": "6.15.0", - "eslint-plugin-import": "2.28.1", - "eslint-plugin-prettier": "3.4.1", "mocha": "5.2.0", "nyc": "12.0.2", - "prettier": "2.8.8", - "prettier-eslint": "11.0.0", "rewire": "4.0.1", "sinon": "6.3.5", "sinon-chai": "3.7.0", diff --git a/weaver/sdks/besu/node/package.json b/weaver/sdks/besu/node/package.json index 7fdedb3598..b18e932a1e 100644 --- a/weaver/sdks/besu/node/package.json +++ b/weaver/sdks/besu/node/package.json @@ -21,19 +21,10 @@ }, "devDependencies": { "@types/node": "16.18.41", - "@typescript-eslint/eslint-plugin": "3.10.1", - "@typescript-eslint/parser": "3.10.1", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "eslint": "7.32.0", - "eslint-config-airbnb-base": "14.2.1", - "eslint-config-prettier": "6.15.0", - "eslint-plugin-import": "2.28.1", - "eslint-plugin-prettier": "5.0.0", "mocha": "5.2.0", "nyc": "12.0.2", - "prettier": "2.8.8", - "prettier-eslint": "11.0.0", "rewire": "4.0.1", "sinon": "6.3.5", "sinon-chai": "3.7.0", diff --git a/weaver/sdks/besu/node/src/AssetManager.ts b/weaver/sdks/besu/node/src/AssetManager.ts index c1070ab189..5d060d26e5 100644 --- a/weaver/sdks/besu/node/src/AssetManager.ts +++ b/weaver/sdks/besu/node/src/AssetManager.ts @@ -5,230 +5,265 @@ */ /** -* This file provides helper functions for interoperability operations. -**/ + * This file provides helper functions for interoperability operations. + **/ /** End file docs */ import * as assetLocksPb from "@hyperledger/cacti-weaver-protos-js/common/asset_locks_pb"; -import * as Web3 from 'web3-utils'; +import * as Web3 from "web3-utils"; import { Hash, SHA256 } from "./HashFunctions"; // Create an asset exchange agreement structure -function createAssetExchangeAgreementSerialized(assetType: string, assetID: string, locker: string, recipient: string) { - const assetExchangeAgreement = new assetLocksPb.AssetExchangeAgreement(); - assetExchangeAgreement.setAssettype(assetType); - assetExchangeAgreement.setId(assetID); - assetExchangeAgreement.setRecipient(recipient); - assetExchangeAgreement.setLocker(locker); - return Buffer.from(assetExchangeAgreement.serializeBinary()) +function createAssetExchangeAgreementSerialized( + assetType: string, + assetID: string, + locker: string, + recipient: string, +) { + const assetExchangeAgreement = new assetLocksPb.AssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setId(assetID); + assetExchangeAgreement.setRecipient(recipient); + assetExchangeAgreement.setLocker(locker); + return Buffer.from(assetExchangeAgreement.serializeBinary()); } -function createFungibleAssetExchangeAgreementSerialized(assetType: string, numUnits: number, locker: string, recipient: string) { - const assetExchangeAgreement = new assetLocksPb.FungibleAssetExchangeAgreement(); - assetExchangeAgreement.setAssettype(assetType); - assetExchangeAgreement.setNumunits(numUnits); - assetExchangeAgreement.setRecipient(recipient); - assetExchangeAgreement.setLocker(locker); - return Buffer.from(assetExchangeAgreement.serializeBinary()) +function createFungibleAssetExchangeAgreementSerialized( + assetType: string, + numUnits: number, + locker: string, + recipient: string, +) { + const assetExchangeAgreement = + new assetLocksPb.FungibleAssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setNumunits(numUnits); + assetExchangeAgreement.setRecipient(recipient); + assetExchangeAgreement.setLocker(locker); + return Buffer.from(assetExchangeAgreement.serializeBinary()); } - -function createHybridAssetExchangeAgreementSerialized(assetType: string, assetID: string, assetData: string, numUnits: number, recipient: string) { - const assetExchangeAgreement = new assetLocksPb.HybridAssetExchangeAgreement(); - assetExchangeAgreement.setAssettype(assetType); - assetExchangeAgreement.setId(assetID); - assetExchangeAgreement.setRecipient(recipient); - assetExchangeAgreement.setAssetdata(Buffer.from(assetData, "hex")); - assetExchangeAgreement.setNumunits(numUnits); - return Buffer.from(assetExchangeAgreement.serializeBinary()) +function createHybridAssetExchangeAgreementSerialized( + assetType: string, + assetID: string, + assetData: string, + numUnits: number, + recipient: string, +) { + const assetExchangeAgreement = + new assetLocksPb.HybridAssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setId(assetID); + assetExchangeAgreement.setRecipient(recipient); + assetExchangeAgreement.setAssetdata(Buffer.from(assetData, "hex")); + assetExchangeAgreement.setNumunits(numUnits); + return Buffer.from(assetExchangeAgreement.serializeBinary()); } // Create an asset lock structure function createAssetLockInfoSerialized(hash: Hash, expiryTimeSecs: number) { - const lockInfoHTLC = new assetLocksPb.AssetLockHTLC(); - lockInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); - lockInfoHTLC.setHashbase64(Buffer.from(hash.getSerializedHashBase64(), 'base64')); - lockInfoHTLC.setExpirytimesecs(expiryTimeSecs); - lockInfoHTLC.setTimespec(assetLocksPb.TimeSpec.EPOCH) - return Buffer.from(lockInfoHTLC.serializeBinary()) + const lockInfoHTLC = new assetLocksPb.AssetLockHTLC(); + lockInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); + lockInfoHTLC.setHashbase64( + Buffer.from(hash.getSerializedHashBase64(), "base64"), + ); + lockInfoHTLC.setExpirytimesecs(expiryTimeSecs); + lockInfoHTLC.setTimespec(assetLocksPb.TimeSpec.EPOCH); + return Buffer.from(lockInfoHTLC.serializeBinary()); } // Create an asset claim structure function createAssetClaimInfoSerialized(hash: Hash) { - const claimInfoHTLC = new assetLocksPb.AssetClaimHTLC(); - claimInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); - claimInfoHTLC.setHashpreimagebase64(Buffer.from(hash.getPreimage())); - const claimInfoHTLCSerialized = claimInfoHTLC.serializeBinary(); - const claimInfo = new assetLocksPb.AssetClaim(); - claimInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); - claimInfo.setClaiminfo(claimInfoHTLCSerialized); - return Buffer.from(claimInfo.serializeBinary()) + const claimInfoHTLC = new assetLocksPb.AssetClaimHTLC(); + claimInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); + claimInfoHTLC.setHashpreimagebase64(Buffer.from(hash.getPreimage())); + const claimInfoHTLCSerialized = claimInfoHTLC.serializeBinary(); + const claimInfo = new assetLocksPb.AssetClaim(); + claimInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); + claimInfo.setClaiminfo(claimInfoHTLCSerialized); + return Buffer.from(claimInfo.serializeBinary()); } const createHTLC = async ( - assetManagerContract: any, - appContract: any, - assetType: string, - assetID: string, - lockerAddress: string, - recipientAddress: string, - expiryTimeSecs: number, - hash: Hash -): Promise<{ result: any, hash: Hash }> => { + assetManagerContract: any, + appContract: any, + assetType: string, + assetID: string, + lockerAddress: string, + recipientAddress: string, + expiryTimeSecs: number, + hash: Hash, +): Promise<{ result: any; hash: Hash }> => { + if (!assetManagerContract || !appContract) { + console.log("Contract handle not supplied"); + return { result: false, hash: null }; + } + if (!recipientAddress) { + console.log(`Recipient address not supplied ${recipientAddress}`); + return { result: false, hash: null }; + } + const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) { + console.log( + "Supplied expiry time invalid or in the past: %s; current time: %s", + new Date(expiryTimeSecs).toISOString(), + new Date(currTimeSecs).toISOString(), + ); + return { result: false, hash: null }; + } + + if (hash == null) { + hash = new SHA256(); + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } - if (!assetManagerContract || !appContract) { - console.log("Contract handle not supplied"); - return { result: false, hash: null }; - } - if (!recipientAddress) { - console.log(`Recipient address not supplied ${recipientAddress}`); - return { result: false, hash: null }; - } - const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds - if (expiryTimeSecs <= currTimeSecs) { - console.log("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); - return { result: false, hash: null }; - } - - if (hash == null) { - hash = new SHA256() - } - if (hash.hash64 == null) { - hash.generateRandomPreimage(22); - } - - var agreement = createAssetExchangeAgreementSerialized(assetType, assetID, "", recipientAddress.slice(2)); + const agreement = createAssetExchangeAgreementSerialized( + assetType, + assetID, + "", + recipientAddress.slice(2), + ); - if (!agreement) { - console.log("Error creating protobuf asset exchange agreement"); - return { result: false, hash: null }; - } - const lockInfo = createAssetLockInfoSerialized(hash, expiryTimeSecs); - // Normal invoke function - let lockStatus = await assetManagerContract.lockNonFungibleAsset( - appContract.address, - agreement, - lockInfo, - { - from: lockerAddress, - } - ).catch(function (e: any) { - console.log(e); - console.log("lockNonFungibleAsset threw an error"); - lockStatus = { result: false, hash: null } + if (!agreement) { + console.log("Error creating protobuf asset exchange agreement"); + return { result: false, hash: null }; + } + const lockInfo = createAssetLockInfoSerialized(hash, expiryTimeSecs); + // Normal invoke function + let lockStatus = await assetManagerContract + .lockNonFungibleAsset(appContract.address, agreement, lockInfo, { + from: lockerAddress, }) - return { result: lockStatus, hash: hash }; + .catch(function (e: any) { + console.log(e); + console.log("lockNonFungibleAsset threw an error"); + lockStatus = { result: false, hash: null }; + }); + return { result: lockStatus, hash: hash }; }; const createFungibleHTLC = async ( - assetManagerContract: any, - appContract: any, - assetType: string, - assetAmount: number, - lockerAddress: string, - recipientAddress: string, - expiryTimeSecs: number, - hash: Hash -): Promise<{ result: any, hash: Hash }> => { + assetManagerContract: any, + appContract: any, + assetType: string, + assetAmount: number, + lockerAddress: string, + recipientAddress: string, + expiryTimeSecs: number, + hash: Hash, +): Promise<{ result: any; hash: Hash }> => { + if (!assetManagerContract || !appContract) { + console.log("Contract handle not supplied"); + return { result: false, hash: null }; + } + if (!recipientAddress) { + console.log(`Recipient address not supplied ${recipientAddress}`); + return { result: false, hash: null }; + } + const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) { + console.log( + "Supplied expiry time invalid or in the past: %s; current time: %s", + new Date(expiryTimeSecs).toISOString(), + new Date(currTimeSecs).toISOString(), + ); + return { result: false, hash: null }; + } - if (!assetManagerContract || !appContract) { - console.log("Contract handle not supplied"); - return { result: false, hash: null }; - } - if (!recipientAddress) { - console.log(`Recipient address not supplied ${recipientAddress}`); - return { result: false, hash: null }; - } - const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds - if (expiryTimeSecs <= currTimeSecs) { - console.log("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); - return { result: false, hash: null }; - } - - if (hash == null) { - hash = new SHA256() - } - if (hash.hash64 == null) { - hash.generateRandomPreimage(22); - } - - var agreement = createFungibleAssetExchangeAgreementSerialized(assetType, assetAmount, "", recipientAddress.slice(2)); + if (hash == null) { + hash = new SHA256(); + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } - if (!agreement) { - console.log("Error creating protobuf fungible asset exchange agreement"); - return { result: false, hash: null }; - } - const lockInfo = createAssetLockInfoSerialized(hash, expiryTimeSecs); - // Normal invoke function - let lockStatus = await assetManagerContract.lockFungibleAsset( - appContract.address, - agreement, - lockInfo, - { - from: lockerAddress, - } - ).catch(function (e: any) { - console.log(e); - console.log("lockFungibleAsset threw an error"); - lockStatus = { result: false, hash: null } + const agreement = createFungibleAssetExchangeAgreementSerialized( + assetType, + assetAmount, + "", + recipientAddress.slice(2), + ); + + if (!agreement) { + console.log("Error creating protobuf fungible asset exchange agreement"); + return { result: false, hash: null }; + } + const lockInfo = createAssetLockInfoSerialized(hash, expiryTimeSecs); + // Normal invoke function + let lockStatus = await assetManagerContract + .lockFungibleAsset(appContract.address, agreement, lockInfo, { + from: lockerAddress, }) - return { result: lockStatus, hash: hash }; + .catch(function (e: any) { + console.log(e); + console.log("lockFungibleAsset threw an error"); + lockStatus = { result: false, hash: null }; + }); + return { result: lockStatus, hash: hash }; }; const createHybridHTLC = async ( - assetManagerContract: any, - appContract: any, - assetType: string, - assetID: string, - assetData: string, - assetAmount: number, - lockerAddress: string, - recipientAddress: string, - expiryTimeSecs: number, - hash: Hash -): Promise<{ result: any, hash: Hash }> => { + assetManagerContract: any, + appContract: any, + assetType: string, + assetID: string, + assetData: string, + assetAmount: number, + lockerAddress: string, + recipientAddress: string, + expiryTimeSecs: number, + hash: Hash, +): Promise<{ result: any; hash: Hash }> => { + if (!assetManagerContract || !appContract) { + console.log("Contract handle not supplied"); + return { result: false, hash: null }; + } + if (!recipientAddress) { + console.log(`Recipient address not supplied ${recipientAddress}`); + return { result: false, hash: null }; + } + const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) { + console.log( + "Supplied expiry time invalid or in the past: %s; current time: %s", + new Date(expiryTimeSecs).toISOString(), + new Date(currTimeSecs).toISOString(), + ); + return { result: false, hash: null }; + } + + if (hash == null) { + hash = new SHA256(); + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } - if (!assetManagerContract || !appContract) { - console.log("Contract handle not supplied"); - return { result: false, hash: null }; - } - if (!recipientAddress) { - console.log(`Recipient address not supplied ${recipientAddress}`); - return { result: false, hash: null }; - } - const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds - if (expiryTimeSecs <= currTimeSecs) { - console.log("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); - return { result: false, hash: null }; - } - - if (hash == null) { - hash = new SHA256() - } - if (hash.hash64 == null) { - hash.generateRandomPreimage(22); - } - - var agreement = createHybridAssetExchangeAgreementSerialized(assetType, String(assetID), Web3.utf8ToHex(String(assetData)), assetAmount, recipientAddress.slice(2)); - if (!agreement) { - console.log("Error creating protobuf hybrid asset exchange agreement"); - return { result: false, hash: null }; - } - const lockInfo = createAssetLockInfoSerialized(hash, expiryTimeSecs); - // Normal invoke function - let lockStatus = await assetManagerContract.lockHybridAsset( - appContract.address, - agreement, - lockInfo, - { - from: lockerAddress, - } - ).catch(function (e: any) { - console.log(e); - console.log("lockHybridAsset threw an error"); - lockStatus = { result: false, hash: null } + const agreement = createHybridAssetExchangeAgreementSerialized( + assetType, + String(assetID), + Web3.utf8ToHex(String(assetData)), + assetAmount, + recipientAddress.slice(2), + ); + if (!agreement) { + console.log("Error creating protobuf hybrid asset exchange agreement"); + return { result: false, hash: null }; + } + const lockInfo = createAssetLockInfoSerialized(hash, expiryTimeSecs); + // Normal invoke function + let lockStatus = await assetManagerContract + .lockHybridAsset(appContract.address, agreement, lockInfo, { + from: lockerAddress, }) - - return { result: lockStatus, hash: hash }; + .catch(function (e: any) { + console.log(e); + console.log("lockHybridAsset threw an error"); + lockStatus = { result: false, hash: null }; + }); + + return { result: lockStatus, hash: hash }; }; /** @@ -236,72 +271,75 @@ const createHybridHTLC = async ( * - Claim a unique asset instance using a hash preimage **/ const claimAssetInHTLC = async ( - assetManagerContract: any, - contractId: string, - lockerAddress: string, - hash: Hash, + assetManagerContract: any, + contractId: string, + lockerAddress: string, + hash: Hash, ): Promise => { + if (!assetManagerContract) { + console.log("Contract Address not supplied"); + return false; + } - if (!assetManagerContract) { - console.log("Contract Address not supplied"); - return false; - } + const claimInfoStr = createAssetClaimInfoSerialized(hash); - const claimInfoStr = createAssetClaimInfoSerialized(hash); - - var claimStatus = await assetManagerContract.claimAsset(contractId, claimInfoStr, { from: lockerAddress }).catch(function (e: any) { - console.log(e) - console.log("claimAsset threw an error"); - claimStatus = false - }) + var claimStatus = await assetManagerContract + .claimAsset(contractId, claimInfoStr, { from: lockerAddress }) + .catch(function (e: any) { + console.log(e); + console.log("claimAsset threw an error"); + claimStatus = false; + }); - return claimStatus; + return claimStatus; }; const isAssetLockedInHTLC = async ( - assetManagerContract: any, - contractId: string, + assetManagerContract: any, + contractId: string, ): Promise => { + if (!assetManagerContract) { + console.log("Contract not supplied"); + return false; + } - if (!assetManagerContract) { - console.log("Contract not supplied"); - return false; - } - - // Normal invoke function - var lockStatus = await assetManagerContract.isAssetLocked(contractId).catch(function (e: any) { - console.log(e) - console.log("isAssetLock threw an error"); - lockStatus = false - }) + // Normal invoke function + var lockStatus = await assetManagerContract + .isAssetLocked(contractId) + .catch(function (e: any) { + console.log(e); + console.log("isAssetLock threw an error"); + lockStatus = false; + }); - return lockStatus; + return lockStatus; }; - const reclaimAssetInHTLC = async ( - interopContract: any, - contractId: string, - locker: string, + interopContract: any, + contractId: string, + locker: string, ): Promise => { - var unlockStatus = await interopContract.unlockAsset(contractId, { - from: locker - }).catch(function (e: any) { - console.log(e) - console.log("unlockAsset threw an error"); - unlockStatus = false + var unlockStatus = await interopContract + .unlockAsset(contractId, { + from: locker, }) + .catch(function (e: any) { + console.log(e); + console.log("unlockAsset threw an error"); + unlockStatus = false; + }); - return unlockStatus -} + return unlockStatus; +}; export { - createAssetExchangeAgreementSerialized, - createAssetClaimInfoSerialized, - createHTLC, - createFungibleHTLC, - createHybridHTLC, - claimAssetInHTLC, - reclaimAssetInHTLC, - isAssetLockedInHTLC + createAssetExchangeAgreementSerialized, + createAssetClaimInfoSerialized, + createHTLC, + createFungibleHTLC, + createHybridHTLC, + claimAssetInHTLC, + reclaimAssetInHTLC, + isAssetLockedInHTLC, }; diff --git a/weaver/sdks/besu/node/src/HashFunctions.ts b/weaver/sdks/besu/node/src/HashFunctions.ts index 982afebdac..c2bd55baa7 100644 --- a/weaver/sdks/besu/node/src/HashFunctions.ts +++ b/weaver/sdks/besu/node/src/HashFunctions.ts @@ -4,11 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -import * as crypto from 'crypto'; +import * as crypto from "crypto"; import { HashMechanism } from "@hyperledger/cacti-weaver-protos-js/common/asset_locks_pb"; //TODO: move all common node SDK functions to one place, instead of replicating in each SDK - + /* * Interface for all hash functions to be used for HTLC * To extend supported hash functions in weaver for HTLC, @@ -17,75 +17,69 @@ import { HashMechanism } from "@hyperledger/cacti-weaver-protos-js/common/asset_ * and serialize the protobuf in base64 in getSerializedHashBase64 function. */ interface Hash { - HASH_MECHANISM: HashMechanism - preimage: any // Preimage for Hash - hash64: string // Serialized Hash in base64 - generateRandomPreimage(length: any): void; - setPreimage(preimage: any): void; - getPreimage(): any; - getSerializedPreimageBase64(): string; - setSerializedHashBase64(hash64: string): void; - getSerializedHashBase64(): string; + HASH_MECHANISM: HashMechanism; + preimage: any; // Preimage for Hash + hash64: string; // Serialized Hash in base64 + generateRandomPreimage(length: any): void; + setPreimage(preimage: any): void; + getPreimage(): any; + getSerializedPreimageBase64(): string; + setSerializedHashBase64(hash64: string): void; + getSerializedHashBase64(): string; } abstract class SHA implements Hash { - abstract HASH_MECHANISM: HashMechanism - preimage: string = ""; - hash64: string = ""; - - abstract computeHash(): string - - // Create a secure pseudo-random preimage of a given length - generateRandomPreimage(length: number) - { - this.setPreimage(crypto.randomBytes(length).toString('base64')); - } - - setPreimage(preimage: any) { - this.preimage = preimage - this.hash64 = this.computeHash() - } - getPreimage(): any { - return this.preimage; - } - getSerializedPreimageBase64(): any { - return Buffer.from(this.preimage) - } - - setSerializedHashBase64(hash64: any) { - this.hash64 = hash64; - } - getSerializedHashBase64(): any { - if(this.hash64 != null) - return this.hash64 - else - throw new Error(`Error: Hash or Preimage needs to be set before access`); - } + abstract HASH_MECHANISM: HashMechanism; + preimage: string = ""; + hash64: string = ""; + + abstract computeHash(): string; + + // Create a secure pseudo-random preimage of a given length + generateRandomPreimage(length: number) { + this.setPreimage(crypto.randomBytes(length).toString("base64")); + } + + setPreimage(preimage: any) { + this.preimage = preimage; + this.hash64 = this.computeHash(); + } + getPreimage(): any { + return this.preimage; + } + getSerializedPreimageBase64(): any { + return Buffer.from(this.preimage); + } + + setSerializedHashBase64(hash64: any) { + this.hash64 = hash64; + } + getSerializedHashBase64(): any { + if (this.hash64 != null) return this.hash64; + else + throw new Error(`Error: Hash or Preimage needs to be set before access`); + } } /* * SHA256 Hash for HTLC, implementing above Hash Interface */ class SHA256 extends SHA { - HASH_MECHANISM = HashMechanism.SHA256; - - computeHash(): string { - return crypto.createHash('sha256').update(this.preimage).digest('base64'); - } + HASH_MECHANISM = HashMechanism.SHA256; + + computeHash(): string { + return crypto.createHash("sha256").update(this.preimage).digest("base64"); + } } /* * SHA512 Hash for HTLC, implementing above Hash Interface */ class SHA512 extends SHA { - HASH_MECHANISM = HashMechanism.SHA512; - - computeHash(): string { - return crypto.createHash('sha512').update(this.preimage).digest('base64'); - } + HASH_MECHANISM = HashMechanism.SHA512; + + computeHash(): string { + return crypto.createHash("sha512").update(this.preimage).digest("base64"); + } } -export { - Hash, - SHA256, - SHA512 -}; +export { Hash, SHA256, SHA512 }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/.eslintignore b/weaver/sdks/fabric/interoperation-node-sdk/.eslintignore deleted file mode 100644 index b4619ec60d..0000000000 --- a/weaver/sdks/fabric/interoperation-node-sdk/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -.nyc_output -fabric-protos -coverage -node_modules -old -protos -protos-js \ No newline at end of file diff --git a/weaver/sdks/fabric/interoperation-node-sdk/.eslintrc.json b/weaver/sdks/fabric/interoperation-node-sdk/.eslintrc.json deleted file mode 100644 index a87c767cad..0000000000 --- a/weaver/sdks/fabric/interoperation-node-sdk/.eslintrc.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", // Specifies the ESLint parser - "ignorePatterns": ["**/out/*.js", "**/protos-js/"], - "extends": [ - "plugin:@typescript-eslint/recommended", // Uses the recommended rules from the @typescript-eslint/eslint-plugin - "prettier", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier - "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. - ], - "env": { - "node": true, - "es6": true, - "mocha": true - }, - "parserOptions": { - "ecmaVersion": 8 - }, - "plugins": ["prettier"], - "rules": { - "@typescript-eslint/no-empty-function": "warn", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/ban-ts-comment": "off", - "linebreak-style": ["error", "unix"], - "quotes": ["warn", "double"], - "semi": ["error", "always"] - } -} diff --git a/weaver/sdks/fabric/interoperation-node-sdk/.prettierrc b/weaver/sdks/fabric/interoperation-node-sdk/.prettierrc deleted file mode 100644 index 1ba4c891d4..0000000000 --- a/weaver/sdks/fabric/interoperation-node-sdk/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "semi": true, - "trailingComma": "all", - "printWidth": 120, - "tabWidth": 4 - } - \ No newline at end of file diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json index 03154d5b9a..d1f39b4ce8 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package-local.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package-local.json @@ -18,7 +18,6 @@ "scripts": { "build": "tsc", "docs": "typedoc --out docs/ src/", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "prepublishOnly": "npm test", "test": "nyc mocha -r ts-node/register --exclude 'test/data/**/*.js' --recursive -t 10000" }, @@ -55,19 +54,10 @@ }, "devDependencies": { "@types/node": "16.18.41", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "eslint": "7.32.0", - "eslint-config-airbnb-base": "14.2.1", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-import": "2.28.1", - "eslint-plugin-prettier": "3.4.1", "mocha": "5.2.0", "nyc": "12.0.2", - "prettier": "2.8.8", - "prettier-eslint": "11.0.0", "rewire": "4.0.1", "sinon": "6.3.5", "sinon-chai": "3.7.0", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/package.json b/weaver/sdks/fabric/interoperation-node-sdk/package.json index e30e94afb1..ce3c3545ed 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/package.json +++ b/weaver/sdks/fabric/interoperation-node-sdk/package.json @@ -18,7 +18,6 @@ "scripts": { "build": "tsc", "docs": "typedoc --out docs/ src/", - "lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix", "prepublishOnly": "npm test", "test": "nyc mocha -r ts-node/register --exclude 'test/data/**/*.js' --recursive -t 10000" }, @@ -55,19 +54,10 @@ }, "devDependencies": { "@types/node": "16.18.41", - "@typescript-eslint/eslint-plugin": "4.33.0", - "@typescript-eslint/parser": "4.33.0", "chai": "4.3.7", "chai-as-promised": "7.1.1", - "eslint": "7.32.0", - "eslint-config-airbnb-base": "14.2.1", - "eslint-config-prettier": "8.10.0", - "eslint-plugin-import": "2.28.1", - "eslint-plugin-prettier": "5.0.0", "mocha": "5.2.0", "nyc": "12.0.2", - "prettier": "2.8.8", - "prettier-eslint": "11.0.0", "rewire": "4.0.1", "sinon": "6.3.5", "sinon-chai": "3.7.0", diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/AssetManager.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/AssetManager.ts index d18813ecb3..6df6a5aa2c 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/AssetManager.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/AssetManager.ts @@ -15,141 +15,177 @@ import fabproto6 from "fabric-protos"; import * as helpers from "./helpers"; import assetLocksPb from "@hyperledger/cacti-weaver-protos-js/common/asset_locks_pb"; import { Contract, ContractListener } from "fabric-network"; -import { Hash, SHA256, SHA512 } from "./HashFunctions" +import { Hash, SHA256, SHA512 } from "./HashFunctions"; const logger = log4js.getLogger("InteroperableHelper"); - // Create an asset exchange agreement structure -function createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, lockerECert) -{ - const assetExchangeAgreement = new assetLocksPb.AssetExchangeAgreement(); - assetExchangeAgreement.setAssettype(assetType); - assetExchangeAgreement.setId(assetID); - assetExchangeAgreement.setRecipient(recipientECert); - assetExchangeAgreement.setLocker(lockerECert); - return Buffer.from(assetExchangeAgreement.serializeBinary()).toString('base64'); +function createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + lockerECert, +) { + const assetExchangeAgreement = new assetLocksPb.AssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setId(assetID); + assetExchangeAgreement.setRecipient(recipientECert); + assetExchangeAgreement.setLocker(lockerECert); + return Buffer.from(assetExchangeAgreement.serializeBinary()).toString( + "base64", + ); } // Create a fungible asset exchange agreement structure -function createFungibleAssetExchangeAgreementSerialized(assetType, numUnits, recipientECert, lockerECert) -{ - const assetExchangeAgreement = new assetLocksPb.FungibleAssetExchangeAgreement(); - assetExchangeAgreement.setAssettype(assetType); - assetExchangeAgreement.setNumunits(numUnits); - assetExchangeAgreement.setRecipient(recipientECert); - assetExchangeAgreement.setLocker(lockerECert); - return Buffer.from(assetExchangeAgreement.serializeBinary()).toString('base64'); +function createFungibleAssetExchangeAgreementSerialized( + assetType, + numUnits, + recipientECert, + lockerECert, +) { + const assetExchangeAgreement = + new assetLocksPb.FungibleAssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setNumunits(numUnits); + assetExchangeAgreement.setRecipient(recipientECert); + assetExchangeAgreement.setLocker(lockerECert); + return Buffer.from(assetExchangeAgreement.serializeBinary()).toString( + "base64", + ); } // Create an asset lock structure -function createAssetLockInfoSerialized(hash, expiryTimeSecs) -{ - const lockInfoHTLC = new assetLocksPb.AssetLockHTLC(); - lockInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); - lockInfoHTLC.setHashbase64(Buffer.from(hash.getSerializedHashBase64())); - lockInfoHTLC.setExpirytimesecs(expiryTimeSecs); - lockInfoHTLC.setTimespec(assetLocksPb.TimeSpec.EPOCH); - const lockInfoHTLCSerialized = lockInfoHTLC.serializeBinary(); - const lockInfo = new assetLocksPb.AssetLock(); - lockInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); - lockInfo.setLockinfo(lockInfoHTLCSerialized); - return Buffer.from(lockInfo.serializeBinary()).toString('base64'); +function createAssetLockInfoSerialized(hash, expiryTimeSecs) { + const lockInfoHTLC = new assetLocksPb.AssetLockHTLC(); + lockInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); + lockInfoHTLC.setHashbase64(Buffer.from(hash.getSerializedHashBase64())); + lockInfoHTLC.setExpirytimesecs(expiryTimeSecs); + lockInfoHTLC.setTimespec(assetLocksPb.TimeSpec.EPOCH); + const lockInfoHTLCSerialized = lockInfoHTLC.serializeBinary(); + const lockInfo = new assetLocksPb.AssetLock(); + lockInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); + lockInfo.setLockinfo(lockInfoHTLCSerialized); + return Buffer.from(lockInfo.serializeBinary()).toString("base64"); } // Create an asset claim structure -function createAssetClaimInfoSerialized(hash) -{ - const claimInfoHTLC = new assetLocksPb.AssetClaimHTLC(); - claimInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); - claimInfoHTLC.setHashpreimagebase64(Buffer.from(hash.getSerializedPreimageBase64())); - const claimInfoHTLCSerialized = claimInfoHTLC.serializeBinary(); - const claimInfo = new assetLocksPb.AssetClaim(); - claimInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); - claimInfo.setClaiminfo(claimInfoHTLCSerialized); - return Buffer.from(claimInfo.serializeBinary()).toString('base64'); +function createAssetClaimInfoSerialized(hash) { + const claimInfoHTLC = new assetLocksPb.AssetClaimHTLC(); + claimInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); + claimInfoHTLC.setHashpreimagebase64( + Buffer.from(hash.getSerializedPreimageBase64()), + ); + const claimInfoHTLCSerialized = claimInfoHTLC.serializeBinary(); + const claimInfo = new assetLocksPb.AssetClaim(); + claimInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); + claimInfo.setClaiminfo(claimInfoHTLCSerialized); + return Buffer.from(claimInfo.serializeBinary()).toString("base64"); } /** * First/second step of a Hashed Time Lock Contract * - Lock a unique asset instance using a hash - * - * Byzantine Swaps: Call StartHTLCAssetLockListener within here while passing new callback + * + * Byzantine Swaps: Call StartHTLCAssetLockListener within here while passing new callback * parameter as newly defined function: assetLockExpirationCallback is passed as localCallback **/ const createHTLC = async ( - contract: Contract, - assetType: string, - assetID: string, - recipientECert: string, - hash: Hash, - expiryTimeSecs: number, - timeoutCallback: (c: Contract, t: string, i: string, r: string, h: Hash) => any, - endorsingOrgs: Array = [], + contract: Contract, + assetType: string, + assetID: string, + recipientECert: string, + hash: Hash, + expiryTimeSecs: number, + timeoutCallback: ( + c: Contract, + t: string, + i: string, + r: string, + h: Hash, + ) => any, + endorsingOrgs: Array = [], ): Promise<{ hash: Hash; result: any }> => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return { hash: null, result: false }; - } - if (!assetType) - { - logger.error("Asset type not supplied"); - return { hash: null, result: false }; - } - if (!assetID) - { - logger.error("Asset ID not supplied"); - return { hash: null, result: false }; - } - if (!recipientECert) - { - logger.error("Recipient ECert not supplied"); - return { hash: null, result: false }; - } - const currTimeSecs = Math.floor(Date.now()/1000); // Convert epoch milliseconds to seconds - if (expiryTimeSecs <= currTimeSecs) - { - logger.error("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); - return { hash: null, result: false }; - } - - if (hash == null) { - hash = new SHA256() - } - if (hash.hash64 == null) { - hash.generateRandomPreimage(22); - } - - const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, ""); - const lockInfoStr = createAssetLockInfoSerialized(hash, expiryTimeSecs); - - //If timeoutCallback is not defined, start automated listener - if (!timeoutCallback) - { - StartHTLCAssetLockListener(contract, "", assetType, assetID, recipientECert, "", assetLockExpirationCallback, endorsingOrgs); - } - - const tx = contract.createTransaction("LockAsset") - const ccArgs = [assetExchangeAgreementStr, lockInfoStr] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - // Normal invoke function - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) + if (!contract) { + logger.error("Contract handle not supplied"); + return { hash: null, result: false }; + } + if (!assetType) { + logger.error("Asset type not supplied"); + return { hash: null, result: false }; + } + if (!assetID) { + logger.error("Asset ID not supplied"); + return { hash: null, result: false }; + } + if (!recipientECert) { + logger.error("Recipient ECert not supplied"); + return { hash: null, result: false }; + } + const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) { + logger.error( + "Supplied expiry time invalid or in the past: %s; current time: %s", + new Date(expiryTimeSecs).toISOString(), + new Date(currTimeSecs).toISOString(), ); - if (submitError) { - throw new Error(`LockAsset submitTransaction Error: ${submitError}`); - } - - if (timeoutCallback) - { - // Start timer for lock expiration - setTimeout(timeoutCallback, (expiryTimeSecs * 1000) - Date.now(), contract, assetType, assetID, recipientECert, hash); - } + return { hash: null, result: false }; + } + + if (hash == null) { + hash = new SHA256(); + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + "", + ); + const lockInfoStr = createAssetLockInfoSerialized(hash, expiryTimeSecs); + + //If timeoutCallback is not defined, start automated listener + if (!timeoutCallback) { + StartHTLCAssetLockListener( + contract, + "", + assetType, + assetID, + recipientECert, + "", + assetLockExpirationCallback, + endorsingOrgs, + ); + } + + const tx = contract.createTransaction("LockAsset"); + const ccArgs = [assetExchangeAgreementStr, lockInfoStr]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + // Normal invoke function + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error(`LockAsset submitTransaction Error: ${submitError}`); + } + + if (timeoutCallback) { + // Start timer for lock expiration + setTimeout( + timeoutCallback, + expiryTimeSecs * 1000 - Date.now(), + contract, + assetType, + assetID, + recipientECert, + hash, + ); + } - return { hash: hash, result: result }; + return { hash: hash, result: result }; }; /** @@ -157,79 +193,108 @@ const createHTLC = async ( * - Lock a set of fungible assets using a hash **/ const createFungibleHTLC = async ( - contract: Contract, - assetType: string, - numUnits: number, - recipientECert: string, - hash: Hash, - expiryTimeSecs: number, - timeoutCallback: (c: Contract, i: string, t: string, n: number, r: string, h: Hash) => any, - endorsingOrgs: Array = [], + contract: Contract, + assetType: string, + numUnits: number, + recipientECert: string, + hash: Hash, + expiryTimeSecs: number, + timeoutCallback: ( + c: Contract, + i: string, + t: string, + n: number, + r: string, + h: Hash, + ) => any, + endorsingOrgs: Array = [], ): Promise<{ hash: Hash; result: any }> => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return { hash: null, result: "" }; - } - if (!assetType) - { - logger.error("Asset type not supplied"); - return { hash: null, result: "" }; - } - if (numUnits <= 0) - { - logger.error("Asset count must be a positive integer"); - return { hash: null, result: "" }; - } - if (!recipientECert) - { - logger.error("Recipient ECert not supplied"); - return { hash: null, result: "" }; - } - const currTimeSecs = Math.floor(Date.now()/1000); // Convert epoch milliseconds to seconds - if (expiryTimeSecs <= currTimeSecs) - { - logger.error("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); - return { hash: null, result: "" }; - } - - if (!hash) { - hash = new SHA256() - } - if (hash.hash64 == null) { - hash.generateRandomPreimage(22); - } - - const assetExchangeAgreementStr = createFungibleAssetExchangeAgreementSerialized(assetType, numUnits, recipientECert, ""); - const lockInfoStr = createAssetLockInfoSerialized(hash, expiryTimeSecs); - - //If timeoutCallback is not defined, start automated listener - if (!timeoutCallback) - { - StartHTLCFungibleAssetLockListener(contract, "", assetType, numUnits, recipientECert, "", fungibleAssetLockExpirationCallback, endorsingOrgs); - } - - const tx = contract.createTransaction("LockFungibleAsset") - const ccArgs = [assetExchangeAgreementStr, lockInfoStr] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - // Normal invoke function - const [contractId, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) + if (!contract) { + logger.error("Contract handle not supplied"); + return { hash: null, result: "" }; + } + if (!assetType) { + logger.error("Asset type not supplied"); + return { hash: null, result: "" }; + } + if (numUnits <= 0) { + logger.error("Asset count must be a positive integer"); + return { hash: null, result: "" }; + } + if (!recipientECert) { + logger.error("Recipient ECert not supplied"); + return { hash: null, result: "" }; + } + const currTimeSecs = Math.floor(Date.now() / 1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) { + logger.error( + "Supplied expiry time invalid or in the past: %s; current time: %s", + new Date(expiryTimeSecs).toISOString(), + new Date(currTimeSecs).toISOString(), ); - if (submitError) { - throw new Error(`LockFungibleAsset submitTransaction Error: ${submitError}`); - } - - if (timeoutCallback) - { - // Start timer for lock expiration - setTimeout(timeoutCallback, (expiryTimeSecs * 1000) - Date.now(), contract, contractId, assetType, numUnits, recipientECert, hash); - } + return { hash: null, result: "" }; + } + + if (!hash) { + hash = new SHA256(); + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } + + const assetExchangeAgreementStr = + createFungibleAssetExchangeAgreementSerialized( + assetType, + numUnits, + recipientECert, + "", + ); + const lockInfoStr = createAssetLockInfoSerialized(hash, expiryTimeSecs); + + //If timeoutCallback is not defined, start automated listener + if (!timeoutCallback) { + StartHTLCFungibleAssetLockListener( + contract, + "", + assetType, + numUnits, + recipientECert, + "", + fungibleAssetLockExpirationCallback, + endorsingOrgs, + ); + } + + const tx = contract.createTransaction("LockFungibleAsset"); + const ccArgs = [assetExchangeAgreementStr, lockInfoStr]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + // Normal invoke function + const [contractId, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error( + `LockFungibleAsset submitTransaction Error: ${submitError}`, + ); + } + + if (timeoutCallback) { + // Start timer for lock expiration + setTimeout( + timeoutCallback, + expiryTimeSecs * 1000 - Date.now(), + contract, + contractId, + assetType, + numUnits, + recipientECert, + hash, + ); + } - return { hash: hash, result: contractId }; + return { hash: hash, result: contractId }; }; /** @@ -237,61 +302,59 @@ const createFungibleHTLC = async ( * - Claim a unique asset instance using a hash preimage **/ const claimAssetInHTLC = async ( - contract: Contract, - assetType: string, - assetID: string, - lockerECert: string, - hash: Hash, - endorsingOrgs: Array = [] + contract: Contract, + assetType: string, + assetID: string, + lockerECert: string, + hash: Hash, + endorsingOrgs: Array = [], ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!assetType) - { - logger.error("Asset type not supplied"); - return false; - } - if (!assetID) - { - logger.error("Asset ID not supplied"); - return false; - } - if (!lockerECert) - { - logger.error("Locker ECert not supplied"); - return false; - } - if (!hash) - { - logger.error("Instance of Hash interface not supplied") - return false - } - if (!hash.preimage) - { - logger.error("Hash Preimage not supplied"); - return false; - } - - const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, "", lockerECert); - const claimInfoStr = createAssetClaimInfoSerialized(hash); - - // Normal invoke function - const tx = contract.createTransaction("ClaimAsset") - const ccArgs = [assetExchangeAgreementStr, claimInfoStr] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) - ); - if (submitError) { - throw new Error(`ClaimAsset submitTransaction Error: ${submitError}`); - } - return result; + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) { + logger.error("Asset ID not supplied"); + return false; + } + if (!lockerECert) { + logger.error("Locker ECert not supplied"); + return false; + } + if (!hash) { + logger.error("Instance of Hash interface not supplied"); + return false; + } + if (!hash.preimage) { + logger.error("Hash Preimage not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized( + assetType, + assetID, + "", + lockerECert, + ); + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("ClaimAsset"); + const ccArgs = [assetExchangeAgreementStr, claimInfoStr]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error(`ClaimAsset submitTransaction Error: ${submitError}`); + } + return result; }; /** @@ -299,98 +362,91 @@ const claimAssetInHTLC = async ( * - Claim a unique asset instance using a hash preimage and contractId **/ const claimAssetInHTLCusingContractId = async ( - contract: Contract, - contractId: string, - hash: Hash, - endorsingOrgs: Array = [] + contract: Contract, + contractId: string, + hash: Hash, + endorsingOrgs: Array = [], ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!contractId) - { - logger.error("contract ID not supplied"); - return false; - } - if (!hash) - { - logger.error("Instance of Hash interface not supplied") - return false - } - if (!hash.preimage) - { - logger.error("Hash Preimage not supplied"); - return false; - } - - const claimInfoStr = createAssetClaimInfoSerialized(hash); - - // Normal invoke function - const tx = contract.createTransaction("ClaimAssetUsingContractId") - const ccArgs = [contractId, claimInfoStr] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) { + logger.error("contract ID not supplied"); + return false; + } + if (!hash) { + logger.error("Instance of Hash interface not supplied"); + return false; + } + if (!hash.preimage) { + logger.error("Hash Preimage not supplied"); + return false; + } + + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("ClaimAssetUsingContractId"); + const ccArgs = [contractId, claimInfoStr]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error( + `ClaimAssetUsingContractId submitTransaction Error: ${submitError}`, ); - if (submitError) { - throw new Error(`ClaimAssetUsingContractId submitTransaction Error: ${submitError}`); - } - return result; + } + return result; }; - /** * Latter step of a Hashed Time Lock Contract * - Claim a set of fungible assets using a hash preimage **/ const claimFungibleAssetInHTLC = async ( - contract: Contract, - contractId: string, - hash: Hash, - endorsingOrgs: Array = [] + contract: Contract, + contractId: string, + hash: Hash, + endorsingOrgs: Array = [], ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!contractId) - { - logger.error("contract ID not supplied"); - return false; - } - if (!hash) - { - logger.error("Instance of Hash interface not supplied") - return false - } - if (!hash.preimage) - { - logger.error("Hash Preimage not supplied"); - return false; - } - - const claimInfoStr = createAssetClaimInfoSerialized(hash); - - // Normal invoke function - const tx = contract.createTransaction("ClaimFungibleAsset") - const ccArgs = [contractId, claimInfoStr] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) { + logger.error("contract ID not supplied"); + return false; + } + if (!hash) { + logger.error("Instance of Hash interface not supplied"); + return false; + } + if (!hash.preimage) { + logger.error("Hash Preimage not supplied"); + return false; + } + + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("ClaimFungibleAsset"); + const ccArgs = [contractId, claimInfoStr]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error( + `ClaimFungibleAsset submitTransaction Error: ${submitError}`, ); - if (submitError) { - throw new Error(`ClaimFungibleAsset submitTransaction Error: ${submitError}`); - } - return result; + } + return result; }; /** @@ -398,49 +454,49 @@ const claimFungibleAssetInHTLC = async ( * - Reclaim a unique asset instance **/ const reclaimAssetInHTLC = async ( - contract: Contract, - assetType: string, - assetID: string, - recipientECert: string, - endorsingOrgs: Array = [] + contract: Contract, + assetType: string, + assetID: string, + recipientECert: string, + endorsingOrgs: Array = [], ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!assetType) - { - logger.error("Asset type not supplied"); - return false; - } - if (!assetID) - { - logger.error("Asset ID not supplied"); - return false; - } - if (!recipientECert) - { - logger.error("Recipient ECert not supplied"); - return false; - } - - const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, ""); - - // Normal invoke function - const tx = contract.createTransaction("UnlockAsset") - const ccArgs = [assetExchangeAgreementStr] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) - ); - if (submitError) { - throw new Error(`UnlockAsset submitTransaction Error: ${submitError}`); - } - return result; + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) { + logger.error("Asset ID not supplied"); + return false; + } + if (!recipientECert) { + logger.error("Recipient ECert not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + "", + ); + + // Normal invoke function + const tx = contract.createTransaction("UnlockAsset"); + const ccArgs = [assetExchangeAgreementStr]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error(`UnlockAsset submitTransaction Error: ${submitError}`); + } + return result; }; /** @@ -448,35 +504,34 @@ const reclaimAssetInHTLC = async ( * - Reclaim a unique asset instance using contractId **/ const reclaimAssetInHTLCusingContractId = async ( - contract: Contract, - contractId: string, - endorsingOrgs: Array = [] + contract: Contract, + contractId: string, + endorsingOrgs: Array = [], ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!contractId) - { - logger.error("contract ID not supplied"); - return false; - } - - // Normal invoke function - const tx = contract.createTransaction("UnlockAssetUsingContractId") - const ccArgs = [contractId] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const tx = contract.createTransaction("UnlockAssetUsingContractId"); + const ccArgs = [contractId]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error( + `UnlockAssetUsingContractId submitTransaction Error: ${submitError}`, ); - if (submitError) { - throw new Error(`UnlockAssetUsingContractId submitTransaction Error: ${submitError}`); - } - return result; + } + return result; }; /** @@ -484,35 +539,34 @@ const reclaimAssetInHTLCusingContractId = async ( * - Reclaim a set of fungible assets **/ const reclaimFungibleAssetInHTLC = async ( - contract: Contract, - contractId: string, - endorsingOrgs: Array = [] + contract: Contract, + contractId: string, + endorsingOrgs: Array = [], ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!contractId) - { - logger.error("contract ID not supplied"); - return false; - } - - // Normal invoke function - const tx = contract.createTransaction("UnlockFungibleAsset") - const ccArgs = [contractId] - if (endorsingOrgs && endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const tx = contract.createTransaction("UnlockFungibleAsset"); + const ccArgs = [contractId]; + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error( + `UnlockFungibleAsset submitTransaction Error: ${submitError}`, ); - if (submitError) { - throw new Error(`UnlockFungibleAsset submitTransaction Error: ${submitError}`); - } - return result; + } + return result; }; /** @@ -520,49 +574,50 @@ const reclaimFungibleAssetInHTLC = async ( * - Determine if a unique asset instance is locked by a given party for another given party **/ const isAssetLockedInHTLC = async ( - contract: Contract, - assetType: string, - assetID: string, - recipientECert: string, - lockerECert: string, + contract: Contract, + assetType: string, + assetID: string, + recipientECert: string, + lockerECert: string, ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!assetType) - { - logger.error("Asset type not supplied"); - return false; - } - if (!assetID) - { - logger.error("Asset ID not supplied"); - return false; - } - if (!recipientECert) - { - logger.error("Recipient ECert not supplied"); - return false; - } - if (!lockerECert) - { - logger.error("Locker ECert not supplied"); - return false; - } - - const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, lockerECert); - - // Normal invoke function - const [result, evaluateError] = await helpers.handlePromise( - contract.evaluateTransaction("IsAssetLocked", assetExchangeAgreementStr), + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) { + logger.error("Asset ID not supplied"); + return false; + } + if (!recipientECert) { + logger.error("Recipient ECert not supplied"); + return false; + } + if (!lockerECert) { + logger.error("Locker ECert not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + lockerECert, + ); + + // Normal invoke function + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("IsAssetLocked", assetExchangeAgreementStr), + ); + if (evaluateError) { + throw new Error( + `IsAssetLocked evaluateTransaction Error: ${evaluateError}`, ); - if (evaluateError) { - throw new Error(`IsAssetLocked evaluateTransaction Error: ${evaluateError}`); - } - return result.toString() === "true"; + } + return result.toString() === "true"; }; /** @@ -570,29 +625,31 @@ const isAssetLockedInHTLC = async ( * - Determine if a unique asset instance is locked by a given party for another given party **/ const isAssetLockedInHTLCqueryUsingContractId = async ( - contract: Contract, - contractId: string, + contract: Contract, + contractId: string, ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!contractId) - { - logger.error("contract ID not supplied"); - return false; - } - - // Normal invoke function - const [result, evaluateError] = await helpers.handlePromise( - contract.evaluateTransaction("IsAssetLockedQueryUsingContractId", contractId), + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction( + "IsAssetLockedQueryUsingContractId", + contractId, + ), + ); + if (evaluateError) { + throw new Error( + `IsAssetLockedQueryUsingContractId evaluateTransaction Error: ${evaluateError}`, ); - if (evaluateError) { - throw new Error(`IsAssetLockedQueryUsingContractId evaluateTransaction Error: ${evaluateError}`); - } - return result.toString() === "true"; + } + return result.toString() === "true"; }; /** @@ -600,32 +657,30 @@ const isAssetLockedInHTLCqueryUsingContractId = async ( * - Determine if a set of fungible assets is locked by a given party for another given party **/ const isFungibleAssetLockedInHTLC = async ( - contract: Contract, - contractId: string, + contract: Contract, + contractId: string, ): Promise => { - - if (!contract) - { - logger.error("Contract handle not supplied"); - return false; - } - if (!contractId) - { - logger.error("contract ID not supplied"); - return false; - } - - // Normal invoke function - const [result, evaluateError] = await helpers.handlePromise( - contract.evaluateTransaction("IsFungibleAssetLocked", contractId), + if (!contract) { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("IsFungibleAssetLocked", contractId), + ); + if (evaluateError) { + throw new Error( + `IsFungibleAssetLocked evaluateTransaction Error: ${evaluateError}`, ); - if (evaluateError) { - throw new Error(`IsFungibleAssetLocked evaluateTransaction Error: ${evaluateError}`); - } - return result.toString() === "true"; + } + return result.toString() === "true"; }; - /** * HTLC Lifecycle Events * - Developers should note that event emission and actions in response occur on a best effort basis. @@ -637,416 +692,708 @@ const isFungibleAssetLockedInHTLC = async ( * The below functions trigger callbacks passed as arguments when a matching event is received from the contract layer **/ const StartHTLCEventListener = ( - contract: Contract, - eventName: string, - contractId: string, - assetType: string, - assetId: string, - numUnits: number, - recipientECert: string, - lockerECert: string, - eventCallback: Function, - endorsingOrgs: Array = [], + contract: Contract, + eventName: string, + contractId: string, + assetType: string, + assetId: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + eventCallback: Function, + endorsingOrgs: Array = [], ): void => { - const listener: ContractListener = async (event) => { - if (event.eventName === eventName) { - let assetLockContractInfo; - - if (eventName.includes('Fungible')) { - const eventInfo: assetLocksPb.FungibleAssetContractHTLC = assetLocksPb.FungibleAssetContractHTLC.deserializeBinary(event.payload); - assetLockContractInfo = eventInfo; - } - else { - const eventInfo: assetLocksPb.AssetContractHTLC = assetLocksPb.AssetContractHTLC.deserializeBinary(event.payload); - assetLockContractInfo = eventInfo; - } - const infoContractId = assetLockContractInfo.getContractid(); - if (contractId && contractId.length > 0) { - if (infoContractId.length > 0 && infoContractId !== contractId) { - return; - } - } - const infoAssetType = assetLockContractInfo.getAgreement().getAssettype(); - if (assetType && assetType.length > 0) { - if (infoAssetType.length > 0 && infoAssetType !== assetType) { - return; - } - } - let infoNumUnits: number, infoAssetId: string; - if (eventName.includes('Fungible')) { - infoNumUnits = assetLockContractInfo.getAgreement().getNumunits(); - if (infoNumUnits != numUnits) { - return; - } - } - else { - infoAssetId = assetLockContractInfo.getAgreement().getId(); - if (assetId && assetId.length > 0) { - if (infoAssetId.length > 0 && infoAssetId !== assetId) { - return; - } - } - } - const infoRecipient = assetLockContractInfo.getAgreement().getRecipient(); - if (recipientECert && recipientECert.length > 0) { - if (infoRecipient.length > 0 && infoRecipient !== recipientECert) { - return; - } - } - const infoLocker = assetLockContractInfo.getAgreement().getLocker(); - if (lockerECert && lockerECert.length > 0) { - if (infoLocker.length > 0 && infoLocker !== lockerECert) { - return; - } - } - // All filters passed - if (eventName === 'LockAsset' || eventName === 'LockFungibleAsset') { - const timeout = assetLockContractInfo.getLock().getExpirytimesecs(); - const hashBase64 = assetLockContractInfo.getLock().getHashbase64(); - let hash: Hash; - - const hashMechanism = assetLockContractInfo.getLock().getHashmechanism(); - if (hashMechanism === assetLocksPb.HashMechanism.SHA256) { - hash = new SHA256(); - } - else if (hashMechanism === assetLocksPb.HashMechanism.SHA512) { - hash = new SHA512(); - } - else { - throw new Error(`Hash Mechanism not supported`); - } - hash.setSerializedHashBase64(hashBase64); - // We only care about timeouts for locking the asset, not for the unlock itself - if (eventName === 'LockAsset') { - eventCallback(contract, infoContractId, infoAssetType, infoAssetId, infoRecipient, infoLocker, hash, timeout, endorsingOrgs); - } - else { - eventCallback(contract, infoContractId, infoAssetType, infoNumUnits, infoRecipient, infoLocker, hash, timeout, endorsingOrgs); - } - } else if (eventName === 'ClaimAsset' || eventName === 'ClaimFungibleAsset') { - const hashPreimageBase64 = assetLockContractInfo.getClaim().getHashpreimagebase64(); - const hashPreimage: string = Buffer.from(hashPreimageBase64.toString(), 'base64').toString('utf8'); - if (eventName === 'ClaimAsset') { - eventCallback(contract, infoContractId, infoAssetType, infoAssetId, infoRecipient, infoLocker, hashPreimage); - } - else { - eventCallback(contract, infoContractId, infoAssetType, infoNumUnits, infoRecipient, infoLocker, hashPreimage); - } - } - else if (eventName === 'UnlockAsset') { - eventCallback(contract, infoContractId, infoAssetType, infoAssetId, infoRecipient, infoLocker); - } - else if (eventName === 'UnlockFungibleAsset') { - eventCallback(contract, infoContractId, infoAssetType, infoNumUnits, infoRecipient, infoLocker); - } + const listener: ContractListener = async (event) => { + if (event.eventName === eventName) { + let assetLockContractInfo; + + if (eventName.includes("Fungible")) { + const eventInfo: assetLocksPb.FungibleAssetContractHTLC = + assetLocksPb.FungibleAssetContractHTLC.deserializeBinary( + event.payload, + ); + assetLockContractInfo = eventInfo; + } else { + const eventInfo: assetLocksPb.AssetContractHTLC = + assetLocksPb.AssetContractHTLC.deserializeBinary(event.payload); + assetLockContractInfo = eventInfo; + } + const infoContractId = assetLockContractInfo.getContractid(); + if (contractId && contractId.length > 0) { + if (infoContractId.length > 0 && infoContractId !== contractId) { + return; } - }; - contract.addContractListener(listener); -} + } + const infoAssetType = assetLockContractInfo.getAgreement().getAssettype(); + if (assetType && assetType.length > 0) { + if (infoAssetType.length > 0 && infoAssetType !== assetType) { + return; + } + } + let infoNumUnits: number, infoAssetId: string; + if (eventName.includes("Fungible")) { + infoNumUnits = assetLockContractInfo.getAgreement().getNumunits(); + if (infoNumUnits != numUnits) { + return; + } + } else { + infoAssetId = assetLockContractInfo.getAgreement().getId(); + if (assetId && assetId.length > 0) { + if (infoAssetId.length > 0 && infoAssetId !== assetId) { + return; + } + } + } + const infoRecipient = assetLockContractInfo.getAgreement().getRecipient(); + if (recipientECert && recipientECert.length > 0) { + if (infoRecipient.length > 0 && infoRecipient !== recipientECert) { + return; + } + } + const infoLocker = assetLockContractInfo.getAgreement().getLocker(); + if (lockerECert && lockerECert.length > 0) { + if (infoLocker.length > 0 && infoLocker !== lockerECert) { + return; + } + } + // All filters passed + if (eventName === "LockAsset" || eventName === "LockFungibleAsset") { + const timeout = assetLockContractInfo.getLock().getExpirytimesecs(); + const hashBase64 = assetLockContractInfo.getLock().getHashbase64(); + let hash: Hash; + + const hashMechanism = assetLockContractInfo + .getLock() + .getHashmechanism(); + if (hashMechanism === assetLocksPb.HashMechanism.SHA256) { + hash = new SHA256(); + } else if (hashMechanism === assetLocksPb.HashMechanism.SHA512) { + hash = new SHA512(); + } else { + throw new Error(`Hash Mechanism not supported`); + } + hash.setSerializedHashBase64(hashBase64); + // We only care about timeouts for locking the asset, not for the unlock itself + if (eventName === "LockAsset") { + eventCallback( + contract, + infoContractId, + infoAssetType, + infoAssetId, + infoRecipient, + infoLocker, + hash, + timeout, + endorsingOrgs, + ); + } else { + eventCallback( + contract, + infoContractId, + infoAssetType, + infoNumUnits, + infoRecipient, + infoLocker, + hash, + timeout, + endorsingOrgs, + ); + } + } else if ( + eventName === "ClaimAsset" || + eventName === "ClaimFungibleAsset" + ) { + const hashPreimageBase64 = assetLockContractInfo + .getClaim() + .getHashpreimagebase64(); + const hashPreimage: string = Buffer.from( + hashPreimageBase64.toString(), + "base64", + ).toString("utf8"); + if (eventName === "ClaimAsset") { + eventCallback( + contract, + infoContractId, + infoAssetType, + infoAssetId, + infoRecipient, + infoLocker, + hashPreimage, + ); + } else { + eventCallback( + contract, + infoContractId, + infoAssetType, + infoNumUnits, + infoRecipient, + infoLocker, + hashPreimage, + ); + } + } else if (eventName === "UnlockAsset") { + eventCallback( + contract, + infoContractId, + infoAssetType, + infoAssetId, + infoRecipient, + infoLocker, + ); + } else if (eventName === "UnlockFungibleAsset") { + eventCallback( + contract, + infoContractId, + infoAssetType, + infoNumUnits, + infoRecipient, + infoLocker, + ); + } + } + }; + contract.addContractListener(listener); +}; const StartHTLCAssetLockListener = ( - contract: Contract, - contractId: string, - assetType: string, - assetId: string, - recipientECert: string, - lockerECert: string, - lockCallback: (c: Contract, d: string, t: string, i: string, r: string, l: string, v: Hash, timeout: number, eOrgs: Array) => any, - endorsingOrgs: Array = [], + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, + lockCallback: ( + c: Contract, + d: string, + t: string, + i: string, + r: string, + l: string, + v: Hash, + timeout: number, + eOrgs: Array, + ) => any, + endorsingOrgs: Array = [], ): void => { - StartHTLCEventListener(contract, 'LockAsset', contractId, assetType, assetId, -1, recipientECert, lockerECert, lockCallback, endorsingOrgs); -} + StartHTLCEventListener( + contract, + "LockAsset", + contractId, + assetType, + assetId, + -1, + recipientECert, + lockerECert, + lockCallback, + endorsingOrgs, + ); +}; // NOTE: For Nonfungible Assets // Byzantine Swaps: Timed counterpart for timed AssetLockListener for reversion const assetLockExpirationCallback = ( - contract: Contract, - contractID: string, - assetType: string, - assetID: string, - recipientECert: string, - lockerECert: string, - hash: Hash, - expiryTime: number, - endorsingOrgs: Array = [] + contract: Contract, + contractID: string, + assetType: string, + assetID: string, + recipientECert: string, + lockerECert: string, + hash: Hash, + expiryTime: number, + endorsingOrgs: Array = [], ): void => { - // Compare expiryTimeSec with currentTimeSec, which is number of milliseconds since epoch (L174) - const currTimeSecs = Math.floor(Date.now()/1000); - const reclaimCallback = async (contract: Contract, contractID: string) => { - // Check if asset hasn't been claimed yet. If true, do nothing. If false, either do the following cases: - const [islocked, isLockedQueryError] = await helpers.handlePromise(isAssetLockedInHTLCqueryUsingContractId(contract, contractID)); - if (islocked === false) { - // CASE #1: Check GetHTLCHashPreImageByContractId(contractId) - const [result, evaluateError] = await helpers.handlePromise( - contract.evaluateTransaction("GetHTLCHashPreImageByContractId", contractID), + // Compare expiryTimeSec with currentTimeSec, which is number of milliseconds since epoch (L174) + const currTimeSecs = Math.floor(Date.now() / 1000); + const reclaimCallback = async (contract: Contract, contractID: string) => { + // Check if asset hasn't been claimed yet. If true, do nothing. If false, either do the following cases: + const [islocked, isLockedQueryError] = await helpers.handlePromise( + isAssetLockedInHTLCqueryUsingContractId(contract, contractID), + ); + if (islocked === false) { + // CASE #1: Check GetHTLCHashPreImageByContractId(contractId) + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction( + "GetHTLCHashPreImageByContractId", + contractID, + ), + ); + + // CASE #2: If the function above returns ANY error, call reclaimAssetInHTLC + if (evaluateError) { + // Put retry logic in event of failure. Retry 3x and then give up if unsuccessful (temp solution for now; requires CORE changes) + // If it fails, retry for i (arbitrarily defined) more attempts until you quit + let i = 0; + do { + const [retryReclaimResult, retryReclaimableQueryError] = + await helpers.handlePromise( + reclaimAssetInHTLCusingContractId( + contract, + contractID, + endorsingOrgs, + ), ); - - // CASE #2: If the function above returns ANY error, call reclaimAssetInHTLC - if (evaluateError) { - // Put retry logic in event of failure. Retry 3x and then give up if unsuccessful (temp solution for now; requires CORE changes) - // If it fails, retry for i (arbitrarily defined) more attempts until you quit - let i = 0; - do { - let [retryReclaimResult, retryReclaimableQueryError] = await helpers.handlePromise(reclaimAssetInHTLCusingContractId(contract, contractID, endorsingOrgs)); - if (!retryReclaimableQueryError) { - console.log("Nonfungible Asset unlocked successfully"); - break; - } - - i++; - } while (i < 3); - } - } - } - - // If you have time remaining, call setTimeout with reclaimCallback - if (expiryTime - currTimeSecs > 0) { - setTimeout(reclaimCallback, 1000 * (expiryTime - currTimeSecs), contract, contractID); - } else { - // If no time remaining, call the reclaim callback immediately - reclaimCallback(contract, contractID); - } -} + if (!retryReclaimableQueryError) { + console.log("Nonfungible Asset unlocked successfully"); + break; + } + + i++; + } while (i < 3); + } + } + }; + + // If you have time remaining, call setTimeout with reclaimCallback + if (expiryTime - currTimeSecs > 0) { + setTimeout( + reclaimCallback, + 1000 * (expiryTime - currTimeSecs), + contract, + contractID, + ); + } else { + // If no time remaining, call the reclaim callback immediately + reclaimCallback(contract, contractID); + } +}; //NOTE: FUNGIBLE counterpart // Byzantine Swaps: Timed counterpart for timed AssetLockListener for reversion const fungibleAssetLockExpirationCallback = ( - contract: Contract, - contractID: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, - hash: Hash, - expiryTime: number, - endorsingOrgs: Array = [] + contract: Contract, + contractID: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + hash: Hash, + expiryTime: number, + endorsingOrgs: Array = [], ): void => { - // Compare expiryTimeSec with currentTimeSec, which is number of milliseconds since epoch (L174) - const currTimeSecs = Math.floor(Date.now()/1000); - const reclaimCallback = async (contract: Contract, contractID: string) => { - // Check if asset hasn't been claimed yet. If true, do nothing. If false, either do the following cases: - const [islocked, isLockedQueryError] = await helpers.handlePromise(isFungibleAssetLockedInHTLC(contract, contractID)); - - if (islocked === false) { - // CASE #1: Check GetHTLCHashPreImageByContractId(contractId) - const [result, evaluateError] = await helpers.handlePromise( - contract.evaluateTransaction("GetHTLCHashPreImageByContractId", contractID), - ); - - // CASE #2: If the function above returns ANY error, call reclaimAssetInHTLC - if (evaluateError) { - // Put retry logic in event of failure. Retry 3x and then give up if unsuccessful (temp solution for now; requires CORE changes) - // If it fails, retry for i (arbitrarily defined) more attempts until you quit - let i = 0; - do { - let [retryReclaimResult, retryReclaimableQueryError] = await helpers.handlePromise(reclaimFungibleAssetInHTLC(contract, contractID, endorsingOrgs)); - if (!retryReclaimableQueryError) { - console.log("Fungible Asset unlocked successfully"); - break; - } - - i++; - } while (i < 3); - } - } - } + // Compare expiryTimeSec with currentTimeSec, which is number of milliseconds since epoch (L174) + const currTimeSecs = Math.floor(Date.now() / 1000); + const reclaimCallback = async (contract: Contract, contractID: string) => { + // Check if asset hasn't been claimed yet. If true, do nothing. If false, either do the following cases: + const [islocked, isLockedQueryError] = await helpers.handlePromise( + isFungibleAssetLockedInHTLC(contract, contractID), + ); - // If you have time remaining, call setTimeout with reclaimCallback - if (expiryTime - currTimeSecs > 0) { - setTimeout(reclaimCallback, 1000 * (expiryTime - currTimeSecs), contract, contractID); - } else { - // If no time remaining, call the reclaim callback immediately - reclaimCallback(contract, contractID); - } -} + if (islocked === false) { + // CASE #1: Check GetHTLCHashPreImageByContractId(contractId) + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction( + "GetHTLCHashPreImageByContractId", + contractID, + ), + ); + + // CASE #2: If the function above returns ANY error, call reclaimAssetInHTLC + if (evaluateError) { + // Put retry logic in event of failure. Retry 3x and then give up if unsuccessful (temp solution for now; requires CORE changes) + // If it fails, retry for i (arbitrarily defined) more attempts until you quit + let i = 0; + do { + const [retryReclaimResult, retryReclaimableQueryError] = + await helpers.handlePromise( + reclaimFungibleAssetInHTLC(contract, contractID, endorsingOrgs), + ); + if (!retryReclaimableQueryError) { + console.log("Fungible Asset unlocked successfully"); + break; + } + + i++; + } while (i < 3); + } + } + }; + + // If you have time remaining, call setTimeout with reclaimCallback + if (expiryTime - currTimeSecs > 0) { + setTimeout( + reclaimCallback, + 1000 * (expiryTime - currTimeSecs), + contract, + contractID, + ); + } else { + // If no time remaining, call the reclaim callback immediately + reclaimCallback(contract, contractID); + } +}; const StartHTLCAssetClaimListener = ( - contract: Contract, - contractId: string, - assetType: string, - assetId: string, - recipientECert: string, - lockerECert: string, - claimCallback: (c: Contract, d: string, t: string, i: string, r: string, l: string, p: string) => any, + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, + claimCallback: ( + c: Contract, + d: string, + t: string, + i: string, + r: string, + l: string, + p: string, + ) => any, ): void => { - StartHTLCEventListener(contract, 'ClaimAsset', contractId, assetType, assetId, -1, recipientECert, lockerECert, claimCallback); -} + StartHTLCEventListener( + contract, + "ClaimAsset", + contractId, + assetType, + assetId, + -1, + recipientECert, + lockerECert, + claimCallback, + ); +}; const StartHTLCAssetUnlockListener = ( - contract: Contract, - contractId: string, - assetType: string, - assetId: string, - recipientECert: string, - lockerECert: string, - unlockCallback: (c: Contract, d: string, t: string, i: string, r: string, l: string) => any, + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, + unlockCallback: ( + c: Contract, + d: string, + t: string, + i: string, + r: string, + l: string, + ) => any, ): void => { - StartHTLCEventListener(contract, 'UnlockAsset', contractId, assetType, assetId, -1, recipientECert, lockerECert, unlockCallback); -} + StartHTLCEventListener( + contract, + "UnlockAsset", + contractId, + assetType, + assetId, + -1, + recipientECert, + lockerECert, + unlockCallback, + ); +}; const StartHTLCFungibleAssetLockListener = ( - contract: Contract, - contractId: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, - lockCallback: (c: Contract, d: string, t: string, n: number, r: string, l: string, v: Hash, timeout: number, eOrgs: Array) => any, - endorsingOrgs: Array = [], + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + lockCallback: ( + c: Contract, + d: string, + t: string, + n: number, + r: string, + l: string, + v: Hash, + timeout: number, + eOrgs: Array, + ) => any, + endorsingOrgs: Array = [], ): void => { - StartHTLCEventListener(contract, 'LockFungibleAsset', contractId, assetType, "", numUnits, recipientECert, lockerECert, lockCallback, endorsingOrgs); -} + StartHTLCEventListener( + contract, + "LockFungibleAsset", + contractId, + assetType, + "", + numUnits, + recipientECert, + lockerECert, + lockCallback, + endorsingOrgs, + ); +}; const StartHTLCFungibleAssetClaimListener = ( - contract: Contract, - contractId: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, - claimCallback: (c: Contract, d: string, t: string, n: number, r: string, l: string, p: string) => any, + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + claimCallback: ( + c: Contract, + d: string, + t: string, + n: number, + r: string, + l: string, + p: string, + ) => any, ): void => { - StartHTLCEventListener(contract, 'ClaimFungibleAsset', contractId, assetType, "", numUnits, recipientECert, lockerECert, claimCallback); -} + StartHTLCEventListener( + contract, + "ClaimFungibleAsset", + contractId, + assetType, + "", + numUnits, + recipientECert, + lockerECert, + claimCallback, + ); +}; const StartHTLCFungibleAssetUnlockListener = ( - contract: Contract, - contractId: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, - unlockCallback: (c: Contract, d: string, t: string, n: number, r: string, l: string) => any, + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + unlockCallback: ( + c: Contract, + d: string, + t: string, + n: number, + r: string, + l: string, + ) => any, ): void => { - StartHTLCEventListener(contract, 'UnlockFungibleAsset', contractId, assetType, "", numUnits, recipientECert, lockerECert, unlockCallback); -} + StartHTLCEventListener( + contract, + "UnlockFungibleAsset", + contractId, + assetType, + "", + numUnits, + recipientECert, + lockerECert, + unlockCallback, + ); +}; /** * The below functions return promises for HTLC events. * Developers can use 'await' to synchronously manage asset swapping logic. **/ - const HTLCAssetLocked = async ( - contract: Contract, - contractId: string, - assetType: string, - assetId: string, - recipientECert: string, - lockerECert: string, +const HTLCAssetLocked = async ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, ): Promise => { - return new Promise((resolve, reject) => { - const waitForLock = (contract, contractId, assetType, assetId, recipientECert, lockerECert, hashValue) => { - resolve(hashValue); - }; - StartHTLCAssetLockListener(contract, contractId, assetType, assetId, recipientECert, lockerECert, waitForLock); - }); -} + return new Promise((resolve, reject) => { + const waitForLock = ( + contract, + contractId, + assetType, + assetId, + recipientECert, + lockerECert, + hashValue, + ) => { + resolve(hashValue); + }; + StartHTLCAssetLockListener( + contract, + contractId, + assetType, + assetId, + recipientECert, + lockerECert, + waitForLock, + ); + }); +}; const HTLCAssetClaimed = async ( - contract: Contract, - contractId: string, - assetType: string, - assetId: string, - recipientECert: string, - lockerECert: string, + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, ): Promise => { - return new Promise((resolve, reject) => { - const waitForClaim = (contract, contractId, assetType, assetId, recipientECert, lockerECert, hashPreimage) => { - resolve(hashPreimage); - }; - StartHTLCAssetClaimListener(contract, contractId, assetType, assetId, recipientECert, lockerECert, waitForClaim); - }); -} + return new Promise((resolve, reject) => { + const waitForClaim = ( + contract, + contractId, + assetType, + assetId, + recipientECert, + lockerECert, + hashPreimage, + ) => { + resolve(hashPreimage); + }; + StartHTLCAssetClaimListener( + contract, + contractId, + assetType, + assetId, + recipientECert, + lockerECert, + waitForClaim, + ); + }); +}; const HTLCAssetUnlocked = async ( - contract: Contract, - contractId: string, - assetType: string, - assetId: string, - recipientECert: string, - lockerECert: string, + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, ): Promise => { - return new Promise((resolve, reject) => { - const waitForUnlock = (contract, contractId, assetType, assetId, recipientECert, lockerECert) => { - resolve(); - }; - StartHTLCAssetUnlockListener(contract, contractId, assetType, assetId, recipientECert, lockerECert, waitForUnlock); - }); -} + return new Promise((resolve, reject) => { + const waitForUnlock = ( + contract, + contractId, + assetType, + assetId, + recipientECert, + lockerECert, + ) => { + resolve(); + }; + StartHTLCAssetUnlockListener( + contract, + contractId, + assetType, + assetId, + recipientECert, + lockerECert, + waitForUnlock, + ); + }); +}; const HTLCFungibleAssetLocked = async ( - contract: Contract, - contractId: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, ): Promise => { - return new Promise((resolve, reject) => { - const waitForLock = (contract, contractId, assetType, numUnits, recipientECert, lockerECert, hashValue) => { - resolve(hashValue); - }; - StartHTLCFungibleAssetLockListener(contract, contractId, assetType, numUnits, recipientECert, lockerECert, waitForLock); - }); -} + return new Promise((resolve, reject) => { + const waitForLock = ( + contract, + contractId, + assetType, + numUnits, + recipientECert, + lockerECert, + hashValue, + ) => { + resolve(hashValue); + }; + StartHTLCFungibleAssetLockListener( + contract, + contractId, + assetType, + numUnits, + recipientECert, + lockerECert, + waitForLock, + ); + }); +}; const HTLCFungibleAssetClaimed = async ( - contract: Contract, - contractId: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, ): Promise => { - return new Promise((resolve, reject) => { - const waitForClaim = (contract, contractId, assetType, numUnits, recipientECert, lockerECert, hashPreimage) => { - resolve(hashPreimage); - }; - StartHTLCFungibleAssetClaimListener(contract, contractId, assetType, numUnits, recipientECert, lockerECert, waitForClaim); - }); -} + return new Promise((resolve, reject) => { + const waitForClaim = ( + contract, + contractId, + assetType, + numUnits, + recipientECert, + lockerECert, + hashPreimage, + ) => { + resolve(hashPreimage); + }; + StartHTLCFungibleAssetClaimListener( + contract, + contractId, + assetType, + numUnits, + recipientECert, + lockerECert, + waitForClaim, + ); + }); +}; const HTLCFungibleAssetUnlocked = async ( - contract: Contract, - contractId: string, - assetType: string, - numUnits: number, - recipientECert: string, - lockerECert: string, + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, ): Promise => { - return new Promise((resolve, reject) => { - const waitForUnlock = (contract, contractId, assetType, numUnits, recipientECert, lockerECert) => { - resolve(); - }; - StartHTLCFungibleAssetUnlockListener(contract, contractId, assetType, numUnits, recipientECert, lockerECert, waitForUnlock); - }); -} + return new Promise((resolve, reject) => { + const waitForUnlock = ( + contract, + contractId, + assetType, + numUnits, + recipientECert, + lockerECert, + ) => { + resolve(); + }; + StartHTLCFungibleAssetUnlockListener( + contract, + contractId, + assetType, + numUnits, + recipientECert, + lockerECert, + waitForUnlock, + ); + }); +}; export { - createAssetExchangeAgreementSerialized, - createFungibleAssetExchangeAgreementSerialized, - createAssetLockInfoSerialized, - createAssetClaimInfoSerialized, - createHTLC, - createFungibleHTLC, - claimAssetInHTLC, - claimAssetInHTLCusingContractId, - claimFungibleAssetInHTLC, - reclaimAssetInHTLC, - reclaimAssetInHTLCusingContractId, - reclaimFungibleAssetInHTLC, - isAssetLockedInHTLC, - isAssetLockedInHTLCqueryUsingContractId, - isFungibleAssetLockedInHTLC, - StartHTLCAssetLockListener, - StartHTLCAssetClaimListener, - StartHTLCAssetUnlockListener, - StartHTLCFungibleAssetLockListener, - StartHTLCFungibleAssetClaimListener, - StartHTLCFungibleAssetUnlockListener, - HTLCAssetLocked, - HTLCAssetClaimed, - HTLCAssetUnlocked, - HTLCFungibleAssetLocked, - HTLCFungibleAssetClaimed, - HTLCFungibleAssetUnlocked, + createAssetExchangeAgreementSerialized, + createFungibleAssetExchangeAgreementSerialized, + createAssetLockInfoSerialized, + createAssetClaimInfoSerialized, + createHTLC, + createFungibleHTLC, + claimAssetInHTLC, + claimAssetInHTLCusingContractId, + claimFungibleAssetInHTLC, + reclaimAssetInHTLC, + reclaimAssetInHTLCusingContractId, + reclaimFungibleAssetInHTLC, + isAssetLockedInHTLC, + isAssetLockedInHTLCqueryUsingContractId, + isFungibleAssetLockedInHTLC, + StartHTLCAssetLockListener, + StartHTLCAssetClaimListener, + StartHTLCAssetUnlockListener, + StartHTLCFungibleAssetLockListener, + StartHTLCFungibleAssetClaimListener, + StartHTLCFungibleAssetUnlockListener, + HTLCAssetLocked, + HTLCAssetClaimed, + HTLCAssetUnlocked, + HTLCFungibleAssetLocked, + HTLCFungibleAssetClaimed, + HTLCFungibleAssetUnlocked, }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/EventsManager.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/EventsManager.ts index 943ff2a819..29f7aed185 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/EventsManager.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/EventsManager.ts @@ -16,293 +16,330 @@ import { Contract } from "fabric-network"; import eventsPb from "@hyperledger/cacti-weaver-protos-js/common/events_pb"; import { Relay } from "./Relay"; import { InteropJSON } from "./types"; -import { getPolicyCriteriaForAddress, createAddress, signMessage } from "./InteroperableHelper"; +import { + getPolicyCriteriaForAddress, + createAddress, + signMessage, +} from "./InteroperableHelper"; import * as helpers from "./helpers"; const logger = log4js.getLogger("EventsManager"); -function createEventMatcher ({ - eventType, - eventClassId, - transactionLedgerId, - transactionContractId, - transactionFunc +function createEventMatcher({ + eventType, + eventClassId, + transactionLedgerId, + transactionContractId, + transactionFunc, }: { - eventType: eventsPb.EventType, - eventClassId: string, - transactionLedgerId: string, - transactionContractId: string, - transactionFunc: string + eventType: eventsPb.EventType; + eventClassId: string; + transactionLedgerId: string; + transactionContractId: string; + transactionFunc: string; }): eventsPb.EventMatcher { - const eventMatcher = new eventsPb.EventMatcher() - eventMatcher.setEventType(eventType) - eventMatcher.setEventClassId(eventClassId) - eventMatcher.setTransactionLedgerId(transactionLedgerId) - eventMatcher.setTransactionContractId(transactionContractId) - eventMatcher.setTransactionFunc(transactionFunc) - return eventMatcher + const eventMatcher = new eventsPb.EventMatcher(); + eventMatcher.setEventType(eventType); + eventMatcher.setEventClassId(eventClassId); + eventMatcher.setTransactionLedgerId(transactionLedgerId); + eventMatcher.setTransactionContractId(transactionContractId); + eventMatcher.setTransactionFunc(transactionFunc); + return eventMatcher; } - -function createEventPublicationSpec ({ - appUrl, - driverId, - channelId, - chaincodeId, - ccFunc, - ccArgs, - replaceArgIndex, - members +function createEventPublicationSpec({ + appUrl, + driverId, + channelId, + chaincodeId, + ccFunc, + ccArgs, + replaceArgIndex, + members, }: { - appUrl?: string, - driverId?: string, - channelId?: string, - chaincodeId?: string, - ccFunc?: string, - ccArgs?: string[], - replaceArgIndex?: number, - members?: string[] + appUrl?: string; + driverId?: string; + channelId?: string; + chaincodeId?: string; + ccFunc?: string; + ccArgs?: string[]; + replaceArgIndex?: number; + members?: string[]; }): eventsPb.EventPublication { - const eventPublicationSpec = new eventsPb.EventPublication() - if (appUrl) { - eventPublicationSpec.setAppUrl(appUrl) - } else { - - let ccArgsBytes = []; - for (const ccArg of ccArgs) { - ccArgsBytes.push(Buffer.from(ccArg)); - } - console.log(`ccArgs: ${ccArgs} ccArgsBytes: ${ccArgsBytes}`) - - const ctx = new eventsPb.ContractTransaction() - ctx.setDriverId(driverId) - ctx.setLedgerId(channelId) - ctx.setContractId(chaincodeId) - ctx.setFunc(ccFunc) - ctx.setArgsList(ccArgsBytes) - ctx.setReplaceArgIndex(replaceArgIndex) - if (members) { - ctx.setMembersList(members) - } - eventPublicationSpec.setCtx(ctx) + const eventPublicationSpec = new eventsPb.EventPublication(); + if (appUrl) { + eventPublicationSpec.setAppUrl(appUrl); + } else { + const ccArgsBytes = []; + for (const ccArg of ccArgs) { + ccArgsBytes.push(Buffer.from(ccArg)); + } + console.log(`ccArgs: ${ccArgs} ccArgsBytes: ${ccArgsBytes}`); + + const ctx = new eventsPb.ContractTransaction(); + ctx.setDriverId(driverId); + ctx.setLedgerId(channelId); + ctx.setContractId(chaincodeId); + ctx.setFunc(ccFunc); + ctx.setArgsList(ccArgsBytes); + ctx.setReplaceArgIndex(replaceArgIndex); + if (members) { + ctx.setMembersList(members); } - return eventPublicationSpec + eventPublicationSpec.setCtx(ctx); + } + return eventPublicationSpec; } const subscribeRemoteEvent = async ( - interopContract: Contract, - eventMatcher: eventsPb.EventMatcher, - eventPublicationSpec: eventsPb.EventPublication, - networkID: string, - org: string, - localRelayEndpoint: string, - interopJSON: InteropJSON, - keyCert: { key: ICryptoKey; cert: any }, - useTls: boolean = false, - tlsRootCACertPaths?: Array, - confidential: boolean = false, + interopContract: Contract, + eventMatcher: eventsPb.EventMatcher, + eventPublicationSpec: eventsPb.EventPublication, + networkID: string, + org: string, + localRelayEndpoint: string, + interopJSON: InteropJSON, + keyCert: { key: ICryptoKey; cert: any }, + useTls: boolean = false, + tlsRootCACertPaths?: Array, + confidential: boolean = false, ): Promise => { - logger.debug("Remote Event Subscription") - const { - address, - ChaincodeFunc, - ChaincodeID, - ChannelID, - RemoteEndpoint, - NetworkID: RemoteNetworkID, - Sign, + logger.debug("Remote Event Subscription"); + const { + address, + ChaincodeFunc, + ChaincodeID, + ChannelID, + RemoteEndpoint, + NetworkID: RemoteNetworkID, + Sign, + ccArgs: args, + } = interopJSON; + // Step 1 + const computedAddress = + address || + createAddress( + { + ccFunc: ChaincodeFunc, + contractName: ChaincodeID, + channel: ChannelID, ccArgs: args, - } = interopJSON; - // Step 1 - const computedAddress = - address || - createAddress( - { ccFunc: ChaincodeFunc, contractName: ChaincodeID, channel: ChannelID, ccArgs: args }, - RemoteNetworkID, - RemoteEndpoint, - ); - - const [policyCriteria, policyCriteriaError] = await helpers.handlePromise( - getPolicyCriteriaForAddress(interopContract, computedAddress), + }, + RemoteNetworkID, + RemoteEndpoint, ); - if (policyCriteriaError) { - throw new Error(`InteropFlow failed to get policy criteria: ${policyCriteriaError}`); - } - const relay = useTls ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) : new Relay(localRelayEndpoint); - const uuidValue = uuidv4(); - - logger.debug("Making event subscription call to relay for \ - event: ${eventMatcher} and publication spec: ${eventPublicationSpec}") - - const [relayResponse, relayResponseError] = await helpers.handlePromise( - relay.ProcessSubscribeEventRequest( - eventMatcher, - eventPublicationSpec, - computedAddress, - policyCriteria, - networkID, - keyCert.cert, - Sign ? signMessage(computedAddress + uuidValue, keyCert.key.toBytes()) : "", - uuidValue, - // Org is empty as the name is in the certs for - org, - confidential, - ), + const [policyCriteria, policyCriteriaError] = await helpers.handlePromise( + getPolicyCriteriaForAddress(interopContract, computedAddress), + ); + if (policyCriteriaError) { + throw new Error( + `InteropFlow failed to get policy criteria: ${policyCriteriaError}`, ); - if (relayResponseError) { - throw new Error(`Event Subscription relay response error: ${relayResponseError}`); - } - - logger.debug(`Event Subscription Successfull: ${JSON.stringify(relayResponse)}`) - - return relayResponse -} + } + const relay = useTls + ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) + : new Relay(localRelayEndpoint); + const uuidValue = uuidv4(); + + logger.debug( + "Making event subscription call to relay for \ + event: ${eventMatcher} and publication spec: ${eventPublicationSpec}", + ); + + const [relayResponse, relayResponseError] = await helpers.handlePromise( + relay.ProcessSubscribeEventRequest( + eventMatcher, + eventPublicationSpec, + computedAddress, + policyCriteria, + networkID, + keyCert.cert, + Sign + ? signMessage(computedAddress + uuidValue, keyCert.key.toBytes()) + : "", + uuidValue, + // Org is empty as the name is in the certs for + org, + confidential, + ), + ); + if (relayResponseError) { + throw new Error( + `Event Subscription relay response error: ${relayResponseError}`, + ); + } + + logger.debug( + `Event Subscription Successfull: ${JSON.stringify(relayResponse)}`, + ); + + return relayResponse; +}; const unsubscribeRemoteEvent = async ( - interopContract: Contract, - eventMatcher: eventsPb.EventMatcher, - eventPublicationSpec: eventsPb.EventPublication, - requestID: string, - networkID: string, - org: string, - localRelayEndpoint: string, - interopJSON: InteropJSON, - keyCert: { key: ICryptoKey; cert: any }, - useTls: boolean = false, - tlsRootCACertPaths?: Array, - confidential: boolean = false, + interopContract: Contract, + eventMatcher: eventsPb.EventMatcher, + eventPublicationSpec: eventsPb.EventPublication, + requestID: string, + networkID: string, + org: string, + localRelayEndpoint: string, + interopJSON: InteropJSON, + keyCert: { key: ICryptoKey; cert: any }, + useTls: boolean = false, + tlsRootCACertPaths?: Array, + confidential: boolean = false, ): Promise => { - logger.debug("Remote Event Unsubscription") - const { - address, - ChaincodeFunc, - ChaincodeID, - ChannelID, - RemoteEndpoint, - NetworkID: RemoteNetworkID, - Sign, + logger.debug("Remote Event Unsubscription"); + const { + address, + ChaincodeFunc, + ChaincodeID, + ChannelID, + RemoteEndpoint, + NetworkID: RemoteNetworkID, + Sign, + ccArgs: args, + } = interopJSON; + // Step 1 + const computedAddress = + address || + createAddress( + { + ccFunc: ChaincodeFunc, + contractName: ChaincodeID, + channel: ChannelID, ccArgs: args, - } = interopJSON; - // Step 1 - const computedAddress = - address || - createAddress( - { ccFunc: ChaincodeFunc, contractName: ChaincodeID, channel: ChannelID, ccArgs: args }, - RemoteNetworkID, - RemoteEndpoint, - ); - - const [policyCriteria, policyCriteriaError] = await helpers.handlePromise( - getPolicyCriteriaForAddress(interopContract, computedAddress), + }, + RemoteNetworkID, + RemoteEndpoint, ); - if (policyCriteriaError) { - throw new Error(`InteropFlow failed to get policy criteria: ${policyCriteriaError}`); - } - const relay = useTls ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) : new Relay(localRelayEndpoint); - const uuidValue = uuidv4(); - - logger.debug("Making event unsubscription call to relay for \ - event: ${eventMatcher} and publication spec: ${eventPublicationSpec}") - - const [relayResponse, relayResponseError] = await helpers.handlePromise( - relay.ProcessUnsubscribeEventRequest( - eventMatcher, - eventPublicationSpec, - requestID, - computedAddress, - policyCriteria, - networkID, - keyCert.cert, - Sign ? signMessage(computedAddress + uuidValue, keyCert.key.toBytes()) : "", - uuidValue, - // Org is empty as the name is in the certs for - org, - confidential, - ), + const [policyCriteria, policyCriteriaError] = await helpers.handlePromise( + getPolicyCriteriaForAddress(interopContract, computedAddress), + ); + if (policyCriteriaError) { + throw new Error( + `InteropFlow failed to get policy criteria: ${policyCriteriaError}`, ); - if (relayResponseError) { - throw new Error(`Event Unsubscription relay response error: ${relayResponseError}`); - } - - logger.debug(`Event Unsubscription Successfull: ${JSON.stringify(relayResponse)}`) - - return relayResponse -} + } + + const relay = useTls + ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) + : new Relay(localRelayEndpoint); + const uuidValue = uuidv4(); + + logger.debug( + "Making event unsubscription call to relay for \ + event: ${eventMatcher} and publication spec: ${eventPublicationSpec}", + ); + + const [relayResponse, relayResponseError] = await helpers.handlePromise( + relay.ProcessUnsubscribeEventRequest( + eventMatcher, + eventPublicationSpec, + requestID, + computedAddress, + policyCriteria, + networkID, + keyCert.cert, + Sign + ? signMessage(computedAddress + uuidValue, keyCert.key.toBytes()) + : "", + uuidValue, + // Org is empty as the name is in the certs for + org, + confidential, + ), + ); + if (relayResponseError) { + throw new Error( + `Event Unsubscription relay response error: ${relayResponseError}`, + ); + } + + logger.debug( + `Event Unsubscription Successfull: ${JSON.stringify(relayResponse)}`, + ); + + return relayResponse; +}; const getSubscriptionStatus = async ( - requestID: string, - localRelayEndpoint: string, - asJson: boolean = true, - useTls: boolean = false, - tlsRootCACertPaths?: Array, + requestID: string, + localRelayEndpoint: string, + asJson: boolean = true, + useTls: boolean = false, + tlsRootCACertPaths?: Array, ): Promise => { - logger.debug("Get Event Subscription Status") + logger.debug("Get Event Subscription Status"); - const relay = useTls ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) : new Relay(localRelayEndpoint); + const relay = useTls + ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) + : new Relay(localRelayEndpoint); - const [relayResponse, relayResponseError] = await helpers.handlePromise( - relay.GetEventSubscriptionState( - requestID, - false - ), + const [relayResponse, relayResponseError] = await helpers.handlePromise( + relay.GetEventSubscriptionState(requestID, false), + ); + if (relayResponseError) { + throw new Error( + `Get event subscription relay response error: ${relayResponseError}`, ); - if (relayResponseError) { - throw new Error(`Get event subscription relay response error: ${relayResponseError}`); - } + } - let eventSubscriptionState: eventsPb.EventSubscriptionState = relayResponse; - for (const eventPubSpec of eventSubscriptionState.getEventPublicationSpecsList()) { - if (eventPubSpec.hasCtx()) { - let ccArgsBytes = eventPubSpec.getCtx().getArgsList(); - let ccArgsStr = []; - for (const ccArgBytes of ccArgsBytes) { - ccArgsStr.push(Buffer.from(ccArgBytes).toString('utf8')); - } - eventPubSpec.getCtx().setArgsList(ccArgsStr); - } + const eventSubscriptionState: eventsPb.EventSubscriptionState = relayResponse; + for (const eventPubSpec of eventSubscriptionState.getEventPublicationSpecsList()) { + if (eventPubSpec.hasCtx()) { + const ccArgsBytes = eventPubSpec.getCtx().getArgsList(); + const ccArgsStr = []; + for (const ccArgBytes of ccArgsBytes) { + ccArgsStr.push(Buffer.from(ccArgBytes).toString("utf8")); + } + eventPubSpec.getCtx().setArgsList(ccArgsStr); } + } - logger.debug(`Get event subscription status response: ${JSON.stringify(relayResponse)}`) + logger.debug( + `Get event subscription status response: ${JSON.stringify(relayResponse)}`, + ); - return asJson? eventSubscriptionState.toObject() : relayResponse; -} + return asJson ? eventSubscriptionState.toObject() : relayResponse; +}; const getAllReceivedEvents = async ( - requestID: string, - localRelayEndpoint: string, - asJson: boolean = true, - useTls: boolean = false, - tlsRootCACertPaths?: Array, + requestID: string, + localRelayEndpoint: string, + asJson: boolean = true, + useTls: boolean = false, + tlsRootCACertPaths?: Array, ): Promise => { - logger.debug("Get all received event states") - - const relay = useTls ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) : new Relay(localRelayEndpoint); - - const [relayResponse, relayResponseError] = await helpers.handlePromise( - relay.GetEventStates( - requestID, - asJson - ), + logger.debug("Get all received event states"); + + const relay = useTls + ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) + : new Relay(localRelayEndpoint); + + const [relayResponse, relayResponseError] = await helpers.handlePromise( + relay.GetEventStates(requestID, asJson), + ); + if (relayResponseError) { + throw new Error( + `Get event states relay response error: ${relayResponseError}`, ); - if (relayResponseError) { - throw new Error(`Get event states relay response error: ${relayResponseError}`); - } - - logger.debug(`Get event states response: ${JSON.stringify(relayResponse)}`) - - return relayResponse -} + } + logger.debug(`Get event states response: ${JSON.stringify(relayResponse)}`); -export { - createEventMatcher, - createEventPublicationSpec, - subscribeRemoteEvent, - unsubscribeRemoteEvent, - getSubscriptionStatus, - getAllReceivedEvents, -} + return relayResponse; +}; +export { + createEventMatcher, + createEventPublicationSpec, + subscribeRemoteEvent, + unsubscribeRemoteEvent, + getSubscriptionStatus, + getAllReceivedEvents, +}; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/HashFunctions.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/HashFunctions.ts index 05b8b4bbdd..47db45f04e 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/HashFunctions.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/HashFunctions.ts @@ -15,75 +15,69 @@ import { HashMechanism } from "@hyperledger/cacti-weaver-protos-js/common/asset_ * and serialize the protobuf in base64 in getSerializedHashBase64 function. */ interface Hash { - HASH_MECHANISM: HashMechanism - preimage: any // Preimage for Hash - hash64: string // Serialized Hash in base64 - generateRandomPreimage(length): void; - setPreimage(preimage: any): void; - getPreimage(): any; - getSerializedPreimageBase64(): string; - setSerializedHashBase64(hash64: string): void; - getSerializedHashBase64(): string; + HASH_MECHANISM: HashMechanism; + preimage: any; // Preimage for Hash + hash64: string; // Serialized Hash in base64 + generateRandomPreimage(length): void; + setPreimage(preimage: any): void; + getPreimage(): any; + getSerializedPreimageBase64(): string; + setSerializedHashBase64(hash64: string): void; + getSerializedHashBase64(): string; } abstract class SHA implements Hash { - abstract HASH_MECHANISM: HashMechanism - preimage: string = null; - hash64: string = null; - - abstract computeHash(): string - - // Create a secure pseudo-random preimage of a given length - generateRandomPreimage(length) - { - this.setPreimage(crypto.randomBytes(length).toString('base64')); - } - - setPreimage(preimage: string) { - this.preimage = preimage - this.hash64 = this.computeHash() - } - getPreimage(): string { - return this.preimage; - } - getSerializedPreimageBase64(): string { - return Buffer.from(this.preimage).toString('base64') - } - - setSerializedHashBase64(hash64: string) { - this.hash64 = hash64; - } - getSerializedHashBase64(): string { - if(this.hash64 != null) - return this.hash64 - else - throw new Error(`Error: Hash or Preimage needs to be set before access`); - } + abstract HASH_MECHANISM: HashMechanism; + preimage: string = null; + hash64: string = null; + + abstract computeHash(): string; + + // Create a secure pseudo-random preimage of a given length + generateRandomPreimage(length) { + this.setPreimage(crypto.randomBytes(length).toString("base64")); + } + + setPreimage(preimage: string) { + this.preimage = preimage; + this.hash64 = this.computeHash(); + } + getPreimage(): string { + return this.preimage; + } + getSerializedPreimageBase64(): string { + return Buffer.from(this.preimage).toString("base64"); + } + + setSerializedHashBase64(hash64: string) { + this.hash64 = hash64; + } + getSerializedHashBase64(): string { + if (this.hash64 != null) return this.hash64; + else + throw new Error(`Error: Hash or Preimage needs to be set before access`); + } } /* * SHA256 Hash for HTLC, implementing above Hash Interface */ class SHA256 extends SHA { - HASH_MECHANISM = HashMechanism.SHA256; - - computeHash(): string { - return crypto.createHash('sha256').update(this.preimage).digest('base64'); - } + HASH_MECHANISM = HashMechanism.SHA256; + + computeHash(): string { + return crypto.createHash("sha256").update(this.preimage).digest("base64"); + } } /* * SHA512 Hash for HTLC, implementing above Hash Interface */ class SHA512 extends SHA { - HASH_MECHANISM = HashMechanism.SHA512; - - computeHash(): string { - return crypto.createHash('sha512').update(this.preimage).digest('base64'); - } + HASH_MECHANISM = HashMechanism.SHA512; + + computeHash(): string { + return crypto.createHash("sha512").update(this.preimage).digest("base64"); + } } -export { - Hash, - SHA256, - SHA512 -}; +export { Hash, SHA256, SHA512 }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/InteroperableHelper.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/InteroperableHelper.ts index e6866ba680..8d11ae47a4 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/InteroperableHelper.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/InteroperableHelper.ts @@ -19,7 +19,10 @@ import fabproto6 from "fabric-protos"; import crypto from "crypto"; import eciesCrypto from "./eciesCrypto.js"; import * as helpers from "./helpers"; -import { deserializeRemoteProposalResponseBase64, serializeRemoteProposalResponse } from "./decoders"; +import { + deserializeRemoteProposalResponseBase64, + serializeRemoteProposalResponse, +} from "./decoders"; import statePb from "@hyperledger/cacti-weaver-protos-js/common/state_pb"; import fabricViewPb from "@hyperledger/cacti-weaver-protos-js/fabric/view_data_pb"; import cordaViewPb from "@hyperledger/cacti-weaver-protos-js/corda/view_data_pb"; @@ -40,43 +43,63 @@ const contractApi = require("fabric-network/lib/contract.js"); * Generate key pair and obtain certificate from CA (MSP) **/ const getKeyAndCertForRemoteRequestbyUserName = async (wallet, username) => { - if (!wallet) { - throw new Error("No wallet passed"); - } - if (!username) { - throw new Error("No username passed"); - } - const identity = await wallet.get(username); - if (!identity) { - throw new Error(`Identity for username ${username} not present in wallet`); - } - // Assume the identity is of type 'fabric-network.X509Identity' - const privKey = FabCommon.Utils.newCryptoSuite().createKeyFromRaw(identity.credentials.privateKey); - return { key: privKey, cert: identity.credentials.certificate }; + if (!wallet) { + throw new Error("No wallet passed"); + } + if (!username) { + throw new Error("No username passed"); + } + const identity = await wallet.get(username); + if (!identity) { + throw new Error(`Identity for username ${username} not present in wallet`); + } + // Assume the identity is of type 'fabric-network.X509Identity' + const privKey = FabCommon.Utils.newCryptoSuite().createKeyFromRaw( + identity.credentials.privateKey, + ); + return { key: privKey, cert: identity.credentials.certificate }; }; -const decryptRemoteProposalResponse = (proposalResponseBytes64: string, eciesPrivateKeyPEM: any) => { - const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(eciesPrivateKeyPEM); - const propResp = deserializeRemoteProposalResponseBase64(proposalResponseBytes64); - const decryptionOptions = { hashAlgorithm: "SHA2" }; +const decryptRemoteProposalResponse = ( + proposalResponseBytes64: string, + eciesPrivateKeyPEM: any, +) => { + const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(eciesPrivateKeyPEM); + const propResp = deserializeRemoteProposalResponseBase64( + proposalResponseBytes64, + ); + const decryptionOptions = { hashAlgorithm: "SHA2" }; + propResp.payload = eciesCrypto.eciesDecryptMessage( + privKey, //@ts-ignore Issue with propResp.payload not being a string but errors when converted to a string - propResp.payload = eciesCrypto.eciesDecryptMessage(privKey, propResp.payload, decryptionOptions); - return propResp; + propResp.payload, + decryptionOptions, + ); + return propResp; }; -const decryptRemoteChaincodeOutput = (proposalResponseBytes64, eciesPrivateKeyPEM) => { - const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(eciesPrivateKeyPEM); - const propResp = deserializeRemoteProposalResponseBase64(proposalResponseBytes64); - const decryptionOptions = { hashAlgorithm: "SHA2" }; +const decryptRemoteChaincodeOutput = ( + proposalResponseBytes64, + eciesPrivateKeyPEM, +) => { + const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(eciesPrivateKeyPEM); + const propResp = deserializeRemoteProposalResponseBase64( + proposalResponseBytes64, + ); + const decryptionOptions = { hashAlgorithm: "SHA2" }; + propResp.response.payload = eciesCrypto.eciesDecryptMessage( + privKey, //@ts-ignore Issue with propResp.payload not being a string but errors when converted to a string - propResp.response.payload = eciesCrypto.eciesDecryptMessage(privKey, propResp.response.payload, decryptionOptions); - return propResp; + propResp.response.payload, + decryptionOptions, + ); + return propResp; }; const decryptData = (dataBytes, eciesPrivateKeyPEM) => { - const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(eciesPrivateKeyPEM); - const decryptionOptions = { hashAlgorithm: "SHA2" }; - return eciesCrypto.eciesDecryptMessage(privKey, dataBytes, decryptionOptions); + const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(eciesPrivateKeyPEM); + const decryptionOptions = { hashAlgorithm: "SHA2" }; + return eciesCrypto.eciesDecryptMessage(privKey, dataBytes, decryptionOptions); }; /* Validate proposal response received from remote network @@ -87,81 +110,105 @@ const decryptData = (dataBytes, eciesPrivateKeyPEM) => { * @returns {boolean} or throw error (caller should catch this) **/ const verifyDecryptedRemoteProposalResponse = async (proposalResponse) => { - logger.debug("verifyDecryptedRemoteProposalResponse - start"); - if (!proposalResponse) { - throw new Error("Missing proposal response"); - } - if (proposalResponse instanceof Error) { - return false; - } - if (!proposalResponse.endorsement) { - throw new Error("Missing ProposalResponse endorsement"); - } - - const { endorsement } = proposalResponse; - let identity; - - const sid = fabproto6.msp.SerializedIdentity.decode(endorsement.endorser); - const { mspid } = sid; - logger.debug("getMSPbyIdentity - found mspid %s", mspid); - - try { - const idCryptoSuite = FabCommon.Utils.newCryptoSuite(); - idCryptoSuite.setCryptoKeyStore(FabCommon.Utils.newCryptoKeyStore()); - const idPubKey = await idCryptoSuite.importKey(sid.id_bytes.toString(), { - // algorithm: FabCommon.CryptoAlgorithms.X509Certificate, - ephemeral: true, - }); - identity = new Identity(sid.id_bytes, idPubKey, sid.mspid, idCryptoSuite); - if (!identity) { - throw new Error("Unable to find the remote endorser identity"); - } - } catch (error) { - logger.error("verifyDecryptedRemoteProposalResponse - getting remote endorser identity failed with: ", error); - return false; + logger.debug("verifyDecryptedRemoteProposalResponse - start"); + if (!proposalResponse) { + throw new Error("Missing proposal response"); + } + if (proposalResponse instanceof Error) { + return false; + } + if (!proposalResponse.endorsement) { + throw new Error("Missing ProposalResponse endorsement"); + } + + const { endorsement } = proposalResponse; + let identity; + + const sid = fabproto6.msp.SerializedIdentity.decode(endorsement.endorser); + const { mspid } = sid; + logger.debug("getMSPbyIdentity - found mspid %s", mspid); + + try { + const idCryptoSuite = FabCommon.Utils.newCryptoSuite(); + idCryptoSuite.setCryptoKeyStore(FabCommon.Utils.newCryptoKeyStore()); + const idPubKey = await idCryptoSuite.importKey(sid.id_bytes.toString(), { + // algorithm: FabCommon.CryptoAlgorithms.X509Certificate, + ephemeral: true, + }); + identity = new Identity(sid.id_bytes, idPubKey, sid.mspid, idCryptoSuite); + if (!identity) { + throw new Error("Unable to find the remote endorser identity"); } + } catch (error) { + logger.error( + "verifyDecryptedRemoteProposalResponse - getting remote endorser identity failed with: ", + error, + ); + return false; + } - try { - // see if the identity is trusted - if (!identity.isValid()) { - logger.error("Endorser identity is not valid"); - return false; - } - logger.debug("verifyDecryptedRemoteProposalResponse - have a valid identity"); - - // check the signature against the endorser and payload hash - const digest = Buffer.concat([proposalResponse.payload, endorsement.endorser]); - if (!identity.verify(digest, endorsement.signature)) { - logger.error("Proposal signature is not valid"); - return false; - } - } catch (error) { - logger.error("verifyDecryptedRemoteProposalResponse - verify failed with: ", error); - return false; + try { + // see if the identity is trusted + if (!identity.isValid()) { + logger.error("Endorser identity is not valid"); + return false; } - logger.debug( - "verifyDecryptedRemoteProposalResponse - This endorsement has both a valid identity and valid signature", + "verifyDecryptedRemoteProposalResponse - have a valid identity", ); - return true; + + // check the signature against the endorser and payload hash + const digest = Buffer.concat([ + proposalResponse.payload, + endorsement.endorser, + ]); + if (!identity.verify(digest, endorsement.signature)) { + logger.error("Proposal signature is not valid"); + return false; + } + } catch (error) { + logger.error( + "verifyDecryptedRemoteProposalResponse - verify failed with: ", + error, + ); + return false; + } + + logger.debug( + "verifyDecryptedRemoteProposalResponse - This endorsement has both a valid identity and valid signature", + ); + return true; }; -const verifyRemoteProposalResponse = async (proposalResponseBase64, isEncrypted, privKeyPEM) => { - let decryptedProposalResponse = proposalResponseBase64; - if (isEncrypted) { - decryptedProposalResponse = decryptRemoteProposalResponse(proposalResponseBase64, privKeyPEM); - if (!decryptedProposalResponse) { - return { proposalResponse: null, valid: false }; - } - } else { - decryptedProposalResponse = deserializeRemoteProposalResponseBase64(decryptedProposalResponse); +const verifyRemoteProposalResponse = async ( + proposalResponseBase64, + isEncrypted, + privKeyPEM, +) => { + let decryptedProposalResponse = proposalResponseBase64; + if (isEncrypted) { + decryptedProposalResponse = decryptRemoteProposalResponse( + proposalResponseBase64, + privKeyPEM, + ); + if (!decryptedProposalResponse) { + return { proposalResponse: null, valid: false }; } - - const isValid = await verifyDecryptedRemoteProposalResponse(decryptedProposalResponse); - return { - proposalResponse: (serializeRemoteProposalResponse(decryptedProposalResponse) as Buffer).toString("base64"), - valid: isValid, - }; + } else { + decryptedProposalResponse = deserializeRemoteProposalResponseBase64( + decryptedProposalResponse, + ); + } + + const isValid = await verifyDecryptedRemoteProposalResponse( + decryptedProposalResponse, + ); + return { + proposalResponse: ( + serializeRemoteProposalResponse(decryptedProposalResponse) as Buffer + ).toString("base64"), + valid: isValid, + }; }; /** @@ -170,164 +217,233 @@ const verifyRemoteProposalResponse = async (proposalResponseBase64, isEncrypted, * TODO - Also take verification policy as parameter and determine if enough matching responses exist (current logic mandates unanimity among payloads) **/ const getResponseDataFromView = (view, privKeyPEM = null) => { - if (view.getMeta().getProtocol() == statePb.Meta.Protocol.FABRIC) { - const fabricView = fabricViewPb.FabricView.deserializeBinary(view.getData()); - const fabricViewProposalResponses = fabricView.getEndorsedProposalResponsesList(); - let viewAddress = ''; - let responsePayload = ''; - let responsePayloadContents = []; - let payloadConfidential = false; - for (let i = 0; i < fabricViewProposalResponses.length; i++) { - const fabricViewChaincodeAction = proposalPb.ChaincodeAction.deserializeBinary(fabricViewProposalResponses[i].getPayload().getExtension_asU8()); - const interopPayload = interopPayloadPb.InteropPayload.deserializeBinary(fabricViewChaincodeAction.getResponse().getPayload_asU8()); - if (interopPayload.getConfidential()) { // Currently this is only supported for Fabric because it uses ECDSA keys in wallets - const confidentialPayload = interopPayloadPb.ConfidentialPayload.deserializeBinary(interopPayload.getPayload_asU8()); - const decryptedPayload = decryptData(Buffer.from(confidentialPayload.getEncryptedPayload()), privKeyPEM); - const decryptedPayloadContents = interopPayloadPb.ConfidentialPayloadContents.deserializeBinary(Uint8Array.from(Buffer.from(decryptedPayload))); - if (i === 0) { - viewAddress = interopPayload.getAddress(); - responsePayload = Buffer.from(decryptedPayloadContents.getPayload()).toString(); - payloadConfidential = true; - } else if (!payloadConfidential) { - throw new Error(`Mismatching payload confidentiality flags across proposal responses`); - } else { - // Match view addresses in the different proposal responses - if (viewAddress !== interopPayload.getAddress()) { - throw new Error(`Proposal response view addresses mismatch: 0 - ${viewAddress}, ${i} - ${interopPayload.getAddress()}`); - } - // Match decrypted view payloads from the different proposal responses - const currentResponsePayload = Buffer.from(decryptedPayloadContents.getPayload()).toString(); - if (responsePayload !== currentResponsePayload) { - throw new Error(`Decrypted proposal response payloads mismatch: 0 - ${responsePayload}, ${i} - ${currentResponsePayload}`); - } - } - responsePayloadContents.push(decryptedPayload.toString("base64")); - } else { - if (i === 0) { - viewAddress = interopPayload.getAddress(); - responsePayload = Buffer.from(interopPayload.getPayload()).toString(); - payloadConfidential = false; - } else if (payloadConfidential) { - throw new Error(`Mismatching payload confidentiality flags across proposal responses`); - } else { - const currentResponsePayload = Buffer.from(interopPayload.getPayload()).toString(); - if (responsePayload !== currentResponsePayload) { - throw new Error(`Proposal response payloads mismatch: 0 - ${responsePayload}, ${i} - ${currentResponsePayload}`); - } - if (viewAddress !== interopPayload.getAddress()) { - throw new Error(`Proposal response view addresses mismatch: 0 - ${viewAddress}, ${i} - ${interopPayload.getAddress()}`); - } - } - } + if (view.getMeta().getProtocol() == statePb.Meta.Protocol.FABRIC) { + const fabricView = fabricViewPb.FabricView.deserializeBinary( + view.getData(), + ); + const fabricViewProposalResponses = + fabricView.getEndorsedProposalResponsesList(); + let viewAddress = ""; + let responsePayload = ""; + const responsePayloadContents = []; + let payloadConfidential = false; + for (let i = 0; i < fabricViewProposalResponses.length; i++) { + const fabricViewChaincodeAction = + proposalPb.ChaincodeAction.deserializeBinary( + fabricViewProposalResponses[i].getPayload().getExtension_asU8(), + ); + const interopPayload = interopPayloadPb.InteropPayload.deserializeBinary( + fabricViewChaincodeAction.getResponse().getPayload_asU8(), + ); + if (interopPayload.getConfidential()) { + // Currently this is only supported for Fabric because it uses ECDSA keys in wallets + const confidentialPayload = + interopPayloadPb.ConfidentialPayload.deserializeBinary( + interopPayload.getPayload_asU8(), + ); + const decryptedPayload = decryptData( + Buffer.from(confidentialPayload.getEncryptedPayload()), + privKeyPEM, + ); + const decryptedPayloadContents = + interopPayloadPb.ConfidentialPayloadContents.deserializeBinary( + Uint8Array.from(Buffer.from(decryptedPayload)), + ); + if (i === 0) { + viewAddress = interopPayload.getAddress(); + responsePayload = Buffer.from( + decryptedPayloadContents.getPayload(), + ).toString(); + payloadConfidential = true; + } else if (!payloadConfidential) { + throw new Error( + `Mismatching payload confidentiality flags across proposal responses`, + ); + } else { + // Match view addresses in the different proposal responses + if (viewAddress !== interopPayload.getAddress()) { + throw new Error( + `Proposal response view addresses mismatch: 0 - ${viewAddress}, ${i} - ${interopPayload.getAddress()}`, + ); + } + // Match decrypted view payloads from the different proposal responses + const currentResponsePayload = Buffer.from( + decryptedPayloadContents.getPayload(), + ).toString(); + if (responsePayload !== currentResponsePayload) { + throw new Error( + `Decrypted proposal response payloads mismatch: 0 - ${responsePayload}, ${i} - ${currentResponsePayload}`, + ); + } } - if (payloadConfidential) { - return { viewAddress: viewAddress, data: responsePayload, contents: responsePayloadContents }; + responsePayloadContents.push(decryptedPayload.toString("base64")); + } else { + if (i === 0) { + viewAddress = interopPayload.getAddress(); + responsePayload = Buffer.from(interopPayload.getPayload()).toString(); + payloadConfidential = false; + } else if (payloadConfidential) { + throw new Error( + `Mismatching payload confidentiality flags across proposal responses`, + ); } else { - return { viewAddress: viewAddress, data: responsePayload }; + const currentResponsePayload = Buffer.from( + interopPayload.getPayload(), + ).toString(); + if (responsePayload !== currentResponsePayload) { + throw new Error( + `Proposal response payloads mismatch: 0 - ${responsePayload}, ${i} - ${currentResponsePayload}`, + ); + } + if (viewAddress !== interopPayload.getAddress()) { + throw new Error( + `Proposal response view addresses mismatch: 0 - ${viewAddress}, ${i} - ${interopPayload.getAddress()}`, + ); + } } - } else if (view.getMeta().getProtocol() == statePb.Meta.Protocol.CORDA) { - const cordaView = cordaViewPb.ViewData.deserializeBinary(view.getData()); - const cordaNotarizedPayloads = cordaView.getNotarizedPayloadsList(); - let viewAddress = ''; - let responsePayload = ''; - let responsePayloadContents = []; - let payloadConfidential = false; - cordaNotarizedPayloads.forEach((notarizedPayload, i) => { - const interopPayload = interopPayloadPb.InteropPayload.deserializeBinary(notarizedPayload.getPayload_asU8()); - if (interopPayload.getConfidential()) { - const confidentialPayload = interopPayloadPb.ConfidentialPayload.deserializeBinary(interopPayload.getPayload_asU8()); - //TODO: Confidentiality in Corda - } else { - if (i === 0) { - viewAddress = interopPayload.getAddress(); - responsePayload = Buffer.from(interopPayload.getPayload()).toString(); - payloadConfidential = false; - } else if (payloadConfidential) { - throw new Error(`Mismatching payload confidentiality flags across notarized payloads`); - } else { - const currentResponsePayload = Buffer.from(interopPayload.getPayload()).toString(); - if (responsePayload !== currentResponsePayload) { - throw new Error(`Proposal response payloads mismatch: 0 - ${responsePayload}, ${i} - ${currentResponsePayload}`); - } - if (viewAddress !== interopPayload.getAddress()) { - throw new Error(`Proposal response view addresses mismatch: 0 - ${viewAddress}, ${i} - ${interopPayload.getAddress()}`); - } - } - } - }) - if (payloadConfidential) { - return { viewAddress: viewAddress, data: responsePayload, contents: responsePayloadContents }; + } + } + if (payloadConfidential) { + return { + viewAddress: viewAddress, + data: responsePayload, + contents: responsePayloadContents, + }; + } else { + return { viewAddress: viewAddress, data: responsePayload }; + } + } else if (view.getMeta().getProtocol() == statePb.Meta.Protocol.CORDA) { + const cordaView = cordaViewPb.ViewData.deserializeBinary(view.getData()); + const cordaNotarizedPayloads = cordaView.getNotarizedPayloadsList(); + let viewAddress = ""; + let responsePayload = ""; + const responsePayloadContents = []; + let payloadConfidential = false; + cordaNotarizedPayloads.forEach((notarizedPayload, i) => { + const interopPayload = interopPayloadPb.InteropPayload.deserializeBinary( + notarizedPayload.getPayload_asU8(), + ); + if (interopPayload.getConfidential()) { + const confidentialPayload = + interopPayloadPb.ConfidentialPayload.deserializeBinary( + interopPayload.getPayload_asU8(), + ); + //TODO: Confidentiality in Corda + } else { + if (i === 0) { + viewAddress = interopPayload.getAddress(); + responsePayload = Buffer.from(interopPayload.getPayload()).toString(); + payloadConfidential = false; + } else if (payloadConfidential) { + throw new Error( + `Mismatching payload confidentiality flags across notarized payloads`, + ); } else { - return { viewAddress: viewAddress, data: responsePayload }; + const currentResponsePayload = Buffer.from( + interopPayload.getPayload(), + ).toString(); + if (responsePayload !== currentResponsePayload) { + throw new Error( + `Proposal response payloads mismatch: 0 - ${responsePayload}, ${i} - ${currentResponsePayload}`, + ); + } + if (viewAddress !== interopPayload.getAddress()) { + throw new Error( + `Proposal response view addresses mismatch: 0 - ${viewAddress}, ${i} - ${interopPayload.getAddress()}`, + ); + } } + } + }); + if (payloadConfidential) { + return { + viewAddress: viewAddress, + data: responsePayload, + contents: responsePayloadContents, + }; } else { - const protocolType = view.getMeta().getProtocol(); - throw new Error(`Unsupported DLT type: ${protocolType}`); + return { viewAddress: viewAddress, data: responsePayload }; } -} + } else { + const protocolType = view.getMeta().getProtocol(); + throw new Error(`Unsupported DLT type: ${protocolType}`); + } +}; /** * Extracts endorsements and the signing authorities backing those endorsements from a Fabric view. * Argument is a View protobuf ('statePb.View') **/ const getEndorsementsAndSignatoriesFromFabricView = (view) => { - if (view.getMeta().getProtocol() != statePb.Meta.Protocol.FABRIC) { - throw new Error(`Not a Fabric view`); - } - const fabricView = fabricViewPb.FabricView.deserializeBinary(view.getData()); - const endorsedProposalResponses = fabricView.getEndorsedProposalResponsesList(); - let serializedEndorsementsWithSignatories = []; - for (let i = 0; i < endorsedProposalResponses.length; i++) { - const endorsement = endorsedProposalResponses[i].getEndorsement(); - const endorsementSerializedBase64 = Buffer.from(endorsement.serializeBinary()).toString('base64'); - const sid = identitiesPb.SerializedIdentity.deserializeBinary(Uint8Array.from(Buffer.from(endorsement.getEndorser()))); - serializedEndorsementsWithSignatories.push([sid.getMspid(), endorsementSerializedBase64]); - } - return serializedEndorsementsWithSignatories; -} + if (view.getMeta().getProtocol() != statePb.Meta.Protocol.FABRIC) { + throw new Error(`Not a Fabric view`); + } + const fabricView = fabricViewPb.FabricView.deserializeBinary(view.getData()); + const endorsedProposalResponses = + fabricView.getEndorsedProposalResponsesList(); + const serializedEndorsementsWithSignatories = []; + for (let i = 0; i < endorsedProposalResponses.length; i++) { + const endorsement = endorsedProposalResponses[i].getEndorsement(); + const endorsementSerializedBase64 = Buffer.from( + endorsement.serializeBinary(), + ).toString("base64"); + const sid = identitiesPb.SerializedIdentity.deserializeBinary( + Uint8Array.from(Buffer.from(endorsement.getEndorser())), + ); + serializedEndorsementsWithSignatories.push([ + sid.getMspid(), + endorsementSerializedBase64, + ]); + } + return serializedEndorsementsWithSignatories; +}; /** * Extracts endorsements and the signing authorities backing those endorsements from a Corda view. * Argument is a View protobuf ('statePb.View') **/ const getEndorsementsAndSignatoriesFromCordaView = (view) => { - if (view.getMeta().getProtocol() != statePb.Meta.Protocol.CORDA) { - throw new Error(`Not a Corda view`); - } - const cordaView = cordaViewPb.ViewData.deserializeBinary(view.getData()); - const notarizations = cordaView.getNotarizedPayloadsList(); - const signatures = []; - const certs = []; - const ids = []; - for (let i = 0 ; i < notarizations.length ; i++) { - signatures.push(notarizations[i].getSignature()); - const cert = notarizations[i].getCertificate(); - certs.push(Buffer.from(cert).toString('base64')); - ids.push(notarizations[i].getId()); - } - return { signatures, certs, ids }; -} + if (view.getMeta().getProtocol() != statePb.Meta.Protocol.CORDA) { + throw new Error(`Not a Corda view`); + } + const cordaView = cordaViewPb.ViewData.deserializeBinary(view.getData()); + const notarizations = cordaView.getNotarizedPayloadsList(); + const signatures = []; + const certs = []; + const ids = []; + for (let i = 0; i < notarizations.length; i++) { + signatures.push(notarizations[i].getSignature()); + const cert = notarizations[i].getCertificate(); + certs.push(Buffer.from(cert).toString("base64")); + ids.push(notarizations[i].getId()); + } + return { signatures, certs, ids }; +}; /** * Extracts signing authority (i.e., organization MSP) a Fabric endorsement. * Argument is an 'Endorsement' in base64 format. **/ const getSignatoryOrgMSPFromFabricEndorsementBase64 = (endorsementBase64) => { - const endorsement = proposalResponsePb.Endorsement.deserializeBinary(Buffer.from(endorsementBase64, 'base64')); - const sid = identitiesPb.SerializedIdentity.deserializeBinary(Uint8Array.from(Buffer.from(endorsement.getEndorser()))); - return sid.getMspid(); -} + const endorsement = proposalResponsePb.Endorsement.deserializeBinary( + Buffer.from(endorsementBase64, "base64"), + ); + const sid = identitiesPb.SerializedIdentity.deserializeBinary( + Uint8Array.from(Buffer.from(endorsement.getEndorser())), + ); + return sid.getMspid(); +}; /** * Accepts a base 64 encoded string of the protobuf view binary and returns a javascript object. **/ const decodeView = (viewBase64) => { - try { - const view = statePb.View.deserializeBinary(viewBase64); - return view; - } catch (e) { - throw new Error(`Decode view failed: ${e}`); - } + try { + const view = statePb.View.deserializeBinary(viewBase64); + return view; + } catch (e) { + throw new Error(`Decode view failed: ${e}`); + } }; /** @@ -335,13 +451,13 @@ const decodeView = (viewBase64) => { * message: string * privateKey: pem string * returns: signature in base64 string -**/ + **/ function signMessage(message, privateKey, algorithm: string = "SHA256") { - const sign = crypto.createSign(algorithm); - sign.write(message); - sign.end(); - return sign.sign(privateKey).toString('base64'); -}; + const sign = crypto.createSign(algorithm); + sign.write(message); + sign.end(); + return sign.sign(privateKey).toString("base64"); +} /** * Verifies a signature over message using SHA256 * message: string @@ -349,133 +465,170 @@ function signMessage(message, privateKey, algorithm: string = "SHA256") { * signature: base64 string * returns: True/False **/ -function verifySignature(message, certificate, signature, algorithm: string = "SHA256") { - const messageBuffer = Buffer.from(message); - const signBuffer = Buffer.from(signature, 'base64'); - const publicKey = crypto.createPublicKey(certificate).export({type:'spki', format:'pem'}); - return crypto.verify(algorithm, messageBuffer, publicKey, signBuffer); -}; +function verifySignature( + message, + certificate, + signature, + algorithm: string = "SHA256", +) { + const messageBuffer = Buffer.from(message); + const signBuffer = Buffer.from(signature, "base64"); + const publicKey = crypto + .createPublicKey(certificate) + .export({ type: "spki", format: "pem" }); + return crypto.verify(algorithm, messageBuffer, publicKey, signBuffer); +} const validPatternString = (pattern: string): boolean => { - // count number of stars in pattern - const numStars = (pattern.match(/\*/g) || []).length; + // count number of stars in pattern + const numStars = (pattern.match(/\*/g) || []).length; - // check if 0 or 1 stars - if (numStars <= 1) { - // if 0 stars, return true, if 1 star, make sure its at the end - return pattern.endsWith("*") || numStars == 0; - } + // check if 0 or 1 stars + if (numStars <= 1) { + // if 0 stars, return true, if 1 star, make sure its at the end + return pattern.endsWith("*") || numStars == 0; + } - return false; + return false; }; -const isPatternAndAddressMatch = (pattern: string, address: string): boolean => { - // make sure the pattern is valid - if (!validPatternString(pattern)) { - return false; - } +const isPatternAndAddressMatch = ( + pattern: string, + address: string, +): boolean => { + // make sure the pattern is valid + if (!validPatternString(pattern)) { + return false; + } - // count number of stars in pattern - const numStars = (pattern.match(/\*/g) || []).length; + // count number of stars in pattern + const numStars = (pattern.match(/\*/g) || []).length; - // if 0 stars, and exact match, return true - if (numStars == 0 && pattern == address) { - return true; - } + // if 0 stars, and exact match, return true + if (numStars == 0 && pattern == address) { + return true; + } - // if 1 star and pattern is a substring of address, return true - if (numStars == 1 && address.includes(pattern.slice(0, -1))) { - return true; - } + // if 1 star and pattern is a substring of address, return true + if (numStars == 1 && address.includes(pattern.slice(0, -1))) { + return true; + } }; /** * Lookup verification policy in the interop chaincode and get the criteria related to query **/ -const getPolicyCriteriaForAddress = async (contract: Contract, address: string): Promise => { - try { - const parsedAddress = helpers.parseAddress(address); - const [queryResponse, queryResponseError] = await helpers.handlePromise( - contract.evaluateTransaction("GetVerificationPolicyBySecurityDomain", parsedAddress.networkSegment), - ); - if (queryResponseError) { - throw new Error(`Error evaluating transaction GetVerificationPolicyBySecurityDomain ${queryResponseError}`); - } - if (!queryResponse || queryResponse.length === 0) { - throw new Error(`No verification policy for address ${address}`); - } - const verificationPolicy = JSON.parse(queryResponse.toString()); - // Get policy criteria matching the requested information in the address - let matchingIdentifier = null; - verificationPolicy.identifiers.forEach((item) => { - if (item.pattern === parsedAddress.viewSegment) { - return true; - } - return false; - }); - for (const item of verificationPolicy.identifiers) { - // short circuit if there is an exact match - if (item.pattern === parsedAddress.viewSegment) { - matchingIdentifier = item; - break; - } - if ( - validPatternString(item.pattern) && - isPatternAndAddressMatch(item.pattern, parsedAddress.viewSegment) && - (!matchingIdentifier || item.pattern.length > matchingIdentifier.pattern.length) - ) { - matchingIdentifier = item; - } - } - if (matchingIdentifier?.policy?.criteria) { - return matchingIdentifier.policy.criteria; - } - return null; - } catch (e) { - throw new Error(`Error during getPolicyCriteriaForAddress: ${e}`); - } +const getPolicyCriteriaForAddress = async ( + contract: Contract, + address: string, +): Promise => { + try { + const parsedAddress = helpers.parseAddress(address); + const [queryResponse, queryResponseError] = await helpers.handlePromise( + contract.evaluateTransaction( + "GetVerificationPolicyBySecurityDomain", + parsedAddress.networkSegment, + ), + ); + if (queryResponseError) { + throw new Error( + `Error evaluating transaction GetVerificationPolicyBySecurityDomain ${queryResponseError}`, + ); + } + if (!queryResponse || queryResponse.length === 0) { + throw new Error(`No verification policy for address ${address}`); + } + const verificationPolicy = JSON.parse(queryResponse.toString()); + // Get policy criteria matching the requested information in the address + let matchingIdentifier = null; + verificationPolicy.identifiers.forEach((item) => { + if (item.pattern === parsedAddress.viewSegment) { + return true; + } + return false; + }); + for (const item of verificationPolicy.identifiers) { + // short circuit if there is an exact match + if (item.pattern === parsedAddress.viewSegment) { + matchingIdentifier = item; + break; + } + if ( + validPatternString(item.pattern) && + isPatternAndAddressMatch(item.pattern, parsedAddress.viewSegment) && + (!matchingIdentifier || + item.pattern.length > matchingIdentifier.pattern.length) + ) { + matchingIdentifier = item; + } + } + if (matchingIdentifier?.policy?.criteria) { + return matchingIdentifier.policy.criteria; + } + return null; + } catch (e) { + throw new Error(`Error during getPolicyCriteriaForAddress: ${e}`); + } }; /** * Verifies the view by using chaincode function in interop chaincode. Verification is based on verification policy of the network, proof type and protocol type. **/ -const verifyView = async (contract: Contract, base64ViewProto: string, address: string): Promise => { - try { - await contract.evaluateTransaction("VerifyView", base64ViewProto, address); - return true; - } catch (e) { - throw new Error(`Unable to verify view: ${e}`); - } +const verifyView = async ( + contract: Contract, + base64ViewProto: string, + address: string, +): Promise => { + try { + await contract.evaluateTransaction("VerifyView", base64ViewProto, address); + return true; + } catch (e) { + throw new Error(`Unable to verify view: ${e}`); + } }; /** * Verifies a view's contents and extracts confidential payload by using chaincode function in interop chaincode. Verification is based on verification policy of the network, proof type and protocol type. **/ -const parseAndValidateView = async (contract: Contract, address: string, base64ViewProto: string, b64ViewContents: Array): Promise => { - try { - const viewPayload = await contract.evaluateTransaction("ParseAndValidateView", address, base64ViewProto, JSON.stringify(b64ViewContents)); - return viewPayload; - } catch (e) { - throw new Error(`Unable to parse and validate view: ${e}`); - } +const parseAndValidateView = async ( + contract: Contract, + address: string, + base64ViewProto: string, + b64ViewContents: Array, +): Promise => { + try { + const viewPayload = await contract.evaluateTransaction( + "ParseAndValidateView", + address, + base64ViewProto, + JSON.stringify(b64ViewContents), + ); + return viewPayload; + } catch (e) { + throw new Error(`Unable to parse and validate view: ${e}`); + } }; /** * Creates an address string based on a query object, networkid and remote url. **/ -const createAddress = (invocationSpec: InvocationSpec, networkID, remoteURL) => { - const { channel, contractName, ccFunc, ccArgs } = invocationSpec; - const addressString = `${remoteURL}/${networkID}/${channel}:${contractName}:${ccFunc}:${ccArgs.join(":")}`; - return addressString; +const createAddress = ( + invocationSpec: InvocationSpec, + networkID, + remoteURL, +) => { + const { channel, contractName, ccFunc, ccArgs } = invocationSpec; + const addressString = `${remoteURL}/${networkID}/${channel}:${contractName}:${ccFunc}:${ccArgs.join(":")}`; + return addressString; }; /** * Creates an address string based on a flow object, networkid and remote url. **/ const createFlowAddress = (flow: Flow, networkID, remoteURL) => { - const { cordappAddress, cordappId, flowId, flowArgs } = flow; - const addressString = `${remoteURL}/${networkID}/${cordappAddress}#${cordappId}.${flowId}:${flowArgs.join(":")}`; - return addressString; + const { cordappAddress, cordappId, flowId, flowArgs } = flow; + const addressString = `${remoteURL}/${networkID}/${cordappAddress}#${cordappId}.${flowId}:${flowArgs.join(":")}`; + return addressString; }; /** @@ -485,125 +638,143 @@ const createFlowAddress = (flow: Flow, networkID, remoteURL) => { * 2. Prepare arguments and call WriteExternalState. **/ const interopFlow = async ( - interopContract: Contract, - networkID: string, - invokeObject: InvocationSpec, - org: string, - localRelayEndpoint: string, - interopArgIndices: Array, - interopJSONs: Array, - keyCert: { key: ICryptoKey; cert: any }, - endorsingOrgs: Array = [], - returnWithoutLocalInvocation: boolean = false, - useTls: boolean = false, - tlsRootCACertPaths?: Array, - confidential: boolean = false, - gateway: Gateway = null, + interopContract: Contract, + networkID: string, + invokeObject: InvocationSpec, + org: string, + localRelayEndpoint: string, + interopArgIndices: Array, + interopJSONs: Array, + keyCert: { key: ICryptoKey; cert: any }, + endorsingOrgs: Array = [], + returnWithoutLocalInvocation: boolean = false, + useTls: boolean = false, + tlsRootCACertPaths?: Array, + confidential: boolean = false, + gateway: Gateway = null, ): Promise<{ views: Array; result: any }> => { - if (interopArgIndices.length !== interopJSONs.length) { - throw new Error(`Number of argument indices ${interopArgIndices.length} does not match number of view addresses ${interopJSONs.length}`); - } - // Step 1: Iterate through the view addresses, and send remote requests and get views in response for each - let views = [], viewsSerializedBase64 = [], computedAddresses = [], viewContentsBase64 = []; - for(let i = 0 ; i < interopJSONs.length ; i++) { - const [requestResponse, requestResponseError] = await helpers.handlePromise( - getRemoteView( - interopContract, - networkID, - org, - localRelayEndpoint, - interopJSONs[i], - keyCert, - useTls, - tlsRootCACertPaths, - confidential - ), - ); - if (requestResponseError) { - throw new Error(`InteropFlow remote view request error: ${requestResponseError}`); - } - views.push(requestResponse.view); - viewsSerializedBase64.push(Buffer.from(requestResponse.view.serializeBinary()).toString("base64")); - computedAddresses.push(requestResponse.address); - if (confidential) { - const respData = getResponseDataFromView(requestResponse.view, keyCert.key.toBytes()); - viewContentsBase64.push(respData.contents); - } else { - viewContentsBase64.push([]); - } - } - // Return here if caller just wants the views and doesn't want to invoke a local chaincode - if (returnWithoutLocalInvocation) { - const ccArgs = getCCArgsForProofVerification( - invokeObject, - interopArgIndices, - computedAddresses, - viewsSerializedBase64, - viewContentsBase64, - ); - return { views, result: ccArgs }; - } - // Step 2 - const result = await submitTransactionWithRemoteViews( + if (interopArgIndices.length !== interopJSONs.length) { + throw new Error( + `Number of argument indices ${interopArgIndices.length} does not match number of view addresses ${interopJSONs.length}`, + ); + } + // Step 1: Iterate through the view addresses, and send remote requests and get views in response for each + const views = [], + viewsSerializedBase64 = [], + computedAddresses = [], + viewContentsBase64 = []; + for (let i = 0; i < interopJSONs.length; i++) { + const [requestResponse, requestResponseError] = await helpers.handlePromise( + getRemoteView( interopContract, - invokeObject, - interopArgIndices, - computedAddresses, - viewsSerializedBase64, - viewContentsBase64, - endorsingOrgs, - gateway + networkID, + org, + localRelayEndpoint, + interopJSONs[i], + keyCert, + useTls, + tlsRootCACertPaths, + confidential, + ), + ); + if (requestResponseError) { + throw new Error( + `InteropFlow remote view request error: ${requestResponseError}`, + ); + } + views.push(requestResponse.view); + viewsSerializedBase64.push( + Buffer.from(requestResponse.view.serializeBinary()).toString("base64"), + ); + computedAddresses.push(requestResponse.address); + if (confidential) { + const respData = getResponseDataFromView( + requestResponse.view, + keyCert.key.toBytes(), + ); + viewContentsBase64.push(respData.contents); + } else { + viewContentsBase64.push([]); + } + } + // Return here if caller just wants the views and doesn't want to invoke a local chaincode + if (returnWithoutLocalInvocation) { + const ccArgs = getCCArgsForProofVerification( + invokeObject, + interopArgIndices, + computedAddresses, + viewsSerializedBase64, + viewContentsBase64, ); - return { views, result }; + return { views, result: ccArgs }; + } + // Step 2 + const result = await submitTransactionWithRemoteViews( + interopContract, + invokeObject, + interopArgIndices, + computedAddresses, + viewsSerializedBase64, + viewContentsBase64, + endorsingOrgs, + gateway, + ); + return { views, result }; }; /** * Prepare arguments for WriteExternalState chaincode transaction to verify a view and write data to ledger. **/ const getCCArgsForProofVerification = ( - invokeObject: InvocationSpec, - interopArgIndices: Array, - viewAddresses: Array, - viewsSerializedBase64: Array, - viewContentsBase64: Array>, + invokeObject: InvocationSpec, + interopArgIndices: Array, + viewAddresses: Array, + viewsSerializedBase64: Array, + viewContentsBase64: Array>, ): Array => { - const { - ccArgs: localCCArgs, - channel: localChannel, - ccFunc: localCCFunc, - contractName: localChaincode, - } = invokeObject; - const ccArgs = [ - localChaincode, - localChannel, - localCCFunc, - JSON.stringify(localCCArgs), - JSON.stringify(interopArgIndices), - JSON.stringify(viewAddresses), - JSON.stringify(viewsSerializedBase64), - JSON.stringify(viewContentsBase64), - ]; - return ccArgs; + const { + ccArgs: localCCArgs, + channel: localChannel, + ccFunc: localCCFunc, + contractName: localChaincode, + } = invokeObject; + const ccArgs = [ + localChaincode, + localChannel, + localCCFunc, + JSON.stringify(localCCArgs), + JSON.stringify(interopArgIndices), + JSON.stringify(viewAddresses), + JSON.stringify(viewsSerializedBase64), + JSON.stringify(viewContentsBase64), + ]; + return ccArgs; }; /** - * Add application chaincode's endorsement policy constraints to the interop chaincode - **/ + * Add application chaincode's endorsement policy constraints to the interop chaincode + **/ const addAppCCEndorsementPolicy = async ( - interopContract: Contract, - invokeObject: InvocationSpec, - gateway: Gateway = null, + interopContract: Contract, + invokeObject: InvocationSpec, + gateway: Gateway = null, ): Promise => { - if (!gateway) { - // Assume here that the caller doesn't intend to add the app cc's endorsement policy - // or that the app cc's endorsement policy is identical to the interop cc's policy - // NOTE: this is absolutely not recommended for production - return interopContract; - } - const appContract = new contractApi.ContractImpl((await gateway.getNetwork(invokeObject.channel)), invokeObject.contractName, ''); - const appDiscInterests = appContract.getDiscoveryInterests(); - appDiscInterests.forEach((interest) => { interopContract.addDiscoveryInterest(interest); }); + if (!gateway) { + // Assume here that the caller doesn't intend to add the app cc's endorsement policy + // or that the app cc's endorsement policy is identical to the interop cc's policy + // NOTE: this is absolutely not recommended for production return interopContract; + } + const appContract = new contractApi.ContractImpl( + await gateway.getNetwork(invokeObject.channel), + invokeObject.contractName, + "", + ); + const appDiscInterests = appContract.getDiscoveryInterests(); + appDiscInterests.forEach((interest) => { + interopContract.addDiscoveryInterest(interest); + }); + return interopContract; }; /** @@ -611,35 +782,39 @@ const addAppCCEndorsementPolicy = async ( * - Prepare arguments and call WriteExternalState. **/ const submitTransactionWithRemoteViews = async ( - interopContract: Contract, - invokeObject: InvocationSpec, - interopArgIndices: Array, - viewAddresses: Array, - viewsSerializedBase64: Array, - viewContentsBase64: Array>, - endorsingOrgs: Array, - gateway: Gateway = null, + interopContract: Contract, + invokeObject: InvocationSpec, + interopArgIndices: Array, + viewAddresses: Array, + viewsSerializedBase64: Array, + viewContentsBase64: Array>, + endorsingOrgs: Array, + gateway: Gateway = null, ): Promise => { - const ccArgs = getCCArgsForProofVerification( - invokeObject, - interopArgIndices, - viewAddresses, - viewsSerializedBase64, - viewContentsBase64, - ); - - interopContract = await addAppCCEndorsementPolicy(interopContract, invokeObject, gateway); - const tx = interopContract.createTransaction("WriteExternalState") - if (endorsingOrgs.length > 0) { - tx.setEndorsingOrganizations(...endorsingOrgs) - } - const [result, submitError] = await helpers.handlePromise( - tx.submit(...ccArgs) - ); - if (submitError) { - throw new Error(`submitTransaction Error: ${submitError}`); - } - return result; + const ccArgs = getCCArgsForProofVerification( + invokeObject, + interopArgIndices, + viewAddresses, + viewsSerializedBase64, + viewContentsBase64, + ); + + interopContract = await addAppCCEndorsementPolicy( + interopContract, + invokeObject, + gateway, + ); + const tx = interopContract.createTransaction("WriteExternalState"); + if (endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs); + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs), + ); + if (submitError) { + throw new Error(`submitTransaction Error: ${submitError}`); + } + return result; }; /** @@ -650,74 +825,85 @@ const submitTransactionWithRemoteViews = async ( * 4. Call the local chaincode to verify the view before trying to submit to chaincode. **/ const getRemoteView = async ( - interopContract: Contract, - networkID: string, - org: string, - localRelayEndpoint: string, - interopJSON: InteropJSON, - keyCert: { key: ICryptoKey; cert: any }, - useTls: boolean = false, - tlsRootCACertPaths?: Array, - confidential: boolean = false, + interopContract: Contract, + networkID: string, + org: string, + localRelayEndpoint: string, + interopJSON: InteropJSON, + keyCert: { key: ICryptoKey; cert: any }, + useTls: boolean = false, + tlsRootCACertPaths?: Array, + confidential: boolean = false, ): Promise<{ view: any; address: any }> => { - const { - address, - ChaincodeFunc, - ChaincodeID, - ChannelID, - RemoteEndpoint, - NetworkID: RemoteNetworkID, - Sign, + const { + address, + ChaincodeFunc, + ChaincodeID, + ChannelID, + RemoteEndpoint, + NetworkID: RemoteNetworkID, + Sign, + ccArgs: args, + } = interopJSON; + // Step 1 + const computedAddress = + address || + createAddress( + { + ccFunc: ChaincodeFunc, + contractName: ChaincodeID, + channel: ChannelID, ccArgs: args, - } = interopJSON; - // Step 1 - const computedAddress = - address || - createAddress( - { ccFunc: ChaincodeFunc, contractName: ChaincodeID, channel: ChannelID, ccArgs: args }, - RemoteNetworkID, - RemoteEndpoint, - ); - // Step 2 - const [policyCriteria, policyCriteriaError] = await helpers.handlePromise( - getPolicyCriteriaForAddress(interopContract, computedAddress), + }, + RemoteNetworkID, + RemoteEndpoint, ); - if (policyCriteriaError) { - throw new Error(`InteropFlow failed to get policy criteria: ${policyCriteriaError}`); - } - const relay = useTls ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) : new Relay(localRelayEndpoint); - const uuidValue = uuidv4(); - // Step 3 - // TODO fix types here so can return proper view - const [relayResponse, relayResponseError] = await helpers.handlePromise( - relay.ProcessRequest( - computedAddress, - policyCriteria, - networkID, - keyCert.cert, - Sign ? signMessage(computedAddress + uuidValue, keyCert.key.toBytes()) : "", - uuidValue, - // Org is empty as the name is in the certs for - org, - confidential, - ), + // Step 2 + const [policyCriteria, policyCriteriaError] = await helpers.handlePromise( + getPolicyCriteriaForAddress(interopContract, computedAddress), + ); + if (policyCriteriaError) { + throw new Error( + `InteropFlow failed to get policy criteria: ${policyCriteriaError}`, ); - if (relayResponseError) { - throw new Error(`InteropFlow relay response error: ${relayResponseError}`); - } - // Step 4 - // Verify view to ensure it is valid before starting expensive WriteExternalState flow. - const [, verifyError] = await helpers.handlePromise( - verifyView( - interopContract, - Buffer.from(relayResponse.getView().serializeBinary()).toString("base64"), - computedAddress, - ), - ); - if (verifyError) { - throw new Error(`View verification failed ${verifyError}`); - } - return { view: relayResponse.getView(), address: computedAddress }; + } + const relay = useTls + ? new Relay(localRelayEndpoint, true, tlsRootCACertPaths) + : new Relay(localRelayEndpoint); + const uuidValue = uuidv4(); + // Step 3 + // TODO fix types here so can return proper view + const [relayResponse, relayResponseError] = await helpers.handlePromise( + relay.ProcessRequest( + computedAddress, + policyCriteria, + networkID, + keyCert.cert, + Sign + ? signMessage(computedAddress + uuidValue, keyCert.key.toBytes()) + : "", + uuidValue, + // Org is empty as the name is in the certs for + org, + confidential, + ), + ); + if (relayResponseError) { + throw new Error(`InteropFlow relay response error: ${relayResponseError}`); + } + // Step 4 + // Verify view to ensure it is valid before starting expensive WriteExternalState flow. + const [, verifyError] = await helpers.handlePromise( + verifyView( + interopContract, + Buffer.from(relayResponse.getView().serializeBinary()).toString("base64"), + computedAddress, + ), + ); + if (verifyError) { + throw new Error(`View verification failed ${verifyError}`); + } + return { view: relayResponse.getView(), address: computedAddress }; }; /** @@ -725,79 +911,87 @@ const getRemoteView = async ( * or a local invoke depending on the remoteJSON configuration provided. Will add the view response as the final arguement to the chaincode. **/ const invokeHandler = async ( - contract: Contract, - networkID: string, - org: string, - invocationSpec: InvocationSpec, - remoteJSON: RemoteJSON, - keyCert: { key: ICryptoKey; cert: any }, + contract: Contract, + networkID: string, + org: string, + invocationSpec: InvocationSpec, + remoteJSON: RemoteJSON, + keyCert: { key: ICryptoKey; cert: any }, ): Promise => { - // If the function exists in the remoteJSON it will start the interop flow - // Otherwise it will treat it as a nomral invoke function - if (remoteJSON?.viewRequests?.[invocationSpec.ccFunc]) { - return interopFlow( - contract, - networkID, - invocationSpec, - org, - remoteJSON.LocalRelayEndpoint, - remoteJSON.viewRequests[invocationSpec.ccFunc].invokeArgIndices, - remoteJSON.viewRequests[invocationSpec.ccFunc].interopJSONs, - keyCert, - ); - } - // Normal invoke function - const [result, submitError] = await helpers.handlePromise( - contract.submitTransaction(invocationSpec.ccFunc, ...invocationSpec.ccArgs), + // If the function exists in the remoteJSON it will start the interop flow + // Otherwise it will treat it as a nomral invoke function + if (remoteJSON?.viewRequests?.[invocationSpec.ccFunc]) { + return interopFlow( + contract, + networkID, + invocationSpec, + org, + remoteJSON.LocalRelayEndpoint, + remoteJSON.viewRequests[invocationSpec.ccFunc].invokeArgIndices, + remoteJSON.viewRequests[invocationSpec.ccFunc].interopJSONs, + keyCert, ); - if (submitError) { - throw new Error(`submitTransaction Error: ${submitError}`); - } - return result; + } + // Normal invoke function + const [result, submitError] = await helpers.handlePromise( + contract.submitTransaction(invocationSpec.ccFunc, ...invocationSpec.ccArgs), + ); + if (submitError) { + throw new Error(`submitTransaction Error: ${submitError}`); + } + return result; }; /** * Get signatory node (Corda) from certificate **/ const getSignatoryNodeFromCertificate = async (certBase64: string) => { - const cert = sshpk.parseCertificate(Buffer.from(certBase64, "base64"), "pem"); - if (!cert) { - throw new Error("Unable to parse Corda certificate"); - } - if (!cert.subjects || !(cert.subjects instanceof Array) || cert.subjects.length === 0) { - throw new Error("No subject found in X.509 certificate"); - } - // Filter out the Organization components ('O' attribute) - const subjectComponents = cert.subjects[0].components.filter((subject) => subject.name === "o"); - if (!subjectComponents || subjectComponents.length === 0) { - throw new Error("No subject found in X.509 certificate with 'O' (Organization) attribute"); - } - return subjectComponents[0].value; + const cert = sshpk.parseCertificate(Buffer.from(certBase64, "base64"), "pem"); + if (!cert) { + throw new Error("Unable to parse Corda certificate"); + } + if ( + !cert.subjects || + !(cert.subjects instanceof Array) || + cert.subjects.length === 0 + ) { + throw new Error("No subject found in X.509 certificate"); + } + // Filter out the Organization components ('O' attribute) + const subjectComponents = cert.subjects[0].components.filter( + (subject) => subject.name === "o", + ); + if (!subjectComponents || subjectComponents.length === 0) { + throw new Error( + "No subject found in X.509 certificate with 'O' (Organization) attribute", + ); + } + return subjectComponents[0].value; }; export { - getSignatoryNodeFromCertificate, - getKeyAndCertForRemoteRequestbyUserName, - getPolicyCriteriaForAddress, - verifyView, - parseAndValidateView, - decryptRemoteChaincodeOutput, - decryptRemoteProposalResponse, - verifyRemoteProposalResponse, - verifyDecryptedRemoteProposalResponse, - getResponseDataFromView, - getEndorsementsAndSignatoriesFromFabricView, - getEndorsementsAndSignatoriesFromCordaView, - getSignatoryOrgMSPFromFabricEndorsementBase64, - decodeView, - signMessage, - verifySignature, - invokeHandler, - interopFlow, - getCCArgsForProofVerification, - submitTransactionWithRemoteViews, - getRemoteView, - createFlowAddress, - createAddress, - decryptData + getSignatoryNodeFromCertificate, + getKeyAndCertForRemoteRequestbyUserName, + getPolicyCriteriaForAddress, + verifyView, + parseAndValidateView, + decryptRemoteChaincodeOutput, + decryptRemoteProposalResponse, + verifyRemoteProposalResponse, + verifyDecryptedRemoteProposalResponse, + getResponseDataFromView, + getEndorsementsAndSignatoriesFromFabricView, + getEndorsementsAndSignatoriesFromCordaView, + getSignatoryOrgMSPFromFabricEndorsementBase64, + decodeView, + signMessage, + verifySignature, + invokeHandler, + interopFlow, + getCCArgsForProofVerification, + submitTransactionWithRemoteViews, + getRemoteView, + createFlowAddress, + createAddress, + decryptData, }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/MembershipManager.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/MembershipManager.ts index 0c1f2e66c7..61df6c6ab3 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/MembershipManager.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/MembershipManager.ts @@ -4,208 +4,235 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { Gateway, Network } from 'fabric-network'; -import { Channel } from 'fabric-common'; -import * as path from 'path'; -import * as fs from 'fs'; -import { credentials } from '@grpc/grpc-js'; - - -import membership_pb from '@hyperledger/cacti-weaver-protos-js/common/membership_pb'; -import agent_grpc_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_grpc_pb'; -import agent_pb from '@hyperledger/cacti-weaver-protos-js/identity/agent_pb'; +import { Gateway, Network } from "fabric-network"; +import { Channel } from "fabric-common"; +import * as path from "path"; +import * as fs from "fs"; +import { credentials } from "@grpc/grpc-js"; + +import membership_pb from "@hyperledger/cacti-weaver-protos-js/common/membership_pb"; +import agent_grpc_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_grpc_pb"; +import agent_pb from "@hyperledger/cacti-weaver-protos-js/identity/agent_pb"; import common_ack_pb from "@hyperledger/cacti-weaver-protos-js/common/ack_pb"; -import { handlePromise, promisifyAll } from './helpers' +import { handlePromise, promisifyAll } from "./helpers"; // Only Admin can create, update and delete local memberships async function createLocalMembership( - gateway: Gateway, - memberMspIds: Array, - securityDomain: string, - channelName: string, - weaverCCId: string + gateway: Gateway, + memberMspIds: Array, + securityDomain: string, + channelName: string, + weaverCCId: string, ): Promise { - const network = await gateway.getNetwork(channelName) - const membership = getMSPConfigurations(network, memberMspIds) - membership.setSecuritydomain(securityDomain) - const membership64 = Buffer.from(membership.serializeBinary()).toString('base64') - const contract = network.getContract(weaverCCId) - return await contract.submitTransaction("CreateLocalMembership", membership64); + const network = await gateway.getNetwork(channelName); + const membership = getMSPConfigurations(network, memberMspIds); + membership.setSecuritydomain(securityDomain); + const membership64 = Buffer.from(membership.serializeBinary()).toString( + "base64", + ); + const contract = network.getContract(weaverCCId); + return await contract.submitTransaction( + "CreateLocalMembership", + membership64, + ); } async function updateLocalMembership( - gateway: Gateway, - memberMspIds: Array, - securityDomain: string, - channelName: string, - weaverCCId: string + gateway: Gateway, + memberMspIds: Array, + securityDomain: string, + channelName: string, + weaverCCId: string, ): Promise { - const network = await gateway.getNetwork(channelName) - const membership = getMSPConfigurations(network, memberMspIds) - membership.setSecuritydomain(securityDomain) - const membership64 = Buffer.from(membership.serializeBinary()).toString('base64') - const contract = network.getContract(weaverCCId) - return await contract.submitTransaction("UpdateLocalMembership", membership64); + const network = await gateway.getNetwork(channelName); + const membership = getMSPConfigurations(network, memberMspIds); + membership.setSecuritydomain(securityDomain); + const membership64 = Buffer.from(membership.serializeBinary()).toString( + "base64", + ); + const contract = network.getContract(weaverCCId); + return await contract.submitTransaction( + "UpdateLocalMembership", + membership64, + ); } async function deleteLocalMembership( - gateway: Gateway, - channelName: string, - weaverCCId: string + gateway: Gateway, + channelName: string, + weaverCCId: string, ): Promise { - const network = await gateway.getNetwork(channelName) - const contract = network.getContract(weaverCCId) - return await contract.submitTransaction("DeleteLocalMembership"); + const network = await gateway.getNetwork(channelName); + const contract = network.getContract(weaverCCId); + return await contract.submitTransaction("DeleteLocalMembership"); } async function readMembership( - gateway: Gateway, - securityDomain: string, - channelName: string, - weaverCCId: string + gateway: Gateway, + securityDomain: string, + channelName: string, + weaverCCId: string, ): Promise { - const network = await gateway.getNetwork(channelName) - const contract = network.getContract(weaverCCId) - return await contract.submitTransaction("GetMembershipBySecurityDomain", securityDomain); + const network = await gateway.getNetwork(channelName); + const contract = network.getContract(weaverCCId); + return await contract.submitTransaction( + "GetMembershipBySecurityDomain", + securityDomain, + ); } -function getMembershipUnit(channel: Channel, mspId: string): membership_pb.Member { - const mspConfig = channel.getMsp(mspId); - let certs = []; - if (Array.isArray(mspConfig.rootCerts)) { - for (let i = 0; i < mspConfig.rootCerts.length; i++) { - certs.push(mspConfig.rootCerts[i]); - } - } else if (mspConfig.rootCerts.length !== 0) { - certs.push(mspConfig.rootCerts); +function getMembershipUnit( + channel: Channel, + mspId: string, +): membership_pb.Member { + const mspConfig = channel.getMsp(mspId); + const certs = []; + if (Array.isArray(mspConfig.rootCerts)) { + for (let i = 0; i < mspConfig.rootCerts.length; i++) { + certs.push(mspConfig.rootCerts[i]); } - if (Array.isArray(mspConfig.intermediateCerts)) { - for (let i = 0; i < mspConfig.intermediateCerts.length; i++) { - certs.push(mspConfig.intermediateCerts[i]); - } - } else if (mspConfig.intermediateCerts.length !== 0) { - certs.push(mspConfig.intermediateCerts); + } else if (mspConfig.rootCerts.length !== 0) { + certs.push(mspConfig.rootCerts); + } + if (Array.isArray(mspConfig.intermediateCerts)) { + for (let i = 0; i < mspConfig.intermediateCerts.length; i++) { + certs.push(mspConfig.intermediateCerts[i]); } - let member = new membership_pb.Member(); - member.setType("certificate"); - member.setValue(""); - member.setChainList(certs); - - return member; + } else if (mspConfig.intermediateCerts.length !== 0) { + certs.push(mspConfig.intermediateCerts); + } + const member = new membership_pb.Member(); + member.setType("certificate"); + member.setValue(""); + member.setChainList(certs); + + return member; } function getMSPConfigurations( - network: Network, - memberMspIds: Array + network: Network, + memberMspIds: Array, ): membership_pb.Membership { - try { - const mspIds = network.getChannel().getMspids(); - const membership = new membership_pb.Membership(); - for (let i = 0 ; i < mspIds.length ; i++) { - if (memberMspIds.includes(mspIds[i])) { - const member = getMembershipUnit(network.getChannel(), mspIds[i]); - membership.getMembersMap().set(mspIds[i], member); - } - } - return membership; - } catch (error) { - console.error(`Failed to get msp details: ${error}`); - throw error; + try { + const mspIds = network.getChannel().getMspids(); + const membership = new membership_pb.Membership(); + for (let i = 0; i < mspIds.length; i++) { + if (memberMspIds.includes(mspIds[i])) { + const member = getMembershipUnit(network.getChannel(), mspIds[i]); + membership.getMembersMap().set(mspIds[i], member); + } } + return membership; + } catch (error) { + console.error(`Failed to get msp details: ${error}`); + throw error; + } } function getAllMSPConfigurations( - network: Network, - ordererMspIds: Array + network: Network, + ordererMspIds: Array, ): membership_pb.Membership { - try { - const mspIds = network.getChannel().getMspids(); - const membership = new membership_pb.Membership(); - for (let i = 0 ; i < mspIds.length ; i++) { - if (!ordererMspIds.includes(mspIds[i])) { - const member = getMembershipUnit(network.getChannel(), mspIds[i]); - membership.getMembersMap().set(mspIds[i], member); - } - } - return membership; - } catch (error) { - console.error(`Failed to get msp details: ${error}`); - throw error; + try { + const mspIds = network.getChannel().getMspids(); + const membership = new membership_pb.Membership(); + for (let i = 0; i < mspIds.length; i++) { + if (!ordererMspIds.includes(mspIds[i])) { + const member = getMembershipUnit(network.getChannel(), mspIds[i]); + membership.getMembersMap().set(mspIds[i], member); + } } + return membership; + } catch (error) { + console.error(`Failed to get msp details: ${error}`); + throw error; + } } async function syncMembershipFromIINAgent( - securityDomain: string, - iinAgentEndpoint: string, - useTls: boolean = false, - tlsCACertPath?: string, + securityDomain: string, + iinAgentEndpoint: string, + useTls: boolean = false, + tlsCACertPath?: string, ) { - try { - const foreignSecurityDomain = new agent_pb.SecurityDomainMemberIdentity(); - foreignSecurityDomain.setSecurityDomain(securityDomain); - - const iinAgentClient = getIINAgentClient(iinAgentEndpoint, useTls, tlsCACertPath) - const { - syncExternalState, - }: { - syncExternalState: (request: agent_pb.SecurityDomainMemberIdentity) => Promise; - } = promisifyAll(iinAgentClient); - - if (typeof syncExternalState === "function") { - const [resp, error] = await handlePromise(syncExternalState(foreignSecurityDomain)); - if (error) { - throw new Error(`Membership Sync error: ${error}`); - } - if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { - throw new Error(`Membership Sync request received negative Ack error: ${resp.getMessage()}`); - } - return resp.toObject(); - } - throw new Error("Error with Membership Sync in NetworkClient"); - } catch (e) { - throw new Error(`Error with IIN Agent Client: ${e}`); + try { + const foreignSecurityDomain = new agent_pb.SecurityDomainMemberIdentity(); + foreignSecurityDomain.setSecurityDomain(securityDomain); + + const iinAgentClient = getIINAgentClient( + iinAgentEndpoint, + useTls, + tlsCACertPath, + ); + const { + syncExternalState, + }: { + syncExternalState: ( + request: agent_pb.SecurityDomainMemberIdentity, + ) => Promise; + } = promisifyAll(iinAgentClient); + + if (typeof syncExternalState === "function") { + const [resp, error] = await handlePromise( + syncExternalState(foreignSecurityDomain), + ); + if (error) { + throw new Error(`Membership Sync error: ${error}`); + } + if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { + throw new Error( + `Membership Sync request received negative Ack error: ${resp.getMessage()}`, + ); + } + return resp.toObject(); } + throw new Error("Error with Membership Sync in NetworkClient"); + } catch (e) { + throw new Error(`Error with IIN Agent Client: ${e}`); + } } export function getIINAgentClient( - endpoint: string, - tls: boolean = false, - tlsCACertPath?: string + endpoint: string, + tls: boolean = false, + tlsCACertPath?: string, ): agent_grpc_pb.IINAgentClient { - let client: agent_grpc_pb.IINAgentClient; - if (tls) { - if (!tlsCACertPath || tlsCACertPath == "") { - client = new agent_grpc_pb.IINAgentClient( - endpoint, - credentials.createSsl() - ); - } else { - if (!(tlsCACertPath && fs.existsSync(tlsCACertPath))) { - throw new Error("Missing or invalid IIN Agent's tlsCACertPaths: " + tlsCACertPath); - } - const rootCert = fs.readFileSync(tlsCACertPath); - client = new agent_grpc_pb.IINAgentClient( - endpoint, - credentials.createSsl(rootCert) - ); - } + let client: agent_grpc_pb.IINAgentClient; + if (tls) { + if (!tlsCACertPath || tlsCACertPath == "") { + client = new agent_grpc_pb.IINAgentClient( + endpoint, + credentials.createSsl(), + ); } else { - client = new agent_grpc_pb.IINAgentClient( - endpoint, - credentials.createInsecure() + if (!(tlsCACertPath && fs.existsSync(tlsCACertPath))) { + throw new Error( + "Missing or invalid IIN Agent's tlsCACertPaths: " + tlsCACertPath, ); + } + const rootCert = fs.readFileSync(tlsCACertPath); + client = new agent_grpc_pb.IINAgentClient( + endpoint, + credentials.createSsl(rootCert), + ); } - return client; + } else { + client = new agent_grpc_pb.IINAgentClient( + endpoint, + credentials.createInsecure(), + ); + } + return client; } export { - createLocalMembership, - updateLocalMembership, - deleteLocalMembership, - readMembership, - getMembershipUnit, - getMSPConfigurations, - getAllMSPConfigurations, - syncMembershipFromIINAgent -} + createLocalMembership, + updateLocalMembership, + deleteLocalMembership, + readMembership, + getMembershipUnit, + getMSPConfigurations, + getAllMSPConfigurations, + syncMembershipFromIINAgent, +}; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/Relay.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/Relay.ts index 02ceff71cd..1f46090d56 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/Relay.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/Relay.ts @@ -20,485 +20,593 @@ import * as helpers from "./helpers"; * The Relay class represents a relay in the target blockchain network. */ class Relay { - static defaultTimeout = 30000; - static defaultBackOffMSec = 500; - timeoutTime = Relay.defaultTimeout; - backOffMSec = Relay.defaultBackOffMSec; - _endPoint = ""; - _useTls = false; - _tlsRootCACerts = ''; - // TODO: make this configurable parameter + static defaultTimeout = 30000; + static defaultBackOffMSec = 500; + timeoutTime = Relay.defaultTimeout; + backOffMSec = Relay.defaultBackOffMSec; + _endPoint = ""; + _useTls = false; + _tlsRootCACerts = ""; + // TODO: make this configurable parameter - /** - * Construct a Relay object with the given url. A Relay object - * encapsulates the properties of a Relay and the interactions with it - * via gRPC. - * - * @param {string} url - The URL with format of "http(s)://host:port". - * @returns {Relay} The Relay instance. - */ - constructor(endPoint: string, useTls = false, tlsRootCACertPaths?: Array, timeoutTime = 30000, backOffMSec = 500) { - if (!endPoint) { - throw new Error("Invalid Arguments"); - } - this.timeoutTime = timeoutTime; - this.backOffMSec = backOffMSec; - // eslint-disable-next-line - this._endPoint = endPoint; - this._useTls = useTls; - if (useTls) { - if (tlsRootCACertPaths && tlsRootCACertPaths.length > 0) { - for(let i = 0 ; i < tlsRootCACertPaths.length ; i++) { - if (!fs.existsSync(tlsRootCACertPaths[i])) { - throw new Error("Invalid TLS root CA file path: " + tlsRootCACertPaths[i]); - } - this._tlsRootCACerts = this._tlsRootCACerts + fs.readFileSync(tlsRootCACertPaths[i]).toString(); - } - } - } - } - - /** - * Get the endpoint for this object. - * @returns {string} The endpoint of the object - */ - getEndpoint(): string { - // eslint-disable-next-line - return this._endPoint; + /** + * Construct a Relay object with the given url. A Relay object + * encapsulates the properties of a Relay and the interactions with it + * via gRPC. + * + * @param {string} url - The URL with format of "http(s)://host:port". + * @returns {Relay} The Relay instance. + */ + constructor( + endPoint: string, + useTls = false, + tlsRootCACertPaths?: Array, + timeoutTime = 30000, + backOffMSec = 500, + ) { + if (!endPoint) { + throw new Error("Invalid Arguments"); } - - /** - * SendRequest to send a request to a remote network using gRPC and the relay. - * @returns {string} The ID of the request - */ - async SendRequest( - address: string, - policy, - requestingNetwork: string, - certificate: string, - signature: string, - nonce: string, - org: string, - confidential: boolean, - ): Promise { - try { - const networkClient = new networksGrpcPb.NetworkClient( - this.getEndpoint(), - this._useTls ? - (this._tlsRootCACerts.length == 0 ? grpcJs.credentials.createSsl() : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts))) : - grpcJs.credentials.createInsecure() + this.timeoutTime = timeoutTime; + this.backOffMSec = backOffMSec; + // eslint-disable-next-line + this._endPoint = endPoint; + this._useTls = useTls; + if (useTls) { + if (tlsRootCACertPaths && tlsRootCACertPaths.length > 0) { + for (let i = 0; i < tlsRootCACertPaths.length; i++) { + if (!fs.existsSync(tlsRootCACertPaths[i])) { + throw new Error( + "Invalid TLS root CA file path: " + tlsRootCACertPaths[i], ); - const { - requestState, - }: { - requestState: (query: networksPb.NetworkQuery) => Promise; - } = helpers.promisifyAll(networkClient); - - const query = new networksPb.NetworkQuery(); - query.setPolicyList(policy); - query.setAddress(address); - query.setCertificate(certificate); - query.setNonce(nonce); - query.setRequestorSignature(signature); - query.setRequestingRelay(""); - query.setRequestingNetwork(requestingNetwork); - query.setRequestingOrg(org || ""); - query.setConfidential(confidential || false); - if (typeof requestState === "function") { - const [resp, error] = await helpers.handlePromise(requestState(query)); - if (error) { - throw new Error(`Request state error: ${error}`); - } - if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { - throw new Error(`Request state received negative Ack error: ${resp.getMessage()}`); - } - return resp.getRequestId(); - } - throw new Error("Error with requeststate in NetworkClient"); - } catch (e) { - throw new Error(`Error with Network Client: ${e}`); + } + this._tlsRootCACerts = + this._tlsRootCACerts + + fs.readFileSync(tlsRootCACertPaths[i]).toString(); } + } } + } - /** - * ProcessRequest sends a request to a remote network using gRPC and the relay and polls for a response on the local network - * Uses the timeout provided by the class. - * @returns {string} The state returned by the remote request - */ - async ProcessRequest( - address: string, - policy, - requestingNetwork: string, - certificate: string, - signature: string, - nonce: string, - org: string, - confidential: boolean, - ): Promise { - try { - const [requestID, error] = await helpers.handlePromise( - this.SendRequest(address, policy, requestingNetwork, certificate, signature, nonce, org, confidential), - ); - if (error) { - throw new Error(`Request state error: ${error}`); - } - // Adds timout time to current time. - const dateObj = new Date(); - dateObj.setMilliseconds(dateObj.getMilliseconds() + this.timeoutTime); - //TODO: SLOW DOWN - const [finalState, stateError] = await helpers.handlePromise(this.recursiveState(requestID, dateObj)); - if (stateError) { - throw new Error(`State error: ${stateError}`); - } - if (finalState.getStatus() === statePb.RequestState.STATUS.ERROR) { - if (finalState.getError()) { - throw new Error(`Error from view payload : ${finalState.getError()}`); - } - else { - throw new Error(`Error from view payload : UNKNOWN REASON}`); - } - } - return finalState; - } catch (e) { - throw new Error(e); - } - } + /** + * Get the endpoint for this object. + * @returns {string} The endpoint of the object + */ + getEndpoint(): string { + // eslint-disable-next-line + return this._endPoint; + } + + /** + * SendRequest to send a request to a remote network using gRPC and the relay. + * @returns {string} The ID of the request + */ + async SendRequest( + address: string, + policy, + requestingNetwork: string, + certificate: string, + signature: string, + nonce: string, + org: string, + confidential: boolean, + ): Promise { + try { + const networkClient = new networksGrpcPb.NetworkClient( + this.getEndpoint(), + this._useTls + ? this._tlsRootCACerts.length == 0 + ? grpcJs.credentials.createSsl() + : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts)) + : grpcJs.credentials.createInsecure(), + ); + const { + requestState, + }: { + requestState: ( + query: networksPb.NetworkQuery, + ) => Promise; + } = helpers.promisifyAll(networkClient); - async recursiveState(requestID: string, dateObj: Date): Promise { - const [state, error] = await helpers.handlePromise(this.GetRequest(requestID, false)); + const query = new networksPb.NetworkQuery(); + query.setPolicyList(policy); + query.setAddress(address); + query.setCertificate(certificate); + query.setNonce(nonce); + query.setRequestorSignature(signature); + query.setRequestingRelay(""); + query.setRequestingNetwork(requestingNetwork); + query.setRequestingOrg(org || ""); + query.setConfidential(confidential || false); + if (typeof requestState === "function") { + const [resp, error] = await helpers.handlePromise(requestState(query)); if (error) { - throw new Error(`Request state error: ${error}`); + throw new Error(`Request state error: ${error}`); } - if ( - state.getStatus() === statePb.RequestState.STATUS.PENDING || - state.getStatus() === statePb.RequestState.STATUS.PENDING_ACK - ) { - if (dateObj.getTime() < Date.now()) { - throw new Error("Timeout: State is still pending."); - } else { - await helpers.delay(this.backOffMSec); - return await this.recursiveState(requestID, dateObj); - } - } else { - return state; + if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { + throw new Error( + `Request state received negative Ack error: ${resp.getMessage()}`, + ); } + return resp.getRequestId(); + } + throw new Error("Error with requeststate in NetworkClient"); + } catch (e) { + throw new Error(`Error with Network Client: ${e}`); } + } - /** - * GetRequest is used to get the request from the local network - * @returns {object} The request object from the relay - */ - async GetRequest(requestId: string, asJson = true): Promise { - const networkClient = new networksGrpcPb.NetworkClient( - this.getEndpoint(), - this._useTls ? - (this._tlsRootCACerts.length == 0 ? grpcJs.credentials.createSsl() : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts))) : - grpcJs.credentials.createInsecure() - ); - const { - getState, - }: { getState: (message: networksPb.GetStateMessage) => Promise } = helpers.promisifyAll( - networkClient, - ); - const getStateMessage = new networksPb.GetStateMessage(); - getStateMessage.setRequestId(requestId); - const [state, error] = await helpers.handlePromise(getState(getStateMessage)); - if (error) { - throw new Error(`Error: ${error}`); + /** + * ProcessRequest sends a request to a remote network using gRPC and the relay and polls for a response on the local network + * Uses the timeout provided by the class. + * @returns {string} The state returned by the remote request + */ + async ProcessRequest( + address: string, + policy, + requestingNetwork: string, + certificate: string, + signature: string, + nonce: string, + org: string, + confidential: boolean, + ): Promise { + try { + const [requestID, error] = await helpers.handlePromise( + this.SendRequest( + address, + policy, + requestingNetwork, + certificate, + signature, + nonce, + org, + confidential, + ), + ); + if (error) { + throw new Error(`Request state error: ${error}`); + } + // Adds timout time to current time. + const dateObj = new Date(); + dateObj.setMilliseconds(dateObj.getMilliseconds() + this.timeoutTime); + //TODO: SLOW DOWN + const [finalState, stateError] = await helpers.handlePromise( + this.recursiveState(requestID, dateObj), + ); + if (stateError) { + throw new Error(`State error: ${stateError}`); + } + if (finalState.getStatus() === statePb.RequestState.STATUS.ERROR) { + if (finalState.getError()) { + throw new Error(`Error from view payload : ${finalState.getError()}`); + } else { + throw new Error(`Error from view payload : UNKNOWN REASON}`); } - - return asJson ? state.toObject() : state; + } + return finalState; + } catch (e) { + throw new Error(e); } - - /** - * SendEventSubscribeRequest to send a request to a remote network using gRPC and the relay. - * @returns {string} The ID of the request - */ - async SendEventSubscribeRequest( - eventMatcher: eventsPb.EventMatcher, - eventPublicationSpec: eventsPb.EventPublication, - address: string, - policy, - requestingNetwork: string, - certificate: string, - signature: string, - nonce: string, - org: string, - confidential: boolean, - ): Promise { - try { - const networkClient = new networksGrpcPb.NetworkClient( - this.getEndpoint(), - this._useTls ? - (this._tlsRootCACerts.length == 0 ? grpcJs.credentials.createSsl() : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts))) : - grpcJs.credentials.createInsecure() - ); - const { - subscribeEvent, - }: { - subscribeEvent: (eventSubscription: networksPb.NetworkEventSubscription) => Promise; - } = helpers.promisifyAll(networkClient); + } - const query = new networksPb.NetworkQuery(); - query.setPolicyList(policy); - query.setAddress(address); - query.setCertificate(certificate); - query.setNonce(nonce); - query.setRequestorSignature(signature); - query.setRequestingRelay(""); - query.setRequestingNetwork(requestingNetwork); - query.setRequestingOrg(org || ""); - query.setConfidential(confidential || false); - - const eventSubscription = new networksPb.NetworkEventSubscription(); - eventSubscription.setEventMatcher(eventMatcher); - eventSubscription.setQuery(query); - eventSubscription.setEventPublicationSpec(eventPublicationSpec); - - if (typeof subscribeEvent === "function") { - const [resp, error] = await helpers.handlePromise(subscribeEvent(eventSubscription)); - if (error) { - throw new Error(`Event Subscription error: ${error}`); - } - if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { - throw new Error(`Event Subscription request received negative Ack error: ${resp.getMessage()}`); - } - return resp.getRequestId(); - } - throw new Error("Error with event subscription in NetworkClient"); - } catch (e) { - throw new Error(`Error with Network Client: ${e}`); - } + async recursiveState(requestID: string, dateObj: Date): Promise { + const [state, error] = await helpers.handlePromise( + this.GetRequest(requestID, false), + ); + if (error) { + throw new Error(`Request state error: ${error}`); } - /** - * GetSubscriptionStatus is used to get the request from the local network - * @returns {object} The request object from the relay - */ - async GetEventSubscriptionState(requestId: string, asJson = true): Promise { - const networkClient = new networksGrpcPb.NetworkClient( - this.getEndpoint(), - this._useTls ? - (this._tlsRootCACerts.length == 0 ? grpcJs.credentials.createSsl() : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts))) : - grpcJs.credentials.createInsecure() - ); - const { - getEventSubscriptionState, - }: { getEventSubscriptionState: (message: networksPb.GetStateMessage) => Promise } = helpers.promisifyAll( - networkClient, - ); - const getStateMessage = new networksPb.GetStateMessage(); - getStateMessage.setRequestId(requestId); - const [state, error] = await helpers.handlePromise(getEventSubscriptionState(getStateMessage)); - if (error) { - throw new Error(`Error: ${error}`); - } + if ( + state.getStatus() === statePb.RequestState.STATUS.PENDING || + state.getStatus() === statePb.RequestState.STATUS.PENDING_ACK + ) { + if (dateObj.getTime() < Date.now()) { + throw new Error("Timeout: State is still pending."); + } else { + await helpers.delay(this.backOffMSec); + return await this.recursiveState(requestID, dateObj); + } + } else { + return state; + } + } - return asJson ? state.toObject() : state; + /** + * GetRequest is used to get the request from the local network + * @returns {object} The request object from the relay + */ + async GetRequest(requestId: string, asJson = true): Promise { + const networkClient = new networksGrpcPb.NetworkClient( + this.getEndpoint(), + this._useTls + ? this._tlsRootCACerts.length == 0 + ? grpcJs.credentials.createSsl() + : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts)) + : grpcJs.credentials.createInsecure(), + ); + const { + getState, + }: { + getState: ( + message: networksPb.GetStateMessage, + ) => Promise; + } = helpers.promisifyAll(networkClient); + const getStateMessage = new networksPb.GetStateMessage(); + getStateMessage.setRequestId(requestId); + const [state, error] = await helpers.handlePromise( + getState(getStateMessage), + ); + if (error) { + throw new Error(`Error: ${error}`); } - - async recursiveEventSubscriptionState(requestID: string, dateObj: Date): Promise { - const [state, error] = await helpers.handlePromise(this.GetEventSubscriptionState(requestID, false)); + + return asJson ? state.toObject() : state; + } + + /** + * SendEventSubscribeRequest to send a request to a remote network using gRPC and the relay. + * @returns {string} The ID of the request + */ + async SendEventSubscribeRequest( + eventMatcher: eventsPb.EventMatcher, + eventPublicationSpec: eventsPb.EventPublication, + address: string, + policy, + requestingNetwork: string, + certificate: string, + signature: string, + nonce: string, + org: string, + confidential: boolean, + ): Promise { + try { + const networkClient = new networksGrpcPb.NetworkClient( + this.getEndpoint(), + this._useTls + ? this._tlsRootCACerts.length == 0 + ? grpcJs.credentials.createSsl() + : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts)) + : grpcJs.credentials.createInsecure(), + ); + const { + subscribeEvent, + }: { + subscribeEvent: ( + eventSubscription: networksPb.NetworkEventSubscription, + ) => Promise; + } = helpers.promisifyAll(networkClient); + + const query = new networksPb.NetworkQuery(); + query.setPolicyList(policy); + query.setAddress(address); + query.setCertificate(certificate); + query.setNonce(nonce); + query.setRequestorSignature(signature); + query.setRequestingRelay(""); + query.setRequestingNetwork(requestingNetwork); + query.setRequestingOrg(org || ""); + query.setConfidential(confidential || false); + + const eventSubscription = new networksPb.NetworkEventSubscription(); + eventSubscription.setEventMatcher(eventMatcher); + eventSubscription.setQuery(query); + eventSubscription.setEventPublicationSpec(eventPublicationSpec); + + if (typeof subscribeEvent === "function") { + const [resp, error] = await helpers.handlePromise( + subscribeEvent(eventSubscription), + ); if (error) { - throw new Error(`Get event subscription state error: ${error}`); + throw new Error(`Event Subscription error: ${error}`); } - if ( - state.getStatus() === eventsPb.EventSubscriptionState.STATUS.SUBSCRIBE_PENDING || - state.getStatus() === eventsPb.EventSubscriptionState.STATUS.SUBSCRIBE_PENDING_ACK || - state.getStatus() === eventsPb.EventSubscriptionState.STATUS.UNSUBSCRIBE_PENDING || - state.getStatus() === eventsPb.EventSubscriptionState.STATUS.UNSUBSCRIBE_PENDING_ACK - ) { - if (dateObj.getTime() < Date.now()) { - throw new Error("Timeout: State is still pending."); - } else { - await helpers.delay(this.backOffMSec); - return await this.recursiveEventSubscriptionState(requestID, dateObj); - } - } else { - return state; + if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { + throw new Error( + `Event Subscription request received negative Ack error: ${resp.getMessage()}`, + ); } + return resp.getRequestId(); + } + throw new Error("Error with event subscription in NetworkClient"); + } catch (e) { + throw new Error(`Error with Network Client: ${e}`); } - /** - * ProcessEventSubscriptionRequest sends a event subscription request to a remote network using gRPC and the relay and polls for a response on the local network - * Uses the timeout provided by the class. - * @returns {string} The state returned by the remote request - */ - async ProcessSubscribeEventRequest( - eventMatcher: eventsPb.EventMatcher, - eventPublicationSpec: eventsPb.EventPublication, - address: string, - policy, - requestingNetwork: string, - certificate: string, - signature: string, - nonce: string, - org: string, - confidential: boolean, - ): Promise { - try { - const [requestID, error] = await helpers.handlePromise( - this.SendEventSubscribeRequest(eventMatcher, eventPublicationSpec, address, policy, requestingNetwork, certificate, signature, nonce, org, confidential), - ); - if (error) { - throw new Error(`Event subscription error: ${error}`); - } - // Adds timout time to current time. - const dateObj = new Date(); - dateObj.setMilliseconds(dateObj.getMilliseconds() + this.timeoutTime); - //TODO: SLOW DOWN - const [finalState, stateError] = await helpers.handlePromise(this.recursiveEventSubscriptionState(requestID, dateObj)); - if (stateError) { - throw new Error(`Event Subscription error: ${stateError}`); - } - if (finalState.getStatus() === eventsPb.EventSubscriptionState.STATUS.ERROR) { - if (finalState.getMessage()) { - throw new Error(`Error during event subscription : ${finalState.getMessage()}`); - } - else { - throw new Error(`Error during event subscription : UNKNOWN REASON}`); - } - } - return finalState; - } catch (e) { - throw new Error(e); - } + } + /** + * GetSubscriptionStatus is used to get the request from the local network + * @returns {object} The request object from the relay + */ + async GetEventSubscriptionState( + requestId: string, + asJson = true, + ): Promise { + const networkClient = new networksGrpcPb.NetworkClient( + this.getEndpoint(), + this._useTls + ? this._tlsRootCACerts.length == 0 + ? grpcJs.credentials.createSsl() + : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts)) + : grpcJs.credentials.createInsecure(), + ); + const { + getEventSubscriptionState, + }: { + getEventSubscriptionState: ( + message: networksPb.GetStateMessage, + ) => Promise; + } = helpers.promisifyAll(networkClient); + const getStateMessage = new networksPb.GetStateMessage(); + getStateMessage.setRequestId(requestId); + const [state, error] = await helpers.handlePromise( + getEventSubscriptionState(getStateMessage), + ); + if (error) { + throw new Error(`Error: ${error}`); } - /** - * SendEventUnsubscribeRequest to send a request to a remote network using gRPC and the relay. - * @returns {string} The ID of the request - */ - async SendEventUnsubscribeRequest( - eventMatcher: eventsPb.EventMatcher, - eventPublicationSpec: eventsPb.EventPublication, - requestId: string, - address: string, - policy, - requestingNetwork: string, - certificate: string, - signature: string, - nonce: string, - org: string, - confidential: boolean, - ): Promise { - try { - const networkClient = new networksGrpcPb.NetworkClient( - this.getEndpoint(), - this._useTls ? - (this._tlsRootCACerts.length == 0 ? grpcJs.credentials.createSsl() : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts))) : - grpcJs.credentials.createInsecure() - ); - const { - unsubscribeEvent, - }: { - unsubscribeEvent: (eventUnsubscription: networksPb.NetworkEventUnsubscription) => Promise; - } = helpers.promisifyAll(networkClient); - const query = new networksPb.NetworkQuery(); - query.setPolicyList(policy); - query.setAddress(address); - query.setCertificate(certificate); - query.setNonce(nonce); - query.setRequestorSignature(signature); - query.setRequestingRelay(""); - query.setRequestingNetwork(requestingNetwork); - query.setRequestingOrg(org || ""); - query.setConfidential(confidential || false); - - const eventSubscription = new networksPb.NetworkEventSubscription(); - eventSubscription.setEventMatcher(eventMatcher); - eventSubscription.setQuery(query); - eventSubscription.setEventPublicationSpec(eventPublicationSpec); - - const eventUnsubscription = new networksPb.NetworkEventUnsubscription(); - eventUnsubscription.setRequest(eventSubscription); - eventUnsubscription.setRequestId(requestId); - - if (typeof unsubscribeEvent === "function") { - const [resp, error] = await helpers.handlePromise(unsubscribeEvent(eventUnsubscription)); - if (error) { - throw new Error(`Event Unsubscription error: ${error}`); - } - if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { - throw new Error(`Event Unsubscription request received negative Ack error: ${resp.getMessage()}`); - } - return resp.getRequestId(); - } - throw new Error("Error with event unsubscription in NetworkClient"); - } catch (e) { - throw new Error(`Error with Network Client: ${e}`); - } + return asJson ? state.toObject() : state; + } + + async recursiveEventSubscriptionState( + requestID: string, + dateObj: Date, + ): Promise { + const [state, error] = await helpers.handlePromise( + this.GetEventSubscriptionState(requestID, false), + ); + if (error) { + throw new Error(`Get event subscription state error: ${error}`); } - /** - * ProcessEventUnsubscriptionRequest sends a event unsubscription request to a remote network using gRPC and the relay and polls for a response on the local network - * Uses the timeout provided by the class. - * @returns {string} The state returned by the remote request - */ - async ProcessUnsubscribeEventRequest( - eventMatcher: eventsPb.EventMatcher, - eventPublicationSpec: eventsPb.EventPublication, - requestId: string, - address: string, - policy, - requestingNetwork: string, - certificate: string, - signature: string, - nonce: string, - org: string, - confidential: boolean, - ): Promise { - try { - const [requestID, error] = await helpers.handlePromise( - this.SendEventUnsubscribeRequest(eventMatcher, eventPublicationSpec, requestId, address, policy, requestingNetwork, certificate, signature, nonce, org, confidential), - ); - if (error) { - throw new Error(`Event unsubscription error: ${error}`); - } - // Adds timout time to current time. - const dateObj = new Date(); - dateObj.setMilliseconds(dateObj.getMilliseconds() + this.timeoutTime); - //TODO: SLOW DOWN - const [finalState, stateError] = await helpers.handlePromise(this.recursiveEventSubscriptionState(requestID, dateObj)); - if (stateError) { - throw new Error(`Event unsubscription error: ${stateError}`); - } - if (finalState.getStatus() === eventsPb.EventSubscriptionState.STATUS.ERROR) { - if (finalState.getMessage()) { - throw new Error(`Error during event unsubscription : ${finalState.getMessage()}`); - } - else { - throw new Error(`Error during event unsubscription : UNKNOWN REASON}`); - } - } - return finalState; - } catch (e) { - throw new Error(e); + if ( + state.getStatus() === + eventsPb.EventSubscriptionState.STATUS.SUBSCRIBE_PENDING || + state.getStatus() === + eventsPb.EventSubscriptionState.STATUS.SUBSCRIBE_PENDING_ACK || + state.getStatus() === + eventsPb.EventSubscriptionState.STATUS.UNSUBSCRIBE_PENDING || + state.getStatus() === + eventsPb.EventSubscriptionState.STATUS.UNSUBSCRIBE_PENDING_ACK + ) { + if (dateObj.getTime() < Date.now()) { + throw new Error("Timeout: State is still pending."); + } else { + await helpers.delay(this.backOffMSec); + return await this.recursiveEventSubscriptionState(requestID, dateObj); + } + } else { + return state; + } + } + /** + * ProcessEventSubscriptionRequest sends a event subscription request to a remote network using gRPC and the relay and polls for a response on the local network + * Uses the timeout provided by the class. + * @returns {string} The state returned by the remote request + */ + async ProcessSubscribeEventRequest( + eventMatcher: eventsPb.EventMatcher, + eventPublicationSpec: eventsPb.EventPublication, + address: string, + policy, + requestingNetwork: string, + certificate: string, + signature: string, + nonce: string, + org: string, + confidential: boolean, + ): Promise { + try { + const [requestID, error] = await helpers.handlePromise( + this.SendEventSubscribeRequest( + eventMatcher, + eventPublicationSpec, + address, + policy, + requestingNetwork, + certificate, + signature, + nonce, + org, + confidential, + ), + ); + if (error) { + throw new Error(`Event subscription error: ${error}`); + } + // Adds timout time to current time. + const dateObj = new Date(); + dateObj.setMilliseconds(dateObj.getMilliseconds() + this.timeoutTime); + //TODO: SLOW DOWN + const [finalState, stateError] = await helpers.handlePromise( + this.recursiveEventSubscriptionState(requestID, dateObj), + ); + if (stateError) { + throw new Error(`Event Subscription error: ${stateError}`); + } + if ( + finalState.getStatus() === eventsPb.EventSubscriptionState.STATUS.ERROR + ) { + if (finalState.getMessage()) { + throw new Error( + `Error during event subscription : ${finalState.getMessage()}`, + ); + } else { + throw new Error(`Error during event subscription : UNKNOWN REASON}`); } + } + return finalState; + } catch (e) { + throw new Error(e); } - /** - * GetSubscriptionStatus is used to get the request from the local network - * @returns {object} The request object from the relay - */ - async GetEventStates(requestId: string, asJson = true): Promise { - const networkClient = new networksGrpcPb.NetworkClient( - this.getEndpoint(), - this._useTls ? - (this._tlsRootCACerts.length == 0 ? grpcJs.credentials.createSsl() : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts))) : - grpcJs.credentials.createInsecure() - ); - const { - getEventStates, - }: { getEventStates: (message: networksPb.GetStateMessage) => Promise } = helpers.promisifyAll( - networkClient, + } + /** + * SendEventUnsubscribeRequest to send a request to a remote network using gRPC and the relay. + * @returns {string} The ID of the request + */ + async SendEventUnsubscribeRequest( + eventMatcher: eventsPb.EventMatcher, + eventPublicationSpec: eventsPb.EventPublication, + requestId: string, + address: string, + policy, + requestingNetwork: string, + certificate: string, + signature: string, + nonce: string, + org: string, + confidential: boolean, + ): Promise { + try { + const networkClient = new networksGrpcPb.NetworkClient( + this.getEndpoint(), + this._useTls + ? this._tlsRootCACerts.length == 0 + ? grpcJs.credentials.createSsl() + : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts)) + : grpcJs.credentials.createInsecure(), + ); + const { + unsubscribeEvent, + }: { + unsubscribeEvent: ( + eventUnsubscription: networksPb.NetworkEventUnsubscription, + ) => Promise; + } = helpers.promisifyAll(networkClient); + + const query = new networksPb.NetworkQuery(); + query.setPolicyList(policy); + query.setAddress(address); + query.setCertificate(certificate); + query.setNonce(nonce); + query.setRequestorSignature(signature); + query.setRequestingRelay(""); + query.setRequestingNetwork(requestingNetwork); + query.setRequestingOrg(org || ""); + query.setConfidential(confidential || false); + + const eventSubscription = new networksPb.NetworkEventSubscription(); + eventSubscription.setEventMatcher(eventMatcher); + eventSubscription.setQuery(query); + eventSubscription.setEventPublicationSpec(eventPublicationSpec); + + const eventUnsubscription = new networksPb.NetworkEventUnsubscription(); + eventUnsubscription.setRequest(eventSubscription); + eventUnsubscription.setRequestId(requestId); + + if (typeof unsubscribeEvent === "function") { + const [resp, error] = await helpers.handlePromise( + unsubscribeEvent(eventUnsubscription), ); - const getStateMessage = new networksPb.GetStateMessage(); - getStateMessage.setRequestId(requestId); - const [state, error] = await helpers.handlePromise(getEventStates(getStateMessage)); if (error) { - throw new Error(`Error: ${error}`); + throw new Error(`Event Unsubscription error: ${error}`); } - - return asJson ? state.toObject() : state; + if (resp.getStatus() === common_ack_pb.Ack.STATUS.ERROR) { + throw new Error( + `Event Unsubscription request received negative Ack error: ${resp.getMessage()}`, + ); + } + return resp.getRequestId(); + } + throw new Error("Error with event unsubscription in NetworkClient"); + } catch (e) { + throw new Error(`Error with Network Client: ${e}`); + } + } + /** + * ProcessEventUnsubscriptionRequest sends a event unsubscription request to a remote network using gRPC and the relay and polls for a response on the local network + * Uses the timeout provided by the class. + * @returns {string} The state returned by the remote request + */ + async ProcessUnsubscribeEventRequest( + eventMatcher: eventsPb.EventMatcher, + eventPublicationSpec: eventsPb.EventPublication, + requestId: string, + address: string, + policy, + requestingNetwork: string, + certificate: string, + signature: string, + nonce: string, + org: string, + confidential: boolean, + ): Promise { + try { + const [requestID, error] = await helpers.handlePromise( + this.SendEventUnsubscribeRequest( + eventMatcher, + eventPublicationSpec, + requestId, + address, + policy, + requestingNetwork, + certificate, + signature, + nonce, + org, + confidential, + ), + ); + if (error) { + throw new Error(`Event unsubscription error: ${error}`); + } + // Adds timout time to current time. + const dateObj = new Date(); + dateObj.setMilliseconds(dateObj.getMilliseconds() + this.timeoutTime); + //TODO: SLOW DOWN + const [finalState, stateError] = await helpers.handlePromise( + this.recursiveEventSubscriptionState(requestID, dateObj), + ); + if (stateError) { + throw new Error(`Event unsubscription error: ${stateError}`); + } + if ( + finalState.getStatus() === eventsPb.EventSubscriptionState.STATUS.ERROR + ) { + if (finalState.getMessage()) { + throw new Error( + `Error during event unsubscription : ${finalState.getMessage()}`, + ); + } else { + throw new Error( + `Error during event unsubscription : UNKNOWN REASON}`, + ); + } + } + return finalState; + } catch (e) { + throw new Error(e); + } + } + /** + * GetSubscriptionStatus is used to get the request from the local network + * @returns {object} The request object from the relay + */ + async GetEventStates(requestId: string, asJson = true): Promise { + const networkClient = new networksGrpcPb.NetworkClient( + this.getEndpoint(), + this._useTls + ? this._tlsRootCACerts.length == 0 + ? grpcJs.credentials.createSsl() + : grpcJs.credentials.createSsl(Buffer.from(this._tlsRootCACerts)) + : grpcJs.credentials.createInsecure(), + ); + const { + getEventStates, + }: { + getEventStates: ( + message: networksPb.GetStateMessage, + ) => Promise; + } = helpers.promisifyAll(networkClient); + const getStateMessage = new networksPb.GetStateMessage(); + getStateMessage.setRequestId(requestId); + const [state, error] = await helpers.handlePromise( + getEventStates(getStateMessage), + ); + if (error) { + throw new Error(`Error: ${error}`); } -} + return asJson ? state.toObject() : state; + } +} export { Relay }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/decoders.js b/weaver/sdks/fabric/interoperation-node-sdk/src/decoders.js index e103397628..0157cb2995 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/decoders.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/decoders.js @@ -7,38 +7,43 @@ const fabproto6 = require("fabric-protos"); // Input parameter: 'peer.Proposal' protobuf in bytes -const deserializeRemoteProposal = (proposalBytes) => fabproto6.protos.Proposal.decode(proposalBytes); +const deserializeRemoteProposal = (proposalBytes) => + fabproto6.protos.Proposal.decode(proposalBytes); // Input parameter: 'peer.ProposalResponse' protobuf in bytes const deserializeRemoteProposalResponse = (proposalResponseBytes) => - fabproto6.protos.ProposalResponse.decode(proposalResponseBytes); + fabproto6.protos.ProposalResponse.decode(proposalResponseBytes); // Input parameter: 'peer.Proposal' protobuf encoded in Hex const deserializeRemoteProposalHex = (proposalBytesHex) => - fabproto6.protos.Proposal.decode(Buffer.from(proposalBytesHex, "hex")); + fabproto6.protos.Proposal.decode(Buffer.from(proposalBytesHex, "hex")); // Input parameter: 'peer.ProposalResponse' protobuf encoded in Hex const deserializeRemoteProposalResponseHex = (proposalResponseBytesHex) => - fabproto6.protos.ProposalResponse.decode(Buffer.from(proposalResponseBytesHex, "hex")); + fabproto6.protos.ProposalResponse.decode( + Buffer.from(proposalResponseBytesHex, "hex"), + ); // Input parameter: 'peer.Proposal' protobuf encoded in Base64 const deserializeRemoteProposalBase64 = (proposalBytes64) => - fabproto6.protos.Proposal.decode(Buffer.from(proposalBytes64, "base64")); + fabproto6.protos.Proposal.decode(Buffer.from(proposalBytes64, "base64")); // Input parameter: 'peer.ProposalResponse' protobuf encoded in Base64 const deserializeRemoteProposalResponseBase64 = (proposalResponseBytes64) => - fabproto6.protos.ProposalResponse.decode(Buffer.from(proposalResponseBytes64, "base64")); + fabproto6.protos.ProposalResponse.decode( + Buffer.from(proposalResponseBytes64, "base64"), + ); // Input parameter: 'peer.ProposalResponse' protobuf structure const serializeRemoteProposalResponse = (proposalResponse) => - fabproto6.protos.ProposalResponse.encode(proposalResponse).finish(); + fabproto6.protos.ProposalResponse.encode(proposalResponse).finish(); module.exports = { - deserializeRemoteProposal, - deserializeRemoteProposalResponse, - deserializeRemoteProposalHex, - deserializeRemoteProposalResponseHex, - deserializeRemoteProposalBase64, - deserializeRemoteProposalResponseBase64, - serializeRemoteProposalResponse, + deserializeRemoteProposal, + deserializeRemoteProposalResponse, + deserializeRemoteProposalHex, + deserializeRemoteProposalResponseHex, + deserializeRemoteProposalBase64, + deserializeRemoteProposalResponseBase64, + serializeRemoteProposalResponse, }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js b/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js index 082084fcc1..7b418f165b 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/eciesCrypto.js @@ -61,65 +61,72 @@ const CURVE_P_384_Size = 384; * Comments below indicate a mapping between variables defined here and in the * 'Decrypt(...)' function implemented in 'ecies.go' in the Golang package */ -function eciesDecryptMessage(recipientPrivateKey, cipherText, options, aesKeyLength = AESKeyLength) { - const level = recipientPrivateKey.ecparams.keylen; - options.securityLevel = level; - processOption(options); - - const Rb_len = Math.floor((level + 7) / 8) * 2 + 1; // 'rLen' - const D_len = level >> 3; // 'hLen' - const ct_len = cipherText.length; // 'len(ct)' - - if (ct_len <= Rb_len + D_len) { - throw new Error(`Illegal cipherText length: ${ct_len} must be > ${Rb_len + D_len}`); - } - - const Rb = cipherText.slice(0, Rb_len); // ephemeral public key bytes - const EM = cipherText.slice(Rb_len, ct_len - D_len); // encrypted content bytes - const D = cipherText.slice(ct_len - D_len); - - const ecdsa = new elliptic.ec(`p${level}`); - - // convert bytes to usable key object - const ephPubKey = ecdsa.keyFromPublic(Buffer.from(Rb, "hex"), "hex"); // 'R' - const privKey = ecdsa.keyFromPrivate(recipientPrivateKey.prvKeyHex, "hex"); - - const Z = privKey.derive(ephPubKey.pub); // 'z' - // Append missing leading zeros to Z - let ZArray = Z.toArray(); - const zerosToAdd = 32 - ZArray.length; - for (let ii=0; ii> 3; // 'hLen' + const ct_len = cipherText.length; // 'len(ct)' + + if (ct_len <= Rb_len + D_len) { + throw new Error( + `Illegal cipherText length: ${ct_len} must be > ${Rb_len + D_len}`, + ); + } + + const Rb = cipherText.slice(0, Rb_len); // ephemeral public key bytes + const EM = cipherText.slice(Rb_len, ct_len - D_len); // encrypted content bytes + const D = cipherText.slice(ct_len - D_len); + + const ecdsa = new elliptic.ec(`p${level}`); + + // convert bytes to usable key object + const ephPubKey = ecdsa.keyFromPublic(Buffer.from(Rb, "hex"), "hex"); // 'R' + const privKey = ecdsa.keyFromPrivate(recipientPrivateKey.prvKeyHex, "hex"); + + const Z = privKey.derive(ephPubKey.pub); // 'z' + // Append missing leading zeros to Z + let ZArray = Z.toArray(); + const zerosToAdd = 32 - ZArray.length; + for (let ii = 0; ii < zerosToAdd; ii++) { + ZArray = new Uint8Array([0, ...ZArray]); + } + // The 'null's below correspond to 's1' and 's2', + // which are both set to nil in golang implementation of the encryption function + const kdfOutput = hkdf(ZArray, ECIESKDFOutput, null, null, options); + + const kbuf = Buffer.from(kdfOutput); + const aesKey = kdfOutput.slice(0, aesKeyLength); // 'Ke' + const hmacKey = kdfOutput.slice(aesKeyLength, aesKeyLength + HMACKeyLength); + + const hmacKeyHash = new options.hashFunctionKeyDerivation(); + hmacKeyHash.update(bytesToBits(hmacKey)); + const hKm = bitsToBytes(hmacKeyHash.finalize()); // 'Km' + + const recoveredD = hmac(hKm, EM, options); + if (D.compare(Buffer.from(recoveredD)) !== 0) { + throw new Error("HMAC verify failed"); + } + const iv = EM.slice(0, IVLength); + // The go-ethereum crypto/ecies package that encrypts/decrypts data uses AES-128-CTR by default for signing certs currently generated by Fabric + let aesAlgorithm; + if (aesKeyLength === 16) { + aesAlgorithm = "aes-128-ctr"; + } else if (aesKeyLength === 32) { + aesAlgorithm = "aes-256-ctr"; + } else { + throw new Error("Invalid AES key length supplied: " + aesKeyLength); + } + const cipher = crypto.createDecipheriv(aesAlgorithm, Buffer.from(aesKey), iv); + const decryptedBytes = cipher.update(EM.slice(IVLength)); + return decryptedBytes; } /** Encrypt a message. @@ -144,206 +151,223 @@ function eciesDecryptMessage(recipientPrivateKey, cipherText, options, aesKeyLen * @returns encrypted message as a Buffer. * */ -function eciesEncryptMessage(recipientPublicKey, msg, options, aesKeyLength = AESKeyLength) { - const level = recipientPublicKey.ecparams.keylen; - options.securityLevel = level; - processOption(options); - - const ecdsa = new elliptic.ec(`p${level}`); - const pubKey = ecdsa.keyFromPublic(recipientPublicKey.pubKeyHex, "hex"); - - // Generate ephemeral key-pair - const ephKeyPair = jsrsa.KEYUTIL.generateKeypair("EC", options.curveName); - const ephPrivKey = ecdsa.keyFromPrivate(ephKeyPair.prvKeyObj.prvKeyHex, "hex"); - const Rb = ephKeyPair.pubKeyObj.pubKeyHex; - - // Derive a shared secret field element z from the ephemeral secret key k - // and convert z to an octet string Z - const Z = ephPrivKey.derive(pubKey.pub); - const kdfOutput = hkdf(Z.toArray(), ECIESKDFOutput, null, null, options); - - const aesKey = kdfOutput.slice(0, aesKeyLength); - const hmacKey = kdfOutput.slice(aesKeyLength, aesKeyLength + HMACKeyLength); - - const hmacKeyHash = new options.hashFunctionKeyDerivation(); - hmacKeyHash.update(bytesToBits(hmacKey)); - const hKm = bitsToBytes(hmacKeyHash.finalize()); - - const iv = crypto.randomBytes(IVLength); - // The go-ethereum crypto/ecies package that encrypts/decrypts data uses AES-128-CTR by default for signing certs currently generated by Fabric - let aesAlgorithm; - if (aesKeyLength === 16) { - aesAlgorithm = "aes-128-ctr"; - } else if (aesKeyLength === 32) { - aesAlgorithm = "aes-256-ctr"; - } else { - throw new Error("Invalid AES key length supplied: " + aesKeyLength); - } - const cipher = crypto.createCipheriv(aesAlgorithm, Buffer.from(aesKey), iv); - const encryptedBytes = cipher.update(msg); - const EM = Buffer.concat([iv, encryptedBytes]); - const D = hmac(hKm, EM, options); - - return Buffer.concat([Buffer.from(Rb, "hex"), EM, Buffer.from(D)]); +function eciesEncryptMessage( + recipientPublicKey, + msg, + options, + aesKeyLength = AESKeyLength, +) { + const level = recipientPublicKey.ecparams.keylen; + options.securityLevel = level; + processOption(options); + + const ecdsa = new elliptic.ec(`p${level}`); + const pubKey = ecdsa.keyFromPublic(recipientPublicKey.pubKeyHex, "hex"); + + // Generate ephemeral key-pair + const ephKeyPair = jsrsa.KEYUTIL.generateKeypair("EC", options.curveName); + const ephPrivKey = ecdsa.keyFromPrivate( + ephKeyPair.prvKeyObj.prvKeyHex, + "hex", + ); + const Rb = ephKeyPair.pubKeyObj.pubKeyHex; + + // Derive a shared secret field element z from the ephemeral secret key k + // and convert z to an octet string Z + const Z = ephPrivKey.derive(pubKey.pub); + const kdfOutput = hkdf(Z.toArray(), ECIESKDFOutput, null, null, options); + + const aesKey = kdfOutput.slice(0, aesKeyLength); + const hmacKey = kdfOutput.slice(aesKeyLength, aesKeyLength + HMACKeyLength); + + const hmacKeyHash = new options.hashFunctionKeyDerivation(); + hmacKeyHash.update(bytesToBits(hmacKey)); + const hKm = bitsToBytes(hmacKeyHash.finalize()); + + const iv = crypto.randomBytes(IVLength); + // The go-ethereum crypto/ecies package that encrypts/decrypts data uses AES-128-CTR by default for signing certs currently generated by Fabric + let aesAlgorithm; + if (aesKeyLength === 16) { + aesAlgorithm = "aes-128-ctr"; + } else if (aesKeyLength === 32) { + aesAlgorithm = "aes-256-ctr"; + } else { + throw new Error("Invalid AES key length supplied: " + aesKeyLength); + } + const cipher = crypto.createCipheriv(aesAlgorithm, Buffer.from(aesKey), iv); + const encryptedBytes = cipher.update(msg); + const EM = Buffer.concat([iv, encryptedBytes]); + const D = hmac(hKm, EM, options); + + return Buffer.concat([Buffer.from(Rb, "hex"), EM, Buffer.from(D)]); } function checkSecurityLevel(securityLevel) { - if (securityLevel !== 256 && securityLevel !== 384) - throw new Error(`Illegal level: ${this.securityLevel} - must be either 256 or 384`); + if (securityLevel !== 256 && securityLevel !== 384) + throw new Error( + `Illegal level: ${this.securityLevel} - must be either 256 or 384`, + ); } function checkHashFunction(hashAlgorithm) { - if (!isString(hashAlgorithm)) - throw new Error(`Illegal Hash function family: ${hashAlgorithm} - must be either SHA2 or SHA3`); + if (!isString(hashAlgorithm)) + throw new Error( + `Illegal Hash function family: ${hashAlgorithm} - must be either SHA2 or SHA3`, + ); - const hashAlgorithmUpper = hashAlgorithm.toUpperCase(); - if (hashAlgorithmUpper !== SHA2 && hashAlgorithmUpper !== SHA3) - throw new Error(`Illegal Hash function family: ${hashAlgorithm} - must be either SHA2 or SHA3`); + const hashAlgorithmUpper = hashAlgorithm.toUpperCase(); + if (hashAlgorithmUpper !== SHA2 && hashAlgorithmUpper !== SHA3) + throw new Error( + `Illegal Hash function family: ${hashAlgorithm} - must be either SHA2 or SHA3`, + ); } function processOption(options) { - checkSecurityLevel(options.securityLevel); - checkHashFunction(options.hashAlgorithm); - - options.suite = `${options.hashAlgorithm.toLowerCase()}-${options.securityLevel}`; - - if (options.securityLevel === CURVE_P_256_Size) { - options.curveName = "secp256r1"; - } else if (options.securityLevel === CURVE_P_384_Size) { - options.curveName = "secp384r1"; - } - - switch (options.suite) { - case "sha3-256": - options.hashFunctionKeyDerivation = sha3.sha3_256; - options.hashOutputSize = 32; - break; - case "sha3-384": - options.hashFunctionKeyDerivation = sha3.sha3_384; - options.hashOutputSize = 48; - break; - case "sha2-256": - options.hashFunctionKeyDerivation = sjcl.hash.sha256; - options.hashOutputSize = 32; - break; - default: - throw new Error(`Suite ${options.suite} not found.`); - } - - switch (options.securityLevel) { - case 256: - options.ecdsaCurve = elliptic.curves.p256; - break; - case 384: - options.ecdsaCurve = elliptic.curves.p384; - break; - default: - throw new Error(`Security level ${options.securityLevel} not found.`); - } - - return options; + checkSecurityLevel(options.securityLevel); + checkHashFunction(options.hashAlgorithm); + + options.suite = `${options.hashAlgorithm.toLowerCase()}-${options.securityLevel}`; + + if (options.securityLevel === CURVE_P_256_Size) { + options.curveName = "secp256r1"; + } else if (options.securityLevel === CURVE_P_384_Size) { + options.curveName = "secp384r1"; + } + + switch (options.suite) { + case "sha3-256": + options.hashFunctionKeyDerivation = sha3.sha3_256; + options.hashOutputSize = 32; + break; + case "sha3-384": + options.hashFunctionKeyDerivation = sha3.sha3_384; + options.hashOutputSize = 48; + break; + case "sha2-256": + options.hashFunctionKeyDerivation = sjcl.hash.sha256; + options.hashOutputSize = 32; + break; + default: + throw new Error(`Suite ${options.suite} not found.`); + } + + switch (options.securityLevel) { + case 256: + options.ecdsaCurve = elliptic.curves.p256; + break; + case 384: + options.ecdsaCurve = elliptic.curves.p384; + break; + default: + throw new Error(`Security level ${options.securityLevel} not found.`); + } + + return options; } function hkdf(ikm, keyBitLength, salt, info, options) { - if (!salt) salt = createZeroBuffer(options.hashOutputSize); - if (!info) info = ""; - - const key = hkdf2( - bytesToBits(Buffer.from(ikm)), - keyBitLength, - bytesToBits(salt), - info, - options.hashFunctionKeyDerivation, - ); - - return bitsToBytes(key); + if (!salt) salt = createZeroBuffer(options.hashOutputSize); + if (!info) info = ""; + + const key = hkdf2( + bytesToBits(Buffer.from(ikm)), + keyBitLength, + bytesToBits(salt), + info, + options.hashFunctionKeyDerivation, + ); + + return bitsToBytes(key); } function hkdf2(ikm, keyBitLength, salt, info, Hash) { - let hmac; - let i; - let curOut; - let ret = []; - - if (typeof info === "string") { - info = sjcl.codec.utf8String.toBits(info); - } else if (!info) { - info = sjcl.codec.utf8String.toBits(""); - } - if (typeof salt === "string") { - salt = sjcl.codec.utf8String.toBits(salt); - } else if (!salt) { - salt = []; - } - - hmac = new sjcl.misc.hmac(salt, Hash); + let hmac; + let i; + let curOut; + let ret = []; + + if (typeof info === "string") { + info = sjcl.codec.utf8String.toBits(info); + } else if (!info) { + info = sjcl.codec.utf8String.toBits(""); + } + if (typeof salt === "string") { + salt = sjcl.codec.utf8String.toBits(salt); + } else if (!salt) { + salt = []; + } + + hmac = new sjcl.misc.hmac(salt, Hash); + hmac.update(ikm); + const key = hmac.digest(); + const hashLen = sjcl.bitArray.bitLength(key); + + const loops = Math.ceil(keyBitLength / hashLen); + if (loops > 255) { + throw new sjcl.exception.invalid("key bit length is too large for hkdf"); + } + + const counter = [0, 0, 0, 1]; + curOut = []; + for (i = 1; i <= loops; i++) { + hmac = new Hash(); + hmac.update(bytesToBits(counter)); hmac.update(ikm); - const key = hmac.digest(); - const hashLen = sjcl.bitArray.bitLength(key); - - const loops = Math.ceil(keyBitLength / hashLen); - if (loops > 255) { - throw new sjcl.exception.invalid("key bit length is too large for hkdf"); - } - - const counter = [0, 0, 0, 1]; - curOut = []; - for (i = 1; i <= loops; i++) { - hmac = new Hash(); - hmac.update(bytesToBits(counter)); - hmac.update(ikm); - hmac.update(bytesToBits(info)); - ret = sjcl.bitArray.concat(hmac.finalize(), curOut); - } - return sjcl.bitArray.clamp(ret, keyBitLength); + hmac.update(bytesToBits(info)); + ret = sjcl.bitArray.concat(hmac.finalize(), curOut); + } + return sjcl.bitArray.clamp(ret, keyBitLength); } function hmac(key, bytes, options) { - const hmac = new sjcl.misc.hmac(bytesToBits(key), options.hashFunctionKeyDerivation); - hmac.update(bytesToBits(bytes)); - const result = hmac.digest(); - return bitsToBytes(result); + const hmac = new sjcl.misc.hmac( + bytesToBits(key), + options.hashFunctionKeyDerivation, + ); + hmac.update(bytesToBits(bytes)); + const result = hmac.digest(); + return bitsToBytes(result); } function bitsToBytes(arr) { - const out = []; - const bl = sjcl.bitArray.bitLength(arr); - let tmp; - for (let i = 0; i < bl / 8; i++) { - if ((i & 3) === 0) { - tmp = arr[i / 4]; - } - out.push(tmp >>> 24); - tmp <<= 8; + const out = []; + const bl = sjcl.bitArray.bitLength(arr); + let tmp; + for (let i = 0; i < bl / 8; i++) { + if ((i & 3) === 0) { + tmp = arr[i / 4]; } - return out; + out.push(tmp >>> 24); + tmp <<= 8; + } + return out; } function bytesToBits(bytes) { - const out = []; - let i; - let tmp = 0; - for (i = 0; i < bytes.length; i++) { - tmp = (tmp << 8) | bytes[i]; - if ((i & 3) === 3) { - out.push(tmp); - tmp = 0; - } - } - if (i & 3) { - out.push(sjcl.bitArray.partial(8 * (i & 3), tmp)); + const out = []; + let i; + let tmp = 0; + for (i = 0; i < bytes.length; i++) { + tmp = (tmp << 8) | bytes[i]; + if ((i & 3) === 3) { + out.push(tmp); + tmp = 0; } - return out; + } + if (i & 3) { + out.push(sjcl.bitArray.partial(8 * (i & 3), tmp)); + } + return out; } function createZeroBuffer(length) { - const buf = Buffer.alloc(length); - buf.fill(0); - return buf; + const buf = Buffer.alloc(length); + buf.fill(0); + return buf; } function isString(obj) { - return typeof obj === "string" || obj instanceof String; + return typeof obj === "string" || obj instanceof String; } module.exports.eciesDecryptMessage = eciesDecryptMessage; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/helpers.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/helpers.ts index 34662c9bae..1a1bd5f973 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/helpers.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/helpers.ts @@ -11,44 +11,48 @@ import { promisify } from "util"; // A better way to handle errors for promises function handlePromise(promise: Promise): Promise<[T?, Error?]> { - const result: Promise<[T?, Error?]> = promise - .then((data) => { - const response: [T?, Error?] = [data, undefined]; - return response; - }) - .catch((error) => Promise.resolve([undefined, error])); - return result; + const result: Promise<[T?, Error?]> = promise + .then((data) => { + const response: [T?, Error?] = [data, undefined]; + return response; + }) + .catch((error) => Promise.resolve([undefined, error])); + return result; } // Necessary until gRPC provides a native async friendly solution https://github.com/grpc/grpc-node/issues/54 function promisifyAll(client: any): any { - const to = {}; - // // eslint-disable-next-line - for (const k in client) { - // eslint-disable-next-line - if (typeof client[k] !== "function") continue - to[k] = promisify(client[k].bind(client)); - } - return to; + const to = {}; + // // eslint-disable-next-line + for (const k in client) { + // eslint-disable-next-line + if (typeof client[k] !== "function") continue; + to[k] = promisify(client[k].bind(client)); + } + return to; } /** * Parses address string into location, view and network segments. * @param address **/ -function parseAddress(address: string): { locationSegment: string; viewSegment: string; networkSegment: string } { - const addressList = address.split("/"); - if (addressList.length !== 3) { - throw new Error("Invalid address string"); - } - return { - locationSegment: addressList[0], - networkSegment: addressList[1], - viewSegment: addressList[2], - }; +function parseAddress(address: string): { + locationSegment: string; + viewSegment: string; + networkSegment: string; +} { + const addressList = address.split("/"); + if (addressList.length !== 3) { + throw new Error("Invalid address string"); + } + return { + locationSegment: addressList[0], + networkSegment: addressList[1], + viewSegment: addressList[2], + }; } async function delay(ms: number) { - await new Promise(f => setTimeout(f, ms)); + await new Promise((f) => setTimeout(f, ms)); } export { handlePromise, promisifyAll, parseAddress, delay }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/types.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/types.ts index 4bdd1aaf4c..cd67667853 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/src/types.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/types.ts @@ -5,36 +5,36 @@ */ export type InvocationSpec = { - ccArgs: string[]; - channel: string; - ccFunc: string; - contractName: string; + ccArgs: string[]; + channel: string; + ccFunc: string; + contractName: string; }; export type Flow = { - flowArgs: string[]; - cordappAddress: string; - flowId: string; - cordappId: string; + flowArgs: string[]; + cordappAddress: string; + flowId: string; + cordappId: string; }; export type InteropJSON = { - address?: string; - ChaincodeFunc?: string; - ChaincodeID?: string; - ChannelID?: string; - RemoteEndpoint?: string; - NetworkID?: string; - Sign: boolean; - ccArgs?: string[]; + address?: string; + ChaincodeFunc?: string; + ChaincodeID?: string; + ChannelID?: string; + RemoteEndpoint?: string; + NetworkID?: string; + Sign: boolean; + ccArgs?: string[]; }; export type RemoteJSON = { - LocalRelayEndpoint: string; - viewRequests: { - [key: string]: { - invokeArgIndices: Array; - interopJSONs: Array; - }; + LocalRelayEndpoint: string; + viewRequests: { + [key: string]: { + invokeArgIndices: Array; + interopJSONs: Array; }; + }; }; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/test/AssetManager.js b/weaver/sdks/fabric/interoperation-node-sdk/test/AssetManager.js index 9674528a55..1e15c3ea42 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/test/AssetManager.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/test/AssetManager.js @@ -25,493 +25,938 @@ const hashFunctions = require("../src/HashFunctions"); import assetLocksPb from "@hyperledger/cacti-weaver-protos-js/common/asset_locks_pb"; describe("AssetManager", () => { - const mspId = "mspId"; - const foreignNetworkId = "foreignNetworkId"; - const userName = "user_name"; - - const assetType = "bond"; - const assetID = "A001"; - const fungibleAssetType = "cbdc"; - const numUnits = 1000; - const recipientECert = fs.readFileSync(`${__dirname}/data/anotherSignCert.pem`).toString(); - let lockerECert; - - let wallet; - let amc; - let amcTx; - // Initialize wallet with a single user identity - async function initializeWallet() { - const privKeyFile = `${__dirname}/data/privKey.pem`; - const signCertFile = `${__dirname}/data/signCert.pem`; - const privateKeyStr = fs.readFileSync(privKeyFile).toString(); - const signCert = fs.readFileSync(signCertFile).toString(); - lockerECert = signCert; - wallet = await Wallets.newInMemoryWallet(); - const userIdentity = { - credentials: { certificate: signCert, privateKey: privateKeyStr }, - mspId, - type: "X.509", - }; - await wallet.put(userName, userIdentity); - return userIdentity; - } - - async function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - beforeEach(async () => { - await initializeWallet(); - const network = sinon.createStubInstance(NetworkImpl); - amc = new ContractImpl(network, "amc", "AssetManager"); - amcTx = sinon.createStubInstance(Transaction) - const amcStub = sinon.stub(amc, "createTransaction").returns(amcTx); - }); - - afterEach(() => { - sinon.restore(); - }); - - describe("create HTLC for unique asset", () => { - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset lock fails with invalid parameters", async () => { - let expiryTimeSecs = Math.floor(Date.now()/1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes - let assetLockInvocation = await assetManager.createHTLC(null, assetType, assetID, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(false); - assetLockInvocation = await assetManager.createHTLC(amc, "", assetID, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(false); - assetLockInvocation = await assetManager.createHTLC(amc, assetType, "", recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(false); - assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, "", null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(false); - assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, recipientECert, null, expiryTimeSecs - 600); // Expiry time in the past - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(false); - }); - - it("submit asset lock invocation", async () => { - let assetAgreementStr = assetManager.createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, ""); - const hashValue = "abcdef123456" - const hash = new hashFunctions.SHA256() - hash.setSerializedHashBase64(hashValue) - let expiryTimeSecs = Math.floor(Date.now()/1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes - let lockInfoStr = assetManager.createAssetLockInfoSerialized(hash, expiryTimeSecs); - amcTx.submit.withArgs(assetAgreementStr, lockInfoStr).resolves(true); - let assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, recipientECert, hash, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.equal(null); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal(hashValue); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(true); - amcTx.submit.withArgs(assetAgreementStr, sinon.match.any).resolves(true); - assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, recipientECert, hash, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.equal(null); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal(hashValue); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(true); - assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.be.a("string"); - expect(assetLockInvocation.hash.getPreimage().length).to.be.above(0); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64().length).to.be.above(0); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(true); - - const hashPreimage = "some-preimage"; - const hash2 = new hashFunctions.SHA256() - hash2.setPreimage("some-preimage") - assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, recipientECert, hash2, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.equal(hashPreimage); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64().length).to.be.above(0); - expect(assetLockInvocation.result).to.be.a('boolean'); - expect(assetLockInvocation.result).to.equal(true); - - const testAttr = assetType + ':' + assetID + ':' + recipientECert + ':' + hash2.getPreimage() + ':' + hash2.getSerializedHashBase64(); - const timeoutCb = function(c, t, i, r, h) { - console.log('Asset lock TIMEOUT at', Date()); - c.testAttr = t + ':' + i + ':' + r + ':' + h.getPreimage() + ':' + h.getSerializedHashBase64(); - }; - expiryTimeSecs = Math.floor(Date.now()/1000) + 3; // 3 seconds - assetLockInvocation = await assetManager.createHTLC(amc, assetType, assetID, recipientECert, hash2, expiryTimeSecs, timeoutCb); - await sleep(4000); - expect(amc).to.have.own.property('testAttr'); - expect(amc.testAttr).to.equal(testAttr); - }); - }); - - describe("create HTLC for fungible asset", () => { - - beforeEach(() => { - amcTx.submit.resolves(""); - }); - - it("asset lock fails with invalid parameters", async () => { - let expiryTimeSecs = Math.floor(Date.now()/1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes - let assetLockInvocation = await assetManager.createFungibleHTLC(null, fungibleAssetType, numUnits, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(''); - assetLockInvocation = await assetManager.createFungibleHTLC(amc, "", numUnits, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(''); - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, -1, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(''); - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, "", null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(''); - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, recipientECert, null, expiryTimeSecs - 600); // Expiry time in the past - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash).to.equal(null); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(''); - }); - - it("submit asset lock invocation", async () => { - let assetAgreementStr = assetManager.createFungibleAssetExchangeAgreementSerialized(fungibleAssetType, numUnits, recipientECert, ""); - const hashValue = "abcdef123456"; - const hash = new hashFunctions.SHA256() - hash.setSerializedHashBase64(hashValue) - let expiryTimeSecs = Math.floor(Date.now()/1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes - let lockInfoStr = assetManager.createAssetLockInfoSerialized(hash, expiryTimeSecs); - const contractId = "CONTRACT-1234"; - amcTx.submit.withArgs(assetAgreementStr, lockInfoStr).resolves(contractId); - let assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, recipientECert, hash, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.equal(null); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal(hashValue); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(contractId); - amcTx.submit.withArgs(assetAgreementStr, sinon.match.any).resolves(contractId); - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, recipientECert, hash, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.equal(null); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal(hashValue); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(contractId); - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, recipientECert, null, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.be.a("string"); - expect(assetLockInvocation.hash.getPreimage().length).to.be.above(0); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64().length).to.be.above(0); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(contractId); - - const hashPreimage = "some-preimage"; - const hash2 = new hashFunctions.SHA256() - hash2.setPreimage(hashPreimage) - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, recipientECert, hash2, expiryTimeSecs); - expect(assetLockInvocation).to.be.an('object').that.has.all.keys('hash', 'result'); - expect(assetLockInvocation.hash.getPreimage()).to.equal(hashPreimage); - expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a("string"); - expect(assetLockInvocation.hash.getSerializedHashBase64().length).to.be.above(0); - expect(assetLockInvocation.result).to.be.a('string'); - expect(assetLockInvocation.result).to.equal(contractId); - const testAttr = contractId + ':' + fungibleAssetType + ':' + numUnits + ':' + recipientECert + ':' + hash2.getPreimage() + ':' + hash2.getSerializedHashBase64(); - const timeoutCb = function(c, i, t, n, r, h) { - console.log('Fungible asset lock TIMEOUT at', Date()); - c.testAttr = i + ':' + t + ':' + n + ':' + r + ':' + h.getPreimage() + ':' + h.getSerializedHashBase64(); - }; - expiryTimeSecs = Math.floor(Date.now()/1000) + 3; // 3 seconds - assetLockInvocation = await assetManager.createFungibleHTLC(amc, fungibleAssetType, numUnits, recipientECert, hash2, expiryTimeSecs, timeoutCb); - await sleep(4000); - expect(amc).to.have.own.property('testAttr'); - expect(amc.testAttr).to.equal(testAttr); - }); - }); - - describe("claim unique asset locked in HTLC", () => { - const hashPreimage = "xyz+123-*ty%"; - const hash = new hashFunctions.SHA256() - hash.setPreimage(hashPreimage) - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset claim fails with invalid parameters", async () => { - let assetClaimInvocation = await assetManager.claimAssetInHTLC(null, assetType, assetID, lockerECert, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimAssetInHTLC(amc, "", assetID, lockerECert, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimAssetInHTLC(amc, assetType, "", lockerECert, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimAssetInHTLC(amc, assetType, assetID, "", hashPreimage); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimAssetInHTLC(amc, assetType, assetID, lockerECert, ""); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - }); - - it("submit asset claim invocation", async () => { - let assetAgreementStr = assetManager.createAssetExchangeAgreementSerialized(assetType, assetID, "", lockerECert); - let claimInfoStr = assetManager.createAssetClaimInfoSerialized(hash); - amcTx.submit.withArgs(assetAgreementStr, claimInfoStr).resolves(true); - let assetClaimInvocation = await assetManager.claimAssetInHTLC(amc, assetType, assetID, lockerECert, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(true); - }); - }); - - describe("claim unique asset locked in HTLC using contractId", () => { - const hashPreimage = "xyz+123-*ty%"; - const hash = new hashFunctions.SHA256() - hash.setPreimage(hashPreimage) - const contractId = "CONTRACT-1234"; - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset claim fails with invalid parameters", async () => { - let assetClaimInvocation = await assetManager.claimAssetInHTLCusingContractId(null, contractId, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimAssetInHTLCusingContractId(amc, "", hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimAssetInHTLCusingContractId(amc, contractId, null); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - }); - - it("submit asset claim invocation", async () => { - let claimInfoStr = assetManager.createAssetClaimInfoSerialized(hash); - amcTx.submit.withArgs(contractId, claimInfoStr).resolves(true); - let assetClaimInvocation = await assetManager.claimAssetInHTLCusingContractId(amc, contractId, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(true); - }); - }); - - describe("claim fungible asset locked in HTLC", () => { - const hashPreimage = "xyz+123-*ty%"; - const hash = new hashFunctions.SHA256() - hash.setPreimage(hashPreimage) - const contractId = "CONTRACT-1234"; - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset claim fails with invalid parameters", async () => { - let assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC(null, contractId, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC(amc, "", hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC(amc, contractId, null); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(false); - }); - - it("submit asset claim invocation", async () => { - let claimInfoStr = assetManager.createAssetClaimInfoSerialized(hash); - amcTx.submit.withArgs(contractId, claimInfoStr).resolves(true); - let assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC(amc, contractId, hash); - expect(assetClaimInvocation).to.be.a('boolean'); - expect(assetClaimInvocation).to.equal(true); - }); - }); - - describe("reclaim unique asset locked in HTLC", () => { - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset reclaim fails with invalid parameters", async () => { - let assetReclaimInvocation = await assetManager.reclaimAssetInHTLC(null, assetType, assetID, recipientECert); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - assetReclaimInvocation = await assetManager.reclaimAssetInHTLC(amc, "", assetID, recipientECert); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - assetReclaimInvocation = await assetManager.reclaimAssetInHTLC(amc, assetType, "", recipientECert); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - assetReclaimInvocation = await assetManager.reclaimAssetInHTLC(amc, assetType, assetID, ""); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - }); - - it("submit asset reclaim invocation", async () => { - let assetAgreementStr = assetManager.createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, ""); - amcTx.submit.withArgs(assetAgreementStr).resolves(true); - let assetReclaimInvocation = await assetManager.reclaimAssetInHTLC(amc, assetType, assetID, recipientECert); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(true); - }); - }); - - describe("reclaim unique asset locked in HTLC using contractId", () => { - const contractId = "CONTRACT-1234"; - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset reclaim fails with invalid parameters", async () => { - let assetReclaimInvocation = await assetManager.reclaimAssetInHTLCusingContractId(null, contractId); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - assetReclaimInvocation = await assetManager.reclaimAssetInHTLCusingContractId(amc, ""); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - }); - - it("submit asset reclaim invocation", async () => { - amcTx.submit.withArgs(contractId).resolves(true); - let assetReclaimInvocation = await assetManager.reclaimAssetInHTLCusingContractId(amc, contractId); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(true); - }); - }); - - describe("reclaim fungible asset locked in HTLC", () => { - const contractId = "CONTRACT-1234"; - - beforeEach(() => { - amcTx.submit.resolves(false); - }); - - it("asset reclaim fails with invalid parameters", async () => { - let assetReclaimInvocation = await assetManager.reclaimFungibleAssetInHTLC(null, contractId); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - assetReclaimInvocation = await assetManager.reclaimFungibleAssetInHTLC(amc, ""); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(false); - }); - - it("submit asset reclaim invocation", async () => { - amcTx.submit.withArgs(contractId).resolves(true); - let assetReclaimInvocation = await assetManager.reclaimFungibleAssetInHTLC(amc, contractId); - expect(assetReclaimInvocation).to.be.a('boolean'); - expect(assetReclaimInvocation).to.equal(true); - }); - }); - - describe("check unique asset lock status in HTLC", () => { - let amcStub; - - beforeEach(() => { - amcStub = sinon.stub(amc, "evaluateTransaction").resolves(false); - }); - - it("asset lock status check fails with invalid parameters", async () => { - let assetLockQuery = await assetManager.isAssetLockedInHTLC(null, assetType, assetID, recipientECert, lockerECert); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - assetLockQuery = await assetManager.isAssetLockedInHTLC(amc, "", assetID, recipientECert, lockerECert); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - assetLockQuery = await assetManager.isAssetLockedInHTLC(amc, assetType, "", recipientECert, lockerECert); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - assetLockQuery = await assetManager.isAssetLockedInHTLC(amc, assetType, assetID, "", lockerECert); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - assetLockQuery = await assetManager.isAssetLockedInHTLC(amc, assetType, assetID, recipientECert, ""); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - }); - - it("submit asset lock status query", async () => { - let assetAgreementStr = assetManager.createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, lockerECert); - amcStub.withArgs("IsAssetLocked", assetAgreementStr).resolves(true); - let assetLockQuery = await assetManager.isAssetLockedInHTLC(amc, assetType, assetID, recipientECert, lockerECert); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(true); - }); - }); - - describe("check unique asset lock status in HTLC using contractId", () => { - let amcStub; - const contractId = "CONTRACT-1234"; - - beforeEach(() => { - amcStub = sinon.stub(amc, "evaluateTransaction").resolves(false); - }); - - it("asset lock status check fails with invalid parameters", async () => { - let assetLockQuery = await assetManager.isAssetLockedInHTLCqueryUsingContractId(null, contractId); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - assetLockQuery = await assetManager.isAssetLockedInHTLCqueryUsingContractId(amc, null); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - }); - - it("submit asset lock status query", async () => { - amcStub.withArgs("IsAssetLockedQueryUsingContractId", contractId).resolves(true); - let assetLockQuery = await assetManager.isAssetLockedInHTLCqueryUsingContractId(amc, contractId); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(true); - }); - }); - - describe("check fungible asset lock status in HTLC", () => { - let amcStub; - const contractId = "CONTRACT-1234"; - - beforeEach(() => { - amcStub = sinon.stub(amc, "evaluateTransaction").resolves(false); - }); - - it("asset lock status check fails with invalid parameters", async () => { - let assetLockQuery = await assetManager.isFungibleAssetLockedInHTLC(null, contractId); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - assetLockQuery = await assetManager.isFungibleAssetLockedInHTLC(amc, ""); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(false); - }); - - it("submit asset lock status query", async () => { - amcStub.withArgs("IsFungibleAssetLocked", contractId).resolves(true); - let assetLockQuery = await assetManager.isFungibleAssetLockedInHTLC(amc, contractId); - expect(assetLockQuery).to.be.a('boolean'); - expect(assetLockQuery).to.equal(true); - }); + const mspId = "mspId"; + const foreignNetworkId = "foreignNetworkId"; + const userName = "user_name"; + + const assetType = "bond"; + const assetID = "A001"; + const fungibleAssetType = "cbdc"; + const numUnits = 1000; + const recipientECert = fs + .readFileSync(`${__dirname}/data/anotherSignCert.pem`) + .toString(); + let lockerECert; + + let wallet; + let amc; + let amcTx; + // Initialize wallet with a single user identity + async function initializeWallet() { + const privKeyFile = `${__dirname}/data/privKey.pem`; + const signCertFile = `${__dirname}/data/signCert.pem`; + const privateKeyStr = fs.readFileSync(privKeyFile).toString(); + const signCert = fs.readFileSync(signCertFile).toString(); + lockerECert = signCert; + wallet = await Wallets.newInMemoryWallet(); + const userIdentity = { + credentials: { certificate: signCert, privateKey: privateKeyStr }, + mspId, + type: "X.509", + }; + await wallet.put(userName, userIdentity); + return userIdentity; + } + + async function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + beforeEach(async () => { + await initializeWallet(); + const network = sinon.createStubInstance(NetworkImpl); + amc = new ContractImpl(network, "amc", "AssetManager"); + amcTx = sinon.createStubInstance(Transaction); + const amcStub = sinon.stub(amc, "createTransaction").returns(amcTx); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("create HTLC for unique asset", () => { + beforeEach(() => { + amcTx.submit.resolves(false); }); + + it("asset lock fails with invalid parameters", async () => { + let expiryTimeSecs = Math.floor(Date.now() / 1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes + let assetLockInvocation = await assetManager.createHTLC( + null, + assetType, + assetID, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(false); + assetLockInvocation = await assetManager.createHTLC( + amc, + "", + assetID, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(false); + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + "", + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(false); + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + "", + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(false); + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + recipientECert, + null, + expiryTimeSecs - 600, + ); // Expiry time in the past + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(false); + }); + + it("submit asset lock invocation", async () => { + let assetAgreementStr = + assetManager.createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + "", + ); + const hashValue = "abcdef123456"; + const hash = new hashFunctions.SHA256(); + hash.setSerializedHashBase64(hashValue); + let expiryTimeSecs = Math.floor(Date.now() / 1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes + let lockInfoStr = assetManager.createAssetLockInfoSerialized( + hash, + expiryTimeSecs, + ); + amcTx.submit.withArgs(assetAgreementStr, lockInfoStr).resolves(true); + let assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + recipientECert, + hash, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.equal(null); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal( + hashValue, + ); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(true); + amcTx.submit.withArgs(assetAgreementStr, sinon.match.any).resolves(true); + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + recipientECert, + hash, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.equal(null); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal( + hashValue, + ); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(true); + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.be.a("string"); + expect(assetLockInvocation.hash.getPreimage().length).to.be.above(0); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect( + assetLockInvocation.hash.getSerializedHashBase64().length, + ).to.be.above(0); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(true); + + const hashPreimage = "some-preimage"; + const hash2 = new hashFunctions.SHA256(); + hash2.setPreimage("some-preimage"); + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + recipientECert, + hash2, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.equal(hashPreimage); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect( + assetLockInvocation.hash.getSerializedHashBase64().length, + ).to.be.above(0); + expect(assetLockInvocation.result).to.be.a("boolean"); + expect(assetLockInvocation.result).to.equal(true); + + const testAttr = + assetType + + ":" + + assetID + + ":" + + recipientECert + + ":" + + hash2.getPreimage() + + ":" + + hash2.getSerializedHashBase64(); + const timeoutCb = function (c, t, i, r, h) { + console.log("Asset lock TIMEOUT at", Date()); + c.testAttr = + t + + ":" + + i + + ":" + + r + + ":" + + h.getPreimage() + + ":" + + h.getSerializedHashBase64(); + }; + expiryTimeSecs = Math.floor(Date.now() / 1000) + 3; // 3 seconds + assetLockInvocation = await assetManager.createHTLC( + amc, + assetType, + assetID, + recipientECert, + hash2, + expiryTimeSecs, + timeoutCb, + ); + await sleep(4000); + expect(amc).to.have.own.property("testAttr"); + expect(amc.testAttr).to.equal(testAttr); + }); + }); + + describe("create HTLC for fungible asset", () => { + beforeEach(() => { + amcTx.submit.resolves(""); + }); + + it("asset lock fails with invalid parameters", async () => { + let expiryTimeSecs = Math.floor(Date.now() / 1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes + let assetLockInvocation = await assetManager.createFungibleHTLC( + null, + fungibleAssetType, + numUnits, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(""); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + "", + numUnits, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(""); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + -1, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(""); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + "", + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(""); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + recipientECert, + null, + expiryTimeSecs - 600, + ); // Expiry time in the past + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash).to.equal(null); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(""); + }); + + it("submit asset lock invocation", async () => { + let assetAgreementStr = + assetManager.createFungibleAssetExchangeAgreementSerialized( + fungibleAssetType, + numUnits, + recipientECert, + "", + ); + const hashValue = "abcdef123456"; + const hash = new hashFunctions.SHA256(); + hash.setSerializedHashBase64(hashValue); + let expiryTimeSecs = Math.floor(Date.now() / 1000) + 300; // Convert epoch milliseconds to seconds and add 5 minutes + let lockInfoStr = assetManager.createAssetLockInfoSerialized( + hash, + expiryTimeSecs, + ); + const contractId = "CONTRACT-1234"; + amcTx.submit + .withArgs(assetAgreementStr, lockInfoStr) + .resolves(contractId); + let assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + recipientECert, + hash, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.equal(null); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal( + hashValue, + ); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(contractId); + amcTx.submit + .withArgs(assetAgreementStr, sinon.match.any) + .resolves(contractId); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + recipientECert, + hash, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.equal(null); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.equal( + hashValue, + ); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(contractId); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + recipientECert, + null, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.be.a("string"); + expect(assetLockInvocation.hash.getPreimage().length).to.be.above(0); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect( + assetLockInvocation.hash.getSerializedHashBase64().length, + ).to.be.above(0); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(contractId); + + const hashPreimage = "some-preimage"; + const hash2 = new hashFunctions.SHA256(); + hash2.setPreimage(hashPreimage); + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + recipientECert, + hash2, + expiryTimeSecs, + ); + expect(assetLockInvocation) + .to.be.an("object") + .that.has.all.keys("hash", "result"); + expect(assetLockInvocation.hash.getPreimage()).to.equal(hashPreimage); + expect(assetLockInvocation.hash.getSerializedHashBase64()).to.be.a( + "string", + ); + expect( + assetLockInvocation.hash.getSerializedHashBase64().length, + ).to.be.above(0); + expect(assetLockInvocation.result).to.be.a("string"); + expect(assetLockInvocation.result).to.equal(contractId); + const testAttr = + contractId + + ":" + + fungibleAssetType + + ":" + + numUnits + + ":" + + recipientECert + + ":" + + hash2.getPreimage() + + ":" + + hash2.getSerializedHashBase64(); + const timeoutCb = function (c, i, t, n, r, h) { + console.log("Fungible asset lock TIMEOUT at", Date()); + c.testAttr = + i + + ":" + + t + + ":" + + n + + ":" + + r + + ":" + + h.getPreimage() + + ":" + + h.getSerializedHashBase64(); + }; + expiryTimeSecs = Math.floor(Date.now() / 1000) + 3; // 3 seconds + assetLockInvocation = await assetManager.createFungibleHTLC( + amc, + fungibleAssetType, + numUnits, + recipientECert, + hash2, + expiryTimeSecs, + timeoutCb, + ); + await sleep(4000); + expect(amc).to.have.own.property("testAttr"); + expect(amc.testAttr).to.equal(testAttr); + }); + }); + + describe("claim unique asset locked in HTLC", () => { + const hashPreimage = "xyz+123-*ty%"; + const hash = new hashFunctions.SHA256(); + hash.setPreimage(hashPreimage); + + beforeEach(() => { + amcTx.submit.resolves(false); + }); + + it("asset claim fails with invalid parameters", async () => { + let assetClaimInvocation = await assetManager.claimAssetInHTLC( + null, + assetType, + assetID, + lockerECert, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimAssetInHTLC( + amc, + "", + assetID, + lockerECert, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimAssetInHTLC( + amc, + assetType, + "", + lockerECert, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimAssetInHTLC( + amc, + assetType, + assetID, + "", + hashPreimage, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimAssetInHTLC( + amc, + assetType, + assetID, + lockerECert, + "", + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + }); + + it("submit asset claim invocation", async () => { + let assetAgreementStr = + assetManager.createAssetExchangeAgreementSerialized( + assetType, + assetID, + "", + lockerECert, + ); + let claimInfoStr = assetManager.createAssetClaimInfoSerialized(hash); + amcTx.submit.withArgs(assetAgreementStr, claimInfoStr).resolves(true); + let assetClaimInvocation = await assetManager.claimAssetInHTLC( + amc, + assetType, + assetID, + lockerECert, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(true); + }); + }); + + describe("claim unique asset locked in HTLC using contractId", () => { + const hashPreimage = "xyz+123-*ty%"; + const hash = new hashFunctions.SHA256(); + hash.setPreimage(hashPreimage); + const contractId = "CONTRACT-1234"; + + beforeEach(() => { + amcTx.submit.resolves(false); + }); + + it("asset claim fails with invalid parameters", async () => { + let assetClaimInvocation = + await assetManager.claimAssetInHTLCusingContractId( + null, + contractId, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimAssetInHTLCusingContractId( + amc, + "", + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimAssetInHTLCusingContractId( + amc, + contractId, + null, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + }); + + it("submit asset claim invocation", async () => { + let claimInfoStr = assetManager.createAssetClaimInfoSerialized(hash); + amcTx.submit.withArgs(contractId, claimInfoStr).resolves(true); + let assetClaimInvocation = + await assetManager.claimAssetInHTLCusingContractId( + amc, + contractId, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(true); + }); + }); + + describe("claim fungible asset locked in HTLC", () => { + const hashPreimage = "xyz+123-*ty%"; + const hash = new hashFunctions.SHA256(); + hash.setPreimage(hashPreimage); + const contractId = "CONTRACT-1234"; + + beforeEach(() => { + amcTx.submit.resolves(false); + }); + + it("asset claim fails with invalid parameters", async () => { + let assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC( + null, + contractId, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC( + amc, + "", + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC( + amc, + contractId, + null, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(false); + }); + + it("submit asset claim invocation", async () => { + let claimInfoStr = assetManager.createAssetClaimInfoSerialized(hash); + amcTx.submit.withArgs(contractId, claimInfoStr).resolves(true); + let assetClaimInvocation = await assetManager.claimFungibleAssetInHTLC( + amc, + contractId, + hash, + ); + expect(assetClaimInvocation).to.be.a("boolean"); + expect(assetClaimInvocation).to.equal(true); + }); + }); + + describe("reclaim unique asset locked in HTLC", () => { + beforeEach(() => { + amcTx.submit.resolves(false); + }); + + it("asset reclaim fails with invalid parameters", async () => { + let assetReclaimInvocation = await assetManager.reclaimAssetInHTLC( + null, + assetType, + assetID, + recipientECert, + ); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + assetReclaimInvocation = await assetManager.reclaimAssetInHTLC( + amc, + "", + assetID, + recipientECert, + ); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + assetReclaimInvocation = await assetManager.reclaimAssetInHTLC( + amc, + assetType, + "", + recipientECert, + ); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + assetReclaimInvocation = await assetManager.reclaimAssetInHTLC( + amc, + assetType, + assetID, + "", + ); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + }); + + it("submit asset reclaim invocation", async () => { + let assetAgreementStr = + assetManager.createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + "", + ); + amcTx.submit.withArgs(assetAgreementStr).resolves(true); + let assetReclaimInvocation = await assetManager.reclaimAssetInHTLC( + amc, + assetType, + assetID, + recipientECert, + ); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(true); + }); + }); + + describe("reclaim unique asset locked in HTLC using contractId", () => { + const contractId = "CONTRACT-1234"; + + beforeEach(() => { + amcTx.submit.resolves(false); + }); + + it("asset reclaim fails with invalid parameters", async () => { + let assetReclaimInvocation = + await assetManager.reclaimAssetInHTLCusingContractId(null, contractId); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + assetReclaimInvocation = + await assetManager.reclaimAssetInHTLCusingContractId(amc, ""); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + }); + + it("submit asset reclaim invocation", async () => { + amcTx.submit.withArgs(contractId).resolves(true); + let assetReclaimInvocation = + await assetManager.reclaimAssetInHTLCusingContractId(amc, contractId); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(true); + }); + }); + + describe("reclaim fungible asset locked in HTLC", () => { + const contractId = "CONTRACT-1234"; + + beforeEach(() => { + amcTx.submit.resolves(false); + }); + + it("asset reclaim fails with invalid parameters", async () => { + let assetReclaimInvocation = + await assetManager.reclaimFungibleAssetInHTLC(null, contractId); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + assetReclaimInvocation = await assetManager.reclaimFungibleAssetInHTLC( + amc, + "", + ); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(false); + }); + + it("submit asset reclaim invocation", async () => { + amcTx.submit.withArgs(contractId).resolves(true); + let assetReclaimInvocation = + await assetManager.reclaimFungibleAssetInHTLC(amc, contractId); + expect(assetReclaimInvocation).to.be.a("boolean"); + expect(assetReclaimInvocation).to.equal(true); + }); + }); + + describe("check unique asset lock status in HTLC", () => { + let amcStub; + + beforeEach(() => { + amcStub = sinon.stub(amc, "evaluateTransaction").resolves(false); + }); + + it("asset lock status check fails with invalid parameters", async () => { + let assetLockQuery = await assetManager.isAssetLockedInHTLC( + null, + assetType, + assetID, + recipientECert, + lockerECert, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + assetLockQuery = await assetManager.isAssetLockedInHTLC( + amc, + "", + assetID, + recipientECert, + lockerECert, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + assetLockQuery = await assetManager.isAssetLockedInHTLC( + amc, + assetType, + "", + recipientECert, + lockerECert, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + assetLockQuery = await assetManager.isAssetLockedInHTLC( + amc, + assetType, + assetID, + "", + lockerECert, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + assetLockQuery = await assetManager.isAssetLockedInHTLC( + amc, + assetType, + assetID, + recipientECert, + "", + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + }); + + it("submit asset lock status query", async () => { + let assetAgreementStr = + assetManager.createAssetExchangeAgreementSerialized( + assetType, + assetID, + recipientECert, + lockerECert, + ); + amcStub.withArgs("IsAssetLocked", assetAgreementStr).resolves(true); + let assetLockQuery = await assetManager.isAssetLockedInHTLC( + amc, + assetType, + assetID, + recipientECert, + lockerECert, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(true); + }); + }); + + describe("check unique asset lock status in HTLC using contractId", () => { + let amcStub; + const contractId = "CONTRACT-1234"; + + beforeEach(() => { + amcStub = sinon.stub(amc, "evaluateTransaction").resolves(false); + }); + + it("asset lock status check fails with invalid parameters", async () => { + let assetLockQuery = + await assetManager.isAssetLockedInHTLCqueryUsingContractId( + null, + contractId, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + assetLockQuery = + await assetManager.isAssetLockedInHTLCqueryUsingContractId(amc, null); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + }); + + it("submit asset lock status query", async () => { + amcStub + .withArgs("IsAssetLockedQueryUsingContractId", contractId) + .resolves(true); + let assetLockQuery = + await assetManager.isAssetLockedInHTLCqueryUsingContractId( + amc, + contractId, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(true); + }); + }); + + describe("check fungible asset lock status in HTLC", () => { + let amcStub; + const contractId = "CONTRACT-1234"; + + beforeEach(() => { + amcStub = sinon.stub(amc, "evaluateTransaction").resolves(false); + }); + + it("asset lock status check fails with invalid parameters", async () => { + let assetLockQuery = await assetManager.isFungibleAssetLockedInHTLC( + null, + contractId, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + assetLockQuery = await assetManager.isFungibleAssetLockedInHTLC(amc, ""); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(false); + }); + + it("submit asset lock status query", async () => { + amcStub.withArgs("IsFungibleAssetLocked", contractId).resolves(true); + let assetLockQuery = await assetManager.isFungibleAssetLockedInHTLC( + amc, + contractId, + ); + expect(assetLockQuery).to.be.a("boolean"); + expect(assetLockQuery).to.equal(true); + }); + }); }); diff --git a/weaver/sdks/fabric/interoperation-node-sdk/test/InteroperableHelper.js b/weaver/sdks/fabric/interoperation-node-sdk/test/InteroperableHelper.js index 2b2f3a808b..af892c0ad5 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/test/InteroperableHelper.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/test/InteroperableHelper.js @@ -22,532 +22,678 @@ const { NetworkImpl } = require("fabric-network/lib/network"); const { Transaction } = require("fabric-network/lib/transaction"); const ecies = require("../src/eciesCrypto"); const { - decryptRemoteProposalResponse, - decryptRemoteChaincodeOutput, - verifyDecryptedRemoteProposalResponse, - verifyRemoteProposalResponse, - getKeyAndCertForRemoteRequestbyUserName, - getPolicyCriteriaForAddress, - getSignatoryNodeFromCertificate, - invokeHandler, - interopFlow + decryptRemoteProposalResponse, + decryptRemoteChaincodeOutput, + verifyDecryptedRemoteProposalResponse, + verifyRemoteProposalResponse, + getKeyAndCertForRemoteRequestbyUserName, + getPolicyCriteriaForAddress, + getSignatoryNodeFromCertificate, + invokeHandler, + interopFlow, } = require("../src/InteroperableHelper"); -const { deserializeRemoteProposalResponseBase64, serializeRemoteProposalResponse } = require("../src/decoders"); +const { + deserializeRemoteProposalResponseBase64, + serializeRemoteProposalResponse, +} = require("../src/decoders"); import { Relay } from "../src/Relay"; import statePb from "@hyperledger/cacti-weaver-protos-js/common/state_pb"; describe("InteroperableHelper", () => { - const mspId = "mspId"; - const foreignNetworkId = "foreignNetworkId"; - const userName = "user_name"; - const localRelayEndpoint = "localhost:9081"; - const viewAddresses = ["localhost:9080/network1/mychannel:simplestate:Read:Arcturus", - "localhost:9080/network1/mychannel:simplestate:Read:Betelguese:1"]; - const wrongViewAddress = "localhost:9080/network1/mychannel:simplestate:ReadWrong:Arcturus"; - - let wallet; - let interopcc; - let interopccStub; - let writeExternalStateTransaction; - // Initialize wallet with a single user identity - async function initializeWallet() { - const privKeyFile = `${__dirname}/data/privKey.pem`; - const signCertFile = `${__dirname}/data/signCert.pem`; - const privateKeyStr = fs.readFileSync(privKeyFile).toString(); - const signCert = fs.readFileSync(signCertFile).toString(); - wallet = await Wallets.newInMemoryWallet(); - const userIdentity = { - credentials: { certificate: signCert, privateKey: privateKeyStr }, - mspId, - type: "X.509", - }; - await wallet.put(userName, userIdentity); - return userIdentity; - } - beforeEach(async () => { - await initializeWallet(); - const network = sinon.createStubInstance(NetworkImpl); - interopcc = new ContractImpl(network, "interopcc", "InteroperableHelper"); - writeExternalStateTransaction = sinon.createStubInstance(Transaction) - interopccStub = sinon.stub(interopcc, "createTransaction").withArgs('WriteExternalState').returns(writeExternalStateTransaction); + const mspId = "mspId"; + const foreignNetworkId = "foreignNetworkId"; + const userName = "user_name"; + const localRelayEndpoint = "localhost:9081"; + const viewAddresses = [ + "localhost:9080/network1/mychannel:simplestate:Read:Arcturus", + "localhost:9080/network1/mychannel:simplestate:Read:Betelguese:1", + ]; + const wrongViewAddress = + "localhost:9080/network1/mychannel:simplestate:ReadWrong:Arcturus"; + + let wallet; + let interopcc; + let interopccStub; + let writeExternalStateTransaction; + // Initialize wallet with a single user identity + async function initializeWallet() { + const privKeyFile = `${__dirname}/data/privKey.pem`; + const signCertFile = `${__dirname}/data/signCert.pem`; + const privateKeyStr = fs.readFileSync(privKeyFile).toString(); + const signCert = fs.readFileSync(signCertFile).toString(); + wallet = await Wallets.newInMemoryWallet(); + const userIdentity = { + credentials: { certificate: signCert, privateKey: privateKeyStr }, + mspId, + type: "X.509", + }; + await wallet.put(userName, userIdentity); + return userIdentity; + } + beforeEach(async () => { + await initializeWallet(); + const network = sinon.createStubInstance(NetworkImpl); + interopcc = new ContractImpl(network, "interopcc", "InteroperableHelper"); + writeExternalStateTransaction = sinon.createStubInstance(Transaction); + interopccStub = sinon + .stub(interopcc, "createTransaction") + .withArgs("WriteExternalState") + .returns(writeExternalStateTransaction); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("deserialize/serialize proposal structures", () => { + const samplePropJSON = JSON.parse( + fs.readFileSync(`${__dirname}/data/prop.json`).toString(), + ); + let deserializedPR; + + it("base64-encoded byte array deserialized into proposal response", () => { + expect(() => { + const dpropResp = deserializeRemoteProposalResponseBase64( + samplePropJSON.resp, + ); + expect(dpropResp) + .to.be.an("object") + .to.include.all.keys("version", "response", "payload", "endorsement"); + expect(dpropResp.response) + .to.be.an("object") + .to.include.all.keys("status", "payload"); + expect(dpropResp.endorsement) + .to.be.an("object") + .that.has.all.keys("endorser", "signature"); + expect(dpropResp.response.status).to.equal(samplePropJSON.status); + expect(dpropResp.response.payload).to.be.a("Uint8Array"); + expect(dpropResp.response.payload.toString("utf8")).to.equal( + samplePropJSON.ccmessage, + ); + expect(dpropResp.endorsement.endorser).to.be.a("Uint8Array"); + expect(dpropResp.endorsement.signature).to.be.a("Uint8Array"); + deserializedPR = dpropResp; + }).to.not.throw(); + }); + + it("proposal response protobuf serialized into byte string", () => { + expect(() => { + const propResp = serializeRemoteProposalResponse(deserializedPR); + expect(propResp).to.be.a("Uint8Array"); + expect(propResp.toString("base64")).to.equal(samplePropJSON.resp); + }).to.not.throw(); + }); + }); + + describe("cryptographic functions", () => { + it("encrypt and decrypt a message with default 128-bit AES key", () => { + const data = '{ "data": "xyz" }'; + const privKeyFile = `${__dirname}/data/privKey.pem`; + const privKeyPEM = fs.readFileSync(privKeyFile).toString(); + const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(privKeyPEM); + const signCertFile = `${__dirname}/data/signCert.pem`; + const signCertPEM = fs.readFileSync(signCertFile).toString(); + const pubKey = keyutil.getKey(signCertPEM); + const cryptoOptions = { hashAlgorithm: "SHA2" }; + expect(() => { + const encryptedData = ecies.eciesEncryptMessage( + pubKey, + Buffer.from(data), + cryptoOptions, + ); + expect(encryptedData).to.be.a("Uint8Array"); + expect(() => { + const decryptedData = ecies.eciesDecryptMessage( + privKey, + encryptedData, + cryptoOptions, + ); + expect(decryptedData).to.be.a("Uint8Array"); + expect(decryptedData.toString()).to.equal(data); + }).to.not.throw(); + }).to.not.throw(); + }); + }); + + describe("cryptographic functions", () => { + it("encrypt and decrypt a message with 256-bit AES key", () => { + const data = '{ "data": "xyz" }'; + const privKeyFile = `${__dirname}/data/privKey.pem`; + const privKeyPEM = fs.readFileSync(privKeyFile).toString(); + const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(privKeyPEM); + const signCertFile = `${__dirname}/data/signCert.pem`; + const signCertPEM = fs.readFileSync(signCertFile).toString(); + const pubKey = keyutil.getKey(signCertPEM); + const cryptoOptions = { hashAlgorithm: "SHA2" }; + expect(() => { + const encryptedData = ecies.eciesEncryptMessage( + pubKey, + Buffer.from(data), + cryptoOptions, + 32, + ); // 32 * 8 == 256 + expect(encryptedData).to.be.a("Uint8Array"); + expect(() => { + const decryptedData = ecies.eciesDecryptMessage( + privKey, + encryptedData, + cryptoOptions, + 32, + ); // 32 * 8 == 256 + expect(decryptedData).to.be.a("Uint8Array"); + expect(decryptedData.toString()).to.equal(data); + }).to.not.throw(); + }).to.not.throw(); + }); + }); + + describe("decrypt remote proposal response", () => { + it("decrypt proposal response using private key", () => { + const samplePropJSON = JSON.parse( + fs.readFileSync(`${__dirname}/data/prop.json`).toString(), + ); + const privKeyFile = `${__dirname}/data/privKey.pem`; + const privKeyPEM = fs.readFileSync(privKeyFile).toString(); + expect(() => { + const decResp = decryptRemoteProposalResponse( + samplePropJSON.eresp, + privKeyPEM, + ); + expect(decResp) + .to.be.an("object") + .to.include.all.keys("version", "response", "payload", "endorsement"); + expect(decResp.response) + .to.be.an("object") + .to.include.all.keys("status", "payload"); + expect(decResp.endorsement) + .to.be.an("object") + .that.has.all.keys("endorser", "signature"); + expect(decResp.response.status).to.equal(samplePropJSON.status); + expect(decResp.response.payload).to.be.a("Uint8Array"); + expect(decResp.response.payload.toString("utf8")).to.equal( + samplePropJSON.ccmessage, + ); + expect(decResp.payload).to.be.a("Uint8Array"); + expect(decResp.endorsement.endorser).to.be.a("Uint8Array"); + expect(decResp.endorsement.signature).to.be.a("Uint8Array"); + }).to.not.throw(); + }); + }); + + describe("decrypt remote chaincode output", () => { + it("decrypt chaincode output using private key", () => { + const samplePropJSON = JSON.parse( + fs.readFileSync(`${__dirname}/data/prop.json`).toString(), + ); + const privKeyFile = `${__dirname}/data/privKey.pem`; + const privKeyPEM = fs.readFileSync(privKeyFile).toString(); + expect(() => { + const decResp = decryptRemoteChaincodeOutput( + samplePropJSON.eccresp, + privKeyPEM, + ); + expect(decResp) + .to.be.an("object") + .to.include.all.keys("version", "response", "payload", "endorsement"); + expect(decResp.response) + .to.be.an("object") + .to.include.all.keys("status", "payload"); + expect(decResp.response.payload).to.be.a("Uint8Array"); + expect(decResp.response.payload.toString("utf8")).to.equal( + samplePropJSON.ccmessage, + ); + }).to.not.throw(); + }); + }); + + describe("verify remote proposal response", () => { + beforeEach(() => { + const ccResult = fs.readFileSync( + `${__dirname}/data/exporter_org_msp_config.json`, + ); + sinon.stub(interopcc, "evaluateTransaction").resolves(ccResult); }); - afterEach(() => { - sinon.restore(); + const samplePropJSON = JSON.parse( + fs.readFileSync(`${__dirname}/data/prop.json`).toString(), + ); + const privKeyFile = `${__dirname}/data/privKey.pem`; + const privKeyPEM = fs.readFileSync(privKeyFile).toString(); + + it("validate plaintext proposal response and endorsement", async () => { + const dpropResp = deserializeRemoteProposalResponseBase64( + samplePropJSON.resp, + ); + const verificationStatus = await verifyDecryptedRemoteProposalResponse( + dpropResp, + foreignNetworkId, + ); + expect(verificationStatus).to.be.a("boolean"); + expect(verificationStatus).to.be.true; }); - describe("deserialize/serialize proposal structures", () => { - const samplePropJSON = JSON.parse(fs.readFileSync(`${__dirname}/data/prop.json`).toString()); - let deserializedPR; - - it("base64-encoded byte array deserialized into proposal response", () => { - expect(() => { - const dpropResp = deserializeRemoteProposalResponseBase64(samplePropJSON.resp); - expect(dpropResp) - .to.be.an("object") - .to.include.all.keys("version", "response", "payload", "endorsement"); - expect(dpropResp.response).to.be.an("object").to.include.all.keys("status", "payload"); - expect(dpropResp.endorsement).to.be.an("object").that.has.all.keys("endorser", "signature"); - expect(dpropResp.response.status).to.equal(samplePropJSON.status); - expect(dpropResp.response.payload).to.be.a("Uint8Array"); - expect(dpropResp.response.payload.toString("utf8")).to.equal(samplePropJSON.ccmessage); - expect(dpropResp.endorsement.endorser).to.be.a("Uint8Array"); - expect(dpropResp.endorsement.signature).to.be.a("Uint8Array"); - deserializedPR = dpropResp; - }).to.not.throw(); - }); - - it("proposal response protobuf serialized into byte string", () => { - expect(() => { - const propResp = serializeRemoteProposalResponse(deserializedPR); - expect(propResp).to.be.a("Uint8Array"); - expect(propResp.toString("base64")).to.equal(samplePropJSON.resp); - }).to.not.throw(); - }); + it("validate plaintext proposal response and endorsement with wrapper", async () => { + const verificationStatus = await verifyRemoteProposalResponse( + samplePropJSON.resp, + false, + null, + foreignNetworkId, + ); + expect(verificationStatus) + .to.be.an("object") + .that.has.all.keys("proposalResponse", "valid"); + expect(verificationStatus.proposalResponse).to.be.a("string"); + expect(verificationStatus.valid).to.be.a("boolean"); + expect(verificationStatus.valid).to.be.true; }); - describe("cryptographic functions", () => { - it("encrypt and decrypt a message with default 128-bit AES key", () => { - const data = '{ "data": "xyz" }'; - const privKeyFile = `${__dirname}/data/privKey.pem`; - const privKeyPEM = fs.readFileSync(privKeyFile).toString(); - const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(privKeyPEM); - const signCertFile = `${__dirname}/data/signCert.pem`; - const signCertPEM = fs.readFileSync(signCertFile).toString(); - const pubKey = keyutil.getKey(signCertPEM); - const cryptoOptions = { hashAlgorithm: "SHA2" }; - expect(() => { - const encryptedData = ecies.eciesEncryptMessage(pubKey, Buffer.from(data), cryptoOptions); - expect(encryptedData).to.be.a("Uint8Array"); - expect(() => { - const decryptedData = ecies.eciesDecryptMessage(privKey, encryptedData, cryptoOptions); - expect(decryptedData).to.be.a("Uint8Array"); - expect(decryptedData.toString()).to.equal(data); - }).to.not.throw(); - }).to.not.throw(); - }); + it("validate decrypted proposal response and endorsement", async () => { + const decResp = decryptRemoteProposalResponse( + samplePropJSON.eresp, + privKeyPEM, + ); + const verificationStatus = await verifyDecryptedRemoteProposalResponse( + decResp, + foreignNetworkId, + ); + expect(verificationStatus).to.be.a("boolean"); + expect(verificationStatus).to.be.true; }); - describe("cryptographic functions", () => { - it("encrypt and decrypt a message with 256-bit AES key", () => { - const data = '{ "data": "xyz" }'; - const privKeyFile = `${__dirname}/data/privKey.pem`; - const privKeyPEM = fs.readFileSync(privKeyFile).toString(); - const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(privKeyPEM); - const signCertFile = `${__dirname}/data/signCert.pem`; - const signCertPEM = fs.readFileSync(signCertFile).toString(); - const pubKey = keyutil.getKey(signCertPEM); - const cryptoOptions = { hashAlgorithm: "SHA2" }; - expect(() => { - const encryptedData = ecies.eciesEncryptMessage(pubKey, Buffer.from(data), cryptoOptions, 32); // 32 * 8 == 256 - expect(encryptedData).to.be.a("Uint8Array"); - expect(() => { - const decryptedData = ecies.eciesDecryptMessage(privKey, encryptedData, cryptoOptions, 32); // 32 * 8 == 256 - expect(decryptedData).to.be.a("Uint8Array"); - expect(decryptedData.toString()).to.equal(data); - }).to.not.throw(); - }).to.not.throw(); - }); + it("validate encrypted proposal response and endorsement with wrapper", async () => { + const verificationStatus = await verifyRemoteProposalResponse( + samplePropJSON.eresp, + true, + privKeyPEM, + foreignNetworkId, + ); + expect(verificationStatus) + .to.be.an("object") + .that.has.all.keys("proposalResponse", "valid"); + expect(verificationStatus.proposalResponse).to.be.a("string"); + expect(verificationStatus.valid).to.be.a("boolean"); + expect(verificationStatus.valid).to.be.true; }); + }); + + describe("get client credentials for remote transaction", () => { + const privKeyFile = `${__dirname}/data/privKey.pem`; + const signCertFile = `${__dirname}/data/signCert.pem`; + const privateKeyStr = fs.readFileSync(privKeyFile).toString(); + const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(privateKeyStr); + const signCert = fs.readFileSync(signCertFile).toString(); - describe("decrypt remote proposal response", () => { - it("decrypt proposal response using private key", () => { - const samplePropJSON = JSON.parse(fs.readFileSync(`${__dirname}/data/prop.json`).toString()); - const privKeyFile = `${__dirname}/data/privKey.pem`; - const privKeyPEM = fs.readFileSync(privKeyFile).toString(); - expect(() => { - const decResp = decryptRemoteProposalResponse(samplePropJSON.eresp, privKeyPEM); - expect(decResp).to.be.an("object").to.include.all.keys("version", "response", "payload", "endorsement"); - expect(decResp.response).to.be.an("object").to.include.all.keys("status", "payload"); - expect(decResp.endorsement).to.be.an("object").that.has.all.keys("endorser", "signature"); - expect(decResp.response.status).to.equal(samplePropJSON.status); - expect(decResp.response.payload).to.be.a("Uint8Array"); - expect(decResp.response.payload.toString("utf8")).to.equal(samplePropJSON.ccmessage); - expect(decResp.payload).to.be.a("Uint8Array"); - expect(decResp.endorsement.endorser).to.be.a("Uint8Array"); - expect(decResp.endorsement.signature).to.be.a("Uint8Array"); - }).to.not.throw(); - }); + it("obtain key and certificate from wallet identity", async () => { + const keyCert = await getKeyAndCertForRemoteRequestbyUserName( + wallet, + userName, + ); + const keyHex = keyutil.getKeyFromPlainPrivatePKCS8PEM( + keyCert.key.toBytes(), + ).prvKeyHex; + expect(keyHex).to.equal(privKey.prvKeyHex); + expect(keyCert.cert).to.equal(signCert); }); + }); - describe("decrypt remote chaincode output", () => { - it("decrypt chaincode output using private key", () => { - const samplePropJSON = JSON.parse(fs.readFileSync(`${__dirname}/data/prop.json`).toString()); - const privKeyFile = `${__dirname}/data/privKey.pem`; - const privKeyPEM = fs.readFileSync(privKeyFile).toString(); - expect(() => { - const decResp = decryptRemoteChaincodeOutput(samplePropJSON.eccresp, privKeyPEM); - expect(decResp).to.be.an("object").to.include.all.keys("version", "response", "payload", "endorsement"); - expect(decResp.response).to.be.an("object").to.include.all.keys("status", "payload"); - expect(decResp.response.payload).to.be.a("Uint8Array"); - expect(decResp.response.payload.toString("utf8")).to.equal(samplePropJSON.ccmessage); - }).to.not.throw(); - }); + describe("verify get policy criteria lookup", () => { + beforeEach(() => { + const vpJSON = { + securityDomain: "network1", + identifiers: [ + { + pattern: "mychannel:simplestate:Read:*", + policy: { type: "Signature", criteria: ["Org1MSP"] }, + }, + { + pattern: "notmatching", + policy: { type: "Signature", criteria: ["NotMatching"] }, + }, + ], + viewPatterns: [], + }; + const vpResult = JSON.stringify(vpJSON); + const interopccStub = sinon + .stub(interopcc, "evaluateTransaction") + .resolves(vpResult); + interopccStub + .withArgs("GetVerificationPolicyBySecurityDomain", "network1") + .resolves(vpResult); + interopccStub + .withArgs("GetVerificationPolicyBySecurityDomain", "network2") + .resolves(""); }); - describe("verify remote proposal response", () => { - beforeEach(() => { - const ccResult = fs.readFileSync(`${__dirname}/data/exporter_org_msp_config.json`); - sinon.stub(interopcc, "evaluateTransaction").resolves(ccResult); - }); - - const samplePropJSON = JSON.parse(fs.readFileSync(`${__dirname}/data/prop.json`).toString()); - const privKeyFile = `${__dirname}/data/privKey.pem`; - const privKeyPEM = fs.readFileSync(privKeyFile).toString(); - - it("validate plaintext proposal response and endorsement", async () => { - const dpropResp = deserializeRemoteProposalResponseBase64(samplePropJSON.resp); - const verificationStatus = await verifyDecryptedRemoteProposalResponse(dpropResp, foreignNetworkId); - expect(verificationStatus).to.be.a("boolean"); - expect(verificationStatus).to.be.true; - }); - - it("validate plaintext proposal response and endorsement with wrapper", async () => { - const verificationStatus = await verifyRemoteProposalResponse( - samplePropJSON.resp, - false, - null, - foreignNetworkId, - ); - expect(verificationStatus).to.be.an("object").that.has.all.keys("proposalResponse", "valid"); - expect(verificationStatus.proposalResponse).to.be.a("string"); - expect(verificationStatus.valid).to.be.a("boolean"); - expect(verificationStatus.valid).to.be.true; - }); - - it("validate decrypted proposal response and endorsement", async () => { - const decResp = decryptRemoteProposalResponse(samplePropJSON.eresp, privKeyPEM); - const verificationStatus = await verifyDecryptedRemoteProposalResponse(decResp, foreignNetworkId); - expect(verificationStatus).to.be.a("boolean"); - expect(verificationStatus).to.be.true; - }); - - it("validate encrypted proposal response and endorsement with wrapper", async () => { - const verificationStatus = await verifyRemoteProposalResponse( - samplePropJSON.eresp, - true, - privKeyPEM, - foreignNetworkId, - ); - expect(verificationStatus).to.be.an("object").that.has.all.keys("proposalResponse", "valid"); - expect(verificationStatus.proposalResponse).to.be.a("string"); - expect(verificationStatus.valid).to.be.a("boolean"); - expect(verificationStatus.valid).to.be.true; - }); + it("validate policy syntax and attributes", async () => { + const policyJSON = await getPolicyCriteriaForAddress( + interopcc, + viewAddresses[0], + ); + expect(policyJSON).to.be.an("array"); + expect(policyJSON.length).to.equal(1); + expect(policyJSON[0]).to.be.equal("Org1MSP"); }); + it("fail to match verificationPolicy", async () => { + // no match found + let policyJSON = await getPolicyCriteriaForAddress( + interopcc, + wrongViewAddress, + ); + expect(policyJSON).to.equal(null); - describe("get client credentials for remote transaction", () => { - const privKeyFile = `${__dirname}/data/privKey.pem`; - const signCertFile = `${__dirname}/data/signCert.pem`; - const privateKeyStr = fs.readFileSync(privKeyFile).toString(); - const privKey = keyutil.getKeyFromPlainPrivatePKCS8PEM(privateKeyStr); - const signCert = fs.readFileSync(signCertFile).toString(); - - it("obtain key and certificate from wallet identity", async () => { - const keyCert = await getKeyAndCertForRemoteRequestbyUserName(wallet, userName); - const keyHex = keyutil.getKeyFromPlainPrivatePKCS8PEM(keyCert.key.toBytes()).prvKeyHex; - expect(keyHex).to.equal(privKey.prvKeyHex); - expect(keyCert.cert).to.equal(signCert); - }); + // no policy found + try { + policyJSON = await getPolicyCriteriaForAddress( + interopcc, + wrongViewAddress, + ); + } catch (error) { + expect(error.toString()).to.equal( + "Error: Error during getPolicyCriteriaForAddress: Error: No verification policy for address " + + wrongViewAddress, + ); + } }); + }); + + describe("extract node id from certificate", () => { + const sampleCordaNodeId = "BuyerBankNode"; + const sampleCertBase64 = + "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUI0VENDQVgyZ0F3SUJBZ0lJSmJTMHJaRFRkNkF3RkFZSUtvWkl6ajBFQXdJR0NDcUdTTTQ5QXdFSE1EWXhDekFKQmdOVkJBWVRBa2RDTVE4d0RRWURWUVFIREFaTWIyNWtiMjR4RmpBVUJnTlZCQW9NRFVKMWVXVnlRbUZ1YTA1dlpHVXdIaGNOTWpBd01qSTRNREF3TURBd1doY05NamN3TlRJd01EQXdNREF3V2pBMk1Rc3dDUVlEVlFRR0V3SkhRakVQTUEwR0ExVUVCd3dHVEc5dVpHOXVNUll3RkFZRFZRUUtEQTFDZFhsbGNrSmhibXRPYjJSbE1Db3dCUVlESzJWd0F5RUFzZnRabnpSZ3Q4UEIzQlc4Z3FRa05mRHMyUGJLaC9ULytiOVNQM2VadHZpamdaa3dnWll3SFFZRFZSME9CQllFRlAyTWs1NjdyQ0VSYWpXcEZYVFNMVTJEVlhGNE1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0N3WURWUjBQQkFRREFnS0VNQ01HQTFVZEpRUWNNQm9HQ0NzR0FRVUZCd01CQmdnckJnRUZCUWNEQWdZRVZSMGxBREFmQmdOVkhTTUVHREFXZ0JTcDRiZFpteFhlblptakJ2enJnMDV0b040MHZEQVJCZ29yQmdFRUFZT0tZZ0VCQkFNQ0FRWXdGQVlJS29aSXpqMEVBd0lHQ0NxR1NNNDlBd0VIQTBnQU1FVUNJRjhIbDhSZ1U5T2VLT2NFaVRyYkZSQ0hUVUppN3MyL2wralIwYmFMUnVGN0FpRUF6SGp1Y1loMGNOWHBiUnE2OG0xcDlMaFJRbTBTSkt4ZUFQV2xtRVphKzZNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t"; - describe("verify get policy criteria lookup", () => { - beforeEach(() => { - const vpJSON = { - securityDomain: "network1", - identifiers: [ - { pattern: "mychannel:simplestate:Read:*", policy: { type: "Signature", criteria: ["Org1MSP"] } }, - { pattern: "notmatching", policy: { type: "Signature", criteria: ["NotMatching"] } }, - ], - viewPatterns: [], - }; - const vpResult = JSON.stringify(vpJSON); - const interopccStub = sinon.stub(interopcc, "evaluateTransaction").resolves(vpResult); - interopccStub.withArgs("GetVerificationPolicyBySecurityDomain", "network1").resolves(vpResult); - interopccStub.withArgs("GetVerificationPolicyBySecurityDomain", "network2").resolves(""); - }); - - it("validate policy syntax and attributes", async () => { - const policyJSON = await getPolicyCriteriaForAddress( - interopcc, - viewAddresses[0], - ); - expect(policyJSON).to.be.an("array"); - expect(policyJSON.length).to.equal(1); - expect(policyJSON[0]).to.be.equal("Org1MSP"); - }); - it("fail to match verificationPolicy", async () => { - // no match found - let policyJSON = await getPolicyCriteriaForAddress( - interopcc, - wrongViewAddress, - ); - expect(policyJSON).to.equal(null); - - // no policy found - try { - policyJSON = await getPolicyCriteriaForAddress( - interopcc, - wrongViewAddress, - ); - } catch(error) { - expect(error.toString()).to.equal('Error: Error during getPolicyCriteriaForAddress: Error: No verification policy for address ' + wrongViewAddress); - } - }); + it("validate remote node name associated with certificate", async () => { + const nodeId = await getSignatoryNodeFromCertificate(sampleCertBase64); + expect(nodeId).to.be.a("string"); + expect(nodeId).to.equal(sampleCordaNodeId); + }); + }); + describe("test invoke handler", () => { + beforeEach(() => { + const vpJSON = { + securityDomain: "network1", + identifiers: [ + { + pattern: "mychannel:simplestate:Read", + policy: { type: "Signature", criteria: ["Org1MSP"] }, + }, + { + pattern: "notmatching", + policy: { type: "Signature", criteria: ["NotMatching"] }, + }, + ], + viewPatterns: [], + }; + const interopccStub = sinon + .stub(interopcc, "submitTransaction") + .resolves(false); + interopccStub.withArgs("Write", "w", "value").resolves(true); + interopccStub + .withArgs( + "WriteExternalState", + "interop", + "mychannel", + "Write", + JSON.stringify(["w"], viewAddresses[0]), + ) + .resolves(true); + const vpResult = JSON.stringify(vpJSON); + const interopccStub2 = sinon + .stub(interopcc, "evaluateTransaction") + .resolves(vpResult); + interopccStub2 + .withArgs("GetVerificationPolicyBySecurityDomain", "network1") + .resolves(vpResult); + }); + it("works as a normal invoke", async () => { + const invokeObject = { + ccArgs: ["w", "value"], + channel: "MyChannel", + ccFunc: "Write", + contractName: "simplestate", + }; + const remoteJSON = {}; + const keyCert = await getKeyAndCertForRemoteRequestbyUserName( + wallet, + userName, + ); + const invokeHandlerResponse = await invokeHandler( + interopcc, + "networkID", + "org", + invokeObject, + remoteJSON, + keyCert, + ); + expect(invokeHandlerResponse).to.be.a("boolean"); + expect(invokeHandlerResponse).to.equal(true); }); + }); + + describe("test interopFlow", () => { + const appId = "simplestate"; + const channel = "mychannel"; + const appFn = "Write"; + const appArgs = ["w", "value", "", ""]; + const argsIndices = [2, 3]; + + const meta = new statePb.Meta(); + meta.setProtocol(statePb.Meta.Protocol.FABRIC); + meta.setTimestamp(new Date().toISOString()); + meta.setProofType("Notarization"); + meta.setSerializationFormat("STRING"); + + const view1 = new statePb.View(); + view1.setMeta(meta); + view1.setData(Buffer.from("1")); + const relayResponse1 = new statePb.RequestState(); + relayResponse1.setRequestId("ABC-123"); + relayResponse1.setStatus(statePb.RequestState.COMPLETED); + relayResponse1.setView(view1); + + const view2 = new statePb.View(); + view2.setMeta(meta); + view2.setData(Buffer.from("2")); + const relayResponse2 = new statePb.RequestState(); + relayResponse2.setRequestId("ABC-124"); + relayResponse2.setStatus(statePb.RequestState.COMPLETED); + relayResponse2.setView(view2); - describe("extract node id from certificate", () => { - const sampleCordaNodeId = "BuyerBankNode"; - const sampleCertBase64 = - "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUI0VENDQVgyZ0F3SUJBZ0lJSmJTMHJaRFRkNkF3RkFZSUtvWkl6ajBFQXdJR0NDcUdTTTQ5QXdFSE1EWXhDekFKQmdOVkJBWVRBa2RDTVE4d0RRWURWUVFIREFaTWIyNWtiMjR4RmpBVUJnTlZCQW9NRFVKMWVXVnlRbUZ1YTA1dlpHVXdIaGNOTWpBd01qSTRNREF3TURBd1doY05NamN3TlRJd01EQXdNREF3V2pBMk1Rc3dDUVlEVlFRR0V3SkhRakVQTUEwR0ExVUVCd3dHVEc5dVpHOXVNUll3RkFZRFZRUUtEQTFDZFhsbGNrSmhibXRPYjJSbE1Db3dCUVlESzJWd0F5RUFzZnRabnpSZ3Q4UEIzQlc4Z3FRa05mRHMyUGJLaC9ULytiOVNQM2VadHZpamdaa3dnWll3SFFZRFZSME9CQllFRlAyTWs1NjdyQ0VSYWpXcEZYVFNMVTJEVlhGNE1BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0N3WURWUjBQQkFRREFnS0VNQ01HQTFVZEpRUWNNQm9HQ0NzR0FRVUZCd01CQmdnckJnRUZCUWNEQWdZRVZSMGxBREFmQmdOVkhTTUVHREFXZ0JTcDRiZFpteFhlblptakJ2enJnMDV0b040MHZEQVJCZ29yQmdFRUFZT0tZZ0VCQkFNQ0FRWXdGQVlJS29aSXpqMEVBd0lHQ0NxR1NNNDlBd0VIQTBnQU1FVUNJRjhIbDhSZ1U5T2VLT2NFaVRyYkZSQ0hUVUppN3MyL2wralIwYmFMUnVGN0FpRUF6SGp1Y1loMGNOWHBiUnE2OG0xcDlMaFJRbTBTSkt4ZUFQV2xtRVphKzZNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t"; + const views64 = [ + Buffer.from(view1.serializeBinary()).toString("base64"), + Buffer.from(view2.serializeBinary()).toString("base64"), + ]; - it("validate remote node name associated with certificate", async () => { - const nodeId = await getSignatoryNodeFromCertificate(sampleCertBase64); - expect(nodeId).to.be.a("string"); - expect(nodeId).to.equal(sampleCordaNodeId); - }); + beforeEach(() => { + const vpJSON = { + securityDomain: "network1", + identifiers: [ + { + pattern: "mychannel:simplestate:Read:*", + policy: { type: "Signature", criteria: ["Org1MSP"] }, + }, + ], + viewPatterns: [], + }; + writeExternalStateTransaction.submit.resolves(false); + writeExternalStateTransaction.submit + .withArgs( + appId, + channel, + appFn, + JSON.stringify(appArgs), + JSON.stringify(argsIndices), + JSON.stringify(viewAddresses), + JSON.stringify(views64), + JSON.stringify([[], []]), + ) + .resolves(true); + + const vpResult = JSON.stringify(vpJSON); + const interopccStub2 = sinon + .stub(interopcc, "evaluateTransaction") + .rejects("interopcc error"); + interopccStub2 + .withArgs("GetVerificationPolicyBySecurityDomain", "network1") + .resolves(vpResult); + interopccStub2 + .withArgs("VerifyView", views64[0], viewAddresses[0]) + .resolves(true); + interopccStub2 + .withArgs("VerifyView", views64[1], viewAddresses[1]) + .resolves(true); + + //Relay Stub response + // const relayStub = sinon.stub(relaySDK, "ProcessRequest") + const relayStub = sinon.stub(Relay.prototype, "ProcessRequest"); + relayStub.onCall(1).resolves(relayResponse2); + relayStub.onCall(2).rejects(new Error("relay error")); + relayStub.resolves(relayResponse1); + }); + + it("successful data sharing query", async () => { + const invokeObject = { + channel: channel, + ccFunc: appFn, + ccArgs: appArgs, + contractName: appId, + }; + const remoteJSON1 = { + address: viewAddresses[0], + Sign: true, + }; + const remoteJSON2 = { + ChaincodeFunc: "Read", + ChaincodeID: "simplestate", + ChannelID: "mychannel", + RemoteEndpoint: "localhost:9080", + NetworkID: "network1", + Sign: true, + ccArgs: ["Betelguese", "1"], + }; + const keyCert = await getKeyAndCertForRemoteRequestbyUserName( + wallet, + userName, + ); + const interopResponse = await interopFlow( + interopcc, + "network-id", + invokeObject, + "org", + localRelayEndpoint, + argsIndices, + [remoteJSON1, remoteJSON2], + keyCert, + ); + expect(interopResponse) + .to.be.an("object") + .that.has.all.keys("views", "result"); + expect(interopResponse.views).to.be.an("array"); + expect(interopResponse.views).to.have.lengthOf(viewAddresses.length); + expect(interopResponse.views[0]).to.equal(view1); + expect(interopResponse.views[1]).to.equal(view2); + expect(interopResponse.result).to.be.a("boolean"); + expect(interopResponse.result).to.equal(true); }); - describe("test invoke handler", () => { - beforeEach(() => { - const vpJSON = { - securityDomain: "network1", - identifiers: [ - { pattern: "mychannel:simplestate:Read", policy: { type: "Signature", criteria: ["Org1MSP"] } }, - { pattern: "notmatching", policy: { type: "Signature", criteria: ["NotMatching"] } }, - ], - viewPatterns: [], - }; - const interopccStub = sinon.stub(interopcc, "submitTransaction").resolves(false); - interopccStub.withArgs("Write", "w", "value").resolves(true); - interopccStub - .withArgs( - "WriteExternalState", - "interop", - "mychannel", - "Write", - JSON.stringify(["w"], viewAddresses[0]), - ) - .resolves(true); - const vpResult = JSON.stringify(vpJSON); - const interopccStub2 = sinon.stub(interopcc, "evaluateTransaction").resolves(vpResult); - interopccStub2.withArgs("GetVerificationPolicyBySecurityDomain", "network1").resolves(vpResult); - }); - it("works as a normal invoke", async () => { - const invokeObject = { - ccArgs: ["w", "value"], - channel: "MyChannel", - ccFunc: "Write", - contractName: "simplestate", - }; - const remoteJSON = {}; - const keyCert = await getKeyAndCertForRemoteRequestbyUserName(wallet, userName); - const invokeHandlerResponse = await invokeHandler( - interopcc, - "networkID", - "org", - invokeObject, - remoteJSON, - keyCert, - ); - expect(invokeHandlerResponse).to.be.a("boolean"); - expect(invokeHandlerResponse).to.equal(true); - }); + + it("fail data sharing query: relay error", async () => { + const invokeObject = { + channel: channel, + ccFunc: appFn, + ccArgs: appArgs, + contractName: appId, + }; + const remoteJSON = { + address: viewAddresses[0], + Sign: true, + }; + const keyCert = await getKeyAndCertForRemoteRequestbyUserName( + wallet, + userName, + ); + try { + const interopResponse = await interopFlow( + interopcc, + "network-id", + invokeObject, + "org", + localRelayEndpoint, + [0], + [remoteJSON], + keyCert, + ); + } catch (error) { + const expectedErrMsg = + "Error: InteropFlow remote view request error: Error: InteropFlow relay response error: Error: relay error"; + expect(error.toString()).to.equal(expectedErrMsg); + } + }); + + it("fail data sharing query: view verification error", async () => { + const invokeObject = { + channel: channel, + ccFunc: appFn, + ccArgs: appArgs, + contractName: appId, + }; + const remoteJSON = { + address: wrongViewAddress, + Sign: true, + }; + const keyCert = await getKeyAndCertForRemoteRequestbyUserName( + wallet, + userName, + ); + try { + const interopResponse = await interopFlow( + interopcc, + "network-id", + invokeObject, + "org", + localRelayEndpoint, + [0], + [remoteJSON], + keyCert, + ); + } catch (error) { + const expectedErrMsg = + "Error: InteropFlow remote view request error: Error: View verification failed Error: Unable to verify view: interopcc error"; + expect(error.toString()).to.equal(expectedErrMsg); + } }); - - describe("test interopFlow", () => { - const appId = "simplestate"; - const channel = "mychannel"; - const appFn = "Write"; - const appArgs = ["w", "value", "", ""]; - const argsIndices = [2, 3]; - - const meta = new statePb.Meta(); - meta.setProtocol(statePb.Meta.Protocol.FABRIC); - meta.setTimestamp(new Date().toISOString()); - meta.setProofType('Notarization'); - meta.setSerializationFormat('STRING'); - - const view1 = new statePb.View(); - view1.setMeta(meta); - view1.setData(Buffer.from('1')); - const relayResponse1 = new statePb.RequestState(); - relayResponse1.setRequestId("ABC-123"); - relayResponse1.setStatus(statePb.RequestState.COMPLETED); - relayResponse1.setView(view1); - - const view2 = new statePb.View(); - view2.setMeta(meta); - view2.setData(Buffer.from('2')); - const relayResponse2 = new statePb.RequestState(); - relayResponse2.setRequestId("ABC-124"); - relayResponse2.setStatus(statePb.RequestState.COMPLETED); - relayResponse2.setView(view2); - - const views64 = [Buffer.from(view1.serializeBinary()).toString("base64"), - Buffer.from(view2.serializeBinary()).toString("base64")] - - beforeEach(() => { - const vpJSON = { - securityDomain: "network1", - identifiers: [ - { pattern: "mychannel:simplestate:Read:*", policy: { type: "Signature", criteria: ["Org1MSP"] } } - ], - viewPatterns: [], - }; - writeExternalStateTransaction.submit.resolves(false); - writeExternalStateTransaction.submit - .withArgs( - appId, - channel, - appFn, - JSON.stringify(appArgs), - JSON.stringify(argsIndices), - JSON.stringify(viewAddresses), - JSON.stringify(views64), - JSON.stringify([[], []]) - ).resolves(true); - - const vpResult = JSON.stringify(vpJSON); - const interopccStub2 = sinon.stub(interopcc, "evaluateTransaction").rejects("interopcc error"); - interopccStub2.withArgs("GetVerificationPolicyBySecurityDomain", "network1").resolves(vpResult); - interopccStub2.withArgs("VerifyView", views64[0], viewAddresses[0]).resolves(true); - interopccStub2.withArgs("VerifyView", views64[1], viewAddresses[1]).resolves(true); - - //Relay Stub response - // const relayStub = sinon.stub(relaySDK, "ProcessRequest") - const relayStub = sinon.stub(Relay.prototype, "ProcessRequest") - relayStub.onCall(1).resolves(relayResponse2) - relayStub.onCall(2).rejects(new Error("relay error")) - relayStub.resolves(relayResponse1) - }); - - - it("successful data sharing query", async () => { - const invokeObject = { - channel: channel, - ccFunc: appFn, - ccArgs: appArgs, - contractName: appId - }; - const remoteJSON1 = { - address: viewAddresses[0], - Sign: true - } - const remoteJSON2 = { - ChaincodeFunc: "Read", - ChaincodeID: "simplestate", - ChannelID: "mychannel", - RemoteEndpoint: "localhost:9080", - NetworkID: "network1", - Sign: true, - ccArgs: ["Betelguese", "1"] - } - const keyCert = await getKeyAndCertForRemoteRequestbyUserName(wallet, userName); - const interopResponse = await interopFlow( - interopcc, - "network-id", - invokeObject, - "org", - localRelayEndpoint, - argsIndices, - [remoteJSON1, remoteJSON2], - keyCert - ); - expect(interopResponse).to.be.an('object').that.has.all.keys('views', 'result'); - expect(interopResponse.views).to.be.an('array'); - expect(interopResponse.views).to.have.lengthOf(viewAddresses.length); - expect(interopResponse.views[0]).to.equal(view1); - expect(interopResponse.views[1]).to.equal(view2); - expect(interopResponse.result).to.be.a('boolean'); - expect(interopResponse.result).to.equal(true); - }); - - it("fail data sharing query: relay error", async () => { - const invokeObject = { - channel: channel, - ccFunc: appFn, - ccArgs: appArgs, - contractName: appId - }; - const remoteJSON = { - address: viewAddresses[0], - Sign: true - } - const keyCert = await getKeyAndCertForRemoteRequestbyUserName(wallet, userName); - try { - const interopResponse = await interopFlow( - interopcc, - "network-id", - invokeObject, - "org", - localRelayEndpoint, - [0], - [remoteJSON], - keyCert - ); - } catch (error) { - const expectedErrMsg = 'Error: InteropFlow remote view request error: Error: InteropFlow relay response error: Error: relay error' - expect(error.toString()).to.equal(expectedErrMsg) - } - }); - - it("fail data sharing query: view verification error", async () => { - const invokeObject = { - channel: channel, - ccFunc: appFn, - ccArgs: appArgs, - contractName: appId - }; - const remoteJSON = { - address: wrongViewAddress, - Sign: true - } - const keyCert = await getKeyAndCertForRemoteRequestbyUserName(wallet, userName); - try { - const interopResponse = await interopFlow( - interopcc, - "network-id", - invokeObject, - "org", - localRelayEndpoint, - [0], - [remoteJSON], - keyCert - ); - } catch (error) { - const expectedErrMsg = 'Error: InteropFlow remote view request error: Error: View verification failed Error: Unable to verify view: interopcc error' - expect(error.toString()).to.equal(expectedErrMsg) - } - }); - - it("fail data sharing query: write external state error", async () => { - const invokeObject = { - channel: channel, - ccFunc: appFn, - ccArgs: appArgs, - contractName: appId - }; - const remoteJSON = { - address: viewAddresses[0], - Sign: true - } - const keyCert = await getKeyAndCertForRemoteRequestbyUserName(wallet, userName); - const interopResponse = await interopFlow( - interopcc, - "network-id", - invokeObject, - "org", - localRelayEndpoint, - [0], - [remoteJSON], - keyCert - ); - expect(interopResponse).to.be.an('object').that.has.all.keys('views', 'result'); - expect(interopResponse.views).to.be.an('array'); - expect(interopResponse.views).to.have.lengthOf(1); - expect(interopResponse.views[0]).to.equal(view1); - expect(interopResponse.result).to.be.a('boolean'); - expect(interopResponse.result).to.equal(false); - }); + + it("fail data sharing query: write external state error", async () => { + const invokeObject = { + channel: channel, + ccFunc: appFn, + ccArgs: appArgs, + contractName: appId, + }; + const remoteJSON = { + address: viewAddresses[0], + Sign: true, + }; + const keyCert = await getKeyAndCertForRemoteRequestbyUserName( + wallet, + userName, + ); + const interopResponse = await interopFlow( + interopcc, + "network-id", + invokeObject, + "org", + localRelayEndpoint, + [0], + [remoteJSON], + keyCert, + ); + expect(interopResponse) + .to.be.an("object") + .that.has.all.keys("views", "result"); + expect(interopResponse.views).to.be.an("array"); + expect(interopResponse.views).to.have.lengthOf(1); + expect(interopResponse.views[0]).to.equal(view1); + expect(interopResponse.result).to.be.a("boolean"); + expect(interopResponse.result).to.equal(false); }); + }); }); diff --git a/weaver/sdks/fabric/interoperation-node-sdk/test/Relay.js b/weaver/sdks/fabric/interoperation-node-sdk/test/Relay.js index d443ee6c64..f92c95497e 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/test/Relay.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/test/Relay.js @@ -24,307 +24,329 @@ import networksPb from "@hyperledger/cacti-weaver-protos-js/networks/networks_pb const { expect } = chai; chai.use(sinonChai); const { Relay } = RelayHelper; -var grpc = require('@grpc/grpc-js'); -var protoLoader = require('@grpc/proto-loader'); +var grpc = require("@grpc/grpc-js"); +var protoLoader = require("@grpc/proto-loader"); const expectThrowsAsync = async (method, args, errorMessage) => { - let error = null; - try { - await method(...args); - } catch (err) { - error = err; - } - expect(error).to.be.an("Error"); - if (errorMessage) { - expect(error.message).to.equal(errorMessage); - } + let error = null; + try { + await method(...args); + } catch (err) { + error = err; + } + expect(error).to.be.an("Error"); + if (errorMessage) { + expect(error.message).to.equal(errorMessage); + } }; // TODO: Add more testing for relay, need a mock gRPC endpoint describe("Relay", () => { - let revert; + let revert; + + const sandbox = sinon.createSandbox(); + let FakeLogger; + let FakeUtils; + + beforeEach(() => { + revert = []; + FakeLogger = { + debug: () => {}, + error: () => {}, + warn: () => {}, + }; + sandbox.stub(FakeLogger, "debug"); + sandbox.stub(FakeLogger, "error"); + sandbox.stub(FakeLogger, "warn"); - const sandbox = sinon.createSandbox(); - let FakeLogger; - let FakeUtils; + FakeUtils = { + getConfigSetting: () => {}, + checkIntegerConfig: () => {}, + pemToDER: () => {}, + }; + sandbox.stub(FakeUtils); + }); + + afterEach(() => { + if (revert.length) { + revert.forEach(Function.prototype.call, Function.prototype.call); + } + sandbox.restore(); + }); + + describe("#constructor", () => { + it("should not permit creation without an url", () => { + (() => { + new Relay(); + }).should.throw(/Invalid Arguments/); + }); + + it("should create a valid instance without any opts", () => { + (() => { + new Relay("http://someurl"); + }).should.not.throw(); + }); + }); + + describe("#getEndpoint", () => { + let relay; beforeEach(() => { - revert = []; - FakeLogger = { - debug: () => {}, - error: () => {}, - warn: () => {}, - }; - sandbox.stub(FakeLogger, "debug"); - sandbox.stub(FakeLogger, "error"); - sandbox.stub(FakeLogger, "warn"); - - FakeUtils = { - getConfigSetting: () => {}, - checkIntegerConfig: () => {}, - pemToDER: () => {}, - }; - sandbox.stub(FakeUtils); + relay = new Relay("http://someurl"); + }); + + it("should set the _endPoint property", () => { + const expectedUrl = "somenewurl"; + relay._endPoint = expectedUrl; + relay.getEndpoint().should.equal(expectedUrl); + }); + }); + + describe("#performRemoteRequest", () => { + let relay; + + it("catch invalid url while doing DNS lookup", async () => { + relay = new Relay("https://someurl:9080"); + await expectThrowsAsync(() => + relay.ProcessRequest( + "address", + "policy", + "requestingNetwork", + "cert", + "sig", + "nonce", + ), + ); }); + }); + + describe("#successful relay api calls", () => { + const localRelayEndpoint = "localhost:19080"; + const relay = new Relay(localRelayEndpoint); + // Sample Request Id + const requestId = "ABC-123"; + // Prepare Sample View + const meta = new statePb.Meta(); + meta.setProtocol(statePb.Meta.Protocol.FABRIC); + meta.setTimestamp(new Date().toISOString()); + meta.setProofType("Notarization"); + meta.setSerializationFormat("STRING"); + const view = new statePb.View(); + view.setMeta(meta); + view.setData(Buffer.from("1")); + + const ack = { + status: ackPb.Ack.STATUS.OK, + requestId: requestId, + message: "", + }; + + const relayResponse = { + requestId: "", + status: statePb.RequestState.STATUS.COMPLETED, + view: view.toObject(), + }; - afterEach(() => { - if (revert.length) { - revert.forEach(Function.prototype.call, Function.prototype.call); - } - sandbox.restore(); + let relayServer; + before(() => { + relayServer = new grpc.Server(); + var packageDefinition = protoLoader.loadSync("networks/networks.proto", { + includeDirs: [__dirname + "/../../../../common/protos"], + }); + var networksProto = grpc.loadPackageDefinition(packageDefinition); + relayServer.addService(networksProto.networks.networks.Network.service, { + getState: (call, callback) => { + relayResponse.requestId = call.request.requestId; + callback(null, relayResponse); + }, + requestState: (_, callback) => { + callback(null, ack); + }, + }); + relayServer.bindAsync( + localRelayEndpoint, + grpc.ServerCredentials.createInsecure(), + () => { + relayServer.start(); + }, + ); + }); + after(() => { + relayServer.forceShutdown(); + }); + it("successful send request", async () => { + const reqId = await relay.SendRequest("", "", "", "", "", "", "", ""); + expect(reqId).to.equal(requestId); }); - describe("#constructor", () => { - it("should not permit creation without an url", () => { - (() => { - new Relay(); - }).should.throw(/Invalid Arguments/); - }); - - it("should create a valid instance without any opts", () => { - (() => { - new Relay("http://someurl"); - }).should.not.throw(); - }); + it("successful get request", async () => { + const res = await relay.GetRequest(requestId, false); + expect(res.getRequestId()).to.equal(requestId); + expect(res.getStatus()).to.equal(relayResponse.status); + expect(res.hasError()).to.equal(false); + expect(res.hasView()).to.equal(true); + expect(res.getView().getData_asB64()).to.equal(view.getData_asB64()); + expect(JSON.stringify(res.getView().getMeta().toObject())).to.equal( + JSON.stringify(view.getMeta().toObject()), + ); }); - describe("#getEndpoint", () => { - let relay; + it("successful process request", async () => { + const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); + expect(res.getRequestId()).to.equal(requestId); + expect(res.getStatus()).to.equal(relayResponse.status); + expect(res.hasError()).to.equal(false); + expect(res.hasView()).to.equal(true); + expect(res.getView().getData_asB64()).to.equal(view.getData_asB64()); + expect(JSON.stringify(res.getView().getMeta().toObject())).to.equal( + JSON.stringify(view.getMeta().toObject()), + ); + }); + }); + describe("#fail relay api calls 1", () => { + const localRelayEndpoint = "localhost:19081"; + const relay = new Relay(localRelayEndpoint); - beforeEach(() => { - relay = new Relay("http://someurl"); - }); + let relayServer; + before(() => { + relayServer = new grpc.Server(); + var packageDefinition = protoLoader.loadSync("networks/networks.proto", { + includeDirs: [__dirname + "/../../../../common/protos"], + }); + var networksProto = grpc.loadPackageDefinition(packageDefinition); + relayServer.addService(networksProto.networks.networks.Network.service, { + getState: (call, callback) => { + callback(new Error("mock error"), null); + }, + requestState: (_, callback) => { + callback(new Error("mock error"), null); + }, + }); + relayServer.bindAsync( + localRelayEndpoint, + grpc.ServerCredentials.createInsecure(), + () => { + relayServer.start(); + }, + ); + }); + after(() => { + relayServer.forceShutdown(); + }); + it("fail send request", async () => { + const expectedErrMsg = + "Error: Error with Network Client: Error: Request state error: Error: 2 UNKNOWN: mock error"; + try { + const reqId = await relay.SendRequest("", "", "", "", "", "", "", ""); + throw new Error("IllegalState"); + } catch (error) { + expect(error.toString()).to.equal(expectedErrMsg); + } + }); - it("should set the _endPoint property", () => { - const expectedUrl = "somenewurl"; - relay._endPoint = expectedUrl; - relay.getEndpoint().should.equal(expectedUrl); - }); + it("fail get request", async () => { + const expectedErrMsg = "Error: Error: Error: 2 UNKNOWN: mock error"; + try { + const reqId = await relay.GetRequest("", false); + throw new Error("IllegalState"); + } catch (error) { + expect(error.toString()).to.equal(expectedErrMsg); + } }); + }); + describe("#fail relay api calls 2", () => { + const localRelayEndpoint = "localhost:19082"; + const relay = new Relay(localRelayEndpoint, false, [], 2000); + const requestId = "ABC-123"; - describe("#performRemoteRequest", () => { - let relay; + const ack = { + status: ackPb.Ack.STATUS.ERROR, + requestId: requestId, + message: "mock error", + }; - it("catch invalid url while doing DNS lookup", async () => { - relay = new Relay("https://someurl:9080"); - await expectThrowsAsync(() => - relay.ProcessRequest("address", "policy", "requestingNetwork", "cert", "sig", "nonce"), - ); - }); + const relayResponse = { + requestId: "", + status: statePb.RequestState.STATUS.ERROR, + error: "mock error", + }; + + let relayServer; + before(() => { + relayServer = new grpc.Server(); + var packageDefinition = protoLoader.loadSync("networks/networks.proto", { + includeDirs: [__dirname + "/../../../../common/protos"], + }); + var networksProto = grpc.loadPackageDefinition(packageDefinition); + relayServer.addService(networksProto.networks.networks.Network.service, { + getState: (call, callback) => { + relayResponse.requestId = call.request.requestId; + callback(null, relayResponse); + }, + requestState: (_, callback) => { + callback(null, ack); + }, + }); + relayServer.bindAsync( + localRelayEndpoint, + grpc.ServerCredentials.createInsecure(), + () => { + relayServer.start(); + }, + ); }); - - describe("#successful relay api calls", () => { - const localRelayEndpoint = "localhost:19080" - const relay = new Relay(localRelayEndpoint); - // Sample Request Id - const requestId = "ABC-123" - // Prepare Sample View - const meta = new statePb.Meta(); - meta.setProtocol(statePb.Meta.Protocol.FABRIC); - meta.setTimestamp(new Date().toISOString()); - meta.setProofType('Notarization'); - meta.setSerializationFormat('STRING'); - const view = new statePb.View(); - view.setMeta(meta); - view.setData(Buffer.from('1')); - - const ack = { - status: ackPb.Ack.STATUS.OK, - requestId: requestId, - message: '' - } - - const relayResponse = { - requestId: '', - status: statePb.RequestState.STATUS.COMPLETED, - view: view.toObject() - } - - let relayServer; - before(() => { - relayServer = new grpc.Server(); - var packageDefinition = protoLoader.loadSync( - 'networks/networks.proto', - { - includeDirs: [__dirname + '/../../../../common/protos'] - }); - var networksProto = grpc.loadPackageDefinition(packageDefinition); - relayServer.addService(networksProto.networks.networks.Network.service, { - getState: (call, callback) => { - relayResponse.requestId = call.request.requestId; - callback(null, relayResponse); - }, - requestState: (_, callback) => { - callback(null, ack); - } - }); - relayServer.bindAsync(localRelayEndpoint, grpc.ServerCredentials.createInsecure(), () => { - relayServer.start(); - }); - }); - after(() => { - relayServer.forceShutdown() - }); - it("successful send request", async () => { - const reqId = await relay.SendRequest("", "", "", "", "", "", "", ""); - expect(reqId).to.equal(requestId); - }); - - it("successful get request", async () => { - const res = await relay.GetRequest(requestId, false); - expect(res.getRequestId()).to.equal(requestId); - expect(res.getStatus()).to.equal(relayResponse.status); - expect(res.hasError()).to.equal(false); - expect(res.hasView()).to.equal(true); - expect(res.getView().getData_asB64()).to.equal(view.getData_asB64()); - expect(JSON.stringify(res.getView().getMeta().toObject())).to.equal(JSON.stringify(view.getMeta().toObject())); - }); - - it("successful process request", async () => { - const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); - expect(res.getRequestId()).to.equal(requestId); - expect(res.getStatus()).to.equal(relayResponse.status); - expect(res.hasError()).to.equal(false); - expect(res.hasView()).to.equal(true); - expect(res.getView().getData_asB64()).to.equal(view.getData_asB64()); - expect(JSON.stringify(res.getView().getMeta().toObject())).to.equal(JSON.stringify(view.getMeta().toObject())); - }); + after(() => { + relayServer.forceShutdown(); }); - describe("#fail relay api calls 1", () => { - const localRelayEndpoint = "localhost:19081" - const relay = new Relay(localRelayEndpoint); - - let relayServer; - before(() => { - relayServer = new grpc.Server(); - var packageDefinition = protoLoader.loadSync( - 'networks/networks.proto', - { - includeDirs: [__dirname + '/../../../../common/protos'] - }); - var networksProto = grpc.loadPackageDefinition(packageDefinition); - relayServer.addService(networksProto.networks.networks.Network.service, { - getState: (call, callback) => { - callback(new Error("mock error"), null); - }, - requestState: (_, callback) => { - callback(new Error("mock error"), null); - } - }); - relayServer.bindAsync(localRelayEndpoint, grpc.ServerCredentials.createInsecure(), () => { - relayServer.start(); - }); - }); - after(() => { - relayServer.forceShutdown() - }); - it("fail send request", async () => { - const expectedErrMsg = 'Error: Error with Network Client: Error: Request state error: Error: 2 UNKNOWN: mock error'; - try { - const reqId = await relay.SendRequest("", "", "", "", "", "", "", ""); - throw new Error('IllegalState'); - } catch (error) { - expect(error.toString()).to.equal(expectedErrMsg) - } - }); - - it("fail get request", async () => { - const expectedErrMsg = 'Error: Error: Error: 2 UNKNOWN: mock error'; - try { - const reqId = await relay.GetRequest('', false); - throw new Error('IllegalState'); - } catch (error) { - expect(error.toString()).to.equal(expectedErrMsg) - } - }); - + it("fail send request", async () => { + const expectedErrMsg = + "Error: Error with Network Client: Error: Request state received negative Ack error: " + + ack.message; + try { + const reqId = await relay.SendRequest("", "", "", "", "", "", "", ""); + throw new Error("IllegalState"); + } catch (error) { + expect(error.toString()).to.equal(expectedErrMsg); + } }); - describe("#fail relay api calls 2", () => { - const localRelayEndpoint = "localhost:19082" - const relay = new Relay(localRelayEndpoint, false, [], 2000); - const requestId = "ABC-123" - - const ack = { - status: ackPb.Ack.STATUS.ERROR, - requestId: requestId, - message: 'mock error' - } - - const relayResponse = { - requestId: '', - status: statePb.RequestState.STATUS.ERROR, - error: 'mock error' - } - - let relayServer; - before(() => { - relayServer = new grpc.Server(); - var packageDefinition = protoLoader.loadSync( - 'networks/networks.proto', - { - includeDirs: [__dirname + '/../../../../common/protos'] - }); - var networksProto = grpc.loadPackageDefinition(packageDefinition); - relayServer.addService(networksProto.networks.networks.Network.service, { - getState: (call, callback) => { - relayResponse.requestId = call.request.requestId; - callback(null, relayResponse); - }, - requestState: (_, callback) => { - callback(null, ack); - } - }); - relayServer.bindAsync(localRelayEndpoint, grpc.ServerCredentials.createInsecure(), () => { - relayServer.start(); - }); - }); - after(() => { - relayServer.forceShutdown() - }); - it("fail send request", async () => { - const expectedErrMsg = 'Error: Error with Network Client: Error: Request state received negative Ack error: ' + ack.message; - try { - const reqId = await relay.SendRequest("", "", "", "", "", "", "", ""); - throw new Error('IllegalState'); - } catch (error) { - expect(error.toString()).to.equal(expectedErrMsg) - } - }); - - it("fail process request", async () => { - // SendRequest error - const expectedErrMsg = 'Error: Error: Request state error: Error: Error with Network Client: Error: Request state received negative Ack error: ' + ack.message; - try { - const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); - throw new Error('IllegalState'); - } catch (error) { - expect(error.toString()).to.equal(expectedErrMsg) - } - - // GetState error - ack.status = ackPb.Ack.STATUS.OK; - ack.message = ''; - const expectedErrMsg2 = 'Error: Error: Error from view payload : ' + relayResponse.error; - try { - const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); - throw new Error('IllegalState'); - } catch (error) { - expect(error.toString()).to.equal(expectedErrMsg2) - } - }); - - it("fail pending state in process request", async () => { - // Pending till timeout - relayResponse.status = statePb.RequestState.STATUS.PENDING; - relayResponse.error = ''; - const expectedErrMsg3 = 'Error: Error: State error: Error: Timeout: State is still pending.'; - try { - const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); - throw new Error('IllegalState'); - } catch (error) { - expect(error.toString()).to.equal(expectedErrMsg3) - } - }); - + + it("fail process request", async () => { + // SendRequest error + const expectedErrMsg = + "Error: Error: Request state error: Error: Error with Network Client: Error: Request state received negative Ack error: " + + ack.message; + try { + const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); + throw new Error("IllegalState"); + } catch (error) { + expect(error.toString()).to.equal(expectedErrMsg); + } + + // GetState error + ack.status = ackPb.Ack.STATUS.OK; + ack.message = ""; + const expectedErrMsg2 = + "Error: Error: Error from view payload : " + relayResponse.error; + try { + const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); + throw new Error("IllegalState"); + } catch (error) { + expect(error.toString()).to.equal(expectedErrMsg2); + } + }); + + it("fail pending state in process request", async () => { + // Pending till timeout + relayResponse.status = statePb.RequestState.STATUS.PENDING; + relayResponse.error = ""; + const expectedErrMsg3 = + "Error: Error: State error: Error: Timeout: State is still pending."; + try { + const res = await relay.ProcessRequest("", "", "", "", "", "", "", ""); + throw new Error("IllegalState"); + } catch (error) { + expect(error.toString()).to.equal(expectedErrMsg3); + } }); + }); }); diff --git a/weaver/tests/network-setups/besu/artifacts/network1/createKeyFile.js b/weaver/tests/network-setups/besu/artifacts/network1/createKeyFile.js index 3c8d5f3b0a..7fb7742329 100644 --- a/weaver/tests/network-setups/besu/artifacts/network1/createKeyFile.js +++ b/weaver/tests/network-setups/besu/artifacts/network1/createKeyFile.js @@ -4,10 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -const Web3 = require('web3') +const Web3 = require("web3"); // Web3 initialization (should point to the JSON-RPC endpoint) -const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8590')) +const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8590")); var V3KeyStore = web3.eth.accounts.encrypt("", "tmppwd"); console.log(JSON.stringify(V3KeyStore)); diff --git a/weaver/tests/network-setups/besu/artifacts/network2/createKeyFile.js b/weaver/tests/network-setups/besu/artifacts/network2/createKeyFile.js index 915cdb87cd..50f382b057 100644 --- a/weaver/tests/network-setups/besu/artifacts/network2/createKeyFile.js +++ b/weaver/tests/network-setups/besu/artifacts/network2/createKeyFile.js @@ -4,10 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -const Web3 = require('web3') +const Web3 = require("web3"); // Web3 initialization (should point to the JSON-RPC endpoint) -const web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:9590')) +const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:9590")); var V3KeyStore = web3.eth.accounts.encrypt("", "tmppwd"); console.log(JSON.stringify(V3KeyStore)); diff --git a/webpack.dev.node.js b/webpack.dev.node.js index ca49b0dbb3..505c21be2b 100644 --- a/webpack.dev.node.js +++ b/webpack.dev.node.js @@ -1,9 +1,8 @@ -const path = require("path"); const packageDir = process.cwd(); +// This code does not run in production and therefore the dynamic require is +// considered acceptable since it provides developer convenience. +// eslint-disable-next-line @typescript-eslint/no-var-requires const pkg = require(`${packageDir}/package.json`); -const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") - .BundleAnalyzerPlugin; - const packageNameNoScope = pkg.name.substring(pkg.name.lastIndexOf("/") + 1); const libraryName = `${packageNameNoScope}`; @@ -45,13 +44,7 @@ module.exports = { }, ], }, - plugins: [ - // new BundleAnalyzerPlugin({ - // analyzerMode: "static", - // openAnalyzer: false, - // reportFilename: `${pkg.main}.html`, - // }), - ], + plugins: [], resolve: { extensions: [".ts", ".js"], }, diff --git a/webpack.prod.node.js b/webpack.prod.node.js index a1e8b89690..b692d7f533 100644 --- a/webpack.prod.node.js +++ b/webpack.prod.node.js @@ -1,8 +1,6 @@ const packageDir = process.cwd(); const pkg = require(`${packageDir}/package.json`); const TerserPlugin = require("terser-webpack-plugin"); -const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") - .BundleAnalyzerPlugin; const packageNameNoScope = pkg.name.substring(pkg.name.lastIndexOf("/") + 1); const libraryName = `${packageNameNoScope}`; @@ -48,13 +46,7 @@ module.exports = { resolve: { extensions: [".ts", ".js"], }, - plugins: [ - // new BundleAnalyzerPlugin({ - // analyzerMode: "static", - // openAnalyzer: false, - // reportFilename: `${pkg.mainMinified}.html`, - // }), - ], + plugins: [], optimization: { minimizer: [new TerserPlugin()], }, diff --git a/yarn.lock b/yarn.lock index 31b976c7b1..5389955590 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1081,15 +1081,6 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:7.12.11": - version: 7.12.11 - resolution: "@babel/code-frame@npm:7.12.11" - dependencies: - "@babel/highlight": "npm:^7.10.4" - checksum: 10/d243f0b1e475f5953ae452f70c0b4bd47a106df59733631b9ae36fb9ad1ae068c3a11d936ed22117084ec7439e843a4b75700922b507aac723ad84a257ae94f9 - languageName: node - linkType: hard - "@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.16.7": version: 7.16.7 resolution: "@babel/code-frame@npm:7.16.7" @@ -2339,7 +2330,7 @@ __metadata: languageName: node linkType: hard -"@babel/highlight@npm:^7.10.4, @babel/highlight@npm:^7.16.7": +"@babel/highlight@npm:^7.16.7": version: 7.16.10 resolution: "@babel/highlight@npm:7.16.10" dependencies: @@ -5981,23 +5972,6 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^0.4.0, @eslint/eslintrc@npm:^0.4.3": - version: 0.4.3 - resolution: "@eslint/eslintrc@npm:0.4.3" - dependencies: - ajv: "npm:^6.12.4" - debug: "npm:^4.1.1" - espree: "npm:^7.3.0" - globals: "npm:^13.9.0" - ignore: "npm:^4.0.6" - import-fresh: "npm:^3.2.1" - js-yaml: "npm:^3.13.1" - minimatch: "npm:^3.0.4" - strip-json-comments: "npm:^3.1.1" - checksum: 10/d41857d255e75870a523b9d88a0367e576cd51acb87732dc5f1ec1857efa56ef82f1c46873fab1fc6944aafaf0a6902ce3eb47c8a55abf8de135558f6f5405f5 - languageName: node - linkType: hard - "@eslint/eslintrc@npm:^2.1.2": version: 2.1.2 resolution: "@eslint/eslintrc@npm:2.1.2" @@ -6039,13 +6013,6 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:8.55.0": - version: 8.55.0 - resolution: "@eslint/js@npm:8.55.0" - checksum: 10/34b001a95b16501fd64f525b1de3ab0e4c252e5820b74069004934cb13977fc04ba4522a3e8f8074bd6af49da10d3444cd49fa711819f425ad73d6bf46eea82d - languageName: node - linkType: hard - "@eslint/js@npm:8.57.0": version: 8.57.0 resolution: "@eslint/js@npm:8.57.0" @@ -7170,7 +7137,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13, @humanwhocodes/config-array@npm:^0.11.14": +"@humanwhocodes/config-array@npm:^0.11.14": version: 0.11.14 resolution: "@humanwhocodes/config-array@npm:0.11.14" dependencies: @@ -7181,17 +7148,6 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.5.0": - version: 0.5.0 - resolution: "@humanwhocodes/config-array@npm:0.5.0" - dependencies: - "@humanwhocodes/object-schema": "npm:^1.2.0" - debug: "npm:^4.1.1" - minimatch: "npm:^3.0.4" - checksum: 10/478ad89d87e6a4aa7ea5626024f24efe0ec695e8d0393e22e5c495e1070fd562220ab74b5cd7a428882eec751126ec4e4e5883c2b1ec1740eb1af2bf4f3329f0 - languageName: node - linkType: hard - "@humanwhocodes/module-importer@npm:^1.0.1": version: 1.0.1 resolution: "@humanwhocodes/module-importer@npm:1.0.1" @@ -7199,7 +7155,7 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^1.2.0, @humanwhocodes/object-schema@npm:^1.2.1": +"@humanwhocodes/object-schema@npm:^1.2.1": version: 1.2.1 resolution: "@humanwhocodes/object-schema@npm:1.2.1" checksum: 10/b48a8f87fcd5fdc4ac60a31a8bf710d19cc64556050575e6a35a4a48a8543cf8cde1598a65640ff2cdfbfd165b38f9db4fa3782bea7848eb585cc3db824002e6 @@ -7303,13 +7259,8 @@ __metadata: "@types/react": "npm:18.2.43" "@types/react-dom": "npm:18.2.17" "@types/sort-by": "npm:1" - "@typescript-eslint/eslint-plugin": "npm:6.14.0" - "@typescript-eslint/parser": "npm:6.14.0" "@vitejs/plugin-react": "npm:4.2.1" apexcharts: "npm:3.45.2" - eslint: "npm:8.55.0" - eslint-plugin-react-hooks: "npm:4.6.0" - eslint-plugin-react-refresh: "npm:0.4.5" localforage: "npm:1.10.0" match-sorter: "npm:6.3.3" moment: "npm:2.30.1" @@ -7357,12 +7308,8 @@ __metadata: "@types/node": "npm:16.18.41" gluegun: "npm:5.1.6" jest: "npm:29.6.2" - prettier: "npm:1.19.1" ts-jest: "npm:29.1.1" ts-node: "npm:10.9.1" - tslint: "npm:5.20.1" - tslint-config-prettier: "npm:1.18.0" - tslint-config-standard: "npm:8.0.1" typescript: "npm:5.3.3" web3: "npm:1.10.0" winston: "npm:3.10.0" @@ -7412,11 +7359,7 @@ __metadata: "@hyperledger/cacti-weaver-protos-js": "npm:2.0.0-alpha.2" "@hyperledger/cacti-weaver-sdk-fabric": "npm:2.0.0-alpha.2" "@types/node": "npm:16.18.41" - "@typescript-eslint/eslint-plugin": "npm:5.62.0" - "@typescript-eslint/parser": "npm:5.62.0" dotenv: "npm:8.6.0" - eslint-config-prettier: "npm:8.9.0" - eslint-plugin-prettier: "npm:5.0.0" fabric-ca-client: "npm:2.2.20" fabric-common: "npm:2.2.20" fabric-network: "npm:2.2.20" @@ -7442,15 +7385,10 @@ __metadata: "@types/express": "npm:4.17.19" "@types/jest": "npm:29.5.3" "@types/node": "npm:12.20.55" - "@typescript-eslint/eslint-plugin": "npm:4.33.0" - "@typescript-eslint/parser": "npm:4.33.0" body-parser: "npm:1.20.2" crypto: "npm:1.0.1" dotenv: "npm:8.6.0" elliptic: "npm:6.5.4" - eslint: "npm:7.32.0" - eslint-config-prettier: "npm:8.10.0" - eslint-plugin-prettier: "npm:5.0.0" express: "npm:4.18.2" fabric-ca-client: "npm:2.2.20" fabric-common: "npm:2.2.20" @@ -7462,7 +7400,6 @@ __metadata: jest: "npm:29.6.2" node-notifier: "npm:8.0.2" pkg: "npm:4.5.1" - prettier: "npm:1.19.1" protobufjs: "npm:7.2.5" ts-jest: "npm:29.1.1" ts-node: "npm:10.9.1" @@ -7486,13 +7423,9 @@ __metadata: "@types/jsrsasign": "npm:10.5.11" "@types/node": "npm:16.18.41" "@types/uuid": "npm:9.0.8" - "@typescript-eslint/eslint-plugin": "npm:3.10.1" - "@typescript-eslint/parser": "npm:3.10.1" chai: "npm:4.3.7" chai-as-promised: "npm:7.1.1" dotenv: "npm:8.6.0" - eslint-config-prettier: "npm:6.15.0" - eslint-plugin-prettier: "npm:5.0.0" fabric-ca-client: "npm:2.2.20" fabric-common: "npm:2.2.20" fabric-network: "npm:2.2.20" @@ -7530,20 +7463,11 @@ __metadata: dependencies: "@hyperledger/cacti-weaver-protos-js": "npm:2.0.0-alpha.2" "@types/node": "npm:16.18.41" - "@typescript-eslint/eslint-plugin": "npm:3.10.1" - "@typescript-eslint/parser": "npm:3.10.1" chai: "npm:4.3.7" chai-as-promised: "npm:7.1.1" - eslint: "npm:7.32.0" - eslint-config-airbnb-base: "npm:14.2.1" - eslint-config-prettier: "npm:6.15.0" - eslint-plugin-import: "npm:2.28.1" - eslint-plugin-prettier: "npm:5.0.0" log4js: "npm:6.9.1" mocha: "npm:5.2.0" nyc: "npm:12.0.2" - prettier: "npm:2.8.8" - prettier-eslint: "npm:11.0.0" rewire: "npm:4.0.1" sinon: "npm:6.3.5" sinon-chai: "npm:3.7.0" @@ -7563,16 +7487,9 @@ __metadata: "@grpc/proto-loader": "npm:0.7.8" "@hyperledger/cacti-weaver-protos-js": "npm:2.0.0-alpha.2" "@types/node": "npm:16.18.41" - "@typescript-eslint/eslint-plugin": "npm:4.33.0" - "@typescript-eslint/parser": "npm:4.33.0" chai: "npm:4.3.7" chai-as-promised: "npm:7.1.1" elliptic: "npm:6.5.4" - eslint: "npm:7.32.0" - eslint-config-airbnb-base: "npm:14.2.1" - eslint-config-prettier: "npm:8.10.0" - eslint-plugin-import: "npm:2.28.1" - eslint-plugin-prettier: "npm:5.0.0" fabric-common: "npm:2.2.20" fabric-network: "npm:2.2.20" fabric-protos: "npm:2.2.20" @@ -7582,8 +7499,6 @@ __metadata: mocha: "npm:5.2.0" nyc: "npm:12.0.2" pkcs11js: "npm:1.3.1" - prettier: "npm:2.8.8" - prettier-eslint: "npm:11.0.0" rewire: "npm:4.0.1" sinon: "npm:6.3.5" sinon-chai: "npm:3.7.0" @@ -8037,15 +7952,10 @@ __metadata: "@types/express": "npm:4.17.19" "@types/node": "npm:14.18.54" "@types/uuid": "npm:9.0.8" - "@typescript-eslint/eslint-plugin": "npm:4.33.0" - "@typescript-eslint/parser": "npm:4.33.0" body-parser: "npm:1.20.2" cookie-parser: "npm:1.4.6" debug: "npm:3.1.0" escape-html: "npm:1.0.3" - eslint: "npm:7.32.0" - eslint-config-prettier: "npm:8.10.0" - eslint-plugin-prettier: "npm:5.0.0" ethereumjs-common: "npm:1.5.2" ethereumjs-tx: "npm:2.1.2" express: "npm:4.18.2" @@ -8056,7 +7966,6 @@ __metadata: jsonwebtoken: "npm:9.0.0" log4js: "npm:6.4.0" morgan: "npm:1.9.1" - prettier: "npm:2.8.8" shelljs: "npm:0.8.5" socket.io: "npm:4.5.4" ts-node: "npm:8.9.1" @@ -8183,15 +8092,10 @@ __metadata: "@types/express": "npm:4.17.19" "@types/node": "npm:14.18.54" "@types/uuid": "npm:9.0.8" - "@typescript-eslint/eslint-plugin": "npm:4.33.0" - "@typescript-eslint/parser": "npm:4.33.0" body-parser: "npm:1.20.2" cookie-parser: "npm:1.4.6" debug: "npm:2.6.9" escape-html: "npm:1.0.3" - eslint: "npm:7.32.0" - eslint-config-prettier: "npm:8.10.0" - eslint-plugin-prettier: "npm:5.0.0" ethereumjs-common: "npm:1.5.2" ethereumjs-tx: "npm:2.1.2" express: "npm:4.18.2" @@ -8202,7 +8106,6 @@ __metadata: jsonwebtoken: "npm:8.5.1" log4js: "npm:6.4.0" morgan: "npm:1.9.1" - prettier: "npm:2.8.8" shelljs: "npm:0.8.5" socket.io: "npm:4.5.4" ts-node: "npm:8.9.1" @@ -8785,7 +8688,6 @@ __metadata: "@types/uuid": "npm:9.0.8" axios: "npm:1.6.0" bl: "npm:5.0.0" - eslint: "npm:7.21.0" express: "npm:4.17.1" express-openapi-validator: "npm:4.13.1" form-data: "npm:4.0.0" @@ -9481,7 +9383,6 @@ __metadata: web3-eth: "npm:4.1.1" web3-utils: "npm:4.0.5" webpack: "npm:5.88.2" - webpack-bundle-analyzer: "npm:4.9.0" webpack-cli: "npm:4.10.0" wget-improved: "npm:3.4.0" yargs: "npm:17.7.2" @@ -12254,20 +12155,6 @@ __metadata: languageName: node linkType: hard -"@pkgr/utils@npm:^2.3.1": - version: 2.4.2 - resolution: "@pkgr/utils@npm:2.4.2" - dependencies: - cross-spawn: "npm:^7.0.3" - fast-glob: "npm:^3.3.0" - is-glob: "npm:^4.0.3" - open: "npm:^9.1.0" - picocolors: "npm:^1.0.0" - tslib: "npm:^2.6.0" - checksum: 10/f0b0b305a83bd65fac5637d28ad3e33f19194043e03ceef6b4e13d260bfa2678b73df76dc56ed906469ffe0494d4bd214e6b92ca80684f38547982edf982dd15 - languageName: node - linkType: hard - "@pmmmwh/react-refresh-webpack-plugin@npm:^0.5.3": version: 0.5.11 resolution: "@pmmmwh/react-refresh-webpack-plugin@npm:0.5.11" @@ -12307,13 +12194,6 @@ __metadata: languageName: node linkType: hard -"@polka/url@npm:^1.0.0-next.20": - version: 1.0.0-next.21 - resolution: "@polka/url@npm:1.0.0-next.21" - checksum: 10/c7654046d38984257dd639eab3dc770d1b0340916097b2fac03ce5d23506ada684e05574a69b255c32ea6a144a957c8cd84264159b545fca031c772289d88788 - languageName: node - linkType: hard - "@polkadot/api-augment@npm:10.9.1": version: 10.9.1 resolution: "@polkadot/api-augment@npm:10.9.1" @@ -14700,13 +14580,6 @@ __metadata: languageName: node linkType: hard -"@types/eslint-visitor-keys@npm:^1.0.0": - version: 1.0.0 - resolution: "@types/eslint-visitor-keys@npm:1.0.0" - checksum: 10/90cd39c84dab2e72d2911b141f56da021ffc781cae75512a3b15f2dcbd82e03bcec553d98bb147cb96ea02043cc3a1a05ebf20880f9ad15a995b8cf605390518 - languageName: node - linkType: hard - "@types/eslint@npm:*": version: 8.4.1 resolution: "@types/eslint@npm:8.4.1" @@ -15101,7 +14974,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.8": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.6, @types/json-schema@npm:^7.0.8": version: 7.0.9 resolution: "@types/json-schema@npm:7.0.9" checksum: 10/7ceb41e396240aa69ae15c02ffbb6548ea2bb2f845a7378c711c7c908a9a8438a0330f3135f1ccb6e82e334b9e2ec5b94fb57a1435f2b15362d38e9d5109e5ea @@ -15115,13 +14988,6 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:^7.0.3, @types/json-schema@npm:^7.0.9": - version: 7.0.11 - resolution: "@types/json-schema@npm:7.0.11" - checksum: 10/e50864a93f4dcb9de64c0c605d836f5416341c824d7a8cde1aa15a5fc68bed44b33cdcb2e04e5098339e9121848378f2d0cc5b124dec41c89203c6f67d6f344a - languageName: node - linkType: hard - "@types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5": version: 7.0.13 resolution: "@types/json-schema@npm:7.0.13" @@ -15129,6 +14995,13 @@ __metadata: languageName: node linkType: hard +"@types/json-schema@npm:^7.0.9": + version: 7.0.11 + resolution: "@types/json-schema@npm:7.0.11" + checksum: 10/e50864a93f4dcb9de64c0c605d836f5416341c824d7a8cde1aa15a5fc68bed44b33cdcb2e04e5098339e9121848378f2d0cc5b124dec41c89203c6f67d6f344a + languageName: node + linkType: hard + "@types/json-stable-stringify@npm:1.0.33": version: 1.0.33 resolution: "@types/json-stable-stringify@npm:1.0.33" @@ -16133,49 +16006,32 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:3.10.1": - version: 3.10.1 - resolution: "@typescript-eslint/eslint-plugin@npm:3.10.1" - dependencies: - "@typescript-eslint/experimental-utils": "npm:3.10.1" - debug: "npm:^4.1.1" - functional-red-black-tree: "npm:^1.0.1" - regexpp: "npm:^3.0.0" - semver: "npm:^7.3.2" - tsutils: "npm:^3.17.1" - peerDependencies: - "@typescript-eslint/parser": ^3.0.0 - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/5f4e48c6f3126d1d1525e6abce37aad3b6ee9b5714ab774a111ecd10ed4f2fc879ccd235f115849a8090458d7a34b16fa7cba1d480dfad4f456ff9c9461d8ccd - languageName: node - linkType: hard - -"@typescript-eslint/eslint-plugin@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/eslint-plugin@npm:4.33.0" +"@typescript-eslint/eslint-plugin@npm:7.1.0": + version: 7.1.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.1.0" dependencies: - "@typescript-eslint/experimental-utils": "npm:4.33.0" - "@typescript-eslint/scope-manager": "npm:4.33.0" - debug: "npm:^4.3.1" - functional-red-black-tree: "npm:^1.0.1" - ignore: "npm:^5.1.8" - regexpp: "npm:^3.1.0" - semver: "npm:^7.3.5" - tsutils: "npm:^3.21.0" + "@eslint-community/regexpp": "npm:^4.5.1" + "@typescript-eslint/scope-manager": "npm:7.1.0" + "@typescript-eslint/type-utils": "npm:7.1.0" + "@typescript-eslint/utils": "npm:7.1.0" + "@typescript-eslint/visitor-keys": "npm:7.1.0" + debug: "npm:^4.3.4" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.2.4" + natural-compare: "npm:^1.4.0" + semver: "npm:^7.5.4" + ts-api-utils: "npm:^1.0.1" peerDependencies: - "@typescript-eslint/parser": ^4.0.0 - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + "@typescript-eslint/parser": ^7.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/9b8d1a1ba5b6fc4fb79f01c965597704ff7d639cb1146663d5e924730bb761dae5b0f62fc94382aea7b6ebd184ebb3651f59bb5ccc8177213d411cf68591a151 + checksum: 10/f0b6b6e6ae2afee1df8dd2fd0c56588f9bb600468be9f255e033709a53371c6434da687e75dcb673503ef4f0416226f4ca3c94c65272828106e39b56aac87334 languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:5.62.0, @typescript-eslint/eslint-plugin@npm:^5.5.0": +"@typescript-eslint/eslint-plugin@npm:^5.5.0": version: 5.62.0 resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" dependencies: @@ -16199,87 +16055,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/eslint-plugin@npm:6.14.0" - dependencies: - "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.14.0" - "@typescript-eslint/type-utils": "npm:6.14.0" - "@typescript-eslint/utils": "npm:6.14.0" - "@typescript-eslint/visitor-keys": "npm:6.14.0" - debug: "npm:^4.3.4" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.4" - natural-compare: "npm:^1.4.0" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" - peerDependencies: - "@typescript-eslint/parser": ^6.0.0 || ^6.0.0-alpha - eslint: ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/d420277bed0104713fb4a3c2e0fed32b300919708db3f2e3d13bc83e80a9aec181bfc4e1e6012c65408c318f3ac113926fc77e6667d7657e34fa0d5a2c21ee32 - languageName: node - linkType: hard - -"@typescript-eslint/eslint-plugin@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.1.0" - dependencies: - "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:7.1.0" - "@typescript-eslint/type-utils": "npm:7.1.0" - "@typescript-eslint/utils": "npm:7.1.0" - "@typescript-eslint/visitor-keys": "npm:7.1.0" - debug: "npm:^4.3.4" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.4" - natural-compare: "npm:^1.4.0" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" - peerDependencies: - "@typescript-eslint/parser": ^7.0.0 - eslint: ^8.56.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/f0b6b6e6ae2afee1df8dd2fd0c56588f9bb600468be9f255e033709a53371c6434da687e75dcb673503ef4f0416226f4ca3c94c65272828106e39b56aac87334 - languageName: node - linkType: hard - -"@typescript-eslint/experimental-utils@npm:3.10.1": - version: 3.10.1 - resolution: "@typescript-eslint/experimental-utils@npm:3.10.1" - dependencies: - "@types/json-schema": "npm:^7.0.3" - "@typescript-eslint/types": "npm:3.10.1" - "@typescript-eslint/typescript-estree": "npm:3.10.1" - eslint-scope: "npm:^5.0.0" - eslint-utils: "npm:^2.0.0" - peerDependencies: - eslint: "*" - checksum: 10/3055eb8588d2ced3972341f5746ca5d1c27b56e5f1cf93c2e32dfb5ecfaaa7616e68050c7d16be2293e7b688be398c00cbe0b78ee0e40bb17aec47f8614d121a - languageName: node - linkType: hard - -"@typescript-eslint/experimental-utils@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/experimental-utils@npm:4.33.0" - dependencies: - "@types/json-schema": "npm:^7.0.7" - "@typescript-eslint/scope-manager": "npm:4.33.0" - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/typescript-estree": "npm:4.33.0" - eslint-scope: "npm:^5.1.1" - eslint-utils: "npm:^3.0.0" - peerDependencies: - eslint: "*" - checksum: 10/718d9445d6e6ca4ad70dd2eb7ade7a13f78b042203d118d5dfa59ddc2476f68a8f59b95802b046319bc9a219c9dfd57f2bbb8243480e8ff0329211eff45e155e - languageName: node - linkType: hard - "@typescript-eslint/experimental-utils@npm:^5.0.0": version: 5.62.0 resolution: "@typescript-eslint/experimental-utils@npm:5.62.0" @@ -16291,42 +16066,25 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:3.10.1, @typescript-eslint/parser@npm:^3.0.0": - version: 3.10.1 - resolution: "@typescript-eslint/parser@npm:3.10.1" - dependencies: - "@types/eslint-visitor-keys": "npm:^1.0.0" - "@typescript-eslint/experimental-utils": "npm:3.10.1" - "@typescript-eslint/types": "npm:3.10.1" - "@typescript-eslint/typescript-estree": "npm:3.10.1" - eslint-visitor-keys: "npm:^1.1.0" - peerDependencies: - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/3488d0a7c06c38893e6fc13d8eaaa408598302b1506f7cca9a4c9ebf1fdb1f30a3dbe8c9f0a8b81a7d5423a45681ddb4eee8a9686b3f811d371fddcc7da136f9 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/parser@npm:4.33.0" +"@typescript-eslint/parser@npm:7.1.0": + version: 7.1.0 + resolution: "@typescript-eslint/parser@npm:7.1.0" dependencies: - "@typescript-eslint/scope-manager": "npm:4.33.0" - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/typescript-estree": "npm:4.33.0" - debug: "npm:^4.3.1" + "@typescript-eslint/scope-manager": "npm:7.1.0" + "@typescript-eslint/types": "npm:7.1.0" + "@typescript-eslint/typescript-estree": "npm:7.1.0" + "@typescript-eslint/visitor-keys": "npm:7.1.0" + debug: "npm:^4.3.4" peerDependencies: - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/92c30f0d2e2305ca0840e87262b72187fb664be14675352dee021534ef999bb932dfc2388ac77eb359f7cb0384f00498836d35722238dd80d4d857ed02c43bbe + checksum: 10/39238d37f5a5f7058371ee3882fb7cd8a4579883fc5f13fda645c151fcf8d15e4c0db3ea7ffa7915a55c82451b544e9340c0228b45b83085158cb97974112f19 languageName: node linkType: hard -"@typescript-eslint/parser@npm:5.62.0, @typescript-eslint/parser@npm:^5.5.0": +"@typescript-eslint/parser@npm:^5.5.0": version: 5.62.0 resolution: "@typescript-eslint/parser@npm:5.62.0" dependencies: @@ -16343,52 +16101,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/parser@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/parser@npm:6.14.0" - dependencies: - "@typescript-eslint/scope-manager": "npm:6.14.0" - "@typescript-eslint/types": "npm:6.14.0" - "@typescript-eslint/typescript-estree": "npm:6.14.0" - "@typescript-eslint/visitor-keys": "npm:6.14.0" - debug: "npm:^4.3.4" - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/34f46aa8aaadb0d0ecb7d791a8436fcf44ec04af33ee9d198bcf6f7ca3927d8caa79d4756e0c4ef0d50979d895df0b8f1a2473fc83104423c96856e9d56047f3 - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:7.1.0": - version: 7.1.0 - resolution: "@typescript-eslint/parser@npm:7.1.0" - dependencies: - "@typescript-eslint/scope-manager": "npm:7.1.0" - "@typescript-eslint/types": "npm:7.1.0" - "@typescript-eslint/typescript-estree": "npm:7.1.0" - "@typescript-eslint/visitor-keys": "npm:7.1.0" - debug: "npm:^4.3.4" - peerDependencies: - eslint: ^8.56.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/39238d37f5a5f7058371ee3882fb7cd8a4579883fc5f13fda645c151fcf8d15e4c0db3ea7ffa7915a55c82451b544e9340c0228b45b83085158cb97974112f19 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/scope-manager@npm:4.33.0" - dependencies: - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/visitor-keys": "npm:4.33.0" - checksum: 10/f7348fe593fe977704bc9d2edd23b2d17a7a6073b0e14756e816578f6cfb56600f71f236eccac2743a1c209e77c467bfb3b5ce93d2067ff257da32a500458c86 - languageName: node - linkType: hard - "@typescript-eslint/scope-manager@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/scope-manager@npm:5.62.0" @@ -16399,16 +16111,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/scope-manager@npm:6.14.0" - dependencies: - "@typescript-eslint/types": "npm:6.14.0" - "@typescript-eslint/visitor-keys": "npm:6.14.0" - checksum: 10/fbe945169fe092df5953a54a552a9e8d9dc3dc158a39cd99de7f1843a169c82d3ba59e314b7d0f5b8110dbbe8c37c9e62dc2dda91a31536fe054221d5d8972c3 - languageName: node - linkType: hard - "@typescript-eslint/scope-manager@npm:7.1.0": version: 7.1.0 resolution: "@typescript-eslint/scope-manager@npm:7.1.0" @@ -16436,23 +16138,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/type-utils@npm:6.14.0" - dependencies: - "@typescript-eslint/typescript-estree": "npm:6.14.0" - "@typescript-eslint/utils": "npm:6.14.0" - debug: "npm:^4.3.4" - ts-api-utils: "npm:^1.0.1" - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/52c2a380d694f629ed2d37ce9decc5d8f6d276b030dcb8ee2d0a21b667d789e0d50c8a4d06fa60a053cbcc162b50c3708260f569ccd765609f17499d5294c19d - languageName: node - linkType: hard - "@typescript-eslint/type-utils@npm:7.1.0": version: 7.1.0 resolution: "@typescript-eslint/type-utils@npm:7.1.0" @@ -16470,20 +16155,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:3.10.1": - version: 3.10.1 - resolution: "@typescript-eslint/types@npm:3.10.1" - checksum: 10/c5c696a0c3b9dbc32b0b9f7ec8d06ab4ccb3422c4147032f001726997faef587d42d7d5c06cc3e4db52c05210b51e8052061630f56258f01523382488e9282ed - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/types@npm:4.33.0" - checksum: 10/c7ec55e6aef47ac49f712da52968c825552a23c59717f338f08c480e5336d592a689a324d21e2d370f48713a1302d7c78c14e6250bcea9b91f0b62ab6b2db3e1 - languageName: node - linkType: hard - "@typescript-eslint/types@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/types@npm:5.62.0" @@ -16491,13 +16162,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/types@npm:6.14.0" - checksum: 10/bcb32d69ac4a570634e37a3f149b7653a85334ac7b1d736961b627647ceff74797c4ac30b1405c508ede9462fad53b0b4442dbdf21877bf91263390c6e426e95 - languageName: node - linkType: hard - "@typescript-eslint/types@npm:7.1.0": version: 7.1.0 resolution: "@typescript-eslint/types@npm:7.1.0" @@ -16505,43 +16169,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:3.10.1": - version: 3.10.1 - resolution: "@typescript-eslint/typescript-estree@npm:3.10.1" - dependencies: - "@typescript-eslint/types": "npm:3.10.1" - "@typescript-eslint/visitor-keys": "npm:3.10.1" - debug: "npm:^4.1.1" - glob: "npm:^7.1.6" - is-glob: "npm:^4.0.1" - lodash: "npm:^4.17.15" - semver: "npm:^7.3.2" - tsutils: "npm:^3.17.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/ed4eedd04d1bcc651fe03925570b6199e76dd27878cde74dd3f06cf4a5b8911244746475ac9b2496d8cb9e20c70027f9f91ef688604167105a40164e4d408258 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/typescript-estree@npm:4.33.0" - dependencies: - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/visitor-keys": "npm:4.33.0" - debug: "npm:^4.3.1" - globby: "npm:^11.0.3" - is-glob: "npm:^4.0.1" - semver: "npm:^7.3.5" - tsutils: "npm:^3.21.0" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/e9409ec992d9d3c44efd53106bf63a6d5f6041e9dc359d54ea4b5f6787404cf44057cbd3090e9cc45ed4157dc631e398079f954490e50a4608cea1fbf9e69226 - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" @@ -16560,24 +16187,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/typescript-estree@npm:6.14.0" - dependencies: - "@typescript-eslint/types": "npm:6.14.0" - "@typescript-eslint/visitor-keys": "npm:6.14.0" - debug: "npm:^4.3.4" - globby: "npm:^11.1.0" - is-glob: "npm:^4.0.3" - semver: "npm:^7.5.4" - ts-api-utils: "npm:^1.0.1" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10/870f00e81de428c0afae3f753c04229170aeec76d62dcded0e22cff1c733fe60a350cf68571c889f87ea7a6008b73f7c62a079e91ab056d79aa2b9803a5b7150 - languageName: node - linkType: hard - "@typescript-eslint/typescript-estree@npm:7.1.0": version: 7.1.0 resolution: "@typescript-eslint/typescript-estree@npm:7.1.0" @@ -16615,23 +16224,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/utils@npm:6.14.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@types/json-schema": "npm:^7.0.12" - "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.14.0" - "@typescript-eslint/types": "npm:6.14.0" - "@typescript-eslint/typescript-estree": "npm:6.14.0" - semver: "npm:^7.5.4" - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 - checksum: 10/fec7338edc31d89d5413ec49ce690e05741511ba1ba2a8c59ce14321f5026e73e0584dc9f35645ab4100561bcf8ecef8a08c042388743db53fe73f047132a150 - languageName: node - linkType: hard - "@typescript-eslint/utils@npm:7.1.0": version: 7.1.0 resolution: "@typescript-eslint/utils@npm:7.1.0" @@ -16649,25 +16241,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:3.10.1": - version: 3.10.1 - resolution: "@typescript-eslint/visitor-keys@npm:3.10.1" - dependencies: - eslint-visitor-keys: "npm:^1.1.0" - checksum: 10/13e8059db306e626de3c55c6d3094af57c189b3f6d08ffda14eb13f6b6b9711b20625beeda6d234aed6c9d8aa9092c465aab62759dc09a03aa10dee28214a3fd - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/visitor-keys@npm:4.33.0" - dependencies: - "@typescript-eslint/types": "npm:4.33.0" - eslint-visitor-keys: "npm:^2.0.0" - checksum: 10/b28cd3f2c5cd919587d576e0cec8a95ea6c12a2e22dfec59ce70714efad4a7af4d467f9f964dd4ba1a4ad82d4a8c680a6d397e621b9be9d1df89b3a95380813f - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" @@ -16678,16 +16251,6 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.14.0": - version: 6.14.0 - resolution: "@typescript-eslint/visitor-keys@npm:6.14.0" - dependencies: - "@typescript-eslint/types": "npm:6.14.0" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10/404f87a121b4375b13e59ffc11ac2fe3c8e40025d0ef5cd6738ab7b3648ce1d41378414b1130ee68e0b454d7e6ec1937540799cdaa4ea572e2447b04d737ee44 - languageName: node - linkType: hard - "@typescript-eslint/visitor-keys@npm:7.1.0": version: 7.1.0 resolution: "@typescript-eslint/visitor-keys@npm:7.1.0" @@ -17262,7 +16825,7 @@ __metadata: languageName: node linkType: hard -"acorn-jsx@npm:^5.2.0, acorn-jsx@npm:^5.3.1, acorn-jsx@npm:^5.3.2": +"acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" peerDependencies: @@ -17278,7 +16841,7 @@ __metadata: languageName: node linkType: hard -"acorn-walk@npm:^8.0.0, acorn-walk@npm:^8.1.1": +"acorn-walk@npm:^8.1.1": version: 8.2.0 resolution: "acorn-walk@npm:8.2.0" checksum: 10/e69f7234f2adfeb16db3671429a7c80894105bd7534cb2032acf01bb26e6a847952d11a062d071420b43f8d82e33d2e57f26fe87d9cce0853e8143d8910ff1de @@ -17303,7 +16866,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^7.1.1, acorn@npm:^7.4.0": +"acorn@npm:^7.1.1": version: 7.4.1 resolution: "acorn@npm:7.4.1" bin: @@ -17312,21 +16875,21 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.4, acorn@npm:^8.4.1, acorn@npm:^8.7.1": - version: 8.8.2 - resolution: "acorn@npm:8.8.2" +"acorn@npm:^8.2.4, acorn@npm:^8.8.2, acorn@npm:^8.9.0": + version: 8.10.0 + resolution: "acorn@npm:8.10.0" bin: acorn: bin/acorn - checksum: 10/b4e77d56d24d3e11a45d9ac8ae661b4e14a4af04ae33edbf1e6bf910887e5bb352cc60e9ea06a0944880e6b658f58c095d3b54e88e1921cb9319608b51085dd7 + checksum: 10/522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd languageName: node linkType: hard -"acorn@npm:^8.2.4, acorn@npm:^8.8.2, acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" +"acorn@npm:^8.4.1, acorn@npm:^8.7.1": + version: 8.8.2 + resolution: "acorn@npm:8.8.2" bin: acorn: bin/acorn - checksum: 10/522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd + checksum: 10/b4e77d56d24d3e11a45d9ac8ae661b4e14a4af04ae33edbf1e6bf910887e5bb352cc60e9ea06a0944880e6b658f58c095d3b54e88e1921cb9319608b51085dd7 languageName: node linkType: hard @@ -17536,7 +17099,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.10.2, ajv@npm:^6.11.0, ajv@npm:^6.12.2, ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.12.6": +"ajv@npm:^6.10.0, ajv@npm:^6.11.0, ajv@npm:^6.12.2, ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -17548,7 +17111,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.0, ajv@npm:^8.0.1": +"ajv@npm:^8.0.0": version: 8.10.0 resolution: "ajv@npm:8.10.0" dependencies: @@ -18556,13 +18119,6 @@ __metadata: languageName: node linkType: hard -"astral-regex@npm:^1.0.0": - version: 1.0.0 - resolution: "astral-regex@npm:1.0.0" - checksum: 10/93417fc0879531cd95ace2560a54df865c9461a3ac0714c60cbbaa5f1f85d2bee85489e78d82f70b911b71ac25c5f05fc5a36017f44c9bb33c701bee229ff848 - languageName: node - linkType: hard - "astral-regex@npm:^2.0.0": version: 2.0.0 resolution: "astral-regex@npm:2.0.0" @@ -19563,7 +19119,7 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.44, big-integer@npm:^1.6.51": +"big-integer@npm:^1.6.51": version: 1.6.51 resolution: "big-integer@npm:1.6.51" checksum: 10/c7a12640901906d6f6b6bdb42a4eaba9578397b6d9a0dd090cf001ec813ff2bfcd441e364068ea0416db6175d2615f8ed19cff7d1a795115bf7c92d44993f991 @@ -19922,15 +19478,6 @@ __metadata: languageName: node linkType: hard -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" - dependencies: - big-integer: "npm:^1.6.44" - checksum: 10/15d31c1b0c7e0fb384e96349453879a33609d92d91b55a9ccee04b4be4b0645f1c823253d73326a1a23104521fbc45c2dd97fb05adf61863841b68cbb2ca7a3d - languageName: node - linkType: hard - "brace-expansion@npm:^1.1.7": version: 1.1.11 resolution: "brace-expansion@npm:1.1.11" @@ -20429,15 +19976,6 @@ __metadata: languageName: node linkType: hard -"bundle-name@npm:^3.0.0": - version: 3.0.0 - resolution: "bundle-name@npm:3.0.0" - dependencies: - run-applescript: "npm:^5.0.0" - checksum: 10/edf2b1fbe6096ed32e7566947ace2ea937ee427391744d7510a2880c4b9a5b3543d3f6c551236a29e5c87d3195f8e2912516290e638c15bcbede7b37cc375615 - languageName: node - linkType: hard - "busboy@npm:^0.2.11": version: 0.2.14 resolution: "busboy@npm:0.2.14" @@ -21952,7 +21490,7 @@ __metadata: languageName: node linkType: hard -"common-tags@npm:^1.4.0, common-tags@npm:^1.8.0": +"common-tags@npm:^1.8.0": version: 1.8.2 resolution: "common-tags@npm:1.8.2" checksum: 10/c665d0f463ee79dda801471ad8da6cb33ff7332ba45609916a508ad3d77ba07ca9deeb452e83f81f24c2b081e2c1315347f23d239210e63d1c5e1a0c7c019fe2 @@ -22125,7 +21663,7 @@ __metadata: languageName: node linkType: hard -"confusing-browser-globals@npm:^1.0.10, confusing-browser-globals@npm:^1.0.11": +"confusing-browser-globals@npm:^1.0.11": version: 1.0.11 resolution: "confusing-browser-globals@npm:1.0.11" checksum: 10/3afc635abd37e566477f610e7978b15753f0e84025c25d49236f1f14d480117185516bdd40d2a2167e6bed8048641a9854964b9c067e3dcdfa6b5d0ad3c3a5ef @@ -23554,7 +23092,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:~4.3.1, debug@npm:~4.3.2": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:~4.3.1, debug@npm:~4.3.2": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -23830,28 +23368,6 @@ __metadata: languageName: node linkType: hard -"default-browser-id@npm:^3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: "npm:^0.2.0" - untildify: "npm:^4.0.0" - checksum: 10/279c7ad492542e5556336b6c254a4eaf31b2c63a5433265655ae6e47301197b6cfb15c595a6fdc6463b2ff8e1a1a1ed3cba56038a60e1527ba4ab1628c6b9941 - languageName: node - linkType: hard - -"default-browser@npm:^4.0.0": - version: 4.0.0 - resolution: "default-browser@npm:4.0.0" - dependencies: - bundle-name: "npm:^3.0.0" - default-browser-id: "npm:^3.0.0" - execa: "npm:^7.1.1" - titleize: "npm:^3.0.0" - checksum: 10/40c5af984799042b140300be5639c9742599bda76dc9eba5ac9ad5943c83dd36cebc4471eafcfddf8e0ec817166d5ba89d56f08e66a126c7c7908a179cead1a7 - languageName: node - linkType: hard - "default-gateway@npm:^6.0.0, default-gateway@npm:^6.0.3": version: 6.0.3 resolution: "default-gateway@npm:6.0.3" @@ -23978,13 +23494,6 @@ __metadata: languageName: node linkType: hard -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 10/f28421cf9ee86eecaf5f3b8fe875f13d7009c2625e97645bfff7a2a49aca678270b86c39f9c32939e5ca7ab96b551377ed4139558c795e076774287ad3af1aa4 - languageName: node - linkType: hard - "define-properties@npm:^1.1.3": version: 1.1.3 resolution: "define-properties@npm:1.1.3" @@ -24386,7 +23895,7 @@ __metadata: languageName: node linkType: hard -"dlv@npm:^1.1.0, dlv@npm:^1.1.3": +"dlv@npm:^1.1.3": version: 1.1.3 resolution: "dlv@npm:1.1.3" checksum: 10/836459ec6b50e43e9ed388a5fc28954be99e3481af3fa4b5d82a600762eb65ef8faacd454097ed7fc2f8a60aea2800d65a4cece5cd0d81ab82b2031f3f759e6e @@ -24453,16 +23962,6 @@ __metadata: languageName: node linkType: hard -"doctrine@npm:0.7.2": - version: 0.7.2 - resolution: "doctrine@npm:0.7.2" - dependencies: - esutils: "npm:^1.1.6" - isarray: "npm:0.0.1" - checksum: 10/b8da8df16b22fdb3cdc9956ac2c02cc240b2ca1444f1df7c5d301fcc0f7774f322cf628cbd0aa08db9ebeec188d2bb896d22bf72acd9d9ac6d2c189d319e8076 - languageName: node - linkType: hard - "doctrine@npm:1.5.0, doctrine@npm:^1.2.2": version: 1.5.0 resolution: "doctrine@npm:1.5.0" @@ -25147,7 +24646,7 @@ __metadata: languageName: node linkType: hard -"enquirer@npm:2.3.6, enquirer@npm:^2.3.0, enquirer@npm:^2.3.5, enquirer@npm:^2.3.6": +"enquirer@npm:2.3.6, enquirer@npm:^2.3.0, enquirer@npm:^2.3.6": version: 2.3.6 resolution: "enquirer@npm:2.3.6" dependencies: @@ -25974,55 +25473,6 @@ __metadata: languageName: node linkType: hard -"eslint-config-airbnb-base@npm:14.2.1": - version: 14.2.1 - resolution: "eslint-config-airbnb-base@npm:14.2.1" - dependencies: - confusing-browser-globals: "npm:^1.0.10" - object.assign: "npm:^4.1.2" - object.entries: "npm:^1.1.2" - peerDependencies: - eslint: ^5.16.0 || ^6.8.0 || ^7.2.0 - eslint-plugin-import: ^2.22.1 - checksum: 10/0d679b6fe8030e18be9d5876bdf4d112988f9a1bc23fbb87a835447d448877041191caae6f9f656238bf5b883da8ea80199d6769075fe3493018c5e74d5fa0dd - languageName: node - linkType: hard - -"eslint-config-prettier@npm:6.15.0": - version: 6.15.0 - resolution: "eslint-config-prettier@npm:6.15.0" - dependencies: - get-stdin: "npm:^6.0.0" - peerDependencies: - eslint: ">=3.14.1" - bin: - eslint-config-prettier-check: bin/cli.js - checksum: 10/8648ec4259066f47f0bf5b75eea6bfe67a45a7eac065a17355638ea91cb09188cbda8b9562c009424268a7ee829e7ef3418edb90327ef5ff21c0aa24e734a6ea - languageName: node - linkType: hard - -"eslint-config-prettier@npm:8.10.0": - version: 8.10.0 - resolution: "eslint-config-prettier@npm:8.10.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 10/0a51ab1417cbf80fabcf7a406960a142663539c8140fdb0a187b78f3d708b9d137a62a4bc4e689150e290b667750ddabd1740a516623b0cb4adb6cc1962cfe2c - languageName: node - linkType: hard - -"eslint-config-prettier@npm:8.9.0": - version: 8.9.0 - resolution: "eslint-config-prettier@npm:8.9.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 10/7c802f650c16f8c122c12abcbbfe76d9fe47d79abf534f97c626b29852d34de82d29461ecc9cae3e6b13592906601d1e0534dab5b834ebe466baa809f2c3ebb2 - languageName: node - linkType: hard - "eslint-config-prettier@npm:9.1.0": version: 9.1.0 resolution: "eslint-config-prettier@npm:9.1.0" @@ -26153,33 +25603,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-import@npm:2.28.1, eslint-plugin-import@npm:^2.25.3": - version: 2.28.1 - resolution: "eslint-plugin-import@npm:2.28.1" - dependencies: - array-includes: "npm:^3.1.6" - array.prototype.findlastindex: "npm:^1.2.2" - array.prototype.flat: "npm:^1.3.1" - array.prototype.flatmap: "npm:^1.3.1" - debug: "npm:^3.2.7" - doctrine: "npm:^2.1.0" - eslint-import-resolver-node: "npm:^0.3.7" - eslint-module-utils: "npm:^2.8.0" - has: "npm:^1.0.3" - is-core-module: "npm:^2.13.0" - is-glob: "npm:^4.0.3" - minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.6" - object.groupby: "npm:^1.0.0" - object.values: "npm:^1.1.6" - semver: "npm:^6.3.1" - tsconfig-paths: "npm:^3.14.2" - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - checksum: 10/707dc97f06b12b0f3f91d5248dcea91bcd6a72c1168249a3ba177dd1ab6f31de9d5db829705236207a6ae79ad99a7a03efdfddb4a703da3a85530f9cc7401b2f - languageName: node - linkType: hard - "eslint-plugin-import@npm:2.29.1": version: 2.29.1 resolution: "eslint-plugin-import@npm:2.29.1" @@ -26207,6 +25630,33 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-import@npm:^2.25.3": + version: 2.28.1 + resolution: "eslint-plugin-import@npm:2.28.1" + dependencies: + array-includes: "npm:^3.1.6" + array.prototype.findlastindex: "npm:^1.2.2" + array.prototype.flat: "npm:^1.3.1" + array.prototype.flatmap: "npm:^1.3.1" + debug: "npm:^3.2.7" + doctrine: "npm:^2.1.0" + eslint-import-resolver-node: "npm:^0.3.7" + eslint-module-utils: "npm:^2.8.0" + has: "npm:^1.0.3" + is-core-module: "npm:^2.13.0" + is-glob: "npm:^4.0.3" + minimatch: "npm:^3.1.2" + object.fromentries: "npm:^2.0.6" + object.groupby: "npm:^1.0.0" + object.values: "npm:^1.1.6" + semver: "npm:^6.3.1" + tsconfig-paths: "npm:^3.14.2" + peerDependencies: + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + checksum: 10/707dc97f06b12b0f3f91d5248dcea91bcd6a72c1168249a3ba177dd1ab6f31de9d5db829705236207a6ae79ad99a7a03efdfddb4a703da3a85530f9cc7401b2f + languageName: node + linkType: hard + "eslint-plugin-import@npm:~2.2.0": version: 2.2.0 resolution: "eslint-plugin-import@npm:2.2.0" @@ -26301,25 +25751,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:5.0.0": - version: 5.0.0 - resolution: "eslint-plugin-prettier@npm:5.0.0" - dependencies: - prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.8.5" - peerDependencies: - "@types/eslint": ">=8.0.0" - eslint: ">=8.0.0" - prettier: ">=3.0.0" - peerDependenciesMeta: - "@types/eslint": - optional: true - eslint-config-prettier: - optional: true - checksum: 10/4ea0e5f82a72c80f109ca7de730a059f3fd4225907caa9fea2d858b22d6488aaa9055d17d0bc0f50b441adf1759daf75d43f9cec016445d61f0df1e93c06bc52 - languageName: node - linkType: hard - "eslint-plugin-prettier@npm:5.1.3": version: 5.1.3 resolution: "eslint-plugin-prettier@npm:5.1.3" @@ -26356,7 +25787,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:4.6.0, eslint-plugin-react-hooks@npm:^4.3.0": +"eslint-plugin-react-hooks@npm:^4.3.0": version: 4.6.0 resolution: "eslint-plugin-react-hooks@npm:4.6.0" peerDependencies: @@ -26365,15 +25796,6 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-refresh@npm:0.4.5": - version: 0.4.5 - resolution: "eslint-plugin-react-refresh@npm:0.4.5" - peerDependencies: - eslint: ">=7" - checksum: 10/f1526f55829f7eb4d9031fa082cb967f0bc578e8e2a3dfb9e5a47fc31cb0785bfa58ae717157f57241f7086a8790a88a6ec82743eaa5ca392a6b0fdb379169f8 - languageName: node - linkType: hard - "eslint-plugin-react@npm:^7.27.1": version: 7.33.2 resolution: "eslint-plugin-react@npm:7.33.2" @@ -26474,16 +25896,7 @@ __metadata: languageName: node linkType: hard -"eslint-utils@npm:^1.4.3": - version: 1.4.3 - resolution: "eslint-utils@npm:1.4.3" - dependencies: - eslint-visitor-keys: "npm:^1.1.0" - checksum: 10/77079d7123385011fc63c438ab95b01482eac04f2b9cd6e942d1f645ea430d610d721fe150bed8ec4ac17e7c4a11f2d6253a8182551ece09444c62c6a9973ad7 - languageName: node - linkType: hard - -"eslint-utils@npm:^2.0.0, eslint-utils@npm:^2.1.0": +"eslint-utils@npm:^2.0.0": version: 2.1.0 resolution: "eslint-utils@npm:2.1.0" dependencies: @@ -26492,25 +25905,14 @@ __metadata: languageName: node linkType: hard -"eslint-utils@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-utils@npm:3.0.0" - dependencies: - eslint-visitor-keys: "npm:^2.0.0" - peerDependencies: - eslint: ">=5" - checksum: 10/7675260a6b220c70f13e4cdbf077e93cad0dfb388429a27d6c0b584b2b20dca24594508e8bdb00a460a5764bd364a5018e20c2b8b1d70f82bcc3fdc30692a4d2 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^1.0.0, eslint-visitor-keys@npm:^1.1.0, eslint-visitor-keys@npm:^1.3.0": +"eslint-visitor-keys@npm:^1.0.0, eslint-visitor-keys@npm:^1.1.0": version: 1.3.0 resolution: "eslint-visitor-keys@npm:1.3.0" checksum: 10/595ab230e0fcb52f86ba0986a9a473b9fcae120f3729b43f1157f88f27f8addb1e545c4e3d444185f2980e281ca15be5ada6f65b4599eec227cf30e41233b762 languageName: node linkType: hard -"eslint-visitor-keys@npm:^2.0.0, eslint-visitor-keys@npm:^2.1.0": +"eslint-visitor-keys@npm:^2.1.0": version: 2.1.0 resolution: "eslint-visitor-keys@npm:2.1.0" checksum: 10/db4547eef5039122d518fa307e938ceb8589da5f6e8f5222efaf14dd62f748ce82e2d2becd3ff9412a50350b726bda95dbea8515a471074547daefa58aee8735 @@ -26547,151 +25949,6 @@ __metadata: languageName: node linkType: hard -"eslint@npm:7.21.0": - version: 7.21.0 - resolution: "eslint@npm:7.21.0" - dependencies: - "@babel/code-frame": "npm:7.12.11" - "@eslint/eslintrc": "npm:^0.4.0" - ajv: "npm:^6.10.0" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.0.1" - doctrine: "npm:^3.0.0" - enquirer: "npm:^2.3.5" - eslint-scope: "npm:^5.1.1" - eslint-utils: "npm:^2.1.0" - eslint-visitor-keys: "npm:^2.0.0" - espree: "npm:^7.3.1" - esquery: "npm:^1.4.0" - esutils: "npm:^2.0.2" - file-entry-cache: "npm:^6.0.1" - functional-red-black-tree: "npm:^1.0.1" - glob-parent: "npm:^5.0.0" - globals: "npm:^12.1.0" - ignore: "npm:^4.0.6" - import-fresh: "npm:^3.0.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - js-yaml: "npm:^3.13.1" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash: "npm:^4.17.20" - minimatch: "npm:^3.0.4" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.1" - progress: "npm:^2.0.0" - regexpp: "npm:^3.1.0" - semver: "npm:^7.2.1" - strip-ansi: "npm:^6.0.0" - strip-json-comments: "npm:^3.1.0" - table: "npm:^6.0.4" - text-table: "npm:^0.2.0" - v8-compile-cache: "npm:^2.0.3" - bin: - eslint: bin/eslint.js - checksum: 10/da1d993cd43dd89ce5c05be2f18595ef2284c49bee59bdf5d3b8cb37bfcbdefe7a050dd0962a23a0fef8ebe440d7e2727be67a6b7f934756608ca455617a1601 - languageName: node - linkType: hard - -"eslint@npm:7.32.0": - version: 7.32.0 - resolution: "eslint@npm:7.32.0" - dependencies: - "@babel/code-frame": "npm:7.12.11" - "@eslint/eslintrc": "npm:^0.4.3" - "@humanwhocodes/config-array": "npm:^0.5.0" - ajv: "npm:^6.10.0" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.0.1" - doctrine: "npm:^3.0.0" - enquirer: "npm:^2.3.5" - escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^5.1.1" - eslint-utils: "npm:^2.1.0" - eslint-visitor-keys: "npm:^2.0.0" - espree: "npm:^7.3.1" - esquery: "npm:^1.4.0" - esutils: "npm:^2.0.2" - fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" - functional-red-black-tree: "npm:^1.0.1" - glob-parent: "npm:^5.1.2" - globals: "npm:^13.6.0" - ignore: "npm:^4.0.6" - import-fresh: "npm:^3.0.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - js-yaml: "npm:^3.13.1" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.0.4" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.1" - progress: "npm:^2.0.0" - regexpp: "npm:^3.1.0" - semver: "npm:^7.2.1" - strip-ansi: "npm:^6.0.0" - strip-json-comments: "npm:^3.1.0" - table: "npm:^6.0.9" - text-table: "npm:^0.2.0" - v8-compile-cache: "npm:^2.0.3" - bin: - eslint: bin/eslint.js - checksum: 10/2015a72bc4c49a933fc7bd707bdb61b0386542c9e23d28be79434b5fd914f14355a4565a29fdcd1c69a8a3682cf20b4f2aed6b60e294b0b0d98ace69138c3a02 - languageName: node - linkType: hard - -"eslint@npm:8.55.0": - version: 8.55.0 - resolution: "eslint@npm:8.55.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.55.0" - "@humanwhocodes/config-array": "npm:^0.11.13" - "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - "@ungap/structured-clone": "npm:^1.2.0" - ajv: "npm:^6.12.4" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" - escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" - esutils: "npm:^2.0.2" - fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" - find-up: "npm:^5.0.0" - glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.1.2" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" - bin: - eslint: bin/eslint.js - checksum: 10/afd016cfbe9e9d667b3f98c14c681a7e518808f6c30856e56cbb02248900eac5bf6dc5e577a7eaec259539486db48ef7d16ef58fb14b1585ba7c84b35490c53c - languageName: node - linkType: hard - "eslint@npm:8.57.0": version: 8.57.0 resolution: "eslint@npm:8.57.0" @@ -26788,53 +26045,6 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^6.8.0": - version: 6.8.0 - resolution: "eslint@npm:6.8.0" - dependencies: - "@babel/code-frame": "npm:^7.0.0" - ajv: "npm:^6.10.0" - chalk: "npm:^2.1.0" - cross-spawn: "npm:^6.0.5" - debug: "npm:^4.0.1" - doctrine: "npm:^3.0.0" - eslint-scope: "npm:^5.0.0" - eslint-utils: "npm:^1.4.3" - eslint-visitor-keys: "npm:^1.1.0" - espree: "npm:^6.1.2" - esquery: "npm:^1.0.1" - esutils: "npm:^2.0.2" - file-entry-cache: "npm:^5.0.1" - functional-red-black-tree: "npm:^1.0.1" - glob-parent: "npm:^5.0.0" - globals: "npm:^12.1.0" - ignore: "npm:^4.0.6" - import-fresh: "npm:^3.0.0" - imurmurhash: "npm:^0.1.4" - inquirer: "npm:^7.0.0" - is-glob: "npm:^4.0.0" - js-yaml: "npm:^3.13.1" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.3.0" - lodash: "npm:^4.17.14" - minimatch: "npm:^3.0.4" - mkdirp: "npm:^0.5.1" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.8.3" - progress: "npm:^2.0.0" - regexpp: "npm:^2.0.1" - semver: "npm:^6.1.2" - strip-ansi: "npm:^5.2.0" - strip-json-comments: "npm:^3.0.1" - table: "npm:^5.2.3" - text-table: "npm:^0.2.0" - v8-compile-cache: "npm:^2.0.3" - bin: - eslint: ./bin/eslint.js - checksum: 10/a3e9dd67f801d1164a4689794c688a1c6f8ddd4862721d1e543ed498688b9ce9ab969977df19e378bf3b57e83751f79139128ad785c4b9c863a0037c72b99bdc - languageName: node - linkType: hard - "eslint@npm:^8.3.0": version: 8.48.0 resolution: "eslint@npm:8.48.0" @@ -26944,28 +26154,6 @@ __metadata: languageName: node linkType: hard -"espree@npm:^6.1.2, espree@npm:^6.2.1": - version: 6.2.1 - resolution: "espree@npm:6.2.1" - dependencies: - acorn: "npm:^7.1.1" - acorn-jsx: "npm:^5.2.0" - eslint-visitor-keys: "npm:^1.1.0" - checksum: 10/e8b1edc0f8c6cdb1ef7c40e633ff1f1ea1585c46aa75c16f5525a3ca7f1a518197ad5fd40cedee31936ff4e1b5a396d585e6742e1f8a4c7dc2a17b3ed1d64c88 - languageName: node - linkType: hard - -"espree@npm:^7.3.0, espree@npm:^7.3.1": - version: 7.3.1 - resolution: "espree@npm:7.3.1" - dependencies: - acorn: "npm:^7.4.0" - acorn-jsx: "npm:^5.3.1" - eslint-visitor-keys: "npm:^1.3.0" - checksum: 10/7cf230d4d726f6e2c53925566ef96e78a5656eb05adbb6cd493f863341e532b491b035db7a4ce292b70243bb727722acff98b66ae751888ee51791d8389c6819 - languageName: node - linkType: hard - "espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" @@ -26987,7 +26175,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.0.0, esquery@npm:^1.0.1, esquery@npm:^1.4.2": +"esquery@npm:^1.0.0, esquery@npm:^1.4.2": version: 1.5.0 resolution: "esquery@npm:1.5.0" dependencies: @@ -26996,15 +26184,6 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.0": - version: 1.4.0 - resolution: "esquery@npm:1.4.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10/25b571ec54f186521819be48cd12643f9f5bdef6be9679161a48dec9cfd478764970a77ef563a516cf1f0f05e7e490e3ff2d514715b86cb8d03329cbb56ae4a8 - languageName: node - linkType: hard - "esrecurse@npm:^4.1.0, esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -27042,13 +26221,6 @@ __metadata: languageName: node linkType: hard -"esutils@npm:^1.1.6": - version: 1.1.6 - resolution: "esutils@npm:1.1.6" - checksum: 10/1657640cda545532db1d7096c7ef7ec2c50b29469ab50bba43d59388b32e1a13f29b9bcf9a079a41eb86118b269d8c72caaee3fdc328ab29fba6b495ba152c86 - languageName: node - linkType: hard - "esutils@npm:^2.0.2": version: 2.0.3 resolution: "esutils@npm:2.0.3" @@ -27559,23 +26731,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^7.1.1": - version: 7.2.0 - resolution: "execa@npm:7.2.0" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^6.0.1" - human-signals: "npm:^4.3.0" - is-stream: "npm:^3.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^5.1.0" - onetime: "npm:^6.0.0" - signal-exit: "npm:^3.0.7" - strip-final-newline: "npm:^3.0.0" - checksum: 10/473feff60f9d4dbe799225948de48b5158c1723021d19c4b982afe37bcd111ae84e1b4c9dfe967fae5101b0894b1a62e4dd564a286dfa3e46d7b0cfdbf7fe62b - languageName: node - linkType: hard - "execa@npm:^8.0.1": version: 8.0.1 resolution: "execa@npm:8.0.1" @@ -28406,15 +27561,6 @@ __metadata: languageName: node linkType: hard -"file-entry-cache@npm:^5.0.1": - version: 5.0.1 - resolution: "file-entry-cache@npm:5.0.1" - dependencies: - flat-cache: "npm:^2.0.1" - checksum: 10/585f3d19043d3552a06ec3e20e13cee054f255d3decce6def7fea5cba50448ce82fb9f779115da61cc58b98e7889cf5cc3b388943100bbd0305f00b11d0f4d84 - languageName: node - linkType: hard - "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -28713,17 +27859,6 @@ __metadata: languageName: node linkType: hard -"flat-cache@npm:^2.0.1": - version: 2.0.1 - resolution: "flat-cache@npm:2.0.1" - dependencies: - flatted: "npm:^2.0.0" - rimraf: "npm:2.6.3" - write: "npm:1.0.3" - checksum: 10/334891772e9af0e860e1e602f0e577c2b0ac5af4e7fbc672f8396b08a48a4dbe9001f7a7e1d8f8060da4cfe592bb51b35d8a8e6159c1cd62337d97c0847fdb44 - languageName: node - linkType: hard - "flat-cache@npm:^3.0.4": version: 3.0.4 resolution: "flat-cache@npm:3.0.4" @@ -28743,13 +27878,6 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^2.0.0": - version: 2.0.2 - resolution: "flatted@npm:2.0.2" - checksum: 10/473c754db7a529e125a22057098f1a4c905ba17b8cc269c3acf77352f0ffa6304c851eb75f6a1845f74461f560e635129ca6b0b8a78fb253c65cea4de3d776f2 - languageName: node - linkType: hard - "flatted@npm:^3.1.0, flatted@npm:^3.2.4": version: 3.2.5 resolution: "flatted@npm:3.2.5" @@ -29622,13 +28750,6 @@ __metadata: languageName: node linkType: hard -"get-stdin@npm:^6.0.0": - version: 6.0.0 - resolution: "get-stdin@npm:6.0.0" - checksum: 10/593f6fb4fff4c8d49ec93a07c430c1edc6bd4fe7e429d222b5da2f367276a98809af9e90467ad88a2d83722ff95b9b35bbaba02b56801421c5e3668173fe12b4 - languageName: node - linkType: hard - "get-stdin@npm:^8.0.0": version: 8.0.0 resolution: "get-stdin@npm:8.0.0" @@ -30066,15 +29187,6 @@ __metadata: languageName: node linkType: hard -"globals@npm:^12.1.0": - version: 12.4.0 - resolution: "globals@npm:12.4.0" - dependencies: - type-fest: "npm:^0.8.1" - checksum: 10/11b38ef0077f5d8d616b1bc5effac20667247fc42c65c6f8fac4fc3758cd14ad73ccd36eff376c29ef395caf5f4c33e8460b78f79c37ce44cf3ab568a3b7623b - languageName: node - linkType: hard - "globals@npm:^13.19.0": version: 13.21.0 resolution: "globals@npm:13.21.0" @@ -30084,15 +29196,6 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.6.0, globals@npm:^13.9.0": - version: 13.12.1 - resolution: "globals@npm:13.12.1" - dependencies: - type-fest: "npm:^0.20.2" - checksum: 10/f92cfc0e5c723c0339bc943668a96b8343470289e81903459b397e4491bc6adaa367edbf75a28c5191d87eaeac9068c75961572a6df03e6faa6494291a5be728 - languageName: node - linkType: hard - "globals@npm:^9.14.0": version: 9.18.0 resolution: "globals@npm:9.18.0" @@ -30139,7 +29242,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^11.0.0, globby@npm:^11.0.1, globby@npm:^11.0.3, globby@npm:^11.0.4, globby@npm:^11.1.0": +"globby@npm:^11.0.0, globby@npm:^11.0.1, globby@npm:^11.0.4, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -31415,13 +30518,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^4.3.0": - version: 4.3.1 - resolution: "human-signals@npm:4.3.1" - checksum: 10/fa59894c358fe9f2b5549be2fb083661d5e1dff618d3ac70a49ca73495a72e873fbf6c0878561478e521e17d498292746ee391791db95ffe5747bfb5aef8765b - languageName: node - linkType: hard - "human-signals@npm:^5.0.0": version: 5.0.0 resolution: "human-signals@npm:5.0.0" @@ -31552,14 +30648,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^4.0.6": - version: 4.0.6 - resolution: "ignore@npm:4.0.6" - checksum: 10/e04d6bd60d9da12cfe8896acf470824172843dddc25a9be0726199d5e031254634a69ce8479a82f194154b9b28cb3b08bb7a53e56f7f7eba2663e04791e74742 - languageName: node - linkType: hard - -"ignore@npm:^5.1.1, ignore@npm:^5.1.8, ignore@npm:^5.2.0": +"ignore@npm:^5.1.1, ignore@npm:^5.2.0": version: 5.2.0 resolution: "ignore@npm:5.2.0" checksum: 10/30283f05fb7d867ee0e08faebb3e69caba2c6c55092042cd061eac1b37a3e78db72bfcfbb08b3598999344fba3d93a9c693b5401da5faaecc0fb7c2dce87beb4 @@ -31900,27 +30989,6 @@ __metadata: languageName: node linkType: hard -"inquirer@npm:^7.0.0": - version: 7.3.3 - resolution: "inquirer@npm:7.3.3" - dependencies: - ansi-escapes: "npm:^4.2.1" - chalk: "npm:^4.1.0" - cli-cursor: "npm:^3.1.0" - cli-width: "npm:^3.0.0" - external-editor: "npm:^3.0.3" - figures: "npm:^3.0.0" - lodash: "npm:^4.17.19" - mute-stream: "npm:0.0.8" - run-async: "npm:^2.4.0" - rxjs: "npm:^6.6.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - through: "npm:^2.3.6" - checksum: 10/052c6fce2d467343ced6500080b4b70eaf2ca996933fc3b5c9b0dd1ea275dd9c2a1070880f5f163f42bd13acf25c1ab8ab384444c1a413050db34aab69112583 - languageName: node - linkType: hard - "inquirer@npm:^9.2.12": version: 9.2.12 resolution: "inquirer@npm:9.2.12" @@ -32500,15 +31568,6 @@ __metadata: languageName: node linkType: hard -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: 10/b698118f04feb7eaf3338922bd79cba064ea54a1c3db6ec8c0c8d8ee7613e7e5854d802d3ef646812a8a3ace81182a085dfa0a71cc68b06f3fa794b9783b3c90 - languageName: node - linkType: hard - "is-dotfile@npm:^1.0.0": version: 1.0.3 resolution: "is-dotfile@npm:1.0.3" @@ -32649,17 +31708,6 @@ __metadata: languageName: node linkType: hard -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: "npm:^3.0.0" - bin: - is-inside-container: cli.js - checksum: 10/c50b75a2ab66ab3e8b92b3bc534e1ea72ca25766832c0623ac22d134116a98bcf012197d1caabe1d1c4bd5f84363d4aa5c36bb4b585fbcaf57be172cd10a1a03 - languageName: node - linkType: hard - "is-installed-globally@npm:^0.4.0": version: 0.4.0 resolution: "is-installed-globally@npm:0.4.0" @@ -36675,7 +35723,7 @@ __metadata: languageName: node linkType: hard -"lodash.merge@npm:^4.6.0, lodash.merge@npm:^4.6.2": +"lodash.merge@npm:^4.6.2": version: 4.6.2 resolution: "lodash.merge@npm:4.6.2" checksum: 10/d0ea2dd0097e6201be083865d50c3fb54fbfbdb247d9cc5950e086c991f448b7ab0cdab0d57eacccb43473d3f2acd21e134db39f22dac2d6c9ba6bf26978e3d6 @@ -36766,13 +35814,6 @@ __metadata: languageName: node linkType: hard -"lodash.truncate@npm:^4.4.2": - version: 4.4.2 - resolution: "lodash.truncate@npm:4.4.2" - checksum: 10/7a495616121449e5d2288c606b1025d42ab9979e8c93ba885e5c5802ffd4f1ebad4428c793ccc12f73e73237e85a9f5b67dd6415757546fbd5a4653ba83e25ac - languageName: node - linkType: hard - "lodash.uniq@npm:^4.5.0": version: 4.5.0 resolution: "lodash.uniq@npm:4.5.0" @@ -36891,16 +35932,6 @@ __metadata: languageName: node linkType: hard -"loglevel-colored-level-prefix@npm:^1.0.0": - version: 1.0.0 - resolution: "loglevel-colored-level-prefix@npm:1.0.0" - dependencies: - chalk: "npm:^1.1.3" - loglevel: "npm:^1.4.1" - checksum: 10/aa60baa2b8f5d7f22327d597cbe4930eea5b0ffd8451b3d60e61824abd8a2401a039f866b810898e1d04ebf39033ef366fce6f0d93293f3b79cb4495773ae0de - languageName: node - linkType: hard - "loglevel-plugin-prefix@npm:0.8.4": version: 0.8.4 resolution: "loglevel-plugin-prefix@npm:0.8.4" @@ -36915,7 +35946,7 @@ __metadata: languageName: node linkType: hard -"loglevel@npm:1.8.1, loglevel@npm:^1.4.1, loglevel@npm:^1.6.8": +"loglevel@npm:1.8.1, loglevel@npm:^1.6.8": version: 1.8.1 resolution: "loglevel@npm:1.8.1" checksum: 10/36a786082a7e4f1d962de330122291da3a102b88dbde81a45eb92a045c38b0903783958ba39dce641440c0413da303410e7f2565f897bccad828853bd5974c86 @@ -38348,13 +37379,6 @@ __metadata: languageName: node linkType: hard -"mrmime@npm:^1.0.0": - version: 1.0.0 - resolution: "mrmime@npm:1.0.0" - checksum: 10/3c6c3b0b6e72f89e4833bd6a72fc5a51e186bfea9f78097305f47f5bfc801dcc761df90c3e3680c76fe542828d6b1fdac88ac952c9dc536d81f228236b924b3b - languageName: node - linkType: hard - "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -40125,17 +39149,6 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.2": - version: 1.1.6 - resolution: "object.entries@npm:1.1.6" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" - es-abstract: "npm:^1.20.4" - checksum: 10/08a09ff839fd541e8af90a47c67a3dd71721683cdc28e55470e191a8afd8b61188fb9a429fd1d1805808097d8d5950b47c0c2862157dad891226112d8321401b - languageName: node - linkType: hard - "object.entries@npm:^1.1.6": version: 1.1.7 resolution: "object.entries@npm:1.1.7" @@ -40419,18 +39432,6 @@ __metadata: languageName: node linkType: hard -"open@npm:^9.1.0": - version: 9.1.0 - resolution: "open@npm:9.1.0" - dependencies: - default-browser: "npm:^4.0.0" - define-lazy-prop: "npm:^3.0.0" - is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^2.2.0" - checksum: 10/b45bcc7a6795804a2f560f0ca9f5e5344114bc40754d10c28a811c0c8f7027356979192931a6a7df2ab9e5bab3058988c99ae55f4fb71db2ce9fc77c40f619aa - languageName: node - linkType: hard - "openapi-types@npm:12.1.3": version: 12.1.3 resolution: "openapi-types@npm:12.1.3" @@ -40438,7 +39439,7 @@ __metadata: languageName: node linkType: hard -"opener@npm:^1.5.1, opener@npm:^1.5.2": +"opener@npm:^1.5.1": version: 1.5.2 resolution: "opener@npm:1.5.2" bin: @@ -40447,7 +39448,7 @@ __metadata: languageName: node linkType: hard -"optionator@npm:^0.8.1, optionator@npm:^0.8.2, optionator@npm:^0.8.3": +"optionator@npm:^0.8.1, optionator@npm:^0.8.2": version: 0.8.3 resolution: "optionator@npm:0.8.3" dependencies: @@ -40461,20 +39462,6 @@ __metadata: languageName: node linkType: hard -"optionator@npm:^0.9.1": - version: 0.9.1 - resolution: "optionator@npm:0.9.1" - dependencies: - deep-is: "npm:^0.1.3" - fast-levenshtein: "npm:^2.0.6" - levn: "npm:^0.4.1" - prelude-ls: "npm:^1.2.1" - type-check: "npm:^0.4.0" - word-wrap: "npm:^1.2.3" - checksum: 10/19cfb625ba3cafd99c204744595a8b5111491632d379be341a8286c53a0101adac6f7ca9be4319ccecaaf5d43a55e65dde8b434620726032472833d958d43698 - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.3 resolution: "optionator@npm:0.9.3" @@ -43120,26 +42107,6 @@ __metadata: languageName: node linkType: hard -"prettier-eslint@npm:11.0.0": - version: 11.0.0 - resolution: "prettier-eslint@npm:11.0.0" - dependencies: - "@typescript-eslint/parser": "npm:^3.0.0" - common-tags: "npm:^1.4.0" - dlv: "npm:^1.1.0" - eslint: "npm:^6.8.0" - indent-string: "npm:^4.0.0" - lodash.merge: "npm:^4.6.0" - loglevel-colored-level-prefix: "npm:^1.0.0" - prettier: "npm:^2.0.0" - pretty-format: "npm:^23.0.1" - require-relative: "npm:^0.8.7" - typescript: "npm:^3.9.3" - vue-eslint-parser: "npm:~7.1.0" - checksum: 10/a66a09af561e13bc2f7f0ee5d710383725190bc3325c7c47387833d59237383f55410e56f95108a427df883f7f965925e3a96e76c9f0f17c8945b13efc858356 - languageName: node - linkType: hard - "prettier-linter-helpers@npm:^1.0.0": version: 1.0.0 resolution: "prettier-linter-helpers@npm:1.0.0" @@ -43149,24 +42116,6 @@ __metadata: languageName: node linkType: hard -"prettier@npm:1.19.1": - version: 1.19.1 - resolution: "prettier@npm:1.19.1" - bin: - prettier: ./bin-prettier.js - checksum: 10/21d245fe788d1123fd7df63a3759f7807d8c0bb7aaa2f4f02cc055998c3e1f92d7c614b6e2749a936c527cdbbb0f3c869bd9723eb32c5232b0fab9fac04b455d - languageName: node - linkType: hard - -"prettier@npm:2.8.8, prettier@npm:^2.0.0": - version: 2.8.8 - resolution: "prettier@npm:2.8.8" - bin: - prettier: bin-prettier.js - checksum: 10/00cdb6ab0281f98306cd1847425c24cbaaa48a5ff03633945ab4c701901b8e96ad558eb0777364ffc312f437af9b5a07d0f45346266e8245beaf6247b9c62b24 - languageName: node - linkType: hard - "prettier@npm:3.2.5": version: 3.2.5 resolution: "prettier@npm:3.2.5" @@ -43193,16 +42142,6 @@ __metadata: languageName: node linkType: hard -"pretty-format@npm:^23.0.1": - version: 23.6.0 - resolution: "pretty-format@npm:23.6.0" - dependencies: - ansi-regex: "npm:^3.0.0" - ansi-styles: "npm:^3.2.0" - checksum: 10/7fda1f30c374e24b4ff2ce1d517ecd42a25b0eb759e3289b04ca93d95d38e84a56fc240e76bdd90b0ac471e77088e543ac581223cafcb56e9be05c9d6ac10516 - languageName: node - linkType: hard - "pretty-format@npm:^27.0.0, pretty-format@npm:^27.0.2, pretty-format@npm:^27.5.1": version: 27.5.1 resolution: "pretty-format@npm:27.5.1" @@ -44672,14 +43611,7 @@ __metadata: languageName: node linkType: hard -"regexpp@npm:^2.0.1": - version: 2.0.1 - resolution: "regexpp@npm:2.0.1" - checksum: 10/06581aa8564f0f6c707de8c6871088f823431cd6379f2504834a84c4b6c09210e2d35791292d6263b6ac8cecb08da60153c1f2a7ee8f48a46d97188be4e16324 - languageName: node - linkType: hard - -"regexpp@npm:^3.0.0, regexpp@npm:^3.1.0": +"regexpp@npm:^3.0.0": version: 3.2.0 resolution: "regexpp@npm:3.2.0" checksum: 10/3310010895a906873262f4b494fc99bcef1e71ef6720a0532c5999ca586498cbd4a284c8e3c2423f9d1d37512fd08d6064b7564e0e59508cf938f76dd15ace84 @@ -45050,13 +43982,6 @@ __metadata: languageName: node linkType: hard -"require-relative@npm:^0.8.7": - version: 0.8.7 - resolution: "require-relative@npm:0.8.7" - checksum: 10/f1c3be06977823bba43600344d9ea6fbf8a55bdb81ec76533126849ab4024e6c31c6666f37fa4b5cfeda9c41dee89b8e19597cac02bdefaab42255c6708661ab - languageName: node - linkType: hard - "require-uncached@npm:^1.0.2, require-uncached@npm:^1.0.3": version: 1.0.3 resolution: "require-uncached@npm:1.0.3" @@ -45509,17 +44434,6 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:2.6.3, rimraf@npm:~2.6.2": - version: 2.6.3 - resolution: "rimraf@npm:2.6.3" - dependencies: - glob: "npm:^7.1.3" - bin: - rimraf: ./bin.js - checksum: 10/756419f2fa99aa119c46a9fc03e09d84ecf5421a80a72d1944c5088c9e4671e77128527a900a313ed9d3fdbdd37e2ae05486cd7e9116d5812d8c31f2399d7c86 - languageName: node - linkType: hard - "rimraf@npm:^2.2.8, rimraf@npm:^2.6.1, rimraf@npm:^2.6.2, rimraf@npm:^2.6.3": version: 2.7.1 resolution: "rimraf@npm:2.7.1" @@ -45542,6 +44456,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:~2.6.2": + version: 2.6.3 + resolution: "rimraf@npm:2.6.3" + dependencies: + glob: "npm:^7.1.3" + bin: + rimraf: ./bin.js + checksum: 10/756419f2fa99aa119c46a9fc03e09d84ecf5421a80a72d1944c5088c9e4671e77128527a900a313ed9d3fdbdd37e2ae05486cd7e9116d5812d8c31f2399d7c86 + languageName: node + linkType: hard + "ripemd160-min@npm:0.0.6": version: 0.0.6 resolution: "ripemd160-min@npm:0.0.6" @@ -45694,15 +44619,6 @@ __metadata: languageName: node linkType: hard -"run-applescript@npm:^5.0.0": - version: 5.0.0 - resolution: "run-applescript@npm:5.0.0" - dependencies: - execa: "npm:^5.0.0" - checksum: 10/d00c2dbfa5b2d774de7451194b8b125f40f65fc183de7d9dcae97f57f59433586d3c39b9001e111c38bfa24c3436c99df1bb4066a2a0c90d39a8c4cd6889af77 - languageName: node - linkType: hard - "run-async@npm:^0.1.0": version: 0.1.0 resolution: "run-async@npm:0.1.0" @@ -45806,7 +44722,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^6.6.0, rxjs@npm:^6.6.3": +"rxjs@npm:^6.6.3": version: 6.6.7 resolution: "rxjs@npm:6.6.7" dependencies: @@ -46839,17 +45755,6 @@ __metadata: languageName: node linkType: hard -"sirv@npm:^1.0.7": - version: 1.0.19 - resolution: "sirv@npm:1.0.19" - dependencies: - "@polka/url": "npm:^1.0.0-next.20" - mrmime: "npm:^1.0.0" - totalist: "npm:^1.0.0" - checksum: 10/b6833ab4d41f5e449ffcb4d89caac45d97de4b246f984f9b9fa86a0107689562c22d24788b533a58a10cf2cfcebb7e6c678ffa84ac7d3392fca9d18b1bd7ee05 - languageName: node - linkType: hard - "sisteransi@npm:^1.0.5": version: 1.0.5 resolution: "sisteransi@npm:1.0.5" @@ -46908,17 +45813,6 @@ __metadata: languageName: node linkType: hard -"slice-ansi@npm:^2.1.0": - version: 2.1.0 - resolution: "slice-ansi@npm:2.1.0" - dependencies: - ansi-styles: "npm:^3.2.0" - astral-regex: "npm:^1.0.0" - is-fullwidth-code-point: "npm:^2.0.0" - checksum: 10/4e82995aa59cef7eb03ef232d73c2239a15efa0ace87a01f3012ebb942e963fbb05d448ce7391efcd52ab9c32724164aba2086f5143e0445c969221dde3b6b1e - languageName: node - linkType: hard - "slice-ansi@npm:^3.0.0": version: 3.0.0 resolution: "slice-ansi@npm:3.0.0" @@ -48416,7 +47310,7 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.0.1, strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": +"strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" checksum: 10/492f73e27268f9b1c122733f28ecb0e7e8d8a531a6662efbd08e22cccb3f9475e90a1b82cab06a392f6afae6d2de636f977e231296400d0ec5304ba70f166443 @@ -48811,16 +47705,6 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.8.5": - version: 0.8.5 - resolution: "synckit@npm:0.8.5" - dependencies: - "@pkgr/utils": "npm:^2.3.1" - tslib: "npm:^2.5.0" - checksum: 10/fb6798a2db2650ca3a2435ad32d4fc14842da807993a1a350b64d267e0e770aa7f26492b119aa7500892d3d07a5af1eec7bfbd6e23a619451558be0f226a6094 - languageName: node - linkType: hard - "synckit@npm:^0.8.6": version: 0.8.8 resolution: "synckit@npm:0.8.8" @@ -48859,44 +47743,6 @@ __metadata: languageName: node linkType: hard -"table@npm:^5.2.3": - version: 5.4.6 - resolution: "table@npm:5.4.6" - dependencies: - ajv: "npm:^6.10.2" - lodash: "npm:^4.17.14" - slice-ansi: "npm:^2.1.0" - string-width: "npm:^3.0.0" - checksum: 10/a00b96779fdeae58fc8b2b10ca7a1dcb81d4a14d1511b2f0202e1ef4ea890ca4d2730cc9b78f399254b9a641458e4897c639079d57dfb7d6726997dd8735a6c3 - languageName: node - linkType: hard - -"table@npm:^6.0.4": - version: 6.8.1 - resolution: "table@npm:6.8.1" - dependencies: - ajv: "npm:^8.0.1" - lodash.truncate: "npm:^4.4.2" - slice-ansi: "npm:^4.0.0" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - checksum: 10/512c4f2bfb6f46f4d5ced19943ae5db1a5163eac1f23ce752625eb49715f84217c1c62bc2d017eb8985b37e0f85731108f654df809c0b34cca1678a672e7ea20 - languageName: node - linkType: hard - -"table@npm:^6.0.9": - version: 6.8.0 - resolution: "table@npm:6.8.0" - dependencies: - ajv: "npm:^8.0.1" - lodash.truncate: "npm:^4.4.2" - slice-ansi: "npm:^4.0.0" - string-width: "npm:^4.2.3" - strip-ansi: "npm:^6.0.1" - checksum: 10/4c2b8ebd75f36db236529680c70f41951c9c7fda3e65cb5b987164244f23f98670ded99983fdc5d62aa02405a212e90f7446efcf87e3435e472dda26d6581645 - languageName: node - linkType: hard - "tablemark@npm:^3.0.0": version: 3.0.0 resolution: "tablemark@npm:3.0.0" @@ -49559,13 +48405,6 @@ __metadata: languageName: node linkType: hard -"titleize@npm:^3.0.0": - version: 3.0.0 - resolution: "titleize@npm:3.0.0" - checksum: 10/71fbbeabbfb36ccd840559f67f21e356e1d03da2915b32d2ae1a60ddcc13a124be2739f696d2feb884983441d159a18649e8d956648d591bdad35c430a6b6d28 - languageName: node - linkType: hard - "tls-browserify@npm:0.2.2": version: 0.2.2 resolution: "tls-browserify@npm:0.2.2" @@ -49675,13 +48514,6 @@ __metadata: languageName: node linkType: hard -"totalist@npm:^1.0.0": - version: 1.1.0 - resolution: "totalist@npm:1.1.0" - checksum: 10/dfab80c7104a1d170adc8c18782d6c04b7df08352dec452191208c66395f7ef2af7537ddfa2cf1decbdcfab1a47afbbf0dec6543ea191da98c1c6e1599f86adc - languageName: node - linkType: hard - "touch@npm:^3.1.0": version: 3.1.0 resolution: "touch@npm:3.1.0" @@ -50058,13 +48890,6 @@ __metadata: languageName: node linkType: hard -"tslib@npm:1.9.0": - version: 1.9.0 - resolution: "tslib@npm:1.9.0" - checksum: 10/3fb8dc249b5db6ff16289c1d6bf238996ff25b01c5f56db6559352ff17854d29a755d3cb4769074bf9be55dd0960aaacdf6650e07bcb6775d98b965a6c304792 - languageName: node - linkType: hard - "tslib@npm:2.0.3": version: 2.0.3 resolution: "tslib@npm:2.0.3" @@ -50093,14 +48918,14 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.6.2, tslib@npm:^2.5.0, tslib@npm:^2.5.3, tslib@npm:^2.6.0, tslib@npm:^2.6.1, tslib@npm:^2.6.2": +"tslib@npm:2.6.2, tslib@npm:^2.5.0, tslib@npm:^2.5.3, tslib@npm:^2.6.1, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 10/bd26c22d36736513980091a1e356378e8b662ded04204453d353a7f34a4c21ed0afc59b5f90719d4ba756e581a162ecbf93118dc9c6be5acf70aa309188166ca languageName: node linkType: hard -"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.8.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": +"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 10/7dbf34e6f55c6492637adb81b555af5e3b4f9cc6b998fb440dac82d3b42bdc91560a35a5fb75e20e24a076c651438234da6743d139e4feabf0783f3cdfe1dddb @@ -50128,63 +48953,6 @@ __metadata: languageName: node linkType: hard -"tslint-config-prettier@npm:1.18.0": - version: 1.18.0 - resolution: "tslint-config-prettier@npm:1.18.0" - bin: - tslint-config-prettier-check: bin/check.js - checksum: 10/f0c548a7a520f9247f8e4ddba1136f300d1b2ec48a8255b030c05e35866cc22c105d9120540dd5ee82e2a04a769d82f5d098b7eaf6928820f6dba1badad6704c - languageName: node - linkType: hard - -"tslint-config-standard@npm:8.0.1": - version: 8.0.1 - resolution: "tslint-config-standard@npm:8.0.1" - dependencies: - tslint-eslint-rules: "npm:^5.3.1" - checksum: 10/38ccb6a85866cb92742750e687a87fbc100c9310909d1fad48cb915b219519787bc61b62867b3e313020e5ac1ff06849f38790eefca10a524bf2ad27afc14af5 - languageName: node - linkType: hard - -"tslint-eslint-rules@npm:^5.3.1": - version: 5.4.0 - resolution: "tslint-eslint-rules@npm:5.4.0" - dependencies: - doctrine: "npm:0.7.2" - tslib: "npm:1.9.0" - tsutils: "npm:^3.0.0" - peerDependencies: - tslint: ^5.0.0 - typescript: ^2.2.0 || ^3.0.0 - checksum: 10/603cb951c71a54a694cbb46c680bfd7ae734eb02263567fb6b88b8b9ad8d56b07be473d031d379bfaa41e4a2abbb77dfd836d55899892a7dd967969175cc9756 - languageName: node - linkType: hard - -"tslint@npm:5.20.1": - version: 5.20.1 - resolution: "tslint@npm:5.20.1" - dependencies: - "@babel/code-frame": "npm:^7.0.0" - builtin-modules: "npm:^1.1.1" - chalk: "npm:^2.3.0" - commander: "npm:^2.12.1" - diff: "npm:^4.0.1" - glob: "npm:^7.1.1" - js-yaml: "npm:^3.13.1" - minimatch: "npm:^3.0.4" - mkdirp: "npm:^0.5.1" - resolve: "npm:^1.3.2" - semver: "npm:^5.3.0" - tslib: "npm:^1.8.0" - tsutils: "npm:^2.29.0" - peerDependencies: - typescript: ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev" - bin: - tslint: ./bin/tslint - checksum: 10/9cfcec0330beeb99ab67b5c6ec40fd182973841a1ebbc6a0ea266d7203efda4db9c615e433282ce6fcd0b8d2a5f1836a821d25a39c5f24f835bfc2a37908543f - languageName: node - linkType: hard - "tslint@npm:6.1.3": version: 6.1.3 resolution: "tslint@npm:6.1.3" @@ -50228,7 +48996,7 @@ __metadata: languageName: node linkType: hard -"tsutils@npm:^3.0.0, tsutils@npm:^3.17.1, tsutils@npm:^3.21.0": +"tsutils@npm:^3.21.0": version: 3.21.0 resolution: "tsutils@npm:3.21.0" dependencies: @@ -50707,16 +49475,6 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^3.9.3": - version: 3.9.10 - resolution: "typescript@npm:3.9.10" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10/f86a085eea24fdd665850c6be4dd69c7a71fe3d27ecc712be88cdc7a52d866f4f2416ad91c554df60f499dedcf288a24b3d8052e502833d8acc661a9d21bb98f - languageName: node - linkType: hard - "typescript@patch:typescript@npm%3A5.2.2#optional!builtin, typescript@patch:typescript@npm%3A^4.6.4 || ^5.0.0#optional!builtin": version: 5.2.2 resolution: "typescript@patch:typescript@npm%3A5.2.2#optional!builtin::version=5.2.2&hash=f3b441" @@ -50737,16 +49495,6 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^3.9.3#optional!builtin": - version: 3.9.10 - resolution: "typescript@patch:typescript@npm%3A3.9.10#optional!builtin::version=3.9.10&hash=3bd3d3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10/77024c200e1f80d95185d5a973bcc4b0ecc12a77851390b1382e372195313769373a4b8b1642df4a8d4ae1df5911dcd9bde111cf6755eb4b6091f374e97c6dc5 - languageName: node - linkType: hard - "ubiquity-ts-client-renovated@npm:1.0.0": version: 1.0.0 resolution: "ubiquity-ts-client-renovated@npm:1.0.0" @@ -51078,13 +49826,6 @@ __metadata: languageName: node linkType: hard -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: 10/39ced9c418a74f73f0a56e1ba4634b4d959422dff61f4c72a8e39f60b99380c1b45ed776fbaa0a4101b157e4310d873ad7d114e8534ca02609b4916bb4187fb9 - languageName: node - linkType: hard - "upath@npm:^1.2.0": version: 1.2.0 resolution: "upath@npm:1.2.0" @@ -51476,13 +50217,6 @@ __metadata: languageName: node linkType: hard -"v8-compile-cache@npm:^2.0.3": - version: 2.3.0 - resolution: "v8-compile-cache@npm:2.3.0" - checksum: 10/7de7423db6f48d76cffae93d70d503e160c97fc85e55945036d719111e20b33c4be5c21aa8b123a3da203bbb3bc4c8180f9667d5ccafcff11d749fae204ec7be - languageName: node - linkType: hard - "v8-to-istanbul@npm:^8.1.0": version: 8.1.1 resolution: "v8-to-istanbul@npm:8.1.1" @@ -51794,22 +50528,6 @@ __metadata: languageName: node linkType: hard -"vue-eslint-parser@npm:~7.1.0": - version: 7.1.1 - resolution: "vue-eslint-parser@npm:7.1.1" - dependencies: - debug: "npm:^4.1.1" - eslint-scope: "npm:^5.0.0" - eslint-visitor-keys: "npm:^1.1.0" - espree: "npm:^6.2.1" - esquery: "npm:^1.0.1" - lodash: "npm:^4.17.15" - peerDependencies: - eslint: ">=5.0.0" - checksum: 10/b7efa48a5c84ef21acc95674b06e974d66e3a8b4ec0acd76a529eac697253ae8eafa5f3aff166256630d6f401b012c6b2fe0310e501ee037b6a60985e6f84362 - languageName: node - linkType: hard - "vuvuzela@npm:1.0.3": version: 1.0.3 resolution: "vuvuzela@npm:1.0.3" @@ -54598,26 +53316,6 @@ __metadata: languageName: node linkType: hard -"webpack-bundle-analyzer@npm:4.9.0": - version: 4.9.0 - resolution: "webpack-bundle-analyzer@npm:4.9.0" - dependencies: - "@discoveryjs/json-ext": "npm:0.5.7" - acorn: "npm:^8.0.4" - acorn-walk: "npm:^8.0.0" - chalk: "npm:^4.1.0" - commander: "npm:^7.2.0" - gzip-size: "npm:^6.0.0" - lodash: "npm:^4.17.20" - opener: "npm:^1.5.2" - sirv: "npm:^1.0.7" - ws: "npm:^7.3.1" - bin: - webpack-bundle-analyzer: lib/bin/analyzer.js - checksum: 10/bd1a7b431b6cf0e8c7582531ad340eb299d93fe3268d980d040df92f9383fe4fe0820032334390941e8deccd370a023a96abb393808e39c7e0855efb5b4987c8 - languageName: node - linkType: hard - "webpack-cli@npm:4.10.0": version: 4.10.0 resolution: "webpack-cli@npm:4.10.0" @@ -55228,7 +53926,7 @@ __metadata: languageName: node linkType: hard -"word-wrap@npm:^1.2.3, word-wrap@npm:~1.2.3": +"word-wrap@npm:~1.2.3": version: 1.2.3 resolution: "word-wrap@npm:1.2.3" checksum: 10/08a677e1578b9cc367a03d52bc51b6869fec06303f68d29439e4ed647257411f857469990c31066c1874678937dac737c9f8f20d3fd59918fb86b7d926a76b15 @@ -55613,15 +54311,6 @@ __metadata: languageName: node linkType: hard -"write@npm:1.0.3": - version: 1.0.3 - resolution: "write@npm:1.0.3" - dependencies: - mkdirp: "npm:^0.5.1" - checksum: 10/abb3a249df922dbd4060d4cab5017b6c07268523d6b3d8c933a7f64afe3078c58507543e4b830065ea02beb8ab25e40dc2f8be8eea5cdfc08d91e89e65e952b5 - languageName: node - linkType: hard - "write@npm:^0.2.1": version: 0.2.1 resolution: "write@npm:0.2.1" @@ -55756,7 +54445,7 @@ __metadata: languageName: node linkType: hard -"ws@npm:^7.3.1, ws@npm:^7.4.6": +"ws@npm:^7.4.6": version: 7.5.7 resolution: "ws@npm:7.5.7" peerDependencies: