Skip to content

Commit

Permalink
feat(wip): wip
Browse files Browse the repository at this point in the history
  • Loading branch information
outSH committed Jan 15, 2024
1 parent 1fb2551 commit ce951ab
Show file tree
Hide file tree
Showing 11 changed files with 453 additions and 366 deletions.
6 changes: 3 additions & 3 deletions packages/cactus-plugin-ledger-connector-ethereum/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@
"sanitize-html": "2.7.0",
"socket.io-client-fixed-types": "4.5.4",
"typescript-optional": "2.0.1",
"web3": "4.1.2",
"web3-eth": "4.2.0",
"web3-eth-contract": "4.1.0"
"web3": "4.3.0",
"web3-eth": "4.3.1",
"web3-eth-contract": "4.1.4"
},
"devDependencies": {
"@hyperledger/cactus-plugin-keychain-memory": "2.0.0-alpha.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ export class PluginLedgerConnectorEthereum
public prometheusExporter: PrometheusExporter;
private readonly instanceId: string;
private readonly log: Logger;
private readonly web3: Web3;
private readonly web3WatchBlock?: Web3;
private readonly web3: InstanceType<typeof Web3>;
private readonly web3WatchBlock?: InstanceType<typeof Web3>;
private endpoints: IWebServiceEndpoint[] | undefined;
public static readonly CLASS_NAME = "PluginLedgerConnectorEthereum";
private watchBlocksSubscriptions: Map<string, NewHeadsSubscription> =
Expand Down Expand Up @@ -292,10 +292,10 @@ export class PluginLedgerConnectorEthereum
}

await this.closeWeb3jsConnection(
this.web3.currentProvider as WebSocketProvider,
this.web3.currentProvider as unknown as WebSocketProvider,
);
await this.closeWeb3jsConnection(
this.web3WatchBlock?.currentProvider as WebSocketProvider,
this.web3WatchBlock?.currentProvider as unknown as WebSocketProvider,
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
export interface IWatchBlocksV1EndpointConfiguration {
logLevel?: LogLevelDesc;
socket: SocketIoSocket;
web3: Web3;
web3: InstanceType<typeof Web3>;
options?: WatchBlocksV1Options;
}

Expand All @@ -35,7 +35,7 @@ export class WatchBlocksV1Endpoint {
Record<WatchBlocksV1, (next: string) => void>,
Record<WatchBlocksV1, (next: WatchBlocksV1Progress | string) => void>
>;
private readonly web3: Web3;
private readonly web3: InstanceType<typeof Web3>;
private readonly isGetBlockData: boolean;

public get className(): string {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
address: HexString;
privateKey: HexString;
},
web3: Web3,
web3: InstanceType<typeof Web3>,
addressInfo,
address: string,
port: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe("Ethereum contract deploy and invoke using keychain tests", () => {
address: HexString;
privateKey: HexString;
},
web3: Web3,
web3: InstanceType<typeof Web3>,
addressInfo,
address: string,
port: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const containerImageVersion = "2023-07-27-2a8c48ed6";
describe("invokeRawWeb3EthMethod Tests", () => {
let ethereumTestLedger: GethTestLedger;
let connector: PluginLedgerConnectorEthereum;
let web3: Web3;
let web3: InstanceType<typeof Web3>;
let apiHost: string;
const expressApp = express();
expressApp.use(bodyParser.json({ limit: "250mb" }));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
/**
* Tests for monitoring endpoints
*/

//////////////////////////////////
// Constants
//////////////////////////////////

const testLogLevel: LogLevelDesc = "debug";
const containerImageName = "ghcr.io/hyperledger/cacti-geth-all-in-one";
const containerImageVersion = "2023-07-27-2a8c48ed6";
const asyncTestTimeout = 1000 * 60 * 2; // 2 minutes

import "jest-extended";
import express from "express";
import bodyParser from "body-parser";
import http from "http";
import { v4 as uuidV4 } from "uuid";
import { Server as SocketIoServer } from "socket.io";
import Web3 from "web3";
import type { Subscription } from "rxjs";

import {
LogLevelDesc,
Servers,
Logger,
LoggerProvider,
} from "@hyperledger/cactus-common";
import { PluginRegistry } from "@hyperledger/cactus-core";
import { Configuration, Constants } from "@hyperledger/cactus-core-api";
import { pruneDockerAllIfGithubAction } from "@hyperledger/cactus-test-tooling";
import { GethTestLedger } from "@hyperledger/cactus-test-geth-ledger";

import {
PluginLedgerConnectorEthereum,
EthereumApiClient,
WatchBlocksV1Progress,
Web3BlockHeader,
} from "../../../main/typescript/public-api";

const log: Logger = LoggerProvider.getOrCreate({
label: "geth-monitoring-blocks.test",
level: testLogLevel,
});

async function testWatchBlock(
apiClient: EthereumApiClient,
getBlockData: boolean,
count = 1,
) {
let subscription: Subscription | undefined = undefined;
const blocksReceived: WatchBlocksV1Progress[] = [];

// Wait for blocks
await new Promise<boolean>((resolve, reject) => {
const watchObservable = apiClient.watchBlocksV1({
getBlockData,
});

subscription = watchObservable.subscribe({
next(event) {
blocksReceived.push(event);
log.debug(
"Received event:",
JSON.stringify(event),
"count:",
blocksReceived.length,
);
if (blocksReceived.length >= count) {
subscription?.unsubscribe();
resolve(true);
}
},
error(err) {
log.error("watchBlocksV1() error:", err);
subscription?.unsubscribe();
reject(err);
},
});
});

return blocksReceived;
}

function assertBlockHeader(header?: Web3BlockHeader) {
if (!header) {
throw new Error("Header is missing!");
}

// Check if defined and with expected type
// Ignore nullable / undefine-able fields
expect(typeof header.parentHash).toEqual("string");
expect(typeof header.sha3Uncles).toEqual("string");
expect(typeof header.miner).toEqual("string");
expect(typeof header.number).toEqual("string");
expect(typeof header.gasLimit).toEqual("string");
expect(typeof header.gasUsed).toEqual("string");
expect(typeof header.difficulty).toEqual("string");
}

describe("Ethereum monitoring endpoints tests", () => {
let ledger: GethTestLedger;
let rpcApiWsHost: string;
let rpcApiHttpHost: string;

//////////////////////////////////
// Setup ledger
//////////////////////////////////

beforeAll(async () => {
const pruning = pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
await expect(pruning).resolves.toBeTruthy();

ledger = new GethTestLedger({
containerImageName,
containerImageVersion,
});
await ledger.start();
rpcApiHttpHost = await ledger.getRpcApiHttpHost();
rpcApiWsHost = await ledger.getRpcApiWebSocketHost();
});

afterAll(async () => {
if (ledger) {
log.info("Closing ethereum ledger");
await ledger.stop();
await ledger.destroy();
}

const pruning = pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
await expect(pruning).resolves.toBeTruthy();
});

//////////////////////////////////
// Monitoring with WebSocket node
//////////////////////////////////

describe("Monitoring ethereum blocks with WebSocket node connection tests", () => {
let web3: InstanceType<typeof Web3>;
let apiClient: EthereumApiClient;
let connector: PluginLedgerConnectorEthereum;
const expressApp = express();
expressApp.use(bodyParser.json({ limit: "250mb" }));
const server = http.createServer(expressApp);
const wsApi = new SocketIoServer(server, {
path: Constants.SocketIoConnectionPathV1,
});

beforeAll(async () => {
const addressInfo = await Servers.listen({
hostname: "127.0.0.1",
port: 0,
server,
});
apiClient = new EthereumApiClient(
new Configuration({
basePath: `http://${addressInfo.address}:${addressInfo.port}`,
}),
);

connector = new PluginLedgerConnectorEthereum({
instanceId: uuidV4(),
rpcApiWsHost,
logLevel: testLogLevel,
pluginRegistry: new PluginRegistry({ plugins: [] }),
});
await connector.getOrCreateWebServices();
await connector.registerWebServices(expressApp, wsApi);
});

afterAll(async () => {
if (server) {
log.info("Shutdown connector servers");
await Servers.shutdown(server);
}

if (connector) {
log.info("Shutdown connector");
await connector.shutdown();
}
});

test(
"Monitor new blocks headers on Ethereum",
async () => {
const ledgerEvents = await testWatchBlock(apiClient, false);
expect(ledgerEvents).toBeTruthy();
expect(ledgerEvents.length).toEqual(1);
const ledgerEvent = ledgerEvents[0];
// blockData should not be present if called with empty options
expect(ledgerEvent.blockData).toBeUndefined();
expect(ledgerEvent.blockHeader).toBeTruthy();

// check some fields
assertBlockHeader(ledgerEvent.blockHeader);
},
asyncTestTimeout,
);

test(
"Monitor new blocks data on Ethereum",
async () => {
const ledgerEvents = await testWatchBlock(apiClient, true);
expect(ledgerEvents).toBeTruthy();
expect(ledgerEvents.length).toEqual(1);
const ledgerEvent = ledgerEvents[0];
// blockHeader should not be present if called with getBlockData option
expect(ledgerEvent.blockHeader).toBeFalsy();
expect(ledgerEvent.blockData).toBeTruthy();

// check some fields
assertBlockHeader(ledgerEvent.blockData as unknown as Web3BlockHeader); // remove as unknown
expect(typeof ledgerEvent.blockData?.size).toEqual("string");
expect(typeof ledgerEvent.blockData?.totalDifficulty).toEqual("string");
expect(typeof ledgerEvent.blockData?.uncles).toEqual("object");
},
asyncTestTimeout,
);
});

//////////////////////////////////
// Monitoring with WebSocket node
//////////////////////////////////

describe("Monitoring ethereum blocks with HTTP node connection tests", () => {
let web3: InstanceType<typeof Web3>;
let apiClient: EthereumApiClient;
let connector: PluginLedgerConnectorEthereum;
const expressApp = express();
expressApp.use(bodyParser.json({ limit: "250mb" }));
const server = http.createServer(expressApp);
const wsApi = new SocketIoServer(server, {
path: Constants.SocketIoConnectionPathV1,
});

beforeAll(async () => {
const addressInfo = await Servers.listen({
hostname: "127.0.0.1",
port: 0,
server,
});
apiClient = new EthereumApiClient(
new Configuration({
basePath: `http://${addressInfo.address}:${addressInfo.port}`,
}),
);

connector = new PluginLedgerConnectorEthereum({
instanceId: uuidV4(),
rpcApiHttpHost,
logLevel: testLogLevel,
pluginRegistry: new PluginRegistry({ plugins: [] }),
});
await connector.getOrCreateWebServices();
await connector.registerWebServices(expressApp, wsApi);
});

afterAll(async () => {
if (server) {
log.info("Shutdown connector servers");
await Servers.shutdown(server);
}

if (connector) {
log.info("Shutdown connector");
await connector.shutdown();
}
});

test(
"Monitor new blocks headers on Ethereum",
async () => {
expect(true).toBeTruthy();
},
asyncTestTimeout,
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const containerImageName = "ghcr.io/hyperledger/cacti-geth-all-in-one";
const containerImageVersion = "2023-07-27-2a8c48ed6";

describe("Running ethereum transactions with different gas configurations", () => {
let web3: Web3,
let web3: InstanceType<typeof Web3>,
addressInfo,
address: string,
port: number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
"@hyperledger/cactus-plugin-keychain-memory": "2.0.0-alpha.2",
"@hyperledger/cactus-plugin-ledger-connector-ethereum": "2.0.0-alpha.2",
"@hyperledger/cactus-verifier-client": "2.0.0-alpha.2",
"web3-eth-contract": "4.1.0"
"web3-eth-contract": "4.1.4"
},
"devDependencies": {
"@hyperledger/cactus-test-geth-ledger": "2.0.0-alpha.2",
Expand All @@ -66,7 +66,7 @@
"@types/uuid": "9.0.6",
"lodash": "4.17.21",
"uuid": "9.0.1",
"web3": "4.1.0"
"web3": "4.3.0"
},
"engines": {
"node": ">=18",
Expand Down
Loading

0 comments on commit ce951ab

Please sign in to comment.