diff --git a/examples/cactus-example-cbdc-bridging-backend/src/main/typescript/infrastructure/cbdc-bridging-app-dummy-infrastructure.ts b/examples/cactus-example-cbdc-bridging-backend/src/main/typescript/infrastructure/cbdc-bridging-app-dummy-infrastructure.ts index 5d8dc9612d..b8e2543ab6 100644 --- a/examples/cactus-example-cbdc-bridging-backend/src/main/typescript/infrastructure/cbdc-bridging-app-dummy-infrastructure.ts +++ b/examples/cactus-example-cbdc-bridging-backend/src/main/typescript/infrastructure/cbdc-bridging-app-dummy-infrastructure.ts @@ -1174,8 +1174,8 @@ export class CbdcBridgingAppDummyInfrastructure { id, status: sessionData.data.status, substatus: sessionData.data.substatus, - sourceLedger: sessionData.data.originChain.dltProtocol, - receiverLedger: sessionData.data.destinationChain.dltProtocol, + sourceLedger: sessionData.data.originNetwork.dltProtocol, + receiverLedger: sessionData.data.destinationNetwork.dltProtocol, }; sessionsData.push(data); diff --git a/packages/cactus-plugin-satp-hermes/src/main/json/openapi-blo-bundled.json b/packages/cactus-plugin-satp-hermes/src/main/json/openapi-blo-bundled.json index 1907e160d7..7697ca6d55 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/json/openapi-blo-bundled.json +++ b/packages/cactus-plugin-satp-hermes/src/main/json/openapi-blo-bundled.json @@ -194,8 +194,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -274,7 +274,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -285,7 +285,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -413,8 +413,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -493,7 +493,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -504,7 +504,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -625,8 +625,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -705,7 +705,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -716,7 +716,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -804,6 +804,12 @@ "tags": [ "admin" ], + "x-hyperledger-cacti": { + "http": { + "verbLowerCase": "get", + "path": "/api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck" + } + }, "responses": { "200": { "description": "OK", @@ -814,7 +820,10 @@ "properties": { "status": { "type": "string", - "example": "OK" + "enum": [ + "AVAILABLE", + "UNAVAILABLE" + ] } } } @@ -887,8 +896,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -967,7 +976,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -978,7 +987,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -1106,8 +1115,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -1186,7 +1195,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -1197,7 +1206,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -1271,11 +1280,11 @@ }, "/api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations": { "get": { + "description": "Retrieves metadata about each supported blockchain networks, chains, and other systems.", + "summary": "Get supported integrations", "tags": [ "transaction" ], - "summary": "Get supported integrations", - "description": "Retrieves metadata about each supported blockchain networks, chains, and other systems.", "operationId": "GetIntegrations", "x-hyperledger-cacti": { "http": { @@ -1289,36 +1298,43 @@ "content": { "application/json": { "schema": { - "title": "Chains", - "type": "array", - "description": "List of chains and related metadata", - "items": { - "type": "object", - "properties": { - "chainId": { - "type": "string", - "description": "A unique identifier for the blockchain network." - }, - "chainName": { - "type": "string", - "description": "The name of the blockchain network." - }, - "chainType": { - "type": "string", - "description": "The type of blockchain network (e.g., 'evm', 'fabric')." - }, - "networkName": { - "type": "string", - "description": "The specific network name within the blockchain (e.g., 'mainnet', 'testnet')." + "description": "List of chains or systems and related metadata", + "type": "object", + "x-category": "response", + "properties": { + "integrations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for the blockchain network/system." + }, + "name": { + "type": "string", + "description": "The name of the blockchain network/system." + }, + "type": { + "type": "string", + "description": "The type of network (e.g., 'evm', 'fabric', 'SQL Database')." + }, + "environment": { + "type": "string", + "description": "The specific network name (e.g., 'mainnet', 'testnet')." + } + }, + "required": [ + "id", + "name", + "type" + ] } - }, - "required": [ - "chainId", - "chainName", - "chainType", - "networkName" - ] - } + } + }, + "required": [ + "integrations" + ] } } } @@ -2526,8 +2542,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -2606,7 +2622,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -2617,7 +2633,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -2660,8 +2676,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -2740,7 +2756,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -2751,7 +2767,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -2939,8 +2955,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -3019,7 +3035,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -3030,7 +3046,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -3078,8 +3094,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -3158,7 +3174,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -3169,7 +3185,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -4897,8 +4913,8 @@ "stage", "step", "startTime", - "originChain", - "destinationChain" + "originNetwork", + "destinationNetwork" ], "properties": { "status": { @@ -4977,7 +4993,7 @@ "format": "date-time", "example": "2023-01-01T00:00:00Z" }, - "originChain": { + "originNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -4988,7 +5004,7 @@ } } }, - "destinationChain": { + "destinationNetwork": { "type": "object", "properties": { "dltProtocol": { @@ -5006,65 +5022,71 @@ "statusResponse" ] }, - "Chain": { + "IntegrationsResponse": { + "description": "List of chains or systems and related metadata", "type": "object", + "x-category": "response", "properties": { - "chainId": { + "integrations": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A unique identifier for the blockchain network/system." + }, + "name": { + "type": "string", + "description": "The name of the blockchain network/system." + }, + "type": { + "type": "string", + "description": "The type of network (e.g., 'evm', 'fabric', 'SQL Database')." + }, + "environment": { + "type": "string", + "description": "The specific network name (e.g., 'mainnet', 'testnet')." + } + }, + "required": [ + "id", + "name", + "type" + ] + } + } + }, + "required": [ + "integrations" + ] + }, + "Integration": { + "type": "object", + "properties": { + "id": { "type": "string", - "description": "A unique identifier for the blockchain network." + "description": "A unique identifier for the blockchain network/system." }, - "chainName": { + "name": { "type": "string", - "description": "The name of the blockchain network." + "description": "The name of the blockchain network/system." }, - "chainType": { + "type": { "type": "string", - "description": "The type of blockchain network (e.g., 'evm', 'fabric')." + "description": "The type of network (e.g., 'evm', 'fabric', 'SQL Database')." }, - "networkName": { + "environment": { "type": "string", - "description": "The specific network name within the blockchain (e.g., 'mainnet', 'testnet')." + "description": "The specific network name (e.g., 'mainnet', 'testnet')." } }, "required": [ - "chainId", - "chainName", - "chainType", - "networkName" + "id", + "name", + "type" ] }, - "Chains": { - "title": "Chains", - "type": "array", - "description": "List of chains and related metadata", - "items": { - "type": "object", - "properties": { - "chainId": { - "type": "string", - "description": "A unique identifier for the blockchain network." - }, - "chainName": { - "type": "string", - "description": "The name of the blockchain network." - }, - "chainType": { - "type": "string", - "description": "The type of blockchain network (e.g., 'evm', 'fabric')." - }, - "networkName": { - "type": "string", - "description": "The specific network name within the blockchain (e.g., 'mainnet', 'testnet')." - } - }, - "required": [ - "chainId", - "chainName", - "chainType", - "networkName" - ] - } - }, "Token": { "type": "object", "description": "Metadata detailing a supported token", @@ -5171,7 +5193,10 @@ "properties": { "status": { "type": "string", - "example": "OK" + "enum": [ + "AVAILABLE", + "UNAVAILABLE" + ] } } }, diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-healthcheck-handler-service.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-healthcheck-handler-service.ts new file mode 100644 index 0000000000..b4e512d121 --- /dev/null +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-healthcheck-handler-service.ts @@ -0,0 +1,50 @@ +import { GetStatusError } from "../../core/errors/satp-errors"; +import { HealthCheckResponse } from "../../generated/gateway-client/typescript-axios/api"; +import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; +import { SATPManager } from "../../gol/satp-manager"; + +export async function executeGetHealthCheck( + logLevel: LogLevelDesc, + manager: SATPManager, +): Promise { + const fnTag = `executeGetHealthCheck()`; + const log = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + + try { + const result = await getHealthCheckService(logLevel, manager); + return result; + } catch (error) { + if (error instanceof GetStatusError) { + log.error(`${fnTag}, Error getting status: ${error.message}`); + throw error; + } else { + log.error(`${fnTag}, Unexpected error: ${error.message}`); + throw new Error("An unexpected error occurred while obtaining status."); + } + } +} + +// TODO call SATP core, use try catch to propagate errors +export async function getHealthCheckService( + logLevel: LogLevelDesc, + manager: SATPManager, +): Promise { + const fnTag = `getHealthCheckService()`; + const log = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + + const status = manager.healthCheck(); + + const res: HealthCheckResponse = { + status: status + }; + + log.debug(res); + + return res; +} diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-integrations-handler-service.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-integrations-handler-service.ts new file mode 100644 index 0000000000..6c61258b51 --- /dev/null +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-integrations-handler-service.ts @@ -0,0 +1,79 @@ +import { SATPError } from "../../core/errors/satp-errors"; +import { + Integration, + IntegrationsResponse, +} from "../../generated/gateway-client/typescript-axios/api"; +import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; +import { SATPManager } from "../../gol/satp-manager"; +import { SupportedChain } from "../../core/types"; + +export async function executeGetIntegrations( + logLevel: LogLevelDesc, + manager: SATPManager, +): Promise { + const fnTag = `executeGetIntegrations()`; + const logger = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + + logger.info(`${fnTag}, Obtaining integrations...`); + + try { + const result = await getIntegrationsService(logLevel, manager); + + return { + integrations: result, + }; + } catch (error) { + if (error instanceof SATPError) { + logger.error(`${fnTag}, Error getting status: ${error.message}`); + throw error; + } else { + logger.error(`${fnTag}, Unexpected error: ${error.message}`); + throw new Error("An unexpected error occurred while obtaining status."); + } + } +} + +export async function getIntegrationsService( + logLevel: LogLevelDesc, + manager: SATPManager, +): Promise { + const fnTag = `getIntegrationsService()`; + const logger = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + + logger.info(`${fnTag}, getting integrations service...`); + + const supportedSystems = manager.supportedDLTs; + + return supportedSystems.map((supportedSystem) => + convertSupportedChainsIntoIntegrations(supportedSystem), + ); +} + +function convertSupportedChainsIntoIntegrations( + supportedChain: SupportedChain, +): Integration { + switch (supportedChain) { + case SupportedChain.FABRIC: + return { + id: "dummyId", + name: "Hyperledger Fabric", + type: "fabric", + environment: "testnet", + } as Integration; + case SupportedChain.BESU: + return { + id: "dummyId", + name: "Hyperledger Besu", + type: "besu", + environment: "testnet", + } as Integration; + default: + throw new Error(`Unsupported chain: ${supportedChain}`); + } +} diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-status-handler-service.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-status-handler-service.ts index 5ea436a3ba..a8e8d4c8b7 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-status-handler-service.ts +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/admin/get-status-handler-service.ts @@ -5,23 +5,28 @@ import { StatusResponseStageEnum, StatusResponseStatusEnum, StatusResponseSubstatusEnum, - Transact200ResponseStatusResponseOriginChain, + Transact200ResponseStatusResponseOriginNetwork, } from "../../generated/gateway-client/typescript-axios/api"; -import { Logger } from "@hyperledger/cactus-common"; +import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; import { SATPManager } from "../../gol/satp-manager"; import { SupportedChain } from "../../core/types"; -export async function ExecuteGetStatus( - logger: Logger, +export async function executeGetStatus( + logLevel: LogLevelDesc, req: StatusRequest, manager: SATPManager, ): Promise { - const fnTag = `GetStatusHandler`; + const fnTag = `executeGetStatus()`; + const logger = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + logger.info(`${fnTag}, Obtaining status for sessionID=${req.sessionID}`); try { const processedRequest = req; - const result = await GetStatusService(logger, processedRequest, manager); + const result = await getStatusService(logLevel, processedRequest, manager); return result; } catch (error) { if (error instanceof GetStatusError) { @@ -35,11 +40,17 @@ export async function ExecuteGetStatus( } // TODO call SATP core, use try catch to propagate errors -export async function GetStatusService( - logger: Logger, +export async function getStatusService( + logLevel: LogLevelDesc, req: StatusRequest, manager: SATPManager, ): Promise { + const fnTag = `getStatusService()`; + const logger = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + // Implement the logic for getting status here; call core const session = manager.getSession(req.sessionID); @@ -63,37 +74,37 @@ export async function GetStatusService( StatusResponseSubstatusEnum.Completed; const startTime = sessionData.receivedTimestamps?.stage0?.newSessionRequestMessageTimestamp; - let originChain: Transact200ResponseStatusResponseOriginChain; - let destinationChain: Transact200ResponseStatusResponseOriginChain; + let originNetwork: Transact200ResponseStatusResponseOriginNetwork; + let destinationNetwork: Transact200ResponseStatusResponseOriginNetwork; if (sessionData.senderGatewayNetworkId === SupportedChain.BESU) { - originChain = { + originNetwork = { dltProtocol: "besu", dltSubnetworkID: "v24.4.0-RC1", }; } else if (sessionData.senderGatewayNetworkId === SupportedChain.FABRIC) { - originChain = { + originNetwork = { dltProtocol: "fabric", dltSubnetworkID: "v2.0.0", }; } else { - originChain = { + originNetwork = { dltProtocol: "ethereum", dltSubnetworkID: "v24.4.0-RC1", }; } if (sessionData.recipientGatewayNetworkId === SupportedChain.BESU) { - destinationChain = { + destinationNetwork = { dltProtocol: "besu", dltSubnetworkID: "v24.4.0-RC1", }; } else if (sessionData.recipientGatewayNetworkId === SupportedChain.FABRIC) { - destinationChain = { + destinationNetwork = { dltProtocol: "fabric", dltSubnetworkID: "v2.0.0", }; } else { - destinationChain = { + destinationNetwork = { dltProtocol: "ethereum", dltSubnetworkID: "v24.4.0-RC1", }; @@ -105,8 +116,8 @@ export async function GetStatusService( stage: StatusResponseStageEnum.Stage0, step: "transfer-complete-message", startTime: startTime || "undefined", - originChain: originChain, - destinationChain: destinationChain, + originNetwork: originNetwork, + destinationNetwork: destinationNetwork, }; } logger.info("completed? " + sessionData.completed); @@ -140,13 +151,11 @@ export async function GetStatusService( stage: ("STAGE" + count) as StatusResponseStageEnum, step: "transfer-complete-message", startTime: startTime || "undefined", - originChain: originChain, - destinationChain: destinationChain, + originNetwork: originNetwork, + destinationNetwork: destinationNetwork, }; logger.info(req); - // logger.error("GetStatusService not implemented"); - // throw new GetStatusError(req.sessionID, "GetStatusService not implemented"); return mock; } diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/dispatcher.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/dispatcher.ts index 20be0488cd..17399ca618 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/dispatcher.ts +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/dispatcher.ts @@ -11,22 +11,27 @@ import { IWebServiceEndpoint } from "@hyperledger/cactus-core-api"; //import { GatewayIdentity, GatewayChannel } from "../core/types"; //import { GetStatusError, NonExistantGatewayIdentity } from "../core/errors"; import { GetStatusEndpointV1 } from "../web-services/status-endpoint"; -import { HealthCheckEndpointV1 } from "../web-services/health-check-endpoint"; //import { GetAuditRequest, GetAuditResponse } from "../generated/gateway-client/typescript-axios"; import { + HealthCheckResponse, + IntegrationsResponse, StatusRequest, StatusResponse, TransactRequest, TransactResponse, } from "../generated/gateway-client/typescript-axios/api"; -import { ExecuteGetStatus } from "./admin/get-status-handler-service"; +import { executeGetIntegrations } from "./admin/get-integrations-handler-service"; import { ISATPManagerOptions, SATPManager } from "../gol/satp-manager"; import { GatewayOrchestrator } from "../gol/gateway-orchestrator"; import { SATPBridgesManager } from "../gol/satp-bridges-manager"; -import { ExecuteTransact } from "./transaction/transact-handler-service"; import { TransactEndpointV1 } from "../web-services/transact-endpoint"; import { GetSessionIdsEndpointV1 } from "../web-services/get-all-session-ids-endpoints"; +import { HealthCheckEndpointV1 } from "../web-services/healthcheck-endpoint"; +import { IntegrationsEndpointV1 } from "../web-services/integrations-endpoint"; +import { executeGetHealthCheck } from "./admin/get-healthcheck-handler-service"; +import { executeGetStatus } from "./admin/get-status-handler-service"; +import { executeTransact } from "./transaction/transact-handler-service"; export interface BLODispatcherOptions { logger: Logger; @@ -41,6 +46,8 @@ export interface BLODispatcherOptions { export class BLODispatcher { public static readonly CLASS_NAME = "BLODispatcher"; private readonly logger: Logger; + private readonly level: LogLevelDesc; + private readonly label: string; private endpoints: IWebServiceEndpoint[] | undefined; private OAPIEndpoints: IWebServiceEndpoint[] | undefined; private readonly instanceId: string; @@ -52,9 +59,9 @@ export class BLODispatcher { const fnTag = `${BLODispatcher.CLASS_NAME}#constructor()`; Checks.truthy(options, `${fnTag} arg options`); - const level = this.options.logLevel || "INFO"; - const label = this.className; - this.logger = LoggerProvider.getOrCreate({ level, label }); + this.level = this.options.logLevel || "INFO"; + this.label = this.className; + this.logger = LoggerProvider.getOrCreate({ level: this.level, label: this.label }); this.instanceId = options.instanceId; this.logger.info(`Instantiated ${this.className} OK`); this.orchestrator = options.orchestrator; @@ -93,23 +100,30 @@ export class BLODispatcher { dispatcher: this, logLevel: this.options.logLevel, }); - const getSessionIdsEndpointV1 = new GetSessionIdsEndpointV1({ + + const getHealthCheckEndpoint = new HealthCheckEndpointV1({ dispatcher: this, logLevel: this.options.logLevel, }); - const healthCheckEndpointV1 = new HealthCheckEndpointV1({ + const getIntegrationsEndpointV1 = new IntegrationsEndpointV1({ dispatcher: this, logLevel: this.options.logLevel, }); - const theEndpoints = [ + const getSessionIdsEndpointV1 = new GetSessionIdsEndpointV1({ + dispatcher: this, + logLevel: this.options.logLevel, + }); + + const endpoints = [ getStatusEndpointV1, + getHealthCheckEndpoint, + getIntegrationsEndpointV1, getSessionIdsEndpointV1, - healthCheckEndpointV1, ]; - this.endpoints = theEndpoints; - return theEndpoints; + this.endpoints = endpoints; + return endpoints; } public async getOrCreateOAPIWebServices(): Promise { @@ -127,9 +141,9 @@ export class BLODispatcher { logLevel: this.options.logLevel, }); - const theEndpoints = [transactEndpointV1]; - this.OAPIEndpoints = theEndpoints; - return theEndpoints; + const endpoints = [transactEndpointV1]; + this.OAPIEndpoints = endpoints; + return endpoints; } private getTargetGatewayClient(id: string) { @@ -149,15 +163,23 @@ export class BLODispatcher { } } + public async healthCheck(): Promise { + return executeGetHealthCheck(this.level, this.manager); + } + + public async getIntegrations(): Promise { + return executeGetIntegrations(this.level, this.manager); + } + public async GetStatus(req: StatusRequest): Promise { - return ExecuteGetStatus(this.logger, req, this.manager); + return executeGetStatus(this.level, req, this.manager); } public async Transact(req: TransactRequest): Promise { //TODO pre-verify verify input this.logger.info(`Transact request: ${req}`); - const res = await ExecuteTransact( - this.logger, + const res = await executeTransact( + this.level, req, this.manager, this.orchestrator, diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/transaction/transact-handler-service.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/transaction/transact-handler-service.ts index ec580687c1..43fb26f88a 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/transaction/transact-handler-service.ts +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/blo/transaction/transact-handler-service.ts @@ -7,20 +7,27 @@ import { LockType, SignatureAlgorithm, } from "../../generated/proto/cacti/satp/v02/common/message_pb"; +import { LoggerProvider, LogLevelDesc } from "@hyperledger/cactus-common"; import { GatewayOrchestrator } from "../../gol/gateway-orchestrator"; import { GatewayIdentity } from "../../core/types"; import { SATP_VERSION } from "../../core/constants"; -import { GetStatusService } from "../admin/get-status-handler-service"; +import { getStatusService } from "../admin/get-status-handler-service"; +import { log } from "console"; // todo -export async function ExecuteTransact( - logger: Logger, +export async function executeTransact( + logLevel: LogLevelDesc, req: TransactRequest, manager: SATPManager, orchestrator: GatewayOrchestrator, ): Promise { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const fn = "BLO#transact-handler-service#ExecuteTransact"; + const fnTag = `executeTransact()`; + const logger = LoggerProvider.getOrCreate({ + label: fnTag, + level: logLevel, + }); + + logger.info(`${fnTag}, executing transaction endpoint`); //TODO check input for valid strings... const ourGateway: GatewayIdentity = orchestrator.ourGateway; @@ -79,14 +86,12 @@ export async function ExecuteTransact( ); await manager.initiateTransfer(session); - logger.info(req); - // logger.error("GetStatusService not implemented"); - // throw new GetStatusError(req.sessionID, "GetStatusService not implemented"); + logger.info(`${fnTag}, ${req}`); return { sessionID: session.getSessionId(), - statusResponse: await GetStatusService( - logger, + statusResponse: await getStatusService( + logLevel, { sessionID: session.getSessionId() }, manager, ), diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/generated/gateway-client/typescript-axios/api.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/generated/gateway-client/typescript-axios/api.ts index 9308e482e4..c08a17c8e8 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/typescript/generated/gateway-client/typescript-axios/api.ts +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/generated/gateway-client/typescript-axios/api.ts @@ -246,68 +246,6 @@ export interface CancelResponse { */ 'cancelSuccessful': boolean; } -/** - * - * @export - * @interface Chain - */ -export interface Chain { - /** - * A unique identifier for the blockchain network. - * @type {string} - * @memberof Chain - */ - 'chainId': string; - /** - * The name of the blockchain network. - * @type {string} - * @memberof Chain - */ - 'chainName': string; - /** - * The type of blockchain network (e.g., \'evm\', \'fabric\'). - * @type {string} - * @memberof Chain - */ - 'chainType': string; - /** - * The specific network name within the blockchain (e.g., \'mainnet\', \'testnet\'). - * @type {string} - * @memberof Chain - */ - 'networkName': string; -} -/** - * - * @export - * @interface Chains1Inner - */ -export interface Chains1Inner { - /** - * A unique identifier for the blockchain network. - * @type {string} - * @memberof Chains1Inner - */ - 'chainId': string; - /** - * The name of the blockchain network. - * @type {string} - * @memberof Chains1Inner - */ - 'chainName': string; - /** - * The type of blockchain network (e.g., \'evm\', \'fabric\'). - * @type {string} - * @memberof Chains1Inner - */ - 'chainType': string; - /** - * The specific network name within the blockchain (e.g., \'mainnet\', \'testnet\'). - * @type {string} - * @memberof Chains1Inner - */ - 'networkName': string; -} /** * Response schema for a continue request, returning the status of the SATP session. * @export @@ -621,7 +559,59 @@ export interface GetHealthCheck200Response { * @type {string} * @memberof GetHealthCheck200Response */ - 'status'?: string; + 'status'?: GetHealthCheck200ResponseStatusEnum; +} + +export const GetHealthCheck200ResponseStatusEnum = { + Available: 'AVAILABLE', + Unavailable: 'UNAVAILABLE' +} as const; + +export type GetHealthCheck200ResponseStatusEnum = typeof GetHealthCheck200ResponseStatusEnum[keyof typeof GetHealthCheck200ResponseStatusEnum]; + +/** + * List of chains or systems and related metadata + * @export + * @interface GetIntegrations200Response + */ +export interface GetIntegrations200Response { + /** + * + * @type {Array} + * @memberof GetIntegrations200Response + */ + 'integrations': Array; +} +/** + * + * @export + * @interface GetIntegrations200ResponseIntegrationsInner + */ +export interface GetIntegrations200ResponseIntegrationsInner { + /** + * A unique identifier for the blockchain network/system. + * @type {string} + * @memberof GetIntegrations200ResponseIntegrationsInner + */ + 'id': string; + /** + * The name of the blockchain network/system. + * @type {string} + * @memberof GetIntegrations200ResponseIntegrationsInner + */ + 'name': string; + /** + * The type of network (e.g., \'evm\', \'fabric\', \'SQL Database\'). + * @type {string} + * @memberof GetIntegrations200ResponseIntegrationsInner + */ + 'type': string; + /** + * The specific network name (e.g., \'mainnet\', \'testnet\'). + * @type {string} + * @memberof GetIntegrations200ResponseIntegrationsInner + */ + 'environment'?: string; } /** * A collection of available and unavailable routes @@ -1175,8 +1165,16 @@ export interface HealthCheckResponse { * @type {string} * @memberof HealthCheckResponse */ - 'status'?: string; + 'status'?: HealthCheckResponseStatusEnum; } + +export const HealthCheckResponseStatusEnum = { + Available: 'AVAILABLE', + Unavailable: 'UNAVAILABLE' +} as const; + +export type HealthCheckResponseStatusEnum = typeof HealthCheckResponseStatusEnum[keyof typeof HealthCheckResponseStatusEnum]; + /** * Details a single step within a route including actions and estimates. * @export @@ -1260,6 +1258,37 @@ export const InsuranceStateEnum = { export type InsuranceStateEnum = typeof InsuranceStateEnum[keyof typeof InsuranceStateEnum]; +/** + * + * @export + * @interface Integration + */ +export interface Integration { + /** + * A unique identifier for the blockchain network/system. + * @type {string} + * @memberof Integration + */ + 'id': string; + /** + * The name of the blockchain network/system. + * @type {string} + * @memberof Integration + */ + 'name': string; + /** + * The type of network (e.g., \'evm\', \'fabric\', \'SQL Database\'). + * @type {string} + * @memberof Integration + */ + 'type': string; + /** + * The specific network name (e.g., \'mainnet\', \'testnet\'). + * @type {string} + * @memberof Integration + */ + 'environment'?: string; +} /** * Describes integration or tool details such as bridges or exchanges involved in the transaction. * @export @@ -1285,6 +1314,19 @@ export interface IntegrationDetails { */ 'logoURI': string; } +/** + * List of chains or systems and related metadata + * @export + * @interface IntegrationsResponse + */ +export interface IntegrationsResponse { + /** + * + * @type {Array} + * @memberof IntegrationsResponse + */ + 'integrations': Array; +} /** * Response for a pause transaction request. Returns the current status of the SATP session post-pause action. * @export @@ -1511,16 +1553,16 @@ export interface StatusResponse { 'startTime': string; /** * - * @type {Transact200ResponseStatusResponseOriginChain} + * @type {Transact200ResponseStatusResponseOriginNetwork} * @memberof StatusResponse */ - 'originChain': Transact200ResponseStatusResponseOriginChain; + 'originNetwork': Transact200ResponseStatusResponseOriginNetwork; /** * - * @type {Transact200ResponseStatusResponseDestinationChain} + * @type {Transact200ResponseStatusResponseDestinationNetwork} * @memberof StatusResponse */ - 'destinationChain': Transact200ResponseStatusResponseDestinationChain; + 'destinationNetwork': Transact200ResponseStatusResponseDestinationNetwork; } export const StatusResponseStatusEnum = { @@ -1719,16 +1761,16 @@ export interface Transact200ResponseStatusResponse { 'startTime': string; /** * - * @type {Transact200ResponseStatusResponseOriginChain} + * @type {Transact200ResponseStatusResponseOriginNetwork} * @memberof Transact200ResponseStatusResponse */ - 'originChain': Transact200ResponseStatusResponseOriginChain; + 'originNetwork': Transact200ResponseStatusResponseOriginNetwork; /** * - * @type {Transact200ResponseStatusResponseDestinationChain} + * @type {Transact200ResponseStatusResponseDestinationNetwork} * @memberof Transact200ResponseStatusResponse */ - 'destinationChain': Transact200ResponseStatusResponseDestinationChain; + 'destinationNetwork': Transact200ResponseStatusResponseDestinationNetwork; } export const Transact200ResponseStatusResponseStatusEnum = { @@ -1798,38 +1840,38 @@ export type Transact200ResponseStatusResponseStepEnum = typeof Transact200Respon /** * * @export - * @interface Transact200ResponseStatusResponseDestinationChain + * @interface Transact200ResponseStatusResponseDestinationNetwork */ -export interface Transact200ResponseStatusResponseDestinationChain { +export interface Transact200ResponseStatusResponseDestinationNetwork { /** * * @type {any} - * @memberof Transact200ResponseStatusResponseDestinationChain + * @memberof Transact200ResponseStatusResponseDestinationNetwork */ 'dltProtocol'?: any; /** * * @type {any} - * @memberof Transact200ResponseStatusResponseDestinationChain + * @memberof Transact200ResponseStatusResponseDestinationNetwork */ 'dltSubnetworkID'?: any; } /** * * @export - * @interface Transact200ResponseStatusResponseOriginChain + * @interface Transact200ResponseStatusResponseOriginNetwork */ -export interface Transact200ResponseStatusResponseOriginChain { +export interface Transact200ResponseStatusResponseOriginNetwork { /** * * @type {any} - * @memberof Transact200ResponseStatusResponseOriginChain + * @memberof Transact200ResponseStatusResponseOriginNetwork */ 'dltProtocol'?: any; /** * * @type {any} - * @memberof Transact200ResponseStatusResponseOriginChain + * @memberof Transact200ResponseStatusResponseOriginNetwork */ 'dltSubnetworkID'?: any; } @@ -2676,7 +2718,7 @@ export const TransactionApiFp = function(configuration?: Configuration) { * @param {*} [options] Override http request option. * @throws {RequiredError} */ - async getIntegrations(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise>> { + async getIntegrations(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { const localVarAxiosArgs = await localVarAxiosParamCreator.getIntegrations(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, @@ -2734,7 +2776,7 @@ export const TransactionApiFactory = function (configuration?: Configuration, ba * @param {*} [options] Override http request option. * @throws {RequiredError} */ - getIntegrations(options?: any): AxiosPromise> { + getIntegrations(options?: any): AxiosPromise { return localVarFp.getIntegrations(options).then((request) => request(axios, basePath)); }, /** diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/gol/satp-manager.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/gol/satp-manager.ts index 6806f3787b..9b95fef1b1 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/typescript/gol/satp-manager.ts +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/gol/satp-manager.ts @@ -44,6 +44,7 @@ import { SatpStage2Service } from "../generated/proto/cacti/satp/v02/stage_2_con import { SatpStage3Service } from "../generated/proto/cacti/satp/v02/stage_3_connect"; import { PromiseClient as PromiseConnectClient } from "@connectrpc/connect"; import { SatpStage0Service } from "../generated/proto/cacti/satp/v02/stage_0_connect"; +import { HealthCheckResponseStatusEnum } from "../generated/gateway-client/typescript-axios"; export interface ISATPManagerOptions { logLevel?: LogLevelDesc; @@ -60,6 +61,7 @@ export class SATPManager { public static readonly CLASS_NAME = "SATPManager"; private readonly logger: Logger; private readonly instanceId: string; + private status: HealthCheckResponseStatusEnum; private endpoints: any[] | undefined; private signer: JsObjectSigner; public supportedDLTs: SupportedChain[] = []; @@ -87,6 +89,7 @@ export class SATPManager { this.logger = LoggerProvider.getOrCreate({ level, label }); this.instanceId = options.instanceId; this.logger.info(`Instantiated ${this.className} OK`); + this.status = HealthCheckResponseStatusEnum.Available; this.supportedDLTs = options.supportedDLTs; this.signer = options.signer; this.bridgesManager = options.bridgeManager; @@ -166,6 +169,10 @@ export class SATPManager { return SATPManager.CLASS_NAME; } + public healthCheck(): HealthCheckResponseStatusEnum { + return this.status; + } + public getSessions(): Map { return this.sessions; } diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/web-services/healthcheck-endpoint.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/web-services/healthcheck-endpoint.ts new file mode 100644 index 0000000000..d41a5eed87 --- /dev/null +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/web-services/healthcheck-endpoint.ts @@ -0,0 +1,96 @@ +import { + Checks, + IAsyncProvider, + Logger, + LoggerProvider, +} from "@hyperledger/cactus-common"; +import { + IEndpointAuthzOptions, + IExpressRequestHandler, + IWebServiceEndpoint, +} from "@hyperledger/cactus-core-api"; +import type { Express, Request, Response } from "express"; +import { IRequestOptions } from "../core/types"; +import OAS from "../../json/openapi-blo-bundled.json"; +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +export class HealthCheckEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "HealthCheckEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return HealthCheckEndpointV1.CLASS_NAME; + } + + constructor(public readonly options: IRequestOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.dispatcher, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck"] { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getPath(): string { + const apiPath = + OAS.paths["/api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck"]; + return apiPath.get["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths["/api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck"]; + return apiPath.get["x-hyperledger-cacti"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck" + ].get.operationId; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + + try { + const result = await this.options.dispatcher.healthCheck(); + res.json(result); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to ping:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-satp-hermes/src/main/typescript/web-services/integrations-endpoint.ts b/packages/cactus-plugin-satp-hermes/src/main/typescript/web-services/integrations-endpoint.ts new file mode 100644 index 0000000000..9b2afaf048 --- /dev/null +++ b/packages/cactus-plugin-satp-hermes/src/main/typescript/web-services/integrations-endpoint.ts @@ -0,0 +1,96 @@ +import { + Checks, + IAsyncProvider, + Logger, + LoggerProvider, +} from "@hyperledger/cactus-common"; +import { + IEndpointAuthzOptions, + IExpressRequestHandler, + IWebServiceEndpoint, +} from "@hyperledger/cactus-core-api"; +import type { Express, Request, Response } from "express"; +import { IRequestOptions } from "../core/types"; +import OAS from "../../json/openapi-blo-bundled.json"; +import { + handleRestEndpointException, + registerWebServiceEndpoint, +} from "@hyperledger/cactus-core"; + +export class IntegrationsEndpointV1 implements IWebServiceEndpoint { + public static readonly CLASS_NAME = "IntegrationsEndpointV1"; + + private readonly log: Logger; + + public get className(): string { + return IntegrationsEndpointV1.CLASS_NAME; + } + + constructor(public readonly options: IRequestOptions) { + const fnTag = `${this.className}#constructor()`; + Checks.truthy(options, `${fnTag} arg options`); + Checks.truthy(options.dispatcher, `${fnTag} arg options.connector`); + + const level = this.options.logLevel || "INFO"; + const label = this.className; + this.log = LoggerProvider.getOrCreate({ level, label }); + } + + public get oasPath(): (typeof OAS.paths)["/api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations"] { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations" + ]; + } + + public async registerExpress( + expressApp: Express, + ): Promise { + await registerWebServiceEndpoint(expressApp, this); + return this; + } + + public getPath(): string { + const apiPath = + OAS.paths["/api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations"]; + return apiPath.get["x-hyperledger-cacti"].http.path; + } + + public getVerbLowerCase(): string { + const apiPath = + OAS.paths["/api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations"]; + return apiPath.get["x-hyperledger-cacti"].http.verbLowerCase; + } + + public getOperationId(): string { + return OAS.paths[ + "/api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations" + ].get.operationId; + } + + public getExpressRequestHandler(): IExpressRequestHandler { + return this.handleRequest.bind(this); + } + + getAuthorizationOptionsProvider(): IAsyncProvider { + return { + get: async () => ({ + isProtected: true, + requiredRoles: [], + }), + }; + } + + public async handleRequest(req: Request, res: Response): Promise { + const fnTag = `${this.className}#handleRequest()`; + const reqTag = `${this.getVerbLowerCase()} - ${this.getPath()}`; + this.log.debug(reqTag); + + try { + const result = await this.options.dispatcher.getIntegrations(); + res.json(result); + } catch (ex) { + const errorMsg = `${reqTag} ${fnTag} Failed to ping:`; + handleRestEndpointException({ errorMsg, log: this.log, error: ex, res }); + } + } +} diff --git a/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo-bundled.yml b/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo-bundled.yml index 6104a604e9..06c259b432 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo-bundled.yml +++ b/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo-bundled.yml @@ -154,8 +154,8 @@ paths: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -224,14 +224,14 @@ paths: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -323,8 +323,8 @@ paths: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -393,14 +393,14 @@ paths: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -487,8 +487,8 @@ paths: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -557,14 +557,14 @@ paths: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -618,6 +618,10 @@ paths: operationId: GetHealthCheck tags: - admin + x-hyperledger-cacti: + http: + verbLowerCase: get + path: /api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck responses: '200': description: OK @@ -628,7 +632,9 @@ paths: properties: status: type: string - example: OK + enum: + - AVAILABLE + - UNAVAILABLE '500': description: Internal server error /api/v1/@hyperledger/cactus-plugin-satp-hermes/continue: @@ -680,8 +686,8 @@ paths: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -750,14 +756,14 @@ paths: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -849,8 +855,8 @@ paths: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -919,14 +925,14 @@ paths: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -974,10 +980,10 @@ paths: example: '2021-07-21T17:32:28Z' /api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations: get: + description: 'Retrieves metadata about each supported blockchain networks, chains, and other systems.' + summary: Get supported integrations tags: - transaction - summary: Get supported integrations - description: 'Retrieves metadata about each supported blockchain networks, chains, and other systems.' operationId: GetIntegrations x-hyperledger-cacti: http: @@ -989,29 +995,33 @@ paths: content: application/json: schema: - title: Chains - type: array - description: List of chains and related metadata - items: - type: object - properties: - chainId: - type: string - description: A unique identifier for the blockchain network. - chainName: - type: string - description: The name of the blockchain network. - chainType: - type: string - description: 'The type of blockchain network (e.g., ''evm'', ''fabric'').' - networkName: - type: string - description: 'The specific network name within the blockchain (e.g., ''mainnet'', ''testnet'').' - required: - - chainId - - chainName - - chainType - - networkName + description: List of chains or systems and related metadata + type: object + x-category: response + properties: + integrations: + type: array + items: + type: object + properties: + id: + type: string + description: A unique identifier for the blockchain network/system. + name: + type: string + description: The name of the blockchain network/system. + type: + type: string + description: 'The type of network (e.g., ''evm'', ''fabric'', ''SQL Database'').' + environment: + type: string + description: 'The specific network name (e.g., ''mainnet'', ''testnet'').' + required: + - id + - name + - type + required: + - integrations default: description: An error occurred content: @@ -1916,8 +1926,8 @@ components: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -1986,14 +1996,14 @@ components: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -2026,8 +2036,8 @@ components: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -2096,14 +2106,14 @@ components: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -2239,8 +2249,8 @@ components: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -2309,14 +2319,14 @@ components: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -2351,8 +2361,8 @@ components: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -2421,14 +2431,14 @@ components: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -3745,8 +3755,8 @@ components: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -3815,14 +3825,14 @@ components: type: string format: date-time example: '2023-01-01T00:00:00Z' - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -3831,50 +3841,53 @@ components: example: subnetwork2 required: - statusResponse - Chain: + IntegrationsResponse: + description: List of chains or systems and related metadata type: object + x-category: response properties: - chainId: + integrations: + type: array + items: + type: object + properties: + id: + type: string + description: A unique identifier for the blockchain network/system. + name: + type: string + description: The name of the blockchain network/system. + type: + type: string + description: 'The type of network (e.g., ''evm'', ''fabric'', ''SQL Database'').' + environment: + type: string + description: 'The specific network name (e.g., ''mainnet'', ''testnet'').' + required: + - id + - name + - type + required: + - integrations + Integration: + type: object + properties: + id: type: string - description: A unique identifier for the blockchain network. - chainName: + description: A unique identifier for the blockchain network/system. + name: type: string - description: The name of the blockchain network. - chainType: + description: The name of the blockchain network/system. + type: type: string - description: 'The type of blockchain network (e.g., ''evm'', ''fabric'').' - networkName: + description: 'The type of network (e.g., ''evm'', ''fabric'', ''SQL Database'').' + environment: type: string - description: 'The specific network name within the blockchain (e.g., ''mainnet'', ''testnet'').' + description: 'The specific network name (e.g., ''mainnet'', ''testnet'').' required: - - chainId - - chainName - - chainType - - networkName - Chains: - title: Chains - type: array - description: List of chains and related metadata - items: - type: object - properties: - chainId: - type: string - description: A unique identifier for the blockchain network. - chainName: - type: string - description: The name of the blockchain network. - chainType: - type: string - description: 'The type of blockchain network (e.g., ''evm'', ''fabric'').' - networkName: - type: string - description: 'The specific network name within the blockchain (e.g., ''mainnet'', ''testnet'').' - required: - - chainId - - chainName - - chainType - - networkName + - id + - name + - type Token: type: object description: Metadata detailing a supported token @@ -3956,7 +3969,9 @@ components: properties: status: type: string - example: OK + enum: + - AVAILABLE + - UNAVAILABLE BridgeInfo: type: object description: Information about the bridge used for the token transfer. diff --git a/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo.yml b/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo.yml index f03a37c97c..b5c34cd998 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo.yml +++ b/packages/cactus-plugin-satp-hermes/src/main/yml/bol/openapi-blo.yml @@ -165,6 +165,10 @@ paths: operationId: GetHealthCheck tags: - admin + x-hyperledger-cacti: + http: + verbLowerCase: get + path: /api/v1/@hyperledger/cactus-plugin-satp-hermes/healthcheck responses: '200': description: OK @@ -237,10 +241,10 @@ paths: /api/v1/@hyperledger/cactus-plugin-satp-hermes/integrations: get: + description: Retrieves metadata about each supported blockchain networks, chains, and other systems. + summary: Get supported integrations tags: - transaction - summary: Get supported integrations - description: Retrieves metadata about each supported blockchain networks, chains, and other systems. operationId: GetIntegrations x-hyperledger-cacti: http: @@ -252,13 +256,14 @@ paths: content: application/json: schema: - $ref: ./schemas.yml#/Chains + $ref: ./schemas.yml#/IntegrationsResponse default: description: An error occurred content: application/json: schema: $ref: ./schemas.yml#/APIError + /api/v1/@hyperledger/cactus-plugin-satp-hermes/routes: get: description: Get a list of possible routes for swapping one asset for another across multiple exchanges diff --git a/packages/cactus-plugin-satp-hermes/src/main/yml/bol/schemas.yml b/packages/cactus-plugin-satp-hermes/src/main/yml/bol/schemas.yml index e77af7f9b5..6041b39281 100644 --- a/packages/cactus-plugin-satp-hermes/src/main/yml/bol/schemas.yml +++ b/packages/cactus-plugin-satp-hermes/src/main/yml/bol/schemas.yml @@ -87,8 +87,8 @@ StatusResponse: - stage - step - startTime - - originChain - - destinationChain + - originNetwork + - destinationNetwork properties: status: type: string @@ -157,14 +157,14 @@ StatusResponse: type: string format: date-time example: "2023-01-01T00:00:00Z" - originChain: + originNetwork: type: object properties: dltProtocol: example: HyperledgerFabric dltSubnetworkID: example: subnetwork1 - destinationChain: + destinationNetwork: type: object properties: dltProtocol: @@ -469,32 +469,36 @@ ContinueResponse: $ref: ./schemas.yml#/StatusResponse required: - statusResponse -Chain: +IntegrationsResponse: + description: "List of chains or systems and related metadata" + type: object + x-category: response + properties: + integrations: + type: array + items: + $ref: ./schemas.yml#/Integration + required: + - integrations +Integration: type: object properties: - chainId: + id: type: string - description: A unique identifier for the blockchain network. - chainName: + description: A unique identifier for the blockchain network/system. + name: type: string - description: The name of the blockchain network. - chainType: + description: The name of the blockchain network/system. + type: type: string - description: The type of blockchain network (e.g., 'evm', 'fabric'). - networkName: + description: The type of network (e.g., 'evm', 'fabric', 'SQL Database'). + environment: type: string - description: The specific network name within the blockchain (e.g., 'mainnet', 'testnet'). + description: The specific network name (e.g., 'mainnet', 'testnet'). required: - - chainId - - chainName - - chainType - - networkName -Chains: - title: Chains - type: array - description: List of chains and related metadata - items: - $ref: ./schemas.yml#/Chain + - id + - name + - type Token: type: object description: Metadata detailing a supported token @@ -552,7 +556,9 @@ HealthCheckResponse: properties: status: type: string - example: 'OK' + enum: + - AVAILABLE + - UNAVAILABLE BridgeInfo: type: object description: Information about the bridge used for the token transfer. @@ -603,6 +609,16 @@ Insurance: description: The fee amount for insurance, represented in USD. example: "10.00" pattern: ^(0|[1-9]\d*)(\.\d+)?$ +# GatewayStatus: +# type: object +# properties: +# state: +# type: string +# description: The state of the gateway. +# example: ACTIVE +# enum: +# - AVAILABLE +# - UNAVAILABLE Action: type: object properties: diff --git a/packages/cactus-plugin-satp-hermes/src/test/typescript/integration/gateway-blo-get-status.test.ts b/packages/cactus-plugin-satp-hermes/src/test/typescript/integration/gateway-blo-get-status.test.ts deleted file mode 100644 index 71cd2a3eea..0000000000 --- a/packages/cactus-plugin-satp-hermes/src/test/typescript/integration/gateway-blo-get-status.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -import "jest-extended"; -import { - Containers, - pruneDockerAllIfGithubAction, -} from "@hyperledger/cactus-test-tooling"; -import { LogLevelDesc, LoggerProvider } from "@hyperledger/cactus-common"; -import { PluginFactorySATPGateway } from "../../../main/typescript/factory/plugin-factory-gateway-orchestrator"; -import { - IPluginFactoryOptions, - PluginImportType, -} from "@hyperledger/cactus-core-api"; - -import { - SATPGatewayConfig, - SupportedChain, -} from "../../../main/typescript/core/types"; -import { createClient } from "../test-utils"; - -const logLevel: LogLevelDesc = "DEBUG"; -const logger = LoggerProvider.getOrCreate({ - level: logLevel, - label: "satp-gateway-orchestrator-init-test", -}); -const factoryOptions: IPluginFactoryOptions = { - pluginImportType: PluginImportType.Local, -}; -const factory = new PluginFactorySATPGateway(factoryOptions); - -beforeAll(async () => { - pruneDockerAllIfGithubAction({ logLevel }) - .then(() => { - logger.info("Pruning throw OK"); - }) - .catch(async () => { - await Containers.logDiagnostics({ logLevel }); - fail("Pruning didn't throw OK"); - }); -}); - -// TODO create unit tests of the services to test that GetStatus functionality works (access via BLODispatcher) -describe("GetStatus Endpoint and Functionality testing", () => { - test("GetStatus endpoint works - SDK call", async () => { - const options: SATPGatewayConfig = { - logLevel: logLevel, - gid: { - id: "mockID", - name: "CustomGateway", - version: [ - { - Core: "v1", - Architecture: "v1", - Crash: "v1", - }, - ], - supportedDLTs: [SupportedChain.FABRIC, SupportedChain.BESU], - proofID: "mockProofID10", - gatewayServerPort: 3010, - gatewayClientPort: 3011, - gatewayOpenAPIPort: 4010, - address: "http://localhost", - }, - }; - - const gateway = await factory.create(options); - - try { - await gateway.startup(); - const address = options.gid!.address!; - const port = options.gid!.gatewayOpenAPIPort!; - //const apiType = "AdminApi"; - - const adminApiClient = createClient("AdminApi", address, port, logger); - - const statusRequest = { - sessionID: "test-session-id", - }; - - const response = await adminApiClient.getStatus(statusRequest.sessionID); - - // expect(response.status).toBe(200); - expect(response).toBeDefined(); - expect(response.status).toBeDefined(); - expect(response.status).toBe(200); - expect(response.data).toBeDefined(); - } catch (error) { - logger.error(`Error: ${error}`); - throw new Error(`Unexpected error during API call`); - } finally { - await gateway.shutdown(); - } - }); - - // TODO create integration tests of the services to test that GetStatus functionality works - test("GetStatus functionality works", async () => {}); -}); - -afterAll(async () => { - await pruneDockerAllIfGithubAction({ logLevel }) - .then(() => { - logger.info("Pruning throw OK"); - }) - .catch(async () => { - await Containers.logDiagnostics({ logLevel }); - fail("Pruning didn't throw OK"); - }); -}); diff --git a/packages/cactus-plugin-satp-hermes/src/test/typescript/integration/gateway-blo.test.ts b/packages/cactus-plugin-satp-hermes/src/test/typescript/integration/gateway-blo.test.ts new file mode 100644 index 0000000000..b32310c8c9 --- /dev/null +++ b/packages/cactus-plugin-satp-hermes/src/test/typescript/integration/gateway-blo.test.ts @@ -0,0 +1,143 @@ +import "jest-extended"; +import { + Containers, + pruneDockerAllIfGithubAction, +} from "@hyperledger/cactus-test-tooling"; +import { LogLevelDesc, LoggerProvider } from "@hyperledger/cactus-common"; +import { PluginFactorySATPGateway } from "../../../main/typescript/factory/plugin-factory-gateway-orchestrator"; +import { + IPluginFactoryOptions, + PluginImportType, +} from "@hyperledger/cactus-core-api"; + +import { + SATPGatewayConfig, + SupportedChain, +} from "../../../main/typescript/core/types"; +import { createClient } from "../test-utils"; +import { HealthCheckResponseStatusEnum } from "../../../main/typescript"; + +const logLevel: LogLevelDesc = "DEBUG"; +const logger = LoggerProvider.getOrCreate({ + level: logLevel, + label: "satp-gateway-orchestrator-init-test", +}); +const factoryOptions: IPluginFactoryOptions = { + pluginImportType: PluginImportType.Local, +}; +const factory = new PluginFactorySATPGateway(factoryOptions); + +beforeAll(async () => { + pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + logger.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +}); + +const options: SATPGatewayConfig = { + logLevel: logLevel, + gid: { + id: "mockID", + name: "CustomGateway", + version: [ + { + Core: "v1", + Architecture: "v1", + Crash: "v1", + }, + ], + supportedDLTs: [SupportedChain.FABRIC, SupportedChain.BESU], + proofID: "mockProofID10", + gatewayServerPort: 3010, + gatewayClientPort: 3011, + gatewayOpenAPIPort: 4010, + address: "http://localhost", + }, +}; + +describe("GetStatus Endpoint and Functionality testing", () => { + test("GetStatus endpoint works", async () => { + const gateway = await factory.create(options); + + try { + await gateway.startup(); + const address = options.gid!.address!; + const port = options.gid!.gatewayOpenAPIPort!; + + const adminApiClient = createClient("AdminApi", address, port, logger); + + const statusRequest = { + sessionID: "test-session-id", + }; + + await adminApiClient.getStatus(statusRequest.sessionID); + } catch (error) { + expect(error.response.data.error).toContain("Session not found"); + } finally { + await gateway.shutdown(); + } + }); + + test("Healthcheck works", async () => { + const gateway = await factory.create(options); + + try { + await gateway.startup(); + const address = options.gid!.address!; + const port = options.gid!.gatewayOpenAPIPort!; + + const adminApiClient = createClient("AdminApi", address, port, logger); + + const result = await adminApiClient.getHealthCheck(); + expect(result).toBeDefined(); + expect(result.status).toBe(200); + expect(result.data.status).toBe(HealthCheckResponseStatusEnum.Available); + } finally { + await gateway.shutdown(); + } + }); + + test("Integrations works", async () => { + const gateway = await factory.create(options); + + try { + await gateway.startup(); + const address = options.gid!.address!; + const port = options.gid!.gatewayOpenAPIPort!; + + const transactApiClient = createClient( + "TransactionApi", + address, + port, + logger, + ); + + const result = await transactApiClient.getIntegrations(); + expect(result).toBeDefined(); + expect(result.status).toBe(200); + expect(result.data.integrations).toBeDefined(); + expect(result.data.integrations).toHaveLength(2); + // the type of the first integration is "fabric" + expect(result.data.integrations[0].type).toEqual("fabric"); + // the type of the second integration is "besu" + expect(result.data.integrations[1].type).toEqual("besu"); + } finally { + await gateway.shutdown(); + } + }); +}); + +afterAll(async () => { + await pruneDockerAllIfGithubAction({ logLevel }) + .then(() => { + logger.info("Pruning throw OK"); + }) + .catch(async () => { + await Containers.logDiagnostics({ logLevel }); + fail("Pruning didn't throw OK"); + }); +});