diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml
new file mode 100644
index 0000000000..e9c9c87e27
--- /dev/null
+++ b/.github/workflows/deploy_docs.yml
@@ -0,0 +1,36 @@
+# Copyright IBM Corp. All Rights Reserved.
+#
+# SPDX-License-Identifier: CC-BY-4.0
+
+name: Deploy Docs (Github Pages)
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'docs/**'
+
+ # Allows you to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+jobs:
+ deploy-docs:
+ runs-on: ubuntu-latest
+ steps:
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v3
+
+ - name: Use Python 3.x
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.10'
+ cache: 'pip' # caching pip dependencies
+
+ - name: Install dependencies
+ run: pip install -r requirements.txt
+ working-directory: docs
+
+ - name: Build and publish
+ run: git pull && mkdocs gh-deploy
+ working-directory: docs
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 8b0df3264f..56757e9229 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -6,17 +6,17 @@ Maintainers
| Name | GitHub | Chat |
|------|--------|------|
| Jonathan Hamilton | [jonathan-m-hamilton][jonathan-m-hamilton] | JHamilton |
-| Izuru Sato | [izuru0][izuru0] | Izuru Sato#6434 |
-| Peter Somogyvari | [petermetz][petermetz] | peter_somogyvari#3365 |
-| Takuma TAKEUCHI | [takeutak][takeutak] | takeutak#7220 |
+| Izuru Sato | [izuru0][izuru0] | izurusato |
+| Peter Somogyvari | [petermetz][petermetz] | peter_somogyvari |
+| Takuma TAKEUCHI | [takeutak][takeutak] | takeutak |
| Jagpreet Singh Sasan | [jagpreetsinghsasan][jagpreetsinghsasan] | jagpreetsinghsasan |
-| Venkatraman Ramakrishna | [VRamakrishna][VRamakrishna] | Ramakrishna#6645 |
-| Sandeep Nishad | [sandeepnRES][sandeepnRES] | sandeepn#1092 |
+| Venkatraman Ramakrishna | [VRamakrishna][VRamakrishna] | vramaiitkgp |
+| Sandeep Nishad | [sandeepnRES][sandeepnRES] | sandeepn |
[jonathan-m-hamilton]: https://github.com/jonathan-m-hamilton
[izuru0]: https://github.com/izuru0
[petermetz]: https://github.com/petermetz
[takeutak]: https://github.com/takeutak
[jagpreetsinghsasan]: https://github.com/jagpreetsinghsasan
-[VRamakrishna]: https://github.com/VRamakrishna/
-[sandeepnRES]: https://github.com/sandeepnRES
\ No newline at end of file
+[VRamakrishna]: https://github.com/VRamakrishna
+[sandeepnRES]: https://github.com/sandeepnRES
diff --git a/docs/Makefile b/docs-cactus/Makefile
similarity index 100%
rename from docs/Makefile
rename to docs-cactus/Makefile
diff --git a/docs-cactus/README.md b/docs-cactus/README.md
new file mode 100644
index 0000000000..871d1ade6c
--- /dev/null
+++ b/docs-cactus/README.md
@@ -0,0 +1,7 @@
+### Building the docs
+```sh
+pip install -U Sphinx
+pip install -r pip-requirements.txt
+make html
+```
+Access the documents from **build/html/** folder.
\ No newline at end of file
diff --git a/docs/architecture/class-diagram.puml b/docs-cactus/architecture/class-diagram.puml
similarity index 100%
rename from docs/architecture/class-diagram.puml
rename to docs-cactus/architecture/class-diagram.puml
diff --git a/docs/architecture/component-diagram.puml b/docs-cactus/architecture/component-diagram.puml
similarity index 100%
rename from docs/architecture/component-diagram.puml
rename to docs-cactus/architecture/component-diagram.puml
diff --git a/docs/architecture/deployment-diagram.puml b/docs-cactus/architecture/deployment-diagram.puml
similarity index 100%
rename from docs/architecture/deployment-diagram.puml
rename to docs-cactus/architecture/deployment-diagram.puml
diff --git a/docs/architecture/document-storage/document-storage-deployment-diagram.puml b/docs-cactus/architecture/document-storage/document-storage-deployment-diagram.puml
similarity index 100%
rename from docs/architecture/document-storage/document-storage-deployment-diagram.puml
rename to docs-cactus/architecture/document-storage/document-storage-deployment-diagram.puml
diff --git a/docs/architecture/routing-to-api-servers-deployment-diagram.puml b/docs-cactus/architecture/routing-to-api-servers-deployment-diagram.puml
similarity index 100%
rename from docs/architecture/routing-to-api-servers-deployment-diagram.puml
rename to docs-cactus/architecture/routing-to-api-servers-deployment-diagram.puml
diff --git a/docs/architecture/routing-to-plugin-instances-deployment-diagram.puml b/docs-cactus/architecture/routing-to-plugin-instances-deployment-diagram.puml
similarity index 100%
rename from docs/architecture/routing-to-plugin-instances-deployment-diagram.puml
rename to docs-cactus/architecture/routing-to-plugin-instances-deployment-diagram.puml
diff --git a/docs/architecture/sequence-diagram-transaction.puml b/docs-cactus/architecture/sequence-diagram-transaction.puml
similarity index 100%
rename from docs/architecture/sequence-diagram-transaction.puml
rename to docs-cactus/architecture/sequence-diagram-transaction.puml
diff --git a/docs/htlc-coordinator-alice-flow.md b/docs-cactus/htlc-coordinator-alice-flow.md
similarity index 100%
rename from docs/htlc-coordinator-alice-flow.md
rename to docs-cactus/htlc-coordinator-alice-flow.md
diff --git a/docs/htlc-coordinator-bob-flow.md b/docs-cactus/htlc-coordinator-bob-flow.md
similarity index 100%
rename from docs/htlc-coordinator-bob-flow.md
rename to docs-cactus/htlc-coordinator-bob-flow.md
diff --git a/docs/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif b/docs-cactus/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif
similarity index 100%
rename from docs/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif
rename to docs-cactus/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif
diff --git a/docs/images/blockchain-integration-framework-high-level-workflow.png b/docs-cactus/images/blockchain-integration-framework-high-level-workflow.png
similarity index 100%
rename from docs/images/blockchain-integration-framework-high-level-workflow.png
rename to docs-cactus/images/blockchain-integration-framework-high-level-workflow.png
diff --git a/docs/images/build-script-decision-tree-2021-03-06.odp b/docs-cactus/images/build-script-decision-tree-2021-03-06.odp
similarity index 100%
rename from docs/images/build-script-decision-tree-2021-03-06.odp
rename to docs-cactus/images/build-script-decision-tree-2021-03-06.odp
diff --git a/docs/images/build-script-decision-tree-2021-03-06.png b/docs-cactus/images/build-script-decision-tree-2021-03-06.png
similarity index 100%
rename from docs/images/build-script-decision-tree-2021-03-06.png
rename to docs-cactus/images/build-script-decision-tree-2021-03-06.png
diff --git a/docs/make.bat b/docs-cactus/make.bat
similarity index 100%
rename from docs/make.bat
rename to docs-cactus/make.bat
diff --git a/docs/manual-of-auto-testing-codes.md b/docs-cactus/manual-of-auto-testing-codes.md
similarity index 100%
rename from docs/manual-of-auto-testing-codes.md
rename to docs-cactus/manual-of-auto-testing-codes.md
diff --git a/docs/meta/guidelines-for-documentation-authors.md b/docs-cactus/meta/guidelines-for-documentation-authors.md
similarity index 100%
rename from docs/meta/guidelines-for-documentation-authors.md
rename to docs-cactus/meta/guidelines-for-documentation-authors.md
diff --git a/docs/pip-requirements.txt b/docs-cactus/pip-requirements.txt
similarity index 100%
rename from docs/pip-requirements.txt
rename to docs-cactus/pip-requirements.txt
diff --git a/docs/source/build.md b/docs-cactus/source/build.md
similarity index 100%
rename from docs/source/build.md
rename to docs-cactus/source/build.md
diff --git a/docs/source/code-of-conduct.md b/docs-cactus/source/code-of-conduct.md
similarity index 100%
rename from docs/source/code-of-conduct.md
rename to docs-cactus/source/code-of-conduct.md
diff --git a/docs/source/conf.py b/docs-cactus/source/conf.py
similarity index 100%
rename from docs/source/conf.py
rename to docs-cactus/source/conf.py
diff --git a/docs/source/contributing.md b/docs-cactus/source/contributing.md
similarity index 100%
rename from docs/source/contributing.md
rename to docs-cactus/source/contributing.md
diff --git a/docs/source/examples.rst b/docs-cactus/source/examples.rst
similarity index 100%
rename from docs/source/examples.rst
rename to docs-cactus/source/examples.rst
diff --git a/docs/source/examples/supply-chain-app.md b/docs-cactus/source/examples/supply-chain-app.md
similarity index 100%
rename from docs/source/examples/supply-chain-app.md
rename to docs-cactus/source/examples/supply-chain-app.md
diff --git a/docs/source/governance.md b/docs-cactus/source/governance.md
similarity index 100%
rename from docs/source/governance.md
rename to docs-cactus/source/governance.md
diff --git a/docs/source/index.rst b/docs-cactus/source/index.rst
similarity index 100%
rename from docs/source/index.rst
rename to docs-cactus/source/index.rst
diff --git a/docs/source/investigations/1036_evm-nonce-manager.md b/docs-cactus/source/investigations/1036_evm-nonce-manager.md
similarity index 100%
rename from docs/source/investigations/1036_evm-nonce-manager.md
rename to docs-cactus/source/investigations/1036_evm-nonce-manager.md
diff --git a/docs/source/maintainers.md b/docs-cactus/source/maintainers.md
similarity index 100%
rename from docs/source/maintainers.md
rename to docs-cactus/source/maintainers.md
diff --git a/docs/source/packages.rst b/docs-cactus/source/packages.rst
similarity index 100%
rename from docs/source/packages.rst
rename to docs-cactus/source/packages.rst
diff --git a/docs/source/packages/business-logic-plugin.md b/docs-cactus/source/packages/business-logic-plugin.md
similarity index 100%
rename from docs/source/packages/business-logic-plugin.md
rename to docs-cactus/source/packages/business-logic-plugin.md
diff --git a/docs/source/packages/cactus-api-client.md b/docs-cactus/source/packages/cactus-api-client.md
similarity index 100%
rename from docs/source/packages/cactus-api-client.md
rename to docs-cactus/source/packages/cactus-api-client.md
diff --git a/docs/source/packages/cactus-cmd-api-server.md b/docs-cactus/source/packages/cactus-cmd-api-server.md
similarity index 100%
rename from docs/source/packages/cactus-cmd-api-server.md
rename to docs-cactus/source/packages/cactus-cmd-api-server.md
diff --git a/docs/source/packages/cactus-cockpit.md b/docs-cactus/source/packages/cactus-cockpit.md
similarity index 100%
rename from docs/source/packages/cactus-cockpit.md
rename to docs-cactus/source/packages/cactus-cockpit.md
diff --git a/docs/source/packages/cactus-common.md b/docs-cactus/source/packages/cactus-common.md
similarity index 100%
rename from docs/source/packages/cactus-common.md
rename to docs-cactus/source/packages/cactus-common.md
diff --git a/docs/source/packages/cactus-core-api.md b/docs-cactus/source/packages/cactus-core-api.md
similarity index 100%
rename from docs/source/packages/cactus-core-api.md
rename to docs-cactus/source/packages/cactus-core-api.md
diff --git a/docs/source/packages/cactus-core.md b/docs-cactus/source/packages/cactus-core.md
similarity index 100%
rename from docs/source/packages/cactus-core.md
rename to docs-cactus/source/packages/cactus-core.md
diff --git a/docs/source/packages/cactus-plugin-consortium-manual.md b/docs-cactus/source/packages/cactus-plugin-consortium-manual.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-consortium-manual.md
rename to docs-cactus/source/packages/cactus-plugin-consortium-manual.md
diff --git a/docs/source/packages/cactus-plugin-keychain-memory.md b/docs-cactus/source/packages/cactus-plugin-keychain-memory.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-keychain-memory.md
rename to docs-cactus/source/packages/cactus-plugin-keychain-memory.md
diff --git a/docs/source/packages/cactus-plugin-keychain-vault.md b/docs-cactus/source/packages/cactus-plugin-keychain-vault.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-keychain-vault.md
rename to docs-cactus/source/packages/cactus-plugin-keychain-vault.md
diff --git a/docs/source/packages/cactus-plugin-ledger-connector-besu.md b/docs-cactus/source/packages/cactus-plugin-ledger-connector-besu.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-ledger-connector-besu.md
rename to docs-cactus/source/packages/cactus-plugin-ledger-connector-besu.md
diff --git a/docs/source/packages/cactus-plugin-ledger-connector-corda.md b/docs-cactus/source/packages/cactus-plugin-ledger-connector-corda.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-ledger-connector-corda.md
rename to docs-cactus/source/packages/cactus-plugin-ledger-connector-corda.md
diff --git a/docs/source/packages/cactus-plugin-ledger-connector-fabric.md b/docs-cactus/source/packages/cactus-plugin-ledger-connector-fabric.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-ledger-connector-fabric.md
rename to docs-cactus/source/packages/cactus-plugin-ledger-connector-fabric.md
diff --git a/docs/source/packages/cactus-plugin-ledger-connector-quorum.md b/docs-cactus/source/packages/cactus-plugin-ledger-connector-quorum.md
similarity index 100%
rename from docs/source/packages/cactus-plugin-ledger-connector-quorum.md
rename to docs-cactus/source/packages/cactus-plugin-ledger-connector-quorum.md
diff --git a/docs/source/packages/cactus-test-api-client.md b/docs-cactus/source/packages/cactus-test-api-client.md
similarity index 100%
rename from docs/source/packages/cactus-test-api-client.md
rename to docs-cactus/source/packages/cactus-test-api-client.md
diff --git a/docs/source/packages/cactus-test-cmd-api-server.md b/docs-cactus/source/packages/cactus-test-cmd-api-server.md
similarity index 100%
rename from docs/source/packages/cactus-test-cmd-api-server.md
rename to docs-cactus/source/packages/cactus-test-cmd-api-server.md
diff --git a/docs/source/packages/cactus-test-consortium-manual.md b/docs-cactus/source/packages/cactus-test-consortium-manual.md
similarity index 100%
rename from docs/source/packages/cactus-test-consortium-manual.md
rename to docs-cactus/source/packages/cactus-test-consortium-manual.md
diff --git a/docs/source/packages/cactus-test-plugin-ledger-connector-besu.md b/docs-cactus/source/packages/cactus-test-plugin-ledger-connector-besu.md
similarity index 100%
rename from docs/source/packages/cactus-test-plugin-ledger-connector-besu.md
rename to docs-cactus/source/packages/cactus-test-plugin-ledger-connector-besu.md
diff --git a/docs/source/packages/cactus-test-plugin-ledger-connector-quorum.md b/docs-cactus/source/packages/cactus-test-plugin-ledger-connector-quorum.md
similarity index 100%
rename from docs/source/packages/cactus-test-plugin-ledger-connector-quorum.md
rename to docs-cactus/source/packages/cactus-test-plugin-ledger-connector-quorum.md
diff --git a/docs/source/packages/cactus-test-tooling.md b/docs-cactus/source/packages/cactus-test-tooling.md
similarity index 100%
rename from docs/source/packages/cactus-test-tooling.md
rename to docs-cactus/source/packages/cactus-test-tooling.md
diff --git a/docs/source/packages/config.md b/docs-cactus/source/packages/config.md
similarity index 100%
rename from docs/source/packages/config.md
rename to docs-cactus/source/packages/config.md
diff --git a/docs/source/packages/ledger-plugin.md b/docs-cactus/source/packages/ledger-plugin.md
similarity index 100%
rename from docs/source/packages/ledger-plugin.md
rename to docs-cactus/source/packages/ledger-plugin.md
diff --git a/docs/source/packages/routing-interface.md b/docs-cactus/source/packages/routing-interface.md
similarity index 100%
rename from docs/source/packages/routing-interface.md
rename to docs-cactus/source/packages/routing-interface.md
diff --git a/docs/source/read-root.md b/docs-cactus/source/read-root.md
similarity index 100%
rename from docs/source/read-root.md
rename to docs-cactus/source/read-root.md
diff --git a/docs/source/regulatory-and-industry-initiatives-reading-list.md b/docs-cactus/source/regulatory-and-industry-initiatives-reading-list.md
similarity index 100%
rename from docs/source/regulatory-and-industry-initiatives-reading-list.md
rename to docs-cactus/source/regulatory-and-industry-initiatives-reading-list.md
diff --git a/docs/source/support.rst b/docs-cactus/source/support.rst
similarity index 100%
rename from docs/source/support.rst
rename to docs-cactus/source/support.rst
diff --git a/docs/source/support/besu.md b/docs-cactus/source/support/besu.md
similarity index 100%
rename from docs/source/support/besu.md
rename to docs-cactus/source/support/besu.md
diff --git a/docs/source/support/corda.md b/docs-cactus/source/support/corda.md
similarity index 100%
rename from docs/source/support/corda.md
rename to docs-cactus/source/support/corda.md
diff --git a/docs/source/support/fabric.md b/docs-cactus/source/support/fabric.md
similarity index 100%
rename from docs/source/support/fabric.md
rename to docs-cactus/source/support/fabric.md
diff --git a/docs/source/support/iroha.md b/docs-cactus/source/support/iroha.md
similarity index 100%
rename from docs/source/support/iroha.md
rename to docs-cactus/source/support/iroha.md
diff --git a/docs/source/support/quorum.md b/docs-cactus/source/support/quorum.md
similarity index 100%
rename from docs/source/support/quorum.md
rename to docs-cactus/source/support/quorum.md
diff --git a/docs/source/support/xdai.md b/docs-cactus/source/support/xdai.md
similarity index 100%
rename from docs/source/support/xdai.md
rename to docs-cactus/source/support/xdai.md
diff --git a/docs/source/whitepaper-init.rst b/docs-cactus/source/whitepaper-init.rst
similarity index 100%
rename from docs/source/whitepaper-init.rst
rename to docs-cactus/source/whitepaper-init.rst
diff --git a/docs/source/whitepaper.md b/docs-cactus/source/whitepaper.md
similarity index 100%
rename from docs/source/whitepaper.md
rename to docs-cactus/source/whitepaper.md
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000000..45ddf0ae39
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1 @@
+site/
diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS
new file mode 100644
index 0000000000..1607d09e51
--- /dev/null
+++ b/docs/CODEOWNERS
@@ -0,0 +1 @@
+* @VRamakrishna
diff --git a/docs/LICENSE b/docs/LICENSE
new file mode 100644
index 0000000000..da6ab6cc8f
--- /dev/null
+++ b/docs/LICENSE
@@ -0,0 +1,396 @@
+Attribution 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution 4.0 International Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution 4.0 International Public License ("Public License"). To the
+extent this Public License may be interpreted as a contract, You are
+granted the Licensed Rights in consideration of Your acceptance of
+these terms and conditions, and the Licensor grants You such rights in
+consideration of benefits the Licensor receives from making the
+Licensed Material available under these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ d. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ e. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ f. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ g. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ h. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ i. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ j. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ k. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part; and
+
+ b. produce, reproduce, and Share Adapted Material.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ 4. If You Share Adapted Material You produce, the Adapter's
+ License You apply must not prevent recipients of the Adapted
+ Material from complying with this Public License.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material; and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+
+=======================================================================
+
+Creative Commons is not a party to its public
+licenses. Notwithstanding, Creative Commons may elect to apply one of
+its public licenses to material it publishes and in those instances
+will be considered the “Licensor.” The text of the Creative Commons
+public licenses is dedicated to the public domain under the CC0 Public
+Domain Dedication. Except for the limited purpose of indicating that
+material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the
+public licenses.
+
+Creative Commons may be contacted at creativecommons.org.
+
diff --git a/docs/README.md b/docs/README.md
index 871d1ade6c..fde2befb01 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,7 +1,61 @@
-### Building the docs
-```sh
-pip install -U Sphinx
-pip install -r pip-requirements.txt
-make html
+# Welcome to the documentation template
+
+This repository serves as a template for creating documentation for Hyperledger projects. The template utilizes MkDocs (documentation at [mkdocs.org](https://www.mkdocs.org)) and the theme Material for MkDocs (documentation at [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)). Material adds a number of extra features to MkDocs, and Hyperledger repositories can take advantage of the theme's [Insiders](https://squidfunk.github.io/mkdocs-material/insiders/) capabilities.
+
+[Material for MkDocs]: https://squidfunk.github.io/mkdocs-material/
+[Mike]: https://github.com/jimporter/mike
+
+## Prerequisites
+
+To test the documents and update the published site, the following tools are needed:
+
+- A Bash shell
+- git
+- Python 3
+- The [Material for Mkdocs] theme.
+- The [Mike] MkDocs plugin for publishing versions to gh-pages.
+ - Not used locally, but referenced in the `mkdocs.yml` file and needed for
+ deploying the site to gh-pages.
+
+### git
+`git` can be installed locally, as described in the [Install Git Guide from GitHub](https://github.com/git-guides/install-git).
+
+### Python 3
+`Python 3` can be installed locally, as described in the [Python Getting Started guide](https://www.python.org/about/gettingstarted/).
+
+### Mkdocs
+
+The Mkdocs-related items can be installed locally, as described in the [Material
+for Mkdocs] installation instructions. The short, case-specific version of those
+instructions follow:
+
+```bash
+pip install -r requirements.txt
```
-Access the documents from **build/html/** folder.
\ No newline at end of file
+
+### Verify Setup
+
+To verify your setup, check that you can run `mkdocs` by running the command `mkdocs --help` to see the help text.
+
+## Useful MkDocs Commands
+
+The commands you will usually use with `mkdocs` are:
+
+* `mkdocs serve` - Start the live-reloading docs server.
+* `mkdocs build` - Build the documentation site.
+* `mkdocs -h` - Print help message and exit.
+* `mkdocs gh-deploy` - Build and push documents to `gh-pages` branch, and publish to URL configured in `mkdocs.yml`.
+
+## Adding Content
+
+The basic process for adding content to the site is:
+
+- Create a new markdown file under the `docs` folder
+- Add the new file to the table of contents (`nav` section in the `mkdocs.yml` file)
+
+## Repository layout
+
+ mkdocs.yml # The configuration file.
+ docs/
+ index.md # The documentation homepage.
+ ... # Other markdown pages, images and other files.
diff --git a/docs/docs/architecture.md b/docs/docs/architecture.md
new file mode 100644
index 0000000000..b38b477ecf
--- /dev/null
+++ b/docs/docs/architecture.md
@@ -0,0 +1,15 @@
+The Cacti integrated architecture is illustrated below.
+
+
+
+This consists of a set of modules, services (offering standard APIs), and libraries that offer a selection of cross-network transaction pipelines, which can be constructed by picking and choosing from the collection.
+
+The integrated architecture was generated by fusing the pre-existing Cactus and Weaver architectures, identifying and re-labeling common (or overlapping) components and calling out unique components separately.
+
+For reference, here is the Cactus architecture.
+
+
+
+And here is the Weaver architecture.
+
+
diff --git a/docs/docs/cactus/_images/build-script-decision-tree-2021-03-06.png b/docs/docs/cactus/_images/build-script-decision-tree-2021-03-06.png
new file mode 100644
index 0000000000..22cf33d8fc
Binary files /dev/null and b/docs/docs/cactus/_images/build-script-decision-tree-2021-03-06.png differ
diff --git a/docs/docs/cactus/_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif b/docs/docs/cactus/_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif
new file mode 100644
index 0000000000..2735870f79
Binary files /dev/null and b/docs/docs/cactus/_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif differ
diff --git a/docs/docs/cactus/_images/related-work-categories.png b/docs/docs/cactus/_images/related-work-categories.png
new file mode 100644
index 0000000000..c773260f13
Binary files /dev/null and b/docs/docs/cactus/_images/related-work-categories.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-enroll.png b/docs/docs/cactus/_images/run-transaction-endpoint-enroll.png
new file mode 100644
index 0000000000..76310b39e2
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-enroll.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-cactuskeychainref.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-cactuskeychainref.png
new file mode 100644
index 0000000000..20647e8258
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-cactuskeychainref.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-pollfortxreceipt.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-pollfortxreceipt.png
new file mode 100644
index 0000000000..c7d4296abe
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-pollfortxreceipt.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-privatekey.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-privatekey.png
new file mode 100644
index 0000000000..1ff8188248
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-privatekey.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-signed.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-signed.png
new file mode 100644
index 0000000000..967eb22b71
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-signed.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact.png
new file mode 100644
index 0000000000..dc51fe46fd
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact1.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact1.png
new file mode 100644
index 0000000000..91a13a4290
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact1.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint.png b/docs/docs/cactus/_images/run-transaction-endpoint.png
new file mode 100644
index 0000000000..4ad53b872d
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint.png differ
diff --git a/docs/docs/cactus/_images/run-transaction-endpoint1.png b/docs/docs/cactus/_images/run-transaction-endpoint1.png
new file mode 100644
index 0000000000..8e6a76a599
Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint1.png differ
diff --git a/docs/docs/cactus/build.md b/docs/docs/cactus/build.md
new file mode 100644
index 0000000000..ac86ed3abe
--- /dev/null
+++ b/docs/docs/cactus/build.md
@@ -0,0 +1,223 @@
+Hyperledger Cactus Build Instructions
+=====================================
+
+This is the place to start if you want to give Cactus a spin on your local machine or if you are planning on contributing.
+
+> This is not a guide for `using` Cactus for your projects that have business logic but rather a guide for people who want to make changes to the code of Cactus. If you are just planning on using Cactus as an npm dependency for your project, then you might not need this guide at all.
+
+The project uses Typescript for both back-end and front-end components.
+
+Developers guide
+----------------
+
+This is a video guide to setup Hyperledger Cactus on your local machine.
+
+### Installing git
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/RJhifrmSiNA/0.jpg)](https://www.youtube.com/watch?v=RJhifrmSiNA)
+
+### Installing and configuring docker
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/V8YBQoxdyiE/0.jpg)](https://www.youtube.com/watch?v=V8YBQoxdyiE)
+
+### Installing npm and node
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/94xoV9Vfu14/0.jpg)](https://www.youtube.com/watch?v=94xoV9Vfu14)
+
+### Installing jdk 8
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/V8YBQoxdyiE/0.jpg)](https://youtube.com/watch?v=t4y57Qvrdcc)
+
+### Installing VSCode and plugins
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/RHQLhZRlAR0/0.jpg)](https://www.youtube.com/watch?v=RHQLhZRlAR0)
+
+### Clone the repository
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/n_HiEwgzPsM/0.jpg)](https://www.youtube.com/watch?v=n_HiEwgzPsM)
+
+### Compiling all packages
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/5v82MAHPQmM/0.jpg)](https://www.youtube.com/watch?v=5v82MAHPQmM)
+
+### Testing all packages
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/mVuk8txh-JE/0.jpg)](https://www.youtube.com/watch?v=mVuk8txh-JE)
+
+### Compiling a specific packages
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/e7vkd9i-I4c/0.jpg)](https://www.youtube.com/watch?v=e7vkd9i-I4c)
+
+### Testing a specific package
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/Jzw9JQZu6c8/0.jpg)](https://www.youtube.com/watch?v=Jzw9JQZu6c8)
+
+### Package structure - OpenAPI
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/5uuRTc3X4MM/0.jpg)](https://www.youtube.com/watch?v=5uuRTc3X4MM)
+
+### Package structure - Web Services
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/DAML56rx5yQ/0.jpg)](https://www.youtube.com/watch?v=DAML56rx5yQ)
+
+### Package structure - Main and Factory Plugin class
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/w0bmkpge2Dw/0.jpg)](https://www.youtube.com/watch?v=w0bmkpge2Dw)
+
+### Package structure - Test class
+
+[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/3XpBYhN-8qs/0.jpg)](https://www.youtube.com/watch?v=3XpBYhN-8qs)
+
+Fast Developer Flow / Code Iterations
+----------------------------------------------------------------------------------------------------------
+
+We put a lot of thought and effort into making sure that fast developer iterations can be achieved (please file a bug if you feel otherwise) while working **on** the framework.
+
+If you find yourself waiting too much for builds to finish, most of the time that can be helped by using the `npm run watch` script which can automatically recompile packages as you modify them (and only the packages that you have modified, not everything).
+
+It also supports re-running the OpenAPI generator when you update any `openapi.json` spec files that we use to describe our endpoints.
+
+The `npm run watch` script in action:
+
+![Fast Developer Flow / Code Iterations](_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif)
+
+Getting Started
+----------------------------------------------------------------
+
+* Use preset environment:
+
+ * [VSCode docker container](#./.devcontainer)
+
+* … or install OS level dependencies manually:
+
+ * Windows Only
+
+ * WSL2 or any virtual machine running Ubuntu 20.04 LTS
+
+ * Git
+
+ * NodeJS v16.14.2, npm v8.5.0 (we recommend using the Node Version Manager (nvm) if available for your OS)
+
+ nvm install 16.14.2
+ nvm use 16.14.2
+
+ * Yarn
+
+ * `npm run install-yarn` (from within the project directory)
+
+ * [Docker Engine](https://docs.docker.com/engine/install/ubuntu/). Make sure that Docker is working and running, for example, running `docker ps -aq`
+
+ * Docker Compose
+
+ * OpenJDK (Corda support Java 8 JDK but do not currently support Java 9 or higher)
+
+ * `sudo apt install openjdk-8-jdk-headless`
+
+ * Indy SDK (optional)
+
+ * [Installing the SDK](https://github.com/hyperledger/indy-sdk#installing-the-sdk)
+
+ * [Build the SDK from source](https://github.com/hyperledger/indy-sdk#how-to-build-indy-sdk-from-source)
+
+* Clone the repository
+
+
+git clone https://github.com/hyperledger/cactus.git
+
+Windows specific gotcha: `File paths too long` error when cloning. To fix: Open PowerShell with administrative rights and then run the following:
+
+git config \--system core.longpaths true
+
+* Change directories to the project root
+
+
+cd cactus
+
+* Run this command to enable corepack (Corepack is included by default with all Node.js installs, but is currently opt-in.)
+
+
+npm run enable-corepack
+
+* Run the initial configuration script (can take a long time, 10+ minutes on a low-spec laptop)
+
+
+yarn run configure
+
+At this point you should have all packages built for development.
+
+You can start making your changes (use your own fork and a feature branch) or just run existing tests and debug them to see how things fit together.
+
+For example you can _run a ledger single status endpoint test_ via the REST API with this command:
+
+npx tap \--ts \--timeout\=600 packages/cactus-test-plugin-htlc-eth-besu/src/test/typescript/integration/plugin-htlc-eth-besu/get-single-status-endpoint.test.ts
+
+_You can also start the API server_ and verify more complex scenarios with an arbitrary list of plugins loaded into Cactus. This is useful for when you intend to develop your plugin either as a Cactus maintained plugin or one on your own.
+
+npm run generate-api-server-config
+
+Notice how this task created a .config.json file in the project root with an example configuration that can be used a good starting point for you to make changes to it specific to your needs or wants.
+
+The most interesting part of the `.config.json` file is the plugins array which takes a list of plugin package names and their options (which can be anything that you can fit into a generic JSON object).
+
+Notice that to include a plugin, all you need is specify it’s npm package name. This is important since it allows you to have your own plugins in their respective, independent Github repositories and npm packages where you do not have to seek explicit approval from the Cactus maintainers to create/maintain your plugin at all.
+
+Once you are satisfied with the `.config.json` file’s contents you can just:
+
+npm run start:api-server
+
+After starting the API server, you will see in the logs that plugins were loaded and that the API is reachable on the port you specified (4000 by default). The Web UI (Cockpit) is disabled by default but can be enabled by changing the property value ‘cockpitEnabled’ to true and it is reachable through port on the port your config specified (3000 by default).
+
+> You may need to enable manually the CORS patterns in the configuration file. This may be slightly inconvenient, but something we are unable to compromise on despite valuing developer experience very much. We have decided that the software should be `secure by default` above all else and allow for customization/degradation of security as an opt-in feature rather than starting from that state.
+
+At this point, with the running API server, you can
+
+* Test the REST API directly with tools like cURL or Postman
+
+* Develop your own applications against it with the `Cactus API Client(s)`
+
+* Create and test your own plugins
+
+
+### Random Windows specific issues not covered here
+
+We recommend that you use WSL2 or any Linux VM (or bare metal). We test most frequently on Ubuntu 20.04 LTS
+
+Build Script Decision Tree
+--------------------------------------------------------------------------------------
+
+The `npm run watch` script should cover 99% of the cases when it comes to working on Cactus code and having it recompile, but for that last 1% you’ll need to get your hands dirty with the rest of the build scripts. Usually this is only needed when you are adding new dependencies (npm packages) as part of something that you are implementing.
+
+There are a lot of different build scripts in Cactus in order to provide contributors fine(r) grained control over what parts of the framework they wish build.
+
+> Q: Why the complexity of so many build scripts?
+>
+> A: We could just keep it simple with a single build script that builds everything always, but that would be a nightmare to wait for after having changed a single line of code for example.
+
+To figure out which script could work for rebuilding Cactus, please follow the following decision tree (and keep in mind that we have `npm run watch` too)
+
+![Build Script Decision Tree](_images/build-script-decision-tree-2021-03-06.png)
+
+Configuring SSH to use upterm
+--------------------------------------------------------------------------------------------
+
+Upload your public key onto github if not done so already. A public key is necessary to join the ssh connection to use upterm. For a comprehensive guide, see the [Generating a new SSH key and adding it to the ssh-agent](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
+
+Locate the `ci.yml` within `.github/workflows` and add to the `ci.yml` code listed below:
+
+* name: Setup upterm session uses: lhotari/action-upterm@v1 with: repo-token: ${{ secrets.GITHUB\_TOKEN }}
+
+
+Keep in mind that the SSH upterm session should come after the checkout step (uses: actions/checkout@v3.1.0) to ensure that the CI doesn’t hang without before the debugging step occurs. Editing the `ci.yml` will create a new upterm session within `.github/workflows` by adding a new build step. For more details, see the [Debug your GitHub Actions by using ssh](https://github.com/marketplace/actions/debugging-with-ssh).
+
+By creating a PR for the edited `ci.yml` file, this will the CI to run their tests. There are two ways to navigate to CIs.
+
+1. Go to the PR and click the `checks` tab
+
+2. Go to the `Actions` tab within the main Hyperledger Cactus Repository
+
+
+Click on the `CI Cactus workflow`. There should be a new job you’ve created be listed underneath the `build (ubuntu-20.04)` jobs. Click on the the new job (what’s you’ve named your build) and locate the SSH Session within the `Setup Upterm Session` dropdown. Copy the SSH command that start with `ssh` and ends in `.dev` (ex. ssh \*\*\*\*\*\*\*\*\*\*:\*\*\*\*\*\*\*\*\*\*\*@uptermd.upterm.dev). Open your OS and paste the SSH command script in order to begin an upterm session.
+
+[Previous](introduction.md "Welcome to Hyperledger Cactus documentation!") [Next](examples.md "Examples")
+
+* * *
diff --git a/docs/docs/cactus/code-of-conduct.md b/docs/docs/cactus/code-of-conduct.md
new file mode 100644
index 0000000000..e2fe51c0e1
--- /dev/null
+++ b/docs/docs/cactus/code-of-conduct.md
@@ -0,0 +1,8 @@
+Code of Conduct Guidelines
+======================================================================================
+
+Please review the Hyperledger [Code of Conduct](https://wiki.hyperledger.org/community/hyperledger-project-code-of-conduct) before participating and abide by these community standards.
+
+[Previous](governance.md "Governance") [Next](contributing.md "Contributing")
+
+* * *
diff --git a/docs/docs/cactus/contributing.md b/docs/docs/cactus/contributing.md
new file mode 100644
index 0000000000..b3b7d421a6
--- /dev/null
+++ b/docs/docs/cactus/contributing.md
@@ -0,0 +1,513 @@
+Contributing
+==========================================================
+
+Thank you for your interest to contribute to Hyperledger Cactus! :tada:
+
+First things first, please review the [Hyperledger Code of Conduct](https://wiki.hyperledger.org/display/HYP/Hyperledger+Code+of+Conduct) before participating.
+
+There are many ways to contribute to Hyperledger Cactus, both as a user and as a developer.
+
+As a user, this can include:
+
+* [Making Feature/Enhancement Proposals](https://github.com/hyperledger/cactus/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)
+
+* [Reporting bugs](https://github.com/hyperledger/cactus/issues/new?assignees=&labels=bug&template=bug_report.md&title=)
+
+
+As a developer:
+
+* if you only have a little time, consider picking up a [“help-wanted”](https://github.com/hyperledger/cactus/labels/help%20wanted) or [“good-first-issue”](https://github.com/hyperledger/cactus/labels/good%20first%20issue) task
+
+* If you can commit to full-time development, then please contact us on our [Rocketchat channel](https://chat.hyperledger.org/channel/cactus) to work through logistics!
+
+
+Git Know How / Reading List
+--------------------------------------------------------------------------------------
+
+This section is for you if you do not know your way around advanced git concepts such as
+
+* rebasing (interactive or otherwise)
+
+* splitting commits/PRs
+
+* when to use and not to use force push
+
+
+A word on the controversial topic of force pushes: In many git guides you will read that force push is basically forbidden. This is true 99% of the time, BUT if you are the only person working on a branch (which is most of time true for a feature/fix branch of yours that you are planning to submit as a PR) then force pushing is not just allowed but necessary to avoid messy git commit logs. The question you need to ask yourself before force pushing is this: Am I going to destroy someone else’s work on the remote branch? If nobody else is working on the branch then the answer is of course no and force push can be used safely. If others are working with you on the branch on the other hand, it is considered polite to ask and warn them in advance prior to force pushing so that they can take the necessary precautions on their side as well.
+
+A handy tool to avoid destroying other’s work accidentally is the new(ish) git feature called `--force-with-lease`: Using `git push --force-with-lease` instead of vanilla `--force` is highly recommended: https://softwareengineering.stackexchange.com/a/312710
+
+The rustlang documentation has an excellent write-up and additional links on pretty much everything you need to know. The only difference between their PR requirements and Cactus’ is that we do encourage people referencing github issues in commit messages. Quoting the most relevant parts below (and thanks to the Rust maintainers for this).
+
+> Pull requests are the primary mechanism we use to change Rust. GitHub itself has some great documentation on using the Pull Request feature. We use the “fork and pull” model described here, where contributors push changes to their personal fork and create pull requests to bring those changes into the source repository.
+>
+> Please make pull requests against the main branch.
+>
+> Rust follows a no merge policy, meaning, when you encounter merge conflicts you are expected to always rebase instead of merge. E.g. always use rebase when bringing the latest changes from the main branch to your feature branch. Also, please make sure that fixup commits are squashed into other related commits with meaningful commit messages.
+>
+> GitHub allows closing issues using keywords. This feature should be used to keep the issue tracker tidy.
+
+Source: https://github.com/rust-lang/rust/blob/53702a67e2ae8a404169a0329f6a38d73bf7494d/CONTRIBUTING.md#pull-requests
+
+Further reading:
+
+* https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-collaborative-development-models
+
+* https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests
+
+
+PR Checklist - Contributor/Developer
+--------------------------------------------------------------------------------------------------------
+
+**To avoid issues in the future, do not install dependencies globally. Ensure all dependencies are kept self-contained.**
+
+1. Fork [hyperledger/cactus](https://github.com/hyperledger/cactus) via Github UI
+
+ * If you are using the Git client on the Windows operating system, you will need to enable long paths for git which you can do in PowerShell by executing the command below. To clarify, this may also apply if you are using any Git GUI application on Windows such as `Github Desktop` or others.
+
+ git config \--global core.longpaths true
+
+2. Clone the fork to your local machine
+
+3. (Optional) [Create local branch](#create-local-branch) for minimizing code conflicts when you want to contribute multiple changes regarding different issues in parallel.
+
+4. Complete the desired changes and where possible test locally
+
+ 1. You can run the full CI suite on Mac/Linux/WSL by running the script at `./tools/ci.sh`
+
+ 2. If you do not have your environment set up for running bash scripts, do not worry, all pull requests will automatically have the same script executed for it when opened. The only downside is the slower feedback loop.
+
+5. Make sure you have set up your git signatures
+
+ 1. Note: Always sign your commits using the `git commit -S`
+
+ 2. For more information see [here](https://gist.github.com/tkuhrt/10211ae0a26a91a8c030d00344f7d11b)
+
+6. Think about/decide on what your commit message will be.
+
+ 1. The commit message syntax might be hard to remember at first so you we invite you to use the `npm run commit` command which upon execution presents you with a series of prompts that you can fill out and have your input validated in realtime, making it impossible (or at least much harder) to produce an invalid commit message that the commit lint bot on Github will flag with an error.
+
+ 1. The use of this tool described above is entirely optional in case you need a crutch.
+
+ 2. Note that running the `npm run commit` command will also attempt to perform the actual commit at the end unless you kill the process with `Ctrl + C` or whatever is your terminal’s shortcut for the same action.
+
+ 3. The `npm run commit` command will also attempt to sign the produced commit so make sure that it is set up properly prior to using it.
+
+7. Commit your changes
+
+ 1. Make sure your commit message follows the formatting requirements (details above) and here: [Conventional Commits syntax](https://www.conventionalcommits.org/en/v1.0.0-beta.4/#specification); this aids in release notes generation which we intend to automate
+
+ 2. Be aware that we are using git commit hooks for the automation of certain mundane tasks such as applying the required code style and formatting so your code will be wrapped at 80 characters each line automatically. If you wish to see how your changes will be altered by the formatter you can run the `npm run prettier` command from a terminal or install an IDE extension for the `Prettier` tool that can do the same (VSCode has one that is known to work).
+
+8. Ensure your branch is rebased onto the `upstream` main branch where `upstream` is fancy git talk for the main Cactus repo on Github (the one you created your fork from).
+
+ 1. **Do not** duplicate your pull request after it has been reviewed. Duplication here means closing the existing PR and then opening a brand new one which does not contain the review history anymore. If you encounter issues with version control that you do not know how to solve the maintainers will be happy to assist to ensure that you do not need to open a new pull request from scratch.
+
+ 1. The only exception from the rule above is if you mistakenly named your branch to contain special characters and somehow ended up in a state where it has become impossible to push changes to the remote due to this (which has happened before with branch names like `refactor(core-api): x` that had to be renamed to `refactor-core-api-x` and then a new PR had to be created in that case because GitHub does not let you rename the remote branch that your pull request is tied to)
+
+ 2. If you are having trouble, there are many great resources out there (so we will not write another here).
+
+ 1. If you are having trouble locating a suitable guide specifically on the mechanics of rebasing, we can recommend [this one](https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history). Thanks to Rafael for the link!
+
+ 2. If you went through that tutorial and still not quite sure what’s up, give this one a shot as well: https://about.gitlab.com/blog/2020/11/23/keep-git-history-clean-with-interactive-rebase/
+
+ 3. If merge conflicts arise, you must fix these at rebase time since omitting this step does not magically make the conflicts go away, just pushes it over the fence to the maintainer who will attempt to merge your pull request at a later point in time.
+
+ 4. If the above happens, at that point said maintainer will most likely ask you (if not already) to perform the rebase anyway since as the author of a change you are best positioned to resolve any conflicts on the code level. Occassionally maintainers may do the merge/conflict resolution themselves, but do not count on this nor try to make a habit out of relying on the potential kindness.
+
+ 5. After successful rebasing, take another look at your commit(s). Ideally there should be just one in each pull request, but also on the other hand each commit should be as small, simple and self contained as possible, so there can be cases where it makes sense to submit a PR with multiple commits if for example you also had to change something in the test tooling while implementing a feature (in which case there could be a commit for the feature itself and another for the necessary changes to the test tooling package). What we respectfully ask though is that you try to avoid these situations and submit most of your PRs with a single, self contained commit that does not touch multiple things. This significantly reduces the cognitive load required to review the changes which in turn makes everyone happier: the maintainers will have an easier job reviewing, which means they’ll be doing it faster which will (probably) cause you joy in turn.
+
+9. Push your changes to your main (or whatever you named your feature branch, that is entirely up to you at the end of the day)
+
+10. Initiate a pull request from your fork to the base repository
+
+11. Remember: Opening a pull request is like saying “Hey maintainers, I have this change finalized and ready for you to spend time on reviewing it.” The word `finalized` here is understood to imply that you are not planning on doing any more changes on the branch apart from when being asked to by the reviewers.
+
+12. It is perfectly acceptable to open a pull request and mark it as `draft` (a GitHub feature) which then signals to the maintainers that if they have time, they are welcome to look at the change, but it may or may not be in its final form yet so you are not responsible for potential loss of time on their end if the review has to be performed multiple times on account of changes. Once you promote your draft PR to a real one, the comments from the point above apply however.
+
+13. If your pull request contains a significant change, we recommend that you apply the similarly named github label on in it as well. It is okay if you do not do this, if we detect that the change is indeed significant, we will apply the label. If you do it in advance however, it will probably speed up the proceedings by removing one communication roundtrip from the review process of your pull request.
+
+14. Await CI, DCO & linting quality checks, as well as any feedback from reviewers
+
+15. If you need to update your pull request either because you discovered an issue or because you were asked to do so we ask that you:
+
+16. try to add the change in a way that does not produce additional commits on the PR but instead do an `git commit --amend --signoff` on your local branch and then a force push to the remote branch of yours (the PR essentially). Again, if the change you are doing does not fit within any one of the existing commits of your PR, then it is justified to add a new commit and this is up to your discretion (maintainers may respectfully ask you to squash if they see otherwise)
+
+17. The rule of thumb for any and all things in git/Cactus is to maintain a clean, tidy commit log/history that enables everyone to easily look up changes and find accurate answers to the basic questions of `Who? / What? / When / Why?`. If you have ever been in a situation when you tried to figure out the original point a bug was introduced (and tried to figure out why the offending change was made in the first place) and the git blame just lead you to a 10 megabyte large patch with the message ‘merge xyz’, then you know exactly what it is we are trying to avoid here. :-)
+
+
+PR Checklist - Maintainer/Reviewer
+----------------------------------------------------------------------------------------------------
+
+Ensure all the following conditions are met (on top of you agreeing with the change itself)
+
+1. All automated checks that are not explicitly called out here are also passing/green.
+
+2. Branch is rebased onto main and there are no dangling/duplicate commits.
+
+3. Commits appear simple and self contained. Simple is always relative to the mangitude of the change itself of course. A 1k line change can still be simple if all it does is rename some commonly used variable in each place its being used.
+
+4. If the contributors are having trouble with git basic functionality such as rebasing / force pushing, DCO, do your best to help them out, when in doubt feel free to reach out to Peter (who is the one insisting an all these git rules so he deserves to be the primary contact for all git related issues).
+
+ 1. Remember that we want to foster a welcoming community so if someone is new to git try to be extra patient with them on this front.
+
+5. Ensure the commit messages are according to the standard format.
+
+ 1. Remember that if you select ‘squash’ on the Github UI when accepting the pull request, Github will (by default) offer up the title of the pull request as the new commit message for your squash commit. This is not good unless the title happens to be a valid commit message, but in the likely event of it not being as such, you must take special care to type in a valid commit message right there and then on the Github UI.
+
+ 2. To avoid the hassle/potential issues with the above, it is recommended that you always use ‘rebase’ when accepting a pull request even if there are multiple commits that you’d otherwise like to see squashed.
+
+ 3. If you are adamant that you do not want to merge a PR with multiple commits, that is completely understandable and fair game. The recommended approach there is to ask the contributor to break the pull request up to multiple pull requests by doing an interactive rebase on their branch and cherry picking/re-ordering things accordingly. This is a fairly advanced git use case so you might want to help them out with it (or ask Peter who is the one constantly nagging everyone about these git rules…)
+
+
+To protect the Hyperledger Cactus source code, GitHub pull requests are accepted from forked repositories only. There are also quality standards identified and documented here that will be enhanced over time.
+
+Create local branch
+------------------------------------------------------------------------
+
+> Whenever you begin work on a new feature or bugfix, it’s important that you create a new branch.
+
+1. Clone your fork to your local machine
+
+2. Setup your local fork to keep up-to-date (optional)
+
+ \# Add 'upstream' repo to list of remotes
+ git remote add upstream https://github.com/hyperledger/cactus.git
+
+ \# Verify the new remote named 'upstream'
+ git remote \-v
+
+ \# Checkout your main branch and rebase to upstream.
+ \# Run those commands whenever you want to synchronize with main branch
+ git fetch upstream
+ git checkout main
+ git rebase upstream/main
+
+3. Create your branch.
+
+ \# Checkout the main branch - you want your new branch to come from main
+ git checkout main
+
+ \# Create a new branch named \`\` (give simple informative name)
+ git branch
+
+4. Checkout your branch and add/modify files.
+
+ git checkout
+ git rebase main
+ \# Happy coding !
+
+5. Commit changes to your branch.
+
+ \# Commit and push your changes to your fork
+ git add \-A
+ git commit \-s \-m "\[optional scope\]: "
+ git push origin
+
+6. Once you’ve committed and pushed all of your changes to GitHub, go to the page for your fork on GitHub, select your development branch, and click the pull request button.
+
+7. Repeat step 3 to 6 when you need to prepare posting new pull request.
+
+
+NOTE: Once you submitted pull request to Cactus repository, step 6 is not necessary when you made further changes with `git commit --amend` since your amends will be sent automatically.
+
+NOTE: You can refer original tutorial [‘GitHub Standard Fork & Pull Request Workflow’](https://gist.github.com/Chaser324/ce0505fbed06b947d962)
+
+### Directory structure
+
+Whenever you begin to use your codes on Hyperledger Cactus, you should follow the directory strecture on Hyperledger Cactus. The current directory structure is described as the following:
+
+> * contrib/ : Contributions from each participants, which are not directly dependent on Cactus code.
+>
+> * Fujitsu-ConnectionChain/
+>
+> * Accenture-BIF/
+>
+> * docs/
+>
+> * API/
+>
+> * business-logic-plugin.md
+>
+> * ledger-plugin.md
+>
+> * routing-interface.md
+>
+> * examples/
+>
+> * example01-car-trade/
+>
+> * src/
+>
+> * plugins/
+>
+> * business-logic-plugin/
+>
+> * lib/ : libraries for building Business Logic Plugin
+>
+> * ledger-plugin/ : Codes of Ledger Plugin
+>
+> * (ledger-name)/ : Including the ledger name (e.g. Ethereum, Fabric, …)
+>
+> * verifier/
+>
+> * src/ : Source codes of Verifier on Ledger Plugin
+>
+> * unit-test/ : Unit test codes of Verifier on Ledger Plugin (single driver / driver and docker env / …)
+>
+> * validator/
+>
+> * src/ : Source codes of Validator on Ledger Plugin
+>
+> * unit-test/ : Unit test codes of Validator on Ledger Plugin (single driver / driver and docker env / …)
+>
+> * routing-interface/
+>
+> * whitepaper/
+>
+> * test/
+>
+> * docker-env/
+>
+> * kubernetes-env/
+>
+
+Test Automation
+----------------------------------------------------------------
+
+> Mantra: Testable code is maintainable code
+
+### Summary
+
+We are all about automating the developer flow wherever possible and a big part of this is automated testing of course.
+
+Whenever contributing a change it is important to have test coverage for the specific change that you are making. This is especially important for bugs and absolutely essential for security related changes/fixes.
+
+Writing testable code is very important to us as not doing so can (and will) snowball into an avalanche of technical debt that will eventually destroy code quality and drive people away who would otherwise be happy to contribute and use the software. So, we want to make sure that does not happen with all this.
+
+This also means that occassionally, when making a change that looks simple on the surface you may find that the reviewer of your pull request asks you to do additional, seemingly unrelated changes that have nothing to do with the actual feature/bug that you just implemented/fixed, but instead are designed to ensure that tests can be written for it or for related code.
+
+This can feel like a chore (because it is) but we respectfully ask everyone to try their best in accomodating this because it really helps steering the ship on the long run.
+
+One of the simplest examples for the above is when you have a class that does something, anything, and it depends on some shared resource to achieve it. The shared resource can be the file system or a network port that is open for TCP connections for example. You can implement your class hardcoding the port number and functionally it will be correct (if you did that part right) _BUT_ if your class does not allow for the customization of said port through the constructor or a setter method, then one of our more obsessive maintainers (like Peter) will immediately be onto you asking for a change so that the port can be customized at runtime, allowing test cases to pass in port 0 that makes the test executable in parallel with other tests without being flaky.
+
+If you oppose this idea, said maintainers will happily refer you to this writing or conjure up an entirely new essay right there on the pull request.
+
+### Test Case Core Principles
+
+There are other principles specific per unit and integration tests, but the list below applies to all tests regardless of their nature.
+
+`All test cases must be...`
+
+* Self contained programs that can be executed on their own if necessary
+
+ * This ensures that if you are iterating on a single test case while trying to make it pass, you will always have the freedom to run just that one test instead of running the full suite of which the execution time will grow rapidly as we add test coverage, so, better nip that in the bud with this principle.
+
+* Excluded from the public API surface of the package they are in by ensuring that the test classes/types/interfaces are NOT exported through the `public-api.ts` file of that particular package.
+
+ * The only exception from this is if a package is itself designed for tests for which a delightful example is the `test-tooling` package which as the name suggests is entirely designated for providing utilities for writing tests and therefore in the case of this package it is allowed and even expected that it will expose test related classes/types in it’s public API surface. Do note however that indirectly the principle still applies, meaning that any package must not depend on the `test-tooling` package as an npm `dependency` but rather it must declare it as a `devDependency` in the relevant section of the `package.json` file.
+
+* Compatible with the [TestAnythingProtocol](https://testanything.org/)
+
+ * The NodeJS implementation of said protocol is in the `node-tap` npm package:
+
+ * [Assertions API](https://node-tap.org/docs/api/asserts/) of Node TAP
+
+ * Simplest possible test case:
+
+ const test, { Test } \= require("tape");
+ import \* as publicApi from "../../../main/typescript/public-api";
+
+ test("Module can be loaded", (t: Test) \=> {
+ t.ok(publicApi);
+ t.end(); // yaay, test coverage
+ });
+
+ * An [end to end test case](#./packages/cactus-test-plugin-consortium-manual/src/test/typescript/integration/plugin-consortium-manual/security-isolation-via-api-server-ports.ts) showcasing everything in action that is being preached in this document about test automation
+
+* Focus/verify a single bug-fix/feature/etc.
+
+* Clearly separated from non-test (aka `main`) source code. This means in practice that we ask that your test cases are either in the
+
+ 1. `./src/test/...` tree of the package that you are testing OR
+
+ 2. your test cases are in the `./src/test/...` tree (yes same name) BUT in an entirely separate package if the dependencies necessitate so. An example to when you would need a separate testing package is if you are developing a ledger plugin that has REST API endpoints shipping with it and you wish to verify in a test that the plugin can be loaded to the `ApiServer` and then called via the web service/SDK. In this case, you cannot place your test case in the ledger plugin’s package because you want to avoid having to pull in the API server as a dependency of your ledger plugin package (to ensure that there will be no circular dependencies).
+
+* Executable with unlimited parallelism (so if I have a 128 test cases and run all of them in parallel on my new 128 CPU core computer, then every single test case runs at the same time)
+
+ * This is important because it weeds out flakyness and hardcoded references to shared resources (Remember the rant about network ports in the previous section?)
+
+ * _BUT_ it is also very important because we (as in humanity) spent the last decade making the average CPUs ship with more and more cores as increasing frequency failed in the late 2000s as a performance increasing strategy.
+
+ What this means is that to utilize the average consumer laptop that most people will have for development, you will need your test cases to run in parallel which will save time for everyone working on the code and faster turnaround times make for a better developer experience which makes for a happier community around our open source project. It’s all connected. ;-)
+
+* Test cases don’t depend on code outside of the `./src/*` directory trees of the packages.
+
+ * Do not depend on any of the example code in your test cases.
+
+ * If you need to import code that is not JS/JSON/TS you can still do so via the Typescript compiler’s relevant feature that allows importing arbitrary files.
+
+
+Working with the Code
+----------------------------------------------------------------------------
+
+There are additional details about this in the [BUILD.md](#./BUILD.md) file in the project root as well.
+
+We use Lerna for managing the [monorepo](https://blog.npmjs.org/post/186494959890/monorepos-and-npm) that is Cactus.
+
+> We heavily rely on Docker for testing the ledger plugins.
+
+### Running/Debugging the tests
+
+Make sure to have the build succeed prior to attempting to run the tests. If you just checked out the project, it is best to just to just run the CI script which will do a full build and run all tests for you. If it fails you can open a bug in the issue tracker.
+
+Assuming you have built the sources, below are the different methods to run the tests:
+
+#### Running a single test case
+
+You execute unit and integration tests in the same way, but here are examples for both them separately anyway:
+
+* An integration test:
+
+ yarn jest packages/cactus-test-plugin-consortium-manual/src/test/typescript/integration/plugin-consortium-manual/get-consortium-jws-endpoint.test.ts
+
+* A unit test:
+
+ npx jest packages/cactus-common/src/test/typescript/unit/objects/get-all-method-names.test.ts
+
+ You can also run tests via the VS Code user interface. To do so, make sure you rename `template.launch.json` to \`\`launch.json\`. Under the “Run and Debug” window of VS Code, select “JEST: Current TS file” to test the currently opened file.
+
+
+#### Running all test cases (unit+integration)
+
+npm run test:all
+
+#### Running unit tests only
+
+npm run test:unit
+
+#### Running integration tests only
+
+npm run test:integration
+
+#### What is npx used for?
+
+`npx` is a standard top level binary placed on the path by NodeJS at installation time. We use it to avoid having to place every node module (project dependencies) on the OS path or to install them globally (`npm install some-pkg -g`)
+
+Read more about npx here: https://blog.npmjs.org/post/162869356040/introducing-npx-an-npm-package-runner
+
+#### What’s the equivalent of npx for Yarn?
+
+Yarn itself. E.g. `npx lerna clean` becomes `yarn lerna clean`.
+
+#### Debugging a test case
+
+Open the `.vscode/template.launch.json` file and either copy it with a name of `launch.json` (if you don’t already have such a file) or just cherry pick the example Visual Studio Code debug tasks that you’d like to use. For debugging a single test case, you need the debug task from the template launch.json file that is called `TAP: Current TS Test File`. Prior to running that debug task you must have your VSCode editor opened to the test file that you wish to run. Breakpoints will work as long as you are debugging code in the same package.
+
+> Source map support is partial at this point but actively being worked on.
+
+### All-In-One Docker Images for Ledger Connector Plugins
+
+If you are working on a new ledger connector you’ll need an `all-in-one` docker image as well, which will allow the expected level of test automation. If your chosen ledger’s maintainers provide an adequate docker image, then you might not need to develop this yourself, but this is rarely the case so YMMV.
+
+To see an existing set of examples for `besu` and `quorum` images take a peek at the `tools/docker/besu-all-in-one` and `tools/docker/quorum-all-in-one` folders. These produce the `ghcr.io/hyperledger/cactus-besu-all-in-one` and `ghcr.io/hyperledger/cactus-quorum-all-in-one` images respectively. Both of these are used in the test cases that are written for the specific ledger connector plugins at:
+
+* `packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-via-web-service.test.ts`
+
+* `packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts`
+
+
+The specific classes that utilize the `all-in-one` images can be found in the `test-tooling` package under these paths:
+
+* `packages/cactus-test-tooling/src/main/typescript/besu/besu-test-ledger.ts`
+
+* `packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts`
+
+
+#### Test Automation of Ledger Plugins
+
+Ledger plugin tests are written the same way as any other test (which is difficult to achieve, but we thrive to get it done).
+
+The only difference between a ledger connector plugin test case and any unit test is that the ledger connector plugin’s test case will pull up a docker container from one of the `all-in-one` images that we maintain as part of Cactus and then use that `all-in-one-*` container to verify things such as the ability of the ledger connector plugin to deploy a contract to said ledger.
+
+As a generic best practice, the test cases should never re-use any `all-in-one` ledger container for the execution of multiple test cases because that will almost surely lead to flaky/unstable test cases over the long run and needless complexity, ordering dependencies and so on. It is recommended that if you have two test cases for a ledger connector plugin, they both pull up a newly created container from scratch, execute the test scenario and then tear down and delete the container completely.
+
+An example for a ledger connector plugin and it’s test automation implemented the way it is explained above: `packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-via-web-service.test.ts`
+
+> This test case is also an example of how to run an ApiServer independently with a single ledger plugin which is how the test case is set up to begin with.
+
+Another option if you want to perform some tests manually is to run the API server with a configuration of your choice:
+
+\# Starting from the project root directory
+
+chmod +x ./packages/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js
+
+./packages/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \--config-file\=.config.json
+
+You can run this test case the same way you would run any other test case (which is also a requirement in itself for each test case):
+
+npx tap \--ts \--timeout\=600 packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-via-web-service.test.ts
+
+You can specify an arbitrary set of test cases to run in a single execution via glob patterns. Examples of these glob patterns can be observed in the root directory’s `package.json` file which has npm scripts for executing all tests with a single command (the CI script uses these):
+
+"test:all": "tap --ts --jobs=1 --timeout=600 \\"packages/cactus-\*/src/test/typescript/{unit,integration}/\\"",
+"test:unit": "tap --ts --timeout=600 \\"packages/cactus-\*/src/test/typescript/unit/\\"",
+"test:integration": "tap --ts --jobs=1 --timeout=600 \\"packages/cactus-\*/src/test/typescript/integration/\\""
+
+Following a similar pattern if you have a specific folder where your test cases are, you can run everything in that folder by specifying the appropriate glob patterns (asterisks and double asterisks as necessary depending on the folder being a flat structure or with sub-directories and tests nested deep within them).
+
+For example this can work as well:
+
+\# Starting from the project root
+cd packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum
+npx tap \--ts \--jobs\=1 \--timeout\=600 \\"./\\"
+
+> Be aware that glob patterns need quoting in some operating system’s shell environments and not necessarily on others. In the npm scripts Cactus uses we quote all of them to ensure a wider shell compatibility.
+
+### Building the API Client(S)
+
+You do not need to do anything special to have the API Client sources generated and compiled. It is all part of the `npm run build:dev:backend` task which you can run yourself or as part of the CI script (`./tools/ci.sh`).
+
+The API client code is automatically generated from the respective `openapi.json` file of each package that exposes ay web serices (REST/SocketIO/gRPC/etc.) and can be dependend on by other packages where applicable. There’s a dedicated `@hyperledger/cactus-api-client` package that is meant to contain common functionality among the rest of API clients. The concept here is similar to abstract classes and their sub-class implementations.
+
+Each `openapi.json` produces its own API client via the code generator that also contains relevant model definitions, such as interfaces describing the request/response bodies of all possible operations and validation constraints as well.
+
+The API clients are designed to be a universal components, meaning that it runs just fine in browser and also NodeJS environments. This is very important as we do not wish to maintain two (or more) separate API client codebases for the various platforms and we also want as much of it being generated automatically as possible (currently this is close to 100%).
+
+### Adding new dependencies
+
+Example:
+
+\# Adds "got" as a dependency to the cactus common package
+\# Note that you must specify the fully qualified package name as present in
+\# the package.json file
+yarn workspace @hyperledger/cactus-common add got \--save-exact
+
+You need to know which package of the monorepo will be using the package and then run the `yarn workspace` command with an additional parameters specifying the package name and the dependency name. See [Yarn Workspaces Documentation](https://classic.yarnpkg.com/en/docs/cli/workspace/) for the official Yarn documentation for further details and examples.
+
+After adding new dependencies, you might need to [Reload VSCode Window After Adding Dependencies](#reload-vscode-window-after-adding-dependencies)
+
+> **Always specify the `--save-exact` when installing new dependencies to ensure [reproducible builds](https://reproducible-builds.org/)**
+
+### Reload VSCode Window After Adding Dependencies
+
+If you added a new dependency and VSCode is showing an error when you try to import it, then sometimes the issue is just a matter of nudging VSCode to reload the Typescript definitions from scratch so that it “notices” the new dependency you just added.
+
+The recommended way of doing this is by hitting the `F1` key (or whatever you have bound the command menu to) and then searching and selecting `Developer: Reload Window` As a simpler alternative you can also just quit and relaunch the VSCode application of course.
+
+### On Reproducible Builds
+
+As a best practice, any given revision (commit hash) stored in version control should produce the exact same build artifacts regardless of when or where the build was performed. This can only be achieved if npm dependency versions are locked down instead of being automatically upgraded by npm (which makes the build time and machine dependent).
+
+Bottom line: Do not use the the `^`, `~` and `*` syntax elements while declaring your npm dependencies.
+
+Further details:
+
+* https://reproducible-builds.org/
+
+* https://spin.atomicobject.com/2016/12/16/reproducible-builds-npm-yarn/
+
+
+[Previous](code-of-conduct.md "Code of Conduct Guidelines") [Next](whitepaper.md "Hyperledger Cactus White Paper")
+
+* * *
diff --git a/docs/docs/cactus/examples.md b/docs/docs/cactus/examples.md
new file mode 100644
index 0000000000..a1b44465d2
--- /dev/null
+++ b/docs/docs/cactus/examples.md
@@ -0,0 +1,10 @@
+Examples
+==================================================
+
+This section shows the sample applications that are provisioned by the Hyperledger Cactus.
+
+* [Supply Chain App](examples/supply-chain-app.md)
+
+[Previous](build.md "Hyperledger Cactus Build Instructions") [Next](examples/supply-chain-app.md "Hyperledger Cactus Example - Supply Chain App")
+
+* * *
diff --git a/docs/docs/cactus/examples/supply-chain-app.md b/docs/docs/cactus/examples/supply-chain-app.md
new file mode 100644
index 0000000000..71409a80e7
--- /dev/null
+++ b/docs/docs/cactus/examples/supply-chain-app.md
@@ -0,0 +1,128 @@
+Example - Supply Chain App
+==========================================================================================================================
+
+Usage
+--------------------------------------------
+
+1. Execute the following from:
+
+ docker run \\
+ \--rm \\
+ \--privileged \\
+ \-p 3000:3000 \\
+ \-p 3100:3100 \\
+ \-p 3200:3200 \\
+ \-p 4000:4000 \\
+ \-p 4100:4100 \\
+ \-p 4200:4200 \\
+ ghcr.io/hyperledger/cactus-example-supply-chain-app:2022-04-05--feat-1579
+
+2. Observe the example application pulling up in the logs
+
+ 1. the test ledger containers,
+
+ 2. a test consortium with multiple members and their Cactus nodes
+
+3. Wait for the output to show the message `INFO (api-server): Cactus Cockpit reachable http://0.0.0.0:3200`
+
+4. Visit http://0.0.0.0:3200 in your web browser with Javascript enabled
+
+
+Building and running the container locally
+----------------------------------------------------------------------------------------------------------------------
+
+\# Change directories to the project root
+
+\# Build the docker image and tag it as "scaeb" for supply chain app example backend
+DOCKER\_BUILDKIT\=1 docker build \-f ./examples/supply-chain-app/Dockerfile . \-t scaeb
+
+\# Run the built image with ports mapped to the host machine as you see fit
+\# The --privileged flag is required because we use Docker-in-Docker for pulling
+\# up ledger containers from within the container in order to have the example
+\# be completely self-contained where you don't need to worry about running
+\# multiple different ledgers jus this one container.
+docker run \--rm \-it \--privileged \-p 3000:3000 \-p 3100:3100 \-p 3200:3200 \-p 4000:4000 \-p 4100:4100 \-p 4200:4200 scaeb
+
+Building the image with a specific npm package version:
+
+DOCKER\_BUILDKIT\=1 docker build \\
+ \--build-arg NPM\_PKG\_VERSION\=jwt-supply-chain \\
+ \--file ./examples/supply-chain-app/Dockerfile \\
+ \--tag scaeb \\
+ ./
+
+Running the Example Application Locally
+----------------------------------------------------------------------------------------------------------------
+
+> Make sure you have all the dependencies set up as explained in `BUILD.md`
+
+On the terminal, issue the following commands:
+
+1. `npm run install-yarn`
+
+2. `yarn configure`
+
+3. `yarn start:example-supply-chain`
+
+
+Debugging the Example Application Locally
+--------------------------------------------------------------------------------------------------------------------
+
+On the terminal, issue the following commands (steps 1 to 6) and then perform the rest of the steps manually.
+
+1. `npm run install-yarn`
+
+2. `yarn configure`
+
+3. `yarn build:dev`
+
+4. `cd ./examples/supply-chain-app/`
+
+5. `yarn --no-lockfile`
+
+6. `cd ../../`
+
+7. Locate the `.vscode/template.launch.json` file
+
+8. Within that file locate the entry named `"Example: Supply Chain App"`
+
+9. Copy the VSCode debug definition object from 2) to your `.vscode/launch.json` file
+
+10. At this point the VSCode `Run and Debug` panel on the left should have an option also titled `"Example: Supply Chain App"` which starts the application
+
+11. When the application finishes loading, the JWT token generated is displayed on the terminal
+
+12. Visit http://localhost:3200 in a web browser with Javascript enabled and insert the token when prompted
+
+
+Live Reloading the GUI Application
+------------------------------------------------------------------------------------------------------
+
+1. `npm run install-yarn`
+
+2. `yarn configure`
+
+3. `yarn build:dev`
+
+4. Locate the `.vscode/template.launch.json` file
+
+5. Within that file locate the entry named `"Example: Supply Chain App"`
+
+6. Copy the VSCode debug definition object from 2) to your `.vscode/launch.json` file
+
+7. At this point the VSCode `Run and Debug` panel on the left should have an option also titled `"Example: Supply Chain App"` which starts the application
+
+8. `cd ./examples/cactus-example-supply-chain-frontend/`
+
+9. `yarn serve:proxy`
+
+10. When the application finishes loading, the JWT token generated is displayed on the terminal
+
+11. Visit http://localhost:8000 in a web browser with Javascript enabled and insert the token when prompted
+
+12. At this point if you modify the source code of the GUI application under the `./examples/cactus-example-supply-chain-frontend/` path it will automatically reload the browser window (you will need to paste in the JWT again when this happens)
+
+
+[Previous](../examples.md "Examples") [Next](../governance.md "Governance")
+
+* * *
diff --git a/docs/docs/cactus/governance.md b/docs/docs/cactus/governance.md
new file mode 100644
index 0000000000..a30538e1c9
--- /dev/null
+++ b/docs/docs/cactus/governance.md
@@ -0,0 +1,72 @@
+Governance
+======================================================
+
+Hyperledger Cactus is managed under an open governance model as described in the Hyperledger charter. Cactus is led by a set of maintainers, who can be found in the MAINTAINERS.md file.
+
+**Maintainers**
+
+Cactus is led by the project’s maintainers. The maintainers are responsible for reviewing and merging all patches submitted for review, and they guide the overall technical direction of the project within the guidelines established by the Hyperledger Technical Steering Committee (TSC).
+
+**Becoming a Maintainer**
+
+The project’s maintainers will, from time-to-time, consider adding or removing a maintainer. An existing maintainer can submit a change set to the MAINTAINERS.md file. A nominated contributor may become a maintainer by a three-quarters approval of the proposal by the existing maintainers. Once approved, the change set is then merged and the individual is added to (or alternatively, removed from) the maintainers group.
+
+Maintainers may be removed by explicit resignation, for prolonged inactivity (3 or more months), or for some infraction of the code of conduct or by consistently demonstrating poor judgement. A maintainer removed for inactivity should be restored following a sustained resumption of contributions and reviews (a month or more) demonstrating a renewed commitment to the project. We require that maintainers that will be temporarily inactive do so “gracefully” and update other maintainers on their status and time availability rather than appearing to “fall off the face of the earth.”
+
+**Releases**
+
+A majority of the maintainers may decide to create a release of Cactus. Any broader rules of Hyperledger pertaining to releases must be followed. Once the project is mature, there will be a stable LTS (long term support) release branch, as well as the main branch for upcoming new features.
+
+**Making Feature/Enhancement Proposals**
+
+Code changes that are either bug fixes, direct and small improvements, or things that are on the roadmap (see below) can be issued as PRs in a relatively quick time period, although we recommend creating a Github ticket to track even bugs and small improvements. For more substantial changes, however, a feature/enhancement proposal is required. These proceed through the approval process like typical PRs, and require the same “2 + 1” approval policy for acceptance.
+
+In particular, all contributors to the project should have enough time to voice an opinion on feature/enhancement proposals before they are accepted. So the maintainers will determine some “comment period” between proposal submission and acceptance so that contributors have enough time to voice their opinions.
+
+Significant changes can be marked as such via the predefined label with the same name. This is a tool that helps maintainers identify the most important issues/discussions to be had at any given time through the GitHub web interface.
+
+To easily access the list of significant changes, navigate to the label: https://github.com/hyperledger/cactus/labels/Significant\_Change
+
+We also recommend reading our CONTRIBUTING.md file (https://github.com/hyperledger/cactus/blob/main/CONTRIBUTING.md) for more information about contributing.
+
+**Approving Pull Requests**
+
+Maintainers designated for review are required to review PRs in a timely manner (all circumstances considered, of course). Any pull request must be reviewed by at least two maintainers, and if a PR is submitted by a maintainer, these two reviewers must be different from the original submitter.
+
+The technical requirements for submitting/approving/merging pull requests are further detailed in the CONTRIBUTING.md file where it is laid out in detail how to ensure git commit graph tidiness.
+
+**Reviewing Pull Requests**
+
+We are strongly committed to processing pull requests from everyone in a fair manner meaning that pull requests are to be reviewed in order of submission. Reviewing PRs in order of submission does not guarantee nor necessitate accepting/merging said PRs in order of submission since some PRs may require lengthy feedback loops while others may pass the muster without any change requests or feedback at all, depending on the nature of the change being proposed. Security related pull requests may be fast tracked even against the “in order of submission” principle if it appears that a vulnerability makes a pull request a time sensitive issue where the sooner we propagate a fix the better it is.
+
+**Maintainers Meeting**
+
+The maintainers hold regular maintainers meetings, which are open to everyone. The purpose of the maintainers meeting is to plan for and review the progress of releases, and to discuss the technical and operational direction of the project.
+
+Please see the wiki for maintainer meeting details.
+
+One point to mention about meetings is that new feature/enhancement proposals as described above should be presented to a maintainers meeting for consideration, feedback, and acceptance.
+
+**Roadmap**
+
+The Cactus maintainers are required to maintain a roadmap. There is a technical roadmap, with all of the issues as they directly relate to code, and a more public-friendly roadmap that anyone can digest. The required features to be implemented will be maintained as issues at the official github repository of Cactus with tag string ‘for current release’ or ‘for future release’. The task which is not volunteered to work, will be dispatched to specific contributors following consensus among the majority of maintainers.
+
+The technical roadmap is implicitly derived from the Github “milestones” feature. To access the list of milestones for Cactus use this link: https://github.com/hyperledger/cactus/milestones
+
+**Communications**
+
+We use the Cactus email list for long-form communications and RocketChat for short, informal announcements and other communications. We encourage all communication, whenever possible, to be public and in the clear (i.e. rather than sending an email directly to a person or two, send it out to the whole list if it pertains to the project).
+
+**Future Changes**
+
+The governance of Cactus may change as the project evolves. In particular, if the project becomes large, we will incorporate tiered maintainership, with top-level maintainers, subprojects, subproject maintainers, release managers, and so forth. We emphasize that this document is intended to be “living” and will be updated periodically.
+
+We require that changes to this document require a three-quarters approval of the existing maintainers. Note that this may also be changed in the future if deemed necessary.
+
+**Attribution**
+
+This document is based on the Hyperledger Fabric governance document, with some substantial changes.
+
+[Previous](examples/supply-chain-app.md "Hyperledger Cactus Example - Supply Chain App") [Next](code-of-conduct.md "Code of Conduct Guidelines")
+
+* * *
diff --git a/docs/docs/cactus/introduction.md b/docs/docs/cactus/introduction.md
new file mode 100644
index 0000000000..5476aa3b34
--- /dev/null
+++ b/docs/docs/cactus/introduction.md
@@ -0,0 +1,28 @@
+Welcome to Hyperledger Cactus documentation!
+=========================================================================================================================
+
+Hyperledger Cactus aims to provide Decentralized, Secure and Adaptable Integration between Blockchain Networks. Hyperledger Cactus is currently undergoing a major refactoring effort to enable the desired to-be architecture which will enable plug-in based collaborative development to increase the breadth of use cases & Ledgers supported.
+
+**What is Cactus?**
+
+A pluggable, enterprise-grade framework to transact on multiple distributed ledgers without introducing yet another competing blockchain.
+
+> * Cactus allows developers to abstract the application layer from the DLT addressing protocol fragmentation, lowering coupling and reducing implementation risks
+>
+> * Cactus allows different DLT networks to interact with each other, through atomic transactions and state commits, this eliminates information silos and increases network’s value
+>
+
+**Why use Cactus?**
+
+> * Maximize flexibility and future-proofing through plug-in architecture.
+>
+> * Avoid needing explicit action from users to have a secure Cactus deployment. Policies such as vaults are built into the SDK
+>
+> * Keys and other credentials are not stored in source, configuration files, or environment variables
+>
+> * Preserving Ledger Features Horizontal Scalability.
+>
+
+[Next](build.md "Hyperledger Cactus Build Instructions")
+
+* * *
diff --git a/docs/docs/cactus/packages.md b/docs/docs/cactus/packages.md
new file mode 100644
index 0000000000..4f509dfc18
--- /dev/null
+++ b/docs/docs/cactus/packages.md
@@ -0,0 +1,23 @@
+Cactus Components
+====================================================================
+
+This section contains the components to form Hyperledger Cactus.
+
+* [Api Client](packages/cactus-api-client.md)
+* [CMD Api Server](packages/cactus-cmd-api-server.md)
+* [Cactus Common](packages/cactus-common.md)
+* [Cactus Core](packages/cactus-core.md)
+* [Consortium Manual](packages/cactus-plugin-consortium-manual.md)
+* [Keychain Vault](packages/cactus-plugin-keychain-vault.md)
+* [Connector Besu](packages/cactus-plugin-ledger-connector-besu.md)
+* [Connector Corda](packages/cactus-plugin-ledger-connector-corda.md)
+* [Connector Fabric](packages/cactus-plugin-ledger-connector-fabric.md)
+* [Connector Quorum](packages/cactus-plugin-ledger-connector-quorum.md)
+* [Test Api Client](packages/cactus-test-api-client.md)
+* [Test CMD Api Server](packages/cactus-test-cmd-api-server.md)
+* [Test Connector Quorum](packages/cactus-test-plugin-ledger-connector-quorum.md)
+* [Test Tooling](packages/cactus-test-tooling.md)
+
+[Previous](regulatory-and-industry-initiatives-reading-list.md "Regulatory and Industry Initiatives Reading List") [Next](packages/cactus-api-client.md "@hyperledger/cactus-api-client")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-api-client.md b/docs/docs/cactus/packages/cactus-api-client.md
new file mode 100644
index 0000000000..3690aef39c
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-api-client.md
@@ -0,0 +1,140 @@
+`@hyperledger/cactus-api-client`
+================================================================================================
+
+Summary
+------------------------------------------------
+
+The Hyperledger Cactus API Client package is designed to be a generic extension with convenience features wrapped around the \[**typescript-axios** flavored API clients\][(https://github.com/OpenAPITools/openapi-generator/blob/v5.2.1/docs/generators/typescript-axios.md](https://github.com/OpenAPITools/openapi-generator/blob/v5.2.1/docs/generators/typescript-axios.md)) that we auto-generate and ship with each web service-enabled plugin such as the API clients of the
+
+* [**Manual Consortium Plugin** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-consortium-manual/src/main/typescript/generated/openapi/typescript-axios)
+
+* [**Besu Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-besu/src/main/typescript/generated/openapi/typescript-axios)
+
+* [**Corda Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/generated/openapi/typescript-axios)
+
+* [**Fabric Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios)
+
+* [**Quorum Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-quorum/src/main/typescript/generated/openapi/typescript-axios)
+
+* [**API Server** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-cmd-api-server/src/main/typescript/generated/openapi/typescript-axios)
+
+* [**Vault Keychain Plugin** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-keychain-vault/src/main/typescript/generated/openapi/typescript-axios)
+
+
+The code generation for the listed code folders above is done by the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) tool that can convert OpenAPI V3 json specifications of ours straight into the program code of the API clients.
+
+The above means that the `ApiClient` class is not the one containing the implementation responsible for executing all the supported API calls by a Cactus node (which would make it a monolith, something that we try to avoid as it is the opposite of a flexible plugin architecture)
+
+For example you can use the `@hyperledger/cactus-api-client` node package to perform Cactus node discovery based on ledger IDs (that can be obtained from the `ConsortiumDatabase` as defined by the [generated models](https://github.com/hyperledger/cactus/blob/main/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts) of the `@hyperledger/cactus-core-api` package.
+
+> While you can generate API Clients for the Cactus API specifications in any supported langauge of the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) the features provided by this package will have to be developed separately (if not already done by the Cactus maintainers). Currently the only implementation of the abstract API Client and its features (node discovery) is in Typescript (e.g. the `@hyperledger/cactus-api-client` package).
+
+Usage
+--------------------------------------------
+
+### Routing to Cactus Node with connector to specific ledger
+
+Let’s say you have a consortium with several members who all have their own ledgers deployed as well. The `ConsortiumDatabase` will therefore contain the entities pertaining to these entities (such as the ledgers or the members themselves) meaning that if you are developing an application that needs to perform operations on one of the ledgers in the consortium then you have a couple of different ways of obtaining an API client to do just that:
+
+#### Leverage the `ConsortiumDatabase` for discovery
+
+import { ApiClient } from "@hyperledger/cactus-api-client";
+
+import { ConsortiumDatabase, Ledger, LedgerType } from "@hyperledger/cactus-core-api";
+
+import { PluginRegistry } from "@hyperledger/cactus-core";
+
+import { DefaultApi as QuorumApi } from "@hyperledger/cactus-plugin-ledger-connector-quorum";
+
+const mainFn \= async () \=> {
+ const ledgerId \= "theIdOfYourLedgerInTheConsortiumDatabase";
+
+ // How you obtain a consortium provider is dependent on which consortium
+ // plugin you use and your exact deployment scenario
+ const consortiumProvider: IAsyncProvider \= ...;
+ const consortiumDatabase: ConsortiumDatabase \= await consortiumProvider.get();
+ const consortium \= consortiumDatabase.consortium\[0\];
+
+ const mainApiClient \= new ApiClient({ basePath: consortium.mainApiHost });
+
+ // This client is now configured to point to a node that has a connector to
+ // the ledger referenced by \`ledgerId\`
+ const apiClient \= await mainApiClient.ofLedger(ledgerId, QuorumApi);
+
+ // Use the client to perform any supported operation on the ledger
+};
+
+mainFn();
+
+#### Use a provided `mainApiHost` and `ledgerId`
+
+import { ApiClient } from "@hyperledger/cactus-api-client";
+
+import { ConsortiumDatabase, Ledger, LedgerType } from "@hyperledger/cactus-core-api";
+
+import { PluginRegistry } from "@hyperledger/cactus-core";
+
+import { DefaultApi as QuorumApi } from "@hyperledger/cactus-plugin-ledger-connector-quorum";
+
+const mainFn \= async () \=> {
+ const ledgerId \= "theIdOfYourLedgerInTheConsortiumDatabase";
+ const consortiumMainApiHost \= "https://cactus.example.com";
+
+ const mainApiClient \= new ApiClient({ basePath: consortiumMainApiHost });
+
+ // This client is now configured to point to a node that has a connector to
+ // the ledger referenced by \`ledgerId\`
+ const apiClient \= await mainApiClient.ofLedger(ledgerId, QuorumApi);
+}
+
+mainFn();
+
+#### Use the API host of a node directly
+
+import { ApiClient } from "@hyperledger/cactus-api-client";
+
+import { ConsortiumDatabase, Ledger, LedgerType } from "@hyperledger/cactus-core-api";
+
+import { PluginRegistry } from "@hyperledger/cactus-core";
+
+import { DefaultApi as QuorumApi } from "@hyperledger/cactus-plugin-ledger-connector-quorum";
+
+const mainFn \= async () \=> {
+ const nodeApiHost \= "https://my-node.cactus.example.com";
+
+ const mainApiClient \= new ApiClient({ basePath: nodeApiHost });
+
+ // This client is now configured to point to a node that has a connector to the ledger of your choice
+ const apiClient \= await mainApiClient.extendWith(QuorumApi);
+}
+
+mainFn();
+
+Public API Surface
+----------------------------------------------------------------------
+
+### `DefaultConsortiumProvider`
+
+Builds the default Consortium provider that can be used by this object to retrieve the Cactus Consortium metadata object when necessary (one such case is when we need information about the consortium nodes to perform routing requests to a specific ledger via a connector plugin, but later other uses could be added as well).
+
+The DefaultConsortiumProvider class leverages the simplest consortium plugin that we have at the time of this writing: @hyperledger/cactus-plugin-consortium-manual which holds the consortium metadata as pre-configured by the consortium operators.
+
+The pattern we use in the ApiClient class is that you can inject your own `IAsyncProvider` implementation which then will be used for routing information and in theory you can implement completely arbitrary consortium management in your own consortium plugins which then Cactus can use and leverage for the routing. This allows us to support any exotic consortium management algorithms that people may come up with such as storing the consortium definition in a multi-sig smart contract or have the list of consortium nodes be powered by some sort of automatic service discovery or anything else that people might think of.
+
+### `ApiClient`
+
+Class responsible for providing additional functionality to the DefaultApi classes of the generated clients (OpenAPI generator / typescript-axios).
+
+Each package (plugin) can define it’s own OpenAPI spec which means that they all can ship with their own `DefaultApi` class that is generated directly from the respective OpenAPI spec of the package/plugin.
+
+The functionality provided by this class is meant to be common traints that can be useful for all of those different `DefaultApi` implementations.
+
+One such common trait is the client side component of the routing that decides which Cactus node to point the `ApiClient` towards (which is in itself ends up being the act of routing).
+
+@see — https ://github.com/OpenAPITools/openapi-generator/blob/v5.0.0-beta2/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache#L337
+
+@see — https ://github.com/OpenAPITools/openapi-generator/blob/v5.0.0/docs/generators/typescript-axios.md
+
+[Previous](../packages.md "Cactus Components") [Next](cactus-cmd-api-server.md "@hyperledger/cactus-cmd-api-server")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-cmd-api-server.md b/docs/docs/cactus/packages/cactus-cmd-api-server.md
new file mode 100644
index 0000000000..fbe8838175
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-cmd-api-server.md
@@ -0,0 +1,441 @@
+`@hyperledger/cactus-cmd-api-server`
+========================================================================================================
+
+* [Summary](#summary)
+
+* [Usage](#usage)
+
+ * [Basic Example](#basic-example)
+
+ * [Remote Plugin Imports at Runtime Example](#remote-plugin-imports-at-runtime-example)
+
+ * [Complete Example](#complete-example)
+
+* [Deployment Scenarios](#deployment-scenarios)
+
+ * [Production Deployment Example](#production-deployment-example)
+
+ * [Low Resource Deployment Example](#low-resource-deployment-example)
+
+* [Containerization](#containerization)
+
+ * [Building the container image locally](#building-the-container-image-locally)
+
+ * [Running the container image locally](#running-the-container-image-locally)
+
+ * [Testing API calls with the container](#testing-api-calls-with-the-container)
+
+* [Prometheus Exporter](#prometheus-exporter)
+
+ * [Usage Prometheus](#usage-prometheus)
+
+ * [Prometheus Integration](#prometheus-integration)
+
+ * [Shutdown Hook](#shutdown-hook)
+
+ * [Helper code](#helper-code) - [response.type.ts](#responsetypets) - [data-fetcher.ts](#data-fetcherts) - [metrics.ts](#metricsts)
+
+* [FAQ](#faq)
+
+ * [What is the difference between a Cactus Node and a Cactus API Server?](#what-is-the-difference-between-a-cactus-node-and-a-cactus-api-server)
+
+ * [Is the API server horizontally scalable?](#is-the-api-server-horizontally-scalable)
+
+ * [Does the API server automatically protect me from malicious plugins?](#does-the-api-server-automatically-protect-me-from-malicious-plugins)
+
+ * [Can I use the API server with plugins deployed as a service?](#can-i-use-the-api-server-with-plugins-deployed-as-a-service)
+
+
+Summary
+------------------------------------------------
+
+This package is part of the Hyperledger Cactus blockchain integration framework and is used as a shell/container of sort for housing different Cactus plugins (which all live in their own npm packages as well).
+
+The API server gives you for free the following benefits, should you choose to use it:
+
+1. Automatic wiring of API endpoints for Cactus plugins which implement the `IPluginWebService` Typescript interface
+
+2. Lightweight inversion of control container provided to plugins in the form of the `PluginRegistry` so that plugins can depend on each other in a way that each plugin instance can be uniquely identified and obtained by other plugins. A great example of this in action is ledger connector plugins frequently using the `PluginRegistry` to look up instances of keychain plugins to get access to secrets that are needed for the connector plugins to accomplish certain tasks such as cryptographically signing some information or SSH-ing into a server instance in order to upload and deploy binary (or otherwise) artifacts of smart contracts.
+
+
+Usage
+--------------------------------------------
+
+Like with most parts of the framework in Cactus, using the `ApiServer` is optional.
+
+To see the `ApiServer` in action, the end to end tests of the framework are a great place to start. A few excerpts that regularly occur in said tests can be seen below as well for the reader’s convenience.
+
+One of our design principles for the framework is **secure by default** which means that the API servers
+
+1. assumes TLS is enabled by default and
+
+2. cross-origin resource sharing is disabled completely
+
+
+### Basic Example
+
+```js
+#!/usr/bin/env node
+
+import { ApiServer } from "../api-server";
+import { ConfigService } from "../config/config-service";
+import { Logger, LoggerProvider } from "@hyperledger/cactus-common";
+
+const log: Logger \= LoggerProvider.getOrCreate({
+ label: "cactus-api",
+ level: "INFO",
+});
+
+const main \= async () \=> {
+ const configService \= new ConfigService();
+ const config \= await configService.getOrCreate();
+ const serverOptions \= config.getProperties();
+
+ LoggerProvider.setLogLevel(serverOptions.logLevel);
+
+ if (process.argv\[2\].includes("help")) {
+ const helpText \= ConfigService.getHelpText();
+ console.log(helpText);
+ log.info(\`Effective Configuration:\`);
+ log.info(JSON.stringify(serverOptions, null, 4));
+ } else {
+ const apiServer \= new ApiServer({ config: serverOptions });
+ await apiServer.start();
+ }
+};
+
+export async function launchApp(): Promise {
+ try {
+ await main();
+ log.info(\`Cactus API server launched OK \`);
+ } catch (ex) {
+ log.error(\`Cactus API server crashed: \`, ex);
+ process.exit(1);
+ }
+}
+
+if (require.main \=== module) {
+ launchApp();
+}
+```
+
+### Remote Plugin Imports at Runtime Example
+
+```js
+import { PluginImportType, PluginImportAction } from "@hyperledger/cactus-core-api";
+import { ApiServer } from "@hyperledger/cactus-cmd-api-server";
+import { ConfigService } from "@hyperledger/cactus-cmd-api-server";
+import { Logger, LoggerProvider } from "@hyperledger/cactus-common";
+
+const main \= async () \=> {
+
+ const configService \= new ConfigService();
+ const apiServerOptions \= await configService.newExampleConfig();
+ // If there is no configuration file on the file system, just set it to empty string
+ apiServerOptions.configFile \= "";
+ // Enable CORS for
+ apiServerOptions.apiCorsDomainCsv \= "your.domain.example.com";
+ apiServerOptions.apiPort \= 3000;
+ apiServerOptions.cockpitPort \= 3100;
+ apiServerOptions.grpcPort \= 5000;
+ // Disble TLS (or provide TLS certs for secure HTTP if you are deploying to production)
+ apiServerOptions.apiTlsEnabled \= false;
+ apiServerOptions.plugins \= \[
+ {
+ // npm package name of the plugin you are installing
+ // Since this will be imported at runtime, you are responsible for
+ // installing the package yourself prior to launching the API server.
+ packageName: "@hyperledger/cactus-plugin-keychain-vault",
+ // The REMOTE value means that a different plugin factory will be imported and
+ // called to obtain the plugin instance. This way plugins can support them
+ // being imported by the API server regardless of the language the plugin
+ // was written in.
+ type: PluginImportType.REMOTE,
+ // The INSTALL value means that the plugin will be installed instead of
+ // only instantiate it
+ action: PluginImportAction.INSTALL,
+ // The options that will be passed in to the plugin factory
+ options: {
+ keychainId: "\_keychainId\_",
+ instanceId: "\_instanceId\_",
+ remoteConfig: configuration,
+ },
+ },
+ \];
+ const config \= await configService.newExampleConfigConvict(apiServerOptions);
+
+ const apiServer \= new ApiServer({
+ config: config.getProperties(),
+ });
+
+ // start the API server here and you are ready to roll
+};
+
+export async function launchApp(): Promise {
+ try {
+ await main();
+ log.info(\`Cactus API server launched OK \`);
+ } catch (ex) {
+ log.error(\`Cactus API server crashed: \`, ex);
+ process.exit(1);
+ }
+}
+
+if (require.main \=== module) {
+ launchApp();
+}
+```
+
+### Complete Example
+
+For a complete example of how to use the API server, read all the code of the supply chain example’s backend package:
+
+https://github.com/hyperledger/cactus/tree/main/examples/cactus-example-supply-chain-backend/src/main/typescript
+
+Deployment Scenarios
+--------------------------------------------------------------------------
+
+There’s a set of building blocks (members, nodes, API server processes, plugin instances) that you can use when defining (founding) a consortium and these building blocks relate to each other in a way that can be expressed with an entity relationship diagram which can be seen below. The composability rules can be deducted from how the diagram elements (entities) are connected (related) to each other, e.g. the API server process can have any number of plugin instances in it and a node can contain any number of API server processes, and so on until the top level construct is reached: the consortium.
+
+> Consortium management does not relate to achieving consensus on data/transactions involving individual ledgers, merely about consensus on the metadata of a consortium.
+
+![deployment-entity-relationship-diagram.png](https://github.com/hyperledger/cactus/raw/4a337be719a9d2e2ccb877edccd7849f4be477ec/whitepaper/deployment-entity-relationship-diagram.png)
+
+Now, with these composability rules in mind, let us demonstrate a few different deployment scenarios (both expected and exotic ones) to showcase the framework’s flexibility in this regard.
+
+### Production Deployment Example
+
+Many different configurations are possible here as well. One way to have two members form a consortium and both of those members provide highly available, high throughput services is to have a deployment as shown on the below figure. What is important to note here is that this consortium has 2 nodes, 1 for each member and it is irrelevant how many API servers those nodes have internally because they all respond to requests through the network host/web domain that is tied to the node. One could say that API servers do not have a distinguishable identity relative to their peer API servers, only the higher-level nodes do.
+
+![deployment-production-example.png](https://github.com/hyperledger/cactus/raw/4a337be719a9d2e2ccb877edccd7849f4be477ec/whitepaper/deployment-production-example.png)
+
+### Low Resource Deployment Example
+
+This is an example to showcase how you can pull up a full consortium even from within a single operating system process (API server) with multiple members and their respective nodes. It is not something that’s recommended for a production grade environment, ever, but it is great for demos and integration tests where you have to simulate a fully functioning consortium with as little hardware footprint as possible to save on time and cost.
+
+The individual nodes/API servers are isolated by listening on seperate TCP ports of the machine they are hosted on:
+
+![deployment-low-resource-example.png](https://github.com/hyperledger/cactus/raw/4a337be719a9d2e2ccb877edccd7849f4be477ec/whitepaper/deployment-low-resource-example.png)
+
+Containerization
+------------------------------------------------------------------
+
+### Building the container image locally
+
+In the Cactus project root say:
+
+DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-cmd-api-server/Dockerfile . \-t cas \-t cactus-api-server
+
+Build with a specific version of the npm package:
+
+DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=main \-f ./packages/cactus-cmd-api-server/Dockerfile . \-t cas \-t cactus-api-server
+
+### Running the container image locally
+
+Before running the examples here you need to build the image locally. See section [Building the container image locally](#building-the-container-image-locally) for details on how to do that.
+
+Once you’ve built the container, the following commands should work:
+
+* Launch container - no plugins, default configuration
+
+ docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ cas
+
+* Launch container with plugins of your choice (keychain, consortium connector, etc.)
+
+ docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ cas \\
+ ./node\_modules/.bin/cactusapi \\
+ \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": { "connectionProfile": {}, "instanceId": "some-unique-instance-id"}}\]'
+
+* Launch container with plugin configuration as an **environment variable**:
+
+ docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\
+ cas
+
+* Launch container with plugin configuration as a **CLI argument**:
+
+ docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ cas \\
+ ./node\_modules/.bin/cactusapi \\
+ \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]'
+
+* Launch container with **configuration file** mounted from host machine:
+
+ echo '\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \> cactus.json
+
+ docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\
+ cas \\
+ ./node\_modules/.bin/cactusapi \\
+ \--config-file\=/cactus.json
+
+
+### Testing API calls with the container
+
+Don’t have a Besu network on hand to test with? Test or develop against our Besu All-In-One container!
+
+1. Terminal Window 1 (Ledger)
+
+ docker run \--publish 8545:8545 hyperledger/cactus-besu-all-in-one:latest
+
+2. Terminal Window 2 (Cactus API Server)
+
+ docker run \\
+ \--network host \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\
+ cas
+
+3. Terminal Window 3 (curl - replace eth accounts as needed)
+
+ curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/run-transaction' \\
+ --header 'Content-Type: application/json' \\
+ --data-raw '{
+ "web3SigningCredential": {
+ "ethAccount": "627306090abaB3A6e1400e9345bC60c78a8BEf57",
+ "secret": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
+ "type": "PRIVATE\_KEY\_HEX"
+ },
+ "consistencyStrategy": {
+ "blockConfirmations": 0,
+ "receiptType": "NODE\_TX\_POOL\_ACK"
+ },
+ "transactionConfig": {
+ "from": "627306090abaB3A6e1400e9345bC60c78a8BEf57",
+ "to": "f17f52151EbEF6C7334FAD080c5704D77216b732",
+ "value": 1,
+ "gas": 10000000
+ }
+ }'
+
+4. The above should produce a response that looks similar to this:
+
+ {
+ "success": true,
+ "data": {
+ "transactionReceipt": {
+ "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd",
+ "blockNumber": 1218,
+ "contractAddress": null,
+ "cumulativeGasUsed": 21000,
+ "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
+ "gasUsed": 21000,
+ "logs": \[\],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": true,
+ "to": "0xf17f52151ebef6c7334fad080c5704d77216b732",
+ "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f",
+ "transactionIndex": 0
+ }
+ }
+ }
+
+
+Prometheus Exporter
+------------------------------------------------------------------------
+
+This class creates a prometheus exporter, which scrapes the total Cactus node count.
+
+### Usage Prometheus
+
+The prometheus exporter object is initialized in the `ApiServer` class constructor itself, so instantiating the object of the `ApiServer` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IApiServerConstructorOptions` interface for `ApiServer` constructor.
+
+`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total plugins imported, which currently refreshes to match the plugin count, everytime `setTotalPluginImports` method is called.
+
+### Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'consortium\_manual\_exporter'
+ metrics\_path: /api/v1/api-server/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-consortium-manual/src/test/typescript/unit/consortium/get-node-jws-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/api-server/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_api\_server\_total\_plugin\_imports** and click **execute**
+
+### Shutdown Hook
+
+The API config contains a flag:
+
+ {
+ "enableShutdownHook": true
+ }
+
+This allows for graceful shutdown of the API server after a SIGINT via cli CTRL + C. This hook can be disabled by passing in false either via the TypeScript constructor or the JSON config file.
+
+### Helper code
+
+#### response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points.
+
+#### metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+FAQ
+----------------------------------------
+
+### What is the difference between a Cactus Node and a Cactus API Server?
+
+The node is what has an identity within your PKI and can be made up of 1-N API server instances that all share the same configuration/identity of the node. See deployment scenarios above for a much more detailed explanation.
+
+### Is the API server horizontally scalable?
+
+**Yes, 100%.** Keep in mind though that the API server can be loaded up with arbitrary plugins meaning that if you write a plugin that has a central database that can only do 1 transaction per second, then it will not help you much that the API server itself is horizontally scalable because deploying a thousand instances of the API server will just result in you having a thousand instances of your plugin all waiting for that underlying database with its 1 TPS throughput hogging your system. When we say that the API server is horizontally scalable, we mean that the API server itself is designed not to have any such state mentioned in the example above. You are responsible for only deploying plugins in the API server that are horizontally scalable as well. In short, your whole system is only horizontally scalable if all components of it are horizontally scalable.
+
+### Does the API server automatically protect me from malicious plugins?
+
+**No.** If you install a third-party plugin that wasn’t vetted by anyone and that plugin happens to have malicious code in it to steal your private keys, it can do so. You are responsible for making sure that the plugins you install have no known security vulnerabilities or backdoors e.g. they are considered “secure”. The double quotes around “secure” is meant to signify the fact that no software is ever really truly secure, just merely lacking of known vulnerabilities at any given point in time.
+
+### Can I use the API server with plugins deployed as a service?
+
+**Yes.** You can deploy your plugin written in any language, anywhere as long as it is accessible over the network and does come with a Typescript API client that you can use to install into the API server as a proxy for an in-process plugin implementation.
+
+[Previous](cactus-api-client.md "@hyperledger/cactus-api-client") [Next](cactus-common.md "@hyperledger/cactus-common")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-common.md b/docs/docs/cactus/packages/cactus-common.md
new file mode 100644
index 0000000000..d3f73629f9
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-common.md
@@ -0,0 +1,13 @@
+`@hyperledger/cactus-common`
+=======================================================================================
+
+> TODO: description
+
+Usage
+--------------------------------------------
+
+// TODO: DEMONSTRATE API
+
+[Previous](cactus-cmd-api-server.md "@hyperledger/cactus-cmd-api-server") [Next](cactus-core.md "@hyperledger/cactus-core")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-core.md b/docs/docs/cactus/packages/cactus-core.md
new file mode 100644
index 0000000000..91475dc7c0
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-core.md
@@ -0,0 +1,17 @@
+`@hyperledger/cactus-core`
+===================================================================================
+
+This module is responsible for providing the backbone for the rest of the packages when it comes to the features of Cactus.
+
+The main difference between this and the `cactus-common` package is that this one does not guarantee it’s features to work in the browser.
+
+The main difference from the `cactus-core-api` package is that this is meant to contain actual implementations while `cactus-core-api` is meant to be strictly about defining interfaces. Based on that latter constraint we may move the `PluginRegistry` out of that package and into this one in the near future.
+
+Usage
+--------------------------------------------
+
+// TODO: DEMONSTRATE API
+
+[Previous](cactus-common.md "@hyperledger/cactus-common") [Next](cactus-plugin-consortium-manual.md "@hyperledger/cactus-plugin-consortium-manual")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-plugin-consortium-manual.md b/docs/docs/cactus/packages/cactus-plugin-consortium-manual.md
new file mode 100644
index 0000000000..6ceb752371
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-plugin-consortium-manual.md
@@ -0,0 +1,45 @@
+`@hyperledger/cactus-plugin-consortium-manual`
+===========================================================================================================================
+
+Prometheus Exporter
+------------------------------------------------------------------------
+
+This class creates a prometheus exporter, which scrapes the total Cactus node count.
+
+### Usage Prometheus
+
+The prometheus exporter object is initialized in the `PluginConsortiumManual` class constructor itself, so instantiating the object of the `PluginConsortiumManual` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginConsortiumManualOptions` interface for `PluginConsortiumManual` constructor.
+
+`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total cactus node count, which currently refreshes to match the node count in the consortium, everytime `updateMetricNodeCount` method of the `PluginConsortiumManual` class is called.
+
+### Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'consortium\_manual\_exporter'
+ metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-consortium-manual/src/test/typescript/unit/consortium/get-node-jws-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_consortium\_manual\_total\_node\_count** and click **execute**
+
+### Helper code
+
+#### response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points.
+
+#### metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+[Previous](cactus-core.md "@hyperledger/cactus-core") [Next](cactus-plugin-keychain-vault.md "@hyperledger/cactus-plugin-keychain-vault")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-plugin-keychain-vault.md b/docs/docs/cactus/packages/cactus-plugin-keychain-vault.md
new file mode 100644
index 0000000000..440986e911
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-plugin-keychain-vault.md
@@ -0,0 +1,45 @@
+`@hyperledger/cactus-plugin-keychain-vault`
+=====================================================================================================================
+
+Prometheus Exporter
+------------------------------------------------------------------------
+
+This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Keychain vault plugin.
+
+### Usage
+
+The prometheus exporter object is initialized in the `PluginKeychainVault` class constructor itself, so instantiating the object of the `PluginKeychainVault` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginKeychainVaultOptions` interface for `PluginKeychainVault` constructor.
+
+`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total key count, which currently increments everytime the `set()` and `delete()` method of the `PluginKeychainVault` class is called.
+
+### Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'keychain\_vault\_exporter'
+ metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-keychain-vault/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-keychain-plugin/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_keychain\_vault\_total\_key\_count** and click **execute**
+
+### Helper code
+
+#### response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points
+
+#### metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+[Previous](cactus-plugin-consortium-manual.md "@hyperledger/cactus-plugin-consortium-manual") [Next](cactus-plugin-ledger-connector-besu.md "@hyperledger/cactus-plugin-ledger-connector-besu")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-besu.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-besu.md
new file mode 100644
index 0000000000..87184d4614
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-besu.md
@@ -0,0 +1,314 @@
+`@hyperledger/cactus-plugin-ledger-connector-besu`
+===================================================================================================================================
+
+This plugin provides `Cactus` a way to interact with Besu networks. Using this we can perform:
+
+* Deploy Smart-contracts through bytecode.
+
+* Build and sign transactions using different keystores.
+
+* Invoke smart-contract functions that we have deployed on the network.
+
+
+Summary
+------------------------------------------------
+
+* [Getting Started](#getting-started)
+
+* [Architecture](#architecture)
+
+* [Usage](#usage)
+
+* [Prometheus Exporter](#prometheus-exporter)
+
+* [Runing the tests](#running-the-tests)
+
+* [Built With](#built-with)
+
+* [Contributing](#contributing)
+
+* [License](#license)
+
+* [Acknowledgments](#acknowledgments)
+
+
+Getting Started
+----------------------------------------------------------------
+
+Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on your local machine for development and testing purposes.
+
+### Prerequisites
+
+In the root of the project to install the dependencies execute the command:
+
+npm run configure
+
+### Compiling
+
+In the project root folder, run this command to compile the plugin and create the dist directory:
+
+npm run tsc
+
+### Architecture
+
+The sequence diagrams for various endpoints are mentioned below
+
+#### run-transaction-endpoint
+
+![run-transaction-endpoint sequence diagram](../_images/run-transaction-endpoint.png) The above diagram shows the sequence diagram of run-transaction-endpoint. User A (One of the many Users) interacts with the API Client which in turn, calls the API server. API server then executes transact() method which is explained in detailed in the subsequent diagrams. ![run-transaction-endpoint transact() method](../_images/run-transaction-endpoint-transact.png) The above diagram shows the sequence diagram of transact() method of the PluginLedgerConnectorBesu class. The caller to this function, which in reference to the above sequence diagram is API server, sends RunTransactionRequest object as an argument to the transact() method. Based on the type of Web3SigningCredentialType, corresponsing responses are sent back to the caller.
+![run-transaction-endpoint transactCactusKeychainRef() method](../_images/run-transaction-endpoint-transact-cactuskeychainref.png) The above diagram shows transactCactusKeychainReference() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is CACTUSKEYCHAINREF. This method inturn calls transactPrivateKey() which calls the signTransaction() method of web3 library. ![runtransaction-endpoint transactPrivateKey() method](../_images/run-transaction-endpoint-transact-privatekey.png) The above diagram shows transactPrivateKey() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is PRIVATEKEYHEX. This method then calls the signTransaction() method of the web3 library. ![run-transaction-endpoint transactSigned() method](../_images/run-transaction-endpoint-transact-signed.png) The above diagram shows transactSigned() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is NONE. This method calls the sendSignedTransaction() of the web3 library and then calls pollForTxReceipt() method. ![run-transaction-endpoint pollForTxReceipt() method](../_images/run-transaction-endpoint-transact-pollfortxreceipt.png) The above diagram shows pollForTxReceipt() method which is called by the transactSigned() method as described in the previous sequence diagram. This method waits for the block confirmation in a loop and then sends the corresponding response back to the caller.
+
+### Usage
+
+To use this import public-api and create new **PluginFactoryLedgerConnector**. Then use it to create a connector.
+
+const factory \= new PluginFactoryLedgerConnector({
+ pluginImportType: PluginImportType.LOCAL,
+ });
+ const connector: PluginLedgerConnectorBesu \= await factory.create({
+ rpcApiHttpHost,
+ instanceId: uuidv4(),
+ pluginRegistry: new PluginRegistry(),
+ });
+
+You can make calls through the connector to the plugin API:
+
+async invokeContract(req: InvokeContractV1Request):Promise;
+async transactSigned(rawTransaction: string): Promise;
+async transactPrivateKey(req: RunTransactionRequest): Promise;
+async transactCactusKeychainRef(req: RunTransactionRequest):Promise;
+async deployContract(req: DeployContractSolidityBytecodeV1Request):Promise;
+async signTransaction(req: SignTransactionRequest):Promise>;
+
+Call example to deploy a contract:
+
+const deployOut \= await connector.deployContract({
+ web3SigningCredential: {
+ ethAccount: firstHighNetWorthAccount,
+ secret: besuKeyPair.privateKey,
+ type: Web3SigningCredentialType.PrivateKeyHex,
+ },
+ bytecode: SmartContractJson.bytecode,
+ gas: 1000000,
+});
+
+The field “type” can have the following values:
+
+enum Web3SigningCredentialType {
+ CACTUSKEYCHAINREF \= 'CACTUS\_KEYCHAIN\_REF',
+ GETHKEYCHAINPASSWORD \= 'GETH\_KEYCHAIN\_PASSWORD',
+ PRIVATEKEYHEX \= 'PRIVATE\_KEY\_HEX',
+ NONE \= 'NONE'
+}
+
+### Transaction Privacy Feature
+
+Private transactions using Besu are currently enabled.
+
+The privateFor and privateFrom fields must be populated, more information about Besu Private Transactions [here](https://besu.hyperledger.org/en/stable/Concepts/Privacy/Private-Transactions/).
+
+Call example to deploy a private contract:
+
+ const deployOut \= await connector1.deployContract({
+ bytecode: SmartContract.bytecode,
+ contractAbi: SmartContract.abi,
+ contractName: SmartContract.contractName,
+ constructorArgs: \[\],
+ privateTransactionConfig: {
+ privateFrom: SendingTesseraPublicKey,
+ privateFor: \[
+ Member1TesseraPrivateKey,
+ Member2TesseraPrivateKey,
+ \],
+ },
+ web3SigningCredential: {
+ secret:SendingBesuPrivateKey,
+ type: Web3SigningCredentialType.PrivateKeyHex,
+ },
+ gas: 3000000
+ });
+
+> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP)
+
+### Building/running the container image locally
+
+In the Cactus project root say:
+
+DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-plugin-ledger-connector-besu/Dockerfile . \-t cplcb
+
+Build with a specific version of the npm package:
+
+DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=1.0.0 \-f ./packages/cactus-plugin-ledger-connector-besu/Dockerfile . \-t cplcb
+
+#### Running the container
+
+Launch container with plugin configuration as an **environment variable**:
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\
+ cplcb
+
+Launch container with plugin configuration as a **CLI argument**:
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ cplcb \\
+ ./node\_modules/.bin/cactusapi \\
+ \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]'
+
+Launch container with **configuration file** mounted from host machine:
+
+echo '\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \> cactus.json
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\
+ cplcb \\
+ ./node\_modules/.bin/cactusapi \\
+ \--config-file\=/cactus.json
+
+#### Testing API calls with the container
+
+Don’t have a Besu network on hand to test with? Test or develop against our Besu All-In-One container!
+
+**Terminal Window 1 (Ledger)**
+
+docker run \\
+ \--publish 0.0.0.0:8545:8545/tcp \\
+ \--publish 0.0.0.0:8546:8546/tcp \\
+ \--publish 0.0.0.0:8888:8888/tcp \\
+ \--publish 0.0.0.0:9001:9001/tcp \\
+ \--publish 0.0.0.0:9545:9545/tcp \\
+ ghcr.io/hyperledger/cactus-besu-all-in-one:2022-05-12-2330a96
+
+**Terminal Window 2 (Cactus API Server)**
+
+docker run \\
+ \--network host \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env GRPC\_TLS\_ENABLED\=false \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\
+ cplcb
+
+**Terminal Window 3 (curl - replace eth accounts as needed)**
+
+curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/run-transaction' \\
+--header 'Content-Type: application/json' \\
+--data-raw '{
+ "web3SigningCredential": {
+ "ethAccount": "627306090abaB3A6e1400e9345bC60c78a8BEf57",
+ "secret": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
+ "type": "PRIVATE\_KEY\_HEX"
+ },
+ "consistencyStrategy": {
+ "blockConfirmations": 0,
+ "receiptType": "NODE\_TX\_POOL\_ACK"
+ },
+ "transactionConfig": {
+ "from": "627306090abaB3A6e1400e9345bC60c78a8BEf57",
+ "to": "f17f52151EbEF6C7334FAD080c5704D77216b732",
+ "value": 1,
+ "gas": 10000000
+ }
+}'
+
+The above should produce a response that looks similar to this:
+
+{
+ "success": true,
+ "data": {
+ "transactionReceipt": {
+ "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd",
+ "blockNumber": 1218,
+ "contractAddress": null,
+ "cumulativeGasUsed": 21000,
+ "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
+ "gasUsed": 21000,
+ "logs": \[\],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": true,
+ "to": "0xf17f52151ebef6c7334fad080c5704d77216b732",
+ "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f",
+ "transactionIndex": 0
+ }
+ }
+}
+
+Prometheus Exporter
+------------------------------------------------------------------------
+
+This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Besu connector plugin.
+
+### Prometheus Exporter Usage
+
+The prometheus exporter object is initialized in the `PluginLedgerConnectorBesu` class constructor itself, so instantiating the object of the `PluginLedgerConnectorBesu` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorBesuOptions` interface for `PluginLedgerConnectoBesu` constructor.
+
+`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorBesu` class is called.
+
+### Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'besu\_ledger\_connector\_exporter'
+ metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_besu\_total\_tx\_count** and click **execute**
+
+### Helper code
+
+#### response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points
+
+#### metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+Running the tests
+--------------------------------------------------------------------
+
+To check that all has been installed correctly and that the pugin has no errors run the tests:
+
+* Run this command at the project’s root:
+
+
+npm run test:plugin-ledger-connector-besu
+
+Contributing
+----------------------------------------------------------
+
+We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do!
+
+Please review [CONTIRBUTING.md](#../../CONTRIBUTING.md) to get started.
+
+License
+------------------------------------------------
+
+This distribution is published under the Apache License Version 2.0 found in the [LICENSE](#../../LICENSE) file.
+
+Acknowledgments
+----------------------------------------------------------------
+
+[Previous](cactus-plugin-keychain-vault.md "@hyperledger/cactus-plugin-keychain-vault") [Next](cactus-plugin-ledger-connector-corda.md "@hyperledger/cactus-plugin-ledger-connector-corda")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-corda.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-corda.md
new file mode 100644
index 0000000000..d4e55a8f53
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-corda.md
@@ -0,0 +1,580 @@
+`@hyperledger/cactus-plugin-ledger-connector-corda`
+======================================================================================================================================
+
+Summary
+------------------------------------------------
+
+The Corda connector is written in Kotlin and ships as a Spring Boot JVM application that accepts API requests and translates those into Corda RPC calls.
+
+Deploying the Corda connector therefore involves also deploying the mentioned JVM application **in addition** to deploying the Cactus API server with the desired plugins configured.
+
+Concepts
+--------------------------------------------------
+
+### Contract Invocation JSON DSL
+
+One of our core design principles for Hyperledger Cactus is to have low impact deployments meaning that changes to the ledgers themselves should be kept to a minimum or preferably have no need for any at all. With this in mind, we had to solve the challenge of providing users with the ability to invoke Corda flows as dynamically as possible within the confines of the strongly typed JVM contrasted with the weakly typed Javascript language runtime of NodeJS.
+
+Corda might release some convenience features to ease this in the future, but in the meantime we have the _Contract Invocation JSON DSL_ which allows developers to specify truly arbitrary JVM types as part of their contract invocation arguments even if otherwise these types would not be possible to serialize or deserialize with traditional tooling such as the excellent [Jackson JSON Java library](https://github.com/FasterXML/jackson) or similar ones.
+
+### Expressing Primitive vs Reference Types with the DLS
+
+The features of the DSL include expressing whether a contract invocation parameter is a reference or a primitive JVM data types. This is a language feature that Javascript has as well to some extent, but for those in need of a refresher, here’s a writeup from a well known Q/A website that I found on the internet: [What’s the difference between primitive and reference types?](https://stackoverflow.com/a/32049775/698470)
+
+To keep it simple, the following types are primitive data types in the Java Virtual Machine (JVM) and everything else not included in the list below can be safely considered a reference type:
+
+* boolean
+
+* byte
+
+* short
+
+* char
+
+* int
+
+* long
+
+* float
+
+* double
+
+
+If you’d like to further clarify how this works and feel like an exciting adventure then we recommend that you dive into the source code of the [deserializer implementation of the JSON DSL](https://github.com/hyperledger/cactus/blob/main/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/JsonJvmObjectDeserializer.kt) and take a look at the following points of interest in the code located there:
+
+* `val exoticTypes: Map>`
+
+* `fun instantiate(jvmObject: JvmObject)`
+
+
+### Flow Invocation Types
+
+Can be **dynamic** or **tracked dynamic** and the corresponding enum values are defined as:
+
+/\*\*
+ \* Determines which flow starting method will be used on the back-end when invoking the flow. Based on the value here the plugin back-end might invoke the rpc.startFlowDynamic() method or the rpc.startTrackedFlowDynamic() method. Streamed responses are aggregated and returned in a single response to HTTP callers who are not equipped to handle streams like WebSocket/gRPC/etc. do.
+ \* @export
+ \* @enum {string}
+ \*/
+export enum FlowInvocationType {
+ TRACKEDFLOWDYNAMIC \= 'TRACKED\_FLOW\_DYNAMIC',
+ FLOWDYNAMIC \= 'FLOW\_DYNAMIC'
+}
+
+[Official Corda Java Docs - startFlowDynamic()](https://api.corda.net/api/corda-os/4.7/html/api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/start-flow-dynamic.html)
+
+[Official Corda Java Docs - startTrackedFlowDynamic()](https://api.corda.net/api/corda-os/4.7/html/api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/start-tracked-flow-dynamic.html)
+
+Usage
+--------------------------------------------
+
+Take a look at how the API client can be used to run transactions on a Corda ledger: `packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts`
+
+### Invoke Contract (flow) with no parameters
+
+Below, we’ll demonstrate invoking a simple contract with no parameters.
+
+**The contract source:**
+
+package com.example.organization.samples.application.flows;
+
+class SomeCoolFlow {
+ // constructor with no arguments
+ public SomeCoolFlow() {
+ this.doSomething();
+ }
+
+ public doSomething(): void {
+ throw new RuntimeException("Method not implemented.");
+ }
+}
+
+**Steps to build your request:**
+
+1. Find out the fully qualified class name of your contract (flow) and set this as the value for the request parameter `flowFullClassName`
+
+2. Decide on your flow invocation type which largely comes down to answering the question of: Does your invocation follow a request/response pattern or more like a channel subscription where multiple updates at different times are streamed to the client in response to the invocation request? In our example we assume the simpler request/response communication pattern and therefore will set the `flowInvocationType` to `FlowInvocationType.FLOWDYNAMIC`
+
+3. Invoke the flow via the API client with the `params` argument being specified as an empty array `[]`
+
+ import { DefaultApi as CordaApi } from "@hyperledger/cactus-plugin-ledger-connector-corda";
+ import { FlowInvocationType } from "@hyperledger/cactus-plugin-ledger-connector-corda";
+
+ const apiUrl \= "your-cactus-host.example.com"; // don't forget to specify the port if applicable
+ const apiClient \= new CordaApi({ basePath: apiUrl });
+
+ const res \= await apiClient.invokeContractV1({
+ flowFullClassName: "com.example.organization.samples.application.flows.SomeCoolFlow",
+ flowInvocationType: FlowInvocationType.FLOWDYNAMIC,
+ params: \[\],
+ timeoutMs: 60000,
+ });
+
+
+### Invoke Contract (flow) with a single integer parameter
+
+Below, we’ll demonstrate invoking a simple contract with a single numeric parameter.
+
+**The contract source:**
+
+package com.example.organization.samples.application.flows;
+
+class SomeCoolFlow {
+ // constructor with a primitive type long argument
+ public SomeCoolFlow(long myParameterThatIsLong) {
+ // do something with the parameter here
+ }
+}
+
+**Steps to build your request:**
+
+1. Find out the fully qualified class name of your contract (flow) and set this as the value for the request parameter `flowFullClassName`
+
+2. Decide on your flow invocation type. More details at [Invoke Contract (flow) with no parameters](#invoke-contract-flow-with-no-parameters)
+
+3. Find out what is the fully qualified class name of the parameter you wish to pass in. You can do this be inspecting the sources of the contract itself. If you do not have access to those sources, then the documentation of the contract should have answers or the person who authored said contract. In our case here the fully qualified class name for the number parameter is simply `long` because it is a primitive data type and as such these can be referred to in their short form, but the fully qualified version also works such as: `java.lang.Long`. When in doubt about these, you can always consult the [official java.lang.Long Java Docs](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Long.html) After having determined the above, you can construct your first `JvmObject` JSON object as follows in order to pass in the number `42` as the first and only parameter for our flow invocation:
+
+ params: \[
+ {
+ jvmTypeKind: JvmTypeKind.PRIMITIVE,
+ jvmType: {
+ fqClassName: "long",
+ },
+ primitiveValue: 42,
+ }
+ \]
+
+4. Invoke the flow via the API client with the `params` populated as explained above:
+
+ import { DefaultApi as CordaApi } from "@hyperledger/cactus-plugin-ledger-connector-corda";
+ import { FlowInvocationType } from "@hyperledger/cactus-plugin-ledger-connector-corda";
+
+ // don't forget to specify the port if applicable
+ const apiUrl \= "your-cactus-host.example.com";
+ const apiClient \= new CordaApi({ basePath: apiUrl });
+
+ const res \= await apiClient.invokeContractV1({
+ flowFullClassName: "com.example.organization.samples.application.flows.SomeCoolFlow",
+ flowInvocationType: FlowInvocationType.FLOWDYNAMIC,
+ params: \[
+ {
+ jvmTypeKind: JvmTypeKind.PRIMITIVE,
+ jvmType: {
+ fqClassName: "long",
+ },
+ primitiveValue: 42,
+ }
+ \],
+ timeoutMs: 60000,
+ });
+
+
+### Invoke Contract (flow) with a custom class parameter
+
+Below, we’ll demonstrate invoking a contract with a single class instance parameter.
+
+**The contract sources:**
+
+package com.example.organization.samples.application.flows;
+
+// contract with a class instance parameter
+class BuildSpaceshipFlow {
+ public BuildSpaceshipFlow(SpaceshipInfo buildSpecs) {
+ // build spaceship as per the specs
+ }
+}
+
+package com.example.organization.samples.application.flows;
+
+// The type that the contract accepts as an input parameter
+class SpaceshipInfo {
+ public SpaceshipInfo(String name, Integer seatsForHumans) {
+ }
+}
+
+**Assembling and Sending your request:**
+
+Invoke the flow via the API client with the `params` populated as shown below.
+
+Key thing notice here is that we now have a class instance as a parameter for our contract (flow) invocation so we have to describe how this class instance itself will be instantiated by providing a nested array of parameters via the `jvmCtorArgs` which stands for Java Virtual Machine Constructor Arguments meaning that elements of this array will be passed in dynamically (via Reflection) to the class constructor.
+
+**Java Equivalent**
+
+cordaRpcClient.startFlowDynamic(
+ BuildSpaceshipFlow.class,
+ new SpaceshipInfo(
+ "The last spaceship you'll ever need.",
+ 10000000
+ )
+);
+
+**Cactus Invocation JSON DLS Equivalent to the Above Java Snippet**
+
+import { DefaultApi as CordaApi } from "@hyperledger/cactus-plugin-ledger-connector-corda";
+import { FlowInvocationType } from "@hyperledger/cactus-plugin-ledger-connector-corda";
+
+// don't forget to specify the port if applicable
+const apiUrl \= "your-cactus-host.example.com";
+const apiClient \= new CordaApi({ basePath: apiUrl });
+
+const res \= await apiClient.invokeContractV1({
+ flowFullClassName: "com.example.organization.samples.application.flows.BuildSpaceshipFlow",
+ flowInvocationType: FlowInvocationType.FLOWDYNAMIC,
+ params: \[
+ {
+ jvmTypeKind: JvmTypeKind.REFERENCE,
+ jvmType: {
+ fqClassName: "com.example.organization.samples.application.flows.SpaceshipInfo",
+ },
+
+ jvmCtorArgs: \[
+ {
+ jvmTypeKind: JvmTypeKind.PRIMITIVE,
+ jvmType: {
+ fqClassName: "java.lang.String",
+ },
+ primitiveValue: "The last spaceship you'll ever need.",
+ },
+ {
+ jvmTypeKind: JvmTypeKind.PRIMITIVE,
+ jvmType: {
+ fqClassName: "java.lang.Long",
+ },
+ primitiveValue: 10000000000,
+ },
+ \],
+ }
+ \],
+ timeoutMs: 60000,
+});
+
+### Transaction Monitoring
+
+* There are two interfaces to monitor changes of vault states - reactive `watchBlocksV1` method, and low-level HTTP API calls.
+
+* Note: The monitoring APIs are implemented only on kotlin-server connector (`main-server`), not typescript connector!
+
+* For usage examples review the functional test file: `packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/monitor-transactions-v4.8.test.ts`
+
+* Because transactions read from corda are stored on the connector, they will be lost if connector is closed/killed before transaction were read by the clients.
+
+* Each client has own set of state monitors that are managed independently. After starting the monitoring, each new transaction is queued on the connector until read and explicitly cleared by `watchBlocksV1` or direct HTTP API call.
+
+* Client monitors can be periodically removed by the connector, if there was no action from the client for specified amount of time.
+
+* Client expiration delay can be configured with `cactus.sessionExpireMinutes` option. It default to 30 minutes.
+
+* Each transaction has own index assigned by the corda connector. Index is unique for each client monitoring session. For instance:
+
+ * Stopping monitoring for given state will reset the transaction index counter for given client. After restart, it will report first transaction with index 0.
+
+ * Each client can see tha same transaction with different index.
+
+ * Index can be used to determine the transaction order for given client session.
+
+
+#### watchBlocksV1
+
+* `watchBlocksV1(options: watchBlocksV1Options): Observable`
+
+* Reactive (RxJS) interface to observe state changes.
+
+* Internally, it uses polling of low-level HTTP APIs.
+
+* Watching block should return each block at least once, no blocks should be missed after startMonitor has started. The only case when transaction is lost is when connector we were connected to died.
+
+* Transactions can be duplicated in case internal `ClearMonitorTransactionsV1` call was not successful (for instance, because of connection problems).
+
+* Options:
+
+ * `stateFullClassName: string`: state to monitor.
+
+ * `pollRate?: number`: how often poll the kotlin server for changes (default 5 seconds).
+
+
+#### Low-level HTTP API
+
+* These should not be used when watchBlocks API is sufficient.
+
+* Consists of the following methods:
+
+ * `startMonitorV1`: Start monitoring for specified state changes. All changes after calling this function will be stored in internal kotlin-server buffer, ready to be read by calls to `GetMonitorTransactionsV1`. Transactions occuring before the call to startMonitorV1 will not be reported.
+
+ * `GetMonitorTransactionsV1`: Read all transactions for given state name still remaining in internal buffer.
+
+ * `ClearMonitorTransactionsV1`: Remove transaction for given state name with specified index number from internal buffer. Should be used to acknowledge receiving specified transactions in user code, so that transactions are not reported multiple times.
+
+ * `stopMonitorV1`: Don’t watch for transactions changes anymore, remove any transactions that were not read until now.
+
+
+### Custom Configuration via Env Variables
+
+{
+ "cactus": {
+ "threadCount": 3,
+ "sessionExpireMinutes": 10,
+ "corda": {
+ "node": {
+ "host": "localhost"
+ },
+ "rpc": {
+ "port": 10006,
+ "username": "user1",
+ "password": "test"
+ }
+ }
+ }
+}
+
+SPRING\_APPLICATION\_JSON\='{"cactus":{"corda":{"node": {"host": "localhost"}, "rpc":{"port": 10006, "username":"user1", "password": "test"}}}}' gradle test
+
+{
+ "flowFullClassName" : "net.corda.samples.example.flows.ExampleFlow${"$"}Initiator",
+ "flowInvocationType" : "FLOW\_DYNAMIC",
+ "params" : \[ {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.Integer"
+ },
+ "primitiveValue" : 42,
+ "jvmCtorArgs" : null
+ }, {
+ "jvmTypeKind" : "REFERENCE",
+ "jvmType" : {
+ "fqClassName" : "net.corda.core.identity.Party"
+ },
+ "primitiveValue" : null,
+ "jvmCtorArgs" : \[ {
+ "jvmTypeKind" : "REFERENCE",
+ "jvmType" : {
+ "fqClassName" : "net.corda.core.identity.CordaX500Name"
+ },
+ "primitiveValue" : null,
+ "jvmCtorArgs" : \[ {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.String"
+ },
+ "primitiveValue" : "PartyB",
+ "jvmCtorArgs" : null
+ }, {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.String"
+ },
+ "primitiveValue" : "New York",
+ "jvmCtorArgs" : null
+ }, {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.String"
+ },
+ "primitiveValue" : "US",
+ "jvmCtorArgs" : null
+ } \]
+ }, {
+ "jvmTypeKind" : "REFERENCE",
+ "jvmType" : {
+ "fqClassName" : "org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl.PublicKeyImpl"
+ },
+ "primitiveValue" : null,
+ "jvmCtorArgs" : \[ {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.String"
+ },
+ "primitiveValue" : "EdDSA",
+ "jvmCtorArgs" : null
+ }, {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.String"
+ },
+ "primitiveValue" : "X.509",
+ "jvmCtorArgs" : null
+ }, {
+ "jvmTypeKind" : "PRIMITIVE",
+ "jvmType" : {
+ "fqClassName" : "java.lang.String"
+ },
+ "primitiveValue" : "MCowBQYDK2VwAyEAoOv19eiCDJ7HzR9UrfwbFig7qcD1jkewKkkS4WF9kPA=",
+ "jvmCtorArgs" : null
+ } \]
+ } \]
+ } \],
+ "timeoutMs" : null
+}
+
+I 16:51:01 1 Client.main - nodeDiagnosticInfo=
+{
+ "version" : "4.6",
+ "revision" : "85e387ea730d9be7d6dc2b23caba1ee18305af74",
+ "platformVersion" : 8,
+ "vendor" : "Corda Open Source",
+ "cordapps" : \[ {
+ "type" : "Workflow CorDapp",
+ "name" : "workflows-1.0",
+ "shortName" : "Example-Cordapp Flows",
+ "minimumPlatformVersion" : 8,
+ "targetPlatformVersion" : 8,
+ "version" : "1",
+ "vendor" : "Corda Open Source",
+ "licence" : "Apache License, Version 2.0",
+ "jarHash" : {
+ "offset" : 0,
+ "size" : 32,
+ "bytes" : "V7ssTw0etgg3nSGk1amArB+fBH8fQUyBwIFs0DhID+0="
+ }
+ }, {
+ "type" : "Contract CorDapp",
+ "name" : "contracts-1.0",
+ "shortName" : "Example-Cordapp Contracts",
+ "minimumPlatformVersion" : 8,
+ "targetPlatformVersion" : 8,
+ "version" : "1",
+ "vendor" : "Corda Open Source",
+ "licence" : "Apache License, Version 2.0",
+ "jarHash" : {
+ "offset" : 0,
+ "size" : 32,
+ "bytes" : "Xe0eoh4+T6fsq4u0QKqkVsVDMYSWhuspHqE0wlOlyqU="
+ }
+ } \]
+}
+
+Building Docker Image Locally
+--------------------------------------------------------------------------------------------
+
+The `cccs` tag used in the below example commands is a shorthand for the full name of the container image otherwise referred to as `cactus-corda-connector-server`.
+
+From the project root:
+
+DOCKER\_BUILDKIT\=1 docker build ./packages/cactus-plugin-ledger-connector-corda/src/main-server/ \-t cccs
+
+Example NodeDiagnosticInfo JSON Response
+------------------------------------------------------------------------------------------------------------------
+
+{
+ "version": "4.6",
+ "revision": "85e387ea730d9be7d6dc2b23caba1ee18305af74",
+ "platformVersion": 8,
+ "vendor": "Corda Open Source",
+ "cordapps": \[
+ {
+ "type": "Workflow CorDapp",
+ "name": "workflows-1.0",
+ "shortName": "Obligation Flows",
+ "minimumPlatformVersion": 8,
+ "targetPlatformVersion": 8,
+ "version": "1",
+ "vendor": "Corda Open Source",
+ "licence": "Apache License, Version 2.0",
+ "jarHash": {
+ "bytes": "Vf9MllnrC7vrWxrlDE94OzPMZW7At1HhTETL/XjiAmc=",
+ "offset": 0,
+ "size": 32
+ }
+ },
+ {
+ "type": "CorDapp",
+ "name": "corda-confidential-identities-4.6",
+ "shortName": "corda-confidential-identities-4.6",
+ "minimumPlatformVersion": 1,
+ "targetPlatformVersion": 1,
+ "version": "Unknown",
+ "vendor": "Unknown",
+ "licence": "Unknown",
+ "jarHash": {
+ "bytes": "nqBwqHJMbLW80hmRbKEYk0eAknFiX8N40LKuGsD0bPo=",
+ "offset": 0,
+ "size": 32
+ }
+ },
+ {
+ "type": "Contract CorDapp",
+ "name": "corda-finance-contracts-4.6",
+ "shortName": "Corda Finance Demo",
+ "minimumPlatformVersion": 1,
+ "targetPlatformVersion": 8,
+ "version": "1",
+ "vendor": "R3",
+ "licence": "Open Source (Apache 2)",
+ "jarHash": {
+ "bytes": "a43Q/GJG6JKTZzq3U80P8L1DWWcB/D+Pl5uitEtAeQQ=",
+ "offset": 0,
+ "size": 32
+ }
+ },
+ {
+ "type": "Workflow CorDapp",
+ "name": "corda-finance-workflows-4.6",
+ "shortName": "Corda Finance Demo",
+ "minimumPlatformVersion": 1,
+ "targetPlatformVersion": 8,
+ "version": "1",
+ "vendor": "R3",
+ "licence": "Open Source (Apache 2)",
+ "jarHash": {
+ "bytes": "wXdD4Iy50RaWzPp7n9s1xwf4K4MB8eA1nmhPquTMvxg=",
+ "offset": 0,
+ "size": 32
+ }
+ },
+ {
+ "type": "Contract CorDapp",
+ "name": "contracts-1.0",
+ "shortName": "Obligation Contracts",
+ "minimumPlatformVersion": 8,
+ "targetPlatformVersion": 8,
+ "version": "1",
+ "vendor": "Corda Open Source",
+ "licence": "Apache License, Version 2.0",
+ "jarHash": {
+ "bytes": "grTZzN71Cpxw6rZe/U5SB6/ehl99B6VQ1+ZJEx1rixs=",
+ "offset": 0,
+ "size": 32
+ }
+ }
+ \]
+}
+
+Monitoring
+------------------------------------------------------
+
+### Usage Prometheus
+
+The prometheus exporter object is initialized in the `PluginLedgerConnectorCorda` class constructor itself, so instantiating the object of the `PluginLedgerConnectorCorda` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorCordaOptions` interface for `PluginLedgerConnectoCorda` constructor.
+
+`getPrometheusExporterMetricsEndpointV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorCorda` class is called.
+
+### Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'corda\_ledger\_connector\_exporter'
+ metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_corda\_total\_tx\_count** and click **execute**
+
+### Helper code
+
+#### response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points
+
+#### metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+[Previous](cactus-plugin-ledger-connector-besu.md "@hyperledger/cactus-plugin-ledger-connector-besu") [Next](cactus-plugin-ledger-connector-fabric.md "@hyperledger/cactus-plugin-ledger-connector-fabric")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-fabric.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-fabric.md
new file mode 100644
index 0000000000..7c51350c58
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-fabric.md
@@ -0,0 +1,540 @@
+`@hyperledger/cactus-plugin-ledger-connector-fabric`
+========================================================================================================================================
+
+1\. Usage
+------------------------------------------------
+
+This plugin provides a way to interact with Fabric networks. Using this one can perform:
+
+* Deploy smart contracts (chaincode).
+
+* Execute transactions on the ledger.
+
+* Invoke chaincode functions.
+
+
+The above functionality can either be accessed by importing the plugin directly as a library (embedding) or by hosting it as a REST API through the [Cactus API server](https://www.npmjs.com/package/@hyperledger/cactus-cmd-api-server)
+
+We also publish the [Cactus API server as a container image](https://github.com/hyperledger/cactus/pkgs/container/cactus-cmd-api-server) to the GitHub Container Registry that you can run easily with a one liner. The API server is also embeddable in your own NodeJS project if you choose to do so.
+
+### 1.1. Installation
+
+**npm**
+
+npm install @hyperledger/cactus-plugin-ledger-connector-fabric
+
+**yarn**
+
+yarn add @hyperledger/cactus-plugin-ledger-connector-fabric
+
+### 1.2. Using as a Library
+
+import {
+ PluginLedgerConnectorFabric,
+ DefaultEventHandlerStrategy,
+} from "@hyperledger/cactus-plugin-ledger-connector-fabric";
+
+const plugin \= new PluginLedgerConnectorFabric({
+ // See test cases for exact details on what parameters are needed
+});
+
+const req: RunTransactionRequest \= {
+ // See tests for specific examples on request properties
+};
+
+try {
+ const res \= await plugin.transact(req);
+} catch (ex: Error) {
+ // Make sure to handle errors gracefully (which is dependent on your use-case)
+ console.error(ex);
+ throw ex;
+}
+
+### 1.3. Using Via The API Client
+
+**Prerequisites**
+
+* A running Fabric ledger (network)
+
+* You have a running Cactus API server on `$HOST:$PORT` with the Fabric connector plugin installed on it (and the latter configured to have access to the Fabric ledger from point 1)
+
+
+import {
+ PluginLedgerConnectorFabric,
+ DefaultApi as FabricApi,
+ DefaultEventHandlerStrategy,
+} from "@hyperledger/cactus-plugin-ledger-connector-fabric";
+
+// Step zero is to deploy your Fabric ledger and the Cactus API server
+const apiUrl \= \`https://${HOST}:${PORT}\`;
+
+const config \= new Configuration({ basePath: apiUrl });
+
+const apiClient \= new FabricApi(config);
+
+const req: RunTransactionRequest \= {
+ // See tests for specific examples on request properties
+};
+
+try {
+ const res \= await apiClient.runTransactionV1(req);
+} catch (ex: Error) {
+ // Make sure to handle errors gracefully (which is dependent on your use-case)
+ console.error(ex);
+ throw ex;
+}
+
+### 1.4. Signing Credentials with Hashicorp Vault
+
+To support signing of message with multiple identity types
+
+// vault server config for supporting vault identity provider
+const vaultConfig:IVaultConfig \= {
+ endpoint : "http://localhost:8200",
+ transitEngineMountPath: "/transit",
+}
+// web-socket server config for supporting vault identity provider
+const webSocketConfig:IVaultConfig \= {
+ server: socketServer as FabricSocketServer
+}
+// provide list of identity signing to be supported
+const supportedIdentity:FabricSigningCredentialType\[\] \= \[FabricSigningCredentialType.VaultX509,FabricSigningCredentialType.WsX509,FabricSigningCredentialType.X509\]
+const pluginOptions:IPluginLedgerConnectorFabricOptions \= {
+ // other options
+ vaultConfig : vaultConfig,
+ webSocketConfig : webSocketConfig,
+ supportedIdentity:supportedIdentity
+ // .. other options
+}
+const connector: PluginLedgerConnectorFabric \= new PluginLedgerConnectorFabric(pluginOptions);
+
+To enroll an identity
+
+await connector.enroll(
+ {
+ keychainId: "keychain-identifier-for storing-certData",
+ keychainRef: "cert-data-identifier",
+
+ // require in case of vault
+ type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509
+ vaultTransitKey: {
+ token: "vault-token",
+ keyName: "vault-key-label",
+ },
+ // required in case of web-socket server
+ type: FabricSigningCredentialType.WsX509,
+ webSocketKey: {
+ signature: signature,
+ sessionId: sessionId,
+ },
+ },
+ {
+ enrollmentID: "client2",
+ enrollmentSecret: "pw",
+ mspId: "Org1MSP",
+ caId: "ca.org1.example.com",
+ },
+ );
+
+To Register an identity using register’s key
+
+const secret \= await connector.register(
+ {
+ keychainId: "keychain-id-that-store-certData-of-registrar",
+ keychainRef: "certData-label",
+
+ // require in case of vault
+ type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509
+ vaultTransitKey: {
+ token: testToken,
+ keyName: registrarKey,
+ },
+ // required in case of web-socket server
+ type: FabricSigningCredentialType.WsX509,
+ webSocketKey: {
+ signature: signature,
+ sessionId: sessionId,
+ },
+ },
+ {
+ enrollmentID: "client-enrollmentID",
+ enrollmentSecret: "pw",
+ affiliation: "org1.department1",
+ },
+ "ca.org1.example.com", // caID
+ );
+
+To transact with fabric
+
+const resp \= await connector.transact{
+ signingCredential: {
+ keychainId: keychainId,
+ keychainRef: "client-certData-id",
+
+ // require in case of vault
+ type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509
+ vaultTransitKey: {
+ token: testToken,
+ keyName: registrarKey,
+ },
+ // required in case of web-socket server
+ type: FabricSigningCredentialType.WsX509,
+ webSocketKey: {
+ signature: signature,
+ sessionId: sessionId,
+ },
+ },
+ // .. other options
+}
+
+To Rotate the key
+
+await connector.rotateKey(
+ {
+ keychainId: keychainId,
+ keychainRef: "client-certData-id",
+ type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509
+
+ // require in case of vault
+ vaultTransitKey: {
+ token: testToken,
+ keyName: registrarKey,
+ },
+ // key rotation currently not available using web-socket server
+ // web-socket connection not used to manages external keys
+ // user should re-enroll with new pub/priv key pair
+ },
+ {
+ enrollmentID: string;
+ enrollmentSecret: string;
+ caId: string;
+ }
+)
+
+> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP)
+
+#### 1.4.1. Identity Providers
+
+Identity providers allows client to manage their private more effectively and securely. Cactus Fabric Connector support multiple type of providers. Each provider differ based upon where the private are stored. On High level certificate credential are stored as
+
+{
+ type: FabricSigningCredentialType;
+ credentials: {
+ certificate: string;
+ // if identity type is IdentityProvidersType.X509
+ privateKey?: string;
+ };
+ mspId: string;
+}
+
+Currently Cactus Fabric Connector supports following Identity Providers
+
+* X509 : Simple and unsecured provider wherein `private` key is stored along with certificate in some `datastore`. Whenever connector require signature on fabric message, private key is brought from the `datastore` and message signed at the connector.
+
+* Vault-X.509 : Secure provider wherein `private` key is stored with vault’s transit transit engine and certificate in `certDatastore`. Rather then bringing the key to the connector, message digest are sent to the vault server which returns the `signature`.
+
+* WS-X.509 : Secure provider wherein `private` key is stored with `client` and certificate in `certDatastore`. To get the fabric messages signed, message digest is sent to the client via `webSocket` connection opened by the client in the beginning (as described above)
+
+
+#### 1.4.2. Setting up a WS-X.509 provider
+
+The following packages are used to access private keys (via web-socket) stored on a clients external device (e.g., browser, mobile app, or an IoT device…). -[ws-identity](https://github.com/brioux/ws-identity): web-socket server that issues new ws-session tickets, authenticates incoming connections, and sends signature requests -[ws-identity-client](https://github.com/brioux/ws-identity-client): backend connector to send requests from fabric application to ws-identity -[ws-wallet](https://github.com/brioux/ws-wallet): external clients crypto key tool: create new key pair, request session ticket and open web-socket connection with ws-identity
+
+#### 1.4.3. Building the ws-identity docker image
+
+TBD
+
+### 1.5 Monitoring new blocks (WatchBlocks)
+
+* Use `ApiClient` to receive new blocks from a fabric ledger.
+
+* Type of the response can be configured.
+
+* Credentials must be configured using `gatewayOptions` argument (you can either send them directly in request or use wallet stored in keychain).
+
+
+#### 1.5.1 Example
+
+For more detailed example check [fabric-watch-blocks-v1-endpoint.test.ts](#./src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-v1-endpoint.test.ts)
+
+// Setup
+const signingCredential \= {
+ keychainId: uuidv4(),
+ keychainRef: "user2",
+};
+
+// Create RxJS Observable.
+// This will connect to the fabric connector and start the monitoring operation.
+const watchObservable \= apiClient.watchBlocksV1({
+ channelName: "mychannel", // fabric channel name
+ gatewayOptions: { // use signing credential from keychain
+ identity: signingCredential.keychainRef,
+ wallet: {
+ keychain: signingCredential,
+ },
+ },
+ WatchBlocksListenerTypeV1.Full, // return full block data
+});
+
+// Subscribe to the observable to receive new blocks
+const subscription \= watchObservable.subscribe({
+ next(event) {
+ // Handle new event
+ },
+ error(err) {
+ // Handle error from connector
+ },
+});
+
+#### 1.5.2 Listener Type
+
+There are two types of listener type - original and cactus ones.
+
+##### Original
+
+Corresponds directly to `BlockType` from `fabric-common`:
+
+* `WatchBlocksListenerTypeV1.Filtered`,
+
+* `WatchBlocksListenerTypeV1.Full`,
+
+* `WatchBlocksListenerTypeV1.Private`,
+
+
+##### Cactus (custom)
+
+Parses the data and returns custom formatted block.
+
+* `WatchBlocksListenerTypeV1.CactusTransactions`: Returns transactions summary. Compatible with legacy `fabric-socketio` monitoring operation.
+
+
+2\. Architecture
+--------------------------------------------------------------
+
+The sequence diagrams for various endpoints are mentioned below
+
+### 2.1. run-transaction-endpoint
+
+![run-transaction-endpoint sequence diagram](../_images/run-transaction-endpoint1.png)
+
+The above diagram shows the sequence diagram of run-transaction-endpoint. User A (One of the many Users) interacts with the API Client which in turn, calls the API server. API server then executes transact() method which is explained in detailed in the subsequent diagram.
+
+![run-transaction-endpoint transact() method](../_images/run-transaction-endpoint-transact1.png)
+
+The above diagram shows the sequence diagram of transact() method of the PluginLedgerConnectorFabric class. The caller to this function, which in reference to the above sequence diagram is API server, sends RunTransactionRequest object as an argument to the transact() method. Based on the invocationType (FabricContractInvocationType.CALL, FabricCOntractInvocationType.SEND), corresponding responses are send back to the caller.
+
+![run-transaction-endpoint-enroll](../_images/run-transaction-endpoint-enroll.png)
+
+The above diagram shows the sequence diagram of enroll() method of the PluginLedgerConnectorFabric class. The caller to this function, which in reference to the above sequence diagram is API server, sends Signer object along with EnrollmentRequest as an argument to the enroll() method. Based on the singerType (FabricSigningCredentialType.X509, FabricSigningCredentialType.VaultX509, FabricSigningCredentialType.WsX509), corresponding identity is enrolled and stored inside keychain.
+
+3\. Containerization
+----------------------------------------------------------------------
+
+### 3.1. Building/running the container image locally
+
+In the Cactus project root say:
+
+DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-plugin-ledger-connector-fabric/Dockerfile . \-t cplcb
+
+Build with a specific version of the npm package:
+
+DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=0.4.1 \-f ./packages/cactus-plugin-ledger-connector-fabric/Dockerfile . \-t cplcb
+
+### 3.2. Running the container
+
+Launch container with plugin configuration as an **environment variable**:
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": {
+ "CORE\_PEER\_LOCALMSPID": "Org1MSP",
+ "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051",
+ "CORE\_PEER\_MSPCONFIGPATH":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp",
+ "CORE\_PEER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt",
+ "ORDERER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
+ },
+ "discoveryOptions": {
+ "enabled": true,
+ "asLocalhost": true
+ }
+ }}}\]' \\
+ cplcb
+
+Launch container with plugin configuration as a **CLI argument**:
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ cplcb \\
+ ./node\_modules/.bin/cactusapi \\
+ \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": {
+ "CORE\_PEER\_LOCALMSPID": "Org1MSP",
+ "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051",
+ "CORE\_PEER\_MSPCONFIGPATH":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp",
+ "CORE\_PEER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt",
+ "ORDERER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
+ },
+ "discoveryOptions": {
+ "enabled": true,
+ "asLocalhost": true
+ }
+ }}}\]'
+
+Launch container with **configuration file** mounted from host machine:
+
+echo '\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": {
+ "CORE\_PEER\_LOCALMSPID": "Org1MSP",
+ "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051",
+ "CORE\_PEER\_MSPCONFIGPATH":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp",
+ "CORE\_PEER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt",
+ "ORDERER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
+ },
+ "discoveryOptions": {
+ "enabled": true,
+ "asLocalhost": true
+ }
+ }}}\]' \> cactus.json
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\
+ cplcb \\
+ ./node\_modules/.bin/cactusapi \\
+ \--config-file\=/cactus.json
+
+### 3.3. Testing API calls with the container
+
+Don’t have a fabric network on hand to test with? Test or develop against our fabric All-In-One container!
+
+**Terminal Window 1 (Ledger)**
+
+docker run \--privileged \-p 0.0.0.0:8545:8545/tcp \-p 0.0.0.0:8546:8546/tcp \-p 0.0.0.0:8888:8888/tcp \-p 0.0.0.0:9001:9001/tcp \-p 0.0.0.0:9545:9545/tcp ghcr.io/hyperledger/cactus-fabric-all-in-one:v1.0.0-rc.2
+
+**Terminal Window 2 (Cactus API Server)**
+
+docker run \\
+ \--network host \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": {
+ "CORE\_PEER\_LOCALMSPID": "Org1MSP",
+ "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051",
+ "CORE\_PEER\_MSPCONFIGPATH":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp",
+ "CORE\_PEER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt",
+ "ORDERER\_TLS\_ROOTCERT\_FILE":
+ "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
+ },
+ "discoveryOptions": {
+ "enabled": true,
+ "asLocalhost": true
+ }
+ }}}\]' \\
+ cplcb
+
+**Terminal Window 3 (curl - replace eth accounts as needed)**
+
+curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/run-transaction' \\
+--header 'Content-Type: application/json' \\
+--data-raw '{
+ channelName: "mychannel",
+ contractName: "contract-example";
+ invocationType: "FabricContractInvocationType.SEND";
+ methodName: "example"
+}'
+
+The above should produce a response that looks similar to this:
+
+{
+ "success": true,
+ "data": {
+ "transactionReceipt": {
+ "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd",
+ "blockNumber": 1218,
+ "contractAddress": null,
+ "cumulativeGasUsed": 21000,
+ "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
+ "gasUsed": 21000,
+ "logs": \[\],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": true,
+ "to": "0xf17f52151ebef6c7334fad080c5704d77216b732",
+ "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f",
+ "transactionIndex": 0
+ }
+ }
+}
+
+4\. Prometheus Exporter
+----------------------------------------------------------------------------
+
+This class creates a prometheus exporter, which scraps the transactions (total transaction count) for the use cases incorporating the use of Fabric connector plugin.
+
+### 4.1. Usage Prometheus
+
+The prometheus exporter object is initialized in the `PluginLedgerConnectorFabric` class constructor itself, so instantiating the object of the `PluginLedgerConnectorFabric` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorFabricOptions` interface for `PluginLedgerConnectoFabric` constructor.
+
+`getPrometheusExporterMetricsEndpointV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorFabric` class is called.
+
+### 4.2. Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'fabric\_ledger\_connector\_exporter'
+ metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_fabric\_total\_tx\_count** and click **execute**
+
+### 4.3. Helper code
+
+#### 4.3.1. response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### 4.3.2. data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points
+
+#### 4.3.3. metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+5\. Contributing
+--------------------------------------------------------------
+
+We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do!
+
+Please review [CONTIRBUTING.md](#../../CONTRIBUTING.md) to get started.
+
+6\. License
+----------------------------------------------------
+
+This distribution is published under the Apache License Version 2.0 found in the [LICENSE](#../../LICENSE) file.
+
+7\. Acknowledgments
+--------------------------------------------------------------------
+
+[Previous](cactus-plugin-ledger-connector-corda.md "@hyperledger/cactus-plugin-ledger-connector-corda") [Next](cactus-plugin-ledger-connector-quorum.md "@hyperledger/cactus-plugin-ledger-connector-quorum")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-quorum.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-quorum.md
new file mode 100644
index 0000000000..319fb26785
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-quorum.md
@@ -0,0 +1,350 @@
+`@hyperledger/cactus-plugin-ledger-connector-quorum`
+=======================================================================================================================================
+
+This plugin provides `Cactus` a way to interact with Quorum networks. Using this we can perform:
+
+* Deploy Smart-contracts through bytecode.
+
+* Build and sign transactions using different keystores.
+
+* Invoke smart-contract functions that we have deployed on the network.
+
+
+Summary
+------------------------------------------------
+
+* [Getting Started](#getting-started)
+
+* [Usage](#usage)
+
+* [Prometheus Exporter](#prometheus-exporter)
+
+* [Runing the tests](#running-the-tests)
+
+* [Contributing](#contributing)
+
+* [License](#license)
+
+* [Acknowledgments](#acknowledgments)
+
+
+Getting Started
+----------------------------------------------------------------
+
+Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on your local machine for development and testing purposes.
+
+### Prerequisites
+
+In the root of the project to install the dependencies execute the command:
+
+npm run configure
+
+Usage
+--------------------------------------------
+
+To use this import public-api and create new **PluginLedgerConnectorQuorum**.
+
+ const connector: PluginLedgerConnectorQuorum \= new PluginLedgerConnectorQuorum({
+ instanceId: uuidV4(),
+ rpcApiHttpHost,
+ pluginRegistry: new PluginRegistry(),
+ });
+
+You can make calls through the connector to the plugin API:
+
+async invokeContract(req: InvokeContractJsonObjectV1Request):Promise;
+async transact(req: RunTransactionRequest): Promise;
+async transactSigned(rawTransaction: string): Promise;
+async transactGethKeychain(txIn: RunTransactionRequest): Promise;
+async transactPrivateKey(req: RunTransactionRequest): Promise;
+async transactCactusKeychainRef(req: RunTransactionRequest):Promise;
+async deployContract(req: DeployContractSolidityBytecodeV1Request :Promise;
+async deployContractJsonObject(req: DeployContractSolidityBytecodeJsonObjectV1Request): Promise
+async invokeRawWeb3EthMethod(req: InvokeRawWeb3EthMethodV1Request): Promise;
+async invokeRawWeb3EthContract(req: InvokeRawWeb3EthContractV1Request): Promise;
+
+Call example to deploy a contract:
+
+const deployOut \= await connector.deployContract({
+ web3SigningCredential: {
+ ethAccount: firstHighNetWorthAccount,
+ secret: "",
+ type: Web3SigningCredentialType.GETHKEYCHAINPASSWORD,
+ },
+ bytecode: ContractJson.bytecode,
+ gas: 1000000,
+});
+
+The field “type” can have the following values:
+
+enum Web3SigningCredentialType {
+ CACTUSKEYCHAINREF \= 'CACTUS\_KEYCHAIN\_REF',
+ GETHKEYCHAINPASSWORD \= 'GETH\_KEYCHAIN\_PASSWORD',
+ PRIVATEKEYHEX \= 'PRIVATE\_KEY\_HEX',
+ NONE \= 'NONE'
+}
+
+> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP)
+
+QuorumApiClient
+----------------------------------------------------------------
+
+All connector API endpoints are defined in [open-api specification](#./src/main/json/openapi.json). You can use [QuorumApiClient](#./src/main/typescript/api-client) to call remote quorum connector functions. It also contain additional utility functions to ease integration.
+
+### REST Functions
+
+See [DefaultApi](#./src/main/typescript/generated/openapi/typescript-axios/api.ts) for up-to-date listing of supported endpoints.
+
+* deployContractSolBytecodeJsonObjectV1
+
+* deployContractSolBytecodeV1
+
+* getPrometheusMetricsV1
+
+* invokeContractV1
+
+* invokeContractV1NoKeychain
+
+* invokeRawWeb3EthContractV1
+
+* invokeRawWeb3EthMethodV1
+
+* runTransactionV1
+
+
+### Asynchronous Functions (socket.io)
+
+* watchBlocksV1
+
+
+### Send Request Methods
+
+Both methods are deprecated, async version returns immediately while sync respond with Promise of a call results.
+
+* `sendAsyncRequest`
+
+* `sendSyncRequest`
+
+
+#### Supported Requests
+
+* `web3Eth`: Calls `invokeRawWeb3EthMethodV1`
+
+* `web3EthContract`: Calls `invokeRawWeb3EthContractV1`
+
+
+#### Arguments
+
+* The same for both async and sync methods.
+
+* Arguments interpretation depends on `method.type` (i.e. request type)
+
+
+// Contract definition for web3EthContract request, ignored otherwise
+contract: {
+ abi?: AbiItem\[\],
+ address?: string
+},
+
+// Request definition
+method: {
+ type: "web3Eth" | "web3EthContract",
+ command: string // web3 method
+ function?: string; // contract function
+ params?: any\[\]; // contract parameters
+}
+
+// web3 method arguments
+args: {
+ {
+ args?: any\[\] | Record;
+ }
+},
+
+Running the tests
+--------------------------------------------------------------------
+
+To check that all has been installed correctly and that the pugin has no errors, there are two options to run the tests:
+
+* Run this command at the project’s root:
+
+
+npm run test:plugin-ledger-connector-quorum
+
+### Building/running the container image locally
+
+In the Cactus project root say:
+
+DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-plugin-ledger-connector-quorum/Dockerfile . \-t cplcb
+
+Build with a specific version of the npm package:
+
+DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=0.4.1 \-f ./packages/cactus-plugin-ledger-connector-quorum/Dockerfile . \-t cplcb
+
+#### Running the container
+
+Launch container with plugin configuration as an **environment variable**:
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env AUTHORIZATION\_PROTOCOL\='NONE' \\
+ \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}\]' \\
+ cplcb
+
+Launch container with plugin configuration as a **CLI argument**:
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ cplcb \\
+ ./node\_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \\
+ \--authorization-protocol\='NONE' \\
+ \--authorization-config-json\='{}' \\
+ \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}\]'
+
+Launch container with **configuration file** mounted from host machine:
+
+echo '{"authorizationProtocol":"NONE","authorizationConfigJson":{},"plugins":\[{"packageName":"@hyperledger/cactus-plugin-ledger-connector-quorum","type":"org.hyperledger.cactus.plugin\_import\_type.LOCAL","action":"org.hyperledger.cactus.plugin\_import\_action.INSTALL","options":{"rpcApiHttpHost":"http://localhost:8545","instanceId":"some-unique-quorum-connector-instance-id"}}\]}' \> cactus.json
+
+docker run \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\
+ cplcb \\
+ ./node\_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \\
+ \--config-file\=/cactus.json
+
+#### Testing API calls with the container
+
+Don’t have a quorum network on hand to test with? Test or develop against our quorum All-In-One container!
+
+**Terminal Window 1 (Ledger)**
+
+docker run \-p 0.0.0.0:8545:8545/tcp \-p 0.0.0.0:8546:8546/tcp \-p 0.0.0.0:8888:8888/tcp \-p 0.0.0.0:9001:9001/tcp \-p 0.0.0.0:9545:9545/tcp hyperledger/cactus-quorum-all-in-one:latest
+
+**Terminal Window 2 (Cactus API Server)**
+
+docker run \\
+ \--network host \\
+ \--rm \\
+ \--publish 3000:3000 \\
+ \--publish 4000:4000 \\
+ \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}\]' \\
+ cplcb
+
+**Terminal Window 3 (curl - replace eth accounts as needed)**
+
+curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/run-transaction' \\
+--header 'Content-Type: application/json' \\
+--data-raw '{
+ "web3SigningCredential": {
+ "ethAccount": "627306090abaB3A6e1400e9345bC60c78a8BEf57",
+ "secret": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
+ "type": "PRIVATE\_KEY\_HEX"
+ },
+ "consistencyStrategy": {
+ "blockConfirmations": 0,
+ "receiptType": "NODE\_TX\_POOL\_ACK"
+ },
+ "transactionConfig": {
+ "from": "627306090abaB3A6e1400e9345bC60c78a8BEf57",
+ "to": "f17f52151EbEF6C7334FAD080c5704D77216b732",
+ "value": 1,
+ "gas": 10000000
+ }
+}'
+
+The above should produce a response that looks similar to this:
+
+{
+ "success": true,
+ "data": {
+ "transactionReceipt": {
+ "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd",
+ "blockNumber": 1218,
+ "contractAddress": null,
+ "cumulativeGasUsed": 21000,
+ "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57",
+ "gasUsed": 21000,
+ "logs": \[\],
+ "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
+ "status": true,
+ "to": "0xf17f52151ebef6c7334fad080c5704d77216b732",
+ "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f",
+ "transactionIndex": 0
+ }
+ }
+}
+
+Prometheus Exporter
+------------------------------------------------------------------------
+
+This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Quorum connector plugin.
+
+### Prometheus Exporter Usage
+
+The prometheus exporter object is initialized in the `PluginLedgerConnectorQuorum` class constructor itself, so instantiating the object of the `PluginLedgerConnectorQuorum` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorQuorumOptions` interface for `PluginLedgerConnectoQuorum` constructor.
+
+`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorQuorum` class is called.
+
+### Prometheus Integration
+
+To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml
+
+\- job\_name: 'quorum\_ledger\_connector\_exporter'
+ metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/get-prometheus-exporter-metrics
+ scrape\_interval: 5s
+ static\_configs:
+ - targets: \['{host}:{port}'\]
+
+Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/get-prometheus-exporter-metrics`
+
+Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_quorum\_total\_tx\_count** and click **execute**
+
+### Helper code
+
+#### response.type.ts
+
+This file contains the various responses of the metrics.
+
+#### data-fetcher.ts
+
+This file contains functions encasing the logic to process the data points
+
+#### metrics.ts
+
+This file lists all the prometheus metrics and what they are used for.
+
+Running the tests
+------------------------------------------------------
+
+To check that all has been installed correctly and that the pugin has no errors, there are two options to run the tests:
+
+* Run this command at the project’s root:
+
+
+npm run test:plugin-ledger-connector-quorum
+
+Contributing
+----------------------------------------------------------
+
+We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do!
+
+Please review [CONTIRBUTING.md](#../../CONTRIBUTING.md) to get started.
+
+License
+------------------------------------------------
+
+This distribution is published under the Apache License Version 2.0 found in the [LICENSE](#../../LICENSE) file.
+
+Acknowledgments
+----------------------------------------------------------------
+
+[Previous](cactus-plugin-ledger-connector-fabric.md "@hyperledger/cactus-plugin-ledger-connector-fabric") [Next](cactus-test-api-client.md "@hyperledger/cactus-test-api-client")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-test-api-client.md b/docs/docs/cactus/packages/cactus-test-api-client.md
new file mode 100644
index 0000000000..85ad4df824
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-test-api-client.md
@@ -0,0 +1,20 @@
+`@hyperledger/cactus-test-api-client`
+=========================================================================================================
+
+This is the test package for the package that’s called `cactus-api-client`
+
+Usage
+--------------------------------------------
+
+// TODO: DEMONSTRATE API
+
+FAQ
+----------------------------------------
+
+### **What is a dedicated test package for?**
+
+This is a dedicated test package meaning that it verifies the integration between two packages that are somehow dependent on each other and therefore these tests cannot be added properly in the child package due to circular dependency issues and it would not be fitting to add it in the parent because the child package’s tests should not be held by the parent as a matter of principle.
+
+[Previous](cactus-plugin-ledger-connector-quorum.md "@hyperledger/cactus-plugin-ledger-connector-quorum") [Next](cactus-test-cmd-api-server.md "@hyperledger/cactus-test-cmd-api-server")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-test-cmd-api-server.md b/docs/docs/cactus/packages/cactus-test-cmd-api-server.md
new file mode 100644
index 0000000000..32873de650
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-test-cmd-api-server.md
@@ -0,0 +1,20 @@
+`@hyperledger/cactus-test-cmd-api-server`
+=================================================================================================================
+
+This is the test package for the package that’s called `cactus-cmd-api-server`
+
+Usage
+--------------------------------------------
+
+// TODO: DEMONSTRATE API
+
+FAQ
+----------------------------------------
+
+### **What is a dedicated test package for?**
+
+This is a dedicated test package meaning that it verifies the integration between two packages that are somehow dependent on each other and therefore these tests cannot be added properly in the child package due to circular dependency issues and it would not be fitting to add it in the parent because the child package’s tests should not be held by the parent as a matter of principle.
+
+[Previous](cactus-test-api-client.md "@hyperledger/cactus-test-api-client") [Next](cactus-test-plugin-ledger-connector-quorum.md "@hyperledger/cactus-test-plugin-ledger-connector-quorum")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-test-plugin-ledger-connector-quorum.md b/docs/docs/cactus/packages/cactus-test-plugin-ledger-connector-quorum.md
new file mode 100644
index 0000000000..0186ecee6f
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-test-plugin-ledger-connector-quorum.md
@@ -0,0 +1,18 @@
+`@hyperledger/cactus-test-plugin-ledger-connector-quorum`
+=================================================================================================================================================
+
+Usage
+--------------------------------------------
+
+// TODO: DEMONSTRATE API
+
+FAQ
+----------------------------------------
+
+### **What is a dedicated test package for?**
+
+This is a dedicated test package meaning that it verifies the integration between two packages that are somehow dependent on each other and therefore these tests cannot be added properly in the child package due to circular dependency issues and it would not be fitting to add it in the parent because the child package’s tests should not be held by the parent as a matter of principle.
+
+[Previous](cactus-test-cmd-api-server.md "@hyperledger/cactus-test-cmd-api-server") [Next](cactus-test-tooling.md "@hyperledger/cactus-test-tooling")
+
+* * *
diff --git a/docs/docs/cactus/packages/cactus-test-tooling.md b/docs/docs/cactus/packages/cactus-test-tooling.md
new file mode 100644
index 0000000000..cfb146ffc7
--- /dev/null
+++ b/docs/docs/cactus/packages/cactus-test-tooling.md
@@ -0,0 +1,24 @@
+`@hyperledger/cactus-test-tooling`
+===================================================================================================
+
+> TODO: description
+
+Usage
+--------------------------------------------
+
+// TODO: DEMONSTRATE API
+
+Docker image for the ws-identity server
+----------------------------------------------------------------------------------------------------------------
+
+A docker image of the [ws-identity server](https://hub.docker.com/repository/docker/brioux/ws-identity) is used to test integration of WS-X.509 credential type in the fabric connector plugin.
+
+[ws-identity](https://github.com/brioux/ws-identity) includes A Docker file to build the image: clone the repo, install packages, build src and the image
+
+npm install
+npm run build
+docker build . \-t \[image\-name\]
+
+[Previous](cactus-test-plugin-ledger-connector-quorum.md "@hyperledger/cactus-test-plugin-ledger-connector-quorum") [Next](../support.md "Ledger Support for Connectors")
+
+* * *
diff --git a/docs/docs/cactus/regulatory-and-industry-initiatives-reading-list.md b/docs/docs/cactus/regulatory-and-industry-initiatives-reading-list.md
new file mode 100644
index 0000000000..9a3f0ddc20
--- /dev/null
+++ b/docs/docs/cactus/regulatory-and-industry-initiatives-reading-list.md
@@ -0,0 +1,59 @@
+Regulatory and Industry Initiatives Reading List
+================================================
+
+A non-exhaustive list of industry standards and regulations/regulatory plans that one could read through if they are trying to get a comprehensive picture of what it takes from the non-technical standpoint to interoperate existing productive systems in finance, trade and more.
+
+While these documents are not dealing with technological problems, even just the awareness of their existence could still add tremendous value to someone who is looking to implement some sort of integration/interoperability between different DLTs or a DLT and any pre-existing centralized system.
+
+MICA European crypto assets regulation (coming into force by 2023)
+------------------------------------------------------------------
+
+https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A52020PC0593
+
+Pilot Regime for DLT market infrastructure
+------------------------------------------
+
+https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:52020PC0594&from=EN
+
+Paperless trade framework (UN / UNESCAP more on APAC now but supposed to expand in EU) for bilateral cooperation
+----------------------------------------------------------------------------------------------------------------
+
+https://readiness.digitalizetrade.org/
+
+ICC Digital Standard Initiative (Private sector)
+------------------------------------------------
+
+https://iccwbo.org/media-wall/news-speeches/digital-trade-standards-initiative-launches-under-the-umbrella-of-icc/
+
+BAFT Digital Ledger Payment Commitment - Technical and Business Best Practices (Private sector - Banking Industry)
+------------------------------------------------------------------------------------------------------------------
+
+https://www.baft.org/wp-content/uploads/2021/03/baft-dlpc-technical-bps-v1-1.pdf
+
+https://www.baft.org/wp-content/uploads/2021/03/baft-dlpc-business-bps-v1-1.pdf
+
+DCSA Digital Container Shipping Association (Private sector - shipping industry)
+--------------------------------------------------------------------------------
+
+https://dcsa.org/dcsa-publishes-standards-for-the-bill-of-lading/
+
+MSB Networked Supervision
+-------------------------
+
+https://www.occ.gov/news-issuances/news-releases/2021/nr-occ-2021-2.html
+
+OCC Interpretative letter on the use of DA for payments
+-------------------------------------------------------
+
+https://www.occ.gov/news-issuances/news-releases/2021/nr-occ-2021-2a.pdf
+
+Open Digital Asset Protocol from IETF (Thanks to Rafael Belchior for these)
+---------------------------------------------------------------------------
+
+https://datatracker.ietf.org/doc/draft-hargreaves-odap/ https://datatracker.ietf.org/doc/draft-belchior-gateway-recovery/
+
+There are some more standards in section 6.2 of https://deepai.org/publication/a-survey-on-blockchain-interoperability-past-present-and-future-trends
+
+[Previous](whitepaper.md "Hyperledger Cactus White Paper") [Next](packages.md "Cactus Components")
+
+* * *
diff --git a/docs/docs/cactus/support.md b/docs/docs/cactus/support.md
new file mode 100644
index 0000000000..255d8e4e1a
--- /dev/null
+++ b/docs/docs/cactus/support.md
@@ -0,0 +1,15 @@
+Ledger Support for Connectors
+============================================================================================
+
+This section contains the ledger supported versions for connectors in Hyperledger Cactus.
+
+* [Besu](support/besu.md)
+* [Corda](support/corda.md)
+* [Fabric](support/fabric.md)
+* [Iroha](support/iroha.md)
+* [Quorum](support/quorum.md)
+* [xDai](support/xdai.md)
+
+[Previous](packages/cactus-test-tooling.md "@hyperledger/cactus-test-tooling") [Next](support/besu.md "Besu Support")
+
+* * *
diff --git a/docs/docs/cactus/support/besu.md b/docs/docs/cactus/support/besu.md
new file mode 100644
index 0000000000..a88205bc7f
--- /dev/null
+++ b/docs/docs/cactus/support/besu.md
@@ -0,0 +1,128 @@
+Besu Support
+==========================================================
+
+Note
+
+The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts.
+
+Hyperledger Cactus v0.9.0
+
+Besu version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Besu 21.1.6 and Orion 21.1.1
+
+✅ test
+
+✅ test
+
+✅ test
+
+Besu 1.5.1 and Orion 1.6
+
+✅ test
+
+✅ test
+
+✅ test
+
+Hyperledger Cactus v0.8.0
+
+Besu version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Besu 1.5.1 and Orion 1.6
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.7.0
+
+Besu version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Besu 1.5.1 and Orion 1.6
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.6.0
+
+Besu version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Besu 1.5.1 and Orion 1.6
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.5.0
+
+Besu version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Besu 1.5.1 and Orion 1.6
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.4.1
+
+Besu version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Besu 1.5.1 and Orion 1.6
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract-v2.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts)
+
+
+
+[Previous](../support.md "Ledger Support for Connectors") [Next](corda.md "Corda Support")
+
+* * *
diff --git a/docs/docs/cactus/support/corda.md b/docs/docs/cactus/support/corda.md
new file mode 100644
index 0000000000..1cb5cfdcae
--- /dev/null
+++ b/docs/docs/cactus/support/corda.md
@@ -0,0 +1,136 @@
+Corda Support
+============================================================
+
+Note
+
+The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts.
+
+Hyperledger Cactus v0.9.0
+
+Corda version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Corda 4.8
+
+✅ test
+
+✅ test
+
+✅ test
+
+Corda 4.7
+
+✅ test
+
+✅ test
+
+✅ test
+
+Corda 4.5
+
+✅ test
+
+✅ test
+
+✅ test
+
+Hyperledger Cactus v0.8.0
+
+Corda version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Corda 4.5
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+Hyperledger Cactus v0.7.0
+
+Corda version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Corda 4.5
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+Hyperledger Cactus v0.6.0
+
+Corda version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Corda 4.5
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+Hyperledger Cactus v0.5.0
+
+Corda version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Corda 4.5
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+Hyperledger Cactus v0.4.1
+
+Corda version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Corda 4.5
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts)
+
+
+
+[Previous](besu.md "Besu Support") [Next](fabric.md "Fabric Support")
+
+* * *
diff --git a/docs/docs/cactus/support/fabric.md b/docs/docs/cactus/support/fabric.md
new file mode 100644
index 0000000000..caa1e79f64
--- /dev/null
+++ b/docs/docs/cactus/support/fabric.md
@@ -0,0 +1,168 @@
+Fabric Support
+==============================================================
+
+Note
+
+The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts.
+
+Hyperledger Cactus v0.9.0
+
+Fabric version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Fabric 2.2.0
+
+✅ test
+
+✅ test
+
+✅ test
+
+Fabric 1.4.8
+
+✅ test
+
+✅ test
+
+✅ test
+
+Hyperledger Cactus v0.8.0
+
+Fabric version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Fabric 2.2.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+Fabric 1.4.8
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+Hyperledger Cactus v0.7.0
+
+Fabric version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Fabric 2.2.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+Fabric 1.4.8
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+Hyperledger Cactus v0.6.0
+
+Fabric version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Fabric 2.2.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+Fabric 1.4.8
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+Hyperledger Cactus v0.5.0
+
+Fabric version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Fabric 2.2.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+Fabric 1.4.8
+
+[✅](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+Hyperledger Cactus v0.4.1
+
+Fabric version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Fabric 2.2.0
+
+❌
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts)
+
+Fabric 1.4.8
+
+✅
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts)
+
+
+
+[Previous](corda.md "Corda Support") [Next](iroha.md "Iroha Support")
+
+* * *
diff --git a/docs/docs/cactus/support/iroha.md b/docs/docs/cactus/support/iroha.md
new file mode 100644
index 0000000000..dec2132b10
--- /dev/null
+++ b/docs/docs/cactus/support/iroha.md
@@ -0,0 +1,22 @@
+Iroha Support
+============================================================
+
+Note
+
+The deployContract feature not yet implemented since Iroha lacks full smart contract support during the initial development stage of the Iroha connector plugin.
+
+Hyperledger Cactus v0.9.0
+
+Iroha version
+
+runTransaction
+
+Iroha 1.2.0 and Postgres 9.5
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.9.0/packages/cactus-plugin-ledger-connector-iroha/src/test/typescript/integration/run-transaction-endpoint-v1.test.ts)
+
+
+
+[Previous](fabric.md "Fabric Support") [Next](quorum.md "Quorum Support")
+
+* * *
diff --git a/docs/docs/cactus/support/quorum.md b/docs/docs/cactus/support/quorum.md
new file mode 100644
index 0000000000..6ad23472bb
--- /dev/null
+++ b/docs/docs/cactus/support/quorum.md
@@ -0,0 +1,168 @@
+Quorum Support
+==============================================================
+
+Note
+
+The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts.
+
+Hyperledger Cactus v0.9.0
+
+Quorum version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Quorum 21.4.1 and Tessera 21.1.1
+
+✅ test
+
+✅ test
+
+✅ test
+
+Quorum 2.3.0 and Tessera 0.10.0
+
+✅ test
+
+✅ test
+
+✅ test
+
+Hyperledger Cactus v0.8.0
+
+Quorum version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Quorum 21.4.1 and Tessera 21.1.1
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts)
+
+Quorum 2.3.0 and Tessera 0.10.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.7.0
+
+Quorum version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Quorum 21.4.1 and Tessera 21.1.1
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts)
+
+Quorum 2.3.0 and Tessera 0.10.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.6.0
+
+Quorum version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Quorum 21.4.1 and Tessera 21.1.1
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts)
+
+Quorum 2.3.0 and Tessera 0.10.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.5.0
+
+Quorum version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Quorum 21.4.1 and Tessera 21.1.1
+
+❌
+
+❌
+
+❌
+
+Quorum 2.3.0 and Tessera 0.10.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/invoke-contract.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts)
+
+Hyperledger Cactus v0.4.1
+
+Quorum version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+Quorum 21.4.1 and Tessera 21.1.1
+
+❌
+
+❌
+
+❌
+
+Quorum 2.3.0 and Tessera 0.10.0
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/invoke-contract-v2.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts)
+
+
+
+[Previous](iroha.md "Iroha Support") [Next](xdai.md "xDai Support")
+
+* * *
diff --git a/docs/docs/cactus/support/xdai.md b/docs/docs/cactus/support/xdai.md
new file mode 100644
index 0000000000..651db15d5b
--- /dev/null
+++ b/docs/docs/cactus/support/xdai.md
@@ -0,0 +1,120 @@
+xDai Support
+==========================================================
+
+Note
+
+The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts.
+
+Hyperledger Cactus v0.9.0
+
+xDai version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+xDai 1.8.27
+
+✅ test
+
+✅ test
+
+✅ test
+
+Hyperledger Cactus v0.8.0
+
+xDai version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+xDai 1.8.27
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+Hyperledger Cactus v0.7.0
+
+xDai version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+xDai 1.8.27
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+Hyperledger Cactus v0.6.0
+
+xDai version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+xDai 1.8.27
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+Hyperledger Cactus v0.5.0
+
+xDai version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+xDai 1.8.27
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts)
+
+✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts)
+
+Hyperledger Cactus v0.4.1
+
+xDai version
+
+deployContract\*
+
+invokeContract
+
+runTransaction
+
+xDai 1.8.27
+
+❌
+
+❌
+
+❌
+
+
+
+[Previous](quorum.md "Quorum Support")
+
+* * *
diff --git a/docs/docs/cactus/whitepaper.md b/docs/docs/cactus/whitepaper.md
new file mode 100644
index 0000000000..4711378684
--- /dev/null
+++ b/docs/docs/cactus/whitepaper.md
@@ -0,0 +1,8 @@
+Hyperledger Cactus White Paper
+======================================================================================
+
+The white paper is presently undergoing a revision. Please visit the [repository](https://github.com/hyperledger/cacti/blob/main/whitepaper/whitepaper.md) for updates.
+
+[Previous](contributing.md "Contributing") [Next](regulatory-and-industry-initiatives-reading-list.md "Regulatory and Industry Initiatives Reading List")
+
+* * *
diff --git a/docs/docs/concepts/data-sharing.md b/docs/docs/concepts/data-sharing.md
new file mode 100644
index 0000000000..b4e9cf00c7
--- /dev/null
+++ b/docs/docs/concepts/data-sharing.md
@@ -0,0 +1,3 @@
+# Data Sharing
+
+This is a basic interoperability mode or use case pattern. [Here](../weaver/interoperability-modes.md#data-sharing) is a description.
diff --git a/docs/docs/contact-us.md b/docs/docs/contact-us.md
new file mode 100644
index 0000000000..c1d7a1926c
--- /dev/null
+++ b/docs/docs/contact-us.md
@@ -0,0 +1,9 @@
+You can contact us or seek help through the following channels:
+
+- Mailing list: [cacti@lists.hyperledger.org](mailto:cacti@lists.hyperledger.org)
+- Discord channels:
+ * Cacti users: [https://discord.com/channels/905194001349627914/908379366650703943](https://discord.com/channels/905194001349627914/908379366650703943)
+ * Cacti contributors: [https://discord.com/channels/905194001349627914/908379338716631050](https://discord.com/channels/905194001349627914/908379338716631050)
+ * Hyperledger: [https://discord.com/invite/hyperledger](https://discord.com/invite/hyperledger)
+
+The maintainers are [listed](https://github.com/hyperledger/cacti/blob/main/MAINTAINERS.md) in the GitHub repository.
diff --git a/docs/docs/contributing/asking-a-question.md b/docs/docs/contributing/asking-a-question.md
new file mode 100644
index 0000000000..7dafbaa6ec
--- /dev/null
+++ b/docs/docs/contributing/asking-a-question.md
@@ -0,0 +1,17 @@
+# Asking a Question
+
+!!! tip
+
+ * check the [FAQs](../faqs.md) to see if your question has already been asked.
+ * make sure you provide all relevant details.
+ * include information about what you have already tried.
+ * review [How to Ask Technical Questions to Get Quality Answers](https://opensource.com/life/16/10/how-ask-technical-questions) prior to asking your question.
+
+## Chat
+[Hyperledger’s Discord server](https://discord.gg/hyperledger) is the place to go for real-time chat about everything from quick help to involved discussions.
+
+For general Hyperledger Cacti discussions, join the Discord server and visit #Cacti.
+
+## Mailing Lists
+The Hyperledger Cacti mailing list is hosted by the Hyperledger Foundation: https://lists.hyperledger.org.
+
diff --git a/docs/docs/contributing/how-to-contribute.md b/docs/docs/contributing/how-to-contribute.md
new file mode 100644
index 0000000000..24593aad55
--- /dev/null
+++ b/docs/docs/contributing/how-to-contribute.md
@@ -0,0 +1,71 @@
+# How to Contribute
+
+The Hyperledger Cacti repository contains [specific instructions](https://github.com/hyperledger/cacti/blob/main/CONTRIBUTING.md) for contributing to that project.
+
+In this section, you will find generic instructions and guidelines for contributing to any Hyperledger project.
+
+## Ways to Contribute
+
+Contributions from the development community help improve the capabilities of
+Hyperledger Cacti. These contributions are the most effective way to
+make a positive impact on the project.
+
+Ways you can contribute:
+
+* Bugs or issues: Report problems or defects found when working with the project (see [Reporting a Bug](./reporting-a-bug.md))
+* Core features and enhancements: Provide expanded capabilities or optimizations
+* Documentation: Improve existing documentation or create new information
+* Tests: Add functional, performance, or scalability tests
+
+Issues can be found in GitHub. Any unassigned items are probably still open. When in doubt, ask on Discord about a specific issue (see [Asking a Question](./asking-a-question.md)). We also use the #good-first-issue tag to represent issues that might be good for first timers.
+
+## The Commit Process
+
+Hyperledger Cacti is Apache 2.0 licensed and accepts contributions via GitHub pull requests. When contributing code, please follow these guidelines:
+
+* Fork the repository and make your changes in a feature branch
+* Include unit and integration tests for any new features and updates to existing tests
+* Ensure that the unit and integration tests run successfully prior to submitting the pull request.
+
+### Pull Request Guidelines
+
+A pull request can contain a single commit or multiple commits. The most
+important guideline is that a single commit should map to a single fix or
+enhancement. Here are some example scenarios:
+
+* If a pull request adds a feature but also fixes two bugs, the pull request should have three commits: one commit for the feature change and two commits for the bug fixes.
+* If a PR is opened with five commits that contain changes to fix a single issue, the PR should be rebased to a single commit.
+* If a PR is opened with several commits, where the first commit fixes one issue and the rest fix a separate issue, the PR should be rebased to two commits (one for each issue).
+
+!!! important
+ Your pull request should be rebased against the current master branch. Do not merge the current master branch in with your topic branch. Do not use the Update Branch button provided by GitHub on the pull request page.
+
+### Commit Messages
+
+Commit messages should follow common Git conventions, such as using the imperative mood, separate subject lines, and a line length of 72 characters. These rules are well documented in [Chris Beam's blog post](https://chris.beams.io/posts/git-commit/#seven-rules).
+
+### Signed-off-by
+
+Each commit must include a "Signed-off-by" line in the commit message (``git commit -s``). This sign-off indicates that you agree the commit satisfies the [Developer Certificate of Origin (DCO)](http://developercertificate.org/).
+
+### Commit Email Address
+
+Your commit email address must match your GitHub email address. For more information, see https://help.github.com/articles/setting-your-commit-email-address-in-git/
+
+### Important GitHub Requirements
+
+A pull request cannot merged until it has passed these status checks:
+
+* The build must pass all checks
+* The PR must be approved by at least two reviewers without any
+ outstanding requests for changes
+
+## Inclusive Language
+
+- Consider that users who will read the source code and documentation are from different background and cultures and that they have different preferences.
+- Avoid potential offensive terms and, for instance, prefer "allow list and deny list" to "white list and black list".
+- We believe that we all have a role to play to improve our world, and even if writing inclusive code and documentation might not look like a huge improvement, it's a first step in the right direction.
+- We suggest to refer to [Microsoft bias free writing guidelines](https://learn.microsoft.com/en-us/style-guide/bias-free-communication) and [Google inclusive doc writing guide](https://developers.google.com/style/inclusive-documentation) as starting points.
+
+## Credits
+This document is based on [Hyperledger Sawtooth's Contributing documentation](https://github.com/hyperledger/sawtooth-docs/blob/main/community/contributing.md).
diff --git a/docs/docs/contributing/reporting-a-bug.md b/docs/docs/contributing/reporting-a-bug.md
new file mode 100644
index 0000000000..9a1139bcbc
--- /dev/null
+++ b/docs/docs/contributing/reporting-a-bug.md
@@ -0,0 +1,14 @@
+# Reporting a Bug
+
+To report a bug, submit an issue in our public [issue tracker].
+
+When reporting an issue, please provide as much detail as possible about how to reproduce it. If possible, explain how to reproduce the issue. Details are very helpful. Please include the following information:
+
+* Operating system and version (if Mac, include the processor)
+* Project version
+* Environment details (virtual, physical, etc.)
+* Steps to reproduce the issue
+* Actual results
+* Expected results
+
+ [issue tracker]: https://github.com/hyperledger/cacti/issues
diff --git a/docs/docs/contributing/requesting-a-change.md b/docs/docs/contributing/requesting-a-change.md
new file mode 100644
index 0000000000..ece4ea2a19
--- /dev/null
+++ b/docs/docs/contributing/requesting-a-change.md
@@ -0,0 +1,157 @@
+# Requesting a Change
+
+Hyperledger Cacti is a powerful tool which serves a wide range of use cases.
+Put yourself in our shoes – with a project of this size, it can be challenging
+to maintain existing functionality while constantly adding new features at the
+same time. We highly value every idea or contribution from our community, and
+we kindly ask you to take the time to read the following guidelines before
+submitting your change request in our public [issue tracker]. This will help us
+better understand the proposed change, and how it will benefit the community.
+
+This guide is our best effort to explain the criteria and reasoning behind our
+decisions when evaluating change requests and considering them for
+implementation.
+
+ [issue tracker]: https://github.com/hyperledger/cacti/issues
+
+## Before creating an issue
+
+Before you invest your time to fill out and submit a change request, we kindly
+ask you to do some preliminary work by answering some questions to determine if
+your idea is a good fit and matches the project's philosophy and tone.
+
+__Please find answers to the following questions before creating an issue.__
+
+### It's not a bug, it's a feature
+
+Change requests are intended for suggesting minor adjustments, ideas for new
+features, or to influence the project's direction and vision. It is important
+to note that change requests are not intended for reporting bugs, as they're
+missing essential information for debugging.
+
+If you want to report a bug, please refer to our [bug reporting guide] instead.
+
+ [bug reporting guide]: reporting-a-bug.md
+
+### Source of inspiration
+
+If you have seen your idea implemented in similar project, make sure to collect enough information on its implementation before submitting, as this allows us to evaluate potential fit more quickly. Explain what you like and dislike about the implementation.
+
+### Benefit for the community
+
+Our [Discord server] is the best place to connect with our community. When
+evaluating new ideas, it's essential to seek input from other users and consider
+alternative viewpoints. This approach helps to implement new features in a way
+that benefits a large number of users.
+
+ [Discord server]: https://discord.gg/hyperledger
+
+## Issue template
+
+Now that you have taken the time to do the necessary preliminary work and ensure
+that your idea meets our requirements, you are invited to create a change
+request. The following guide will walk you through all necessary steps to help
+you submit a comprehensive and useful issue:
+
+- [Title]
+- [Context] optional
+- [Description]
+- [Related links]
+- [Use cases]
+- [Visuals] optional
+- [Checklist]
+
+ [Title]: #title
+ [Context]: #context
+ [Description]: #description
+ [Related links]: #related-links
+ [Use cases]: #use-cases
+ [Visuals]: #visuals
+ [Checklist]: #checklist
+
+### Title
+
+A good title is short and descriptive. It should be a one-sentence executive
+summary of the idea, so the potential impact and benefit for the community can
+be inferred from the title.
+
+### Context optional { #context }
+
+Before describing your idea, you can provide additional context for us to
+understand what you are trying to achieve. Explain the circumstances
+in which you're using Hyperledger Cacti, and what you _think_ might be
+relevant. Don't write about the change request here.
+
+!!! success "Why we need this"
+ Some ideas might only benefit specific settings, environments or edge cases. With a little context, change requests can be prioritized more accurately.
+
+### Description
+
+Next, provide a detailed and clear description of your idea. Explain why your
+idea is relevant to Hyperledger Cacti and must be implemented here, and not
+in one of its dependencies.
+
+- __Explain the what, not the why__ – don't explain
+ [the benefits of your idea][Use cases] here, we're getting there.
+ Focus on describing the proposed change request as precisely as possible.
+
+- __Keep it short and concise__ – be brief and to the point when describing
+ your idea, there is no need to over-describe it. Maintainers and future
+ users will be grateful for having to read less.
+
+- __One idea at a time__ – if you have multiple ideas that don't belong
+together, please open separate change requests for each of those ideas.
+
+- :material-run-fast: __Stretch goal__ – if you have a customization or another way to add the proposed change, you can help other users by sharing it here before we maintainers can add it to our code base.
+
+!!! success "Why we need this"
+ To understand and evaluate your proposed change, we need to have a clear understanding of your idea. By providing a detailed and precise description, you can help save you and us time spent discussing further clarification of your idea in the comments.
+
+### Related links
+
+Please provide any relevant links to issues, discussions, or documentation
+sections related to your change request. If you (or someone else) already
+discussed this idea with the community on our discussion board, please include
+the link to the discussion as well.
+
+!!! success "Why we need this"
+ Related links help us gain a comprehensive understanding of your change request by providing additional context. Additionally, linking to previous issues and discussions allows us to quickly evaluate the feedback and input already provided by the community.
+
+### Use cases
+
+Explain how your change request would work from a user's
+perspective – what's the expected impact and why does it not only benefit you,
+but other users? How many of them? Furthermore, would it potentially break
+existing functionality?
+
+!!! success "Why we need this"
+ Understanding the use cases and benefits of an idea is crucial in evaluating its potential impact and usefulness for the project and its users. This information helps us to understand the expected value of the idea and how it aligns with the goals of the project.
+
+### Visuals optional { #visuals }
+
+We now have a clear and detailed description of your idea, including information
+on its potential use cases and relevant links for context. If you have any
+visuals, such as sketches, screenshots, mockups, or external assets, you may
+present them in this section.
+
+!!! tip
+ You can drag and drop the files here or include links to external assets.
+
+Additionally, if you have seen this change, feature, or improvement used
+elsewhere, please provide an example by showcasing
+it and describing how it was implemented and incorporated.
+
+!!! success "Why we need this"
+ Illustrations and visuals can help us maintainers better understand and envision your idea. Screenshots, sketches, or mockups can create an additional level of detail and clarity that text alone may not be able to convey. Also, seeing how your idea has been implemented in other projects can help us understand its potential impact and feasibility in Hyperledger Cacti, which helps us maintainers evaluate and triage change requests.
+
+### Checklist
+
+Thanks for following the change request guide and creating a high-quality
+change request. This section ensures that you have read this guide and have
+worked to your best knowledge to provide us with every piece of information to
+review your idea for Hyperledger Cacti.
+
+__We'll take it from here.__
+
+## Credits
+This document is based on [Material for MkDocs Requesting a Change](https://github.com/squidfunk/mkdocs-material/blob/master/docs/contributing/requesting-a-change.md).
diff --git a/docs/docs/faqs.md b/docs/docs/faqs.md
new file mode 100644
index 0000000000..f2963a897f
--- /dev/null
+++ b/docs/docs/faqs.md
@@ -0,0 +1,18 @@
+# Frequently Asked Questions
+
+## History
+
+### When and how was Cacti created?
+
+Cacti was created as the merer of two pre-existing Hyperledger projects in late 2022. See the [announcement blog post](https://www.hyperledger.org/blog/2022/11/07/introducing-hyperledger-cacti-a-multi-faceted-pluggable-interoperability-framework) for details.
+
+### Who is involved in maintaining Cacti?
+
+The project is maintained jointly by members of Accenture, Fujitsu, and IBM, with contributions from a diverse community of open-source developers and researchers.
+
+## Usage and Logistics
+
+### How do I contribute to the project?
+
+[Here](contributing/how-to-contribute.md) is how you can contribute to Cacti. For specific help or troubleshooting, visit the project's [Discord channels](./contact-us.md).
+
diff --git a/docs/docs/glossary.md b/docs/docs/glossary.md
new file mode 100644
index 0000000000..011cd1daa9
--- /dev/null
+++ b/docs/docs/glossary.md
@@ -0,0 +1,31 @@
+**interoperability**
+
+: capabilities that enable a given blockchain or DLT network to share and exchange ledger state information and assets with each other, and thereby to seamlessly fulfil transactions that advance the states of multiple chains simultaneously.
+
+**asset exchange**
+
+: _to be filled in_
+
+**asset transfer**
+
+: _to be filled in_
+
+**data sharing**
+
+: _to be filled in_
+
+**node server**
+
+: _to be filled in_
+
+**relay**
+
+: _to be filled in_
+
+**connector**
+
+: _to be filled in_
+
+**driver**
+
+: (synonymous with "connector")
diff --git a/docs/docs/guides/developers.md b/docs/docs/guides/developers.md
new file mode 100644
index 0000000000..2d332cf37a
--- /dev/null
+++ b/docs/docs/guides/developers.md
@@ -0,0 +1,3 @@
+# Developer's Guide
+
+We will provide more instructions and guidelines soon. For now, please refer to the [Cacti Contributions guide](../contributing/how-to-contribute.md) and the [project best practices](../references/best-practices.md).
diff --git a/docs/docs/guides/operations.md b/docs/docs/guides/operations.md
new file mode 100644
index 0000000000..f444606144
--- /dev/null
+++ b/docs/docs/guides/operations.md
@@ -0,0 +1,3 @@
+# Operator's Guide
+
+We will provide more instructions and guidelines soon. For now, please refer to the [Cacti Contributions guide](../contributing/how-to-contribute.md) and the [project best practices](../references/best-practices.md).
diff --git a/docs/docs/guides/upgrading.md b/docs/docs/guides/upgrading.md
new file mode 100644
index 0000000000..fc6e79042a
--- /dev/null
+++ b/docs/docs/guides/upgrading.md
@@ -0,0 +1,3 @@
+# Upgrading
+
+We will provide more instructions and guidelines soon. For now, please refer to the [Cacti Contributions guide](../contributing/how-to-contribute.md) and the [project best practices](../references/best-practices.md).
diff --git a/docs/docs/images b/docs/docs/images
new file mode 120000
index 0000000000..847b03ed05
--- /dev/null
+++ b/docs/docs/images
@@ -0,0 +1 @@
+../../images/
\ No newline at end of file
diff --git a/docs/docs/images-weaver b/docs/docs/images-weaver
new file mode 120000
index 0000000000..d6b3bf143b
--- /dev/null
+++ b/docs/docs/images-weaver
@@ -0,0 +1 @@
+../../weaver/resources/images/
\ No newline at end of file
diff --git a/docs/docs/images-weaver-docs b/docs/docs/images-weaver-docs
new file mode 120000
index 0000000000..ea8bec7b12
--- /dev/null
+++ b/docs/docs/images-weaver-docs
@@ -0,0 +1 @@
+../../weaver/docs/static
\ No newline at end of file
diff --git a/docs/docs/index.md b/docs/docs/index.md
new file mode 100644
index 0000000000..d8d5f20abd
--- /dev/null
+++ b/docs/docs/index.md
@@ -0,0 +1,35 @@
+# A Pluggable Interoperability Toolkit for Blockchain and DLT Networks
+
+![Cacti Logo Color](./images/HL_Cacti_Logo_Color.png#gh-light-mode-only){: style="height:70%;width:70%"}
+![Cacti Logo Color](./images/HL_Cacti_Logo_Colorreverse.svg#gh-dark-mode-only){: style="height:70%;width:70%"}
+
+Cacti is a multi-faceted pluggable interoperability framework to link networks built on heterogeneous distributed ledger and blockchain technologies and to run transactions spanning multiple networks. It offers a collection of vendor-neutral and DLT-specific modules, libraries, and SDKs for popular DLTs, and templates to help you configure your networks and adapt your DApps to interoperate with other networks and their DApps for the purposes of carrying out atomic asset swaps, asset transfers, sharing ledger state, and other use cases. Cacti does not require deployment of, or dependence on, separate chains, and therefore is uniquely suited to help private (or permissioned) DLT networks be interoperable while keeping control of their governance and maintaining security and privacy.
+
+Cacti is the product of a [merger](https://www.hyperledger.org/blog/2022/11/07/introducing-hyperledger-cacti-a-multi-faceted-pluggable-interoperability-framework) between the pre-existing Cactus and Weaver Lab projects, bringing together two code bases with overlapping as well as complementary feature sets under a common umbrella repository. The core (and shared) design philosophy of Cacti is the enablement of interoperability in a manner that preserves the self-sovereignty of existing networks while providing consensus-driven control over cross-network interactions, does not require modifications to existing DLT stacks, and eschews reliance on third-party chains. Cacti covers the spectrum of generic interoperability modes required to fulfil cross-network transactions, namely asset exchanges, asset transfers, and ledger data sharing.
+
+Cacti is built on a modular architecture and supports extensions through the plugin model. It maintains certain core components that are independent of DLTs, and also packages (called _connectors_ or _drivers_) and libraries for specific DLTs. The following blockchains and DLTs are presently supported to varying extents within the repository:
+
+* Hyperledger Besu
+* Hyperledger Fabric
+* Hyperledger Indy
+* Hyperledger Iroha
+* Hyperledger Sawtooth
+* R3 Corda
+* Go-Ethereum
+* Quorum
+* Xdai
+
+Client libraries and examples are provided in the following languages: JavaScript/TypeScript, Golang, Java/Kotlin, Solidity.
+
+## Useful links
+
+* [Vision](./vision.md)
+* [Architecture](./architecture.md)
+* [Cactus whitepaper](https://github.com/hyperledger/cacti/blob/main/whitepaper/whitepaper.md)
+* [Weaver RFCs](https://github.com/hyperledger/cacti/tree/main/weaver/rfcs)
+* [Running pipelines with Cactus packages](./cactus/)
+* [Running pipelines with Weaver packages](./weaver/)
+
+!!! note
+
+ If you have questions not addressed by this documentation, or run into issues with any of the tutorials, please [reach out](./contact-us.md) to the Cacti maintainers (and community).
diff --git a/docs/docs/references/best-practices.md b/docs/docs/references/best-practices.md
new file mode 100644
index 0000000000..ec0dab879d
--- /dev/null
+++ b/docs/docs/references/best-practices.md
@@ -0,0 +1,3 @@
+# Project Best Practices
+
+See the [Hyperledger Project Best Practices guidelines](https://github.com/hyperledger/toc/blob/gh-pages/guidelines/project-best-practices.md) for a comprehensive and up-to-date set of practices recommended for anyone wishing to build, maintain, or contribute to a team-based open-source project, especially one built on GitHub.
diff --git a/docs/docs/references/business.md b/docs/docs/references/business.md
new file mode 100644
index 0000000000..79d50a9515
--- /dev/null
+++ b/docs/docs/references/business.md
@@ -0,0 +1,3 @@
+# BUsiness Uses of Cacti
+
+Here is a list of practical real-world projects that Cacti (or portions of it) have been used in.
diff --git a/docs/docs/references/events.md b/docs/docs/references/events.md
new file mode 100644
index 0000000000..e0ddcfef59
--- /dev/null
+++ b/docs/docs/references/events.md
@@ -0,0 +1,3 @@
+# Events and Podcasts
+
+See list of presentations and panel discussions on the topic of interoperability generally as well as Cacti specifically.
diff --git a/docs/docs/references/github.md b/docs/docs/references/github.md
new file mode 100644
index 0000000000..9a5b9b76f2
--- /dev/null
+++ b/docs/docs/references/github.md
@@ -0,0 +1,3 @@
+# Hyperledger GitHub Contribution Guide
+
+See the [Hyperledger GitHub Contribution Guide](https://github.com/hyperledger/toc/blob/gh-pages/guidelines/github-contribution-guide.md) for instructions on how to use, sync, and contribute to any open-source Hyperledger project maintained on GitHub.
diff --git a/docs/docs/references/publications.md b/docs/docs/references/publications.md
new file mode 100644
index 0000000000..6034c64945
--- /dev/null
+++ b/docs/docs/references/publications.md
@@ -0,0 +1,3 @@
+# Published Articles and Research Papers
+
+See list below.
diff --git a/docs/docs/references/specs.md b/docs/docs/references/specs.md
new file mode 100644
index 0000000000..cbb84b7282
--- /dev/null
+++ b/docs/docs/references/specs.md
@@ -0,0 +1,10 @@
+# Technical Specifications
+
+The two legacy projects that Cacti is comprised of have independent sets of design and interface specifications, including examples of usage, as follows:
+
+- **Cactus**: See the official [Cactus whitepaper](https://github.com/hyperledger/cacti/tree/main/whitepaper/whitepaper.md) for technical designs and usage.
+- **Weaver**: See the official [Weaver RFCs](https://github.com/hyperledger/cacti/tree/main/weaver/rfcs/) for technical designs and interface specifications.
+
+!!! note
+
+ We will create a unified set of technical specifications for Cacti as the Cactus and Weaver modules get integrated in a deeper way following the [reference architecture](). Keep watching these pages for updates!
diff --git a/docs/docs/use-cases.md b/docs/docs/use-cases.md
new file mode 100644
index 0000000000..2c50ad393c
--- /dev/null
+++ b/docs/docs/use-cases.md
@@ -0,0 +1,3 @@
+# Use Cases and Applications for Cacti
+
+This page is under construction. While we are working on it, you can find compelling examples and sample code [here](https://github.com/hyperledger/cacti/blob/main/whitepaper/whitepaper.md), [here](./weaver/user-stories/), [here](https://github.com/hyperledger/cacti/tree/main/examples), and [here](https://github.com/hyperledger/cacti/tree/main/weaver/samples).
diff --git a/docs/docs/vision.md b/docs/docs/vision.md
new file mode 100644
index 0000000000..7f2799f0fc
--- /dev/null
+++ b/docs/docs/vision.md
@@ -0,0 +1,21 @@
+## Mission and Objectives
+
+Cacti aims to make the process of interoperation, interconnection, and integration of systems built on blockchain or DLT with each other (or with centralized systems) easy, controllable, trustworthy, and decentralized. It will allow networks to remain self-sovereign and evolve independently without losing the ability to link with other networks and manage digital assets across networks when required. In effect, it enables a _network-of-networks_, or a global scale decentrantralized system of networks (akin to the Internet) without forcing all networks to coalesce, or subscribe to, a single canonical chain.
+
+## Project Scope
+
+The existence of several blockchain and distributed ledger technologies of different flavors in the market as well as networks of varying scopes and sizes built on them necessitates the need for interoperability and integration, lest we end up with a fragmented ecosystem where digital assets and the workfows (often contracts) governing them remain isolated in silos. The solution to this is not to force all chains to coalesce (i.e., "*a single chain to rule them all*") but rather enable the networks to orchestrate transactions spanning their boundaries without sacrificing security, privacy, or governance autonomy (i.e., self-sovereignty). Hyperledger Cacti offers a family of protocols, modules, libraries, and SDKs, that can enable one network to be interoperable with, and carry out transactions directly with, another while eschewing the need for a central or common settlement chain. Cacti will allow networks to share ledger data, and exchange and transfer assets atomically, and manage identities, across their boundaries, as illustrated in the figure below.
+
+
+
+As a fusion of two earlier systems (Cactus and Weaver) that have similar philosophies and goals, yet offer distinct mechanisms backed by differemt design and trust assumptions, Cacti offers a spectrum of selectable and configurable features for cross-network transaction orchestrations. An example illustrated below shows how distributed applications running on Fabric and Besu ledgers respectively can carry out the same set of cross-network transactions using the **Node Server** (Cactus legacy) or through **Relays** (Weaver legacy).
+
+
+
+The present (initial) version of the Cacti code base is simply an aggregation of the legacy Cactus and Weaver code bases with their original folder structures. Until merge and integration (see further below), users should examine, test, and use them separately as follows:
+- Cactus code and documentation lies within this (root) folder, excluding the `weaver` folder. See [Cactus documentation](./README-cactus.md) to test and use Cactus.
+- Weaver code and documentation lies within the [weaver](./weaver/) folder. See [Weaver documentation](./weaver/README.md) to test and use Weaver.
+
+## Project Roadmap
+
+You can find the project roadmap in the [GitHub repository](https://github.com/hyperledger/cacti/blob/main/ROADMAP.md).
diff --git a/docs/docs/weaver/architecture-and-design/decentralized-identity.md b/docs/docs/weaver/architecture-and-design/decentralized-identity.md
new file mode 100644
index 0000000000..3fcc40badf
--- /dev/null
+++ b/docs/docs/weaver/architecture-and-design/decentralized-identity.md
@@ -0,0 +1,162 @@
+---
+id: decentralized-identity
+title: Decentralized Identity
+---
+
+
+
+Interoperation for asset or data transfers/exchanges relies on a message-passing infratructure and pan-network data processing modules, as we have seen in earlier pages. But there is yet another crucial basis these data processing modules need to satisfy our design principles of network independence and avoidance of trust parties. This is the ability of a network as a whole and of its individual members to accurately identify and authenticate another network's members.
+
+Further, for the networks to remain independent and interact ad hoc with each other, we cannot impose a central authority that unifies their private identity management systems. So the identity basis of interoperation must be decentralized, leading inevitably to the requirement of exchanging identity information across networks as a pre-requisite for asset and data transfers/exchanges. This is illustrated in the figure below where interoperation protocols are classified in two planes (or tiers), data and identity, with the former depending on the latter.
+
+![alt text](../../../images-weaver-docs/architecture-assets/identity-data-planes.jpg)
+
+- In the __data plane__ lies the protocols that effect the actual exchanges of data and assets. The figure above illustrates a typical data-sharing instance, where the network at the left requests a data record from the right. The latter receives the request via the two relays (not explicitly marked in this diagram) and runs an access control check through consensus in its _interop module_ before responding with the data record and supporting proof. The network at the left receives the data and proof, again via the two relays, and verifies the data using the supplied proof. __Note: since a core part of both request and proof are digital signatures of network members, the ability to identify and authenticate network members is necessary to perform these endpoint functions__.
+- Here is where the __identity plane__ enters the picture, as a trust anchor for the data plane. The most general function of this plane is illustrated in the figure, where the networks get each others' identity and configuration (i.e., membership structure and network topology) information. This exchange has as its own trust basis (or dependency) a set of identity providers and verifiers. (_Note_: these identity providers and verifiers may belong to the two networks or they could be external entities.) The outcome of the exchange is a record of the other network's identity and configuration information on one's ledger, which can then be looked up in a data plane protocol instance.
+
+### Identity Plane: Strawman Approach
+
+The simplest identity plane protocol involves a direct exchange of identity information between representatives of the two networks: in other words, an API integration. But this approach suffers from the same drawbacks that API integration in the data plane would. It diminishes a blockchain network to a single trusted spokesperson, exposing that network to risk. Even if such a spokesperson could be designated, appropriately framing access control policies for potentially every other blockchain network in the world would be very challenging. This approach is therefore insecure and not scalable, and therefore ought to be treated purely as a strawman.
+
+### Networks as Groups of Self-Sovereign Members
+
+A secure and sustainable identity plane plaform can be built on the basis of _self-sovereign identity_ and _decentralized identifiers_. We recognize that:
+
+- Each constituent member of a blockchain network may already possess an identity from a third-party provider
+- Membership within a network can be treated as a property of a sovereign organization rather than subordination to a network's governing authority
+- DIDs allow members to control who they wish to share their identities with and the levels of exposure
+- Network membership lists and individual members' identities can respectively be validated by different providers, thereby maintaining decentralization of infrastructure
+
+### Distributed Identity Management Infrastructure
+
+The distributed identity management infrastructure for interoperation is illustrated in the figure below. We assume the existence of one or more _Interoperation Identity Networks (IINs)_ that act as registries and credential validators for the organizations that form the memberships of blockchain networks.
+
+![alt text](../../../images-weaver-docs/architecture-assets/decentralized-id-mgmt-arch.jpg)
+
+An IIN can be built from scratch to facilitate blockchain interoperation, but it can also be an augmentation of an existing decentralized identity provider or registry. Its purpose is to maintain identity records and credentials for organizations and validate these to third parties as per the desire of the identity or credential owner. In this model, an IIN can itself be reputed or it can bring together many reputed and trusted identity providers (called _stewards_) into a shared network. As long as the members of two blockchain networks have shared trust in one or more IINs, an identity plane exchange can be effected, thereby setting the foundation for data and asset transfers.
+
+#### Interoperation Identity Network
+
+The ideal IIN architecture is illustrated in the figure below, inspired by Hyperleder Indy, whose architecture is used in our canonical (or reference) implementation. Built on a DLT itself, an Indy-based IIN can provide the combination of assurance and decentralization that a centralized registry cannot. Further, such an IIN will support the entire SSI and DID standard, maintaining credential schemas and verification keys, and issuing _verifiable credentials_ that can be used for privacy-preserving authentications.
+
+![alt text](../../../images-weaver-docs/architecture-assets/iin.jpg)
+
+An IIN is modeled as a network with a distributed shared ledger, implemented using an Indy Node Pool and running BFT consensus. The ledger is also (ideally) meant to be publicly accessible, though there is nothing preventing our protocols from working with a private IIN.
+
+A canonical IIN maintains the following:
+
+- DID records corresponding to organizations that are members of one or more blockchain networks, whose salient attributes include:
+ * Unique (within an IIN) identifier or _verinym_ for the identity owner
+ * Service endpoint for the identity owner
+ * Credential schemas
+ * Credential definitions (public keys used to authenticate signed credentials)
+
+Every IIN has a set of bootstrapped _trust anchors_ called _stewards_. A steward can create other trust anchors by issuing them suitable credentials. The trust anchors are the primary identity providers in our distributed identity management architecture. They can be existing reputed authorities or identity providers who are trusted to certify blockchain networks' memberships, or they can be created ad hoc by a consortium representing the members of a blockchain network.
+
+For one blockchain network to discover and validate another in the identity plane, it must trust one or more IINs and trust anchors who can provide that validation. We envision a shared and mutually reinforcing trust among stewards and other anchors within an IIN. An anchor could gain trust by virtue of joining a well-established IIN. Similarly, an IIN bootstrapped with well-known stewards gains trust because of the collective reputations of those stewards.
+
+Examples of entities that can act as stewards or trust anchors within IINs: the Sovrin Foundation (an organization dedicated to enabling open-source digital ID management, and which also maintains Indy), companies like Maersk or Walmart that have founded real-world blockchain networks, companies like IBM or R3 that maintain popular DLT platforms.
+
+IINs don't have to be built on Indy. Alternatives like Sidetree exist, providing similar functionality. There are also various existing DID registries that are already issuing credentials to existing organizations. To the extent possible, we would like to leverage all of this existing infrastructure and not force any network menmber to find yet another identity provider. Therefore, these existing registries or networks can be used as IINs: the only requirement is that they follow the standards for SSI and DIDs and issuing VCs.
+
+#### Network Membership Credentials
+
+Two kinds of credentials (each with a schema and a definition) are maintained on an IIN ledger:
+
+1. __Member list__: This contains a network name or ID and a set of DIDs of that network's members.
+ * This is a per-network credential whose schema and verification key must be maintained on an IIN.
+ * This is issued by a steward or trust anchor in an IIN and is associated with that steward's or anchor's DID.
+2. __Membership__: This contains an oranization's attributes, including the set of IDs of networks to which it belongs.
+ * This is designed to be an extensible credential, i.e., support more attributes in the future.
+ * An existing membership credential (of the VC form) can be used as long as it matches the schema recorded on an IIN.
+ * The issuer must be a steward or trust anchor (or equivalent, if it's a non-Indy registry) in an IIN.
+ * This is associated with the member's DID.
+
+#### Identity Info: Units of Exchange
+
+The IIN is used to discover the membership list of a foreign network and establish the authenticity of its members. Memnbership credentials are independent of blockchain networks.
+
+But data plane transfers and exchanges require knowledge of in-network identities and certificates, which are issued by a network's membership manager(s) to peers and clients. These are not shared through IINs for several reasons. First, the volume of this information can be quite high and further it is subject to change based on a network's internal needs. Also, a network or its members may not wish to expose all this information to an IIN, which is designed to be publicly accessible. Therefore, it is infeasible or undesirable to shared network-specific credentials via established IINs. Instead, we will enable the _peer-to-peer_ exchange of such credentials after the membership discovery and validation procedure is complete.
+
+Specifically, the identity information for a network member consists of the set of certificate chains of the membership managers for that particular member (organization). These consist of one or more hierarchies of root and intermediate CA certificates. For example:
+
+- In Fabric, each organization uses one or more MSPs (_membership service providers_), each running one or more root and intermediate Fabric-CA servers. Any network peer belonging to an organization is issued a certificate authorized by one of these certificate chains. To authenticate a network peer or client in a data plane protocol, knowledge of these certificate chains is essential.
+- In Corda, the entire network typically consists of a hierarchy of CAs, from a root to multiple _doormen_, and from each doorman to multiple nodes. Finally, the certificates used to sign transactions are issued by the node CAs. Therefore, knowledge of the root, doormen, and node CA certificates is essential for authenticating signers.
+
+More generally, each unit of exchange corresponding to a network member is a _Security Group_, so-called because each network member is an independent organization in its own right with a security domain.
+
+#### IIN Agents as Member Representatives
+
+Every network member needs a proxy (either an abstraction or a separate module) for communication with IINs and with the members of foreign networks in the identity plane. We use the term "IIN Agent" to refer to this proxy, and illustrate its functioning as a module within a Fabric network through the reference diagram below.
+
+![alt text](../../../images-weaver-docs/architecture-assets/iin-augmented-network.jpg)
+
+In the reference implementation, IIN Agents are built as Hyperledger Aries nodes and communicate with each other and with IIN stewards and trust anchors using the Aries protocol. (IIN stewards and trust anchors are also built as Aries nodes.)
+
+The list of trusted IINs is recorded on the local network's shared ledger, as illustrated in the figure (and thereby agreed through network consensus). To be able to interoperate with another network, the latter's members must have identity records maintained by sume subset of these trusted IINs and their VCs must be issued by these IINs stewards and trust anchors.
+
+#### Protocols
+
+Let us consider a scenario where _NETWORK 1_ and _NETWORK 2_ wish to interoperate, and their respective member organizations are as follows:
+
+- _NETWORK 1_: Org3, Org4, Org5
+- _NETWORK 2_: Org1, Org2
+
+Each network discovers the other's member list and obtains and records ech member's security group to the local shared ledger. We can enumerate these as follows:
+
+- _NETWORK 1_ discovers and registers _NETWORK 2_:Org1
+- _NETWORK 1_ discovers and registers _NETWORK 2_:Org2
+- _NETWORK 2_ discovers and registers _NETWORK 1_:Org3
+- _NETWORK 2_ discovers and registers _NETWORK 1_:Org4
+- _NETWORK 2_ discovers and registers _NETWORK 1_:Org5
+
+Each of these can be done in parallel and each discovery and registration operation is idempotent as long as the security group of a network member does not change.
+
+The high-level workflow for discovery and registration is illustrated below (using _NETWORK 2_ as the seeker and _NETWORK 1_ as the provider).
+
+![alt text](../../../images-weaver-docs/architecture-assets/protocol-identity-overview.jpg)
+
+(_Note_: "Network unit" is synonymous with "network member")
+
+Prerequisites for this process are:
+
+- The member list credential of _NETWORK 1_ is provided by a steward or trust anchor in a particular IIN which is also on the trust list recorded in the ledger of _NETWORK 2_.
+- The membership credentials for both organizations in _NETWORK 1_ are supplied by one or more IINs that are on the trust list of _NETWORK 2_.
+- Each of the 5 organizations (2 in _NETWORK 1_ and 3 in _NETWORK 2_) has an IIN Agent running on their behalf.
+
+Let us take the example of _NETWORK 2_ having already obtained the security group info for Org4 and Org5 in _NETWORK 1_. It is now discovering and registering _NETWORK 1_:Org3. We assume that there is a single IIN with a single Steward for validating member list as well as membership credentials for all members of both the networks.
+
+_Note_: we assume here for simplicity that a steward as a reputed identity provider has a mechanism to validate the bona fides of an orgganization and its membership in a given network. There are other techniques involving group signatures that could be applied to corroborate an organization's claim to network membership rather than requiring a steward to use an out-of-band security mechanism, but that is presently beyond the scope of this design.
+
+The discovery and registration procedure steps are as follows:
+
+- The IIN Agent for Org3 registers its membership to _NETWORK 1_ at the Steward in IIN:
+ * _NETWORK 1_:Org3 gets a DID (verinym) issued
+ * The Steward updates the member list credential for _NETWORK 1_ to include Org3
+ * Org3 obtains a membership credential from Steward
+- The IIN Agent for Org3 issues itself a self-signed VC containing its security group info
+- The IIN Agent for _NETWORK 2_:Org2 (only one organization in the network needs to do this) obtains the new member list credential from Steward in IIN and validates it using the IIN ledger records
+- The IIN Agent for _NETWORK 2_:Org2 discovers that Org3 is a member of _NETWORK 1_, fetches Org3's membership credential from Org3's IIN Agent, and validates it using the IIN ledger records
+- The IIN agent for _NETWORK 2_:Org2 fetches the self-signed security group credential from the IIN agent of _NETWORK 1_:Org3 and validates it
+- The IIN agent for _NETWORK 2_:Org2 triggers a flow among the IIN Agents of _NETWORK 2_ to collect signatures endorsing the security group info for _NETWORK 1_:Org3 fetched above
+ * The IIN Agent for _NETWORK 2_:Org1 gets this endorsement request, and validates both the membership credential and the security group info for _NETWORK 1_:Org3 by communicating with the Steward, the IIN ledger, and the IIN Agent for _NETWORK 1_:Org3
+ * The IIN Agent for _NETWORK 2_:Org1 signs the request from Org2 containing the security group info for _NETWORK 1_:Org3 after the above check succeeds
+- When the IIN agent for _NETWORK 2_:Org2 gets signatures from the IIN Agents representing each member of _NETWORK 2_, it submits the security group info for _NETWORK 1_:Org3 alon with the signatures to the _interop module_ (typically smart contract) for recording on the ledger of _NETWORK 2_
+ * Now the ledger of _NETWORK 2_ contains the identities and certificates of all three members of _NETWORK 1_: Org3,Org4,Org5, and data plane interoperation may ensue.
+
+_Note_: the last step above (recording to the local ledger via the _interop module_) may be performed by IIN Agents of both Org1 and Org2 as they have no means of synchronizing their actions, but this recording will be idempotent and hence not cause any harm.
+
+The process above is illustrated with a few more details in the sequence of protocol diagrams below.
+
+![alt text](../../../images-weaver-docs/architecture-assets/protocol-registration-phase.jpg)
+
+![alt text](../../../images-weaver-docs/architecture-assets/protocol-get-info-phase.jpg)
+
+![alt text](../../../images-weaver-docs/architecture-assets/protocol-update-info-phase.jpg)
+
+### References
+Bishakh Chandra Ghosh, Venkatraman Ramakrishna, Chander Govindarajan, Dushyant Behl, Dileban Karunamoorthy, Ermyas Abebe, Sandip Chakraborty, [Decentralized Cross-Network Identity Management for Blockchain Interoperation](https://arxiv.org/abs/2104.03277), _ICBC 2021_
diff --git a/docs/docs/weaver/architecture-and-design/drivers.md b/docs/docs/weaver/architecture-and-design/drivers.md
new file mode 100644
index 0000000000..e98bf16a69
--- /dev/null
+++ b/docs/docs/weaver/architecture-and-design/drivers.md
@@ -0,0 +1,17 @@
+---
+id: drivers
+title: Drivers
+---
+
+
+
+The driver is responsible for all communication between the relay and its network. In the previous sections we have thought about the driver as a component of the relay. We have done this because conceptually it makes sense to think about it like that. However, in our reference implementation we have made it a seperate process which communicates with the relay via gRPC, as shown below. There are two main reasons for this:
+
+1. There must exist a different driver for each network type (e.g. Fabric, Corda etc.) and therefore having the driver as a seperate process makes it easy to "plug" different drivers into the relay.
+2. A possible use case of the relay is that a single relay instance may have multiple drivers (e.g. if multiple entities in the network want to run their own driver). In this case, this plugin style approach of drivers makes it possible to do without having to modify code for each configuration.
+
+![](../../../images-weaver-docs/architecture-assets/driver_architecture.png)
diff --git a/docs/docs/weaver/architecture-and-design/overview.md b/docs/docs/weaver/architecture-and-design/overview.md
new file mode 100644
index 0000000000..12c6400b73
--- /dev/null
+++ b/docs/docs/weaver/architecture-and-design/overview.md
@@ -0,0 +1,34 @@
+---
+id: overview
+title: Overview
+---
+
+
+
+The below diagram shows a high level architecture diagram of the Weaver framework.
+
+![](../../../images-weaver-docs/architecture-assets/architecture_overview.png)
+
+## Network
+
+The networks in the system can be made up of various heterogenious technologies, including Hyperledger Fabric and Corda. Each network in the system needs to contain an interoperability (IOP) module that enables them to communicate with the relays.
+
+## Relay
+
+The relays act as a conduit to facilitate communication of protocols between networks (e.g. data transfer, asset exchange etc). The roles of the relays are described in more detail in [relay](./relay.md).
+
+# Design Decisions
+
+The high level design decisions that were made for the system are outlined here.
+
+## Synchronous vs Asynchronous message communication
+
+We decided to go with an asynchronous message architecture. The primary reason for this is because requests can take an arbitary amount of time to respond, it is not practical for a synchronous message to wait that long for a reply. For example, obtaining a 12 block confirmation on the Bitcoin network can take about 2 hours.
+
+## Message vs connection oriented communication
+
+We decided to go with a message oriented architecture. The primary reason for this is because it makes the system more fault tolerant. With a message oriented architecture the requester and responder don't need to be alive at the same time. For example, if the requestor crashes while the responder is processing the request, the communication is not interrupted since the responder will just send a message when it has finished processing the request. The design choice also enables the systen to be made more fault tolerant in the future by implementing message queues between components in the system.
diff --git a/docs/docs/weaver/architecture-and-design/relay.md b/docs/docs/weaver/architecture-and-design/relay.md
new file mode 100644
index 0000000000..b74fd13937
--- /dev/null
+++ b/docs/docs/weaver/architecture-and-design/relay.md
@@ -0,0 +1,29 @@
+---
+id: relay
+title: Relay
+---
+
+
+
+![](../../../images-weaver-docs/architecture-assets/relay_architecture.png)
+
+As mentioned in the overview, relays facilitate communication of protocols between networks. To do this, they are composed of three main pieces:
+
+- `Relay service` - A gRPC server that listens for and handles incoming requests from other relays. For example, a remote network requesting state.
+- `App service` - A gRPC server that listens for and handles requests from applications that are requesting an asset from a remote network.
+- `Driver` - The driver is responsible for all communication between the relay and its network. The driver is described in more detail in [drivers](./drivers.md).
+
+The diagram below shows an example communication between two networks, A and B, where network A is requesting state from network B.
+
+![](../../../images-weaver-docs/architecture-assets/relay_flow.png)
+
+1. An application sends a request to their networks relay over gRPC
+2. The local relay inspects the query within the request and uses the relevant information to forward the request to the correct remote relay
+3. The remote relay's driver interprets the query and invokes the smart contract for the query
+4. Once network B has returned a response to its relay, the relay forwards the response back to relay A
+5. The application gets the response from the relay, this can either be via a push or pull mechanism
+6. The application invokes a domain specific smart contract to process the response from network B
diff --git a/docs/docs/weaver/architecture-and-design/weaver-dapps.md b/docs/docs/weaver/architecture-and-design/weaver-dapps.md
new file mode 100644
index 0000000000..b4cc327242
--- /dev/null
+++ b/docs/docs/weaver/architecture-and-design/weaver-dapps.md
@@ -0,0 +1,32 @@
+---
+id: weaver-dapps
+title: Weaver Dapps
+---
+
+
+
+As mentioned in the [overview](./overview.md), DLTs that integrate with Weaver must contain an interop (IOP) module to facilitate interoperation between ledgers. The interop module contains all the logic responsible for membership, verification policies and access control policies (refer to the RFCs for more information on these). Below shows the architecture of how these interop modules work with the two currently supported DLTs, Fabric and Corda.
+
+## Fabric
+
+When Fabric is the requesting network, the IOP module is used to verify the proof and then forward the state onto the application chaincode.
+
+![](../../../images-weaver-docs/architecture-assets/fabric_dapp_flow1.png)
+
+When Fabric is the responding network, the IOP module is in charge of verifying the identity of the requester, making sure the requester has access to the state they are requesting, and then finally retrieving the state from the application chaincode to send back to the requesting network.
+
+![](../../../images-weaver-docs/architecture-assets/fabric_dapp_flow2.png)
+
+Verification Policy, Access Control and Membership are modular components within the interop chaincode for seperation of concerns of the code.
+
+## Corda
+
+As can be seen from the diagrams below, the architecture for Corda is very similar to that of Fabric. The main difference is that the interop module and the application specific flows are in seperate CorDapps, instead of seperate chaincodes like in Fabric.
+
+![](../../../images-weaver-docs/architecture-assets/corda_dapp_flow1.png)
+
+![](../../../images-weaver-docs/architecture-assets/corda_dapp_flow2.png)
diff --git a/docs/docs/weaver/deployment-considerations/deployment-patterns.md b/docs/docs/weaver/deployment-considerations/deployment-patterns.md
new file mode 100644
index 0000000000..bfcd1610b2
--- /dev/null
+++ b/docs/docs/weaver/deployment-considerations/deployment-patterns.md
@@ -0,0 +1,10 @@
+---
+id: "deployment-patterns"
+title: Deployment Patterns
+---
+
+
diff --git a/docs/docs/weaver/deployment-considerations/governance-and-policies.md b/docs/docs/weaver/deployment-considerations/governance-and-policies.md
new file mode 100644
index 0000000000..bc1314e27c
--- /dev/null
+++ b/docs/docs/weaver/deployment-considerations/governance-and-policies.md
@@ -0,0 +1,10 @@
+---
+id: "governance-and-policies"
+title: Governance and Policies
+---
+
+
diff --git a/docs/docs/weaver/deployment-considerations/legal-and-regulation.md b/docs/docs/weaver/deployment-considerations/legal-and-regulation.md
new file mode 100644
index 0000000000..f2ffed8875
--- /dev/null
+++ b/docs/docs/weaver/deployment-considerations/legal-and-regulation.md
@@ -0,0 +1,10 @@
+---
+id: legal-and-regulation
+title: Legal and Regulation
+---
+
+
diff --git a/docs/docs/weaver/design-principles.md b/docs/docs/weaver/design-principles.md
new file mode 100644
index 0000000000..21b57378a5
--- /dev/null
+++ b/docs/docs/weaver/design-principles.md
@@ -0,0 +1,101 @@
+---
+id: design-principles
+title: Design Principles
+---
+
+
+
+We list principles and considerations that guide the design of a framework for interoperability between decentralized networks, along with associated reasoning. Our present solution, though a work-in-progress, attempts to adhere to these principles.
+
+
+### How to determine need for interoperation, and its mode and mechanics?
+- Assess dependence decision (i,e., between networks) to determine goals and required assurances:
+ * The decision to depend on a network is a complex one, as a network is itself an affiliation of independent parties.
+ * There are different approaches with varying levels of complexity and assurance.
+ * Examine structural assurances provided by networks and their participants, and do a cost-benefit analysis to determine a suitable approach.
+- The mechanics of interoperation can be derived from assumptions made in the above assessment.
+- __Our assumptions and aproach__:
+ * Individual network participants are untrustworthy.
+ * The network is trustworthy in the collective.
+ * The internal consensus mechanism of a network protects it from Byzantine failures.
+ * Interoperability needs will not force structural changes or forks in a network nor constrain that network's internal evolution.
+
+
+### Principles and Ideals for Interoperability Solution Design
+Here are our guiding principles that accord with our assumptions and approach, in no particular order.
+
+#### Favor Technical Assurances over Social Assurances
+- Technical assurances are provided by protocols and security mechanisms, including distributed consensus.
+- Social assurances include governance (collectively, through a consortium, or via a hierarchy), legal rules and regulations, reputations and history of past behavior.
+- The reason to favor the former is that it can provide provable guarantees that are independent of the trustworthiness of individual participants, whereas the latter can be brittle and rely on participants' compliance.
+
+#### Be Inclusive and Accommodate Heterogeneity
+- Avoid approaches for protocol design that are specific to a particular DLT implementation or network structure.
+- Specify the communication protocol in a network-neutral language.
+- Design protocol units that can abstract out common features for information and assurances from diverse DLTs.
+
+#### Allow Networks to Retain Independence and Collective Sovereignty
+- A network is treated as an independent self-governing system with the freedom of choice to interoperate with another on a need basis.
+- Network members retain collective sovereignty over their internal processes as well as access control rules governing remote interoperation.
+- Networks have full and collective control, via their native consensus and smart contract mechanisms, over exposure of data, assets, and transactions to other networks.
+ * A network acts as a unit for framing and enforcing rules controlling access to information held on its ledger(s) by a remote network.
+- Similarly, networks have full and collective control, via their native consensus and smart contract mechanisms, over acceptance of data or assets and verifications of transactions occurring in, other networks.
+
+#### Minimize Network Coupling
+- Networks/consortia must retain independence for governance and configuration
+ * Therefore, interoperation must require loose coupling rather than a merging or overlapping of two networks
+- Loose coupling between dependent networks allows changes to counterparty networks' implementations with minimal or no impact to cross-network dependencies.
+- Domain decoupling:
+ * Define standards for contract interfaces
+ * Define standards for representing data types and assets types (e.g. https://www.gs1.org/traceability)
+ * Define standards for identity portability
+- Communication decoupling:
+ * Define standards for network interface/API
+ * Define standards for protocol behavior
+ * Define standards for messaging formats
+
+#### Do not Compromise on Privacy and Confidentiality
+- By design, a permissioned network should retain its privacy, and interoperation mechanisms should not leak information outside the bounds of what access control rules allow.
+- Cross-network communications should be kept private and confidential and revealed only to interested parties, applying the principle of least privilege.
+
+#### Minimize Trust Footprint and Avoid Centralization
+- Design for decentralization across networks as within networks:
+ * Avoid introducing centralized services that are easy to compromise
+ * Assume that failure scenarios that apply to networks also hold for any service coordinating interoperability.
+- Reduce trust to only what is essential (i.e. identity providers in the network).
+- No trusted third-party intermediary or infrastructure (e.g., Polka Dot, Cosmos) should be relied upon for the purpose of cross network data verification or settlement.
+- Reduce trust and centralization to only essential functions that cannot be completely decentralized:
+ * Communicate messages across networks using some networking infrastructure:
+ - This communication infrastructure is not trusted to maintain confidentiality or integrity of messages, and it may mount denial of service attacks.
+ * Identity provision and verification:
+ - This is necessary for permissioned networks that have private memberships governed by a _committee_ that may be centralized or distributed.
+
+#### Favor dependence on proofs over trust
+- _This is also implied by the "No Trusted Intermediaries" principle_.
+- Information transferred across networks must carry verifiable proofs.
+- The receiving network must be able to specify a _verification policy_ for proofs that it can independently and collectively (i.e., through consensus) verify.
+
+#### Minimize Impact and Adaptation
+- Enabling interoperation must not require changes to existing network protocols.
+- Enabling interoperation must not impact existing network operation in any way nor require any blockchain forks.
+- Adaptation in existing smart contracts and applications must be avoided unless absolutely necessary, and follow modular principles.
+
+#### Maximize Operational Efficiency
+- Minimize payloads in cross-network protocol units.
+- Strive for event-driven asynchronous messaging architectures (_this is also implied by the "Minimal Coupling" principle_).
+
+
+### Design Guidelines for Network Architects and Developers
+- Architects and application developers (both in the smart contract and services layers) must design with interoperability in mind:
+ * This has the advantage of minimizing or eliminating any code adaptations required for interoperability during a network's life cycle.
+- Apply standards when defining assets, data and logic within network apps to maximize external consumption:
+ * Networks with well-defined standards-based interfaces simplifies interoperability:
+ - Interfaces include: contracts, data/assets, identity, APIs, protocol, messaging.
+- Enables network implementation to evolve while eliminating or minimising external impact:
+ * Implement in a modular way: many patterns and principles exist in the field of web services.
+ * Decouple interoperability-related application modules as much as possible (_this guideline applies to blockchain-related modules within enterprise apps too_).
+ - This will make maintenance easier and also allow administrators to minimize the amount of code that needs to be deployed in higher-security enterprise zones.
diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/besu.md b/docs/docs/weaver/getting-started/enabling-weaver-network/besu.md
new file mode 100644
index 0000000000..81c3c4e16c
--- /dev/null
+++ b/docs/docs/weaver/getting-started/enabling-weaver-network/besu.md
@@ -0,0 +1,11 @@
+---
+id: besu
+title: Hyperledger Besu
+---
+
+
+
diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/corda.md b/docs/docs/weaver/getting-started/enabling-weaver-network/corda.md
new file mode 100644
index 0000000000..41caa7afb5
--- /dev/null
+++ b/docs/docs/weaver/getting-started/enabling-weaver-network/corda.md
@@ -0,0 +1,637 @@
+---
+id: corda
+title: Corda
+---
+
+
+
+After testing the Weaver interoperation mechanisms on [basic sample networks](../test-network/overview.md), you may be interested in finding out how you can equip an existing real network, whether in development or in production, to exercise these mechanisms. In this document, we will demonstrate how to equip a Corda network and application with Weaver components and capabilities.
+
+## Model
+
+The figure below illustrates a typical Corda network. The infrastructure consists of a set of nodes (each maintaining its share of the global state in a local vault), notaries, and CAs. On the nodes are installed one or more CorDapps, representing shared business logic across subsets of those nodes. The core of a CorDapp consists of a collection of workflows (or flows) and contracts acting on states; we layer the flows above the contracts in thebelow image just to illustrate that flows represent transaction (state update) triggers, and contract validations occur during the executions of flows. Further up in the stack lie client applications associated with CorDapps that can are used to trigger flows (and by implication, contracts).
+
+![alt text](../../../../images-weaver-docs/enabling-weaver/corda-network-model.png)
+
+Such a network equipped with Weaver components and capabilities will look like the figure below. Legacy components are marked in grey and Weaver and bridging components in green.
+
+![alt text](../../../../images-weaver-docs/enabling-weaver/corda-weaver-model.png)
+
+The relay and driver are the only additional infrastructure that need to be installed. One or more relays can be installed, as can one or more drivers. The drivers are illustrated in the client layer rather than in the bottom layer because, though they are coupled with relays, they trigger flows just like any client application does.
+
+Existing CorDapp flows and contracts deployed on the network's nodes remain undisturbed. All that is required is the deployment of an Interoperation CorDapp (flows and contracts) on every node that needs to offer or consume state from foreign networks.
+
+Client applications will need some additional code and configuration because the decisions to exercise interoperation mechanisms (relay queries for data sharing or atomic asset exchanges) are strictly part of business logic. But Weaver's Corda Interoperation Java-Kotlin SDK offers various helper functions to ease this process and keep the adaptation to a minimum, as we wil see later in this document. Finally, an _identity service_ must be offered by the network to expose its CAs' certificate chains to foreign networks, thereby laying the basis for interoperation. This service simply needs to offer a REST endpoint, and can be implemented as a standalone application or (more conveniently) as an augmentation of one or more of the existing client layer applications.
+
+## Procedural Overview
+
+A Corda network is typically created in phases, in the following sequence:
+
+1. **Development**: This involves writing CorDapp which consists of contracts and workflows, and client layer applications. The cordapp's deployment name/ID and its transaction API must be designed first, but subsequent development of the two layers of applications can then proceed parallelly.
+2. **Pre-Configuration**: This involves creating a desired specification (as a set of configuration diles) of the network topology and the ledgers it maintains.
+3. **Startup and Bootstrap**: This is the launch phase, in which the network components and applications are started and bootstrapped (i.e., configured with initial state and operating rules).
+
+Assuming that the reader is familiar with this procedure, we will walk through the changes required in each phase to make your network ready for interoperation using Weaver components and code templates. This will involve code addition and adaptation, deployment of additional modules, additional configuration, and creation of additional ledger state records. The requirements and effort will vary with the mode of interoperation you wish to support in your Fabric network.
+
+## Development Phase
+
+A Corda distributed application's business logic code spans three layers as illustrated in the network model:
+
+### CorDapp
+
+CorDapps (Corda Distributed Applications) are distributed applications that run on the Corda platform. The goal of a CorDapp is to allow nodes to reach agreement on updates to the ledger. They achieve this goal by defining flows that Corda node owners can invoke over RPC.
+
+#### For Data Sharing
+
+No code changes are required for Weaver enablement, because data sharing involves:
+
+- View packaging (and optionally, encryption) logic and access control logic in a source network, and
+- View validation logic in a destination network
+
+This logic is standard and independent of contract, workflow, and state, particulars. It is already implemented in the Interoperation CorDapp offered by Weaver. Hence you just need to deploy that CorDapp to exercise data sharing from, or to, your application CorDapp. Your application CorDapp can be oblivious of the Interoperation CorDapp's workings and of the view request-response protocol.
+
+#### For Asset Exchange
+
+To exchange an asset using Weaver, the asset's state on the ledger must be controlled in the following ways:
+
+- Locked in favor of a party
+- Claimed by the party to whom the asset is pledged
+- Returned to the original owner if it is not claimed within a given timeframe
+
+In addition, the state of the asset (i.e., whether it is locked), and its current and targeted owners, must be determinable by looking at the ledger records.
+
+The bookkeeping logic required to maintain records of locks can be abstracted away from the particulars of a digital asset and its workflow. But as such assets and their properties (including ownership) can be, and are, encoded in an arbitrary number of ways, we cannot provide a one-size-fits all set of functions (like in the data sharing protocol) to exchange any kind of asset. Instead, we must rely on the application CorDapp managing an asset, as it knows precisely what the asset's properties are and how they can be updated and queried on the ledger.
+
+What Weaver offers, therefore, is the following:
+
+- Lock management logic implemented in the Interoperation CorDapp that treats each asset as an abstract object (an instance of generic corda's `ContractState`) and is agnostic of the assets' internals. It consumes (burns) the asset state and creates a new `HTLC` state that indicates that the asset is locked, while in claim and unlock new asset state is created (minted) with appropriate owner while consuming `HTLC` state. This logic can be exercised in by installing Interoperation CorDapp on the nodes.
+- A set of template functions with sample (and extensible) code that must be added to the application CorDapp to augment the above lock management functions.
+
+Below, we list the template functions with sample code that you, as a developer, must use and adapt within your CorDapp.
+
+- **Flow to get Asset State**: For non-fungible assets, create a flow like:
+ ```kotlin
+ class RetrieveStateAndRef(
+ val type: String,
+ val id: String
+ ): FlowLogic>
+ ```
+ And for fungible assets, create a flow like:
+ ```kotlin
+ class RetrieveStateAndRef(
+ val type: String,
+ val quantity: Long
+ ): FlowLogic>
+ ```
+ The name of these flows can be anything, but the parameters should be same, and return type should `StateAndRef`. These flows are supposed to get the `StateAndRef` object to the asset state that has to be locked, which can be identified by `type` and `id` for non-fungible assets, and `type` and `quantity` for fungible assets.
+
+- **Flow to update owner in asset state**: Create a flow like:
+ ```kotlin
+ class UpdateOwnerFromPointer(
+ val statePointer: StaticPointer
+ ) : FlowLogic()
+ ```
+ Again the name can be anything but the function parameter should be same, i.e. take a `StaticPointer` and return the `ContractState` of the asset involved in asset exchange. This flow is supposed to resolve the `StaticPointer` to actual asset, and update the owner of this asset to the caller of this flow.
+
+#### For Asset Transfer
+
+_TBD_
+
+### Contracts CorDapp
+
+No code changes are required for Weaver enablement. For asset exchange, Weaver assumes that application CorDapp that manages assets must already have a asset creation (mint) contract command and asset deletion (burn) contract command, which can be invoked when `Issuer` party is involved in the transaction.
+
+## Client Layer applications
+
+Weaver provides an SDK to help you adapt your applications to exercise the various interoperability modes. These are called out as **SDK Helpers** in the network model illustrated earlier. Your Corda network's Client layer applications have business logic embedded in them that, broadly speaking, accept data from users and other external agents and invoke workflows from CorDapp over RPC. When you use Weaver for network interoperability, other options can be added, namely requesting and accepting data from foreign networks, and triggering locks and claims for atomic exchanges spanning two networks. Weaver's Corda Interoperation SDK offers a library to exercise these options. But this will involve modification to the application's business logic.
+To use Weaver's Corda SDK, you need to create a [personal access token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` access in GitHub, to access Weaver packages.
+You also need to add the following to your application's `build.gradle` file:
+```groovy
+repositories {
+ maven {
+ url https://maven.pkg.github.com/hyperledger/cacti
+ credentials {
+ username
+ password
+ }
+ }
+}
+dependencies {
+ implementation(group: 'org.hyperledger.cacti.weaver.sdk.corda', name: 'weaver-sdk-corda', version: "2.0.0-alpha.1")
+ implementation(group: 'org.hyperledger.cacti.weaver.imodule.corda', name: 'interop-contracts', version: "2.0.0-alpha.1")
+ implementation(group: 'org.hyperledger.cacti.weaver.imodule.corda', name: 'interop-workflows', version: "2.0.0-alpha.1")
+ implementation(group: 'org.hyperledger.cacti.weaver.protos', name: 'protos-java-kt', version: "2.0.0-alpha.1")
+}
+```
+(Or check out the [package website](https://github.com/hyperledger/cacti/packages/1856827) and select a different version.)
+
+#### For Identity Administration
+
+A Corda network needs to share its security domain (or membership) configuration, i.e., its nodes' CA certificate chains, with a foreign network with which it seeks to interoperate. Though such sharing can be implemented using several different mechanisms, ranging from manual to automated, the simplest and most modular way is to expose a REST endpoint that agents in foreign networks can reach. Further, this REST endpoint can be implemented as a standalone web application or it can be an extension of one or more of the existing client layer applications. (Multiple apps can expose the same endpoint serving the same information for redundancy.) We will demonstrate an example of this while leaving other implementation modes to the user.
+Let's say a Corda network consists of two nodes called `PartyA` and `PartyB`, each running a client layer application with a web server whose URL prefixes are `http://partya.mynetwork.com:9000` and `http://partyb.mynetwork.com:9000` respectively. Each app then can expose a REST endpoint (again, as an example) `http://partya.mynetwork.com:9000/node_sec_grp` and `http://partyb.mynetwork.com:9000/node_sec_grp` respectively.
+At each web server's backend, you need to implement logic to retrieve the node's ID and it's associated certificated chains. Sample code is given below for a Kotlin implementation built on `weaver-sdk-corda`. You can use this code verbatim, except for some minor changes like ``, other parameters like security domain, and list of names of nodes as appropriate for your environment:
+
+```kotlin
+import org.hyperledger.cacti.weaver.sdk.corda.CredentialsCreator
+import com.google.protobuf.util.JsonFormat
+
+
+@RestController
+@CrossOrigin
+@RequestMapping("/") // The paths for HTTP requests are relative to this base path.
+class Controller {
+ // Expose "node_sec_grp" endpoint using Rest Controller
+ @RequestMapping(value = ["/node_sec_grp"], method = arrayOf(RequestMethod.GET), produces = arrayOf("application/json"))
+ private fun GetNetworkConfig(): String {
+ val jsonPrinter = JsonFormat.printer().includingDefaultValueFields()
+
+ val credentialsCreator = CredentialsCreator(
+ "/build/nodes",
+ "mynetwork", // security domain name
+ ["PartyA", "PartyB"], // list of nodes
+ "",
+ ""
+ )
+
+ // Generate Membership
+ val membership = credentialsCreator.createMembership()
+ return jsonPrinter.print(membership)
+ }
+}
+```
+An agent from a foreign network can query either `http://partya.mynetwork.com:9000/sec_group` or `http://partyb.mynetwork.com:9000/sec_group` and obtain the security domain (or membership) configuration of the entire network.
+
+#### For Data Sharing
+
+Consider a scenario inspired by the [global trade use case](../../user-stories/global-trade.md) where a letter of credit (L/C) management business logic is installed in the `trade-finance-network` network, supports a flow named `UploadBillOfLading`, which validates and records a bill of lading (B/L) supplied by a user via a UI. Weaver will enable such a B/L to be fetched from a different network `trade-logistics-network` by querying the function `GetBillOfLading` exposed by the chaincode `shipmentcc` installed in the `tradelogisticschannel` channel (_The trade logistics network can be built on Corda as well. The steps for Weaver-enablement will mostly be the same, with the exception of view address creation logic. Here, for demonstration purposes, we assume that that counter-party network is built on Fabric_).
+
+(In preparation, a suitable access control policy must be recorded on `tradelogisticschannel` in `trade-logistics-network`, and a suitable verification policy must be recorded in the vault of `trade-finance-network`. We will see how to do this in the [Startup and Bootstrap Weaver Components](#startup-and-bootstrap-weaver-components) section later.)
+
+You will need to insert some code in the client layer application that accepts a B/L and submits a `UploadBillOfLading` request in `trade-finance-network`. (No code changes need to be made in any application in the other network.) The logic to accept a B/L should be replaced (or you can simply add an alternative) by a call to the `InteroperableHelper.interopFlow` function offered by the [cacti-weaver-sdk-corda](https://github.com/hyperledger/cacti/packages/1856827) library. The following code sample illustrates this:
+
+```kt
+import org.hyperledger.cacti.weaver.sdk.corda.InteroperableHelper
+import com.mynetwork.flow.UploadBillOfLading
+
+val viewAddress = InteroperableHelper.createFabricViewAddress(
+ 'trade-logistics-network', // Security Domain/Group
+ ], // Replace with remote network's relay
+ 'tradelogisticschannel', // Remote network's channel
+ 'shipmentcc', // Remote network's cc
+ 'GetBillOfLading', // Remote network's cc Fun
+ [ ] // Replace with a value that can be used to look up the right B/L
+)
+try {
+ val response = InteroperableHelper.interopFlow(
+ proxy, // CordaRPCOps instance to start flows
+ viewAddress,
+ [:] // Replace with local network's relay address and port
+ ).fold({
+ println("Error in Interop Flow: ${it.message}")
+ }, {
+ val linearId = it.toString()
+ val BoLString = InteroperableHelper.getExternalStatePayloadString(
+ proxy,
+ linearId
+ )
+ val result = proxy.startFlow(::UploadBillOfLading, BoLString)
+ println("$result")
+ }
+} catch (e: Exception) {
+ println("Error: ${e.toString()}")
+}
+```
+
+Let us understand this code snippet better. The function `UploadBillOfLading` expects one argument, the bill of lading contents. The `InteroperableHelper.createFabricViewAddress` is used to create view address that is to passed to `InteroperableHelper.interopFlow` function. The equivalent function to create a view address for a remote Corda network is `InteroperableHelper.createCordaViewAddress`.
+
+The rest of the code ought to be self-explanatory. Values are hardcoded for explanation purposes.
+
+**Enabling TLS**:
+By default, the TLS is set to false in `interopFlow`, i.e. disabled. But if you want to enable TLS, can pass additional parameters to the `interopFlow` function as follows:
+```kt
+val response = InteroperableHelper.interopFlow(
+ proxy, // CordaRPCOps instance to start flows
+ viewAddress,
+ [:], // Replace with local network's relay address and port
+ 'trade-finance-network', // Local network name (destination)
+ true, // Boolean indication TLS is enabled.
+ // JKS file path containing relay server TLS CA certificates
+ , // password used to create the JKS file
+)
+```
+OR
+```kt
+val response = InteroperableHelper.interopFlow(
+ proxy, // CordaRPCOps instance to start flows
+ viewAddress,
+ [:], // Replace with local network's relay address and port
+ 'trade-finance-network', // Local network name (destination)
+ true, // Boolean indication TLS is enabled.
+ , // colon-separated list of CA certificate file paths
+)
+```
+
+#### For Asset exchange
+
+Let's take an example of asset exchange between `Alice` and `Bob`, where Bob wants to purchase an asset of type `Gold` with id `A123` from `Alice` in `BondNetwork` in exchange for `200` tokens of type `CBDC01` in `TokenNetwork`.
+
+`Alice` needs to select a secret text (say `s`), and hash it (say `H`) using say `SHA512`, which will be used to lock her asset in `BondNetwork`. To lock the non-fungible asset using hash `H` and timeout duration of 10 minutes, you need to add following code snippet in your application:
+```kotlin
+import org.hyperledger.cacti.weaver.sdk.corda.AssetManager
+import org.hyperledger.cacti.weaver.sdk.corda.HashFunctions
+
+var hash: HashFunctions.Hash = HashFunctions.SHA512
+hash.setSerializedHashBase64(H)
+val proxy =
+val issuer =
+val recipient =
+val contractId = AssetManager.createHTLC(
+ proxy,
+ "Gold", // Type
+ "A123", // ID
+ recipient,
+ hash,
+ 10L, // Duration tmeout in secs, L denotes Long
+ 1, // 1 if timeout is Duration, 0 if timeout is in absolute epochs
+ "com.cordaSimpleApplication.flow.RetrieveStateAndRef", // full name of "Flow to get Asset State"
+ AssetContract.Commands.Delete(), // Contract command for Asset to Burn/Delete the state
+ issuer,
+ observers // Optional parameter for list of observers for this transaction
+)
+```
+
+Now `Bob` will lock his tokens in `TokenNetwork`. To lock the fungible asset using same hash `H` and timeout of 5 minutes (half the timeout duration used by Alice in `BondNetwork`), add following code snippet in your application:
+```kotlin
+import org.hyperledger.cacti.weaver.sdk.corda.AssetManager
+import org.hyperledger.cacti.weaver.sdk.corda.HashFunctions
+
+var hash: HashFunctions.Hash = HashFunctions.SHA512
+hash.setSerializedHashBase64(H)
+val proxy =
+val issuer =
+val recipient =
+val contractId = AssetManager.createFungibleHTLC(
+ proxy,
+ "CBDC01", // Type
+ "200", // Quantity
+ recipient,
+ hash,
+ 5L, // Duration timeout in secs, L denotes Long
+ 1, // 1 if timeout is Duration, 0 if timeout is in absolute epochs
+ "com.cordaSimpleApplication.flow.RetrieveStateAndRef", // full name of "Flow to get Asset State"
+ AssetContract.Commands.Delete(), // Contract command for Asset to Burn/Delete the state
+ issuer,
+ observers // Optional parameter for list of observers for this transaction
+)
+```
+
+The above locks will return `contractId`, that has to be stored and will be used in other HTLC functions.
+
+To query whether the assets are locked or not in any network, use following query function:
+```kotlin
+val isLockedBoolean = AssetManager.isAssetLockedInHTLC(
+ rpc.proxy,
+ contractId
+)
+```
+
+Now to claim the asset using the secret text (pre-image of hash) `s`, add following code snippet:
+```kotlin
+var hash: HashFunctions.Hash = HashFunctions.SHA512()
+hash.setPreimage(s)
+val issuer =
+val proxu =
+val res = AssetManager.claimAssetInHTLC(
+ proxy,
+ contractId, // ContractId obtained during lock
+ hash,
+ AssetContract.Commands.Issue(), // Contract command for issuing/minting asset
+ "com.cordaSimpleApplication.flow.UpdateAssetOwnerFromPointer", // full name of flow to update owner in asset state
+ issuer,
+ observers // Optional parameter for list of observers for this transaction
+)
+// return value is boolean indicating success or failure of claim
+```
+The above function can be adapted to both `BondNetwork` and `TokenNetwork`.
+
+If the asset has to be unlocked, use following code snippet:
+```kotlin
+val issuer =
+val proxu =
+val res = AssetManager.reclaimAssetInHTLC(
+ rpc.proxy,
+ contractId, // ContractId obtained during lock
+ AssetContract.Commands.Issue(), // Contract command for issuing/minting asset
+ issuer,
+ observers // Optional parameter for list of observers for this transaction
+)
+// return value is boolean indicating success or failure of claim
+```
+
+#### For Asset Transfer
+
+_TBD_
+
+## Pre-Configuration Phase
+
+No changes are required in your network's pre-configuration process for Weaver enablement.
+
+Typically, pre-configuration involves:
+
+* Generating node folders for each participating node in the network, which contains CorDapps, certificates, persistence db, etc sub directories. Using Gradle task `net.corda.plugins.Cordform` or `net.corda.plugins.Dockerform`, the folders get created under the directory `build/nodes` (this path is used in above sample code for Identity Service).
+
+* The RPC address, username and password specified in above task will be used to create an instance of `CordaRPCOps`, which is the first argument for most `weaver-sdk-corda` static functions as we saw in previous section. For example, one of them is `InteroperableHelper.interopFlow`:
+```kotlin
+val response = InteroperableHelper.interopFlow(
+ proxy, // CordaRPCOps instance to start flows
+ viewAddress,
+ [:], // Replace with local network's relay address and port
+)
+```
+Also, the Corda Driver (which we will setup in the following sections) needs a specific RPC user to be created, so make sure to add that in the Gradle task above, and note the credentials.
+
+* Sample `net.corda.plugins.Dockerform` task:
+```groovy
+task prepareDockerNodes(type: net.corda.plugins.Dockerform, dependsOn: ['jar']) {
+ def HOST_ADDRESS = "0.0.0.0"
+ nodeDefaults {
+ projectCordapp {
+ deploy = false
+ }
+ }
+ node {
+ name "O=Notary,L=London,C=GB"
+ notary = [validating : true]
+ p2pPort 10004
+ rpcSettings {
+ address("$HOST_ADDRESS:10003")
+ adminAddress("$HOST_ADDRESS:10005")
+ }
+ cordapps.clear()
+ }
+ node {
+ name "O=PartyA,L=London,C=GB"
+ p2pPort 10007
+ rpcSettings {
+ address("$HOST_ADDRESS:10003")
+ adminAddress("$HOST_ADDRESS:10005")
+ }
+ rpcUsers = [
+ [ user: "user1", "password": "test", "permissions": ["ALL"]],
+ [ user: "driverUser1", "password": "test", "permissions": ["ALL"]]] // <-- Driver RPC User
+ }
+ node {
+ name "O=PartyB,L=London,C=GB"
+ p2pPort 10009
+ rpcSettings {
+ address("$HOST_ADDRESS:10003")
+ adminAddress("$HOST_ADDRESS:10005")
+ }
+ rpcUsers = [
+ [ user: "user1", "password": "test", "permissions": ["ALL"]],
+ [ user: "driverUser1", "password": "test", "permissions": ["ALL"]]] // <-- Driver RPC User
+ }
+}
+```
+
+## Startup and Bootstrap Phase
+
+To launch a network using containerized components, you will typically use a Docker Compose or Kubernetes configuration file. No modifications are needed to the node's configurations. Sample instructions are given below for networks launched using Docker Compose; we leave it to the reader to adapt these to their custom launch processes.
+
+### For Asset Exchange
+
+The asset exchange mode currently requires only the Interoperation CorDapp module from Weaver. Relays and drivers are not necessary. In the future, we expect to make the asset exchange protocol moe automated using these components; the instructions here will be updated appropriately.
+
+### Install Interoperation CorDapp on Nodes
+
+After bootstrapping the nodes folder, copy the following two CorDapps in `build/nodes/PartyA/cordapps` and `build/nodes/PartyB/cordapps` folders (`PartyA` and `PartyB` node names are for example only):
+
+- [org.hyperledger.cacti.weaver.imodule.corda.interop-contracts](https://github.com/hyperledger/cacti/packages/1856825)
+- [org.hyperledger.cacti.weaver.imodule.corda.interop-workflows](https://github.com/hyperledger/cacti/packages/1856826)
+
+| Notes |
+|:------|
+| You can follow any installation process for this CorDapp, but make sure it is installed on all the nodes that maintain the states involved in cross-network operations in their vaults. |
+
+### For Data Sharing or Asset Transfer
+
+Both the data sharing and asset transfer modes require the Interoperation CorDapp, relays, and drivers, to be deployed.
+
+#### Install Interoperation CorDapp on Nodes
+
+After bootstrapping the nodes folder, copy the following two CorDapps in `build/nodes/PartyA/cordapps` and `build/nodes/PartyB/cordapps` folders (`PartyA` and `PartyB` node names are for example only):
+
+- [org.hyperledger.cacti.weaver.imodule.corda.interop-contracts](https://github.com/hyperledger/cacti/packages/1856825)
+- [org.hyperledger.cacti.weaver.imodule.corda.interop-workflows](https://github.com/hyperledger/cacti/packages/1856826)
+
+| Notes |
+|:------|
+| You can follow any installation process for this CorDapp, but make sure it is installed on all the nodes that maintain the states involved in cross-network operations in their vaults. |
+
+#### Launch Relay
+
+You need to run one or more relays for network-to-network communication. Here we provide instructions to run one relay running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple relays, which will be useful from a failover perspective.)
+
+Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-relay-server) for the relay. Before launching a container, you just need to customize its configuration for your Fabric network, which you can do by simply creating a folder (let's call it `relay_config`) and configuring the following files in it:
+
+- `.env`: This sets suitable environment variables within the relay container. Copy the `.env.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/.env.template) and customize it for your purposes, as indicated in the below sample:
+ ```
+ PATH_TO_CONFIG=./config.toml
+ RELAY_NAME=<"name" in config.toml>
+ RELAY_PORT=
+ EXTERNAL_NETWORK=
+ DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-relay-server
+ DOCKER_TAG=2.0.0-alpha.1
+ ```
+ - The `PATH_TO_CONFIG` variable should point to the properties file typically named `config.toml` (you can name this whatever you wish). See further below for instructions to write this file.
+ - The `RELAY_NAME` variable specifies a unique name for this relay. It should match what's specified in the `config.toml` (more on that below).
+ - The `RELAY_PORT` variable specifies the port this relay server will listen on. It should match what's specified in the `config.toml` (more on that below).
+ - The `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Fabric network.
+ - The `DOCKER_*` variables are used to specify the image on which the container will be built. Make sure you set `DOCKER_TAG` to the latest version you see on [GitHub](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-relay-server).
+
+ For more details, see the [Relay Docker README](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/relay-docker.md) ("Relay Server Image" and "Running With Docker Compose" sections).
+
+- `config.toml`: This is the file specified in the `PATH_TO_CONFIG` variable in the `.env`. It specifies properties of this relay and the driver(s) it supports. A sample is given below:
+ ```toml
+ name=
+ port=
+ host="0.0.0.0"
+ db_path="db//requests"
+ remote_db_path="db//remote_request"
+
+ # FOR TLS
+ cert_path="credentials/fabric_cert.pem"
+ key_path="credentials/fabric_key"
+ tls=
+
+ [networks]
+ [networks.]
+ network=""
+
+ [relays]
+ [relays.]
+ hostname=""
+ port=""
+
+ [drivers]
+ [drivers.]
+ hostname=""
+ port=""
+ ```
+ - `` should be a unique ID representing this relay; e.g., `my_network_relay`. It should match the `RELAY_NAME` value in `.env`.
+ - `` is the port number the relay server will listen on. It should match the `RELAY_PORT` value in `.env`.
+ - `db_path` and `remote_db_path` are used internally by the relay to store data. Replace `` with the same value set for the `name` parameter. (These can point to any filesystem paths in the relay's container.)
+ - If you set `tls` to `true`, the relay will enforce TLS communication. The `cert_path` and `key_path` should point to a Fabric TLS certificate and key respectively, such as those created using the `cryptogen` tool.
+ - `` is a unique identifier for your local network. You can set it to whatever value you wish.
+ - `` refers to the driver used by this relay to respond to requests. This also refers to one of the drivers's specifications in the `drivers` section further below. In this code snippet, we have defined one driver. (The names in lines 14 and 22 must match.) In lines 23 and 24 respectively, you should specify the hostname and port for the driver (whose configuration we will handle later).
+ - The `relays` section specifies all foreign relays this relay can connect to. The `` value should be a unique ID for a given foreign relay, and this value will be used by your Layer-2 applications when constructing view addresses for data sharing requests. In lines 18 and 19, you should specify the hostname and port for the foreign relay.
+ - **Enabling TLS**:
+ - You can make your relay accept TLS connections by specifying a TLS certificate file path and private key file path in `cert_path` and `key_path` respectively, and set `tls` to `true`.
+ - To communicate with a foreign relay using TLS, specify that relay's TLS CA certificate path in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that relay's section as follows (*Note*: this CA certificate should match the one specified in the `cert_path` property in the foreign relay's `config.toml` file):
+ ```toml
+ [relays]
+ [relays.]
+ hostname=""
+ port=""
+ tls=
+ tlsca_cert_path=""
+ ```
+ - To communicate with a driver using TLS, specify the driver's TLS CA certificate in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that driver's section as follows (*Note*: this CA certificate must match the certificate used by the driver using the `DRIVER_TLS_CERT_PATH` property in its `.env` configuration file, which we will examine later):
+ ```toml
+ [drivers]
+ [drivers.]
+ hostname=""
+ port=""
+ tls=
+ tlsca_cert_path=""
+ ```
+
+ | Notes |
+ |:------|
+ | You can specify more than one foreign relay instance in the `relays` section. |
+ | You can specify more than one driver instance in the `drivers` section. |
+
+- `docker-compose.yaml`: This specifies the properties of the relay container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/docker-compose.yaml) verbatim.
+
+To start the relay server, navigate to the folder containing the above files and run the following:
+```bash
+docker-compose up -d relay-server
+```
+
+#### Launch Driver
+
+You need to run one or more drivers through which your relay can interact with your Corda network. Here we provide instructions to run one Corda driver running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple drivers, which will be useful both from a failover perspective and to interact with different subsets of your Corda network.)
+
+Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-driver-corda) for the Corda driver. Before launching a container, you just need to customize the container configuration for your Corda network, which you can do by simply configuring the following:
+
+- `.env`: This sets suitable environment variables within the driver container. Copy the `.env.docker.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/corda-driver/.env.docker.template) and customize it for your purposes, as indicated in the below sample:
+ ```
+ NETWORK_NAME=
+ DRIVER_PORT=
+ DRIVER_RPC_USERNAME=
+ DRIVER_RPC_PASSWORD=
+ EXTERNAL_NETWORK=
+ DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-driver-corda
+ DOCKER_TAG=2.0.0-alpha.1
+ RELAY_TLS=
+ RELAY_TLSCA_TRUST_STORE=
+ RELAY_TLSCA_TRUST_STORE_PASSWORD=
+ RELAY_TLSCA_CERT_PATHS=
+ DRIVER_TLS=
+ DRIVER_TLS_CERT_PATH=
+ DRIVER_TLS_KEY_PATH=
+ ```
+ - `NETWORK_NAME` is only used as suffix for container and has no other significance.
+ - `DRIVER_PORT` variable should be set to the port this driver will listen on.
+ - `DRIVER_RPC_USERNAME` variable should be set to rpc user created [above](#pre-configuration) for the driver.
+ - `DRIVER_RPC_PASSWORD` variable should be set to password of above rpc user.
+ - `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Corda network.
+ - **Enabling TLS**:
+ - You can make your driver accept TLS connections by specifying `DRIVER_TLS` as `true` and specifying a TLS certificate file path and private key file path in `DRIVER_TLS_CERT_PATH` and `DRIVER_TLS_KEY_PATH` respectively. The same certificate should be specified in this driver's definition in the `drivers` section in the `config.toml` file of your relay in the `tlsca_cert_path` property (see the earlier section on relay configuration).
+ - To communicate with your network' relay using TLS (i.e., if the relay is TLS-enabled), specify that relay's TLS CA certificate path in `RELAY_TLSCA_CERT_PATH` (currently only one certificate can be configured) and set `RELAY_TLS` to `true`. This CA certificate should match the one specified in the `cert_path` property in the relay's `config.toml` file (see the earlier section on relay configuration):
+ - You can point to the folder in your host system containing the certificate and key using the `TLS_CREDENTIALS_DIR` variable. (This folder will be synced to the `/corda-driver/credentials` folder in the Fabric Driver container as specified in the [docker-compose file](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/docker-compose.yml).) Make sure you point to the right certificate and key file paths within the container using the `DRIVER_TLS_CERT_PATH`, `DRIVER_TLS_KEY_PATH`, and `RELAY_TLSCA_CERT_PATH` variables.
+
+- `docker-compose.yaml`: This specifies the properties of the driver container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/corda-driver/docker-compose.yml) verbatim.
+
+To start the driver, navigate to the folder containing the above files and run the following:
+```bash
+docker-compose up -d
+```
+
+#### Vault Initialization
+
+To prepare your network for interoperation with a foreign network, you need to record the following to your vault using the [Corda SDK](https://github.com/hyperledger/cacti/packages/1856827) (`org.hyperledger.cacti.weaver.sdk.corda.weaver-sdk-corda`):
+
+- **Access control policies**:
+ Let's take the example of the request made from `trade-finance-network` to `trade-logistics-network` for a B/L earlier in this document. `trade-logistics-network` can have a policy of the following form permitting access to the `GetBillOfLading` function from a client representing the `PartyA` node in `trade-finance-network` as follows:
+ ```json
+ {
+ "securityDomain":"trade-finance-network",
+ "rules":
+ [
+ {
+ "principal":"",
+ "principalType":"certificate",
+ "resource":"exporternode:10003;carriernode:10003#com.mynetwork.flow.GetBillOfLading:*",
+ "read":true
+ }
+ ]
+ }
+ ```
+ In this sample, a single rule is specified for requests coming from `trade-finance-network`: it states that a workflow call to `com.mynetwork.flow.GetBillOfLading` made to `exporter` and `carrier` nodes of remote Corda network is permitted for a requestor whose certificate is specified in the `principal` attribute. The `*` at the end indicates that any arguments passed to the function will pass the access control check. The `exporternode:10003` and `carriernode:10003` are of form `:`, for `exporter` and `carrier` nodes respectively in the remote Corda network.
+
+ You need to record this policy rule on your Corda network's vault by invoking either the `AccessControlPolicyManager.createAccessControlPolicyState` function or the `AccessControlPolicyManager.updateAccessControlPolicyState` function on the `weaver-sdk-corda`; use the former if you are recording a set of rules for the given `securityDomain` for the first time and the latter to overwrite a set of rules recorded earlier. The above JSON needs to be converted to protobuf object of `org.hyperledger.cacti.weaver.protos.common.access_control.AccessControl.AccessControlPolicy`, using google's protobuf library, and the object is the second argument of above functions (first being the instance of CordaRPCOps).
+
+- **Verification policies**:
+ Taking the same example as above, an example of a verification policy for a B/L requested by the `trade-finance-network` from the `trade-logistics-network` is as follows:
+ ```json
+ {
+ "securityDomain":"trade-logistics-network",
+ "identifiers":
+ [
+ {
+ "pattern":"tradelogisticschannel:shipmentcc:GetBillOfLading:*",
+ "policy":
+ {
+ "type":"Signature",
+ "criteria":
+ [
+ "ExporterMSP",
+ "CarrierMSP"
+ ]
+ }
+ }
+ ]
+ }
+ ```
+ In this sample, a single verification policy rule is specified for data views coming from `trade-logistics-network`: it states that the data returned by the `GetBillOfLading` query made to the `shipmentcc` chaincode on the `tradelogisticschannel` channel requires as proof two signatures, one from a peer in the organization whose MSP ID is `ExporterMSP` and another from a peer in the organization whose MSP ID is `CarrierMSP`.
+
+ | Notes |
+ |:------|
+ | If the remote network is built on Corda, the resource specified in the access control policy can be used here as the `pattern`, with different node names specified in the `criteria`. |
+
+ You need to record this policy rule on your Corda network's vault by invoking Corda sdk's function `VerificationPolicyManager.createVerificationPolicyState(proxy, verificationPolicyProto)`, where `proxy` is an instance of `CordaRPCOps` as described in previous sections, and `verificationPolicyProto` is an object of protobuf `org.hyperledger.cacti.weaver.protos.common.verification_policy.VerificationPolicyOuterClass.VerificationPolicy`. You can examine the full proto structure [here](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos/common/verification_policy.proto). (_Google's protobuf library can be used to convert above JSON to protobuf object._)
+
+ | Notes |
+ |:------|
+ | For any cross-network data request, make sure an access control policy is recorded in the _source network_ (`trade-logistics-network` in the above example) and a corresponding verification policy is recorded in the _destination network_ (`trade-finance-network` in the above example) before any relay request is triggered. |
+
+- **Foreign network security domain (membership) configuration**:
+ Run the following procedure (pseudocode) to record security domain configuration for every foreign network you wish your Corda network to interoperate with (you will need to collect the identity service URLs for all the foreign networks first):
+ ```
+ for each foreign network:
+ send an HTTP GET request to the network's identity service (using 'curl' or 'wget' from a shell script or equivalent programming language APIs).
+ convert the response string to protobuf object of 'org.hyperledger.cacti.weaver.protos.common.membership.MembershipOuterClass.Membership'.
+ invoke 'MembershipManager.createMembershipState(proxy, membershipProto)' or 'MembershipManager.updateMembershipState(proxy, membershipProto)' on Corda sdk.
+ ```
+ As in the above two cases, use `createMembershipState` to record a confiuration for the first time for a given `securityDomain` and `updateMembershipState` to overwrite a configuration.
+
+ | Notes |
+ |:------|
+ | Security domain configurations (organization lists and their certificate chains) for any Fabric/Corda network are subject to change, so you should run the above procedure periodically in a loop. |
+
+Your Corda network is now up and running with the necessary Weaver components, and your network's vault is bootstrapped with the initial configuration necessary for cross-network interactions!
diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/fabric.md b/docs/docs/weaver/getting-started/enabling-weaver-network/fabric.md
new file mode 100644
index 0000000000..81c0543f4b
--- /dev/null
+++ b/docs/docs/weaver/getting-started/enabling-weaver-network/fabric.md
@@ -0,0 +1,865 @@
+---
+id: fabric
+title: Hyperledger Fabric
+---
+
+
+
+After testing the Weaver interoperation mechanisms on [basic sample networks](../test-network/overview.md), you may be interested in finding out how you can equip an existing real network, whether in development or in production, to exercise these mechanisms. In this document, we will demonstrate how to equip a Fabric network and application with Weaver components and capabilities.
+
+## Model
+
+The figure below illustrates a typical Fabric network. The infrastructure consists of a set of peers, ordering service nodes, and CAs that perform the roles of MSPs; each serves a given _organization_ which is one of the constituent units of the network. On the peers are installed one or more smart contracts (_chaincode_), representing shared business logic across the different organizations. Further up lie the so-called Layer-2 (or client) applications that consist of organization-specific business logic and invoke the smart contracts using APIs exposed by the Fabric SDK and with wallet credentials issued by their respective organizations' CAs.
+
+![alt text](../../../../images-weaver-docs/enabling-weaver/fabric-network-model.png)
+
+Such a network equipped with Weaver components and capabilities will look like the figure below. Legacy components are marked in grey and Weaver and bridging components in green.
+
+![alt text](../../../../images-weaver-docs/enabling-weaver/fabric-weaver-model.png)
+
+The relay and driver are the only additional infrastructure that need to be installed. One or more relays can be installed, as can one or more drivers. The drivers are illustrated in Layer-2 rather than in the bottom layer because, though they are coupled with relays, they exercise contracts using the Fabric SDK and organization-issued credentials just like any Layer-2 application does.
+
+Existing chaincode deployed on the network's channels remain undisturbed. All that is required in the smart contracts layer is the deployment of the Fabric Interoperation Chaincode on every channel that needs to offer or consume state from foreign networks.
+
+Layer-2, or client, applications will need some additional code and configuration because the decisions to exercise interoperation mechanisms (relay queries for data sharing or atomic asset exchanges) are strictly part of business logic. But Weaver's Fabric Interoperation Node SDK offers various helper functions to ease this process and keep the adaptation to a minimum, as we wil see later in this document. Finally, an _identity service_ must be offered by the network to expose its CAs' certificate chains to foreign networks, thereby laying the basis for interoperation. This service simply needs to offer a REST endpoint, and can be implemented as a standalone application or (more conveniently) as an augmentation of one or more of the existing Layer-2 applications.
+
+## Procedural Overview
+
+A Hyperledger Fabric network is typically created in phases, in the following sequence:
+
+1. **Development**: This involves writing chaincode and Layer-2 applications. The chaincode's deployment name/ID and its transaction API must be designed first, but subsequent development of the two layers of applications can then proceed parallelly.
+2. **Pre-Configuration**: This involves creating a desired specification (as a set of configuration diles) of the network topology and the ledgers it maintains.
+3. **Startup and Bootstrap**: This is the launch phase, in which the network components and applications are started and bootstrapped (i.e., configured with initial state and operating rules).
+
+Assuming that the reader is familiar with this procedure, we will walk through the changes required in each phase to make your network ready for interoperation using Weaver components and code templates. This will involve code addition and adaptation, deployment of additional modules, additional configuration, and creation of additional ledger state records. The requirements and effort will vary with the mode of interoperation you wish to support in your Fabric network.
+
+## Development Phase
+
+A Fabric distributed application's business logic code spans two layers as illustrated in the network model.
+
+### Chaincode
+
+These are smart contracts embodied in code, managing business workflow state and digital assets.
+
+#### For Data Sharing
+
+No code changes are required for Weaver enablement, because data sharing involves:
+
+- View packaging (and optionally, encryption) logic and access control logic in a source network, and
+- View validation logic in a destination network
+
+This logic is standard and independent of smart contract, asset, and state, particulars. It is already implemented in the Fabric Interoperation Chaincode offered by Weaver. Hence you just need to deploy that chaincode to exercise data sharing from, or to, your application chaincode. Your application chaincode can be oblivious of the Fabric Interoperation Chaincode's workings and of the view request-response protocol.
+
+#### For Asset Exchange
+
+To exchange an asset using Weaver, the asset's state on the ledger must be controlled in the following ways:
+
+- Locked in favor of a party
+- Claimed by the party to whom the asset is pledged
+- Returned to the original owner if it is not claimed within a given timeframe
+
+In addition, the state of the asset (i.e., whether it is locked), and its current and targeted owners, must be determinable by looking at the ledger records.
+
+The bookkeeping logic required to maintain records of locks can be abstracted away from the particulars of a digital asset and its workflow. But as such assets and their properties (including ownership) can be, and are, encoded in an arbitrary number of ways, we cannot provide a one-size-fits all set of functions (like in the data sharing protocol) to exchange any kind of asset. Instead, we must rely on the application contract (chaincode) managing an asset, as it knows precisely what the asset's properties are and how they can be updated and queried on the ledger (channel).
+
+What Weaver offers, therefore, is the following:
+
+- Lock management (bookkeeping) logic implemented in the Fabric Interoperation Chaincode that treats each asset as an abstract object and is agnostic of the assets' internals. This logic can be exercised in one of two ways:
+ - Importing the [`assetexchange`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2) library from the Fabric Interoperation Chaincode into your application chaincode, or
+ - Invoking them within the Fabric Interoperation Chaincode using a [chaincode-to-chaincode call](https://pkg.go.dev/github.com/hyperledger/fabric-chaincode-go/shim#ChaincodeStub.InvokeChaincode).
+- A set of template functions with sample (and extensible) code that must be added to the application chaincode to exercise the above lock management functions.
+
+Below, we list the template functions with sample code that you, as a developer, must use and adapt within your chaincode, in either mode (library import or chaincode invocations).
+
+| Notes |
+|:------|
+| The instructions here apply only to chaincode implemented in Go, because Weaver presently offers only a Go version of the Fabric Interoperation Chaincode. |
+
+- _Using the [`assetexchange`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2) Library_: This method doesn't require the [`Fabric Interoperation Chaincode`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop/v2) to be installed. In your smart contract's `go.mod`, add the following in the `require` section (the sample below uses the current versions for dependency packages; update them to the latest versions offered by Cacti):
+ ```go
+ require(
+ ...
+ github.com/hyperledger/cacti/weaver/common/protos-go/v2 v2.0.0-alpha.1
+ github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2 v2.0.0-alpha.1
+ ...
+ )
+ ```
+ The following functions need to be added to your chaincode, and the smart contract class/type used below is called `SmartContract` (_Note_: the function signature, i.e. the name, arguments, and return values, need to be exactly what is given in the below samples; you can have additional code to manage asset state as per need):
+ 1. **LockAsset**
+ ```go
+ import (
+ ...
+ "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2"
+ )
+ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, assetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) {
+ // Add some safety checks before calling LockAsset from library
+ // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked.
+ contractId, err := assetexchange.LockAsset(ctx, "", assetExchangeAgreementSerializedProto64, lockInfoSerializedProto64)
+ if err != nil {
+ return "", logThenErrorf(err.Error())
+ }
+ // Post proccessing of asset after LockAsset called like change status of the asset so that it can't be spent.
+ ...
+ return contractId, nil
+ }
+ ```
+ Here `assetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetExchangeAgreement` protobuf structure, and can be used to extract details like asset id, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements).
+ Similarly `lockInfoSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetLock` protobuf structure. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-locks-on-assets).
+ 2. **LockFungibleAsset**
+ ```go
+ func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInterface, fungibleAssetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) {
+ // Add some safety checks before calling LockFungibleAsset from library
+ // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked.
+ contractId, err := assetexchange.LockFungibleAsset(ctx, "", fungibleAssetExchangeAgreementSerializedProto64, lockInfoSerializedProto64)
+ if err != nil {
+ return "", logThenErrorf(err.Error())
+ }
+ // Post proccessing of asset after LockFungibleAsset called like reduce the amount of tokens owned by the locker, or mark it locked so that it can't be spent.
+ ...
+ return contractId, nil
+ }
+ ```
+ Here `fungibleAssetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `FungibleAssetExchangeAgreement` protobuf structure, and can be used to extract details like asset quantity, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements).
+ 3. **IsAssetLockedQueryUsingContractId**
+ ```go
+ func (s *SmartContract) IsAssetLockedQueryUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) {
+ return assetexchange.IsAssetLockedQueryUsingContractId(ctx, contractId)
+ }
+ ```
+ 4. **ClaimAssetUsingContractId**
+ ```go
+ func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId, claimInfoSerializedProto64 string) (bool, error) {
+ // Note recipient will be the caller for this function
+ claimed := false
+ err := assetexchange.ClaimAssetUsingContractId(ctx, contractId, claimInfoSerializedProto64)
+ if err != nil {
+ return false, logThenErrorf(err.Error())
+ }
+ claimed = true
+ // After the above function call, update the owner of the asset with recipeint/caller
+ ...
+ return claimed, nil
+ }
+ ```
+ 5. **UnlockAssetUsingContractId**
+ ```go
+ func (s *SmartContract) UnlockAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) {
+ unlocked := false
+ err := assetexchange.UnlockAssetUsingContractId(ctx, contractId)
+ if err != nil {
+ return false, logThenErrorf(err.Error())
+ }
+ unlocked = true
+ ...
+ return true, nil
+ }
+ ```
+
+ In addition, you should add the following extra utility functions to enable client applications to query and discover asset state:
+ ```go
+ func (s *SmartContract) GetHTLCHashByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) {
+ return assetexchange.GetHTLCHashByContractId(ctx, contractId)
+ }
+ func (s *SmartContract) GetHTLCHashPreImageByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) {
+ return assetexchange.GetHTLCHashPreImageByContractId(ctx, contractId)
+ }
+ ```
+
+ There is an alternative API to implement asset exchange using this library, which doesn't involve contract IDs. For details, see the [Asset Exchange Library README](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/fabric-interop-cc/libs/assetexchange/README.md#without-contractid).
+
+- _Using the [`Fabric Interoperation Chaincode`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop/v2)_: This method requires the Fabric Interoperation Chaincode to be installed on all peers of the channel, using a special chaincode ID (e.g., `interop`, which is what we will use later in this document). Your application chaincode needs to implement the interface `github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2`.
+ In your smart contract's `go.mod`, add the following in the `require` section (update the version to the latest Cacti version):
+ ```go
+ require(
+ ...
+ github.com/hyperledger/cacti/weaver/common/protos-go/v2 v2.0.0-alpha.1
+ github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2 v2.0.0-alpha.1
+ ...
+ )
+ ```
+ In the SmartContract class definition file, add the following code:
+ ```go
+ import (
+ ...
+ am "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2"
+ )
+ type SmartContract struct {
+ contractapi.Contract
+ amc am.AssetManagementContract
+ }
+ ```
+ The following functions need to be added to your chaincode (_Note_: the function signature, i.e. the name, arguments, and return values, need to be exactly what is given in the below samples; you can have additional code to manage asset state as per need):
+ 1. **LockAsset**
+ ```go
+ func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, assetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) {
+ // Add some safety checks before calling LockAsset from library
+ // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked.
+ contractId, err := s.amc.LockAsset(ctx, "", assetExchangeAgreementSerializedProto64, lockInfoSerializedProto64)
+ if err != nil {
+ return "", logThenErrorf(err.Error())
+ }
+ // Post proccessing of asset after LockAsset called like change status of the asset so that it can't be spent.
+ ...
+ return contractId, nil
+ }
+ ```
+ Here `assetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetExchangeAgreement` protobuf structure, and can be used to extract details like asset id, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements).
+ Similarly `lockInfoSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetLock` protobuf structure. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-locks-on-assets).
+ 2. **LockFungibleAsset**
+ ```go
+ func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInterface, fungibleAssetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) {
+ // Add some safety checks before calling LockFungibleAsset from library
+ // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked.
+ contractId, err := s.amc.LockFungibleAsset(ctx, "", fungibleAssetExchangeAgreementSerializedProto64, lockInfoSerializedProto64)
+ if err != nil {
+ return "", logThenErrorf(err.Error())
+ }
+ // Post proccessing of asset after LockFungibleAsset called like reduce the amount of tokens owned by the locker, or mark it locked so that it can't be spent.
+ ...
+ return contractId, nil
+ }
+ ```
+ Here `fungibleAssetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `FungibleAssetExchangeAgreement` protobuf structure, and can be used to extract details like asset quantity, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements).
+ 3. **IsAssetLockedQueryUsingContractId**
+ ```go
+ func (s *SmartContract) IsAssetLockedQueryUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) {
+ return s.amc.IsAssetLockedQueryUsingContractId(ctx, contractId)
+ }
+ ```
+ 4. **ClaimAssetUsingContractId**
+ ```go
+ func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId, claimInfoSerializedProto64 string) (bool, error) {
+ // Note recipient will be the caller for this function
+ claimed := false
+ err := s.amc.ClaimAssetUsingContractId(ctx, contractId, claimInfoSerializedProto64)
+ if err != nil {
+ return false, logThenErrorf(err.Error())
+ }
+ claimed = true
+ // After the above function call, update the owner of the asset with recipeint/caller
+ ...
+ return claimed, nil
+ }
+ ```
+ 5. **UnlockAssetUsingContractId**
+ ```go
+ func (s *SmartContract) UnlockAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) {
+ unlocked := false
+ err := s.amc.UnlockAssetUsingContractId(ctx, contractId)
+ if err != nil {
+ return false, logThenErrorf(err.Error())
+ }
+ unlocked = true
+ ...
+ return true, nil
+ }
+ ```
+ In addition, you should add the following extra utility functions to enable client applications to query and discover asset state:
+ ```go
+ func (s *SmartContract) GetHTLCHashByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) {
+ return s.amc.GetHTLCHashByContractId(ctx, contractId)
+ }
+ func (s *SmartContract) GetHTLCHashPreImageByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) {
+ return s.amc.GetHTLCHashPreImageByContractId(ctx, contractId)
+ }
+ ```
+
+#### For Asset Transfer
+
+_TBD_
+
+### Client (or Layer-2) Applications
+
+Weaver provides an SDK to help you adapt your applications to exercise the various interoperability modes. These are called out as **Interoperation Helpers** in the network model illustrated earlier. Your Fabric network's Layer-2 applications have business logic embedded in them that, broadly speaking, accept data from users and other external agents and invoke smart contracts using library functions and APIs offered by the Fabric SDK. When you use Weaver for network interoperability, other options can be added, namely requesting and accepting data from foreign networks, and triggering locks and claims for atomic exchanges spanning two networks. Weaver's Fabric Interoperation SDK (currently implemented both in Node.js and Golang) offers a library to exercise these options, supplementing the Fabric SDK. But this will involve modification to the application's business logic.
+
+| Notes |
+|:------|
+| The instructions here apply to applications implemented in Node.js (JavaScript and TypeScript), using the Weaver Node SDK for Fabric. We will add instructions later for Go applications using the Weaver Go SDK for Fabric. |
+
+To import and use the Weaver SDK, you need to add the following dependency to the `dependencies` section of your Node.js application's `package.json` file:
+```json
+"@hyperledger/cacti-weaver-sdk-fabric": "latest",
+```
+(Instead of `latest`, you can select a particular version from the [package website](https://github.com/hyperledger/cacti/pkgs/npm/cacti-weaver-sdk-fabric).)
+
+Before you run `npm install` to fetch the dependencies, make sure you create a [personal access token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` access in GitHub. Create an `.npmrc` file in the same folder as the `package.json` with the following contents:
+
+```
+@hyperledger:registry=https://npm.pkg.github.com/hyperledger
+//npm.pkg.github.com/:_authToken=
+```
+Replace `` in this file with the token you created in GitHub.
+
+First, you must incorporate some code for Weaver's network administration, specifically identity management. Then, using the given sample code and examples, you can adapt your applications for each interoperability mode.
+
+#### For Identity Administration
+
+A Fabric network channel must share its security domain (or membership) configuration, i.e., its organizations' CA certificate chains, with a foreign network with which it seeks to interoperate. Each organization must run an IIN Agent for this purpose. The set of IIN Agents, a.k.a. the _local membership_ must be recorded in the ledger before those agents can be operational. In your Fabric network application suite, one or more applications will exist for network administration; the following code snippet should be added in at least one of those applications to record local membership as a prerequisite for interoperability:
+ ```typescript
+ import { MembershipManager } from '@hyperledger/cacti-weaver-sdk-fabric'
+
+ const gateway =
+
+ try {
+ const response = await MembershipManager.createLocalMembership(
+ gateway,
+ members, // list of all organization MSPIDs that are part of the channel
+ securityDomain, // name of the local network's security domain
+ channelName, // Channel Name
+ contractName // Fabric Interoperation Chaincode installation ID on the channel
+ )
+ } catch (e) {
+ // On error try updating local membership
+ const response = await MembershipManager.updateLocalMembership(gateway, members, securityDomain, channelName, contractName)
+ }
+ ```
+
+ - `` should be replaced with standard (boilerplate) code to get a handle to your network's gateway. This requires a special wallet identity, namely one with a `network-admin` attribute indicating that the caller is a trusted network administrator who is authorized to record local memberships on the `channelName` channel.
+ - `members` must consist of the list of organizational MSP IDs for the `channelName` channel.
+
+#### For Data Sharing
+
+Consider a scenario inspired by the [global trade use case](../../user-stories/global-trade.md) where a letter of credit (L/C) management business logic (chaincode `letterofcreditcc`) installed in the `tradefinancechannel` channel in the `trade-finance-network` network supports a transaction `RecordBillOfLading`, which validates and records a bill of lading (B/L) supplied by a user via a UI. Weaver will enable such a B/L to be fetched from a different network `trade-logistics-network` by querying the function `GetBillOfLading` exposed by the chaincode `shipmentcc` installed in the `tradelogisticschannel` channel.
+
+(In preparation, a suitable access control policy must be recorded on `tradelogisticschannel` in `trade-logistics-network`, and a suitable verification policy must be recorded on `tradefinancechannel` in `trade-finance-network`. We will see how to do this in the "Startup and Boostrap" section later.)
+
+You will need to insert some code in the Layer-2 application that accepts a B/L and submits a `RecordBillOfLading` transaction in `trade-finance-network`. (No code changes need to be made in any application in the other network.) The logic to accept a B/L should be replaced (or you can simply add an alternative) by a call to the `interopFlow` function offered by the [cacti-weaver-sdk-fabric](https://github.com/hyperledger/cacti/pkgs/npm/cacti-weaver-sdk-fabric) library (there's an [equivalent library in Golang](https://github.com/hyperledger/cacti/releases/tag/weaver%2Fsdks%2Ffabric%2Fgo-sdk%2Fv2.0.0-alpha.1) too). The following code sample illustrates this (the Golang equivalent is left to the reader):
+```js
+const ihelper = require('@hyperledger/cacti-weaver-sdk-fabric').InteroperableHelper;
+const interopcc = ; // Use Fabric SDK functions: (new Gateway()).getNetwork(...).getContract()
+const keyCert = await ihelper.getKeyAndCertForRemoteRequestbyUserName(, ); // Read key and certificate for from wallet (get handle using Fabric SDK Wallets API)
+// Collect view addresses for relay requests in the context of an interop flow
+interopJSONs.push({
+ NetworkID: 'trade-logistics-network',
+ RemoteEndpoint: ], // Replace with remote network's relay address and port
+ ChannelID: 'tradelogisticschannel',
+ ChaincodeID: 'shipmentcc',
+ ChaincodeFunc: 'GetBillOfLading',
+ ccArgs: [ ], // Replace with a value that can be used to look up the right B/L
+ Sign: true
+});
+const indices = [ 1 ];
+// Trigger an end-to-end interoperation (data sharing) protocol
+// Send a request to a foreign network via your relay, receive the response and submit a transaction to a local chaincode
+const flowResponse = await ihelper.interopFlow(
+ interopcc,
+ 'trade-finance-network',
+ {
+ channel: 'tradefinancechannel',
+ contractName: 'letterofcreditcc',
+ ccFunc: 'RecordBillOfLading',
+ ccArgs: [ , '' ]
+ },
+ , // Replace with this Layer-2 application's organization's MSP ID
+ [:], // Replace with local network's relay address and port
+ indices,
+ interopJSONs,
+ keyCert,
+ , // List of orgs to submit transaction to local i.e. trade logistics network
+ false, // Boolean flag to indicate whether return without submit transaction to local i.e. trade logistics network
+ false, // Boolean flag indicating no TLS communication with relay
+ [], // Keep it empty when TLS is disabled
+ , // Boolean flag to indicate whether to use to end-to-end encryption
+);
+// List of errors to check for
+if (!flowResponse.views || flowResponse.views.length === 0 || !flowResponse.result || flowResponse.views.length !== argIndices.length) {
+ throw ;
+}
+```
+Let us understand this code snippet better. The structure in lines 20-25 specifies the local chaincode transaction that is to be triggered after remote data (view) has been requested and obtained via relays. The function `RecordBillOfLading` expects two arguments as specified in line 24: the first is the common shipment reference that is used by the letter of credit in `trade-finance-network` and the bill of lading in `trade-logistics-network`, and the second is the bill of lading contents. When the `interopFlow` function is called, this argument is left blank because it is supposed to be filled with contents obtained from a view request. The array list `indices`, which is passed as an argument to `interopFlow` therefore contains the index value `1` (line 14), indicating which argument ought to be substituted with view data. The `interopJSONs` array correspondingly contains a list of view addresses that are to be supplied to the relay. The `` if set to `true` will enable end-to-end confidentiality, i.e. payload will be encrypted from `trade-finance-network`'s Weaver chaincode, and will be decrypted in SDK (i.e. Layer-2 client application) at `trade-logistics-network`, but relays and drivers in between will not be able to see the payload. By default this flag is set to `false`.
+
+| Notes |
+|:------|
+| A local chaincode invocation may require multiple view requests to different networks, which is why `indices` and `interopJSONs` are arrays; they therefore must have the same lengths. |
+
+The rest of the code ought to be self-explanatory. Values are hardcoded for explanation purposes, but you can refactor the above code by reading view addresses corresponding to chaincode invocations from a configuration file.
+
+**Enabling TLS**:
+By default, the TLS is set to false in `interopFlow`, i.e. disabled. But if you want to enable TLS, can pass additional parameters to the `interopFlow` function as follows:
+```TypeScript
+const flowResponse = await ihelper.interopFlow(
+ interopcc,
+ 'trade-finance-network',
+ {
+ channel: 'tradefinancechannel',
+ contractName: 'letterofcreditcc',
+ ccFunc: 'RecordBillOfLading',
+ ccArgs: [ , '' ]
+ },
+ , // Replace with this Layer-2 application's organization's MSP ID
+ [:], // Replace with local network's relay address and port
+ indices,
+ interopJSONs,
+ keyCert,
+ , // List of orgs to submit transaction to in trade logistics network
+ false, // Boolean flag to indicate whether return without submit transaction to local i.e. trade logistics network
+ true, // Boolean indication TLS is enabled.
+ , // list of CA certificate file paths
+);
+```
+
+#### For Asset Exchange
+
+Let's take an example of asset exchange between `Alice` and `Bob`, where Bob wants to purchase an asset of type `Gold` with id `A123` from `Alice` in `BondNetwork` in exchange for `200` tokens of type `CBDC01` in `TokenNetwork`.
+
+`Alice` needs to select a secret text (say `s`), and hash it (say `H`) using say `SHA512`, which will be used to lock her asset in `BondNetwork`. At the place in your application where an asset exchange is to be initiated, you need to add code to enable Alice to lock the non-fungible asset using hash `H` and timeout duration of 10 minutes:
+```typescript
+import { AssetManager, HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric'
+
+const hash = HashFunctions.SHA512(); // Create Hash instance of one of the supported Hash Algorithm
+hash.setSerializedHashBase64(H); // Set the Hash
+const timeout = Math.floor(Date.now()/1000) + 10 * 60;
+
+const bondContract = ;
+
+const result = await AssetManager.createHTLC(
+ bondContract,
+ "Gold", // Asset ID
+ "A123", // Asset Type
+ bobCertificate, // Certificate of Bob in Bond Network
+ hash, // Hash generated by Alice using her secret s
+ timeout, // Timeout in epoch for 10 mins from current time
+ null // Optional callback function to be called after the asset is locked
+);
+let bondContractId = result.result; // Unique ID for this asset exchange contract in BondNetwork
+```
+
+| Notes |
+|:------|
+| Note that 'Alice' and 'Bob' and the asset specifics can be parameterized in the above code, which can be reused for arbitrary asset exchange scenarios in your business workflow. The above code is only meant to be a sample. |
+
+Now `Bob` will lock his tokens in `TokenNetwork`. To lock the fungible asset using same hash `H` and timeout of 5 minutes (half the timeout duration used by Alice in `BondNetwork`), add the following code snippet in your application:
+```typescript
+const hash = HashFunctions.SHA512(); // Create Hash instance of one of the supported Hash Algorithm
+hash.setSerializedHashBase64(H); // Set the Hash
+const timeout = Math.floor(Date.now()/1000) + 5 * 60;
+
+const tokenContract = ;
+const result = await AssetManager.createFungibleHTLC(
+ tokenContract,
+ "CBDC01", // Token ID
+ 200, // Token Quantity
+ aliceCertificate, // Certificate of Alice in Token Network
+ hash, // Hash H used by Alice in Bond Network
+ timeout, // Timeout in epoch for 5 mins from current time
+ null // Optional callback function to be called after the asset is locked
+)
+const tokenContractId = result.result // Unique ID for this asset exchange contract in TokenNetwork
+```
+
+Wherever the lock status of the asset is required in your application, you should insert a query function call as follows:
+```typescript
+const contract = ;
+// Below contractId is the ID obtained during lock
+const isLocked = AssetManager.isAssetLockedInHTLCqueryUsingContractId(contract, contractId)
+```
+
+Wherever a participant (either 'Alice' or 'Bob' in this example) needs to claim a locked asset using the secret text (pre-image of hash) `s` in your application, insert the following code snippet (*Note*: typically one would insert this in event callback functions or in functions that are polling the ledger to monitor whether the asset is locked in favor of a given recipient):
+```typescript
+const hash = HashFunctions.SHA512(); // Create Hash instance of one of the supported Hash Algorithm
+hash.setPreimage(s) // Set Pre-Image s
+const contract = ;
+const claimSuccess = await AssetManager.claimAssetInHTLCusingContractId(
+ contract,
+ contractId, // contractId obtained during lock
+ hash
+)
+// return value claimSuccess is boolean indicating success or failure of claim
+```
+
+Wherever the asset must be unlocked in your application (typically, an event callback function triggered upon the expiration of the time lock), insert the following code snippet:
+```typescript
+const contract = ;
+const reclaimSuccess = await AssetManager.reclaimAssetInHTLCusingContractId(
+ contract,
+ contractId // contractId obtained during lock
+)
+// return value 'reclaimSuccess' is a boolean indicating success or failure of reclaim
+```
+
+#### For Asset Transfer
+
+_TBD_
+
+## Pre-Configuration Phase
+
+Typically, pre-configuration in a Fabric network involves generating (after creating the channel specifications and policies):
+
+- _Channel artifacts_: orderer genesis block, channel transaction, and anchor peer configurations from a `configtx.yaml` file (using Fabric's `configtxgen` tool)
+- _Crypto artifacts_: keys and certificates for CAs, peers, orderers, and clients from a `crypto-config.yaml` file (using Fabric's `cryptogen` tool)
+- _Connection profiles_: one for every network organization, which will be used by the organization's Layer-2 applications to connect to the network's peers and CAs
+
+No changes are required in this process to support any of the three interoperation modes using Weaver. The connection profiles generated above will be used by certain Weaver modules, as we will see later. The only additional step required is to generate special wallet identities for the following:
+
+- Network administrator: one or more identities containing the `network-admin` attribute; only a user/application possessing this identity may record special (privileged) information regarding memberships and policies on the channel.
+- Fabric Driver: one or more identities (for each deployed driver) containing the `relay` attribute; only a relay-driver combination possessing this identity may run data sharing-related operations on the deployed Fabric Interoperation Chaincode.
+- IIN Agent: one or more identities (for each deployed agent) containing the `iin-agent` attribute: only an agent may submit foreign network membership records to the Fabric Interoperation Chaincode.
+
+Later we will see how the components possessing these identities are deployed.
+
+## Startup and Bootstrap Phase
+
+After writing application code and creating the network configuration files, the components of a Fabric network (peers, CAs, and ordering service) are launched. In this section, we will list the additional tasks you, as a Fabric network administrator, must perform to make your network ready to interoperate.
+
+To launch a network using containerized components, you will typically use a Docker Compose or Kubernetes configuration file. No modifications are needed to the peers', orderers', and CAs' configurations. Sample instructions are given below for networks launched using Docker Compose; we leave it to the reader to adapt these to their custom launch processes.
+
+### For Asset Exchange
+
+The asset exchange mode currently requires only the Fabric Interoperation Chaincode module from Weaver. Relays, drivers, and IIN agents, are not necessary. In the future, we expect to make the asset exchange protocol moe automated using these components; the instructions here will be updated appropriately.
+
+#### Install the Fabric Interoperation Chaincode
+
+Install the Fabric Interoperation Chaincode in the relevant channel(s), i.e., those that run chaincodes that will be involved in asset exchanges. This is a Go module that can be fetched from `github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop`. Following that, you an install it using the appropriate Fabric process: in Fabric v2, you will need to package, install, approve, and commit this module on the selected channels in your network.
+
+### For Data Sharing or Asset Transfer
+
+Both the data sharing and asset transfer modes require the Fabric Interoperation Chaincode, relays, drivers, and IIN agents, to be deployed.
+
+#### Install the Fabric Interoperation Chaincode
+
+Install the Fabric Interoperation Chaincode in the relevant channel(s), i.e., those that run chaincodess that will be involved in data sharing (and asset transfers, which require multiple data shares). This is a Go module that can be fetched from `github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop`. Following that, you an install it using the appropriate Fabric process: in Fabric v2, you will need to package, install, approve, and commit this module on the selected channels in your network.
+
+#### Launch Relay
+
+You need to run one or more relays for network-to-network communication. Here we provide instructions to run one relay running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple relays, which will be useful from a failover perspective.)
+
+Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-relay-server) for the relay. Before launching a container, you just need to customize its configuration for your Fabric network, which you can do by simply creating a folder (let's call it `relay_config`) and configuring the following files in it:
+
+- `.env`: This sets suitable environment variables within the relay container. Copy the `.env.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/.env.template) and customize it for your purposes, as indicated in the below sample:
+ ```
+ PATH_TO_CONFIG=./config.toml
+ RELAY_NAME=<"name" in config.toml>
+ RELAY_PORT=
+ EXTERNAL_NETWORK=
+ DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-relay-server
+ DOCKER_TAG=2.0.0-alpha.1
+ ```
+ - The `PATH_TO_CONFIG` variable should point to the properties file typically named `config.toml` (you can name this whatever you wish). See further below for instructions to write this file.
+ - The `RELAY_NAME` variable specifies a unique name for this relay. It should match what's specified in the `config.toml` (more on that below).
+ - The `RELAY_PORT` variable specifies the port this relay server will listen on. It should match what's specified in the `config.toml` (more on that below).
+ - The `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Fabric network.
+ - The `DOCKER_*` variables are used to specify the image on which the container will be built. Make sure you set `DOCKER_TAG` to the latest version you see on [GitHub](ility/pkgs/container/weaver-relay-server).
+
+ For more details, see the [Relay Docker README](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/relay-docker.md) ("Relay Server Image" and "Running With Docker Compose" sections).
+
+- `config.toml`: This is the file specified in the `PATH_TO_CONFIG` variable in the `.env`. It specifies properties of this relay and the driver(s) it supports. A sample is given below:
+ ```toml
+ name=
+ port=
+ host="0.0.0.0"
+ db_path="db//requests"
+ remote_db_path="db//remote_request"
+
+ # FOR TLS
+ cert_path="credentials/fabric_cert.pem"
+ key_path="credentials/fabric_key"
+ tls=
+
+ [networks]
+ [networks.]
+ network=""
+
+ [relays]
+ [relays.]
+ hostname=""
+ port=""
+
+ [drivers]
+ [drivers.]
+ hostname=""
+ port=""
+ ```
+ - `` should be a unique ID representing this relay; e.g., `my_network_relay`. It should match the `RELAY_NAME` value in `.env`.
+ - `` is the port number the relay server will listen on. It should match the `RELAY_PORT` value in `.env`.
+ - `db_path` and `remote_db_path` are used internally by the relay to store data. Replace `` with the same value set for the `name` parameter. (These can point to any filesystem paths in the relay's container.)
+ - If you set `tls` to `true`, the relay will enforce TLS communication. The `cert_path` and `key_path` should point to a Fabric TLS certificate and key respectively, such as those created using the `cryptogen` tool.
+ - `` is a unique identifier for your local network. You can set it to whatever value you wish.
+ - `` refers to the driver used by this relay to respond to requests. This also refers to one of the drivers's specifications in the `drivers` section further below. In this code snippet, we have defined one driver. (The names in lines 14 and 22 must match.) In lines 23 and 24 respectively, you should specify the hostname and port for the driver (whose configuration we will handle later).
+ - The `relays` section specifies all foreign relays this relay can connect to. The `` value should be a unique ID for a given foreign relay, and this value will be used by your Layer-2 applications when constructing view addresses for data sharing requests. In lines 18 and 19, you should specify the hostname and port for the foreign relay.
+ - **Enabling TLS**:
+ - You can make your relay accept TLS connections by specifying a TLS certificate file path and private key file path in `cert_path` and `key_path` respectively, and set `tls` to `true`.
+ - To communicate with a foreign relay using TLS, specify that relay's TLS CA certificate path in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that relay's section as follows (*Note*: this CA certificate should match the one specified in the `cert_path` property in the foreign relay's `config.toml` file):
+ ```toml
+ [relays]
+ [relays.]
+ hostname=""
+ port=""
+ tls=
+ tlsca_cert_path=""
+ ```
+ - To communicate with a driver using TLS, specify the driver's TLS CA certificate in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that driver's section as follows (*Note*: this CA certificate must match the certificate used by the driver using the `DRIVER_TLS_CERT_PATH` property in its `.env` configuration file, which we will examine later):
+ ```toml
+ [drivers]
+ [drivers.]
+ hostname=""
+ port=""
+ tls=
+ tlsca_cert_path=""
+ ```
+
+ | Notes |
+ |:------|
+ | You can specify more than one foreign relay instance in the `relays` section. |
+ | You can specify more than one driver instance in the `drivers` section. |
+
+- `docker-compose.yaml`: This specifies the properties of the relay container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/docker-compose.yaml) verbatim.
+
+To start the relay server, navigate to the folder containing the above files and run the following:
+```bash
+docker-compose up -d relay-server
+```
+
+#### Launch Driver
+
+You need to run one or more drivers through which your relay can interact with your Fabric network. Here we provide instructions to run one Fabric driver running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple drivers, which will be useful both from a failover perspective and to interact with different subsets of your Fabric network, like private data collections.)
+
+Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-driver-fabric) for the Fabric driver. Before launching a container, you just need to customize its configuration for your Fabric network, which you can do by simply creating a folder (let's call it `driver_config`) and configuring the following files in it:
+
+- `.env`: This sets suitable environment variables within the driver container. Copy the `.env.docker.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/.env.docker.template) and customize it for your purposes, as indicated in the below sample:
+ ```
+ CONNECTION_PROFILE=
+ DRIVER_CONFIG=./config.json
+ RELAY_ENDPOINT=:
+ NETWORK_NAME=
+ DRIVER_PORT=
+ INTEROP_CHAINCODE=
+ EXTERNAL_NETWORK=
+ TLS_CREDENTIALS_DIR=
+ DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-driver-fabric
+ DOCKER_TAG=2.0.0-alpha.1
+ DRIVER_TLS=
+ DRIVER_TLS_CERT_PATH=path_to_tls_cert_pem_for_driver
+ DRIVER_TLS_KEY_PATH=path_to_tls_key_pem_for_driver
+ RELAY_TLS=
+ RELAY_TLSCA_CERT_PATH=path_to_tls_ca_cert_pem_for_relay
+ ```
+ - `` should point to the path of a connection profile you generated in the "Pre-Configuration" section. A Fabric driver obtains client credentials from one of the organizations in your network, so pick an organization and point to the right connection profile.
+ - The `DRIVER_CONFIG` variable should point to the `config.json` (you can name this whatever you wish) specified below.
+ - `` should be set to the hostname of the relay server machine and `` should match the `port` value in the relay's `config.toml` (see above).
+ - The `NETWORK_NAME` variable should be a unique ID referring to the Fabric network. It will be used to distinguish container names and wallet paths. (This setting is relevant in situations where a driver is used to query multiple network channels.)
+ - The `DRIVER_PORT` variable should be set to the port this driver will listen on.
+ - The `INTEROP_CHAINCODE` variable should be set to the ID of the Fabric Interop Chaincode installed on your Fabric network channel.
+ - The `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Fabric network.
+ - **Enabling TLS**:
+ - You can make your driver accept TLS connections by specifying `DRIVER_TLS` as `true` and specifying a TLS certificate file path and private key file path in `DRIVER_TLS_CERT_PATH` and `DRIVER_TLS_KEY_PATH` respectively. The same certificate should be specified in this driver's definition in the `drivers` section in the `config.toml` file of your relay in the `tlsca_cert_path` property (see the earlier section on relay configuration).
+ - To communicate with your network' relay using TLS (i.e., if the relay is TLS-enabled), specify that relay's TLS CA certificate path in `RELAY_TLSCA_CERT_PATH` (currently only one certificate can be configured) and set `RELAY_TLS` to `true`. This CA certificate should match the one specified in the `cert_path` property in the relay's `config.toml` file (see the earlier section on relay configuration):
+ - You can point to the folder in your host system containing the certificate and key using the `TLS_CREDENTIALS_DIR` variable. (This folder will be synced to the `/fabric-driver/credentials` folder in the Fabric Driver container as specified in the [docker-compose file](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/docker-compose.yml).) Make sure you point to the right certificate and key file paths within the container using the `DRIVER_TLS_CERT_PATH`, `DRIVER_TLS_KEY_PATH`, and `RELAY_TLSCA_CERT_PATH` variables.
+
+- `config.json`: This contains settings used to connect to a CA of a Fabric network organization and enroll a client. A sample is given below:
+ ```json
+ {
+ "admin":{
+ "name":"admin",
+ "secret":"adminpw"
+ },
+ "relay": {
+ "name":"relay",
+ "affiliation":"",
+ "role": "client",
+ "attrs": [{ "name": "relay", "value": "true", "ecert": true }]
+ },
+ "mspId":"",
+ "caUrl":""
+ }
+ ```
+ - As in the `.env` configuration, you should pick an organization for the driver to associate with. The `admin` section specifies the registrar name and password (this should be familiar to any Fabric network administrator) used to enroll clients. Default values of `admin` and `adminpw` are specified above as examples, which you should replace with the right values configured in your network organization's CA.
+ - `` should be what's specified in your organization's Fabric CA server configuration. The default is `org1.department1`, but you should look up the appropriate value from the CA server's configuration file.
+ - `` should be set to the (or an) MSP ID of the selected organization.
+ - `` should be set to the CA server's endpoint. If you launched your CA server as a container from a docker-compose file, this should be set to the container's service name.
+
+ | Notes |
+ |:------|
+ | If your connection profile already contains specifications for a CA server, you can leave the `` value as a blank. |
+
+- `docker-compose.yaml`: This specifies the properties of the driver container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/docker-compose.yml) verbatim.
+
+To start the driver, navigate to the folder containing the above files and run the following:
+```bash
+docker-compose up -d
+```
+
+#### Launch IIN Agents
+
+You need to run one IIN Agent for each organization in the Fabric network channel you are enabling Weaver in. This agent runs a protocol with other organizations' agents and with targeted foreign networks' agents to sync and record foreign networks' memberships to the channel ledger.
+
+Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-iin-agent) for the IIN Agent. Before launching a container, you just need to customize its configuration for your Fabric network organization, which you can do by simply creating a folder (let's call it `iin_agent_config_`) and configuring the following files in it:
+
+- `config.json`: This contains settings used to connect to a Fabric network organization and its CA (part of the organization's MSP). A sample is given below:
+ ```
+ {
+ "admin":{
+ "name":"admin",
+ "secret":"adminpw"
+ },
+ "agent": {
+ "name":"iin-agent",
+ "affiliation":"",
+ "role": "client",
+ "attrs": [{ "name": "iin-agent", "value": "true", "ecert": true }]
+ },
+ "mspId":"",
+ "ordererMspIds": [],
+ "ccpPath": "",
+ "walletPath": "",
+ "caUrl": "",
+ "local": "false"
+ }
+ ```
+
+- `dnsconfig.json`: This specifies the list of known IIN agents of your network (i.e., belonging to other organizations) and of foreign networks. A sample DNS configuration file is given below:
+ ```
+ {
+ "": {
+ "": {
+ "endpoint": "",
+ "tls": ,
+ "tlsCACertPath": ""
+ },
+ "": {
+ "endpoint": "",
+ "tls": ,
+ "tlsCACertPath": ""
+ }
+ },
+ "": {
+ "": {
+ "endpoint": "",
+ "tls": ,
+ "tlsCACertPath": ""
+ },
+ "": {
+ "endpoint": "",
+ "tls": ,
+ "tlsCACertPath": ""
+ }
+ }
+ }
+ ```
+ - Each security domain (i.e., unique ledger, like a Fabric channel) scopes a set of JSON objects, each containing specifications of an IIN Agent. The key (`` for example) in each is the IIN Agent's name, which can be the organization's MSP ID (for a Fabric network). The value is another JSON object, containing an `endpoint` with a hostname and port for the agent.
+ - **Enabling TLS**: To communicate with a given IIN Agent using TLS (i.e., if that agent is TLS-enabled), specify `tls` as `true` and that agent's TLS CA certificate path in `tlsCACertPath` (currently only one certificate can be configured) within the JSON object corresponding to that agent. This CA certificate should match the one specified in that IIN Agent's `.env` file, whose configuration we will specify later.
+
+- `security-domain-config.json`: This config file contains list of security domain defined for the network and its members, i.e. it can be list of organizations or channel name. Sample security domain configuration file:
+ ```
+ {
+ "": "",
+ "": [
+ "",
+ ""
+ ]
+ }
+ ```
+
+- `.env`: This sets suitable environment variables within the driver container. Copy the `.env.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/identity-management/iin-agent/.env.docker.template) and customize it for your purposes, as indicated in the below sample:
+ ```
+ IIN_AGENT_PORT=
+ IIN_AGENT_TLS=
+ IIN_AGENT_TLS_CERT_PATH=
+ IIN_AGENT_TLS_KEY_PATH=
+ MEMBER_ID=
+ SECURITY_DOMAIN=network1
+ DLT_TYPE=fabric
+ CONFIG_PATH=./config.json
+ DNS_CONFIG_PATH=./dnsconfig.json
+ SECURITY_DOMAIN_CONFIG_PATH=./security-domain-config.json
+ WEAVER_CONTRACT_ID=
+ SYNC_PERIOD=
+ AUTO_SYNC=
+ TLS_CREDENTIALS_DIR=
+ DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-iin-agent
+ DOCKER_TAG=
+ EXTERNAL_NETWORK=
+ ```
+ - `IIN_AGENT_ENDPOINT`: The endpoint at which IIN Agent server should listen. E.g.: `0.0.0.0:9500`
+ - `IIN_AGENT_TLS`: Set this to `true` to enable TLS on IIN Agent server
+ - `IIN_AGENT_TLS_CERT_PATH`: Path to TLS certificate if TLS is enabled
+ - `IIN_AGENT_TLS_KEY_PATH`: Path to TLS key if TLS is enabled
+ - `MEMBER_ID`: Member Id for this IIN Agent. For fabric network, it should be the Organization's MSP ID
+ - `SECURITY_DOMAIN`: Security domain to which this IIN Agent belongs
+ - `DLT_TYPE`: To indicate the type of DLT for which this IIN Agent is running. E.g. `fabric`
+ - `CONFIG_PATH`: Path to ledger specific config file (explained in next subsection)
+ - `DNS_CONFIG_PATH`: Path to DNS config file explained in previous sub sections
+ - `SECURITY_DOMAIN_CONFIG_PATH`: Path to security domain config file explained in previous sub sections
+ - `WEAVER_CONTRACT_ID`: Contract ID for DLT specific Weaver interoperation module installed on network
+ - `SYNC_PERIOD`: Period at which auto synchronization of memberships from other security domains should happen
+ - `AUTO_SYNC`: Set this to `true` to enable auto synchronization of memberships from other security domains
+ - `DOCKER_TAG`: Set this to the desired version of the Weaver IIN Agent [docker image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-iin-agent)
+ - `EXTERNAL_NETWORK`: Set to the network [name](https://docs.docker.com/compose/networking/) of your Fabric network.
+ - **Enabling TLS**:
+ - Make your IIN Agent accept TLS connections by specifying `IIN_AGENT_TLS` as `true` and specifying a TLS certificate file path and private key file path in `IIN_AGENT_TLS_CERT_PATH` and `IIN_AGENT_TLS_KEY_PATH` respectively. The same certificate should be specified in this agent's JSON object in another agent's `dnsconfig.json` file under the appropriate security domain and IIN Agent ID scope.
+ - You can point to the folder in your host system containing the certificate and key using the `TLS_CREDENTIALS_DIR` variable. (This folder will be synced to the `/opt/iinagent/credentials` folder in the IIN Agent container as specified in the [docker-compose file](https://github.com/hyperledger/cacti/blob/main/weaver/core/identity-management/iin-agent/docker-compose.yml).) Make sure you point to the right certificate and key file paths within the container using the `IIN_AGENT_TLS_CERT_PATH` and `IIN_AGENT_TLS_KEY_PATH` variables respectively.
+
+- `docker-compose.yaml`: This specifies the properties of the IIN agent container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/identity-management/iin-agent/docker-compose.yml) verbatim.
+
+Now to start the IIN agent, navigate to the folder containing the above files and run the following:
+```bash
+docker-compose up -d
+```
+
+Repeat the above steps to launch an IIN Agent for every other organization on your channnel, i.e., create similar configuration files in an organization-specific folder. Make sure you:
+
+- Update the organization names in every relevant location in the `config.json`.
+- Update `IIN_AGENT_ENDPOINT` and `MEMBER_ID` in the `.env`.
+
+
+#### Ledger Initialization
+
+To prepare your network for interoperation with a foreign network, you need to record the following to your network channel through the Fabric Interoperation Chaincode:
+
+- **Access control policies**:
+ Let's take the example of the request made from `trade-finance-network` to `trade-logistics-network` for a B/L earlier in this document. `trade-logistics-network` can have a policy of the following form permitting access to the `GetBillOfLading` function from a client belonging to the `Exporter` organization in `trade-finance-network` as follows:
+ ```json
+ {
+ "securityDomain":"trade-finance-network",
+ "rules":
+ [
+ {
+ "principal":"ExporterMSP",
+ "principalType":"ca",
+ "resource":"tradelogisticschannel:shipmentcc:GetBillOfLading:*",
+ "read":true
+ }
+ ]
+ }
+ ```
+ In this sample, a single rule is specified for requests coming from `trade-finance-network`: it states that a `GetBillOfLading` query made to the `shipmentcc` contract installed on the `tradelogisticschannel` channel is permitted for a requestor possessing credentials certified by an MSP with the `ExporterMSP` identity. The `*` at the end indicates that any arguments passed to the function will pass the access control check.
+
+ You need to record this policy rule on your Fabric network's channel by invoking either the `CreateAccessControlPolicy` function or the `UpdateAccessControlPolicy` function on the Fabric Interoperation Chaincode that is already installed on that channel; use the former if you are recording a set of rules for the given `securityDomain` for the first time and the latter to overwrite a set of rules recorded earlier. In either case, the chaincode function will take a single argument, which is the policy in the form of a JSON string (make sure you escape the double quotes before sending the request to avoid parsing errors). You can do this in one of two ways: (1) writing a small piece of code in Layer-2 that invokes the contract using the Fabric SDK Gateway API, or (2) running a `peer chaincode invoke` command from within a Docker container built on the `hyperledger/fabric-tools` image. Either approach should be familiar to a Fabric practitioner.
+
+- **Verification policies**:
+ Taking the same example as above, an example of a verification policy for a B/L requested by the `trade-finance-network` from the `trade-logistics-network` is as follows:
+ ```json
+ {
+ "securityDomain":"trade-logistics-network",
+ "identifiers":
+ [
+ {
+ "pattern":"tradelogisticschannel:shipmentcc:GetBillOfLading:*",
+ "policy":
+ {
+ "type":"Signature",
+ "criteria":
+ [
+ "ExporterMSP",
+ "CarrierMSP"
+ ]
+ }
+ }
+ ]
+ }
+ ```
+ In this sample, a single verification policy rule is specified for data views coming from `trade-logistics-network`: it states that the data returned by the `GetBillOfLading` query made to the `shipmentcc` chaincode on the `tradelogisticschannel` channel requires as proof two signatures, one from a peer in the organization whose MSP ID is `ExporterMSP` and another from a peer in the organization whose MSP ID is `CarrierMSP`.
+
+ You need to record this policy rule on your Fabric network's channel by invoking either the `CreateVerificationPolicy` function or the `UpdateVerificationPolicy` function on the Fabric Interoperation Chaincode that is already installed on that channel; use the former if you are recording a set of rules for the given `securityDomain` for the first time and the latter to overwrite a set of rules recorded earlier. In either case, the chaincode function will take a single argument, which is the policy in the form of a JSON string (make sure you escape the double quotes before sending the request to avoid parsing errors). As with the access control policy, you can do this in one of two ways: (1) writing a small piece of code in Layer-2 that invokes the contract using the Fabric SDK Gateway API, or (2) running a `peer chaincode invoke` command from within a Docker container built on the `hyperledger/fabric-tools` image. Either approach should be familiar to a Fabric practitioner.
+
+ | Notes |
+ |:------|
+ | For any cross-network data request, make sure an access control policy is recorded in the _source network_ (`trade-logistics-network` in the above example) and a corresponding verification policy is recorded in the _destination network_ (`trade-finance-network` in the above example) before any relay request is triggered. |
+
+- **Local network security domain (membership) configuration**:
+ Recall the code snippet added to your application in the "Identity Administration" section. Exercise that code snippet, exposed either through a function API or an HTTP endpoint, to record the initial local membership for the relevant network channels.
+
+Your Fabric network is now up and running with the necessary Weaver components, and your network's channel's ledger is bootstrapped with the initial configuration necessary for cross-network interactions!
diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/overview.md b/docs/docs/weaver/getting-started/enabling-weaver-network/overview.md
new file mode 100644
index 0000000000..08473b624a
--- /dev/null
+++ b/docs/docs/weaver/getting-started/enabling-weaver-network/overview.md
@@ -0,0 +1,19 @@
+---
+id: overview
+title: Enabling Cacti Weaver in Existing DLT Applications Overview
+sidebar_label: Overview
+pagination_label: Enabling Cacti Weaver in Existing DLT Applications
+pagination_prev: external/getting-started/interop/overview
+---
+
+
+
+If you have an existing DLT network and application suite built on any of the following platforms, follow the appropriate link below to understand how to adapt it to use Cacti-Weaver capabilities for cross-network interactions.
+
+* [Hyperledger Fabric](./fabric.md)
+* [R3 Corda](./corda.md)
+* [Hyperledger Besu](./besu.md)
diff --git a/docs/docs/weaver/getting-started/guide.md b/docs/docs/weaver/getting-started/guide.md
new file mode 100644
index 0000000000..81fab08518
--- /dev/null
+++ b/docs/docs/weaver/getting-started/guide.md
@@ -0,0 +1,34 @@
+---
+id: guide
+title: Using Weaver
+---
+
+
+
+The easiest way to understand how Weaver works is to run it at a small scale:
+
+- First, [launch a set of basic test networks](./test-network/overview.md) built on Fabric, Corda and Besu. These networks offer the most basic capabilities of their DLT platforms and run toy applications (contracts and Layer-2) that can easily be tracked and debugged. You can launch these networks in one of several different ways: building Weaver components and dependencies locally or importing pre-built ones from Github packages, running core components in the host or in Docker containers. The choice depends on whether you just want to get these networks up and running or if you wish to customize the setup by modifying source code and configurations.
+- Once the test networks are launched, you can test two distinct kinds of interoperation modes:
+ * [Data sharing](./interop/data-sharing.md): all combinations of Fabric and Corda networks supported
+ * [Asset exchange](./interop/asset-exchange/overview.md): all pairs of network types from {Fabric, Corda, Besu} are supported
+ * [Asset transfer](./interop/asset-transfer.md): all combinations of Fabric and Corda networks supported
+- (To bring down the test networks, go back to the "Setup" pages and follow instructions in the respective "Teardown" sections.)
+- After you run these tests and get a flavor of how the system and protocols work, you will be ready to move on to "real" networks, enhancing them with interoperation capabilities by incorporating Weaver into them. Check out the guidelines and templates for [Fabric](./enabling-weaver-network/fabric.md), [Corda](./enabling-weaver-network/corda.md), and [Besu](./enabling-weaver-network/besu.md) networks.
+
+If you wish to go further and understand Weaver specifics, dig into the code, or contribute to the open-source project, check out the [project repository](https://github.com/hyperledger/cacti/weaver). For specific information about individual Weaver components, see:
+
+- [Relay](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/README.md) module
+- [Fabric](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/readme.md) and [Corda](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/corda-driver/README.md) drivers
+- [Fabric Interoperation Chaincode](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/fabric-interop-cc/README.md), [Interoperation CorDapp](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/corda-interop-app/README.md), and [Besu Interoperation Contract](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/besu/README.md)
+- Common [protobufs](https://github.com/hyperledger/cacti/tree/main/weaver/common/protos): compiled in [JavaScript](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-js/README.md), [Golang](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-go/README.md), [Java](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-java-kt/README.md), [Rust](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-rs/README.md) and [Solidity](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-sol/README.md)
+- Fabric Interoperation SDKs in [Node.js](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/fabric/interoperation-node-sdk/README.md) and [Golang](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/fabric/go-sdk/readme.md)
+- Corda Interoperation SDK in [Kotlin/Java](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/corda/README.md)
+- Besu Interoperation SDK in [Node.js](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/besu/interoperation-node-sdk/README.md)
+- Sample [Fabric](https://github.com/hyperledger/cacti/tree/main/weaver/samples/fabric) and [Corda](https://github.com/hyperledger/cacti/tree/main/weaver/samples/corda) applications for experimentation and testing
+- [Fabric](https://github.com/hyperledger/cacti/blob/main/weaver/tests/network-setups/fabric/dev/README.md), [Corda](https://github.com/hyperledger/cacti/blob/main/weaver/tests/network-setups/corda/README.md), and [Besu](https://github.com/hyperledger/cacti/blob/main/weaver/tests/network-setups/besu/README.md) test network setups
+
+The Weaver [RFCs](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/README.md) contain detailed specifications of the models, data structures, protocols, and message formats.
diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/besu-besu.md b/docs/docs/weaver/getting-started/interop/asset-exchange/besu-besu.md
new file mode 100644
index 0000000000..0000224ead
--- /dev/null
+++ b/docs/docs/weaver/getting-started/interop/asset-exchange/besu-besu.md
@@ -0,0 +1,144 @@
+---
+id: besu-besu
+title: "Asset Exchange: Besu with Besu"
+sidebar_label: Besu with Besu
+pagination_label: Besu with Besu
+pagination_prev: external/getting-started/interop/asset-exchange/overview
+---
+
+We divide this page into two sections, if you used default configuration in ledger initialization step, then go to section [AliceERC721 with BobERC20](#aliceerc721-with-boberc20), otherwise if you used hybrid tokens in `network`, then go to section [AliceERC1155 with BobERC20](#aliceerc1155-with-boberc20)
+
+| Notes |
+|:------|
+| The hash used in following steps can be replaced by any valid `SHA256` hash. |
+
+## AliceERC721 with BobERC20
+
+One Besu network transfers an non-fungible `AliceERC721` token with id `0` from Alice to Bob in exchange for a transfer of `10 BobERC20` tokens from Bob to Alice in the other network. We will use account `1` for Alice and account `2` for Bob in both networks.
+
+Run the following steps:
+
+1. Navigate to the `weaver/samples/besu/besu-cli` folder in your clone of the Cacti repository.
+2. Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks:
+ ```bash
+ ./bin/besu-cli asset get-balance --network=network1 --account=1
+ ./bin/besu-cli asset get-balance --network=network1 --account=2
+ ./bin/besu-cli asset get-balance --network=network2 --account=1
+ ./bin/besu-cli asset get-balance --network=network2 --account=2
+ ```
+3. Generate Secret-Hash Pair using following command (prints hash in base64):
+ ```
+ ./bin/besu-cli hash --hash_fn=SHA256 secrettext
+ ```
+4. Run the following to trigger `alice` locking `AliceERC721` token with id `0` for `bob` in `network1` for 1 hour
+ ```bash
+ ./bin/besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --token_id=0 --asset_type=ERC721 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs=
+ ```
+ Value set to `hash_base64` argument corresponds to what was generated in Step 3. Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this:
+ ```bash
+ Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925
+ ```
+5. Run the following to verify `alice`'s lock, replacing `` with actual `contract-id`:
+ ```bash
+ ./bin/besu-cli asset is-locked --network=network1 --lock_contract_id=
+ ```
+6. Run the following to trigger `bob` locking `10` units of `BobERC20` tokens for `alice` in `network2` for 30 mins:
+ ```bash
+ ./bin/besu-cli asset lock --network=network2 --sender_account=2 --recipient_account=1 --amount=10 --timeout=1800 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs=
+ ```
+ Note the `contract-id` again for this lock printed as output in above command. Let's refer it `` for this demonstration.
+7. Run the following to verify `bob`'s lock:
+ ```bash
+ ./bin/besu-cli asset is-locked --network=network2 --lock_contract_id=
+ ```
+8. Run the following to trigger `alice`'s claim for `10` units of `BobERC20` tokens locked by `bob` in `network2`:
+ ```bash
+ ./bin/besu-cli asset claim --network=network2 --recipient_account=1 --preimage=secrettext --lock_contract_id=
+ ```
+9. Run the following to trigger `bob`'s claim for `AliceERC721` NFT with id `0` locked by `alice` in `network1`:
+ ```bash
+ ./bin/besu-cli asset claim --network=network1 --recipient_account=2 --preimage=secrettext --token_id=0 --lock_contract_id=
+ ```
+
+The above steps complete a successful asset exchange between two Besu networks.
+In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed.
+
+- If `alice` wants to unlock the asset, run the following to trigger `alice`'s re-claim for `AliceERC721` NFT with id `0` locked in `network1`:
+ ```bash
+ ./bin/besu-cli asset unlock --network=network1 --lock_contract_id= --sender_account=1 --token_id=0
+ ```
+
+- If `bob` wants to unlock the token asset, run the following to trigger `bob`'s re-claim for `10 BobERC20` tokens locked in `network2`:
+ ```bash
+ ./bin/besu-cli asset unlock --network=network2 --lock_contract_id= --sender_account=2
+ ```
+
+## AliceERC1155 with BobERC20
+
+One Besu network transfers an non-fungible `5 AliceERC1155` tokens with id `0` from Alice to Bob in exchange for a transfer of `50 BobERC20` tokens from Bob to Alice in the other network. We will use account `1` for Alice and account `2` for Bob in both networks.
+
+Run the following steps:
+
+1. Navigate to the `weaver/samples/besu/besu-cli` folder in your clone of the Cacti repository.
+2. Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks:
+ ```bash
+ ./bin/besu-cli asset get-balance --network=network1 --account=1
+ ./bin/besu-cli asset get-balance --network=network1 --account=2
+ ./bin/besu-cli asset get-balance --network=network2 --account=1
+ ./bin/besu-cli asset get-balance --network=network2 --account=2
+ ```
+3. Generate Secret-Hash Pair using following command (prints hash in base64):
+ ```
+ ./bin/besu-cli hash --hash_fn=SHA256 secrettext
+ ```
+4. Run the following to trigger `alice` locking `5 AliceERC1155` token with id `0` for `bob` in `network1` for 1 hour
+ ```bash
+ ./bin/besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --amount=5 --token_id=0 --asset_type=ERC1155 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs=
+ ```
+ Value set to `hash_base64` argument corresponds to what was generated in Step 3. Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this:
+ ```bash
+ Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925
+ ```
+5. Run the following to verify `alice`'s lock, replacing `` with actual `contract-id`:
+ ```bash
+ ./bin/besu-cli asset is-locked --network=network1 --lock_contract_id=
+ ```
+6. Run the following to trigger `bob` locking `50` units of `BobERC20` tokens for `alice` in `network2`:
+ ```bash
+ ./bin/besu-cli asset lock --network=network2 --sender_account=2 --recipient_account=1 --amount=50 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs=
+ ```
+ Note the `contract-id` again for this lock printed as output in above command. Let's refer it `` for this demonstration.
+7. Run the following to verify `bob`'s lock:
+ ```bash
+ ./bin/besu-cli asset is-locked --network=network2 --lock_contract_id=
+ ```
+8. Run the following to trigger `alice`'s claim for `50` units of `BobERC20` tokens locked by `bob` in `network2`:
+ ```bash
+ ./bin/besu-cli asset claim --network=network2 --recipient_account=1 --preimage=secrettext --lock_contract_id=
+ ```
+9. Run the following to trigger `bob`'s claim for `5 AliceERC1155` tokens with id `0` locked by `alice` in `network1`:
+ ```bash
+ ./bin/besu-cli asset claim --network=network1 --recipient_account=2 --preimage=secrettext --token_id=0 --lock_contract_id=
+ ```
+
+The above steps complete a successful asset exchange between two Besu networks.
+In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed.
+
+- If `alice` wants to unlock the asset, run the following to trigger `alice`'s re-claim for `5 AliceERC1155` tokens with id `0` locked in `network1`:
+ ```bash
+ ./bin/besu-cli asset unlock --network=network1 --lock_contract_id= --sender_account=1 --token_id=0
+ ```
+
+- If `bob` wants to unlock the token asset, run the following to trigger `bob`'s re-claim for `50 BobERC20` tokens locked in `network2`:
+ ```bash
+ ./bin/besu-cli asset unlock --network=network2 --lock_contract_id= --sender_account=2
+ ```
+
+Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks:
+```bash
+./bin/besu-cli asset get-balance --network=network1 --account=1
+./bin/besu-cli asset get-balance --network=network1 --account=2
+./bin/besu-cli asset get-balance --network=network2 --account=1
+./bin/besu-cli asset get-balance --network=network2 --account=2
+```
+
diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/corda-besu.md b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-besu.md
new file mode 100644
index 0000000000..00daa3dc5b
--- /dev/null
+++ b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-besu.md
@@ -0,0 +1,79 @@
+---
+id: corda-besu
+title: "Asset Exchange: Corda with Besu"
+sidebar_label: Corda with Besu
+pagination_label: Corda with Besu
+pagination_prev: external/getting-started/interop/asset-exchange/overview
+---
+
+We will demonstrate asset exchange of an `AliceERC721` NFT in Besu `network1` with `10` tokens on `Corda_Network`.
+For Besu commands, run from `weaver/weaver/samples/besu/besu-cli` folder, and for Corda commands, run from `samples/corda/corda-simple-application` folder, in your clone of the Cacti repository. Here `Alice` with account `1` and `Bob` with account `2` in Besu `network1` correspond to `PartyA` (`CORDA_PORT=10006`) and `PartyB` (`CORDA_PORT=10009`) in `Corda_Network` respectively. Following are the step-by-step asset exchange process:
+
+1. From corda client, generate secret-hash pair using following command (prints hash in base64):
+ ```
+ ./clients/build/install/clients/bin/clients utils hash --hash-fn=SHA256 -s secrettext
+ ```
+2. Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`:
+ ```bash
+ ./scripts/getAssetStatus.sh 2
+ ```
+3. Run the following in `besu-cli`, to verify the status of the assets owned by `Alice` and `Bob` in the Besu networks:
+ ```bash
+ ./bin/besu-cli asset get-balance --network=network1 --account=1
+ ./bin/besu-cli asset get-balance --network=network1 --account=2
+ ```
+4. Complete the asset exchange using following steps:
+ - Run the following to trigger `alice` locking `AliceERC721` token with id `0` for `bob` in `network1` for 1 hour
+ ```bash
+ ./bin/besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --token_id=0 --asset_type=ERC721 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs=
+ ```
+ Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this:
+ ```bash
+ Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925
+ ```
+ - Run the following to verify `alice`'s lock, replacing `` with actual `contract-id`:
+ ```bash
+ ./bin/besu-cli asset is-locked --network=network1 --lock_contract_id=
+ ```
+ - Run the following to trigger `PartyB` locking `50` units of token type `t1` for `PartyA` in `Corda_Network` for 30 mins:
+ ```bash
+ CORDA_PORT=10009 ./clients/build/install/clients/bin/clients lock-asset --fungible --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout=1800 --recipient="O=PartyA,L=London,C=GB" --param=t1:50
+ ```
+ Note the `contract-id` displayed after successful execution of the command, will be used in next steps. The output containing `contract-id` would like this:
+ ```bash
+ HTLC Lock State created with contract ID Right(b=10448674_80d2bee7-5a5d-45df-b14e-60bac4ba1bf3).
+ ```
+ `contract-id` is the alphanumeric text (with underscore and hyphens) after `b=` within parenthesis. Let's refer it `` for this demonstration.
+ - Run the following to verify `PartyB`'s lock (can be verified by both parties):
+ ```bash
+ CORDA_PORT=10006 ./clients/build/install/clients/bin/clients is-asset-locked --contract-id=
+ ```
+ - Run the following to trigger `PartyA`'s claim for `50` units of token type `t1` locked by `PartyB` in `Corda_Network`:
+ ```bash
+ CORDA_PORT=10006 ./clients/build/install/clients/bin/clients claim-asset --secret=secrettext --contract-id=
+ ```
+ `PartyB` can see its node's logs to get the revealed hash preimage, and use it to claim in the Besu network.
+ - Run the following to trigger `bob`'s claim for `AliceERC721` NFT with id `0` locked by `alice` in `network1`:
+ ```bash
+ ./bin/besu-cli asset claim --network=network1 --recipient_account=2 --preimage=secrettext --token_id=0 --lock_contract_id=
+ ```
+
+ The above steps complete a successful asset exchange between two Besu networks.
+ In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed.
+ - If `alice` wants to unlock the asset, run the following to trigger `alice`'s re-claim for `AliceERC721` NFT with id `0` locked in `network1`:
+ ```bash
+ ./bin/besu-cli asset unlock --network=network1 --lock_contract_id= --sender_account=1 --token_id=0
+ ```
+ - If `PartyB` wants to unlock the token asset, run the following to trigger unlock for `t1:50` locked in `Corda_Network`:
+ ```bash
+ CORDA_PORT=10009 ./clients/build/install/clients/bin/clients unlock-asset --contract-id=
+ ```
+5. Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`:
+ ```bash
+ ./scripts/getAssetStatus.sh 2
+ ```
+6. Run the following in `besu-cli`, to verify the status of the assets owned by `Alice` and `Bob` in the Besu networks:
+ ```bash
+ ./bin/besu-cli asset get-balance --network=network1 --account=1
+ ./bin/besu-cli asset get-balance --network=network1 --account=2
+ ```
diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/corda-corda.md b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-corda.md
new file mode 100644
index 0000000000..f4e5b5f6a3
--- /dev/null
+++ b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-corda.md
@@ -0,0 +1,71 @@
+---
+id: corda-corda
+title: "Asset Exchange: Corda with Corda"
+sidebar_label: Corda with Corda
+pagination_label: Corda with Corda
+pagination_prev: external/getting-started/interop/asset-exchange/overview
+---
+
+We will demonstrate asset exchange of a tokens in `Corda_Network` with tokens on `Corda_Network2`. Here `PartyA` (`CORDA_PORT=10006`) and `PartyB` (`CORDA_PORT=10009`) in `Corda_Network` correspond to `PartyA` (`CORDA_PORT=30006`) and `PartyB` (`CORDA_PORT=30009`) in `Corda_Network2` respectively. Following are the step-by-step asset exchange process:
+
+| Notes |
+|:------|
+| The hash used in following steps can be replaced by any valid `SHA256` hash. |
+
+- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository.
+- Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`:
+ ```bash
+ ./scripts/getAssetStatus.sh 2
+ ```
+- Generate Secret-Hash Pair using following command (prints hash in base64):
+ ```
+ ./clients/build/install/clients/bin/clients utils hash --hash-fn=SHA256 -s secrettext
+ ```
+- Run the following to trigger `PartyA` locking `30` units of token type `t1` for `PartyB` in `Corda_Network` for 60 mins:
+ ```bash
+ CORDA_PORT=10006 ./clients/build/install/clients/bin/clients lock-asset --fungible --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout=3600 --recipient="O=PartyB,L=London,C=GB" --param=t1:30
+ ```
+ Note the `contract-id` displayed after successful execution of the command, will be used in next steps. The output containing `contract-id` would like this:
+ ```bash
+ HTLC Lock State created with contract ID Right(b=10448674_80d2bee7-5a5d-45df-b14e-60bac4ba1bf3).
+ ```
+ `contract-id` is the alphanumeric text (with underscore and hyphens) after `b=` within parenthesis. Let's denote it `