diff --git a/examples/cactus-workshop-examples-2022-11-14/README.md b/examples/cactus-workshop-examples-2022-11-14/README.md new file mode 100644 index 00000000000..8afdc158d27 --- /dev/null +++ b/examples/cactus-workshop-examples-2022-11-14/README.md @@ -0,0 +1,65 @@ +# Hyperledger Cacti Workshop 2022-11-14 Examples + +This folder contains several simple examples using different components of Hyperledger Cacti that are used in the first Hyperledger workshop dedicated to interoperability, using Cacti: https://wiki.hyperledger.org/display/events/Blockchain+Interoperability+with+Hyperledger+Cacti + +## Hyperledger Cacti Workshop Examples - Hello World +WARNING: This code IS NOT production-ready nor secure! Namely, cross-site scripting is possible if user input is not sanitized. + +``src/main/typescript/hello-world.ts`` + +Creates an APIServer listening on port 3001 that exposes the endpoints of the ingested plugins - for demonstration purposes we use only one plugin, the cactus-plugin-object-store-ipfs. This plugin interacts with an underlying IPFS network (a simple key-value store). + +Run the file with the following command ``npx ts-node src/main/typescript/hello-world.ts`` + +To interact with the IPFS connector through the APIServer follow the next commands: +- POST `/api/v1/plugins/@hyperledger/cactus-plugin-object-store-ipfs/set-object`, which sets a new key-value pair. + ``` + curl --header "Content-Type: application/json" \ + --request POST \ + --data '{"key":"1234","value":"xyz"}' \ + http://localhost:3001/api/v1/plugins/@hyperledger/cactus-plugin-object-store-ipfs/set-object + ``` + +- POST `/api/v1/plugins/@hyperledger/cactus-plugin-object-store-ipfs/get-object`, which gets a key-value pair. + ``` + curl --header "Content-Type: application/json" \ + --request POST \ + --data '{"key":"1234"}' \ + http://localhost:3001/api/v1/plugins/@hyperledger/cactus-plugin-object-store-ipfs/get-object + ``` + +- GET "/has-key/:key", which checks if a key-value pair exits in the client. + ``` + curl --header "Content-Type: application/json" \ + --request POST \ + --data '{"key":"1234"}' \ + http://localhost:3001/api/v1/plugins/@hyperledger/cactus-plugin-object-store-ipfs/has-object + ``` + +*NOTE: other carachters might appear in the output of the commands since we should insert the values in base64. For demo purposes we don't make the conversion.* + +## Hyperledger Cacti Workshop Examples - Simple Consortium + +``src/main/typescript/test-ledger.ts`` + +Creates a simple Cacti Consortium. + +Runs with the following command ``npx ts-node src/main/typescript/simple-consortium.ts`` + +## Hyperledger Cacti Workshop Examples - Substrate test ledger + +``src/main/typescript/test-ledger.ts`` + +Creates a substrate test ledger programmatically. + +Runs with the following command ``npx ts-node src/main/typescript/test-ledger.ts`` + +## Known issues +This example package works with version 1.0.0 of ``@hyperledger/cactus-test-tooling``. It will work with the most recent version once #2213 is resolved. + +## Authors + +- Rafael Belchior +- Mónica Gomez +- Abhinav Srivastava +- André Augusto \ No newline at end of file diff --git a/examples/cactus-workshop-examples-2022-11-14/package.json b/examples/cactus-workshop-examples-2022-11-14/package.json new file mode 100644 index 00000000000..be4774cc60e --- /dev/null +++ b/examples/cactus-workshop-examples-2022-11-14/package.json @@ -0,0 +1,73 @@ +{ + "name": "@hyperledger/cactus-workshop-examples-2022-11-14", + "version": "1.1.2", + "description": "Cacti Workshop 2022-11-14 Examples", + "keywords": [ + "Hyperledger", + "Cactus", + "Integration", + "Blockchain", + "Distributed Ledger Technology" + ], + "homepage": "https://github.com/hyperledger/cactus#readme", + "bugs": { + "url": "https://github.com/hyperledger/cactus/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger/cactus.git" + }, + "license": "Apache-2.0", + "author": { + "name": "Hyperledger Cactus Contributors", + "email": "cactus@lists.hyperledger.org", + "url": "https://www.hyperledger.org/use/cactus" + }, + "contributors": [ + { + "name": "Please add yourself to the list of contributors", + "email": "your.name@example.com", + "url": "https://example.com" + }, + { + "name": "Rafael Belchior", + "email": "rbelchior@blockdaemon.com" + }, + { + "name": "Mónica Gomez", + "email": "monica.gomez@tecnico.ulisboa.pt" + } + ], + "main": "dist/lib/main/typescript/index.js", + "module": "dist/lib/main/typescript/index.js", + "browser": "dist/cactus-workshop-examples-2022-11-14.web.umd.js", + "types": "dist/lib/main/typescript/index.d.ts", + "files": [ + "dist/*" + ], + "scripts": { + "watch": "npm-watch", + "webpack": "npm-run-all webpack:dev", + "webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web", + "webpack:dev:node": "webpack --env=dev --target=node --config ../../../webpack.config.js", + "webpack:dev:web": "webpack --env=dev --target=web --config ../../../webpack.config.js" + }, + "dependencies": { + "@hyperledger/cactus-common": "1.1.2", + "@hyperledger/cactus-core": "1.1.2", + "@hyperledger/cactus-test-tooling": "1.1.2", + "typescript-optional": "2.0.1" + }, + "devDependencies": { + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "publishConfig": { + "access": "public" + }, + "browserMinified": "dist/cactus-workshop-examples-2022-11-14.web.umd.min.js", + "mainMinified": "dist/cactus-workshop-examples-2022-11-14.node.umd.min.js", + "watch": {} +} diff --git a/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/hello-world.ts b/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/hello-world.ts new file mode 100644 index 00000000000..04b7ab48cf0 --- /dev/null +++ b/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/hello-world.ts @@ -0,0 +1,79 @@ +// WARNING: This code IS NOT production-ready nor secure! Namely, cross-site scripting is possible if user input is not sanitized. +import { ApiServer, ConfigService } from "@hyperledger/cactus-cmd-api-server"; +import { Logger, LoggerProvider } from "@hyperledger/cactus-common"; +import { GoIpfsTestContainer } from "@hyperledger/cactus-test-tooling"; +import { create } from "ipfs-http-client"; +import { createServer } from "http"; +import { v4 as uuidv4 } from "uuid"; +import { + PluginImportAction, + PluginImportType, +} from "@hyperledger/cactus-core-api"; + +const log: Logger = LoggerProvider.getOrCreate({ + label: "cacti-node-test-app", + level: "info", +}); + +const main = async () => { + // start an IPFS network (a key-value store) for demonstration purposes + const ipfsNetwork = new GoIpfsTestContainer({}); + await ipfsNetwork.start(); + + // retrieve the url so that the IPFS connector plugin is + // able to connect to the IPFS network. This will be used + // as an argument for the plugin bellow + const ipfsClientOrOptions = create({ + url: await ipfsNetwork.getApiUrl(), + }); + + //Configuring APIServer + const configService = new ConfigService(); + const apiServerOptions: any = await configService.newExampleConfig(); + apiServerOptions.configFile = ""; + apiServerOptions.authorizationProtocol = "NONE"; + + //The port where the APIServer will be listening + apiServerOptions.apiPort = 3001; + apiServerOptions.cockpitPort = 3100; + apiServerOptions.grpcPort = 5000; + apiServerOptions.apiTlsEnabled = false; //Disable TLS (or provide TLS certs for secure HTTP if you are deploying to production) + apiServerOptions.plugins = [ + //add plugins that will be exposed by the API Server + { + packageName: "@hyperledger/cactus-plugin-object-store-ipfs", + type: PluginImportType.Remote, + action: PluginImportAction.Install, + options: { + parentDir: `/${uuidv4()}/${uuidv4()}/`, + logLevel: "DEBUG", + instanceId: uuidv4(), + ipfsClientOrOptions, + }, + }, + ]; + + const config = await configService.newExampleConfigConvict(apiServerOptions); + + const apiServer = new ApiServer({ + httpServerApi: createServer(), + config: config.getProperties(), + }); + + //Starting the Cacti APIServer + apiServer.start(); +}; + +export async function launchApp(): Promise { + try { + await main(); + log.info(`Cacti Hello World example ran OK `); + } catch (ex) { + log.error(`Cacti Hello World example crashed: `, ex); + process.exit(1); + } +} + +if (require.main === module) { + launchApp(); +} diff --git a/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/simple-consortium.ts b/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/simple-consortium.ts new file mode 100644 index 00000000000..39ff67f3a54 --- /dev/null +++ b/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/simple-consortium.ts @@ -0,0 +1,42 @@ +import { + LogLevelDesc, + Logger, + LoggerProvider, +} from "@hyperledger/cactus-common"; + +import { + ConsortiumRepository, + IConsortiumRepositoryOptions, +} from "@hyperledger/cactus-core"; +import { ConsortiumDatabase } from "@hyperledger/cactus-core-api"; + +const logLevelConsortium: LogLevelDesc = "INFO"; +const loggerLevel: LogLevelDesc = "INFO"; + +async function runHelloWorld() { + const logger: Logger = LoggerProvider.getOrCreate({ + label: "test-deploy-contract-via-web-service", + level: loggerLevel, + }); + + logger.info("Initialized logger"); + const consortiumDB: ConsortiumDatabase = { + consortium: [], + ledger: [], + consortiumMember: [], + cactusNode: [], + pluginInstance: [], + }; + + const consortiumOptions: IConsortiumRepositoryOptions = { + logLevel: logLevelConsortium, + db: consortiumDB, + }; + const consortiumRepo = new ConsortiumRepository(consortiumOptions); + + logger.info(`Initialized consortium: ${consortiumRepo}`); + + logger.info("Done"); +} + +runHelloWorld(); diff --git a/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/test-ledger.ts b/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/test-ledger.ts new file mode 100644 index 00000000000..f56fd2151b7 --- /dev/null +++ b/examples/cactus-workshop-examples-2022-11-14/src/main/typescript/test-ledger.ts @@ -0,0 +1,49 @@ +import { + LogLevelDesc, + Logger, + LoggerProvider, +} from "@hyperledger/cactus-common"; +import { + SubstrateTestLedger, + ISubstrateTestLedgerOptions, +} from "@hyperledger/cactus-test-tooling"; + +const logLevelLedger: LogLevelDesc = "DEBUG"; +const loggerLevel: LogLevelDesc = "INFO"; + +async function testLedger() { + const logger: Logger = LoggerProvider.getOrCreate({ + label: "test-deploy-contract-via-web-service", + level: loggerLevel, + }); + + logger.info("Initialized logger"); + + logger.info("Creating ledger"); + const ledgerOps: ISubstrateTestLedgerOptions = { + publishAllPorts: false, + logLevel: logLevelLedger, + emitContainerLogs: true, + imageTag: "2022-03-29--1496", + envVars: new Map([ + ["WORKING_DIR", "/var/www/node-template"], + ["CONTAINER_NAME", "cacti-ledger"], + ["WS_PORT", "9944"], + ["PORT", "9944"], + ["DOCKER_PORT", "9944"], + ["CARGO_HOME", "/var/www/node-template/.cargo"], + ]), + }; + + const ledger = new SubstrateTestLedger(ledgerOps); + await ledger.start(); + + logger.info("Ledger up and running"); + + logger.info("Destroying ledger"); + await ledger.stop(); + + logger.info("Done"); +} + +testLedger(); diff --git a/examples/cactus-workshop-examples-2022-11-14/tsconfig.json b/examples/cactus-workshop-examples-2022-11-14/tsconfig.json new file mode 100644 index 00000000000..ee17492afef --- /dev/null +++ b/examples/cactus-workshop-examples-2022-11-14/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist/lib/", + "declarationDir": "dist/lib", + "rootDir": "./src", + "tsBuildInfoFile": "../../.build-cache/cactus-workshop-examples-2022-11-14.tsbuildinfo" + }, + "include": [ + "./src", + "src/**/*.json" + ], + "references": [ + { + "path": "../../packages/cactus-common/tsconfig.json" + }, + { + "path": "../../packages/cactus-core/tsconfig.json" + }, + { + "path": "../../packages/cactus-test-tooling/tsconfig.json" + } + ] +} \ No newline at end of file