Skip to content

Commit

Permalink
feat(connector-ubiquity): initial implementation
Browse files Browse the repository at this point in the history
This plugin defines interfaces for developers to use a wrapped version of the Ubiquity SDK.
Ubiquity is a high performance, multi-chain API for accessing blockchain data.
This API complements current connectors by allowing to connect to a public blockchains.

Signed-off-by: Rafael Belchior <rafael.belchior@tecnico.ulisboa.pt>
  • Loading branch information
RafaelAPB authored and petermetz committed Dec 24, 2022
1 parent db78969 commit 7c59790
Show file tree
Hide file tree
Showing 31 changed files with 1,372 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"caio",
"cccs",
"ccid",
"celo",
"cids",
"commenceack",
"configtx",
Expand Down Expand Up @@ -122,6 +123,8 @@
"supervisord",
"svcs",
"sykesm",
"TEZOS",
"tezos",
"thream",
"tlsca",
"tlscacerts",
Expand Down
30 changes: 30 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,36 @@ jobs:
restore-keys: |
${{ runner.os }}-yarn-
- run: ./tools/ci.sh
cactus-plugin-connector-ubiquity:
continue-on-error: false
env:
FULL_BUILD_DISABLED: true
JEST_TEST_PATTERN: packages/cactus-plugin-ledger-connector-ubiquity/src/test/typescript/(unit|integration|benchmark)/.*/*.test.ts
JEST_TEST_RUNNER_DISABLED: false
TAPE_TEST_RUNNER_DISABLED: true
UBIQUITY_AUTH_TOKEN: ${{ secrets.UBIQUITY_AUTH_TOKEN }}
needs: build-dev
runs-on: ubuntu-20.04
steps:
- name: Use Node.js v16.14.2
uses: actions/setup-node@v2.1.2
with:
node-version: v16.14.2
- uses: actions/checkout@v2.3.4
- id: yarn-cache-dir-path
name: Get yarn cache directory path
run: echo "::set-output name=dir::$(yarn cache dir)"
- id: yarn-cache
name: Restore Yarn Cache
uses: actions/cache@v3.0.4
with:
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
restore-keys: |
${{ runner.os }}-yarn-
- run: ./tools/ci.sh
env:
UBIQUITY_AUTH_TOKEN: ${{ secrets.UBIQUITY_AUTH_TOKEN }}
cactus-test-api-client:
continue-on-error: false
env:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
UBIQUITY_AUTH_TOKEN=xpto
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
43 changes: 43 additions & 0 deletions packages/cactus-plugin-ledger-connector-ubiquity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# `@hyperledger/cactus-plugin-ledger-connector-ubiquity <!-- omit in toc -->
This plugin defines interfaces for developers to use a wrapped version of the Ubiquity SDK. Ubiquity is a high performance, multi-chain API for accessing blockchain data, i.e., provides one API to access multiple protocols: https://ubiquity.docs.blockdaemon.com/swagger-ui

This API complements Cactus current connector offering by allowing to connect seamlessly to a multitude of public blockchains. Although it can be considered a ledger connector, for now

## Supported Functionality
-Read from smart contracts and addresses from 10+ different blockchains.

## Usage
TBD

## Installation

**npm**

```sh
npm install @hyperledger/cactus-plugin-ledger-connector-ubiquity
```

**yarn**

```sh
yarn add @hyperledger/cactus-plugin-ledger-connector-ubiquity
```

Rename .env.example to .env and poopulate the environment variables. Alternatively, setup the AUTH_TOKEN environment variable (will be used to set up the auth token for the Ubiquity client).

### Using as a Library
TBD

## TODO
- Implement IPluginLedgerConnectorInterface with perhaps State pattern
- Containerize the plugin
- Add unit and integration tests
- Support full historical data across all Ubiquity supported protocols.
- Deploy public blockchain nodes on-the-go

## License

This distribution is published under the Apache License Version 2.0 found in the [LICENSE](../../LICENSE) file.

## Acknowledgments
The development of this plugin is supported by Blockdaemon
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json",
"spaces": 2,
"generator-cli": {
"version": "6.0.1"
}
}
102 changes: 102 additions & 0 deletions packages/cactus-plugin-ledger-connector-ubiquity/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"name": "@hyperledger/cactus-plugin-ledger-connector-ubiquity",
"version": "1.1.2",
"description": "Allows Cacti nodes to connect to a set of public blockchains.",
"keywords": [
"Hyperledger",
"Cactus",
"Integration",
"Blockchain",
"Distributed Ledger Technology",
"Ubiquity"
],
"homepage": "https://github.com/hyperledger/cactus#readme",
"bugs": {
"url": "https://github.com/hyperledger/cactus/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/hyperledger/cactus.git"
},
"license": "Apache-2.0",
"author": {
"name": "Hyperledger Cactus Contributors",
"email": "cactus@lists.hyperledger.org",
"url": "https://www.hyperledger.org/use/cactus"
},
"contributors": [
{
"name": "Please add yourself to the list of contributors",
"email": "your.name@example.com",
"url": "https://example.com"
},
{
"name": "Rafael Belchior",
"email": "rbelchior@blockdaemon.com",
"url": "https://blockdaemon.com"
}
],
"main": "dist/lib/main/typescript/index.js",
"module": "dist/lib/main/typescript/index.js",
"browser": "dist/cactus-plugin-ledger-connector-ubiquity.web.umd.js",
"types": "dist/lib/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",
"watch": "npm-watch",
"webpack": "npm-run-all webpack:dev",
"webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web",
"webpack:dev:node": "webpack --env=dev --target=node --config ../../webpack.config.js",
"webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js",
"tsc": "tsc --project ./tsconfig.json"
},
"dependencies": {
"@hyperledger/cactus-core": "1.1.2",
"@hyperledger/cactus-core-api": "1.1.2",
"@ubiquity/ubiquity-ts-client-modified": "https://github.com/RafaelAPB/ubiquity-ts-client-mirror.git",
"typescript-optional": "2.0.1",
"dotenv": "16.0.1"
},
"devDependencies": {
"@types/express": "4.17.8",
"@hyperledger/cactus-test-tooling": "1.1.2",
"@hyperledger/cactus-common": "1.1.2"

},
"engines": {
"node": ">=10",
"npm": ">=6"
},
"publishConfig": {
"access": "public"
},
"browserMinified": "dist/cactus-plugin-ledger-connector-ubiquity.web.umd.min.js",
"mainMinified": "dist/cactus-plugin-ledger-connector-ubiquity.node.umd.min.js",
"watch": {
"codegen:openapi": {
"patterns": [
"./src/main/json/openapi.json"
]
},
"tsc": {
"patterns": [
"src/",
"src/*/json/**/openapi*"
],
"ignore": [
"src/**/generated/*"
],
"extensions": [
"ts",
"json"
],
"quiet": true,
"verbose": false,
"runOnChangeOnly": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"openapi": "3.0.3",
"info": {
"title": "Hyperledger Cactus Plugin - Ubiquity",
"description": "Ubiquity wrapper for Hyperledger Cactus",
"version": "0.0.1",
"license": {
"name": "Apache 2.0",
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
}
},
"components": {
"schemas": {
"GetTransactionsByAddressEndpoint": {
"type": "object",
"description": "Gets transactions that an address was involved with, from newest to oldest. This call uses pagination. Source: https://ubiquity.docs.blockdaemon.com/swagger-ui/#/Accounts/GetTxsByAddress",
"properties": {
"protocol": {
"type": "string"
},
"network": {
"type": "string"
},
"address": {
"type": "string"
}
},
"required": [
"protocol",
"network",
"address"
]
}
}
},
"paths": {
"/api/v1/@hyperledger/cactus-plugin-ledger-connector-ubiquity/GetTransactionByAddress": {
"post": {
"x-hyperledger-cactus": {
"http": {
"verbLowerCase": "post",
"path": "/api/v1/@hyperledger/cactus-plugin-ledger-connector-ubiquity/GetTransactionByAddress"
}
},
"operationId": "GetTransactionByAddressV1",
"description": "",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GetTransactionsByAddressEndpoint"
}
}
}
},
"responses": {
"200": {
"description": "OK"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { Express, Request, Response } from "express";

import {
IWebServiceEndpoint,
IExpressRequestHandler,
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";
import {
Logger,
Checks,
LogLevelDesc,
LoggerProvider,
IAsyncProvider,
} from "@hyperledger/cactus-common";

import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";

import { PluginLedgerConnectorUbiquity } from "../../plugin-ledger-connector-ubiquity";

import OAS from "../../../json/openapi.json";

export interface IGetTransactionsByAddressEndpointOptions {
logLevel?: LogLevelDesc;
ubiquity: PluginLedgerConnectorUbiquity;
}

export class GetTransactionsByAddressEndpoint implements IWebServiceEndpoint {
public static readonly CLASS_NAME = "GetTransactionsByAddressEndpointOptions";

private readonly log: Logger;

public get className(): string {
return GetTransactionsByAddressEndpoint.CLASS_NAME;
}

constructor(
public readonly options: IGetTransactionsByAddressEndpointOptions,
) {
const fnTag = `${this.className}#constructor()`;
Checks.truthy(options, `${fnTag} arg options`);
Checks.truthy(options.ubiquity, `${fnTag} arg options.connector`);

const level = this.options.logLevel || "INFO";
const label = this.className;
this.log = LoggerProvider.getOrCreate({ level, label });
}

public getPath(): string {
const apiPath =
OAS.paths[
"/api/v1/@hyperledger/cactus-plugin-ledger-connector-ubiquity/GetTransactionByAddress"
];
return apiPath.post["x-hyperledger-cactus"].http.path;
}

public getVerbLowerCase(): string {
const apiPath =
OAS.paths[
"/api/v1/@hyperledger/cactus-plugin-ledger-connector-ubiquity/GetTransactionByAddress"
];
return apiPath.post["x-hyperledger-cactus"].http.verbLowerCase;
}

public getOperationId(): string {
return OAS.paths[
"/api/v1/@hyperledger/cactus-plugin-ledger-connector-ubiquity/GetTransactionByAddress"
].post.operationId;
}

getAuthorizationOptionsProvider(): IAsyncProvider<IEndpointAuthzOptions> {
// TODO: make this an injectable dependency in the constructor
return {
get: async () => ({
isProtected: true,
requiredRoles: [],
}),
};
}

public async registerExpress(
expressApp: Express,
): Promise<IWebServiceEndpoint> {
await registerWebServiceEndpoint(expressApp, this);
return this;
}

public getExpressRequestHandler(): IExpressRequestHandler {
return this.handleRequest.bind(this);
}

public async handleRequest(req: Request, res: Response): Promise<void> {
const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`;
this.log.debug(reqTag);
try {
await this.options.ubiquity.getTxsByAddress(
req.body.protocol,
req.body.network,
req.body.address,
);
res.status(200).json("OK");
} catch (ex) {
this.log.error(`Crash while serving ${reqTag}`, ex);
res.status(500).json({
message: "Internal Server Error",
error: ex?.stack || ex?.message,
});
}
}
}
Loading

0 comments on commit 7c59790

Please sign in to comment.