diff --git a/.cspell.json b/.cspell.json index 76a276f2f80..686dfceff26 100644 --- a/.cspell.json +++ b/.cspell.json @@ -170,6 +170,7 @@ "vscc", "vuln", "wasm", + "WSPROVIDER", "Xdai" ], "dictionaries": [ diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 86b6bf510ea..1f6dbe9e4fd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -19,6 +19,7 @@ jobs: compute_changed_packages: outputs: cmd-api-server-changed: ${{ steps.changes.outputs.cmd-api-server-changed }} + plugin-ledger-connector-polkadot-changed: ${{ steps.changes.outputs.plugin-ledger-connector-polkadot-changed }} plugin-ledger-connector-aries-changed: ${{ steps.changes.outputs.plugin-ledger-connector-aries-changed }} plugin-ledger-connector-besu-changed: ${{ steps.changes.outputs.plugin-ledger-connector-besu-changed }} plugin-ledger-connector-corda-changed: ${{ steps.changes.outputs.plugin-ledger-connector-corda-changed }} @@ -49,6 +50,14 @@ jobs: - './packages/cactus-plugin-keychain-vault/**' # - './.github/workflows/ci.yaml' + plugin-ledger-connector-polkadot-changed: + - './packages/cactus-plugin-ledger-connector-polkadot/**!(*.md|*.css|*.html|*.jpg|*.jpeg|*.png)' + - './packages/cactus-common/**!(*.md|*.css|*.html|*.jpg|*.jpeg|*.png)' + - './packages/cactus-core/**!(*.md|*.css|*.html|*.jpg|*.jpeg|*.png)' + - './packages/cactus-core-api/**!(*.md|*.css|*.html|*.jpg|*.jpeg|*.png)' + - './packages/cactus-test-tooling/**!(*.md|*.css|*.html|*.jpg|*.jpeg|*.png)' + # - './.github/workflows/ci.yaml' + plugin-ledger-connector-aries-changed: - './packages/cactus-plugin-ledger-connector-aries/**' - './packages/cactus-common/**' @@ -982,6 +991,34 @@ jobs: node-version: ${{ env.NODEJS_VERSION }} - uses: actions/checkout@v3.5.2 + - id: yarn-cache + name: Restore Yarn Cache + uses: actions/cache@v3.3.1 + with: + key: ${{ runner.os }}-yarn-${{ hashFiles('./yarn.lock') }} + path: ./.yarn/ + restore-keys: | + ${{ runner.os }}-yarn-${{ hashFiles('./yarn.lock') }} + - run: ./tools/ci.sh + cactus-plugin-ledger-connector-polkadot: + continue-on-error: false + env: + FULL_BUILD_DISABLED: true + JEST_TEST_PATTERN: packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/(unit|integration|benchmark)/.*/*.test.ts + JEST_TEST_RUNNER_DISABLED: false + TAPE_TEST_RUNNER_DISABLED: true + needs: + - build-dev + - compute_changed_packages + if: needs.compute_changed_packages.outputs.plugin-ledger-connector-polkadot-changed == 'true' + runs-on: ubuntu-20.04 + steps: + - name: Use Node.js ${{ env.NODEJS_VERSION }} + uses: actions/setup-node@v3.6.0 + with: + node-version: ${{ env.NODEJS_VERSION }} + - uses: actions/checkout@v3.5.2 + - id: yarn-cache name: Restore Yarn Cache uses: actions/cache@v3.3.1 diff --git a/docs-cactus/source/support.rst b/docs-cactus/source/support.rst index 7f3c854f880..320a40e69e2 100644 --- a/docs-cactus/source/support.rst +++ b/docs-cactus/source/support.rst @@ -11,6 +11,6 @@ This section contains the ledger supported versions for connectors in Hyperledge Fabric Iroha Quorum - xDai - + xDai + Substrate diff --git a/docs-cactus/source/support/substrate.md b/docs-cactus/source/support/substrate.md new file mode 100644 index 00000000000..bad2192eae6 --- /dev/null +++ b/docs-cactus/source/support/substrate.md @@ -0,0 +1,16 @@ +Substrate Support +----------------- + + +```{note} +Substrate chains include Polkadot, Kusama, Rococco, etc. 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 v1.0.0-rc3 + + | Substrate API version | deployContract* | invokeContract | runTransaction | + | --- | :---: | :---: | :---: | + | @polkadot/api 10.9.1 | ✅ [test]() | ✅ [test]() | ✅ [test]() | + +
diff --git a/packages/cactus-plugin-ledger-connector-polkadot/Dockerfile b/packages/cactus-plugin-ledger-connector-polkadot/Dockerfile new file mode 100644 index 00000000000..d3f0a96727f --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/Dockerfile @@ -0,0 +1,10 @@ +FROM ghcr.io/hyperledger/cactus-cmd-api-server:2024-01-02-1fb2551 + +RUN npm install -g yarn \ + && yarn set version 3.6.3 \ + && yarn config set nodeLinker node-modules + +ENV NODE_ENV=production +ARG NPM_PKG_VERSION=latest + +RUN yarn add @hyperledger/cactus-plugin-ledger-connector-polkadot@${NPM_PKG_VERSION} \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/README.md b/packages/cactus-plugin-ledger-connector-polkadot/README.md new file mode 100644 index 00000000000..0af673825c7 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/README.md @@ -0,0 +1,240 @@ +# `@hyperledger/cactus-plugin-ledger-connector-polkadot` + +## Table of Contents + +- [1. Usage](#1-usage) + - [1.1. Installation](#11-installation) + - [1.2. Using as a Library](#12-using-as-a-library) + - [1.3. Using Via The API Client](#13-using-via-the-api-client) +- [2. Architecture](#2-architecture) + - [2.1. run-transaction-endpoint](#21-run-transaction-endpoint) +- [3. Containerization](#3-containerization) + - [3.1. Building/running the container image locally](#31-buildingrunning-the-container-image-locally) + - [3.2. Running the container](#32-running-the-container) +- [4. Prometheus Exporter](#4-prometheus-exporter) + - [4.1. Usage Prometheus](#41-usage-prometheus) + - [4.2. Prometheus Integration](#42-prometheus-integration) + - [4.3. Helper code](#43-helper-code) + - [4.3.1. response.type.ts](#431-responsetypets) + - [4.3.2. data-fetcher.ts](#432-data-fetcherts) + - [4.3.3. metrics.ts](#433-metricsts) +- [5. Contributing](#5-contributing) +- [6. License](#6-license) +- [7. Acknowledgments](#7-acknowledgments) + + +## 1. Usage + +This plugin provides a way to interact with Substrate networks. +Using this one can perform: +* Deploy smart contracts (ink! contract). +* Execute transactions on the ledger. +* Invoke ink! contract 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** + +```sh +npm install @hyperledger/cactus-plugin-ledger-connector-polkadot +``` + +**yarn** + +```sh +yarn add @hyperledger/cactus-plugin-ledger-connector-polkadot +``` + +### 1.2. Using as a Library + +```typescript +import { + PluginLedgerConnectorPolkadot, +} from "@hyperledger/cactus-plugin-ledger-connector-polkadot"; + +const plugin = new PluginLedgerConnectorPolkadot({ + // 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 Substrate ledger (network) +- You have a running Cactus API server on `$HOST:$PORT` with the Polkadot connector plugin installed on it (and the latter configured to have access to the Substrate ledger from point 1) + +```typescript +import { + PluginLedgerConnectorPolkadot, + DefaultApi as PolkadotApi, +} from "@hyperledger/cactus-plugin-ledger-connector-polkadot"; + +// Step zero is to deploy your Substrate ledger and the Cactus API server + +const apiHost = `http://${address}:${port}`; + +const apiConfig = new Configuration({ basePath: apiHost }); + +const apiClient = new PolkadotApi(apiConfig); + +const req: RunTransactionRequest = { + // See tests for specific examples on request properties +}; + +try { + const res = await apiClient.runTransaction(req); +} catch (ex: Error) { + // Make sure to handle errors gracefully (which is dependent on your use-case) + console.error(ex); + throw ex; +} +``` +## 2. Architecture +The sequence diagrams for various endpoints are mentioned below + +### 2.1. run-transaction-endpoint + +![run-transaction-endpoint sequence diagram](docs/architecture/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](docs/architecture/images/run-transaction-endpoint-transact.png) +The above diagram shows the sequence diagram of transact() method of the PluginLedgerConnectorPolkadot 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, corresponding responses are sent back to the caller. +![run-transaction-endpoint transactCactusKeychainRef() method](docs/architecture/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 transactMnemonicString() which calls the signAndSend() method of the Polkadot library. +![runtransaction-endpoint transactMnemonicString() method](docs/architecture/images/run-transaction-endpoint-transact-mnemonicstring.png) +The above diagram shows transactMnemonicString() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is MNEMONICSTRING. This method then calls the signAndSend() method of the Polkadot library. +![run-transaction-endpoint transactSigned() method](docs/architecture/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 api.rpc.author.submitAndWatchExtrinsic() of the Polkadot library. + + +## 3. Containerization +### 3.1. Building/running the container image locally + +In the Cactus project root say: + +```sh +DOCKER_BUILDKIT=1 docker build -f ./packages/cactus-plugin-ledger-connector-polkadot/Dockerfile . -t cplcb +``` + +Build with a specific version of the npm package: +```sh +DOCKER_BUILDKIT=1 docker build --build-arg NPM_PKG_VERSION=latest -f ./packages/cactus-plugin-ledger-connector-polkadot/Dockerfile . -t cplcb +``` + +### 3.2. Running the container + +Launch container with plugin configuration as an **environment variable**: + +```sh +docker run \ + --rm \ + --publish 3000:3000 \ + --publish 4000:4000 \ + --env AUTHORIZATION_PROTOCOL='NONE' \ + --env AUTHORIZATION_CONFIG_JSON='{}' \ + --env GRPC_TLS_ENABLED=false \ + cplcb \ + node_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \ + --env PLUGINS='[{"packageName": "cactus-plugin-ledger-connector-polkadot", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"wsProviderUrl":"ws://127.0.0.1:9944", "instanceId": "some-unique-polkadot-connector-instance-id"}}]' +``` + +Launch container with plugin configuration as a **CLI argument**: +```sh +docker run \ + --rm \ + --publish 3000:3000 \ + --publish 4000:4000 \ + --publish 5000:5000 \ + --env AUTHORIZATION_PROTOCOL='NONE' \ + --env AUTHORIZATION_CONFIG_JSON='{}' \ + --env GRPC_TLS_ENABLED=false \ + cplcb \ + node_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \ + --plugins='[{"packageName": "cactus-plugin-ledger-connector-polkadot", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"wsProviderUrl":"ws://127.0.0.1:9944", "instanceId": "some-unique-polkadot-connector-instance-id"}}]' +``` + +Launch container with **configuration file** mounted from host machine: +```sh + +echo '[{"packageName": "cactus-plugin-ledger-connector-polkadot", "type": "org.hyperledger.cactus.plugin_import_type.LOCAL", "action": "org.hyperledger.cactus.plugin_import_action.INSTALL", "options": {"wsProviderUrl":"ws://127.0.0.1:9944", "instanceId": "some-unique-polkadot-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 \ + cplcb \ + node_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \ + --config-file=/cactus.json +``` + +## 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 `PluginLedgerConnectorPolkadot` class constructor itself, so instantiating the object of the `PluginLedgerConnectorPolkadot` class, gives access to the exporter object. +You can also initialize the Prometheus exporter object separately and then pass it to the `IPluginLedgerConnectorPolkadotOptions` interface for `PluginLedgerConnectorPolkadot` constructor. + +`getPrometheusExporterMetricsEndpoint` function returns the Prometheus exporter metrics, currently displaying the total transaction count, which currently increments every time the `transact()` method of the `PluginLedgerConnectoPolkadot` 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 + +```(yaml) +- job_name: 'polkadot_ledger_connector_exporter' + metrics_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/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-polkadot/src/test/typescript/integration/run-transaction.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-polkadot/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_Polkadot_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 \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-cactuskeychainref.png b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-cactuskeychainref.png new file mode 100644 index 00000000000..2e45ff41264 Binary files /dev/null and b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-cactuskeychainref.png differ diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-mnemonicstring.png b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-mnemonicstring.png new file mode 100644 index 00000000000..9544dbccf50 Binary files /dev/null and b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-mnemonicstring.png differ diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-signed.png b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-signed.png new file mode 100644 index 00000000000..2637d2a6e0c Binary files /dev/null and b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact-signed.png differ diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact.png b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact.png new file mode 100644 index 00000000000..e8c892acd93 Binary files /dev/null and b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint-transact.png differ diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint.png b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint.png new file mode 100644 index 00000000000..36e972226ce Binary files /dev/null and b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/images/run-transaction-endpoint.png differ diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-cactuskeychainref.puml b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-cactuskeychainref.puml new file mode 100644 index 00000000000..93fcaba08db --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-cactuskeychainref.puml @@ -0,0 +1,29 @@ +@startuml +title Hyperledger Cactus\nSequence Diagram\nRun Transaction Endpoint\ntransactCactusKeychainRef() method + +skinparam sequenceArrowThickness 2 +skinparam roundcorner 20 +skinparam maxmessagesize 120 +skinparam sequenceParticipant underline + +actor "Caller" as caller +participant "transactCactusKeychainRef()" as tckr +participant "transactMnemonicString()" as tms +participant ".signAndSend()" as sas + +caller-> tckr: req +activate caller +group #LightBlue if web3SigningCredential == CACTUSKEYCHAINREF + activate tckr + tckr -> tms: [transactionConfig, web3SigningCredential] + activate tms + tms -> sas: [transactionConfig, mnemonicString] + activate sas + sas --> tms: return [success, blockhash, transactionHash] + deactivate sas + tms --> tckr: return [success, blockhash, transactionHash] + tckr --> caller : return {success, blockhash, transactionHash} as resBody + deactivate tckr + deactivate tms +end +@enduml \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-mnemonicstring.puml b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-mnemonicstring.puml new file mode 100644 index 00000000000..48a23798182 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-mnemonicstring.puml @@ -0,0 +1,23 @@ +@startuml +title Hyperledger Cactus\nSequence Diagram\nRun Transaction Endpoint\ntransactMnemonicString() method + +skinparam sequenceArrowThickness 2 +skinparam roundcorner 20 +skinparam maxmessagesize 120 +skinparam sequenceParticipant underline + +actor "Caller" as caller +participant "transactMnemonicString()" as tms +participant ".signAndSend()" as sas + +caller -> tms: req +activate caller +alt #LightGreen web3SigningCredential == MNEMONICSTRING + activate tms + tms -> sas: [transactionConfig, mnemonicString] + activate sas + sas --> tms: return [success, txHash, blockHash] + deactivate sas + tms --> caller: return [success, txHash, blockHash] as resBody +end +@enduml \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-signed.puml b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-signed.puml new file mode 100644 index 00000000000..94ab78b369f --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact-signed.puml @@ -0,0 +1,24 @@ +@startuml +title Hyperledger Cactus\nSequence Diagram\nRun Transaction Endpoint\ntransactSigned() method + +skinparam sequenceArrowThickness 2 +skinparam roundcorner 20 +skinparam maxmessagesize 120 +skinparam sequenceParticipant underline + +actor "Caller" as caller +participant "transactSigned()" as ts +participant "api.rpc.author.submitAndWatchExtrinsic()" as aras + +caller -> ts: req +activate caller +group #e6e632 if web3SigningCredential == NONE + activate ts + ts -> aras: deserializedTransaction + activate aras + aras --> ts: success, txHash, blockHash + deactivate aras +ts --> caller: returns [success, txHash, blockHash] as resBody +end +deactivate caller +@enduml \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact.puml b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact.puml new file mode 100644 index 00000000000..06aae5d4a67 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint-transact.puml @@ -0,0 +1,36 @@ +@startuml +title Hyperledger Cactus\nSequence Diagram\nRun Transaction Endpoint\ntransact() method + +skinparam sequenceArrowThickness 2 +skinparam roundcorner 20 +skinparam maxmessagesize 120 +skinparam sequenceParticipant underline + +actor "Caller" as caller +participant "PluginLedgerConnectorPolkadot" as t << (C,#ADD1B2) class >> + +autoactivate on + +activate caller +caller -> t: transact(RunTransactionRequest) + +alt #LightBlue web3SigningCredential == CACTUSKEYCHAINREF + t -> t: transactCactusKeychainRef(RunTransactionRequest) + return RunTransactionResponse + t --> caller: return RunTransactionResponse +else #LightGreen web3SigningCredential == MNEMONICSTRING + t -> t: transactMnemonicString(RunTransactionRequest) + return RunTransactionResponse + t --> caller: return RunTransactionResponse +else #e6e632 web3SigningCredential == NONE + group #LightGray if defined: req.transactionConfig.transferSubmittable + t -> t: transactSigned(RunTransactionRequest) + return RunTransactionResponse + t --> caller: return RunTransactionResponse + else #LightCoral + t --> caller: throw Error: Expected pre-signed raw transaction + end +else #LightCoral default + t --> caller: throw Error: Unrecognized Web3SigningCredentialType +end +@enduml \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint.puml b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint.puml new file mode 100644 index 00000000000..1885b8d3f91 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/docs/architecture/run-transaction-endpoint.puml @@ -0,0 +1,27 @@ +@startuml +title Hyperledger Cactus\nSequence Diagram\nRun Transaction Endpoint + +skinparam sequenceArrowThickness 2 +skinparam roundcorner 20 +skinparam maxmessagesize 120 +skinparam sequenceParticipant underline + +box "Users" #LightBlue +actor "User A" as a +end box + +box "Hyperledger Cactus" #LightGray +entity "API Client" as apic +entity "API Server" as apis +end box + +box "Ledger Connector" #LightGreen +database "Polkadot" as polkadotcon +end box + +a --> apic : Tx Polkadot Ledger +apic --> apis: Request +apis --> polkadotcon: transact() +polkadotcon --> apis: Response +apis --> apic: Formatted Response +@enduml \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/openapitools.json b/packages/cactus-plugin-ledger-connector-polkadot/openapitools.json new file mode 100644 index 00000000000..225ff1aaaee --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "6.6.0" + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/package.json b/packages/cactus-plugin-ledger-connector-polkadot/package.json new file mode 100644 index 00000000000..67ae96c3ddb --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/package.json @@ -0,0 +1,123 @@ +{ + "name": "@hyperledger/cactus-plugin-ledger-connector-polkadot", + "version": "2.0.0-alpha.2", + "description": "Allows Cactus nodes to connect to a Substrate ledger.", + "keywords": [ + "Hyperledger", + "Cactus", + "Integration", + "Blockchain", + "Distributed Ledger Technology" + ], + "homepage": "https://github.com/hyperledger/cacti#readme", + "bugs": { + "url": "https://github.com/hyperledger/cacti/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/hyperledger/cacti.git" + }, + "license": "Apache-2.0", + "author": { + "name": "Hyperledger Cactus Contributors", + "email": "cactus@lists.hyperledger.org", + "url": "https://www.hyperledger.org/use/cactus" + }, + "contributors": [ + { + "name": "Please add yourself to the list of contributors", + "email": "your.name@example.com", + "url": "https://example.com" + }, + { + "name": "Catarina Pedreira" + }, + { + "name": "Rafael Belchior" + }, + { + "name": "Anmol Bansal", + "email": "anmolbansal1807@gmail.com" + } + ], + "main": "dist/lib/main/typescript/index.js", + "module": "dist/lib/main/typescript/index.js", + "browser": "dist/cactus-plugin-ledger-connector-polkadot.web.umd.js", + "types": "dist/types/main/typescript/index.d.ts", + "files": [ + "dist/*" + ], + "scripts": { + "codegen": "run-p 'codegen:*'", + "codegen:openapi": "npm run generate-sdk", + "generate-sdk": "openapi-generator-cli generate -i ./src/main/json/openapi.json -g typescript-axios -o ./src/main/typescript/generated/openapi/typescript-axios/ --reserved-words-mappings protected=protected", + "lint": "tslint tests/*.ts -t verbose", + "lint-fix": "tslint --fix tests/*.ts -t verbose", + "watch": "npm-watch", + "webpack": "npm-run-all webpack:dev webpack:prod", + "webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web", + "webpack:dev:node": "webpack --env=dev --target=node --config ../../webpack.config.js", + "webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js", + "webpack:prod": "npm-run-all webpack:prod:node webpack:prod:web", + "webpack:prod:node": "webpack --env=prod --target=node --config ../../webpack.config.js", + "webpack:prod:web": "webpack --env=prod --target=web --config ../../webpack.config.js" + }, + "dependencies": { + "@hyperledger/cactus-common": "2.0.0-alpha.2", + "@hyperledger/cactus-core": "2.0.0-alpha.2", + "@hyperledger/cactus-core-api": "2.0.0-alpha.2", + "@polkadot/api": "10.9.1", + "@polkadot/api-contract": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "12.6.2", + "bl": "5.0.0", + "eslint": "7.21.0", + "express": "4.17.1", + "express-openapi-validator": "4.13.1", + "form-data": "4.0.0", + "fs-extra": "11.2.0", + "http-errors": "2.0.0", + "http-status-codes": "2.1.4", + "joi": "14.3.1", + "multer": "1.4.2", + "ngo": "2.6.2", + "openapi-types": "9.1.0", + "prom-client": "13.2.0", + "run-time-error": "1.4.0", + "temp": "0.9.1", + "tslint": "6.1.3", + "typescript-optional": "2.0.1", + "uuid": "8.3.2" + }, + "devDependencies": { + "@hyperledger/cactus-plugin-keychain-memory": "2.0.0-alpha.2", + "@hyperledger/cactus-test-tooling": "2.0.0-alpha.2", + "@types/express": "4.17.19", + "@types/http-errors": "2.0.4", + "@types/joi": "14.3.4", + "@types/multer": "1.4.7", + "@types/ssh2": "0.5.44", + "@types/supertest": "2.0.11", + "@types/temp": "0.9.1", + "@types/uuid": "8.3.1", + "axios": "0.22.0", + "supertest": "6.1.6" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + }, + "publishConfig": { + "access": "public" + }, + "browserMinified": "dist/cactus-plugin-ledger-connector-polkadot.web.umd.min.js", + "mainMinified": "dist/cactus-plugin-ledger-connector-polkadot.node.umd.min.js", + "watch": { + "codegen:openapi": { + "patterns": [ + "./src/main/json/openapi.json" + ] + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json b/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json new file mode 100644 index 00000000000..6a41999fa3f --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/json/openapi.json @@ -0,0 +1,868 @@ +{ + "openapi": "3.0.3", + "info": { + "title": "Hyperledger Cactus Plugin - Connector Polkadot", + "description": "Can perform basic tasks on a Polkadot parachain", + "version": "v2.0.0-alpha.2", + "license": { + "name": "Apache-2.0", + "url": "https://www.apache.org/licenses/LICENSE-2.0.html" + } + }, + "components": { + "schemas": { + "PrometheusExporterMetricsResponse": { + "type": "string", + "nullable": false + }, + "TransactionInfoRequest": { + "type": "object", + "required": [ + "accountAddress", + "transactionExpiration" + ], + "additionalProperties": false, + "properties": { + "accountAddress": { + "type": "string", + "nullable": false + }, + "transactionExpiration":{ + "type": "number", + "nullable": true + } + } + }, + "TransactionInfoResponseData": { + "type": "object", + "required": [ + "nonce", + "blockHash", + "era" + ], + "additionalProperties": false, + "properties": { + "nonce": { + "type": "object", + "nullable": false + }, + "blockHash": { + "type": "object", + "nullable": false + }, + "era": { + "type": "object", + "nullable": true + } + } + }, + "TransactionInfoResponse": { + "type": "object", + "required": [ + "responseContainer" + ], + "additionalProperties": false, + "properties": { + "responseContainer": { + "type": "object", + "required": [ + "response_data", + "succeeded", + "message", + "error" + ], + "additionalProperties": false, + "properties": { + "response_data": { + "$ref": "#/components/schemas/TransactionInfoResponseData", + "nullable": false + }, + "succeeded": { + "type": "boolean", + "nullable": false + }, + "message": { + "type": "string", + "nullable": false + }, + "error": { + "type": "string", + "nullable": true + } + } + } + } + }, + "RawTransactionRequest": { + "type": "object", + "required": ["to", "value"], + "additionalProperties": false, + "properties": { + "to": { + "type": "string", + "nullable": false + }, + "value": { + "type": "number", + "nullable": false + } + } + }, + "RawTransactionResponseData": { + "type": "object", + "required": [ + "rawTransaction" + ], + "additionalProperties": false, + "properties": { + "rawTransaction": { + "type": "string", + "nullable": false + } + } + }, + "RawTransactionResponse": { + "type": "object", + "required": ["responseContainer"], + "additionalProperties": false, + "properties": { + "responseContainer": { + "type": "object", + "required": [ + "response_data", + "succeeded", + "message", + "error" + ], + "additionalProperties": false, + "properties": { + "response_data": { + "$ref": "#/components/schemas/RawTransactionResponseData", + "nullable": false + }, + "succeeded": { + "type": "boolean", + "nullable": false + }, + "message": { + "type": "string", + "nullable": false + }, + "error": { + "type": "string", + "nullable": true + } + } + } + } + }, + "SignRawTransactionRequest": { + "type": "object", + "required": ["rawTransaction", "mnemonic"], + "additionalProperties": false, + "properties": { + "rawTransaction": { + "type": "string", + "nullable": false + }, + "mnemonic": { + "type": "string", + "nullable": false + }, + "signingOptions": { + "type": "object", + "nullable": false + } + } + }, + "SignRawTransactionResponse": { + "type": "object", + "required": ["success", "signedTransaction"], + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean", + "nullable": false + }, + "signedTransaction": { + "type": "string", + "nullable": false + } + } + }, + "web3SigningCredential": { + "type": "object", + "required": ["type"], + "discriminator": { + "propertyName": "type" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/Web3SigningCredentialCactusKeychainRef" + }, + { + "$ref": "#/components/schemas/Web3SigningCredentialMnemonicString" + }, + { + "$ref": "#/components/schemas/Web3SigningCredentialNone" + } + ], + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" + } + } + }, + "Web3SigningCredentialCactusKeychainRef": { + "type": "object", + "required": ["type", "ethAccount", "keychainId", "keychainEntryKey"], + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" + }, + "keychainEntryKey": { + "type": "string", + "description": "The key to use when looking up the the keychain entry holding the secret pointed to by the keychainEntryKey parameter.", + "minLength": 0, + "maxLength": 1024 + }, + "keychainId": { + "type": "string", + "description": "The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter.", + "minLength": 0, + "maxLength": 1024 + } + } + }, + "Web3SigningCredentialMnemonicString": { + "type": "object", + "required": ["type", "mnemonic"], + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" + }, + "mnemonic": { + "type": "string", + "description": "The Polkadot account's seed phrase for signing transaction", + "nullable": false + } + } + }, + "Web3SigningCredentialNone": { + "type": "object", + "required": ["type"], + "description": "Using this denotes that there is no signing required because the transaction is pre-signed.", + "properties": { + "type": { + "$ref": "#/components/schemas/Web3SigningCredentialType" + } + } + }, + "Web3SigningCredentialType": { + "type": "string", + "enum": [ + "CACTUS_KEYCHAIN_REF", + "MNEMONIC_STRING", + "NONE" + ] + }, + "PolkadotTransactionConfig": { + "type": "object", + "additionalProperties": true, + "properties": { + "transferSubmittable": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "to": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "value": { + "oneOf": [ + { + "type": "number" + } + ] + } + } + }, + "RunTransactionRequest": { + "type": "object", + "required": [ + "web3SigningCredential", "transactionConfig" + ], + "additionalProperties": false, + "properties": { + "web3SigningCredential": { + "$ref": "#/components/schemas/web3SigningCredential", + "nullable": false + }, + "transactionConfig": { + "$ref": "#/components/schemas/PolkadotTransactionConfig", + "nullable": false + } + } + }, + "RunTransactionResponse": { + "type": "object", + "required": [ + "success" + ], + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean", + "nullable": false + }, + "txHash": { + "type": "string", + "nullable": false + }, + "blockHash": { + "type": "string", + "nullable": false + } + } + }, + "DeployContractInkRequest": { + "type": "object", + "required": [ + "web3SigningCredential", + "wasm", + "metadata", + "gasLimit" + ], + "additionalProperties": false, + "properties": { + "web3SigningCredential": { + "$ref": "#/components/schemas/web3SigningCredential", + "nullable": false + }, + "wasm": { + "description": "raw wasm for the compiled contract in base64 format", + "type": "string", + "format": "byte", + "nullable": false + }, + "constructorMethod": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "metadata": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "gasLimit": { + "type": "object", + "required": ["refTime", "proofSize"], + "properties": { + "refTime": { + "type": "integer", + "minimum": 0 + }, + "proofSize": { + "type": "integer", + "minimum": 0 + } + } + }, + "storageDepositLimit": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ], + "nullable": true + }, + "params": { + "description": "The list of arguments to pass in to the contract method being deployed", + "type": "array", + "default": [], + "items": {} + }, + "balance": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ] + }, + "salt": { + "oneOf": [ + { + "type": "string" + } + ], + "nullable": true + } + } + }, + "DeployContractInkResponse": { + "type": "object", + "required": ["success"], + "additionalProperties": false, + "properties": { + "success": { + "type": "boolean", + "nullable": false + }, + "contractAddress": { + "type": "string", + "nullable": false + } + } + }, + "PolkadotContractInvocationType": { + "type": "string", + "enum": ["SEND", "QUERY"] + }, + "InvokeContractRequest": { + "type": "object", + "required": [ + "invocationType", + "metadata", + "contractAddress", + "methodName", + "gasLimit", + "accountAddress", + "web3SigningCredential" + ], + "additionalProperties": false, + "properties": { + "invocationType": { + "$ref": "#/components/schemas/PolkadotContractInvocationType", + "nullable": false, + "description": "Indicates whether it is a QUERY or a SEND type of invocation where only SEND ends up creating an actual transaction on the ledger." + }, + "accountAddress": { + "type": "string", + "nullable": false + }, + "web3SigningCredential": { + "$ref": "#/components/schemas/web3SigningCredential", + "nullable": false + }, + "metadata": { + "oneOf": [ + { + "type": "string" + } + ] + }, + "contractAddress": { + "type": "string", + "nullable": false + }, + "methodName": { + "description": "The name of the contract method to invoke.", + "type": "string", + "nullable": false, + "minLength": 1, + "maxLength": 2048 + }, + "gasLimit": { + "type": "object", + "required": ["refTime", "proofSize"], + "properties": { + "refTime": { + "type": "integer", + "minimum": 0 + }, + "proofSize": { + "type": "integer", + "minimum": 0 + } + } + }, + "storageDepositLimit": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ], + "nullable": true + }, + "balance": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer", + "minimum": 0 + } + ] + }, + "params": { + "description": "The list of arguments to pass in to the contract method being invoked", + "type": "array", + "default": [], + "items": {} + } + } + }, + "InvokeContractResponse": { + "type": "object", + "required": ["success"], + "properties": { + "callOutput": {}, + "success": { + "type": "boolean", + "nullable": false + }, + "txHash": { + "type": "string", + "nullable": false + }, + "blockHash": { + "type": "string", + "nullable": false + } + } + }, + "ErrorExceptionResponse": { + "type": "object", + "description": "Error response from the connector.", + "required": ["message", "error"], + "properties": { + "message": { + "type": "string", + "description": "Short error description message.", + "nullable": false + }, + "error": { + "type": "string", + "description": "Detailed error information.", + "nullable": false + } + } + } + } + }, + "paths": { + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-prometheus-exporter-metrics": { + "get": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-prometheus-exporter-metrics" + } + }, + "operationId": "getPrometheusMetrics", + "summary": "Get the Prometheus Metrics", + "parameters": [], + "responses": { + "200": { + "description": "OK", + "content": { + "text/plain": { + "schema": { + "$ref": "#/components/schemas/PrometheusExporterMetricsResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-transaction-info": { + "post": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-transaction-info" + } + }, + "operationId": "getTransactionInfo", + "summary": "Get the necessary Transaction Info for a account", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionInfoRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransactionInfoResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-raw-transaction": { + "post": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-raw-transaction" + } + }, + "operationId": "getRawTransaction", + "summary": "Get raw unsigned transaction", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RawTransactionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RawTransactionResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/sign-raw-transaction": { + "post": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/sign-raw-transaction" + } + }, + "operationId": "signRawTransaction", + "summary": "sign the raw transaction", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignRawTransactionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SignRawTransactionResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/run-transaction": { + "post": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/run-transaction" + } + }, + "operationId": "runTransaction", + "summary": "Executes a transaction on a Polkadot ledger", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunTransactionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RunTransactionResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/deploy-contract-ink": { + "post": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/deploy-contract-ink" + } + }, + "operationId": "deployContractInk", + "summary": "Deploys the ink! contract", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployContractInkRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeployContractInkResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + }, + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/invoke-contract": { + "post": { + "x-hyperledger-cactus": { + "http": { + "verbLowerCase": "post", + "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/invoke-contract" + } + }, + "operationId": "invokeContract", + "summary": "Invokes a contract on a polkadot ledger", + "parameters": [], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvokeContractRequest" + } + } + } + }, + "responses": { + "200": { + "description": "OK", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/InvokeContractResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorExceptionResponse" + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore new file mode 100644 index 00000000000..6ff76cf80a2 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator-ignore @@ -0,0 +1,27 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md + +.npmignore +.gitignore +git_push.sh \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES new file mode 100644 index 00000000000..53250c02696 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/FILES @@ -0,0 +1,5 @@ +api.ts +base.ts +common.ts +configuration.ts +index.ts diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION new file mode 100644 index 00000000000..cd802a1ec4e --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/.openapi-generator/VERSION @@ -0,0 +1 @@ +6.6.0 \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/api.ts new file mode 100644 index 00000000000..9f2cae5f0c4 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/api.ts @@ -0,0 +1,1151 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Connector Polkadot + * Can perform basic tasks on a Polkadot parachain + * + * The version of the OpenAPI document: v2.0.0-alpha.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from './configuration'; +import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; +// Some imports not used depending on template conditions +// @ts-ignore +import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from './common'; +import type { RequestArgs } from './base'; +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from './base'; + +/** + * + * @export + * @interface DeployContractInkRequest + */ +export interface DeployContractInkRequest { + /** + * + * @type {Web3SigningCredential} + * @memberof DeployContractInkRequest + */ + 'web3SigningCredential': Web3SigningCredential; + /** + * raw wasm for the compiled contract in base64 format + * @type {string} + * @memberof DeployContractInkRequest + */ + 'wasm': string; + /** + * + * @type {PolkadotTransactionConfigTransferSubmittable} + * @memberof DeployContractInkRequest + */ + 'constructorMethod'?: PolkadotTransactionConfigTransferSubmittable; + /** + * + * @type {PolkadotTransactionConfigTransferSubmittable} + * @memberof DeployContractInkRequest + */ + 'metadata': PolkadotTransactionConfigTransferSubmittable; + /** + * + * @type {DeployContractInkRequestGasLimit} + * @memberof DeployContractInkRequest + */ + 'gasLimit': DeployContractInkRequestGasLimit; + /** + * + * @type {DeployContractInkRequestStorageDepositLimit} + * @memberof DeployContractInkRequest + */ + 'storageDepositLimit'?: DeployContractInkRequestStorageDepositLimit | null; + /** + * The list of arguments to pass in to the contract method being deployed + * @type {Array} + * @memberof DeployContractInkRequest + */ + 'params'?: Array; + /** + * + * @type {DeployContractInkRequestBalance} + * @memberof DeployContractInkRequest + */ + 'balance'?: DeployContractInkRequestBalance; + /** + * + * @type {DeployContractInkRequestSalt} + * @memberof DeployContractInkRequest + */ + 'salt'?: DeployContractInkRequestSalt | null; +} +/** + * @type DeployContractInkRequestBalance + * @export + */ +export type DeployContractInkRequestBalance = number | string; + +/** + * + * @export + * @interface DeployContractInkRequestGasLimit + */ +export interface DeployContractInkRequestGasLimit { + /** + * + * @type {number} + * @memberof DeployContractInkRequestGasLimit + */ + 'refTime': number; + /** + * + * @type {number} + * @memberof DeployContractInkRequestGasLimit + */ + 'proofSize': number; +} +/** + * @type DeployContractInkRequestSalt + * @export + */ +export type DeployContractInkRequestSalt = string; + +/** + * @type DeployContractInkRequestStorageDepositLimit + * @export + */ +export type DeployContractInkRequestStorageDepositLimit = number | string; + +/** + * + * @export + * @interface DeployContractInkResponse + */ +export interface DeployContractInkResponse { + /** + * + * @type {boolean} + * @memberof DeployContractInkResponse + */ + 'success': boolean; + /** + * + * @type {string} + * @memberof DeployContractInkResponse + */ + 'contractAddress'?: string; +} +/** + * Error response from the connector. + * @export + * @interface ErrorExceptionResponse + */ +export interface ErrorExceptionResponse { + /** + * Short error description message. + * @type {string} + * @memberof ErrorExceptionResponse + */ + 'message': string; + /** + * Detailed error information. + * @type {string} + * @memberof ErrorExceptionResponse + */ + 'error': string; +} +/** + * + * @export + * @interface InvokeContractRequest + */ +export interface InvokeContractRequest { + /** + * + * @type {PolkadotContractInvocationType} + * @memberof InvokeContractRequest + */ + 'invocationType': PolkadotContractInvocationType; + /** + * + * @type {string} + * @memberof InvokeContractRequest + */ + 'accountAddress': string; + /** + * + * @type {Web3SigningCredential} + * @memberof InvokeContractRequest + */ + 'web3SigningCredential': Web3SigningCredential; + /** + * + * @type {PolkadotTransactionConfigTransferSubmittable} + * @memberof InvokeContractRequest + */ + 'metadata': PolkadotTransactionConfigTransferSubmittable; + /** + * + * @type {string} + * @memberof InvokeContractRequest + */ + 'contractAddress': string; + /** + * The name of the contract method to invoke. + * @type {string} + * @memberof InvokeContractRequest + */ + 'methodName': string; + /** + * + * @type {DeployContractInkRequestGasLimit} + * @memberof InvokeContractRequest + */ + 'gasLimit': DeployContractInkRequestGasLimit; + /** + * + * @type {DeployContractInkRequestStorageDepositLimit} + * @memberof InvokeContractRequest + */ + 'storageDepositLimit'?: DeployContractInkRequestStorageDepositLimit | null; + /** + * + * @type {DeployContractInkRequestBalance} + * @memberof InvokeContractRequest + */ + 'balance'?: DeployContractInkRequestBalance; + /** + * The list of arguments to pass in to the contract method being invoked + * @type {Array} + * @memberof InvokeContractRequest + */ + 'params'?: Array; +} + + +/** + * + * @export + * @interface InvokeContractResponse + */ +export interface InvokeContractResponse { + /** + * + * @type {any} + * @memberof InvokeContractResponse + */ + 'callOutput'?: any; + /** + * + * @type {boolean} + * @memberof InvokeContractResponse + */ + 'success': boolean; + /** + * + * @type {string} + * @memberof InvokeContractResponse + */ + 'txHash'?: string; + /** + * + * @type {string} + * @memberof InvokeContractResponse + */ + 'blockHash'?: string; +} +/** + * + * @export + * @enum {string} + */ + +export const PolkadotContractInvocationType = { + Send: 'SEND', + Query: 'QUERY' +} as const; + +export type PolkadotContractInvocationType = typeof PolkadotContractInvocationType[keyof typeof PolkadotContractInvocationType]; + + +/** + * + * @export + * @interface PolkadotTransactionConfig + */ +export interface PolkadotTransactionConfig { + [key: string]: any; + + /** + * + * @type {PolkadotTransactionConfigTransferSubmittable} + * @memberof PolkadotTransactionConfig + */ + 'transferSubmittable'?: PolkadotTransactionConfigTransferSubmittable; + /** + * + * @type {PolkadotTransactionConfigTransferSubmittable} + * @memberof PolkadotTransactionConfig + */ + 'to'?: PolkadotTransactionConfigTransferSubmittable; + /** + * + * @type {PolkadotTransactionConfigValue} + * @memberof PolkadotTransactionConfig + */ + 'value'?: PolkadotTransactionConfigValue; +} +/** + * @type PolkadotTransactionConfigTransferSubmittable + * @export + */ +export type PolkadotTransactionConfigTransferSubmittable = string; + +/** + * @type PolkadotTransactionConfigValue + * @export + */ +export type PolkadotTransactionConfigValue = number; + +/** + * + * @export + * @interface RawTransactionRequest + */ +export interface RawTransactionRequest { + /** + * + * @type {string} + * @memberof RawTransactionRequest + */ + 'to': string; + /** + * + * @type {number} + * @memberof RawTransactionRequest + */ + 'value': number; +} +/** + * + * @export + * @interface RawTransactionResponse + */ +export interface RawTransactionResponse { + /** + * + * @type {RawTransactionResponseResponseContainer} + * @memberof RawTransactionResponse + */ + 'responseContainer': RawTransactionResponseResponseContainer; +} +/** + * + * @export + * @interface RawTransactionResponseData + */ +export interface RawTransactionResponseData { + /** + * + * @type {string} + * @memberof RawTransactionResponseData + */ + 'rawTransaction': string; +} +/** + * + * @export + * @interface RawTransactionResponseResponseContainer + */ +export interface RawTransactionResponseResponseContainer { + /** + * + * @type {RawTransactionResponseData} + * @memberof RawTransactionResponseResponseContainer + */ + 'response_data': RawTransactionResponseData; + /** + * + * @type {boolean} + * @memberof RawTransactionResponseResponseContainer + */ + 'succeeded': boolean; + /** + * + * @type {string} + * @memberof RawTransactionResponseResponseContainer + */ + 'message': string; + /** + * + * @type {string} + * @memberof RawTransactionResponseResponseContainer + */ + 'error': string | null; +} +/** + * + * @export + * @interface RunTransactionRequest + */ +export interface RunTransactionRequest { + /** + * + * @type {Web3SigningCredential} + * @memberof RunTransactionRequest + */ + 'web3SigningCredential': Web3SigningCredential; + /** + * + * @type {PolkadotTransactionConfig} + * @memberof RunTransactionRequest + */ + 'transactionConfig': PolkadotTransactionConfig; +} +/** + * + * @export + * @interface RunTransactionResponse + */ +export interface RunTransactionResponse { + /** + * + * @type {boolean} + * @memberof RunTransactionResponse + */ + 'success': boolean; + /** + * + * @type {string} + * @memberof RunTransactionResponse + */ + 'txHash'?: string; + /** + * + * @type {string} + * @memberof RunTransactionResponse + */ + 'blockHash'?: string; +} +/** + * + * @export + * @interface SignRawTransactionRequest + */ +export interface SignRawTransactionRequest { + /** + * + * @type {string} + * @memberof SignRawTransactionRequest + */ + 'rawTransaction': string; + /** + * + * @type {string} + * @memberof SignRawTransactionRequest + */ + 'mnemonic': string; + /** + * + * @type {object} + * @memberof SignRawTransactionRequest + */ + 'signingOptions'?: object; +} +/** + * + * @export + * @interface SignRawTransactionResponse + */ +export interface SignRawTransactionResponse { + /** + * + * @type {boolean} + * @memberof SignRawTransactionResponse + */ + 'success': boolean; + /** + * + * @type {string} + * @memberof SignRawTransactionResponse + */ + 'signedTransaction': string; +} +/** + * + * @export + * @interface TransactionInfoRequest + */ +export interface TransactionInfoRequest { + /** + * + * @type {string} + * @memberof TransactionInfoRequest + */ + 'accountAddress': string; + /** + * + * @type {number} + * @memberof TransactionInfoRequest + */ + 'transactionExpiration': number | null; +} +/** + * + * @export + * @interface TransactionInfoResponse + */ +export interface TransactionInfoResponse { + /** + * + * @type {TransactionInfoResponseResponseContainer} + * @memberof TransactionInfoResponse + */ + 'responseContainer': TransactionInfoResponseResponseContainer; +} +/** + * + * @export + * @interface TransactionInfoResponseData + */ +export interface TransactionInfoResponseData { + /** + * + * @type {object} + * @memberof TransactionInfoResponseData + */ + 'nonce': object; + /** + * + * @type {object} + * @memberof TransactionInfoResponseData + */ + 'blockHash': object; + /** + * + * @type {object} + * @memberof TransactionInfoResponseData + */ + 'era': object | null; +} +/** + * + * @export + * @interface TransactionInfoResponseResponseContainer + */ +export interface TransactionInfoResponseResponseContainer { + /** + * + * @type {TransactionInfoResponseData} + * @memberof TransactionInfoResponseResponseContainer + */ + 'response_data': TransactionInfoResponseData; + /** + * + * @type {boolean} + * @memberof TransactionInfoResponseResponseContainer + */ + 'succeeded': boolean; + /** + * + * @type {string} + * @memberof TransactionInfoResponseResponseContainer + */ + 'message': string; + /** + * + * @type {string} + * @memberof TransactionInfoResponseResponseContainer + */ + 'error': string | null; +} +/** + * @type Web3SigningCredential + * @export + */ +export type Web3SigningCredential = Web3SigningCredentialCactusKeychainRef | Web3SigningCredentialMnemonicString | Web3SigningCredentialNone; + +/** + * + * @export + * @interface Web3SigningCredentialCactusKeychainRef + */ +export interface Web3SigningCredentialCactusKeychainRef { + /** + * + * @type {Web3SigningCredentialType} + * @memberof Web3SigningCredentialCactusKeychainRef + */ + 'type': Web3SigningCredentialType; + /** + * The key to use when looking up the the keychain entry holding the secret pointed to by the keychainEntryKey parameter. + * @type {string} + * @memberof Web3SigningCredentialCactusKeychainRef + */ + 'keychainEntryKey': string; + /** + * The keychain ID to use when looking up the the keychain plugin instance that will be used to retrieve the secret pointed to by the keychainEntryKey parameter. + * @type {string} + * @memberof Web3SigningCredentialCactusKeychainRef + */ + 'keychainId': string; +} + + +/** + * + * @export + * @interface Web3SigningCredentialMnemonicString + */ +export interface Web3SigningCredentialMnemonicString { + /** + * + * @type {Web3SigningCredentialType} + * @memberof Web3SigningCredentialMnemonicString + */ + 'type': Web3SigningCredentialType; + /** + * The Polkadot account\'s seed phrase for signing transaction + * @type {string} + * @memberof Web3SigningCredentialMnemonicString + */ + 'mnemonic': string; +} + + +/** + * Using this denotes that there is no signing required because the transaction is pre-signed. + * @export + * @interface Web3SigningCredentialNone + */ +export interface Web3SigningCredentialNone { + /** + * + * @type {Web3SigningCredentialType} + * @memberof Web3SigningCredentialNone + */ + 'type': Web3SigningCredentialType; +} + + +/** + * + * @export + * @enum {string} + */ + +export const Web3SigningCredentialType = { + CactusKeychainRef: 'CACTUS_KEYCHAIN_REF', + MnemonicString: 'MNEMONIC_STRING', + None: 'NONE' +} as const; + +export type Web3SigningCredentialType = typeof Web3SigningCredentialType[keyof typeof Web3SigningCredentialType]; + + + +/** + * DefaultApi - axios parameter creator + * @export + */ +export const DefaultApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Deploys the ink! contract + * @param {DeployContractInkRequest} [deployContractInkRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deployContractInk: async (deployContractInkRequest?: DeployContractInkRequest, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/deploy-contract-ink`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(deployContractInkRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusMetrics: async (options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-prometheus-exporter-metrics`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get raw unsigned transaction + * @param {RawTransactionRequest} [rawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getRawTransaction: async (rawTransactionRequest?: RawTransactionRequest, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-raw-transaction`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(rawTransactionRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Get the necessary Transaction Info for a account + * @param {TransactionInfoRequest} [transactionInfoRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTransactionInfo: async (transactionInfoRequest?: TransactionInfoRequest, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-transaction-info`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(transactionInfoRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Invokes a contract on a polkadot ledger + * @param {InvokeContractRequest} [invokeContractRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + invokeContract: async (invokeContractRequest?: InvokeContractRequest, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/invoke-contract`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(invokeContractRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Executes a transaction on a Polkadot ledger + * @param {RunTransactionRequest} [runTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + runTransaction: async (runTransactionRequest?: RunTransactionRequest, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/run-transaction`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(runTransactionRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary sign the raw transaction + * @param {SignRawTransactionRequest} [signRawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + signRawTransaction: async (signRawTransactionRequest?: SignRawTransactionRequest, options: AxiosRequestConfig = {}): Promise => { + const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/sign-raw-transaction`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(signRawTransactionRequest, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + } +}; + +/** + * DefaultApi - functional programming interface + * @export + */ +export const DefaultApiFp = function(configuration?: Configuration) { + const localVarAxiosParamCreator = DefaultApiAxiosParamCreator(configuration) + return { + /** + * + * @summary Deploys the ink! contract + * @param {DeployContractInkRequest} [deployContractInkRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async deployContractInk(deployContractInkRequest?: DeployContractInkRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.deployContractInk(deployContractInkRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getPrometheusMetrics(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getPrometheusMetrics(options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Get raw unsigned transaction + * @param {RawTransactionRequest} [rawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getRawTransaction(rawTransactionRequest?: RawTransactionRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getRawTransaction(rawTransactionRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Get the necessary Transaction Info for a account + * @param {TransactionInfoRequest} [transactionInfoRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTransactionInfo(transactionInfoRequest?: TransactionInfoRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.getTransactionInfo(transactionInfoRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Invokes a contract on a polkadot ledger + * @param {InvokeContractRequest} [invokeContractRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async invokeContract(invokeContractRequest?: InvokeContractRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.invokeContract(invokeContractRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary Executes a transaction on a Polkadot ledger + * @param {RunTransactionRequest} [runTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async runTransaction(runTransactionRequest?: RunTransactionRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.runTransaction(runTransactionRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + /** + * + * @summary sign the raw transaction + * @param {SignRawTransactionRequest} [signRawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async signRawTransaction(signRawTransactionRequest?: SignRawTransactionRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.signRawTransaction(signRawTransactionRequest, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, + } +}; + +/** + * DefaultApi - factory interface + * @export + */ +export const DefaultApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) { + const localVarFp = DefaultApiFp(configuration) + return { + /** + * + * @summary Deploys the ink! contract + * @param {DeployContractInkRequest} [deployContractInkRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deployContractInk(deployContractInkRequest?: DeployContractInkRequest, options?: any): AxiosPromise { + return localVarFp.deployContractInk(deployContractInkRequest, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getPrometheusMetrics(options?: any): AxiosPromise { + return localVarFp.getPrometheusMetrics(options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get raw unsigned transaction + * @param {RawTransactionRequest} [rawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getRawTransaction(rawTransactionRequest?: RawTransactionRequest, options?: any): AxiosPromise { + return localVarFp.getRawTransaction(rawTransactionRequest, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Get the necessary Transaction Info for a account + * @param {TransactionInfoRequest} [transactionInfoRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTransactionInfo(transactionInfoRequest?: TransactionInfoRequest, options?: any): AxiosPromise { + return localVarFp.getTransactionInfo(transactionInfoRequest, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Invokes a contract on a polkadot ledger + * @param {InvokeContractRequest} [invokeContractRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + invokeContract(invokeContractRequest?: InvokeContractRequest, options?: any): AxiosPromise { + return localVarFp.invokeContract(invokeContractRequest, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary Executes a transaction on a Polkadot ledger + * @param {RunTransactionRequest} [runTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + runTransaction(runTransactionRequest?: RunTransactionRequest, options?: any): AxiosPromise { + return localVarFp.runTransaction(runTransactionRequest, options).then((request) => request(axios, basePath)); + }, + /** + * + * @summary sign the raw transaction + * @param {SignRawTransactionRequest} [signRawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + signRawTransaction(signRawTransactionRequest?: SignRawTransactionRequest, options?: any): AxiosPromise { + return localVarFp.signRawTransaction(signRawTransactionRequest, options).then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * DefaultApi - object-oriented interface + * @export + * @class DefaultApi + * @extends {BaseAPI} + */ +export class DefaultApi extends BaseAPI { + /** + * + * @summary Deploys the ink! contract + * @param {DeployContractInkRequest} [deployContractInkRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public deployContractInk(deployContractInkRequest?: DeployContractInkRequest, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).deployContractInk(deployContractInkRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get the Prometheus Metrics + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getPrometheusMetrics(options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).getPrometheusMetrics(options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get raw unsigned transaction + * @param {RawTransactionRequest} [rawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getRawTransaction(rawTransactionRequest?: RawTransactionRequest, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).getRawTransaction(rawTransactionRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Get the necessary Transaction Info for a account + * @param {TransactionInfoRequest} [transactionInfoRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public getTransactionInfo(transactionInfoRequest?: TransactionInfoRequest, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).getTransactionInfo(transactionInfoRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Invokes a contract on a polkadot ledger + * @param {InvokeContractRequest} [invokeContractRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public invokeContract(invokeContractRequest?: InvokeContractRequest, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).invokeContract(invokeContractRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary Executes a transaction on a Polkadot ledger + * @param {RunTransactionRequest} [runTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public runTransaction(runTransactionRequest?: RunTransactionRequest, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).runTransaction(runTransactionRequest, options).then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @summary sign the raw transaction + * @param {SignRawTransactionRequest} [signRawTransactionRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof DefaultApi + */ + public signRawTransaction(signRawTransactionRequest?: SignRawTransactionRequest, options?: AxiosRequestConfig) { + return DefaultApiFp(this.configuration).signRawTransaction(signRawTransactionRequest, options).then((request) => request(this.axios, this.basePath)); + } +} + + diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/base.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/base.ts new file mode 100644 index 00000000000..15c10077e03 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/base.ts @@ -0,0 +1,72 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Connector Polkadot + * Can perform basic tasks on a Polkadot parachain + * + * The version of the OpenAPI document: v2.0.0-alpha.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from './configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from 'axios'; +import globalAxios from 'axios'; + +export const BASE_PATH = "http://localhost".replace(/\/+$/, ""); + +/** + * + * @export + */ +export const COLLECTION_FORMATS = { + csv: ",", + ssv: " ", + tsv: "\t", + pipes: "|", +}; + +/** + * + * @export + * @interface RequestArgs + */ +export interface RequestArgs { + url: string; + options: AxiosRequestConfig; +} + +/** + * + * @export + * @class BaseAPI + */ +export class BaseAPI { + protected configuration: Configuration | undefined; + + constructor(configuration?: Configuration, protected basePath: string = BASE_PATH, protected axios: AxiosInstance = globalAxios) { + if (configuration) { + this.configuration = configuration; + this.basePath = configuration.basePath || this.basePath; + } + } +}; + +/** + * + * @export + * @class RequiredError + * @extends {Error} + */ +export class RequiredError extends Error { + constructor(public field: string, msg?: string) { + super(msg); + this.name = "RequiredError" + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/common.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/common.ts new file mode 100644 index 00000000000..c9590939d0e --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/common.ts @@ -0,0 +1,150 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Connector Polkadot + * Can perform basic tasks on a Polkadot parachain + * + * The version of the OpenAPI document: v2.0.0-alpha.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +import type { Configuration } from "./configuration"; +import type { RequestArgs } from "./base"; +import type { AxiosInstance, AxiosResponse } from 'axios'; +import { RequiredError } from "./base"; + +/** + * + * @export + */ +export const DUMMY_BASE_URL = 'https://example.com' + +/** + * + * @throws {RequiredError} + * @export + */ +export const assertParamExists = function (functionName: string, paramName: string, paramValue: unknown) { + if (paramValue === null || paramValue === undefined) { + throw new RequiredError(paramName, `Required parameter ${paramName} was null or undefined when calling ${functionName}.`); + } +} + +/** + * + * @export + */ +export const setApiKeyToObject = async function (object: any, keyParamName: string, configuration?: Configuration) { + if (configuration && configuration.apiKey) { + const localVarApiKeyValue = typeof configuration.apiKey === 'function' + ? await configuration.apiKey(keyParamName) + : await configuration.apiKey; + object[keyParamName] = localVarApiKeyValue; + } +} + +/** + * + * @export + */ +export const setBasicAuthToObject = function (object: any, configuration?: Configuration) { + if (configuration && (configuration.username || configuration.password)) { + object["auth"] = { username: configuration.username, password: configuration.password }; + } +} + +/** + * + * @export + */ +export const setBearerAuthToObject = async function (object: any, configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const accessToken = typeof configuration.accessToken === 'function' + ? await configuration.accessToken() + : await configuration.accessToken; + object["Authorization"] = "Bearer " + accessToken; + } +} + +/** + * + * @export + */ +export const setOAuthToObject = async function (object: any, name: string, scopes: string[], configuration?: Configuration) { + if (configuration && configuration.accessToken) { + const localVarAccessTokenValue = typeof configuration.accessToken === 'function' + ? await configuration.accessToken(name, scopes) + : await configuration.accessToken; + object["Authorization"] = "Bearer " + localVarAccessTokenValue; + } +} + +function setFlattenedQueryParams(urlSearchParams: URLSearchParams, parameter: any, key: string = ""): void { + if (parameter == null) return; + if (typeof parameter === "object") { + if (Array.isArray(parameter)) { + (parameter as any[]).forEach(item => setFlattenedQueryParams(urlSearchParams, item, key)); + } + else { + Object.keys(parameter).forEach(currentKey => + setFlattenedQueryParams(urlSearchParams, parameter[currentKey], `${key}${key !== '' ? '.' : ''}${currentKey}`) + ); + } + } + else { + if (urlSearchParams.has(key)) { + urlSearchParams.append(key, parameter); + } + else { + urlSearchParams.set(key, parameter); + } + } +} + +/** + * + * @export + */ +export const setSearchParams = function (url: URL, ...objects: any[]) { + const searchParams = new URLSearchParams(url.search); + setFlattenedQueryParams(searchParams, objects); + url.search = searchParams.toString(); +} + +/** + * + * @export + */ +export const serializeDataIfNeeded = function (value: any, requestOptions: any, configuration?: Configuration) { + const nonString = typeof value !== 'string'; + const needsSerialization = nonString && configuration && configuration.isJsonMime + ? configuration.isJsonMime(requestOptions.headers['Content-Type']) + : nonString; + return needsSerialization + ? JSON.stringify(value !== undefined ? value : {}) + : (value || ""); +} + +/** + * + * @export + */ +export const toPathString = function (url: URL) { + return url.pathname + url.search + url.hash +} + +/** + * + * @export + */ +export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) { + return >(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url}; + return axios.request(axiosRequestArgs); + }; +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/configuration.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/configuration.ts new file mode 100644 index 00000000000..b8927c55bd0 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/configuration.ts @@ -0,0 +1,101 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Connector Polkadot + * Can perform basic tasks on a Polkadot parachain + * + * The version of the OpenAPI document: v2.0.0-alpha.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface ConfigurationParameters { + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + username?: string; + password?: string; + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + basePath?: string; + baseOptions?: any; + formDataCtor?: new () => any; +} + +export class Configuration { + /** + * parameter for apiKey security + * @param name security name + * @memberof Configuration + */ + apiKey?: string | Promise | ((name: string) => string) | ((name: string) => Promise); + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + username?: string; + /** + * parameter for basic security + * + * @type {string} + * @memberof Configuration + */ + password?: string; + /** + * parameter for oauth2 security + * @param name security name + * @param scopes oauth2 scope + * @memberof Configuration + */ + accessToken?: string | Promise | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise); + /** + * override base path + * + * @type {string} + * @memberof Configuration + */ + basePath?: string; + /** + * base options for axios calls + * + * @type {any} + * @memberof Configuration + */ + baseOptions?: any; + /** + * The FormData constructor that will be used to create multipart form data + * requests. You can inject this here so that execution environments that + * do not support the FormData class can still run the generated client. + * + * @type {new () => FormData} + */ + formDataCtor?: new () => any; + + constructor(param: ConfigurationParameters = {}) { + this.apiKey = param.apiKey; + this.username = param.username; + this.password = param.password; + this.accessToken = param.accessToken; + this.basePath = param.basePath; + this.baseOptions = param.baseOptions; + this.formDataCtor = param.formDataCtor; + } + + /** + * Check if the given MIME is a JSON MIME. + * JSON MIME examples: + * application/json + * application/json; charset=UTF8 + * APPLICATION/JSON + * application/vnd.company+json + * @param mime - MIME (Multipurpose Internet Mail Extensions) + * @return True if the given MIME is JSON, false otherwise. + */ + public isJsonMime(mime: string): boolean { + const jsonMime: RegExp = new RegExp('^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$', 'i'); + return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === 'application/json-patch+json'); + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/index.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/index.ts new file mode 100644 index 00000000000..5e9005e050e --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/generated/openapi/typescript-axios/index.ts @@ -0,0 +1,18 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Hyperledger Cactus Plugin - Connector Polkadot + * Can perform basic tasks on a Polkadot parachain + * + * The version of the OpenAPI document: v2.0.0-alpha.2 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export * from "./api"; +export * from "./configuration"; + diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/index.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/index.ts new file mode 100644 index 00000000000..87cb558397c --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/index.ts @@ -0,0 +1 @@ +export * from "./public-api"; diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/index.web.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/index.web.ts new file mode 100644 index 00000000000..cb0ff5c3b54 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/index.web.ts @@ -0,0 +1 @@ +export {}; diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/model-type-guards.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/model-type-guards.ts new file mode 100644 index 00000000000..e5bfc5822f8 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/model-type-guards.ts @@ -0,0 +1,24 @@ +import { + Web3SigningCredentialNone, + Web3SigningCredentialMnemonicString, + Web3SigningCredentialType, + Web3SigningCredentialCactusKeychainRef, +} from "./generated/openapi/typescript-axios/api"; + +export function isWeb3SigningCredentialMnemonicString(x?: { + type?: Web3SigningCredentialType; +}): x is Web3SigningCredentialMnemonicString { + return x?.type === Web3SigningCredentialType.MnemonicString; +} + +export function isWeb3SigningCredentialCactusRef(x?: { + type?: Web3SigningCredentialType; +}): x is Web3SigningCredentialCactusKeychainRef { + return x?.type === Web3SigningCredentialType.CactusKeychainRef; +} + +export function isWeb3SigningCredentialNone(x?: { + type?: Web3SigningCredentialType; +}): x is Web3SigningCredentialNone { + return x?.type === Web3SigningCredentialType.None; +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-factory-ledger-connector-polkadot.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-factory-ledger-connector-polkadot.ts new file mode 100644 index 00000000000..ea2db2248d6 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-factory-ledger-connector-polkadot.ts @@ -0,0 +1,21 @@ +import { + IPluginFactoryOptions, + PluginFactory, +} from "@hyperledger/cactus-core-api"; + +import { + IPluginLedgerConnectorPolkadotOptions, + PluginLedgerConnectorPolkadot, +} from "./plugin-ledger-connector-polkadot"; + +export class PluginFactoryLedgerConnector extends PluginFactory< + PluginLedgerConnectorPolkadot, + IPluginLedgerConnectorPolkadotOptions, + IPluginFactoryOptions +> { + async create( + pluginOptions: IPluginLedgerConnectorPolkadotOptions, + ): Promise { + return new PluginLedgerConnectorPolkadot(pluginOptions); + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts new file mode 100644 index 00000000000..cdab9b5236b --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/plugin-ledger-connector-polkadot.ts @@ -0,0 +1,925 @@ +import { Server } from "http"; +import { Server as SecureServer } from "https"; +import { Express } from "express"; +import { ApiPromise, Keyring } from "@polkadot/api"; +import { WsProvider } from "@polkadot/rpc-provider/ws"; +import { WeightV2 } from "@polkadot/types/interfaces"; +import { CodePromise, Abi, ContractPromise } from "@polkadot/api-contract"; +import { isHex, stringCamelCase } from "@polkadot/util"; +import { PrometheusExporter } from "./prometheus-exporter/prometheus-exporter"; +import { + GetPrometheusMetricsEndpoint, + IGetPrometheusMetricsEndpointOptions, +} from "./web-services/get-prometheus-exporter-metrics-endpoint"; + +import "multer"; +import { Optional } from "typescript-optional"; + +import OAS from "../json/openapi.json"; + +import { + consensusHasTransactionFinality, + PluginRegistry, +} from "@hyperledger/cactus-core"; + +import { + IPluginLedgerConnector, + ConsensusAlgorithmFamily, + IPluginWebService, + IWebServiceEndpoint, + ICactusPlugin, + ICactusPluginOptions, +} from "@hyperledger/cactus-core-api"; + +import { + Logger, + Checks, + LogLevelDesc, + LoggerProvider, +} from "@hyperledger/cactus-common"; +import { promisify } from "util"; +import { + DeployContractInkRequest, + DeployContractInkResponse, + InvokeContractRequest, + InvokeContractResponse, + PolkadotContractInvocationType, + RawTransactionRequest, + RawTransactionResponse, + RunTransactionRequest, + RunTransactionResponse, + SignRawTransactionRequest, + SignRawTransactionResponse, + TransactionInfoRequest, + TransactionInfoResponse, + Web3SigningCredential, + Web3SigningCredentialCactusKeychainRef, + Web3SigningCredentialMnemonicString, + Web3SigningCredentialType, +} from "./generated/openapi/typescript-axios/index"; +import { + GetTransactionInfoEndpoint, + IGetTransactionInfoEndpointOptions, +} from "./web-services/get-transaction-info-endpoint"; + +import { + RunTransactionEndpoint, + IRunTransactionEndpointOptions, +} from "./web-services/run-transaction-endpoint"; +import { + GetRawTransactionEndpoint, + IGetRawTransactionEndpointOptions, +} from "./web-services/get-raw-transaction-endpoint"; +import { + ISignRawTransactionEndpointOptions, + SignRawTransactionEndpoint, +} from "./web-services/sign-raw-transaction-endpoint"; +import { + DeployContractInkEndpoint, + IDeployContractInkEndpointOptions, +} from "./web-services/deploy-contract-ink-endpoint"; +import { + isWeb3SigningCredentialCactusRef, + isWeb3SigningCredentialMnemonicString, + isWeb3SigningCredentialNone, +} from "./model-type-guards"; +import { + IInvokeContractEndpointOptions, + InvokeContractEndpoint, +} from "./web-services/invoke-contract-endpoint"; +import createHttpError from "http-errors"; + +export interface IPluginLedgerConnectorPolkadotOptions + extends ICactusPluginOptions { + logLevel?: LogLevelDesc; + pluginRegistry?: PluginRegistry; + prometheusExporter?: PrometheusExporter; + wsProviderUrl: string; + instanceId: string; + autoConnect?: boolean; +} + +export class PluginLedgerConnectorPolkadot + implements + IPluginLedgerConnector< + DeployContractInkRequest, + DeployContractInkResponse, + RunTransactionRequest, + RunTransactionResponse + >, + ICactusPlugin, + IPluginWebService +{ + public static readonly CLASS_NAME = "PluginLedgerConnectorPolkadot"; + private readonly instanceId: string; + private readonly log: Logger; + private readonly pluginRegistry: PluginRegistry; + public wsProvider: WsProvider | undefined; + public api: ApiPromise | undefined; + public prometheusExporter: PrometheusExporter; + private endpoints: IWebServiceEndpoint[] | undefined; + private autoConnect: false | number | undefined; + + public getOpenApiSpec(): unknown { + return OAS; + } + + public get className(): string { + return PluginLedgerConnectorPolkadot.CLASS_NAME; + } + + constructor(public readonly opts: IPluginLedgerConnectorPolkadotOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(opts, `${fnTag} arg options`); + if (typeof opts.logLevel !== "undefined") { + Checks.truthy(opts.logLevel, `${fnTag} options.logLevelDesc`); + } + Checks.truthy(opts.wsProviderUrl, `${fnTag} options.wsProviderUrl`); + Checks.truthy(opts.instanceId, `${fnTag} options.instanceId`); + this.pluginRegistry = opts.pluginRegistry || new PluginRegistry({}); + this.prometheusExporter = + opts.prometheusExporter || + new PrometheusExporter({ pollingIntervalInMin: 1 }); + Checks.truthy( + this.prometheusExporter, + `${fnTag} options.prometheusExporter`, + ); + + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + + this.instanceId = opts.instanceId; + if (opts.autoConnect) { + this.autoConnect = 1; + } + this.setProvider(opts.wsProviderUrl); + this.prometheusExporter.startMetricsCollection(); + } + + public setProvider(wsProviderUrl: string): void { + try { + this.wsProvider = new WsProvider(wsProviderUrl, this.autoConnect); + } catch (err) { + const errorMessage = `Could not create wsProvider. InnerException: + ${err}`; + throw createHttpError[500](errorMessage); + } + } + + public async getOrCreateWebServices(): Promise { + if (Array.isArray(this.endpoints)) { + return this.endpoints; + } + + const { log } = this; + log.info(`Installing web services for plugin ${this.getPackageName()}...`); + + const endpoints: IWebServiceEndpoint[] = []; + { + const opts: IGetPrometheusMetricsEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new GetPrometheusMetricsEndpoint(opts); + endpoints.push(endpoint); + } + { + const opts: IGetTransactionInfoEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new GetTransactionInfoEndpoint(opts); + endpoints.push(endpoint); + } + { + const opts: IRunTransactionEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new RunTransactionEndpoint(opts); + endpoints.push(endpoint); + } + { + const opts: IGetRawTransactionEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new GetRawTransactionEndpoint(opts); + endpoints.push(endpoint); + } + { + const opts: ISignRawTransactionEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new SignRawTransactionEndpoint(opts); + endpoints.push(endpoint); + } + { + const opts: IDeployContractInkEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new DeployContractInkEndpoint(opts); + endpoints.push(endpoint); + } + { + const opts: IInvokeContractEndpointOptions = { + connector: this, + logLevel: this.opts.logLevel, + }; + + const endpoint = new InvokeContractEndpoint(opts); + endpoints.push(endpoint); + } + + this.endpoints = endpoints; + + const pkg = this.getPackageName(); + log.info(`Installed web services for plugin ${pkg} OK`, { endpoints }); + return endpoints; + } + + async registerWebServices(app: Express): Promise { + const webServices = await this.getOrCreateWebServices(); + await Promise.all(webServices.map((ws) => ws.registerExpress(app))); + return webServices; + } + + public async shutdown(): Promise { + const serverMaybe = this.getHttpServer(); + if (serverMaybe.isPresent()) { + const server = serverMaybe.get(); + await promisify(server.close.bind(server))(); + } + } + + public getInstanceId(): string { + return this.instanceId; + } + + public getPackageName(): string { + return `@hyperledger/cactus-plugin-ledger-connector-polkadot`; + } + + public getHttpServer(): Optional { + return Optional.empty(); + } + + public async onPluginInit(): Promise { + try { + this.api = await ApiPromise.create({ provider: this.wsProvider }); + } catch (err) { + const errorMessage = `Could not create API. InnerException: + ${err}`; + throw createHttpError[500](errorMessage); + } + } + + public async getConsensusAlgorithmFamily(): Promise { + return ConsensusAlgorithmFamily.Stake; + } + + public async hasTransactionFinality(): Promise { + const currentConsensusAlgorithmFamily = + await this.getConsensusAlgorithmFamily(); + + return consensusHasTransactionFinality(currentConsensusAlgorithmFamily); + } + + public rawTransaction(req: RawTransactionRequest): RawTransactionResponse { + const fnTag = `${this.className}#rawTx()`; + Checks.truthy(req, `${fnTag} req`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + try { + const accountAddress = req.to; + const transferValue = req.value; + const rawTransaction = this.api.tx.balances.transferAllowDeath( + accountAddress, + transferValue, + ); + const responseContainer = { + response_data: { + rawTransaction: rawTransaction.toHex(), + }, + succeeded: true, + message: "obtainRawTransaction", + error: null, + }; + + const response: RawTransactionResponse = { + responseContainer: responseContainer, + }; + return response; + } catch (err) { + const errorMessage = + `${fnTag} Obtaining raw transaction has failed. ` + + `InnerException: ${err}`; + throw createHttpError[500](errorMessage); + } + } + + public async signTransaction( + req: SignRawTransactionRequest, + ): Promise { + const fnTag = `${this.className}#signTx()`; + Checks.truthy(req, `${fnTag} req`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + try { + const keyring = new Keyring({ type: "sr25519" }); + const accountPair = keyring.createFromUri(req.mnemonic); + const deserializedRawTransaction = this.api.tx(req.rawTransaction); + const signedTransaction = await deserializedRawTransaction.signAsync( + accountPair, + req.signingOptions, + ); + const serializedSignedTransaction = signedTransaction.toHex(); + const response: SignRawTransactionResponse = { + success: true, + signedTransaction: serializedSignedTransaction, + }; + return response; + } catch (err) { + const errorMessage = + `${fnTag} signing raw transaction has failed. ` + + `InnerException: ${err}`; + throw createHttpError[500](errorMessage); + } + } + + // Perform a monetary transaction to Polkadot; + public async transact( + req: RunTransactionRequest, + ): Promise { + const fnTag = `${this.className}#transact()`; + switch (req.web3SigningCredential.type) { + case Web3SigningCredentialType.CactusKeychainRef: { + return this.transactCactusKeychainRef(req); + } + case Web3SigningCredentialType.MnemonicString: { + return this.transactMnemonicString(req); + } + case Web3SigningCredentialType.None: { + if (req.transactionConfig.transferSubmittable) { + return this.transactSigned(req); + } else { + const errorMessage = + `${fnTag} Expected pre-signed raw transaction ` + + ` since signing credential is specified as` + + `Web3SigningCredentialType.NONE`; + throw createHttpError[400](errorMessage); + } + } + default: { + const errorMessage = + `${fnTag} Unrecognized Web3SigningCredentialType: ` + + `Supported ones are: ` + + `${Object.values(Web3SigningCredentialType).join(";")}`; + throw createHttpError[400](errorMessage); + } + } + } + public async transactCactusKeychainRef( + req: RunTransactionRequest, + ): Promise { + const fnTag = `${this.className}#transactCactusKeychainRef()`; + const { transactionConfig, web3SigningCredential } = req; + const { keychainEntryKey, keychainId } = + web3SigningCredential as Web3SigningCredentialCactusKeychainRef; + + // locate the keychain plugin that has access to the keychain backend + // denoted by the keychainID from the request. + const keychainPlugin = this.pluginRegistry.findOneByKeychainId(keychainId); + + Checks.truthy(keychainPlugin, `${fnTag} keychain for ID:"${keychainId}"`); + + // Now use the found keychain plugin to actually perform the lookup of + // the private key that we need to run the transaction. + const mnemonic = await keychainPlugin?.get(keychainEntryKey); + return this.transactMnemonicString({ + web3SigningCredential: { + type: Web3SigningCredentialType.MnemonicString, + mnemonic, + }, + transactionConfig, + }); + } + public async transactMnemonicString( + req: RunTransactionRequest, + ): Promise { + const fnTag = `${this.className}#transactMnemonicString()`; + Checks.truthy(req, `${fnTag} req`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + const { transactionConfig, web3SigningCredential } = req; + const { mnemonic } = + web3SigningCredential as Web3SigningCredentialMnemonicString; + if (!mnemonic) { + throw createHttpError[400]( + `cannot perform transaction without mnemonic string`, + ); + } + let success = false; + const keyring = new Keyring({ type: "sr25519" }); + const accountPair = keyring.createFromUri(mnemonic); + const accountAddress = transactionConfig.to; + const transferValue = transactionConfig.value; + const txResult = await new Promise<{ + success: boolean; + transactionHash: string; + blockhash: string; + }>((resolve, reject) => { + if (!this.api) { + reject("transaction not successful"); + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + this.api.tx.balances + .transferAllowDeath(accountAddress, transferValue) + .signAndSend(accountPair, ({ status, txHash, dispatchError }) => { + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + if (status.isInBlock) { + if (dispatchError) { + reject("transaction not successful"); + if (dispatchError.isModule) { + const decoded = this.api.registry.findMetaError( + dispatchError.asModule, + ); + const { docs, name, section } = decoded; + throw createHttpError[400]( + `${section}.${name}: ${docs.join(" ")}`, + ); + } else { + throw createHttpError[400](dispatchError.toString()); + } + } + this.prometheusExporter.addCurrentTransaction(); + resolve({ + success: true, + blockhash: status.asInBlock.toHex(), + transactionHash: txHash.toHex(), + }); + } + }); + }); + success = txResult.success; + const transactionHash = txResult.transactionHash; + const blockHash = txResult.blockhash; + return { + success, + txHash: transactionHash, + blockHash: blockHash, + }; + } + public async transactSigned( + req: RunTransactionRequest, + ): Promise { + const fnTag = `${this.className}#transactSigned()`; + Checks.truthy( + req.transactionConfig.transferSubmittable, + `${fnTag}:req.transactionConfig.transferSubmittable`, + ); + const signedTx = req.transactionConfig.transferSubmittable as string; + + this.log.debug( + "Starting api.rpc.author.submitAndWatchExtrinsic(transferSubmittable) ", + ); + let success = false; + Checks.truthy(req, `${fnTag} req`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + const deserializedTransaction = this.api.tx(signedTx); + const signature = deserializedTransaction.signature.toHex(); + if (!signature) { + throw createHttpError[400](`${fnTag} Transaction is not signed.`); + } + + if (!isHex(signature)) { + throw createHttpError[400]( + `${fnTag} Transaction signature is not valid.`, + ); + } + + const txResult = await new Promise<{ + success: boolean; + transactionHash: string; + blockhash: string; + }>((resolve, reject) => { + if (!this.api) { + reject("transaction not successful"); + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + this.api.rpc.author.submitAndWatchExtrinsic( + deserializedTransaction, + ({ isInBlock, hash, asInBlock, type }) => { + if (isInBlock) { + this.prometheusExporter.addCurrentTransaction(); + resolve({ + success: true, + blockhash: asInBlock.toHex(), + transactionHash: hash.toHex(), + }); + } else { + reject("transaction not successful"); + const errorMessage = `transaction not submitted with status: ${type}`; + throw new createHttpError[400](errorMessage); + } + }, + ); + }); + + success = txResult.success; + const txHash = txResult.transactionHash; + const blockHash = txResult.blockhash; + return { success, txHash, blockHash }; + } + + private async getMnemonicStringFromWeb3SigningCredential( + fnTag: string, + type: "deploy" | "invoke", + web3SigningCredential: Web3SigningCredential, + ): Promise { + if (isWeb3SigningCredentialNone(web3SigningCredential)) { + throw createHttpError[400]( + `${fnTag} Cannot ${type} contract with pre-signed TX`, + ); + } + let mnemonic: string; + if (isWeb3SigningCredentialMnemonicString(web3SigningCredential)) { + const Credential = + web3SigningCredential as Web3SigningCredentialMnemonicString; + mnemonic = Credential.mnemonic; + if (!mnemonic) { + const errorMessage = `${fnTag} Cannot ${type} contract without mnemonic string.`; + throw createHttpError[400](errorMessage); + } + return mnemonic; + } else if (isWeb3SigningCredentialCactusRef(web3SigningCredential)) { + const Credential = + web3SigningCredential as Web3SigningCredentialCactusKeychainRef; + const { keychainEntryKey, keychainId } = Credential; + if (!keychainId || !keychainEntryKey) { + const errorMessage = `${fnTag} Cannot ${type} contract without keychainId and the keychainEntryKey.`; + throw createHttpError[400](errorMessage); + } + // locate the keychain plugin that has access to the keychain backend + // denoted by the keychainID from the request. + const keychainPlugin = + this.pluginRegistry.findOneByKeychainId(keychainId); + if (!keychainPlugin) { + const errorMessage = + `${fnTag} The plugin registry does not contain` + + ` a keychain plugin for ID:"${keychainId}"`; + throw createHttpError[400](errorMessage); + } + // Now use the found keychain plugin to actually perform the lookup of + // the private key that we need to run the transaction. + mnemonic = await keychainPlugin.get(keychainEntryKey); + if (!mnemonic) { + const errorMessage = + `${fnTag} Cannot ${type} contract because` + + `the mnemonic string does not exist on the keychain`; + throw new createHttpError[400](errorMessage); + } + return mnemonic; + } else { + const errorMessage = + `${fnTag} Unrecognized Web3SigningCredentialType: ` + + `Supported ones are: ` + + `${Object.values(Web3SigningCredentialType).join(";")}`; + throw createHttpError[400](errorMessage); + } + } + + // Deploy and instantiate a smart contract in Polkadot + public async deployContract( + req: DeployContractInkRequest, + ): Promise { + const fnTag = `${this.className}#deployContract()`; + Checks.truthy(req, `${fnTag} req`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + const mnemonic = await this.getMnemonicStringFromWeb3SigningCredential( + fnTag, + "deploy", + req.web3SigningCredential, + ); + let success = false; + const contractAbi = new Abi( + req.metadata, + this.api.registry.getChainProperties(), + ); + const contractCode = new CodePromise( + this.api, + contractAbi, + Buffer.from(req.wasm, "base64"), + ); + const gasLimit: WeightV2 = this.api.registry.createType("WeightV2", { + refTime: req.gasLimit.refTime, + proofSize: req.gasLimit.proofSize, + }); + const keyring = new Keyring({ type: "sr25519" }); + const accountPair = keyring.createFromUri(mnemonic); + const params = req.params ?? []; + const constructorMethod = req.constructorMethod ?? "new"; + const tx = contractCode.tx[stringCamelCase(constructorMethod)]( + { + gasLimit, + storageDepositLimit: req.storageDepositLimit, + salt: req.salt, + value: req.balance, + }, + ...params, + ); + const txResult = await new Promise<{ + success: boolean; + address: string | undefined; + }>((resolve, reject) => { + tx.signAndSend( + accountPair, + //https://github.com/polkadot-js/api/issues/5722 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + ({ contract, status, dispatchError }) => { + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + if (status.isInBlock || status.isFinalized) { + if (dispatchError) { + reject("deployment not successful"); + if (dispatchError.isModule) { + const decoded = this.api.registry.findMetaError( + dispatchError.asModule, + ); + const { docs, name, section } = decoded; + throw createHttpError[400]( + `${section}.${name}: ${docs.join(" ")}`, + ); + } else { + throw createHttpError[400](dispatchError.toString()); + } + } + this.prometheusExporter.addCurrentTransaction(); + resolve({ + success: true, + address: contract.address.toString(), + }); + } + }, + ); + }); + success = txResult.success; + const contractAddress = txResult.address; + return { + success: success, + contractAddress: contractAddress, + }; + } + + public async isSafeToCallContractMethod( + abi: Abi, + name: string, + ): Promise { + Checks.truthy(abi, `${this.className}#isSafeToCallContractMethod():abi`); + Checks.truthy( + abi.messages, + `${this.className}#isSafeToCallContractMethod():abi.messages`, + ); + Checks.nonBlankString( + name, + `${this.className}#isSafeToCallContractMethod():name`, + ); + const methods = abi.messages.map((m) => m.method); + return methods.includes(name); + } + + // invoke the smart contract + public async invokeContract( + req: InvokeContractRequest, + ): Promise { + const fnTag = `${this.className}#invokeContract()`; + Checks.truthy(req, `${fnTag} req`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + const contractAbi = new Abi( + req.metadata, + this.api.registry.getChainProperties(), + ); + const methodName = stringCamelCase(req.methodName); + const isSafeToCall = await this.isSafeToCallContractMethod( + contractAbi, + methodName, + ); + if (!isSafeToCall) { + throw createHttpError[400]( + `Invalid method name provided in request. ${req.methodName} does not exist on the contract abi.messages object's "method" property.`, + ); + } + const contract = new ContractPromise( + this.api, + req.metadata, + req.contractAddress, + ); + const gasLimit: WeightV2 = this.api.registry.createType("WeightV2", { + refTime: req.gasLimit.refTime, + proofSize: req.gasLimit.proofSize, + }); + if (req.invocationType === PolkadotContractInvocationType.Query) { + let success = false; + const params = req.params ?? []; + const query = contract.query[methodName]( + req.accountAddress, + { + gasLimit, + storageDepositLimit: req.storageDepositLimit, + value: req.balance, + }, + ...params, + ); + const callOutput = await query; + success = true; + return { success, callOutput }; + } else if (req.invocationType === PolkadotContractInvocationType.Send) { + const mnemonic = await this.getMnemonicStringFromWeb3SigningCredential( + fnTag, + "invoke", + req.web3SigningCredential, + ); + const keyring = new Keyring({ type: "sr25519" }); + const accountPair = keyring.createFromUri(mnemonic); + let success = false; + const params = req.params ?? []; + const tx = contract.tx[methodName]( + { + gasLimit, + storageDepositLimit: req.storageDepositLimit, + value: req.balance, + }, + ...params, + ); + const txResult = await new Promise<{ + success: boolean; + transactionHash: string; + blockHash: string; + }>((resolve, reject) => { + tx.signAndSend(accountPair, ({ status, txHash, dispatchError }) => { + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + if (status.isInBlock || status.isFinalized) { + if (dispatchError) { + reject("TX not successful"); + if (dispatchError.isModule) { + const decoded = this.api.registry.findMetaError( + dispatchError.asModule, + ); + const { docs, name, section } = decoded; + throw createHttpError[400]( + `${section}.${name}: ${docs.join(" ")}`, + ); + } else { + throw createHttpError[400](dispatchError.toString()); + } + } + this.prometheusExporter.addCurrentTransaction(); + resolve({ + success: true, + transactionHash: txHash.toHex(), + blockHash: status.asInBlock.toHex(), + }); + } + }); + }); + success = txResult.success; + const txHash = txResult.transactionHash; + const blockHash = txResult.blockHash; + return { success, txHash, blockHash }; + } else { + throw createHttpError[400]( + `${fnTag} Unsupported invocation type ${req.invocationType}`, + ); + } + } + + public getPrometheusExporter(): PrometheusExporter { + return this.prometheusExporter; + } + + public async getPrometheusExporterMetrics(): Promise { + const fnTag = `${this.className}#getPrometheusExporterMetrics()`; + try { + const res: string = await this.prometheusExporter.getPrometheusMetrics(); + this.log.debug(`getPrometheusExporterMetrics() response: %o`, res); + return res; + } catch (err) { + throw createHttpError[500]( + `${fnTag} Obtaining Prometheus Exporter Metrics has failed. ` + + `InnerException: ${err}`, + ); + } + } + + // Obtains information to sign a transaction + public async obtainTransactionInformation( + req: TransactionInfoRequest, + ): Promise { + const fnTag = `${this.className}#obtainTxInformation()`; + Checks.truthy(req, `${fnTag} req`); + this.log.info(`getTxFee`); + if (!this.api) { + throw createHttpError[400]( + `The operation has failed because the API is not connected to Substrate Node`, + ); + } + const accountAddress = req.accountAddress; + const transactionExpiration = (req.transactionExpiration as number) || 50; + try { + const signedBlock = await this.api.rpc.chain.getBlock(); + const nonce = (await this.api.derive.balances.account(accountAddress)) + .accountNonce; + const blockHash = signedBlock.block.header.hash; + const era = this.api.createType("ExtrinsicEra", { + current: signedBlock.block.header.number, + period: transactionExpiration, + }); + + const options = { + nonce: nonce, + blockHash: blockHash, + era: era, + }; + + const responseContainer = { + response_data: options, + succeeded: true, + message: "obtainTransactionInformation", + error: null, + }; + + const response: TransactionInfoResponse = { + responseContainer: responseContainer, + }; + + return response; + } catch (err) { + throw createHttpError[500]( + `${fnTag} Obtaining info for this transaction has failed. ` + + `InnerException: ${err}`, + ); + } + } + + public async shutdownConnectionToSubstrate(): Promise { + try { + if (this.api) { + this.log.info("Shutting down connection to substrate..."); + this.api.disconnect(); + } else { + this.log.warn( + "Trying to shutdown connection to substrate, but no connection is available", + ); + } + } catch (err) { + this.log.error("Could not disconnect from Substrate Ledger"); + throw createHttpError[500]( + `Could not disconnect from Substrate Ledger. InnerException: ${err} `, + ); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/data-fetcher.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/data-fetcher.ts new file mode 100644 index 00000000000..140bb1a540f --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/data-fetcher.ts @@ -0,0 +1,12 @@ +import { Transactions } from "./response.type"; + +import { totalTxCount, K_CACTUS_POLKADOT_TOTAL_TX_COUNT } from "./metrics"; + +export async function collectMetrics( + transactions: Transactions, +): Promise { + transactions.counter++; + totalTxCount + .labels(K_CACTUS_POLKADOT_TOTAL_TX_COUNT) + .set(transactions.counter); +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/metrics.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/metrics.ts new file mode 100644 index 00000000000..4de9b34e6df --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/metrics.ts @@ -0,0 +1,10 @@ +import { Gauge } from "prom-client"; + +export const K_CACTUS_POLKADOT_TOTAL_TX_COUNT = + "cactus_polkadot_total_tx_count"; + +export const totalTxCount = new Gauge({ + name: "cactus_polkadot_total_tx_count", + help: "Total transactions executed", + labelNames: ["type"], +}); diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/prometheus-exporter.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/prometheus-exporter.ts new file mode 100644 index 00000000000..81454cae5bb --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/prometheus-exporter.ts @@ -0,0 +1,39 @@ +import promClient, { Registry } from "prom-client"; +import { Transactions } from "./response.type"; +import { collectMetrics } from "./data-fetcher"; +import { K_CACTUS_POLKADOT_TOTAL_TX_COUNT } from "./metrics"; +import { totalTxCount } from "./metrics"; + +export interface IPrometheusExporterOptions { + pollingIntervalInMin?: number; +} + +export class PrometheusExporter { + public readonly metricsPollingIntervalInMin: number; + public readonly transactions: Transactions = { counter: 0 }; + public readonly registry: Registry; + + constructor( + public readonly prometheusExporterOptions: IPrometheusExporterOptions, + ) { + this.metricsPollingIntervalInMin = + prometheusExporterOptions.pollingIntervalInMin || 1; + this.registry = new Registry(); + } + + public addCurrentTransaction(): void { + collectMetrics(this.transactions); + } + + public async getPrometheusMetrics(): Promise { + const result = await this.registry.getSingleMetricAsString( + K_CACTUS_POLKADOT_TOTAL_TX_COUNT, + ); + return result; + } + + public startMetricsCollection(): void { + this.registry.registerMetric(totalTxCount); + promClient.collectDefaultMetrics({ register: this.registry }); + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/response.type.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/response.type.ts new file mode 100644 index 00000000000..3f1bc7f4911 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/prometheus-exporter/response.type.ts @@ -0,0 +1,3 @@ +export type Transactions = { + counter: number; +}; diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/public-api.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/public-api.ts new file mode 100644 index 00000000000..a490e3bbe5a --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/public-api.ts @@ -0,0 +1,16 @@ +export * from "./generated/openapi/typescript-axios/index"; + +export { + PluginLedgerConnectorPolkadot, + IPluginLedgerConnectorPolkadotOptions, +} from "./plugin-ledger-connector-polkadot"; +export { PluginFactoryLedgerConnector } from "./plugin-factory-ledger-connector-polkadot"; + +import { IPluginFactoryOptions } from "@hyperledger/cactus-core-api"; +import { PluginFactoryLedgerConnector } from "./plugin-factory-ledger-connector-polkadot"; + +export async function createPluginFactory( + pluginFactoryOptions: IPluginFactoryOptions, +): Promise { + return new PluginFactoryLedgerConnector(pluginFactoryOptions); +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/deploy-contract-ink-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/deploy-contract-ink-endpoint.ts new file mode 100644 index 00000000000..a6d4c57eed6 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/deploy-contract-ink-endpoint.ts @@ -0,0 +1,100 @@ +import type { Express, Request, Response } from "express"; +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; +import OAS from "../../json/openapi.json"; + +export interface IDeployContractInkEndpointOptions { + logLevel?: LogLevelDesc; + connector: PluginLedgerConnectorPolkadot; +} + +export class DeployContractInkEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "DeployContractInkEndpoint"; + + constructor(public readonly opts: IDeployContractInkEndpointOptions) { + const fnTag = "DeployContractInkEndpoint#constructor()"; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.connector, `${fnTag} arg options.connector`); + + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return DeployContractInkEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/deploy-contract-ink"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/deploy-contract-ink" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + const reqBody = req.body; + try { + const resBody = await this.opts.connector.deployContract(reqBody); + res.json(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to deploy contract:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-prometheus-exporter-metrics-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-prometheus-exporter-metrics-endpoint.ts new file mode 100644 index 00000000000..72076c2ebbc --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-prometheus-exporter-metrics-endpoint.ts @@ -0,0 +1,104 @@ +import type { Express, Request, Response } from "express"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import OAS from "../../json/openapi.json"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + LogLevelDesc, + Logger, + LoggerProvider, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; + +export interface IGetPrometheusMetricsEndpointOptions { + connector: PluginLedgerConnectorPolkadot; + logLevel?: LogLevelDesc; +} + +export class GetPrometheusMetricsEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "GetPrometheusExporterEndpoint"; + constructor(public readonly options: IGetPrometheusMetricsEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + + Checks.truthy(options, `${fnTag} options`); + Checks.truthy(options.connector, `${fnTag} options.connector`); + + const label = this.className; + const level = options.logLevel || "INFO"; + this.log = LoggerProvider.getOrCreate({ label, level }); + } + + public get className(): string { + return GetPrometheusMetricsEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-prometheus-exporter-metrics"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-prometheus-exporter-metrics" + ]; + } + + public getPath(): string { + return this.oasPath.get["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.get["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.get.operationId; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + const verbUpper = this.getVerbLowerCase().toUpperCase(); + this.log.debug(`${verbUpper} ${this.getPath()}`); + + try { + const resBody = + await this.options.connector.getPrometheusExporterMetrics(); + res.status(200); + res.send(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to get Prometheus Exporter Metrics:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-raw-transaction-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-raw-transaction-endpoint.ts new file mode 100644 index 00000000000..27d1ec18775 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-raw-transaction-endpoint.ts @@ -0,0 +1,100 @@ +import type { Express, Request, Response } from "express"; +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; +import OAS from "../../json/openapi.json"; + +export interface IGetRawTransactionEndpointOptions { + logLevel?: LogLevelDesc; + connector: PluginLedgerConnectorPolkadot; +} + +export class GetRawTransactionEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "GetRawTransactionEndpoint"; + + constructor(public readonly opts: IGetRawTransactionEndpointOptions) { + const fnTag = "GetRawTransactionEndpoint#constructor()"; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.connector, `${fnTag} arg options.connector`); + + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return GetRawTransactionEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-raw-transaction"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-raw-transaction" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + handleRequest(req: Request, res: Response): void { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + const reqBody = req.body; + try { + const resBody = this.opts.connector.rawTransaction(reqBody); + res.json(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to get Raw Transaction:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-transaction-info-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-transaction-info-endpoint.ts new file mode 100644 index 00000000000..2a7e360ba42 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/get-transaction-info-endpoint.ts @@ -0,0 +1,101 @@ +import type { Express, Request, Response } from "express"; +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; +import OAS from "../../json/openapi.json"; + +export interface IGetTransactionInfoEndpointOptions { + logLevel?: LogLevelDesc; + connector: PluginLedgerConnectorPolkadot; +} + +export class GetTransactionInfoEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "GetTransactionInfoEndpoint"; + + constructor(public readonly opts: IGetTransactionInfoEndpointOptions) { + const fnTag = "GetTransactionInfoEndpoint#constructor()"; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.connector, `${fnTag} arg options.connector`); + + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return GetTransactionInfoEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-transaction-info"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/get-transaction-info" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + const reqBody = req.body; + try { + const resBody = + await this.opts.connector.obtainTransactionInformation(reqBody); + res.json(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to obtain Transaction Information:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/invoke-contract-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/invoke-contract-endpoint.ts new file mode 100644 index 00000000000..daae2a3a3c7 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/invoke-contract-endpoint.ts @@ -0,0 +1,96 @@ +import type { Express, Request, Response } from "express"; + +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; +import OAS from "../../json/openapi.json"; +export interface IInvokeContractEndpointOptions { + logLevel?: LogLevelDesc; + connector: PluginLedgerConnectorPolkadot; +} + +export class InvokeContractEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "InvokeContractEndpoint"; + + constructor(public readonly opts: IInvokeContractEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + + Checks.truthy(opts, `${fnTag} arg options`); + Checks.truthy(opts.connector, `${fnTag} arg options.connector`); + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + public get className(): string { + return InvokeContractEndpoint.CLASS_NAME; + } + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/invoke-contract"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/invoke-contract" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + const reqBody = req.body; + try { + const resBody = await this.opts.connector.invokeContract(reqBody); + res.json(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to invoke contract:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/run-transaction-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/run-transaction-endpoint.ts new file mode 100644 index 00000000000..89e5366c011 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/run-transaction-endpoint.ts @@ -0,0 +1,96 @@ +import type { Express, Request, Response } from "express"; + +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; +import OAS from "../../json/openapi.json"; +export interface IRunTransactionEndpointOptions { + logLevel?: LogLevelDesc; + connector: PluginLedgerConnectorPolkadot; +} + +export class RunTransactionEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "RunTransactionEndpoint"; + + constructor(public readonly opts: IRunTransactionEndpointOptions) { + const fnTag = `${this.className}#constructor()`; + + Checks.truthy(opts, `${fnTag} arg options`); + Checks.truthy(opts.connector, `${fnTag} arg options.connector`); + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + public get className(): string { + return RunTransactionEndpoint.CLASS_NAME; + } + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/run-transaction"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/run-transaction" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + const reqBody = req.body; + try { + const resBody = await this.opts.connector.transact(reqBody); + res.json(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to perform transaction:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/sign-raw-transaction-endpoint.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/sign-raw-transaction-endpoint.ts new file mode 100644 index 00000000000..ee457b567da --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/main/typescript/web-services/sign-raw-transaction-endpoint.ts @@ -0,0 +1,100 @@ +import type { Express, Request, Response } from "express"; +import { + Logger, + LoggerProvider, + LogLevelDesc, + Checks, + IAsyncProvider, +} from "@hyperledger/cactus-common"; + +import { + IWebServiceEndpoint, + IExpressRequestHandler, + IEndpointAuthzOptions, +} from "@hyperledger/cactus-core-api"; + +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +import { PluginLedgerConnectorPolkadot } from "../plugin-ledger-connector-polkadot"; +import OAS from "../../json/openapi.json"; + +export interface ISignRawTransactionEndpointOptions { + logLevel?: LogLevelDesc; + connector: PluginLedgerConnectorPolkadot; +} + +export class SignRawTransactionEndpoint implements IWebServiceEndpoint { + private readonly log: Logger; + public static readonly CLASS_NAME = "SignRawTransactionEndpoint"; + + constructor(public readonly opts: ISignRawTransactionEndpointOptions) { + const fnTag = "SignRawTransactionEndpoint#constructor()"; + + Checks.truthy(opts, `${fnTag} options`); + Checks.truthy(opts.connector, `${fnTag} arg options.connector`); + + const level = this.opts.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get className(): string { + return SignRawTransactionEndpoint.CLASS_NAME; + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + // TODO: make this an injectable dependency in the constructor + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + public getPath(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.path; + } + + public getVerbLowerCase(): string { + return this.oasPath.post["x-hyperledger-cactus"].http.verbLowerCase; + } + + public getOperationId(): string { + return this.oasPath.post.operationId; + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/sign-raw-transaction"] { + return OAS.paths[ + "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-polkadot/sign-raw-transaction" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + const reqBody = req.body; + try { + const resBody = await this.opts.connector.signTransaction(reqBody); + res.json(resBody); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to sign Transaction:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.contract b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.contract new file mode 100644 index 00000000000..d346e67f8fa --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.contract @@ -0,0 +1 @@ +{"source":{"hash":"0x7b5ef2f314c9ada626e2ef1b54c3fad8f02fd09c8f349414b762dcfc8dee6353","language":"ink! 4.2.1","compiler":"rustc 1.69.0","wasm":"0x0061736d0100000001450c60027f7f017f60037f7f7f017f60027f7f0060037f7f7f0060017f0060047f7f7f7f017f60000060047f7f7f7f0060017f017f60017f017e60057f7f7f7f7f006000017f028a0107057365616c310b6765745f73746f726167650005057365616c301176616c75655f7472616e736665727265640002057365616c3005696e7075740002057365616c300d64656275675f6d6573736167650000057365616c320b7365745f73746f726167650005057365616c300b7365616c5f72657475726e000303656e76066d656d6f7279020102100336350102030b08030400020801020604030202060600010103000300070204060202000400040900000a0507050000030a01000000000704050170010f0f0608017f01418080040b0711020463616c6c0017066465706c6f7900180914010041010b0e0d31263928323738271b1d1f362a0a8744352b01017f037f2002200346047f200005200020036a200120036a2d00003a0000200341016a21030c010b0b0b2601017f230041106b22022400200220003a000f20012002410f6a41011008200241106a24000b5c01037f02402000280208220420026a220320044f04402003200028020422054b0d01200028020020046a200320046b2001200241c897041034200020033602080f0b41f09504411c41a89704101e000b2003200541b89704100b000b5502027f027e230041206b22002400200041106a22014200370300200042003703082000411036021c200041086a2000411c6a10012001290300210220002903082103200041206a2400410541042002200384501b0b1b002000418180014f044020004180800141dc8104100b000b20000b7501017f230041306b220324002003200136020420032000360200200341146a41023602002003411c6a41023602002003412c6a41033602002003418c8f0436021020034100360208200341033602242003200341206a3602182003200341046a36022820032003360220200341086a2002100e000b5201017f230041206b220124002001410c6a4101360200200141146a4101360200200141e49404360208200141003602002001410136021c200120003602182001200141186a360210200141c88204100e000b910101017f230041306b22022400200241146a41013602002002411c6a4101360200200241e494043602102002410036020820024102360224200220002d0000410274220041949a046a28020036022c2002200041a89a046a280200360228200141046a28020021002002200241206a3602182002200241286a36022020012802002000200241086a1035200241306a24000b3c01017f230041206b22022400200241013a00182002200136021420022000360210200241d08a0436020c200241e49504360208200241086a1029000b4001017f230041106b22012400200141003a000f20002001410f6a41011010047f4102054101410220012d000f22004101461b410020001b0b200141106a24000b6001047f230041106b22032400200028020422042002492205450440200341086a4100200220002802002206103a200120022003280208200328020c41849a0410342003200220042006103a200020032903003702000b200341106a240020050b3f01017f230041106b22022400200242808001370204200241c49a0436020020022001047f20024101101641010541000b101620002002280208100a1015000b3701017f230041106b22002400200042808001370204200041c49a0436020020004100101620004100101641002000280208100a1015000bae0102057f017e230041306b2201240020014100360218200142808001370224200141c49a043602202001410036021c200141206a22022001411c6a4104100820012001290320370310200141086a200141106a220320012802281014200128020c2104200128020820012903102106200141003602282001200637032020002002100720012001290320370310200120032001280228101420042001280200200128020410041a200141306a24000b4501017f2002200128020422034b0440418c9604412341e89704101e000b2001200320026b36020420012001280200220120026a36020020002002360204200020013602000b0d00200041c49a0420011005000ba10101027f20002802082202200028020422034904402000200241016a360208200028020020026a20013a00000f0b230041306b220024002000200336020420002002360200200041146a41023602002000411c6a41023602002000412c6a4103360200200041a48a0436021020004100360208200041033602242000200041206a360218200020003602282000200041046a360220200041086a41d89704100e000baf0501077f230041406a22002400024002400240024002400240100941ff0171410546044020004180800136022041c49a04200041206a100220002802202201418180014f0d0120002001360224200041c49a0436022020004100360210200041206a200041106a410410100d0520002802102201411876210220014110762104200141087621030240200141ff01712201412f470440200141e30047200341ff0171413a4772200441ff017141a50147720d0741012101200241d100460d010c070b200341ff017141860147200441ff017141db0047720d0641002101200241d901470d060b20004100360218200042808001370224200041c49a043602202000410036023c200041206a22032000413c6a4104100820002000290320370310200041086a200041106a20002802281014200028020c210520002802082000280210210220002000280214220436022020052002200310002103200420002802202205490d02024002400240410c20032003410c4f1b0e0402000001000b2000412c6a4101360200200041346a4100360200200041888204360228200041e4950436023020004100360220200041206a41908204100e000b2000412c6a4101360200200041346a4100360200200041a083043602280c070b2000200536022420002002360220200041206a100f41ff017122024102460d042001450d032002451013410041001011000b200041043a0020200041206a100c000b20014180800141e48004100b000b2005200441e48004100b000b230041106b22002400200042808001370204200041c49a0436020020004100101620024100472000100741002000280208100a1015000b2000412c6a4101360200200041346a41003602002000418083043602280c010b410141011011000b200041e4950436023020004100360220200041206a41c88204100e000b8f0201057f230041106b2200240002400240100941ff01712201410546044020004180800136020041c49a042000100220002802002201418180014f0d0120002001360204200041c49a043602002000410036020802402000200041086a410410100d002000280208220141187621022001411076210320014108762104200141ff01712201419b01470440200141ed0147200441ff017141cb004772200341ff0171419d01472002411b4772720d01410010131012000b200441ff017141ae0147200341ff0171419d014772200241de0047720d002000100f41ff017122004102470d030b410141011011000b200020013a00002000100c000b20014180800141e48004100b000b200010131012000b5501017f230041206b2202240020022000360204200241186a200141106a290200370300200241106a200141086a29020037030020022001290200370308200241046a41a88304200241086a101a200241206a24000bee0301057f230041406a22032400200341033a003820034280808080800437033020034100360228200341003602202003200136021c20032000360218027f0240024020022802002201450440200241146a28020022004103742105200041ffffffff017121072002280210210441002101034020012005460d02200228020820016a220041046a28020022060440200328021820002802002006200328021c28020c1101000d040b200141086a2101200428020020042802042106200441086a2104200341186a2006110000450d000b0c020b200228020422074105742100200741ffffff3f71210703402000450d01200228020820046a220541046a28020022060440200328021820052802002006200328021c28020c1101000d030b20032001411c6a2d00003a00382003200141146a290200370330200341106a200228021022052001410c6a103320032003290310370320200341086a2005200141046a103320032003290308370328200441086a2104200041206b210020012802002106200141206a2101200520064103746a2205280200200341186a2005280204110000450d000b0c010b2002410c6a28020020074b04402003280218200228020820074103746a22002802002000280204200328021c28020c1101000d010b41000c010b41010b200341406b24000b0f00200028020020012002101c41000b7701027f230041106b2204240020022000280200200028020822036b4b0440200441086a20002003200210202004280208200428020c1021200028020821030b200028020420036a2001200210061a2003200220036a22014b044041c08304411c41a08904101e000b20002001360208200441106a24000bdd0201037f230041106b220224000240024002400240200028020022002002410c6a027f0240024020014180014f04402002410036020c2001418010490d012001418080044f0d0220022001413f71418001723a000e20022001410c7641e001723a000c20022001410676413f71418001723a000d41030c030b200028020822032000280200460d030c040b20022001413f71418001723a000d2002200141067641c001723a000c41020c010b20022001413f71418001723a000f20022001410676413f71418001723a000e20022001410c76413f71418001723a000d2002200141127641077141f001723a000c41040b101c0c020b230041106b22042400200441086a20002003410110202004280208200428020c1021200441106a2400200028020821030b200028020420036a20013a0000200341016a2201450d01200020013602080b200241106a240041000f0b41c08304411c41908904101e000b5001017f230041206b220324002003410c6a4101360200200341146a4100360200200341e49504360210200341003602002003200136021c200320003602182003200341186a36020820032002100e000b4a01017f230041206b220224002000280200200241186a200141106a290200370300200241106a200141086a29020037030020022001290200370308200241086a1019200241206a24000bac0401067f230041206b2204240002402000027f4100200220036a22032002490d001a2001280200220220026a22062002490d0141082006200320032006491b2203200341084d1b2203417f73411f7621050240200204402004410136021820042002360214200420012802043602100c010b200441003602180b200441106a2107230041106b220624002004027f0240027f0240200504400240200341004e044020072802080d012006200310242006280204210220062802000c040b0c040b20072802042209450440200641086a20031024200628020c210220062802080c030b20032102410041bc9a04280200220520036a22082005490d021a2007280200210741c09a042802002008490440200341ffff036a220841107640002202417f46200241ffff0371200247720d022002411074220520084180807c716a22022005490d0241c09a042002360200200321024100200320056a22082005490d031a0b41bc9a04200836020041002005450d021a20052007200910060c020b200420033602040c020b2003210241000b2205044020042005360204200441086a200236020041000c020b20042003360204200441086a410136020041010c010b200441086a410036020041010b360200200641106a240020042802004504402004280204210220012003360200200120023602044181808080780c010b20042802042103200441086a2802000b36020420002003360200200441206a24000f0b41e08304412141848504101e000b1f00024020014181808080784704402001450d0120001022000b0f0b1023000b900101017f230041306b220124002001200036020c2001411c6a4102360200200141246a4101360200200141d08604360218200141003602102001410336022c2001200141286a36022020012001410c6a360228230041206b22002400200041003a0018200041e086043602142000200141106a360210200041d08a0436020c200041e49504360208200041086a1029000b4601017f230041206b22002400200041146a41013602002000411c6a4100360200200041a88504360210200041e4950436021820004100360208200041086a41b08504100e000ba10101027f027f410041bc9a04280200220220016a22032002490d001a024041c09a042802002003490440200141ffff036a22032001490d01200341107640002202417f46200241ffff0371200247720d012002411074220220034180807c716a22032002490d0141c09a0420033602004100200120026a22032002490d021a0b41bc9a04200336020020020c010b41000b210320002001360204200020033602000b5301027f230041106b2202240002402001450440410121030c010b200141004e0440200241086a20011024200228020822030d0120011022000b1023000b2000200336020420002001360200200241106a24000bd806020b7f027e230041406a2203240020002802002202ad210d0240024002400240024002400240024020024190ce004f044041272100200d210e0240034020004104490d01200341196a20006a220241046b200e200e4290ce0080220d4290ce007e7da7220441ffff037141e4006e220641017441818c046a2f00003b0000200241026b2004200641e4006c6b41ffff037141017441818c046a2f00003b0000200041046b2100200e42ffc1d72f56200d210e0d000b200da7220241e3004d0d0320004102490d090c020b0c080b41272100200241e3004b0d002002410a490d040c020b200041026b2200200341196a6a200da72202200241ffff037141e4006e220241e4006c6b41ffff037141017441818c046a2f00003b00000b2002410a490d01200041024f0d000c050b200041026b2200200341196a6a200241017441818c046a2f00003b00000c020b2000450d030b200041016b2200200341196a6a200241306a3a00000b200041274b0d01412820006b412720006b22062001280218220541017122071b2102410021042005410471044041e495042104200241e4950441e49504102b20026a22024b0d010b412b418080c40020071b2107200341196a20006a2108024020012802084504404101210020012802002202200141046a280200220120072004102e0d01200220082006200128020c11010021000c010b024020022001410c6a28020022094904402005410871450d01200128021c210b2001413036021c20012d0020210c41012100200141013a002020012802002205200141046a280200220a20072004102e0d02200341106a2001200920026b4101102f20032802142202418080c400460d022003280210200520082006200a28020c1101000d0220022005200a10300d022001200c3a00202001200b36021c410021000c020b4101210020012802002202200141046a280200220120072004102e0d01200220082006200128020c11010021000c010b41012100200341086a2001200920026b4101102f200328020c2205418080c400460d00200328020820012802002202200141046a280200220120072004102e0d00200220082006200128020c1101000d00200520022001103021000b200341406b240020000f0b41b08904411c41b88e04101e000b41d08904412141cc9404101e000b0300010b0e0020002802001a03400c000b000baa05020a7f017e230041406a220124002001200036020c2001412c6a4102360200200141346a4101360200200141b09604360228200141003602202001410436023c2001200141386a36023020012001410c6a360238200141106a210641002100230041306b22022400200141206a220441146a2802002107200428020821050240024002400240200241086a027f024002400240200241106a027f024002402004410c6a28020022080e020001040b20070d0241e49504210341000c010b20070d022005280200210320052802040b22001025200228021021042006200228021422053602042006200436020020052003200010061a200620003602080c040b200428021021090c010b200541046a21032008410374210a2004280210210903402000200020032802006a22004b0d04200341086a2103200a41086b220a0d000b20002007450d011a2000410f4b0d0041002005280204450d011a0b200020006a22034100200020034d1b0b10252002290308210b200641003602082006200b3702002002200736022c200220093602282002200836022420022005360220200220042902003703182006200241186a10190d020b200241306a24000c020b41c08304411c41bc9404101e000b230041406a220024002000413336020c200041f086043602082000418484043602142000200241186a360210200041246a41023602002000412c6a41023602002000413c6a4106360200200041848b0436022020004100360218200041023602342000200041306a3602282000200041106a3602382000200041086a360230200041186a41908804100e000b2001280214210020012802182101024041c49a052d000045044041c59a052d00004101710d010b410c20002001100322002000410c4f1b410947044041c49a0541013a00000b41c59a0541013a00000b000b0d0042e8a1eef1be9ca9fda07f0ba704010a7f230041106b2203240002400240200020016b22024110490d002002200141036a417c7120016b220049200041044b720d00200220006b22044104490d0020012000102c2206200020016a22082004417c716a2004410371102c6a220220064f0440200441027621050240024003402005450d0520032008200541c0012005200541c0014f1b418c9004102d200328020c21052003280208210820032003280200200328020422002000417c7141f49104102d200328020c210920032802082107024020032802042200450440410021010c010b2003280200220420004102746a210a4100210103402004220641106a2104410021000240034020012001200020066a280200220b417f73410776200b410676724181828408716a22014d0440200041046a22004110470d010c020b0b41b08904411c41849204101e000b2004200a470d000b0b20022002200141087641ff81fc0771200141ff81fc07716a418180046c4110766a22024b0d012009450d000b200941027421004100210103402001200120072802002204417f734107762004410676724181828408716a22014b0d02200741046a2107200041046b22000d000b20022002200141087641ff81fc0771200141ff81fc07716a418180046c4110766a22024d0d0441b08904411c41b49204101e000b41b08904411c41949204101e000b41b08904411c41a49204101e000b41b08904411c41e49104101e000b20012002102c21020b200341106a240020020b4601017f200145044041000f0b024003402002200220002c000041bf7f4a6a22024b0d01200041016a2100200141016b22010d000b20020f0b41b08904411c41bc9404101e000b3e00200220034f044020002003360204200020013602002000410c6a200220036b3602002000200120034102746a3602080f0b418c960441232004101e000b39000240027f2002418080c40047044041012000200220012802101100000d011a0b20030d0141000b0f0b200020034100200128020c1101000bae0101027f20022104024002400240200320012d0020220320034103461b41ff0171220341016b0e03010001020b200241016a2203044020034101762104200241017621030c020b41b08904411c41c88e04101e000b41002104200221030b200341016a2102200128021c2103200128020421052001280200210102400340200241016b2202450d01200120032005280210110000450d000b418080c40021030b20002003360204200020043602000b3201017f027f0340200020002004460d011a200441016a2104200220012003280210110000450d000b200441016b0b2000490bea04010b7f230041106b2209240020002802042104200028020021030240024002402001280208220b410147200128021022024101477145044020024101470d02200320046a210c200141146a28020041016a210a410021022003210003402000200c460d03027f024020002c0000220641004e0440200041016a2105200641ff017121070c010b20002d0001413f7121052006411f7121072006415f4d044020074106742005722107200041026a21050c010b20002d0002413f7120054106747221082006417049044020082007410c74722107200041036a21050c010b200041046a210520022106418080c4002007411274418080f0007120002d0003413f71200841067472722207418080c400460d011a0b2002200520006b6a22062002490d0320070b2108200a41016b220a044020052100200621022008418080c400470d010c040b0b2008418080c400460d02024002402002450d00200220044f04404100210020022004460d010c020b41002100200220036a2c00004140480d010b200321000b2002200420001b21042000200320001b21030c020b200128020020032004200128020428020c11010021000c020b41b08904411c41b49304101e000b200b450440200128020020032004200128020428020c11010021000c010b2001410c6a2802002200200320046a2003102b22024b0440200941086a2001200020026b4100102f41012100200928020c2202418080c400460d0120092802082001280200220520032004200141046a280200220128020c1101000d01200220052001103021000c010b200128020020032004200128020428020c11010021000b200941106a240020000b140020002802002001200028020428020c1100000b5501027f0240027f02400240200228020041016b0e020103000b200241046a0c010b200120022802044103746a22012802044105470d0120012802000b2802002104410121030b20002004360204200020033602000b8501002001200346044020002002200110061a0f0b230041306b220024002000200336020420002001360200200041146a41033602002000411c6a41023602002000412c6a4103360200200041dc900436021020004100360208200041033602242000200041206a360218200020003602282000200041046a360220200041086a2004100e000b4901017f230041206b22032400200341186a200241106a290200370300200341106a200241086a2902003703002003200229020037030820002001200341086a101a200341206a24000b1800200128020041dc94044105200128020428020c1101000b5801027f230041206b22022400200128020421032001280200200241186a2000280200220041106a290200370300200241106a200041086a290200370300200220002902003703082003200241086a101a200241206a24000b0b002000280200200110310b990301037f230041406a22022400200028020021034101210002402001280200220441e08a04410c200141046a280200220128020c1101000d0002402003280208220004402002200036020c200241346a4102360200410121002002413c6a4101360200200241f08a0436023020024100360228200241073602142002200241106a36023820022002410c6a36021020042001200241286a1035450d010c020b20032802002200200328020428020c11090042c8b5e0cfca86dbd3897f520d002002200036020c200241346a4102360200410121002002413c6a4101360200200241f08a0436023020024100360228200241083602142002200241106a36023820022002410c6a36021020042001200241286a10350d010b200328020c21002002411c6a4103360200200241246a41033602002002413c6a4103360200200241346a4103360200200241b88a043602182002410036021020022000410c6a3602382002200041086a3602302002410236022c200220003602282002200241286a36022020042001200241106a103521000b200241406b240020000b2c00200120024d04402000200220016b3602042000200120036a3602000f0b41809904412141ec9804101e000b0bc01a0200418080040be4152f686f6d652f616e6d6f6c2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f696e6b5f656e762d342e322e312f7372632f656e67696e652f6f6e5f636861696e2f6578742e72730000010064000000e4000000140000002f686f6d652f616e6d6f6c2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f696e6b5f656e762d342e322e312f7372632f656e67696e652f6f6e5f636861696e2f696d706c732e7273000074000100660000002401000023000000656e636f756e746572656420756e6578706563746564206572726f72ec0001001c0000007400010066000000ed000000170000002f686f6d652f616e6d6f6c2f646f636b65722d7475742f666c69707065722f6c69622e727300000020010100250000000600000005000000636f756c64206e6f742070726f7065726c79206465636f64652073746f7261676520656e74727900580101002700000073746f7261676520656e7472792077617320656d7074790088010100170000000900000004000000040000000a0000000b0000000c000000617474656d707420746f206164642077697468206f766572666c6f7700000000617474656d707420746f206d756c7469706c792077697468206f766572666c6f770000000900000000000000010000000d0000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f616c6c6f632f7372632f7261775f7665632e72730000140201006e0000008f0100001c0000006361706163697479206f766572666c6f770000009402010011000000140201006e0000000d020000050000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f616c6c6f632f7372632f616c6c6f632e72736d656d6f727920616c6c6f636174696f6e206f6620206279746573206661696c656400002c03010015000000410301000d000000c00201006c0000009f0100000d0000006120666f726d617474696e6720747261697420696d706c656d656e746174696f6e2072657475726e656420616e206572726f722f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f616c6c6f632f7372632f666d742e7273000000a30301006a00000064020000200000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f616c6c6f632f7372632f7665632f6d6f642e72730000200401006e000000350700000d000000200401006e000000a307000009000000617474656d707420746f206164642077697468206f766572666c6f7700000000617474656d707420746f2073756274726163742077697468206f766572666c6f7729696e646578206f7574206f6620626f756e64733a20746865206c656e20697320206275742074686520696e64657820697320f20401002000000012050100120000003a000000e40a010000000000340501000100000034050100010000000900000000000000010000000e00000070616e69636b65642061742027272c206c050100010000006d050100030000003a200000e40a01000000000080050100020000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f666d742f6e756d2e727330303031303230333034303530363037303830393130313131323133313431353136313731383139323032313232323332343235323632373238323933303331333233333334333533363337333833393430343134323433343434353436343734383439353035313532353335343535353635373538353936303631363236333634363536363637363836393730373137323733373437353736373737383739383038313832383338343835383638373838383939303931393239333934393539363937393839392f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f666d742f6d6f642e72730000c90601006d000000750500000d000000c90601006d0000000506000038000000206f7574206f662072616e676520666f7220736c696365206f66206c656e6774682072616e676520656e6420696e6465782000007a0701001000000058070100220000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f736c6963652f697465722e72739c07010070000000c005000025000000736f7572636520736c696365206c656e67746820282920646f6573206e6f74206d617463682064657374696e6174696f6e20736c696365206c656e67746820281c08010015000000310801002b000000f1040100010000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f7374722f636f756e742e727300740801006f0000004700000015000000740801006f0000004f00000032000000740801006f0000005400000011000000740801006f0000005a00000009000000740801006f0000006400000011000000740801006f000000660000000d0000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f7374722f697465722e72730000440901006e00000091000000110000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f697465722f7472616974732f616363756d2e727300c4090100770000009500000001000000940501006d000000cd010000050000004572726f72000000e40a0100000000007061696420616e20756e70617961626c65206d657373616765636f756c64206e6f74207265616420696e707574756e61626c6520746f206465636f646520696e707574656e636f756e746572656420756e6b6e6f776e2073656c6563746f72756e61626c6520746f206465636f64652073656c6563746f720041f095040bcb04617474656d707420746f206164642077697468206f766572666c6f77617373657274696f6e206661696c65643a206d6964203c3d2073656c662e6c656e28290ae40a0100000000002f0b0100010000002f686f6d652f616e6d6f6c2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f696e6b5f656e762d342e322e312f7372632f656e67696e652f6f6e5f636861696e2f6275666665722e727300400b0100670000005a0000001c000000400b0100670000005a00000009000000400b0100670000005a00000031000000400b0100670000006500000009000000400b0100670000008d000000210000002f686f6d652f616e6d6f6c2f2e7275737475702f746f6f6c636861696e732f312e36392d7838365f36342d756e6b6e6f776e2d6c696e75782d676e752f6c69622f727573746c69622f7372632f727573742f6c6962726172792f636f72652f7372632f736c6963652f696e6465782e7273000000f80b010071000000820100004700000000000000617474656d707420746f2073756274726163742077697468206f766572666c6f772f686f6d652f616e6d6f6c2f2e636172676f2f72656769737472792f7372632f6769746875622e636f6d2d316563633632393964623965633832332f7061726974792d7363616c652d636f6465632d332e362e342f7372632f636f6465632e72730000a10c010061000000770000000e000000190000001c000000160000001400000019000000cb0a0100af0a0100990a0100850a01006c0a01","build_info":{"build_mode":"Debug","cargo_contract_version":"2.0.0-rc","rust_toolchain":"stable-x86_64-unknown-linux-gnu","wasm_opt_settings":{"keep_debug_symbols":false,"optimization_passes":"Z"}}},"contract":{"name":"flipper","version":"0.1.0","authors":["[your_name] <[your_email]>"]},"spec":{"constructors":[{"args":[{"label":"init_value","type":{"displayName":["bool"],"type":0}}],"default":false,"docs":["Constructor that initializes the `bool` value to the given `init_value`."],"label":"new","payable":false,"returnType":{"displayName":["ink_primitives","ConstructorResult"],"type":1},"selector":"0x9bae9d5e"},{"args":[],"default":false,"docs":["Constructor that initializes the `bool` value to `false`.","","Constructors can delegate to other constructors."],"label":"default","payable":false,"returnType":{"displayName":["ink_primitives","ConstructorResult"],"type":1},"selector":"0xed4b9d1b"}],"docs":[],"environment":{"accountId":{"displayName":["AccountId"],"type":5},"balance":{"displayName":["Balance"],"type":8},"blockNumber":{"displayName":["BlockNumber"],"type":11},"chainExtension":{"displayName":["ChainExtension"],"type":12},"hash":{"displayName":["Hash"],"type":9},"maxEventTopics":4,"timestamp":{"displayName":["Timestamp"],"type":10}},"events":[],"lang_error":{"displayName":["ink","LangError"],"type":3},"messages":[{"args":[],"default":false,"docs":[" A message that can be called on instantiated contracts."," This one flips the value of the stored `bool` from `true`"," to `false` and vice versa."],"label":"flip","mutates":true,"payable":false,"returnType":{"displayName":["ink","MessageResult"],"type":1},"selector":"0x633aa551"},{"args":[],"default":false,"docs":[" Simply returns the current value of our `bool`."],"label":"get","mutates":false,"payable":false,"returnType":{"displayName":["ink","MessageResult"],"type":4},"selector":"0x2f865bd9"}]},"storage":{"root":{"layout":{"struct":{"fields":[{"layout":{"leaf":{"key":"0x00000000","ty":0}},"name":"value"}],"name":"Flipper"}},"root_key":"0x00000000"}},"types":[{"id":0,"type":{"def":{"primitive":"bool"}}},{"id":1,"type":{"def":{"variant":{"variants":[{"fields":[{"type":2}],"index":0,"name":"Ok"},{"fields":[{"type":3}],"index":1,"name":"Err"}]}},"params":[{"name":"T","type":2},{"name":"E","type":3}],"path":["Result"]}},{"id":2,"type":{"def":{"tuple":[]}}},{"id":3,"type":{"def":{"variant":{"variants":[{"index":1,"name":"CouldNotReadInput"}]}},"path":["ink_primitives","LangError"]}},{"id":4,"type":{"def":{"variant":{"variants":[{"fields":[{"type":0}],"index":0,"name":"Ok"},{"fields":[{"type":3}],"index":1,"name":"Err"}]}},"params":[{"name":"T","type":0},{"name":"E","type":3}],"path":["Result"]}},{"id":5,"type":{"def":{"composite":{"fields":[{"type":6,"typeName":"[u8; 32]"}]}},"path":["ink_primitives","types","AccountId"]}},{"id":6,"type":{"def":{"array":{"len":32,"type":7}}}},{"id":7,"type":{"def":{"primitive":"u8"}}},{"id":8,"type":{"def":{"primitive":"u128"}}},{"id":9,"type":{"def":{"composite":{"fields":[{"type":6,"typeName":"[u8; 32]"}]}},"path":["ink_primitives","types","Hash"]}},{"id":10,"type":{"def":{"primitive":"u64"}}},{"id":11,"type":{"def":{"primitive":"u32"}}},{"id":12,"type":{"def":{"variant":{}},"path":["ink_env","types","NoChainExtension"]}}],"version":"4"} \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.wasm b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.wasm new file mode 100644 index 00000000000..b399579659c Binary files /dev/null and b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.wasm differ diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/metadata.json b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/metadata.json new file mode 100644 index 00000000000..f7a99ee086d --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/metadata.json @@ -0,0 +1,400 @@ +{ + "source": { + "hash": "0x7b5ef2f314c9ada626e2ef1b54c3fad8f02fd09c8f349414b762dcfc8dee6353", + "language": "ink! 4.2.1", + "compiler": "rustc 1.69.0", + "build_info": { + "build_mode": "Debug", + "cargo_contract_version": "2.0.0-rc", + "rust_toolchain": "stable-x86_64-unknown-linux-gnu", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "flipper", + "version": "0.1.0", + "authors": [ + "[your_name] <[your_email]>" + ] + }, + "spec": { + "constructors": [ + { + "args": [ + { + "label": "init_value", + "type": { + "displayName": [ + "bool" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [ + "Constructor that initializes the `bool` value to the given `init_value`." + ], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0x9bae9d5e" + }, + { + "args": [], + "default": false, + "docs": [ + "Constructor that initializes the `bool` value to `false`.", + "", + "Constructors can delegate to other constructors." + ], + "label": "default", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0xed4b9d1b" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 5 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 8 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 11 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 12 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 9 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 10 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 3 + }, + "messages": [ + { + "args": [], + "default": false, + "docs": [ + " A message that can be called on instantiated contracts.", + " This one flips the value of the stored `bool` from `true`", + " to `false` and vice versa." + ], + "label": "flip", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 1 + }, + "selector": "0x633aa551" + }, + { + "args": [], + "default": false, + "docs": [ + " Simply returns the current value of our `bool`." + ], + "label": "get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 4 + }, + "selector": "0x2f865bd9" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "value" + } + ], + "name": "Flipper" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 1, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 2 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 2 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 2, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 3, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 6, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 6, + "type": { + "def": { + "array": { + "len": 32, + "type": 7 + } + } + } + }, + { + "id": 7, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 8, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 9, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 6, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 10, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 11, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 12, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/README.md b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/README.md new file mode 100644 index 00000000000..33e552b43ea --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/README.md @@ -0,0 +1,10 @@ +## Getting Started + +#### Preparation +To build the artifacts, run: +``cargo install cargo-contract --force`` + +#### Compile + +Run: +``cargo +nightly contract build`` diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/.gitignore b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/.gitignore new file mode 100755 index 00000000000..8de8f877e47 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/Cargo.toml b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/Cargo.toml new file mode 100755 index 00000000000..2fe9e4bfd0c --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "flipper" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "4.0.0-beta", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } + +[lib] +name = "flipper" +path = "lib.rs" +crate-type = [ + # Used for normal contract Wasm blobs. + "cdylib", +] + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", +] +ink-as-dependency = [] diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/lib.rs b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/lib.rs new file mode 100755 index 00000000000..ccbad9954ba --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/ink/flipper/lib.rs @@ -0,0 +1,69 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +#[ink::contract] +mod flipper { + + /// Defines the storage of your contract. + /// Add new fields to the below struct in order + /// to add new static storage fields to your contract. + #[ink(storage)] + pub struct Flipper { + /// Stores a single `bool` value on the storage. + value: bool, + } + + impl Flipper { + /// Constructor that initializes the `bool` value to the given `init_value`. + #[ink(constructor)] + pub fn new(init_value: bool) -> Self { + Self { value: init_value } + } + + /// Constructor that initializes the `bool` value to `false`. + /// + /// Constructors can delegate to other constructors. + #[ink(constructor)] + pub fn default() -> Self { + Self::new(Default::default()) + } + + /// A message that can be called on instantiated contracts. + /// This one flips the value of the stored `bool` from `true` + /// to `false` and vice versa. + #[ink(message)] + pub fn flip(&mut self) { + self.value = !self.value; + } + + /// Simply returns the current value of our `bool`. + #[ink(message)] + pub fn get(&self) -> bool { + self.value + } + } + + /// Unit tests in Rust are normally defined within such a `#[cfg(test)]` + /// module and test functions are marked with a `#[test]` attribute. + /// The below code is technically just normal Rust code. + #[cfg(test)] + mod tests { + /// Imports all the definitions from the outer scope so we can use them here. + use super::*; + + /// We test if the default constructor does its job. + #[ink::test] + fn default_works() { + let flipper = Flipper::default(); + assert_eq!(flipper.get(), false); + } + + /// We test a simple use case of our contract. + #[ink::test] + fn it_works() { + let mut flipper = Flipper::new(false); + assert_eq!(flipper.get(), false); + flipper.flip(); + assert_eq!(flipper.get(), true); + } + } +} diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/deploy-ink-contract.test.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/deploy-ink-contract.test.ts new file mode 100644 index 00000000000..6df0213e856 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/deploy-ink-contract.test.ts @@ -0,0 +1,163 @@ +import { + IListenOptions, + LogLevelDesc, + Servers, +} from "@hyperledger/cactus-common"; +import { SubstrateTestLedger } from "../../../../../cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger"; +import metadata from "../../rust/fixtures/ink/metadata.json"; +import fs from "fs-extra"; +import { v4 as uuidv4 } from "uuid"; +import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling"; +import express from "express"; +import http from "http"; +import { + PluginLedgerConnectorPolkadot, + IPluginLedgerConnectorPolkadotOptions, + DefaultApi as PolkadotApi, + Web3SigningCredentialType, + PluginFactoryLedgerConnector, +} from "../../../main/typescript/public-api"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { AddressInfo } from "net"; +import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import "jest-extended"; + +const testCase = "deploy contract through all available methods"; +describe(testCase, () => { + const logLevel: LogLevelDesc = "TRACE"; + + const DEFAULT_WSPROVIDER = "ws://127.0.0.1:9944"; + const instanceId = "test-polkadot-connector"; + const ledgerOptions = { + publishAllPorts: false, + logLevel: logLevel, + emitContainerLogs: true, + }; + const ledger = new SubstrateTestLedger(ledgerOptions); + const expressApp = express(); + expressApp.use(express.json()); + expressApp.use(express.urlencoded({ extended: false })); + const server = http.createServer(expressApp); + let addressInfo: AddressInfo, + address: string, + port: number, + apiHost: string, + plugin: PluginLedgerConnectorPolkadot, + keychainEntryKey: string, + keychainEntryValue: string, + keychainPlugin: PluginKeychainMemory, + apiClient: PolkadotApi, + apiConfig: Configuration, + rawWasm: Buffer; + + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).toResolve(); + }); + afterAll(async () => { + await ledger.stop(); + await plugin.shutdownConnectionToSubstrate(); + }); + afterAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.toBeTruthy(); + }); + afterAll(async () => await Servers.shutdown(server)); + beforeAll(async () => { + const ledgerContainer = await ledger.start(); + expect(ledgerContainer).toBeTruthy(); + keychainEntryKey = uuidv4(); + keychainEntryValue = "//Bob"; + keychainPlugin = new PluginKeychainMemory({ + instanceId: uuidv4(), + keychainId: uuidv4(), + // pre-provision keychain with mock backend holding the private key of the + // test account that we'll reference while sending requests with the + // signing credential pointing to this keychain entry. + backend: new Map([[keychainEntryKey, keychainEntryValue]]), + logLevel, + }); + const connectorOptions: IPluginLedgerConnectorPolkadotOptions = { + logLevel: logLevel, + pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }), + wsProviderUrl: DEFAULT_WSPROVIDER, + instanceId: instanceId, + }; + const factory = new PluginFactoryLedgerConnector({ + pluginImportType: PluginImportType.Local, + }); + + plugin = await factory.create(connectorOptions); + await plugin.onPluginInit(); + + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + addressInfo = await Servers.listen(listenOptions); + ({ address, port } = addressInfo); + apiHost = `http://${address}:${port}`; + apiConfig = new Configuration({ basePath: apiHost }); + apiClient = new PolkadotApi(apiConfig); + await plugin.registerWebServices(expressApp); + await plugin.getOrCreateWebServices(); + rawWasm = await fs.readFile( + "packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.wasm", + ); + }); + const proofSize = 131072; + const refTime = 6219235328; + const gasLimit = { + refTime, + proofSize, + }; + test("deploy contract with pre-signed TX", async () => { + const result = apiClient.deployContractInk({ + wasm: rawWasm.toString("base64"), + metadata: JSON.stringify(metadata), + gasLimit: gasLimit, + storageDepositLimit: null, + salt: new Uint8Array().toString(), + web3SigningCredential: { type: Web3SigningCredentialType.None }, + params: [false], + }); + await expect(result).rejects.toHaveProperty(["response", "status"], 400); + }); + test("deploy contract using passing mnemonic string", async () => { + const result = await apiClient.deployContractInk({ + wasm: rawWasm.toString("base64"), + metadata: JSON.stringify(metadata), + gasLimit: gasLimit, + storageDepositLimit: null, + salt: new Uint8Array().toString(), + web3SigningCredential: { + type: Web3SigningCredentialType.MnemonicString, + mnemonic: "//Alice", + }, + params: [false], + }); + expect(result).toBeTruthy(); + expect(result.data.success).toBeTrue; + expect(result.data.contractAddress).toBeTruthy(); + }); + test("deploy contract using passing cactus keychain ref", async () => { + const result = await apiClient.deployContractInk({ + wasm: rawWasm.toString("base64"), + metadata: JSON.stringify(metadata), + gasLimit: gasLimit, + storageDepositLimit: null, + salt: new Uint8Array().toString(), + web3SigningCredential: { + type: Web3SigningCredentialType.CactusKeychainRef, + keychainEntryKey: keychainEntryKey, + keychainId: keychainPlugin.getKeychainId(), + }, + params: [false], + }); + expect(result).toBeTruthy(); + expect(result.data.success).toBeTrue; + expect(result.data.contractAddress).toBeTruthy(); + }); +}); diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/invoke-ink-contract.test.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/invoke-ink-contract.test.ts new file mode 100644 index 00000000000..1a8f60cfb2b --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/invoke-ink-contract.test.ts @@ -0,0 +1,190 @@ +import { + IListenOptions, + LogLevelDesc, + Servers, +} from "@hyperledger/cactus-common"; +import { SubstrateTestLedger } from "../../../../../cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger"; +import metadata from "../../rust/fixtures/ink/metadata.json"; +import fs from "fs-extra"; +import { v4 as uuidv4 } from "uuid"; +import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling"; +import express from "express"; +import http from "http"; +import { + PluginLedgerConnectorPolkadot, + IPluginLedgerConnectorPolkadotOptions, + DefaultApi as PolkadotApi, + Web3SigningCredentialType, + PolkadotContractInvocationType, + PluginFactoryLedgerConnector, +} from "../../../main/typescript/public-api"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { AddressInfo } from "net"; +import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import "jest-extended"; + +const testCase = "invoke contract with all invocation types"; +describe(testCase, () => { + const logLevel: LogLevelDesc = "TRACE"; + + const DEFAULT_WSPROVIDER = "ws://127.0.0.1:9944"; + const instanceId = "test-polkadot-connector"; + const ledgerOptions = { + publishAllPorts: false, + logLevel: logLevel, + emitContainerLogs: true, + }; + const ledger = new SubstrateTestLedger(ledgerOptions); + const expressApp = express(); + expressApp.use(express.json()); + expressApp.use(express.urlencoded({ extended: false })); + const server = http.createServer(expressApp); + let addressInfo: AddressInfo, + address: string, + port: number, + apiHost: string, + plugin: PluginLedgerConnectorPolkadot, + keychainEntryKey: string, + keychainEntryValue: string, + keychainPlugin: PluginKeychainMemory, + apiClient: PolkadotApi, + apiConfig: Configuration, + contractAddress: string; + + const proofSize = 131072; + const refTime = 6219235328; + const gasLimit = { + refTime, + proofSize, + }; + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).toResolve(); + }); + afterAll(async () => { + await ledger.stop(); + await plugin.shutdownConnectionToSubstrate(); + }); + afterAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.toBeTruthy(); + }); + afterAll(async () => await Servers.shutdown(server)); + beforeAll(async () => { + const ledgerContainer = await ledger.start(); + expect(ledgerContainer).toBeTruthy(); + keychainEntryKey = uuidv4(); + keychainEntryValue = "//Bob"; + keychainPlugin = new PluginKeychainMemory({ + instanceId: uuidv4(), + keychainId: uuidv4(), + // pre-provision keychain with mock backend holding the private key of the + // test account that we'll reference while sending requests with the + // signing credential pointing to this keychain entry. + backend: new Map([[keychainEntryKey, keychainEntryValue]]), + logLevel, + }); + const connectorOptions: IPluginLedgerConnectorPolkadotOptions = { + logLevel: logLevel, + pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }), + wsProviderUrl: DEFAULT_WSPROVIDER, + instanceId: instanceId, + }; + + const factory = new PluginFactoryLedgerConnector({ + pluginImportType: PluginImportType.Local, + }); + + plugin = await factory.create(connectorOptions); + await plugin.onPluginInit(); + + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + addressInfo = await Servers.listen(listenOptions); + ({ address, port } = addressInfo); + apiHost = `http://${address}:${port}`; + apiConfig = new Configuration({ basePath: apiHost }); + apiClient = new PolkadotApi(apiConfig); + await plugin.registerWebServices(expressApp); + await plugin.getOrCreateWebServices(); + }); + beforeAll(async () => { + const rawWasm = await fs.readFile( + "packages/cactus-plugin-ledger-connector-polkadot/src/test/rust/fixtures/ink/flipper.wasm", + ); + const result = await apiClient.deployContractInk({ + wasm: rawWasm.toString("base64"), + metadata: JSON.stringify(metadata), + gasLimit: gasLimit, + storageDepositLimit: null, + salt: new Uint8Array().toString(), + web3SigningCredential: { + type: Web3SigningCredentialType.MnemonicString, + mnemonic: "//Alice", + }, + params: [false], + }); + expect(result).toBeTruthy(); + expect(result.data.success).toBeTrue; + expect(result.data.contractAddress).toBeTruthy(); + if (!result.data.contractAddress) { + throw new Error("contract address cannot be undefined"); + } + contractAddress = result.data.contractAddress; + }); + test("invalid methodName contract invocation", async () => { + const result = apiClient.invokeContract({ + invocationType: PolkadotContractInvocationType.Send, + contractAddress, + gasLimit, + metadata: JSON.stringify(metadata), + methodName: "invalid", + accountAddress: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", //Alice account address + web3SigningCredential: { + type: Web3SigningCredentialType.CactusKeychainRef, + keychainEntryKey: keychainEntryKey, + keychainId: keychainPlugin.getKeychainId(), + }, + }); + await expect(result).rejects.toHaveProperty(["response", "status"], 400); + }); + test("query ink! contract", async () => { + const result = await apiClient.invokeContract({ + invocationType: PolkadotContractInvocationType.Query, + contractAddress, + gasLimit, + metadata: JSON.stringify(metadata), + methodName: "get", + accountAddress: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", //Alice account address + web3SigningCredential: { + type: Web3SigningCredentialType.None, + }, + }); + expect(result).toBeTruthy(); + expect(result.data.success).toBeTrue; + expect(result.data.callOutput).toBeTruthy(); + }); + test("flip() invocation", async () => { + const result = await apiClient.invokeContract({ + invocationType: PolkadotContractInvocationType.Send, + contractAddress, + gasLimit, + metadata: JSON.stringify(metadata), + methodName: "flip", + accountAddress: "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", //Alice account address + web3SigningCredential: { + type: Web3SigningCredentialType.CactusKeychainRef, + keychainEntryKey: keychainEntryKey, + keychainId: keychainPlugin.getKeychainId(), + }, + }); + expect(result).toBeTruthy(); + expect(result.data.success).toBeTrue; + expect(result.data.blockHash).toBeTruthy(); + expect(result.data.txHash).toBeTruthy(); + }); +}); diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts new file mode 100644 index 00000000000..5375995cc9e --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/integration/run-transaction.test.ts @@ -0,0 +1,244 @@ +import { + IListenOptions, + LogLevelDesc, + Servers, +} from "@hyperledger/cactus-common"; +import { SubstrateTestLedger } from "../../../../../cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger"; +import { v4 as uuidv4 } from "uuid"; +import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling"; +import express from "express"; +import http from "http"; +import { + PluginLedgerConnectorPolkadot, + IPluginLedgerConnectorPolkadotOptions, + DefaultApi as PolkadotApi, + Web3SigningCredentialType, + PluginFactoryLedgerConnector, +} from "../../../main/typescript/public-api"; +import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import { AddressInfo } from "net"; +import { Configuration, PluginImportType } from "@hyperledger/cactus-core-api"; +import { Keyring } from "@polkadot/api"; +import { K_CACTUS_POLKADOT_TOTAL_TX_COUNT } from "../../../main/typescript/prometheus-exporter/metrics"; +import "jest-extended"; + +const testCase = "transact through all available methods"; +describe(testCase, () => { + const logLevel: LogLevelDesc = "TRACE"; + + const DEFAULT_WSPROVIDER = "ws://127.0.0.1:9944"; + const instanceId = "test-polkadot-connector"; + const ledgerOptions = { + publishAllPorts: false, + logLevel: logLevel, + emitContainerLogs: true, + }; + const ledger = new SubstrateTestLedger(ledgerOptions); + const expressApp = express(); + expressApp.use(express.json()); + expressApp.use(express.urlencoded({ extended: false })); + const server = http.createServer(expressApp); + let addressInfo: AddressInfo, + address: string, + port: number, + apiHost: string, + plugin: PluginLedgerConnectorPolkadot, + keychainEntryKey: string, + keychainEntryValue: string, + keychainPlugin: PluginKeychainMemory, + apiClient: PolkadotApi, + apiConfig: Configuration; + + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).toResolve(); + }); + afterAll(async () => { + await ledger.stop(); + await plugin.shutdownConnectionToSubstrate(); + }); + afterAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).resolves.toBeTruthy(); + }); + afterAll(async () => await Servers.shutdown(server)); + beforeAll(async () => { + const ledgerContainer = await ledger.start(); + expect(ledgerContainer).toBeTruthy(); + keychainEntryKey = uuidv4(); + keychainEntryValue = "//Alice"; + keychainPlugin = new PluginKeychainMemory({ + instanceId: uuidv4(), + keychainId: uuidv4(), + // pre-provision keychain with mock backend holding the private key of the + // test account that we'll reference while sending requests with the + // signing credential pointing to this keychain entry. + backend: new Map([[keychainEntryKey, keychainEntryValue]]), + logLevel, + }); + const connectorOptions: IPluginLedgerConnectorPolkadotOptions = { + logLevel: logLevel, + pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }), + wsProviderUrl: DEFAULT_WSPROVIDER, + instanceId: instanceId, + }; + + const factory = new PluginFactoryLedgerConnector({ + pluginImportType: PluginImportType.Local, + }); + + plugin = await factory.create(connectorOptions); + await plugin.onPluginInit(); + + const listenOptions: IListenOptions = { + hostname: "127.0.0.1", + port: 0, + server, + }; + addressInfo = await Servers.listen(listenOptions); + ({ address, port } = addressInfo); + apiHost = `http://${address}:${port}`; + apiConfig = new Configuration({ basePath: apiHost }); + apiClient = new PolkadotApi(apiConfig); + await plugin.registerWebServices(expressApp); + await plugin.getOrCreateWebServices(); + }); + test("transact using pre-signed transaction", async () => { + const keyring = new Keyring({ type: "sr25519" }); + const alicePair = keyring.createFromUri("//Alice"); + const bobPair = keyring.createFromUri("//Bob"); + + const infoForSigningTransaction = await apiClient.getTransactionInfo({ + accountAddress: alicePair.address, + transactionExpiration: 500, + }); + expect(infoForSigningTransaction.status).toEqual(200); + const response = infoForSigningTransaction.data; + expect(response).toBeTruthy(); + const nonce = response.responseContainer.response_data.nonce; + expect(nonce).toBeTruthy(); + const blockHash = response.responseContainer.response_data.blockHash; + expect(blockHash).toBeTruthy(); + const era = response.responseContainer.response_data.era; + expect(era).toBeTruthy(); + + const signingOptions = { + nonce: nonce, + blockHash: blockHash, + era: era, + }; + + const transaction = await apiClient.getRawTransaction({ + to: bobPair.address, + value: 20, + }); + expect(transaction).toBeTruthy(); + expect( + transaction.data.responseContainer.response_data.rawTransaction, + ).toBeTruthy(); + const rawTransaction = + transaction.data.responseContainer.response_data.rawTransaction; + + const signedTransactionResponse = await apiClient.signRawTransaction({ + rawTransaction: rawTransaction, + mnemonic: "//Alice", + signingOptions: signingOptions, + }); + expect(signedTransactionResponse.data.success).toBeTrue(); + expect(signedTransactionResponse.data.signedTransaction).toBeTruthy(); + const signedTransaction = signedTransactionResponse.data.signedTransaction; + const TransactionDetails = await apiClient.runTransaction({ + web3SigningCredential: { type: Web3SigningCredentialType.None }, + transactionConfig: { + transferSubmittable: signedTransaction, + }, + }); + expect(TransactionDetails.status).toEqual(200); + const transactionResponse = TransactionDetails.data; + expect(transactionResponse).toBeTruthy(); + expect(transactionResponse.success).toBeTrue(); + expect(transactionResponse.txHash).toBeTruthy(); + expect(transactionResponse.blockHash).toBeTruthy(); + }); + + test("transact by omiting mnemonic string", async () => { + const keyring = new Keyring({ type: "sr25519" }); + const bobPair = keyring.createFromUri("//Bob"); + const TransactionDetails = apiClient.runTransaction({ + web3SigningCredential: { + type: Web3SigningCredentialType.MnemonicString, + mnemonic: "", + }, + transactionConfig: { + to: bobPair.address, + value: 30, + }, + }); + + await expect(TransactionDetails).rejects.toHaveProperty( + ["response", "status"], + 400, + ); + }); + test("transact using passing mnemonic string", async () => { + const keyring = new Keyring({ type: "sr25519" }); + const bobPair = keyring.createFromUri("//Bob"); + const TransactionDetails = await apiClient.runTransaction({ + web3SigningCredential: { + type: Web3SigningCredentialType.MnemonicString, + mnemonic: "//Alice", + }, + transactionConfig: { + to: bobPair.address, + value: 30, + }, + }); + expect(TransactionDetails.status).toEqual(200); + const transactionResponse = TransactionDetails.data; + expect(transactionResponse).toBeTruthy(); + expect(transactionResponse.success).toBeTrue(); + expect(transactionResponse.txHash).toBeTruthy(); + expect(transactionResponse.blockHash).toBeTruthy(); + }); + test("transact using passing cactus keychain ref", async () => { + const keyring = new Keyring({ type: "sr25519" }); + const bobPair = keyring.createFromUri("//Bob"); + const TransactionDetails = await apiClient.runTransaction({ + web3SigningCredential: { + type: Web3SigningCredentialType.CactusKeychainRef, + keychainEntryKey: keychainEntryKey, + keychainId: keychainPlugin.getKeychainId(), + }, + transactionConfig: { + to: bobPair.address, + value: 30, + }, + }); + expect(TransactionDetails.status).toEqual(200); + const transactionResponse = TransactionDetails.data; + expect(transactionResponse).toBeTruthy(); + expect(transactionResponse.success).toBeTrue(); + expect(transactionResponse.txHash).toBeTruthy(); + expect(transactionResponse.blockHash).toBeTruthy(); + }); + + test("get prometheus exporter metrics", async () => { + const res = await apiClient.getPrometheusMetrics(); + const promMetricsOutput = + "# HELP " + + K_CACTUS_POLKADOT_TOTAL_TX_COUNT + + " Total transactions executed\n" + + "# TYPE " + + K_CACTUS_POLKADOT_TOTAL_TX_COUNT + + " gauge\n" + + K_CACTUS_POLKADOT_TOTAL_TX_COUNT + + '{type="' + + K_CACTUS_POLKADOT_TOTAL_TX_COUNT + + '"} 3'; + expect(res).toBeTruthy(); + expect(res.data).toBeTruthy(); + expect(res.status).toEqual(200); + expect(res.data).toContain(promMetricsOutput); + }); +}); diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/unit/api-surface.test.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/unit/api-surface.test.ts new file mode 100644 index 00000000000..84b652f4a78 --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/unit/api-surface.test.ts @@ -0,0 +1,7 @@ +import "jest-extended"; + +import * as apiSurface from "../../../main/typescript/public-api"; + +test("Library can be loaded", async () => { + expect(apiSurface).toBeTruthy(); +}); diff --git a/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/unit/constructor-instantiation.test.ts b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/unit/constructor-instantiation.test.ts new file mode 100644 index 00000000000..9ce0eb5370a --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/src/test/typescript/unit/constructor-instantiation.test.ts @@ -0,0 +1,57 @@ +import { PrometheusExporter } from "../../../main/typescript/prometheus-exporter/prometheus-exporter"; +import { LogLevelDesc } from "@hyperledger/cactus-common"; +import { SubstrateTestLedger } from "../../../../../cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger"; +import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling"; +import { + PluginLedgerConnectorPolkadot, + IPluginLedgerConnectorPolkadotOptions, + PluginFactoryLedgerConnector, +} from "../../../main/typescript"; +import { PluginRegistry } from "@hyperledger/cactus-core"; +import "jest-extended"; +import { PluginImportType } from "@hyperledger/cactus-core-api"; + +const testCase = "Instantiate plugin"; +const logLevel: LogLevelDesc = "TRACE"; +const DEFAULT_WSPROVIDER = "ws://127.0.0.1:9944"; +const instanceId = "test-polkadot-connector"; +const prometheus: PrometheusExporter = new PrometheusExporter({ + pollingIntervalInMin: 1, +}); + +describe(testCase, () => { + let plugin: PluginLedgerConnectorPolkadot; + const connectorOptions: IPluginLedgerConnectorPolkadotOptions = { + logLevel: logLevel, + prometheusExporter: prometheus, + pluginRegistry: new PluginRegistry({ plugins: [] }), + wsProviderUrl: DEFAULT_WSPROVIDER, + instanceId: instanceId, + }; + const ledgerOptions = { + publishAllPorts: false, + logLevel: logLevel, + emitContainerLogs: true, + }; + const ledger = new SubstrateTestLedger(ledgerOptions); + const factory = new PluginFactoryLedgerConnector({ + pluginImportType: PluginImportType.Local, + }); + + beforeAll(async () => { + const pruning = pruneDockerAllIfGithubAction({ logLevel }); + await expect(pruning).toResolve(); + }); + afterAll(async () => { + await ledger.stop(); + await plugin.shutdownConnectionToSubstrate(); + await pruneDockerAllIfGithubAction({ logLevel }); + }); + test(testCase, async () => { + await ledger.start(); + expect(ledger).toBeTruthy(); + plugin = await factory.create(connectorOptions); + await plugin.onPluginInit(); + await plugin.getOrCreateWebServices(); + }); +}); diff --git a/packages/cactus-plugin-ledger-connector-polkadot/tsconfig.json b/packages/cactus-plugin-ledger-connector-polkadot/tsconfig.json new file mode 100644 index 00000000000..8d5d434fb1d --- /dev/null +++ b/packages/cactus-plugin-ledger-connector-polkadot/tsconfig.json @@ -0,0 +1,32 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "composite": true, + "outDir": "./dist/lib/", + "declarationDir": "dist/lib", + "resolveJsonModule": true, + "rootDir": "./src", + "tsBuildInfoFile": "../../.build-cache/cactus-plugin-ledger-connector-polkadot.tsbuildinfo" + }, + "include": [ + "./src", + "src/**/*.json" + ], + "references": [ + { + "path": "../cactus-common/tsconfig.json" + }, + { + "path": "../cactus-core/tsconfig.json" + }, + { + "path": "../cactus-core-api/tsconfig.json" + }, + { + "path": "../cactus-plugin-keychain-memory/tsconfig.json" + }, + { + "path": "../cactus-test-tooling/tsconfig.json" + } + ] +} \ No newline at end of file diff --git a/packages/cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger.ts b/packages/cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger.ts index 784070a1c79..981db2e65b2 100644 --- a/packages/cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger.ts +++ b/packages/cactus-test-tooling/src/main/typescript/substrate-test-ledger/substrate-test-ledger.ts @@ -58,7 +58,7 @@ export class SubstrateTestLedger { this._containerId = Optional.empty(); this.imageName = opts.imageName || "ghcr.io/hyperledger/cactus-substrate-all-in-one"; - this.imageTag = opts.imageTag || "2021-09-24---feat-1274"; + this.imageTag = opts.imageTag || "2024-01-16-pr-2877"; this.imageFqn = `${this.imageName}:${this.imageTag}`; this.envVars = opts.envVars || new Map(); this.emitContainerLogs = Bools.isBooleanStrict(opts.emitContainerLogs) @@ -104,7 +104,7 @@ export class SubstrateTestLedger { Healthcheck: { Test: [ "CMD-SHELL", - `rustup --version && rustc --version && cargo --version`, + `(echo '{"id":1,"jsonrpc":"2.0","method":"system_health","params":[]}' | websocat -n1 ws://127.0.0.1:9944) > /dev/null; echo $?`, ], Interval: 1000000000, // 1 second Timeout: 3000000000, // 3 seconds diff --git a/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts b/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts index 9da9d4f3c4f..f2da95a35a2 100644 --- a/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts +++ b/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-constructor.test.ts @@ -17,16 +17,6 @@ test(testCase, async (t: Test) => { publishAllPorts: true, logLevel: logLevel, emitContainerLogs: true, - imageName: "ghcr.io/hyperledger/cactus-substrate-all-in-one", - imageTag: "2022-03-29--1496", - envVars: new Map([ - ["WORKING_DIR", "/var/www/node-template"], - ["CONTAINER_NAME", "contracts-node-template-cactus"], - ["WS_PORT", "9944"], - ["PORT", "9944"], - ["DOCKER_PORT", "9944"], - ["CARGO_HOME", "/var/www/node-template/.cargo"], - ]), }; const ledger = new SubstrateTestLedger(options); diff --git a/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts b/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts index dbc4c1c501a..f89eba6197d 100644 --- a/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts +++ b/packages/cactus-test-tooling/src/test/typescript/integration/substrate/substrate-test-ledger-multiple-concurrent.test.ts @@ -17,15 +17,10 @@ test(testCase, async (t: Test) => { publishAllPorts: true, logLevel: logLevel, emitContainerLogs: true, - imageName: "ghcr.io/hyperledger/cactus-substrate-all-in-one", - imageTag: "2022-03-29--1496", envVars: new Map([ - ["WORKING_DIR", "/var/www/node-template"], - ["CONTAINER_NAME", "contracts-node-template-cactus"], ["WS_PORT", "9945"], ["PORT", "9944"], ["DOCKER_PORT", "9945"], - ["CARGO_HOME", "/var/www/node-template/.cargo"], ]), }; @@ -35,15 +30,10 @@ test(testCase, async (t: Test) => { publishAllPorts: true, logLevel: logLevel, emitContainerLogs: true, - imageName: "ghcr.io/hyperledger/cactus-substrate-all-in-one", - imageTag: "2022-03-29--1496", envVars: new Map([ - ["WORKING_DIR", "/var/www/node-template"], - ["CONTAINER_NAME", "contracts-node-template-cactus"], ["WS_PORT", "9947"], ["PORT", "9946"], ["DOCKER_PORT", "9947"], - ["CARGO_HOME", "/var/www/node-template/.cargo"], ]), }; diff --git a/tools/docker/substrate-all-in-one/Dockerfile b/tools/docker/substrate-all-in-one/Dockerfile index 3a595f59043..ebac55bf10b 100644 --- a/tools/docker/substrate-all-in-one/Dockerfile +++ b/tools/docker/substrate-all-in-one/Dockerfile @@ -1,48 +1,31 @@ -FROM paritytech/ci-linux:production -LABEL AUTHORS="Rafael Belchior, Catarina Pedreira" -LABEL VERSION="2021-11-01" -LABEL org.opencontainers.image.source=https://github.com/hyperledger/cactus +FROM paritytech/ci-linux:production as builder -WORKDIR / -ENV WORKING_DIR=/var/www/node-template -ENV CONTAINER_NAME=contracts-node-template-cactus -# Specify p2p protocol TCP port -ENV PORT=9614 +RUN cargo install contracts-node -# Specify HTTP RPC server TCP port -ENV RPC_PORT=9618 +## second stage +FROM ubuntu:20.04 -#Specify WebSockets RPC server TCP port -ENV WS_PORT=9944 +COPY --from=builder /usr/local/cargo/bin/substrate-contracts-node /usr/local/bin/ -ENV DOCKER_PORT=9944 -ENV CARGO_HOME=/var/www/node-template/.cargo -ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus +RUN apt-get update && apt-get install -y supervisor \ + && apt-get install wget -y \ + && wget -qO /usr/local/bin/websocat https://github.com/vi/websocat/releases/download/v1.11.0/websocat.x86_64-unknown-linux-musl \ + && chmod a+x /usr/local/bin/websocat -VOLUME .:/var/www/node-template +COPY ./healthcheck.sh /usr/bin/ -RUN apt update +RUN chmod a+x /usr/bin/healthcheck.sh -# Get ubuntu and rust packages -RUN apt install -y build-essential pkg-config git clang curl libssl-dev llvm libudev-dev +HEALTHCHECK --interval=10s --timeout=10s --start-period=30s --retries=10 \ + CMD ["/usr/bin/healthcheck.sh"] -ENV CACTUS_CFG_PATH=/etc/hyperledger/cactus -RUN mkdir -p $CACTUS_CFG_PATH +# for substrate node +EXPOSE 9944 +# for supervisord +EXPOSE 9001 -RUN set -e +COPY supervisord.conf /etc/supervisord.conf -RUN echo "*** Instaling Rust environment ***" -RUN curl https://sh.rustup.rs -y -sSf | sh -RUN echo 'source $HOME/.cargo/env' >> $HOME/.bashrc -RUN rustup default nightly +ENTRYPOINT ["/usr/bin/supervisord"] -RUN echo "*** Initializing WASM build environment" -RUN rustup target add wasm32-unknown-unknown --toolchain nightly - -RUN echo "*** Installing Substrate node environment ***" -RUN cargo install contracts-node --git https://github.com/paritytech/substrate-contracts-node.git --force --locked - -COPY start.sh / - -RUN echo "*** Start Substrate node template ***" -CMD /start.sh +CMD ["--configuration", "/etc/supervisord.conf", "--nodaemon"] diff --git a/tools/docker/substrate-all-in-one/README.md b/tools/docker/substrate-all-in-one/README.md index 0028ebfd961..9aa2a5ca119 100644 --- a/tools/docker/substrate-all-in-one/README.md +++ b/tools/docker/substrate-all-in-one/README.md @@ -14,23 +14,11 @@ This is the test ledger used by the `polkadot-connector` package. To run the test ledger, use: ```sh -docker run --expose HOST_PORT --env WS_PORT=WS_PORT --env WORKING_DIR=/var/www/node-template --env CONTAINER_NAME=contracts-node-template-ovl --env CARGO_HOME=/var/www/node-template/.cargo -p HOST_PORT:WS_PORT rafaelapb/cactus-substrate-aio:2021-11-02-fix - - - -``` - -Example: - - -``` -docker run --expose 9946 --env WS_PORT=9947 --env WORKING_DIR=/var/www/node-template --env CONTAINER_NAME=contracts-node-template-ovl --env CARGO_HOME=/var/www/node-template/.cargo -p 9940:9947 rafaelapb/cactus-substrate-aio:2021-11-02-fix - - +docker run -p 9944:9944 anmol02/cactus-substrate-aio:2023-10-28 ``` ## Build ```sh -DOCKER_BUILDKIT=1 docker build ./tools/docker/substrate-all-in-one/ -f ./tools/docker/substrate-all-in-one/Dockerfile --tag saio +docker build ./tools/docker/substrate-all-in-one/ -f ./tools/docker/substrate-all-in-one/Dockerfile --tag saio ``` diff --git a/tools/docker/substrate-all-in-one/healthcheck.sh b/tools/docker/substrate-all-in-one/healthcheck.sh new file mode 100755 index 00000000000..eb436e45a3b --- /dev/null +++ b/tools/docker/substrate-all-in-one/healthcheck.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env sh + +# Fail on first wrong command +set -e + +# health check command +(echo '{"id":1,"jsonrpc":"2.0","method":"system_health","params":[]}' | websocat -n1 ws://127.0.0.1:9944) > /dev/null; + + echo $? diff --git a/tools/docker/substrate-all-in-one/start.sh b/tools/docker/substrate-all-in-one/start.sh deleted file mode 100755 index cde8da5efda..00000000000 --- a/tools/docker/substrate-all-in-one/start.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -set -euxo pipefail - -echo "ENV:PORT=${PORT}" -echo "ENV:WS_PORT=${WS_PORT}" - -exec /var/www/node-template/.cargo/bin/substrate-contracts-node --dev --port ${PORT} --ws-port ${WS_PORT} diff --git a/tools/docker/substrate-all-in-one/supervisord.conf b/tools/docker/substrate-all-in-one/supervisord.conf new file mode 100644 index 00000000000..05652e80a64 --- /dev/null +++ b/tools/docker/substrate-all-in-one/supervisord.conf @@ -0,0 +1,22 @@ +[supervisord] +logfile = /var/log/supervisord.log +logfile_maxbytes = 50MB +logfile_backups=10 +loglevel = info + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=http://127.0.0.1:9001/ + +[inet_http_server] +port = 0.0.0.0:9001 + +[program:polkadot] +command=/usr/local/bin/substrate-contracts-node --dev --rpc-external -ldebug +autostart=true +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 9239b9d4fb4..27a1cb17672 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -55,6 +55,9 @@ { "path": "./packages/cactus-plugin-ledger-connector-besu/tsconfig.json" }, + { + "path": "./packages/cactus-plugin-ledger-connector-polkadot/tsconfig.json" + }, { "path": "./packages/cactus-plugin-ledger-connector-corda/tsconfig.json" }, diff --git a/yarn.lock b/yarn.lock index a590a39b7e4..13f0a98671e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -440,6 +440,18 @@ __metadata: languageName: node linkType: hard +"@apidevtools/json-schema-ref-parser@npm:9.0.9": + version: 9.0.9 + resolution: "@apidevtools/json-schema-ref-parser@npm:9.0.9" + dependencies: + "@jsdevtools/ono": ^7.1.3 + "@types/json-schema": ^7.0.6 + call-me-maybe: ^1.0.1 + js-yaml: ^4.1.0 + checksum: b21f6bdd37d2942c3967ee77569bc74fadd1b922f688daf5ef85057789a2c3a7f4afc473aa2f3a93ec950dabb6ef365f8bd9cf51e4e062a1ee1e59b989f8f9b4 + languageName: node + linkType: hard + "@apidevtools/json-schema-ref-parser@npm:^9.1.2": version: 9.1.2 resolution: "@apidevtools/json-schema-ref-parser@npm:9.1.2" @@ -5979,7 +5991,7 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^0.4.3": +"@eslint/eslintrc@npm:^0.4.0, @eslint/eslintrc@npm:^0.4.3": version: 0.4.3 resolution: "@eslint/eslintrc@npm:0.4.3" dependencies: @@ -8754,6 +8766,51 @@ __metadata: languageName: unknown linkType: soft +"@hyperledger/cactus-plugin-ledger-connector-polkadot@workspace:packages/cactus-plugin-ledger-connector-polkadot": + version: 0.0.0-use.local + resolution: "@hyperledger/cactus-plugin-ledger-connector-polkadot@workspace:packages/cactus-plugin-ledger-connector-polkadot" + dependencies: + "@hyperledger/cactus-common": 2.0.0-alpha.2 + "@hyperledger/cactus-core": 2.0.0-alpha.2 + "@hyperledger/cactus-core-api": 2.0.0-alpha.2 + "@hyperledger/cactus-plugin-keychain-memory": 2.0.0-alpha.2 + "@hyperledger/cactus-test-tooling": 2.0.0-alpha.2 + "@polkadot/api": 10.9.1 + "@polkadot/api-contract": 10.9.1 + "@polkadot/rpc-provider": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/util": 12.6.2 + "@types/express": 4.17.19 + "@types/http-errors": 2.0.4 + "@types/joi": 14.3.4 + "@types/multer": 1.4.7 + "@types/ssh2": 0.5.44 + "@types/supertest": 2.0.11 + "@types/temp": 0.9.1 + "@types/uuid": 8.3.1 + axios: 0.22.0 + bl: 5.0.0 + eslint: 7.21.0 + express: 4.17.1 + express-openapi-validator: 4.13.1 + form-data: 4.0.0 + fs-extra: 11.2.0 + http-errors: 2.0.0 + http-status-codes: 2.1.4 + joi: 14.3.1 + multer: 1.4.2 + ngo: 2.6.2 + openapi-types: 9.1.0 + prom-client: 13.2.0 + run-time-error: 1.4.0 + supertest: 6.1.6 + temp: 0.9.1 + tslint: 6.1.3 + typescript-optional: 2.0.1 + uuid: 8.3.2 + languageName: unknown + linkType: soft + "@hyperledger/cactus-plugin-ledger-connector-quorum@2.0.0-alpha.2, @hyperledger/cactus-plugin-ledger-connector-quorum@workspace:packages/cactus-plugin-ledger-connector-quorum": version: 0.0.0-use.local resolution: "@hyperledger/cactus-plugin-ledger-connector-quorum@workspace:packages/cactus-plugin-ledger-connector-quorum" @@ -11343,6 +11400,15 @@ __metadata: languageName: node linkType: hard +"@noble/curves@npm:^1.3.0": + version: 1.3.0 + resolution: "@noble/curves@npm:1.3.0" + dependencies: + "@noble/hashes": 1.3.3 + checksum: b65342ee66c4a440eee2978524412eabba9a9efdd16d6370e15218c6a7d80bddf35e66bb57ed52c0dfd32cb9a717b439ab3a72db618f1a0066dfebe3fd12a421 + languageName: node + linkType: hard + "@noble/ed25519@npm:^1.6.0": version: 1.7.3 resolution: "@noble/ed25519@npm:1.7.3" @@ -11378,6 +11444,13 @@ __metadata: languageName: node linkType: hard +"@noble/hashes@npm:1.3.3, @noble/hashes@npm:^1.3.3": + version: 1.3.3 + resolution: "@noble/hashes@npm:1.3.3" + checksum: 8a6496d1c0c64797339bc694ad06cdfaa0f9e56cd0c3f68ae3666cfb153a791a55deb0af9c653c7ed2db64d537aa3e3054629740d2f2338bb1dcb7ab60cd205b + languageName: node + linkType: hard + "@noble/secp256k1@npm:1.7.1, @noble/secp256k1@npm:^1.5.4, @noble/secp256k1@npm:~1.7.0": version: 1.7.1 resolution: "@noble/secp256k1@npm:1.7.1" @@ -12238,6 +12311,433 @@ __metadata: languageName: node linkType: hard +"@polkadot/api-augment@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/api-augment@npm:10.9.1" + dependencies: + "@polkadot/api-base": 10.9.1 + "@polkadot/rpc-augment": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-augment": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/util": ^12.3.1 + tslib: ^2.5.3 + checksum: b0aeed5ebf640c58a252a29a33f12d4c39d0dcdf10b875501012c3b4b05955ed8be85efbf75e17ad237a561e1171821979ffdddf7e6a64cb0806badb2752c190 + languageName: node + linkType: hard + +"@polkadot/api-base@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/api-base@npm:10.9.1" + dependencies: + "@polkadot/rpc-core": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/util": ^12.3.1 + rxjs: ^7.8.1 + tslib: ^2.5.3 + checksum: a761f4ade747a295c16b7e6f24c1bb93e1736aa7fa9f1cb3c651c84d02a99cc62658e83326fa339882423966a55bf0046b74a69a1a4e4567c8d6c1c4db4eb306 + languageName: node + linkType: hard + +"@polkadot/api-contract@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/api-contract@npm:10.9.1" + dependencies: + "@polkadot/api": 10.9.1 + "@polkadot/api-augment": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/types-create": 10.9.1 + "@polkadot/util": ^12.3.1 + "@polkadot/util-crypto": ^12.3.1 + rxjs: ^7.8.1 + tslib: ^2.5.3 + checksum: 2a4b4818e5fd4ef1b385a0ad1144d986b449b531c278ccc3a441770c1e95a2fd24cd5da401d56040dcd594254e2a5c2e4a09a9de5827ee8bb951e3aad9558bed + languageName: node + linkType: hard + +"@polkadot/api-derive@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/api-derive@npm:10.9.1" + dependencies: + "@polkadot/api": 10.9.1 + "@polkadot/api-augment": 10.9.1 + "@polkadot/api-base": 10.9.1 + "@polkadot/rpc-core": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/util": ^12.3.1 + "@polkadot/util-crypto": ^12.3.1 + rxjs: ^7.8.1 + tslib: ^2.5.3 + checksum: 072a43bcc55787beb6c29afe0f011c03cdde3a9b6ac38d972d0b13ff93a1e14198d769a926edfd324c3947735dd8c8fcb7a61629409322230fd8559e7c17a1d7 + languageName: node + linkType: hard + +"@polkadot/api@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/api@npm:10.9.1" + dependencies: + "@polkadot/api-augment": 10.9.1 + "@polkadot/api-base": 10.9.1 + "@polkadot/api-derive": 10.9.1 + "@polkadot/keyring": ^12.3.1 + "@polkadot/rpc-augment": 10.9.1 + "@polkadot/rpc-core": 10.9.1 + "@polkadot/rpc-provider": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-augment": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/types-create": 10.9.1 + "@polkadot/types-known": 10.9.1 + "@polkadot/util": ^12.3.1 + "@polkadot/util-crypto": ^12.3.1 + eventemitter3: ^5.0.1 + rxjs: ^7.8.1 + tslib: ^2.5.3 + checksum: 6b37d9bacf0599bb7c385ddefca929547299a6f1d242ce3215f8480672297c81ec30c251bc9aac3889c5956bd9ef3918d69364819861eec308f4aa347c08110d + languageName: node + linkType: hard + +"@polkadot/keyring@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/keyring@npm:12.6.2" + dependencies: + "@polkadot/util": 12.6.2 + "@polkadot/util-crypto": 12.6.2 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": 12.6.2 + "@polkadot/util-crypto": 12.6.2 + checksum: b8591690cdd2b9c0fea5de88efe0be19190466572ecb696cc284eec61343b1a2fe0b61a7cfad54933730a132f65d7444619bcb2c8620f38bc0246bfaaa5026f4 + languageName: node + linkType: hard + +"@polkadot/networks@npm:12.6.2, @polkadot/networks@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/networks@npm:12.6.2" + dependencies: + "@polkadot/util": 12.6.2 + "@substrate/ss58-registry": ^1.44.0 + tslib: ^2.6.2 + checksum: 7f3dbdd02d8429f82c36ce284ca279af663d45c1a40ce4ce1e38ec2a06fc9d6d27c66d374f32b91ae3058257f33d60701481c9e95ceab19bd2eb70d83465b026 + languageName: node + linkType: hard + +"@polkadot/rpc-augment@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/rpc-augment@npm:10.9.1" + dependencies: + "@polkadot/rpc-core": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/util": ^12.3.1 + tslib: ^2.5.3 + checksum: 4f7b090be6d88ef6a56679a80da856bf007994e2142e16fbac6030132789b5a2411421650935ed4b18334afca399edfc0387135731836c6d9f8420acf510f11b + languageName: node + linkType: hard + +"@polkadot/rpc-core@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/rpc-core@npm:10.9.1" + dependencies: + "@polkadot/rpc-augment": 10.9.1 + "@polkadot/rpc-provider": 10.9.1 + "@polkadot/types": 10.9.1 + "@polkadot/util": ^12.3.1 + rxjs: ^7.8.1 + tslib: ^2.5.3 + checksum: 538a207f5d321b4b18b0580da438598dd78e496dbc7069a776abcc39ede36903981ba2b9897eea73ecfe2f48a4d0cbd5b5cd738b3184f5c333709e6f4603f22a + languageName: node + linkType: hard + +"@polkadot/rpc-provider@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/rpc-provider@npm:10.9.1" + dependencies: + "@polkadot/keyring": ^12.3.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-support": 10.9.1 + "@polkadot/util": ^12.3.1 + "@polkadot/util-crypto": ^12.3.1 + "@polkadot/x-fetch": ^12.3.1 + "@polkadot/x-global": ^12.3.1 + "@polkadot/x-ws": ^12.3.1 + "@substrate/connect": 0.7.26 + eventemitter3: ^5.0.1 + mock-socket: ^9.2.1 + nock: ^13.3.1 + tslib: ^2.5.3 + dependenciesMeta: + "@substrate/connect": + optional: true + checksum: 4521ba64a1e69ed323910796a4598755e8101704aae3be33b6c363be4ebb9ea1a99ced17b8cd9fa3ab15abf5900e1055279f532f47b8472e8a143a299bfa046d + languageName: node + linkType: hard + +"@polkadot/types-augment@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/types-augment@npm:10.9.1" + dependencies: + "@polkadot/types": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/util": ^12.3.1 + tslib: ^2.5.3 + checksum: d643f83ab0a9498267037d95b878fa4e3b0087882195c3bd609038e8c934a092d9c82f7164ac97989305805aabe0d9186736c50a372498c81c22b3d7f4cfcccb + languageName: node + linkType: hard + +"@polkadot/types-codec@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/types-codec@npm:10.9.1" + dependencies: + "@polkadot/util": ^12.3.1 + "@polkadot/x-bigint": ^12.3.1 + tslib: ^2.5.3 + checksum: ac11b770fa4328f55daf6dd78fc8fc4d6906fb0d4b2bf92eaece58332c74f2b178d598a310a6dd068c72856acefddf5f7d23cac56991fa12f61d6853fb73d582 + languageName: node + linkType: hard + +"@polkadot/types-create@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/types-create@npm:10.9.1" + dependencies: + "@polkadot/types-codec": 10.9.1 + "@polkadot/util": ^12.3.1 + tslib: ^2.5.3 + checksum: 43f8fbd70a7891d6b49f1edb00b4a918c21924f2c1e44eb81ef7c9327e1fcc7eac65dbc2a9d0e3ba49079fdddda5498115e47f5fd99ec2a91f79c7f305bf553a + languageName: node + linkType: hard + +"@polkadot/types-known@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/types-known@npm:10.9.1" + dependencies: + "@polkadot/networks": ^12.3.1 + "@polkadot/types": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/types-create": 10.9.1 + "@polkadot/util": ^12.3.1 + tslib: ^2.5.3 + checksum: 8a3dd0dead1759112b9011c5ff47bf9fa0f5a00d0d5cba841d724494a9434a2f565fad8ab654ae8cc3949a10c28f3966034bfc23e493b7cc373d3532de508953 + languageName: node + linkType: hard + +"@polkadot/types-support@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/types-support@npm:10.9.1" + dependencies: + "@polkadot/util": ^12.3.1 + tslib: ^2.5.3 + checksum: f5df33f215f529c33d4fd7ad7d6877a4567954488971c2986da416b6578ccb6d5c6eeadab4602abe0e3ce17373cdd6de0ce6f09529852b6e2fd6bc28b9183f9b + languageName: node + linkType: hard + +"@polkadot/types@npm:10.9.1": + version: 10.9.1 + resolution: "@polkadot/types@npm:10.9.1" + dependencies: + "@polkadot/keyring": ^12.3.1 + "@polkadot/types-augment": 10.9.1 + "@polkadot/types-codec": 10.9.1 + "@polkadot/types-create": 10.9.1 + "@polkadot/util": ^12.3.1 + "@polkadot/util-crypto": ^12.3.1 + rxjs: ^7.8.1 + tslib: ^2.5.3 + checksum: c9b0873b52f33c5d7913bc1e474c67d797411ac592c10af987dfecfee7480aeda02b9fc100ff506bc8af704a7fc239162a8ec7eec580e2e7a62ac7f7b95f3900 + languageName: node + linkType: hard + +"@polkadot/util-crypto@npm:12.6.2, @polkadot/util-crypto@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/util-crypto@npm:12.6.2" + dependencies: + "@noble/curves": ^1.3.0 + "@noble/hashes": ^1.3.3 + "@polkadot/networks": 12.6.2 + "@polkadot/util": 12.6.2 + "@polkadot/wasm-crypto": ^7.3.2 + "@polkadot/wasm-util": ^7.3.2 + "@polkadot/x-bigint": 12.6.2 + "@polkadot/x-randomvalues": 12.6.2 + "@scure/base": ^1.1.5 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": 12.6.2 + checksum: 63d4bd9bdc3a7089a0a68555cd6a510b8da3cfab142a8f96ba4b43d5d1db2a543433079bc88c2daf15a329d19ba2cc60f6cca6dbebaefd25e96169cb6343794b + languageName: node + linkType: hard + +"@polkadot/util@npm:12.6.2, @polkadot/util@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/util@npm:12.6.2" + dependencies: + "@polkadot/x-bigint": 12.6.2 + "@polkadot/x-global": 12.6.2 + "@polkadot/x-textdecoder": 12.6.2 + "@polkadot/x-textencoder": 12.6.2 + "@types/bn.js": ^5.1.5 + bn.js: ^5.2.1 + tslib: ^2.6.2 + checksum: a42a226f3c299026458d82e48516abf59c1cd8638167edaa3fc1a17aec0ebab203e0ad68a096a4a4fa188afd55093535a98e5083d682a79242a3c5ad79342599 + languageName: node + linkType: hard + +"@polkadot/wasm-bridge@npm:7.3.2": + version: 7.3.2 + resolution: "@polkadot/wasm-bridge@npm:7.3.2" + dependencies: + "@polkadot/wasm-util": 7.3.2 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": "*" + "@polkadot/x-randomvalues": "*" + checksum: 8c68b78cbd62347ebdf3fa66f2ffd1f7e883df71d770f5099ff652b083a79f1d7e9e7826a6acd8e986e9da0b07c0170a3f77b6a35726c6b24d856e3f8d08d201 + languageName: node + linkType: hard + +"@polkadot/wasm-crypto-asmjs@npm:7.3.2": + version: 7.3.2 + resolution: "@polkadot/wasm-crypto-asmjs@npm:7.3.2" + dependencies: + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": "*" + checksum: 669ea001565301f9b1a8feecb0e301c854fc318e5605316b57be7e83d717e7ee8ac460001cd44b18075a3d028c32c4a605c0e0e2e95ae00865282321b009ed26 + languageName: node + linkType: hard + +"@polkadot/wasm-crypto-init@npm:7.3.2": + version: 7.3.2 + resolution: "@polkadot/wasm-crypto-init@npm:7.3.2" + dependencies: + "@polkadot/wasm-bridge": 7.3.2 + "@polkadot/wasm-crypto-asmjs": 7.3.2 + "@polkadot/wasm-crypto-wasm": 7.3.2 + "@polkadot/wasm-util": 7.3.2 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": "*" + "@polkadot/x-randomvalues": "*" + checksum: af7bc62bba16f1fbbfd76601ecf18ed8f4dfc685807e2e89ef8e8d02f824d1a1ed1635e9c2448c6c12a9a183192b18943f9ce077d6b7781c4d43cdb5c45c9161 + languageName: node + linkType: hard + +"@polkadot/wasm-crypto-wasm@npm:7.3.2": + version: 7.3.2 + resolution: "@polkadot/wasm-crypto-wasm@npm:7.3.2" + dependencies: + "@polkadot/wasm-util": 7.3.2 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": "*" + checksum: e112ea3d4f8858a95fdaad47341b422db3db3256b7e7d709d1c3e0bc4c4bbdf81028eaa556b688078b32ff15be33af093b903c680f54eb1552072afede621a6a + languageName: node + linkType: hard + +"@polkadot/wasm-crypto@npm:^7.3.2": + version: 7.3.2 + resolution: "@polkadot/wasm-crypto@npm:7.3.2" + dependencies: + "@polkadot/wasm-bridge": 7.3.2 + "@polkadot/wasm-crypto-asmjs": 7.3.2 + "@polkadot/wasm-crypto-init": 7.3.2 + "@polkadot/wasm-crypto-wasm": 7.3.2 + "@polkadot/wasm-util": 7.3.2 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": "*" + "@polkadot/x-randomvalues": "*" + checksum: 574006cdcc3e76af28cc79102726a79fdcd765ca5b45cbc4807d70917d82131b59f50b5cc07bd165b2863ed131b8764fef74b00c68ba5ec30a21c04c72061f8f + languageName: node + linkType: hard + +"@polkadot/wasm-util@npm:7.3.2, @polkadot/wasm-util@npm:^7.3.2": + version: 7.3.2 + resolution: "@polkadot/wasm-util@npm:7.3.2" + dependencies: + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": "*" + checksum: 44bd445043714aac6d184ce02d62fbdb97a117fd4d8bdbf3f2c1d14f6911a7d87ed6bb4682035eb757524ade995f7f4f8aaa07c8a194f761884ded25a6b383a9 + languageName: node + linkType: hard + +"@polkadot/x-bigint@npm:12.6.2, @polkadot/x-bigint@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/x-bigint@npm:12.6.2" + dependencies: + "@polkadot/x-global": 12.6.2 + tslib: ^2.6.2 + checksum: 12b2d5c3a7b994f5bd4f7aeda9e268384b04bd080892400c65b88fb5aa4951df6c4abe3baf9820f3adf3da92e2add710858dd35dcd597d2527bbfd1cd0efe534 + languageName: node + linkType: hard + +"@polkadot/x-fetch@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/x-fetch@npm:12.6.2" + dependencies: + "@polkadot/x-global": 12.6.2 + node-fetch: ^3.3.2 + tslib: ^2.6.2 + checksum: 2f0269b17ebbb907f4f4fa777898fd8ea16ecd37abfc2c0b69cfc49bd5ab0ed38cf836a4941e85f9100192f7005731a9a8c6b135799efd17b4261c3cc1ebf844 + languageName: node + linkType: hard + +"@polkadot/x-global@npm:12.6.2, @polkadot/x-global@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/x-global@npm:12.6.2" + dependencies: + tslib: ^2.6.2 + checksum: eb17e039cb1668743c84f5eafbf518cf6248e93090e4877f81f338b418b3e6b0173f2414c62bd9cbe7bf8911ec566527ca7c49c4354ba90d57e62e90195329d0 + languageName: node + linkType: hard + +"@polkadot/x-randomvalues@npm:12.6.2": + version: 12.6.2 + resolution: "@polkadot/x-randomvalues@npm:12.6.2" + dependencies: + "@polkadot/x-global": 12.6.2 + tslib: ^2.6.2 + peerDependencies: + "@polkadot/util": 12.6.2 + "@polkadot/wasm-util": "*" + checksum: 7faccf2dbcf0c7383b5ecfd7beb098c8c8ad5cf4c8f5bafd601657f8271af8f00b66741531ecf8b2f7c59911d96f77e358184a7c5034c70bf387a8e929a4c210 + languageName: node + linkType: hard + +"@polkadot/x-textdecoder@npm:12.6.2": + version: 12.6.2 + resolution: "@polkadot/x-textdecoder@npm:12.6.2" + dependencies: + "@polkadot/x-global": 12.6.2 + tslib: ^2.6.2 + checksum: c7e4b7f7ff943095a96bef3e3e56216d33d6ff38c965931356a06d01594b2c523ccbeada697a31b5457b134e578618f35425e0883f45187adffa98df99a45f27 + languageName: node + linkType: hard + +"@polkadot/x-textencoder@npm:12.6.2": + version: 12.6.2 + resolution: "@polkadot/x-textencoder@npm:12.6.2" + dependencies: + "@polkadot/x-global": 12.6.2 + tslib: ^2.6.2 + checksum: d3eacdc0eb2e1ef8b8132d52a1f1033be62bc64360753a117f2e6517ccf7c9cde628558bbd016a73836eacd91cb1e2ac382dce0ce9c8d32c2f7db3fcc8863911 + languageName: node + linkType: hard + +"@polkadot/x-ws@npm:^12.3.1": + version: 12.6.2 + resolution: "@polkadot/x-ws@npm:12.6.2" + dependencies: + "@polkadot/x-global": 12.6.2 + tslib: ^2.6.2 + ws: ^8.15.1 + checksum: a6bddc7ac81690f222fbc192f87f2d9b951d67414ea31a0377fb20844db8fde05d7771df5291633417aa4616bf968a31005ff22d416b2d4fecda2109f820abf7 + languageName: node + linkType: hard + "@popperjs/core@npm:^2.11.8": version: 2.11.8 resolution: "@popperjs/core@npm:2.11.8" @@ -12584,6 +13084,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:^1.1.5": + version: 1.1.5 + resolution: "@scure/base@npm:1.1.5" + checksum: 9e9ee6088cb3aa0fb91f5a48497d26682c7829df3019b1251d088d166d7a8c0f941c68aaa8e7b96bbad20c71eb210397cb1099062cde3e29d4bad6b975c18519 + languageName: node + linkType: hard + "@scure/base@npm:~1.1.0": version: 1.1.1 resolution: "@scure/base@npm:1.1.1" @@ -13064,6 +13571,31 @@ __metadata: languageName: node linkType: hard +"@substrate/connect-extension-protocol@npm:^1.0.1": + version: 1.0.1 + resolution: "@substrate/connect-extension-protocol@npm:1.0.1" + checksum: 116dee587e81e832e14c25038bd849438c9493c6089aa6c1bf1760780d463880d44d362ed983d57ac3695368ac46f3c9df3dbaed92f36de89626c9735cecd1e4 + languageName: node + linkType: hard + +"@substrate/connect@npm:0.7.26": + version: 0.7.26 + resolution: "@substrate/connect@npm:0.7.26" + dependencies: + "@substrate/connect-extension-protocol": ^1.0.1 + eventemitter3: ^4.0.7 + smoldot: 1.0.4 + checksum: 3179d241f073318d5973deb61c9c8d9b89ae28909a594b6b9fbcdfffd030a70ba58e8428eaa9d72484810bad10c93de1ad9c440b878d0fcfaaf4559d2e6f4502 + languageName: node + linkType: hard + +"@substrate/ss58-registry@npm:^1.44.0": + version: 1.46.0 + resolution: "@substrate/ss58-registry@npm:1.46.0" + checksum: 10e9bfd8d509abf78759d3e62cc41de515fc832dc2eab503071dda4cf0fb71c9d52247d0c32f93af6f8c4463add50d7f7f3483b52cbf43de621ac255226efb5f + languageName: node + linkType: hard + "@supabase/functions-js@npm:^1.3.4": version: 1.3.4 resolution: "@supabase/functions-js@npm:1.3.4" @@ -13900,6 +14432,15 @@ __metadata: languageName: node linkType: hard +"@types/bn.js@npm:^5.1.5": + version: 5.1.5 + resolution: "@types/bn.js@npm:5.1.5" + dependencies: + "@types/node": "*" + checksum: c87b28c4af74545624f8a3dae5294b16aa190c222626e8d4b2e327b33b1a3f1eeb43e7a24d914a9774bca43d8cd6e1cb0325c1f4b3a244af6693a024e1d918e6 + languageName: node + linkType: hard + "@types/body-parser@npm:*, @types/body-parser@npm:1.19.2": version: 1.19.2 resolution: "@types/body-parser@npm:1.19.2" @@ -14048,6 +14589,13 @@ __metadata: languageName: node linkType: hard +"@types/cookiejar@npm:^2.1.5": + version: 2.1.5 + resolution: "@types/cookiejar@npm:2.1.5" + checksum: 04d5990e87b6387532d15a87d9ec9b2eb783039291193863751dcfd7fc723a3b3aa30ce4c06b03975cba58632e933772f1ff031af23eaa3ac7f94e71afa6e073 + languageName: node + linkType: hard + "@types/cordova@latest": version: 0.0.34 resolution: "@types/cordova@npm:0.0.34" @@ -14536,6 +15084,13 @@ __metadata: languageName: node linkType: hard +"@types/joi@npm:14.3.4": + version: 14.3.4 + resolution: "@types/joi@npm:14.3.4" + checksum: 084c0fe211b43a84d25317d772bb8f6426382f1975cb4065fbfa1da7a64c600e9068a9b13ec2a32ddbe71d14f25c90da14a196651acb27e35d02856dbf6d4798 + languageName: node + linkType: hard + "@types/js-yaml@npm:4.0.3": version: 4.0.3 resolution: "@types/js-yaml@npm:4.0.3" @@ -14702,6 +15257,13 @@ __metadata: languageName: node linkType: hard +"@types/methods@npm:^1.1.4": + version: 1.1.4 + resolution: "@types/methods@npm:1.1.4" + checksum: ad2a7178486f2fd167750f3eb920ab032a947ff2e26f55c86670a6038632d790b46f52e5b6ead5823f1e53fc68028f1e9ddd15cfead7903e04517c88debd72b1 + languageName: node + linkType: hard + "@types/mime@npm:*": version: 3.0.1 resolution: "@types/mime@npm:3.0.1" @@ -15332,6 +15894,16 @@ __metadata: languageName: node linkType: hard +"@types/ssh2@npm:0.5.44": + version: 0.5.44 + resolution: "@types/ssh2@npm:0.5.44" + dependencies: + "@types/node": "*" + "@types/ssh2-streams": "*" + checksum: bb45290b67b9fc3ca6539e23179e378c2400df1dfa3549b13cb9263c511002db2dea9d812e1c494291671defb6cbc130edde34020558380e5f2e13afca0f60e1 + languageName: node + linkType: hard + "@types/ssh2@npm:0.5.47": version: 0.5.47 resolution: "@types/ssh2@npm:0.5.47" @@ -15358,6 +15930,26 @@ __metadata: languageName: node linkType: hard +"@types/superagent@npm:*": + version: 8.1.4 + resolution: "@types/superagent@npm:8.1.4" + dependencies: + "@types/cookiejar": ^2.1.5 + "@types/methods": ^1.1.4 + "@types/node": "*" + checksum: e1c47f20c93a87cf14a016fa1a154b538291b0ed370f6eb4255ca58a693a6d0470896079d86e58e3489e3107e5796370b6208a983e90696549709c43cc51bfdf + languageName: node + linkType: hard + +"@types/supertest@npm:2.0.11": + version: 2.0.11 + resolution: "@types/supertest@npm:2.0.11" + dependencies: + "@types/superagent": "*" + checksum: 291abc0d37abe833d517fcfd0c22d51e7d5ffea85ce990603a0d058afa7fe2465b1251d50642ddfd640f66d047029af512793215b612c39adbee72fae5b2ef4f + languageName: node + linkType: hard + "@types/tape-promise@npm:4.0.1": version: 4.0.1 resolution: "@types/tape-promise@npm:4.0.1" @@ -15445,6 +16037,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:8.3.1": + version: 8.3.1 + resolution: "@types/uuid@npm:8.3.1" + checksum: b41bdc5e86c6f0f1899306be10455636da0f2168c9489b869edd6837ddeb7c0e501b1ff7d857402462986bada2a379125743dd895fa801d03437cd632116a373 + languageName: node + linkType: hard + "@types/uuid@npm:8.3.4": version: 8.3.4 resolution: "@types/uuid@npm:8.3.4" @@ -16961,7 +17560,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.10.2, ajv@npm:^6.11.0, ajv@npm:^6.12.2, ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.5": +"ajv@npm:^6.10.0, ajv@npm:^6.10.2, ajv@npm:^6.11.0, ajv@npm:^6.12.2, ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.5, ajv@npm:^6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -19755,6 +20354,16 @@ __metadata: languageName: node linkType: hard +"busboy@npm:^0.2.11": + version: 0.2.14 + resolution: "busboy@npm:0.2.14" + dependencies: + dicer: 0.2.5 + readable-stream: 1.1.x + checksum: 9df9fca6d96dab9edd03f568bde31f215794e6fabd73c75d2b39a4be2e8b73a45121d987dea5db881f3fb499737c261b372106fe72d08b8db92afaed8d751165 + languageName: node + linkType: hard + "busboy@npm:^1.0.0, busboy@npm:^1.6.0": version: 1.6.0 resolution: "busboy@npm:1.6.0" @@ -21291,6 +21900,13 @@ __metadata: languageName: node linkType: hard +"component-emitter@npm:^1.3.0": + version: 1.3.1 + resolution: "component-emitter@npm:1.3.1" + checksum: 94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d + languageName: node + linkType: hard + "compressible@npm:~2.0.16": version: 2.0.18 resolution: "compressible@npm:2.0.18" @@ -21509,7 +22125,7 @@ __metadata: languageName: node linkType: hard -"content-type@npm:^1.0.5, content-type@npm:~1.0.5": +"content-type@npm:^1.0.4, content-type@npm:^1.0.5, content-type@npm:~1.0.5": version: 1.0.5 resolution: "content-type@npm:1.0.5" checksum: 566271e0a251642254cde0f845f9dd4f9856e52d988f4eb0d0dcffbb7a1f8ec98de7a5215fc628f3bce30fe2fb6fd2bc064b562d721658c59b544e2d34ea2766 @@ -21746,7 +22362,7 @@ __metadata: languageName: node linkType: hard -"cookiejar@npm:^2.1.1": +"cookiejar@npm:^2.1.1, cookiejar@npm:^2.1.2": version: 2.1.4 resolution: "cookiejar@npm:2.1.4" checksum: c4442111963077dc0e5672359956d6556a195d31cbb35b528356ce5f184922b99ac48245ac05ed86cf993f7df157c56da10ab3efdadfed79778a0d9b1b092d5b @@ -23576,6 +24192,16 @@ __metadata: languageName: node linkType: hard +"dicer@npm:0.2.5": + version: 0.2.5 + resolution: "dicer@npm:0.2.5" + dependencies: + readable-stream: 1.1.x + streamsearch: 0.1.2 + checksum: a6f0ce9ac5099c7ffeaec7398d711eea1dd803eb99036d0f05342e9ed46a4235a5ed0ea01ad5d6c785fdb0aae6d61d2722e6e64f9fabdfe39885f7f52eb635ee + languageName: node + linkType: hard + "did-resolver@npm:^4.0.0, did-resolver@npm:^4.1.0": version: 4.1.0 resolution: "did-resolver@npm:4.1.0" @@ -25670,6 +26296,53 @@ __metadata: languageName: node linkType: hard +"eslint@npm:7.21.0": + version: 7.21.0 + resolution: "eslint@npm:7.21.0" + dependencies: + "@babel/code-frame": 7.12.11 + "@eslint/eslintrc": ^0.4.0 + ajv: ^6.10.0 + chalk: ^4.0.0 + cross-spawn: ^7.0.2 + debug: ^4.0.1 + doctrine: ^3.0.0 + enquirer: ^2.3.5 + eslint-scope: ^5.1.1 + eslint-utils: ^2.1.0 + eslint-visitor-keys: ^2.0.0 + espree: ^7.3.1 + esquery: ^1.4.0 + esutils: ^2.0.2 + file-entry-cache: ^6.0.1 + functional-red-black-tree: ^1.0.1 + glob-parent: ^5.0.0 + globals: ^12.1.0 + ignore: ^4.0.6 + import-fresh: ^3.0.0 + imurmurhash: ^0.1.4 + is-glob: ^4.0.0 + js-yaml: ^3.13.1 + json-stable-stringify-without-jsonify: ^1.0.1 + levn: ^0.4.1 + lodash: ^4.17.20 + minimatch: ^3.0.4 + natural-compare: ^1.4.0 + optionator: ^0.9.1 + progress: ^2.0.0 + regexpp: ^3.1.0 + semver: ^7.2.1 + strip-ansi: ^6.0.0 + strip-json-comments: ^3.1.0 + table: ^6.0.4 + text-table: ^0.2.0 + v8-compile-cache: ^2.0.3 + bin: + eslint: bin/eslint.js + checksum: 2ac78e255ff27c6462420adff9b6c6bf8d785ce121d5d2a41d9eddd4e9584027f70cfca1f4c30eaa144c7980cbf7017be1c2c6778b9569cb265fcd37b821146c + languageName: node + linkType: hard + "eslint@npm:7.32.0": version: 7.32.0 resolution: "eslint@npm:7.32.0" @@ -26477,7 +27150,7 @@ __metadata: languageName: node linkType: hard -"eventemitter3@npm:^4.0.0": +"eventemitter3@npm:^4.0.0, eventemitter3@npm:^4.0.7": version: 4.0.7 resolution: "eventemitter3@npm:4.0.7" checksum: 1875311c42fcfe9c707b2712c32664a245629b42bb0a5a84439762dd0fd637fc54d078155ea83c2af9e0323c9ac13687e03cfba79b03af9f40c89b4960099374 @@ -26792,6 +27465,26 @@ __metadata: languageName: node linkType: hard +"express-openapi-validator@npm:4.13.1": + version: 4.13.1 + resolution: "express-openapi-validator@npm:4.13.1" + dependencies: + "@types/multer": ^1.4.7 + ajv: ^6.12.6 + content-type: ^1.0.4 + json-schema-ref-parser: ^9.0.9 + lodash.clonedeep: ^4.5.0 + lodash.get: ^4.4.2 + lodash.uniq: ^4.5.0 + lodash.zipobject: ^4.1.3 + media-typer: ^1.1.0 + multer: ^1.4.3 + ono: ^7.1.3 + path-to-regexp: ^6.2.0 + checksum: 5e1eb8f5e68727925a56aeac07716354940d3615d85ff219bebe076afed15a2b35a785774ae22128dd6b6e44b74148342e7b8d5bcb6473e2562bb308073bb541 + languageName: node + linkType: hard + "express-openapi-validator@npm:5.0.4": version: 5.0.4 resolution: "express-openapi-validator@npm:5.0.4" @@ -27273,7 +27966,7 @@ __metadata: languageName: node linkType: hard -"fast-safe-stringify@npm:2.1.1, fast-safe-stringify@npm:^2.1.1": +"fast-safe-stringify@npm:2.1.1, fast-safe-stringify@npm:^2.0.7, fast-safe-stringify@npm:^2.1.1": version: 2.1.1 resolution: "fast-safe-stringify@npm:2.1.1" checksum: a851cbddc451745662f8f00ddb622d6766f9bd97642dabfd9a405fb0d646d69fc0b9a1243cbf67f5f18a39f40f6fa821737651ff1bceeba06c9992ca2dc5bd3d @@ -27994,6 +28687,13 @@ __metadata: languageName: node linkType: hard +"formidable@npm:^1.2.2": + version: 1.2.6 + resolution: "formidable@npm:1.2.6" + checksum: 2b68ed07ba88302b9c63f8eda94f19a460cef6017bfda48348f09f41d2a36660c9353137991618e0e4c3db115b41e4b8f6fa63bc973b7a7c91dec66acdd02a56 + languageName: node + linkType: hard + "forwarded@npm:0.2.0": version: 0.2.0 resolution: "forwarded@npm:0.2.0" @@ -28091,6 +28791,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:11.2.0, fs-extra@npm:^11.2.0": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: ^4.2.0 + jsonfile: ^6.0.1 + universalify: ^2.0.0 + checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 + languageName: node + linkType: hard + "fs-extra@npm:^0.30.0": version: 0.30.0 resolution: "fs-extra@npm:0.30.0" @@ -28115,17 +28826,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.2.0": - version: 11.2.0 - resolution: "fs-extra@npm:11.2.0" - dependencies: - graceful-fs: ^4.2.0 - jsonfile: ^6.0.1 - universalify: ^2.0.0 - checksum: b12e42fa40ba47104202f57b8480dd098aa931c2724565e5e70779ab87605665594e76ee5fb00545f772ab9ace167fe06d2ab009c416dc8c842c5ae6df7aa7e8 - languageName: node - linkType: hard - "fs-extra@npm:^4.0.2": version: 4.0.3 resolution: "fs-extra@npm:4.0.3" @@ -33959,6 +34659,15 @@ __metadata: languageName: node linkType: hard +"json-schema-ref-parser@npm:^9.0.9": + version: 9.0.9 + resolution: "json-schema-ref-parser@npm:9.0.9" + dependencies: + "@apidevtools/json-schema-ref-parser": 9.0.9 + checksum: e05166a84c702f54f192edb2eb2e39236c3b03c30561777d63fd156ecd3aa3d2fffc0806a5703384bfba3c78800b1dc05f8da1ea25e6470b35a823210f7d48c4 + languageName: node + linkType: hard + "json-schema-traverse@npm:^0.3.0": version: 0.3.1 resolution: "json-schema-traverse@npm:0.3.1" @@ -36658,6 +37367,15 @@ __metadata: languageName: node linkType: hard +"mime@npm:^2.4.6": + version: 2.6.0 + resolution: "mime@npm:2.6.0" + bin: + mime: cli.js + checksum: 1497ba7b9f6960694268a557eae24b743fd2923da46ec392b042469f4b901721ba0adcf8b0d3c2677839d0e243b209d76e5edcbd09cfdeffa2dfb6bb4df4b862 + languageName: node + linkType: hard + "mimic-fn@npm:^1.0.0": version: 1.2.0 resolution: "mimic-fn@npm:1.2.0" @@ -37041,7 +37759,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^0.5.0, mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.4, mkdirp@npm:^0.5.5, mkdirp@npm:~0.5.1": +"mkdirp@npm:^0.5.0, mkdirp@npm:^0.5.1, mkdirp@npm:^0.5.3, mkdirp@npm:^0.5.4, mkdirp@npm:^0.5.5, mkdirp@npm:~0.5.1": version: 0.5.6 resolution: "mkdirp@npm:0.5.6" dependencies: @@ -37154,7 +37872,7 @@ __metadata: languageName: node linkType: hard -"mock-socket@npm:^9.3.0": +"mock-socket@npm:^9.2.1, mock-socket@npm:^9.3.0": version: 9.3.1 resolution: "mock-socket@npm:9.3.1" checksum: cb2dde4fc5dde280dd5ccb78eaaa223382ee16437f46b86558017655584ad08c22e733bde2dd5cc86927def506b6caeb0147e3167b9a62d70d5cf19d44103853 @@ -37257,6 +37975,22 @@ __metadata: languageName: node linkType: hard +"multer@npm:1.4.2": + version: 1.4.2 + resolution: "multer@npm:1.4.2" + dependencies: + append-field: ^1.0.0 + busboy: ^0.2.11 + concat-stream: ^1.5.2 + mkdirp: ^0.5.1 + object-assign: ^4.1.1 + on-finished: ^2.3.0 + type-is: ^1.6.4 + xtend: ^4.0.0 + checksum: a77ba79ec96b8376fdd09531c1cfd36f1d04e195b5e944a2cd4979c992cdc9b521887abed0893f75a21c59bb4dffe6356046da966059c268801d1f7c83e6ea16 + languageName: node + linkType: hard + "multer@npm:1.4.5-lts.1, multer@npm:^1.4.5-lts.1": version: 1.4.5-lts.1 resolution: "multer@npm:1.4.5-lts.1" @@ -37272,6 +38006,22 @@ __metadata: languageName: node linkType: hard +"multer@npm:^1.4.3": + version: 1.4.4 + resolution: "multer@npm:1.4.4" + dependencies: + append-field: ^1.0.0 + busboy: ^0.2.11 + concat-stream: ^1.5.2 + mkdirp: ^0.5.4 + object-assign: ^4.1.1 + on-finished: ^2.3.0 + type-is: ^1.6.4 + xtend: ^4.0.0 + checksum: b5550d250aeee9c4d630eaecd133af0899239f6b10cec4b448ddd0a808025b383520b8227198a8612f60c2cd2094bcb60de93d973084f889d4e40efe6dbd641e + languageName: node + linkType: hard + "multibase@npm:^0.7.0": version: 0.7.0 resolution: "multibase@npm:0.7.0" @@ -37684,6 +38434,21 @@ __metadata: languageName: node linkType: hard +"ngo@npm:2.6.2": + version: 2.6.2 + resolution: "ngo@npm:2.6.2" + dependencies: + execa: ^4.0.0 + go-bin: ^1.4.0 + go-versions: ^1.3.2 + bin: + ngo: cli.js + ngo-binary: cli-binary.js + ngo-update: cli-update.js + checksum: 17cf87495689d45eade7f1675e6a050770fdc7ec1e09f66ab62faa3f661c85a4537d76f4add5e3ad7bf2279b226ea6688b511ecf152998208e6ea9b1a4715cd8 + languageName: node + linkType: hard + "ngo@npm:2.7.0": version: 2.7.0 resolution: "ngo@npm:2.7.0" @@ -37751,6 +38516,17 @@ __metadata: languageName: node linkType: hard +"nock@npm:^13.3.1": + version: 13.5.4 + resolution: "nock@npm:13.5.4" + dependencies: + debug: ^4.1.0 + json-stringify-safe: ^5.0.1 + propagate: ^2.0.0 + checksum: d31f924e34c87ae985edfb7b5a56e8a4dcfc3a072334ceb6d686326581f93090b3e23492663a64ce61b8df4f365b113231d926bc300bcfe9e5eb309c3e4b8628 + languageName: node + linkType: hard + "node-abi@npm:^2.7.0": version: 2.30.1 resolution: "node-abi@npm:2.30.1" @@ -39073,7 +39849,7 @@ __metadata: languageName: node linkType: hard -"on-finished@npm:2.4.1": +"on-finished@npm:2.4.1, on-finished@npm:^2.3.0": version: 2.4.1 resolution: "on-finished@npm:2.4.1" dependencies: @@ -39839,6 +40615,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:^2.0.4": + version: 2.1.0 + resolution: "pako@npm:2.1.0" + checksum: 71666548644c9a4d056bcaba849ca6fd7242c6cf1af0646d3346f3079a1c7f4a66ffec6f7369ee0dc88f61926c10d6ab05da3e1fca44b83551839e89edd75a3e + languageName: node + linkType: hard + "param-case@npm:^2.1.0": version: 2.1.1 resolution: "param-case@npm:2.1.1" @@ -42159,6 +42942,13 @@ __metadata: languageName: node linkType: hard +"propagate@npm:^2.0.0": + version: 2.0.1 + resolution: "propagate@npm:2.0.1" + checksum: c4febaee2be0979e82fb6b3727878fd122a98d64a7fa3c9d09b0576751b88514a9e9275b1b92e76b364d488f508e223bd7e1dcdc616be4cdda876072fbc2a96c + languageName: node + linkType: hard + "proto-list@npm:~1.2.1": version: 1.2.4 resolution: "proto-list@npm:1.2.4" @@ -42398,7 +43188,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.11.0": +"qs@npm:^6.11.0, qs@npm:^6.9.4": version: 6.11.2 resolution: "qs@npm:6.11.2" dependencies: @@ -43054,7 +43844,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:1.1.14, readable-stream@npm:^1.0.26-4, readable-stream@npm:^1.0.33": +"readable-stream@npm:1.1.14, readable-stream@npm:1.1.x, readable-stream@npm:^1.0.26-4, readable-stream@npm:^1.0.33": version: 1.1.14 resolution: "readable-stream@npm:1.1.14" dependencies: @@ -45678,6 +46468,16 @@ __metadata: languageName: node linkType: hard +"smoldot@npm:1.0.4": + version: 1.0.4 + resolution: "smoldot@npm:1.0.4" + dependencies: + pako: ^2.0.4 + ws: ^8.8.1 + checksum: 81ecc38b98f7ac4dd093753e85956262608dca3c8a288c20a25fe1762a6afcdbe6f3622ea30a346df3f4145e0900ef0595e56e96e9e0de83c59f0649d1ab4786 + languageName: node + linkType: hard + "snake-case@npm:^2.1.0": version: 2.1.0 resolution: "snake-case@npm:2.1.0" @@ -46723,6 +47523,13 @@ __metadata: languageName: node linkType: hard +"streamsearch@npm:0.1.2": + version: 0.1.2 + resolution: "streamsearch@npm:0.1.2" + checksum: d2db57cbfbf7947ab9c75a7b4c80a8ef8d24850cf0a1a24258bb6956c97317ce1eab7dbcbf9c5aba3e6198611af1053b02411057bbedb99bf9c64b8275248997 + languageName: node + linkType: hard + "streamsearch@npm:^1.1.0": version: 1.1.0 resolution: "streamsearch@npm:1.1.0" @@ -47229,6 +48036,35 @@ __metadata: languageName: node linkType: hard +"superagent@npm:^6.1.0": + version: 6.1.0 + resolution: "superagent@npm:6.1.0" + dependencies: + component-emitter: ^1.3.0 + cookiejar: ^2.1.2 + debug: ^4.1.1 + fast-safe-stringify: ^2.0.7 + form-data: ^3.0.0 + formidable: ^1.2.2 + methods: ^1.1.2 + mime: ^2.4.6 + qs: ^6.9.4 + readable-stream: ^3.6.0 + semver: ^7.3.2 + checksum: 32ca1bc9805679cddeffdf5cf369da47359a0d38ee45ea668bba4116e17c247739e4084db9cc88217dd594a816e766a3dbf2431de017fbac0bc80efd6af30c1d + languageName: node + linkType: hard + +"supertest@npm:6.1.6": + version: 6.1.6 + resolution: "supertest@npm:6.1.6" + dependencies: + methods: ^1.1.2 + superagent: ^6.1.0 + checksum: 51d11b794a022b49f0f9664e6d8ffef5e8d18467f65d2b4326e52ec96f0801d7066bf9a97eb06e8b6cd3eb6f662ee5bed937cd5764ab0617a822d7ee4c72ff36 + languageName: node + linkType: hard + "supports-color@npm:5.4.0": version: 5.4.0 resolution: "supports-color@npm:5.4.0" @@ -47525,6 +48361,19 @@ __metadata: languageName: node linkType: hard +"table@npm:^6.0.4": + version: 6.8.1 + resolution: "table@npm:6.8.1" + dependencies: + ajv: ^8.0.1 + lodash.truncate: ^4.4.2 + slice-ansi: ^4.0.0 + string-width: ^4.2.3 + strip-ansi: ^6.0.1 + checksum: 08249c7046125d9d0a944a6e96cfe9ec66908d6b8a9db125531be6eb05fa0de047fd5542e9d43b4f987057f00a093b276b8d3e19af162a9c40db2681058fd306 + languageName: node + linkType: hard + "table@npm:^6.0.9": version: 6.8.0 resolution: "table@npm:6.8.0" @@ -47896,6 +48745,15 @@ __metadata: languageName: node linkType: hard +"temp@npm:0.9.1": + version: 0.9.1 + resolution: "temp@npm:0.9.1" + dependencies: + rimraf: ~2.6.2 + checksum: 568be30ec54f2a9d74b10caebb0c8e169577741122822aaeee13150af83fab2a73954ef12d7772b85f136529ffa80e940a51b42735d010dea0a634fbc70c0223 + languageName: node + linkType: hard + "temp@npm:0.9.4": version: 0.9.4 resolution: "temp@npm:0.9.4" @@ -48713,14 +49571,14 @@ __metadata: languageName: node linkType: hard -"tslib@npm:2.6.2, tslib@npm:^2.5.0, tslib@npm:^2.6.0, tslib@npm:^2.6.1, tslib@npm:^2.6.2": +"tslib@npm:2.6.2, tslib@npm:^2.5.0, tslib@npm:^2.5.3, tslib@npm:^2.6.0, tslib@npm:^2.6.1, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: 329ea56123005922f39642318e3d1f0f8265d1e7fcb92c633e0809521da75eeaca28d2cf96d7248229deb40e5c19adf408259f4b9640afd20d13aecc1430f3ad languageName: node linkType: hard -"tslib@npm:^1.10.0, tslib@npm:^1.8.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": +"tslib@npm:^1.10.0, tslib@npm:^1.13.0, tslib@npm:^1.8.0, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: dbe628ef87f66691d5d2959b3e41b9ca0045c3ee3c7c7b906cc1e328b39f199bb1ad9e671c39025bd56122ac57dfbf7385a94843b1cc07c60a4db74795829acd @@ -48805,6 +49663,31 @@ __metadata: languageName: node linkType: hard +"tslint@npm:6.1.3": + version: 6.1.3 + resolution: "tslint@npm:6.1.3" + dependencies: + "@babel/code-frame": ^7.0.0 + builtin-modules: ^1.1.1 + chalk: ^2.3.0 + commander: ^2.12.1 + diff: ^4.0.1 + glob: ^7.1.1 + js-yaml: ^3.13.1 + minimatch: ^3.0.4 + mkdirp: ^0.5.3 + resolve: ^1.3.2 + semver: ^5.3.0 + tslib: ^1.13.0 + tsutils: ^2.29.0 + peerDependencies: + typescript: ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + bin: + tslint: bin/tslint + checksum: 7348b7abd6b8939f0b295c4dddbb104adfe2e96c9cc5be4a946a87a28df648bde61046cfb07951708938192f553eba6254f7729b85fd230efebbd72f7988255e + languageName: node + linkType: hard + "tsort@npm:0.0.1": version: 0.0.1 resolution: "tsort@npm:0.0.1" @@ -54316,6 +55199,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.15.1": + version: 8.16.0 + resolution: "ws@npm:8.16.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: feb3eecd2bae82fa8a8beef800290ce437d8b8063bdc69712725f21aef77c49cb2ff45c6e5e7fce622248f9c7abaee506bae0a9064067ffd6935460c7357321b + languageName: node + linkType: hard + "ws@npm:^8.4.0": version: 8.8.1 resolution: "ws@npm:8.8.1"