diff --git a/examples/cactus-example-discounted-asset-trade/business-logic-asset-trade.ts b/examples/cactus-example-discounted-asset-trade/business-logic-asset-trade.ts
index 9b23867198..d9c09a7a1e 100644
--- a/examples/cactus-example-discounted-asset-trade/business-logic-asset-trade.ts
+++ b/examples/cactus-example-discounted-asset-trade/business-logic-asset-trade.ts
@@ -23,7 +23,7 @@ import {
import { json2str } from "@hyperledger/cactus-cmd-socketio-server";
import { AssetTradeStatus } from "./define";
import {
- WatchBlocksCactusTransactionsEventV1 as FabricWatchBlocksCactusTransactionsEventV1,
+ CactiBlockTransactionEventV1,
WatchBlocksListenerTypeV1 as FabricWatchBlocksListenerTypeV1,
WatchBlocksResponseV1 as FabricWatchBlocksResponseV1,
} from "@hyperledger/cactus-plugin-ledger-connector-fabric";
@@ -242,19 +242,19 @@ export class BusinessLogicAssetTrade extends BusinessLogicBase {
const fabricApiClient = getFabricApiClient();
const watchObservable = fabricApiClient.watchBlocksDelegatedSignV1({
channelName: config.assetTradeInfo.fabric.channelName,
- type: FabricWatchBlocksListenerTypeV1.CactusTransactions,
+ type: FabricWatchBlocksListenerTypeV1.CactiTransactions,
signerCertificate: getSignerIdentity().credentials.certificate,
signerMspID: getSignerIdentity().mspId,
uniqueTransactionData: createSigningToken("watchBlock"),
});
const watchSub = watchObservable.subscribe({
next: (event: FabricWatchBlocksResponseV1) => {
- if (!("cactusTransactionsEvents" in event)) {
+ if (!("cactiTransactionsEvents" in event)) {
logger.error("Wrong input block format!", event);
return;
}
- for (const ev of event.cactusTransactionsEvents) {
+ for (const ev of event.cactiTransactionsEvents) {
logger.debug(`##in onEventFabric()`);
try {
@@ -363,7 +363,7 @@ export class BusinessLogicAssetTrade extends BusinessLogicBase {
}
executeNextTransaction(
- txInfo: FabricWatchBlocksCactusTransactionsEventV1 | Web3TransactionReceipt,
+ txInfo: CactiBlockTransactionEventV1 | Web3TransactionReceipt,
txId: string,
): void {
let transactionInfo: TransactionInfo | null = null;
diff --git a/packages/cactus-plugin-bungee-hermes/src/main/typescript/strategy/strategy-fabric.ts b/packages/cactus-plugin-bungee-hermes/src/main/typescript/strategy/strategy-fabric.ts
index 106958db7b..a08bbbff46 100644
--- a/packages/cactus-plugin-bungee-hermes/src/main/typescript/strategy/strategy-fabric.ts
+++ b/packages/cactus-plugin-bungee-hermes/src/main/typescript/strategy/strategy-fabric.ts
@@ -4,6 +4,7 @@ import {
Configuration,
FabricContractInvocationType,
RunTransactionRequest,
+ GetBlockResponseTypeV1,
} from "@hyperledger/cactus-plugin-ledger-connector-fabric";
import { NetworkDetails, ObtainLedgerStrategy } from "./obtain-ledger-strategy";
import {
@@ -170,7 +171,7 @@ export class StrategyFabric implements ObtainLedgerStrategy {
query: {
transactionId: txId,
},
- skipDecode: false,
+ type: GetBlockResponseTypeV1.Full,
};
const getBlockResponse = await api.getBlockV1(getBlockReq);
diff --git a/packages/cactus-plugin-ledger-connector-fabric/README.md b/packages/cactus-plugin-ledger-connector-fabric/README.md
index 90f14a0986..940c2a5be0 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/README.md
+++ b/packages/cactus-plugin-ledger-connector-fabric/README.md
@@ -331,6 +331,11 @@ Corresponds directly to `BlockType` from `fabric-common`:
- `WatchBlocksListenerTypeV1.Full`,
- `WatchBlocksListenerTypeV1.Private`,
+##### Cacti (custom)
+Parses the data and returns custom formatted block.
+- `WatchBlocksListenerTypeV1.CactiTransactions`: Returns transactions summary. Compatible with legacy `fabric-socketio` monitoring operation.
+- `WatchBlocksListenerTypeV1.CactiFullBlock`: Returns full block summary.
+
### 1.6 Delegated Signature
- Custom signature callback can be used when increased security is needed or currently available options are not sufficient.
- Signature callback is used whenever fabric request must be signed.
@@ -365,17 +370,13 @@ await apiClient.runDelegatedSignTransactionV1({
// Monitor for transactions:
apiClient.watchBlocksDelegatedSignV1({
- type: WatchBlocksListenerTypeV1.CactusTransactions,
+ type: WatchBlocksListenerTypeV1.CactiTransactions,
signerCertificate: adminIdentity.credentials.certificate,
signerMspID: adminIdentity.mspId,
channelName: ledgerChannelName,
})
```
-##### Cactus (custom)
-Parses the data and returns custom formatted block.
-- `WatchBlocksListenerTypeV1.CactusTransactions`: Returns transactions summary. Compatible with legacy `fabric-socketio` monitoring operation.
-
## 2. Architecture
The sequence diagrams for various endpoints are mentioned below
diff --git a/packages/cactus-plugin-ledger-connector-fabric/package.json b/packages/cactus-plugin-ledger-connector-fabric/package.json
index a61f15959f..fbc1df0031 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/package.json
+++ b/packages/cactus-plugin-ledger-connector-fabric/package.json
@@ -72,6 +72,7 @@
"form-data": "4.0.0",
"http-status-codes": "2.1.4",
"jsrsasign": "11.0.0",
+ "long": "5.2.3",
"multer": "1.4.5-lts.1",
"ngo": "2.7.0",
"node-ssh": "13.1.0",
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.json b/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.json
index d50db8d9cb..fc508436b6 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.json
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.json
@@ -1056,10 +1056,35 @@
}
}
},
- "skipDecode": {
- "type": "boolean",
- "description": "If true, encoded buffer will be returned. Otherwise, entire block object is returned.",
- "default": false,
+ "responseType": {
+ "$ref": "#/components/schemas/GetBlockResponseTypeV1",
+ "description": "Type of response block to return.",
+ "nullable": false
+ }
+ }
+ },
+ "GetChainInfoRequestV1": {
+ "description": "Request for GetChainInfo endpoint.",
+ "type": "object",
+ "required": ["channelName", "gatewayOptions"],
+ "properties": {
+ "channelName": {
+ "type": "string",
+ "description": "Fabric channel which we want to query.",
+ "minLength": 1,
+ "maxLength": 100,
+ "nullable": false
+ },
+ "connectionChannelName": {
+ "type": "string",
+ "description": "Fabric channel we want to connect to. If not provided, then one from channelName parameter will be used",
+ "minLength": 1,
+ "maxLength": 100,
+ "nullable": false
+ },
+ "gatewayOptions": {
+ "$ref": "#/components/schemas/GatewayOptions",
+ "description": "Fabric SDK gateway options.",
"nullable": false
}
}
@@ -1091,6 +1116,12 @@
"GetBlockResponseV1": {
"description": "Response from GetBlock endpoint.",
"oneOf": [
+ {
+ "$ref": "#/components/schemas/CactiBlockTransactionsResponseV1"
+ },
+ {
+ "$ref": "#/components/schemas/CactiBlockFullResponseV1"
+ },
{
"$ref": "#/components/schemas/GetBlockResponseDecodedV1"
},
@@ -1099,6 +1130,28 @@
}
]
},
+ "GetChainInfoResponseV1": {
+ "type": "object",
+ "description": "Response from GetChainInfo endpoint.",
+ "required": ["height", "currentBlockHash", "previousBlockHash"],
+ "properties": {
+ "height": {
+ "description": "Current height of fabric ledger",
+ "type": "number",
+ "nullable": false
+ },
+ "currentBlockHash": {
+ "description": "Current block hash of fabric ledger",
+ "type": "string",
+ "nullable": false
+ },
+ "previousBlockHash": {
+ "description": "Previous block hash of fabric ledger",
+ "type": "string",
+ "nullable": false
+ }
+ }
+ },
"ErrorExceptionResponseV1": {
"type": "object",
"required": ["message", "error"],
@@ -1139,9 +1192,33 @@
},
"WatchBlocksListenerTypeV1": {
"type": "string",
- "description": "Response type from WatchBlocks. 'Cactus*' are custom views, others correspond to fabric SDK call.",
- "enum": ["filtered", "full", "private", "cactus:transactions"],
- "x-enum-varnames": ["Filtered", "Full", "Private", "CactusTransactions"]
+ "description": "Response type from WatchBlocks. 'Cacti*' are custom views, others correspond to fabric SDK call.",
+ "enum": [
+ "filtered",
+ "full",
+ "private",
+ "cacti:transactions",
+ "cacti:full-block"
+ ],
+ "x-enum-varnames": [
+ "Filtered",
+ "Full",
+ "Private",
+ "CactiTransactions",
+ "CactiFullBlock"
+ ]
+ },
+ "GetBlockResponseTypeV1": {
+ "type": "string",
+ "default": "full",
+ "description": "Response type from GetBlock.",
+ "enum": ["full", "encoded", "cacti:transactions", "cacti:full-block"],
+ "x-enum-varnames": [
+ "Full",
+ "Encoded",
+ "CactiTransactions",
+ "CactiFullBlock"
+ ]
},
"WatchBlocksOptionsV1": {
"type": "object",
@@ -1211,7 +1288,7 @@
}
}
},
- "WatchBlocksCactusTransactionsEventV1": {
+ "CactiBlockTransactionEventV1": {
"type": "object",
"description": "Transaction summary from commited block.",
"required": [
@@ -1247,21 +1324,33 @@
}
}
},
- "WatchBlocksCactusTransactionsResponseV1": {
+ "CactiBlockTransactionsResponseV1": {
"type": "object",
"description": "Custom response containing block transactions summary. Compatible with legacy fabric-socketio connector monitoring.",
- "required": ["cactusTransactionsEvents"],
+ "required": ["cactiTransactionsEvents"],
"properties": {
- "cactusTransactionsEvents": {
+ "cactiTransactionsEvents": {
"description": "List of transactions summary",
"type": "array",
"items": {
- "$ref": "#/components/schemas/WatchBlocksCactusTransactionsEventV1",
+ "$ref": "#/components/schemas/CactiBlockTransactionEventV1",
"nullable": false
}
}
}
},
+ "CactiBlockFullResponseV1": {
+ "type": "object",
+ "description": "Custom response containing full block summary.",
+ "required": ["cactiFullEvents"],
+ "properties": {
+ "cactiFullEvents": {
+ "description": "Full parsed block with transactions.",
+ "$ref": "#/components/schemas/CactiBlockFullEventV1",
+ "nullable": false
+ }
+ }
+ },
"WatchBlocksFullResponseV1": {
"type": "object",
"description": "Response that corresponds to Fabric SDK 'full' EventType.",
@@ -1295,6 +1384,200 @@
}
}
},
+ "FabricX509CertificateV1": {
+ "type": "object",
+ "description": "Transaction endorser certificate object",
+ "required": [
+ "issuer",
+ "serialNumber",
+ "subject",
+ "subjectAltName",
+ "validFrom",
+ "validTo",
+ "pem"
+ ],
+ "properties": {
+ "issuer": {
+ "nullable": false,
+ "type": "string"
+ },
+ "serialNumber": {
+ "nullable": false,
+ "type": "string"
+ },
+ "subject": {
+ "nullable": false,
+ "type": "string"
+ },
+ "subjectAltName": {
+ "nullable": false,
+ "type": "string"
+ },
+ "validFrom": {
+ "nullable": false,
+ "type": "string"
+ },
+ "validTo": {
+ "nullable": false,
+ "type": "string"
+ },
+ "pem": {
+ "nullable": false,
+ "type": "string"
+ }
+ }
+ },
+ "FabricCertificateIdentityV1": {
+ "type": "object",
+ "description": "Combination of certificate and it's MSP ID used to identify fabric actors.",
+ "required": ["mspid", "cert"],
+ "properties": {
+ "mspid": {
+ "nullable": false,
+ "type": "string"
+ },
+ "cert": {
+ "$ref": "#/components/schemas/FabricX509CertificateV1",
+ "nullable": false
+ }
+ }
+ },
+ "FullBlockTransactionEndorsementV1": {
+ "type": "object",
+ "description": "Transaction endorsment object returned from fabric block.",
+ "required": ["signer", "signature"],
+ "properties": {
+ "signer": {
+ "$ref": "#/components/schemas/FabricCertificateIdentityV1",
+ "nullable": false
+ },
+ "signature": {
+ "nullable": false,
+ "type": "string"
+ }
+ }
+ },
+ "FullBlockTransactionActionV1": {
+ "type": "object",
+ "description": "Transaction action returned from fabric block.",
+ "required": [
+ "functionName",
+ "functionArgs",
+ "chaincodeId",
+ "creator",
+ "endorsements"
+ ],
+ "properties": {
+ "functionName": {
+ "nullable": false,
+ "type": "string"
+ },
+ "functionArgs": {
+ "type": "array",
+ "items": {
+ "nullable": false,
+ "type": "string"
+ }
+ },
+ "chaincodeId": {
+ "nullable": false,
+ "type": "string"
+ },
+ "creator": {
+ "$ref": "#/components/schemas/FabricCertificateIdentityV1",
+ "nullable": false
+ },
+ "endorsements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/FullBlockTransactionEndorsementV1",
+ "nullable": false
+ }
+ }
+ }
+ },
+ "FullBlockTransactionEventV1": {
+ "type": "object",
+ "description": "Transaction returned from fabric block.",
+ "required": [
+ "hash",
+ "channelId",
+ "timestamp",
+ "protocolVersion",
+ "transactionType",
+ "epoch",
+ "actions"
+ ],
+ "properties": {
+ "hash": {
+ "nullable": false,
+ "type": "string"
+ },
+ "channelId": {
+ "nullable": false,
+ "type": "string"
+ },
+ "timestamp": {
+ "nullable": false,
+ "type": "string"
+ },
+ "protocolVersion": {
+ "nullable": false,
+ "type": "number"
+ },
+ "transactionType": {
+ "nullable": false,
+ "type": "string"
+ },
+ "epoch": {
+ "nullable": false,
+ "type": "number"
+ },
+ "actions": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/FullBlockTransactionActionV1",
+ "nullable": false
+ }
+ }
+ }
+ },
+ "CactiBlockFullEventV1": {
+ "type": "object",
+ "description": "Custom format full fabric block with transactions",
+ "required": [
+ "blockNumber",
+ "blockHash",
+ "previousBlockHash",
+ "transactionCount",
+ "cactiTransactionsEvents"
+ ],
+ "properties": {
+ "blockNumber": {
+ "nullable": false,
+ "type": "number"
+ },
+ "blockHash": {
+ "nullable": false,
+ "type": "string"
+ },
+ "previousBlockHash": {
+ "nullable": false,
+ "type": "string"
+ },
+ "transactionCount": {
+ "nullable": false,
+ "type": "number"
+ },
+ "cactiTransactionsEvents": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/FullBlockTransactionEventV1",
+ "nullable": false
+ }
+ }
+ }
+ },
"WatchBlocksCactusErrorResponseV1": {
"type": "object",
"description": "Error response from WatchBlocks operation.",
@@ -1314,7 +1597,11 @@
"description": "Response block from WatchBlocks endpoint. Depends on 'type' passed in subscription options.",
"oneOf": [
{
- "$ref": "#/components/schemas/WatchBlocksCactusTransactionsResponseV1",
+ "$ref": "#/components/schemas/CactiBlockTransactionsResponseV1",
+ "nullable": false
+ },
+ {
+ "$ref": "#/components/schemas/CactiBlockFullResponseV1",
"nullable": false
},
{
@@ -1617,6 +1904,50 @@
}
}
},
+ "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info": {
+ "post": {
+ "operationId": "getChainInfoV1",
+ "summary": "Get fabric ledger chain info.",
+ "x-hyperledger-cacti": {
+ "http": {
+ "verbLowerCase": "post",
+ "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info"
+ }
+ },
+ "parameters": [],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/GetChainInfoRequestV1"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/GetChainInfoResponseV1"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorExceptionResponseV1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics": {
"get": {
"x-hyperledger-cacti": {
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.tpl.json b/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.tpl.json
index d50db8d9cb..fc508436b6 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.tpl.json
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/json/openapi.tpl.json
@@ -1056,10 +1056,35 @@
}
}
},
- "skipDecode": {
- "type": "boolean",
- "description": "If true, encoded buffer will be returned. Otherwise, entire block object is returned.",
- "default": false,
+ "responseType": {
+ "$ref": "#/components/schemas/GetBlockResponseTypeV1",
+ "description": "Type of response block to return.",
+ "nullable": false
+ }
+ }
+ },
+ "GetChainInfoRequestV1": {
+ "description": "Request for GetChainInfo endpoint.",
+ "type": "object",
+ "required": ["channelName", "gatewayOptions"],
+ "properties": {
+ "channelName": {
+ "type": "string",
+ "description": "Fabric channel which we want to query.",
+ "minLength": 1,
+ "maxLength": 100,
+ "nullable": false
+ },
+ "connectionChannelName": {
+ "type": "string",
+ "description": "Fabric channel we want to connect to. If not provided, then one from channelName parameter will be used",
+ "minLength": 1,
+ "maxLength": 100,
+ "nullable": false
+ },
+ "gatewayOptions": {
+ "$ref": "#/components/schemas/GatewayOptions",
+ "description": "Fabric SDK gateway options.",
"nullable": false
}
}
@@ -1091,6 +1116,12 @@
"GetBlockResponseV1": {
"description": "Response from GetBlock endpoint.",
"oneOf": [
+ {
+ "$ref": "#/components/schemas/CactiBlockTransactionsResponseV1"
+ },
+ {
+ "$ref": "#/components/schemas/CactiBlockFullResponseV1"
+ },
{
"$ref": "#/components/schemas/GetBlockResponseDecodedV1"
},
@@ -1099,6 +1130,28 @@
}
]
},
+ "GetChainInfoResponseV1": {
+ "type": "object",
+ "description": "Response from GetChainInfo endpoint.",
+ "required": ["height", "currentBlockHash", "previousBlockHash"],
+ "properties": {
+ "height": {
+ "description": "Current height of fabric ledger",
+ "type": "number",
+ "nullable": false
+ },
+ "currentBlockHash": {
+ "description": "Current block hash of fabric ledger",
+ "type": "string",
+ "nullable": false
+ },
+ "previousBlockHash": {
+ "description": "Previous block hash of fabric ledger",
+ "type": "string",
+ "nullable": false
+ }
+ }
+ },
"ErrorExceptionResponseV1": {
"type": "object",
"required": ["message", "error"],
@@ -1139,9 +1192,33 @@
},
"WatchBlocksListenerTypeV1": {
"type": "string",
- "description": "Response type from WatchBlocks. 'Cactus*' are custom views, others correspond to fabric SDK call.",
- "enum": ["filtered", "full", "private", "cactus:transactions"],
- "x-enum-varnames": ["Filtered", "Full", "Private", "CactusTransactions"]
+ "description": "Response type from WatchBlocks. 'Cacti*' are custom views, others correspond to fabric SDK call.",
+ "enum": [
+ "filtered",
+ "full",
+ "private",
+ "cacti:transactions",
+ "cacti:full-block"
+ ],
+ "x-enum-varnames": [
+ "Filtered",
+ "Full",
+ "Private",
+ "CactiTransactions",
+ "CactiFullBlock"
+ ]
+ },
+ "GetBlockResponseTypeV1": {
+ "type": "string",
+ "default": "full",
+ "description": "Response type from GetBlock.",
+ "enum": ["full", "encoded", "cacti:transactions", "cacti:full-block"],
+ "x-enum-varnames": [
+ "Full",
+ "Encoded",
+ "CactiTransactions",
+ "CactiFullBlock"
+ ]
},
"WatchBlocksOptionsV1": {
"type": "object",
@@ -1211,7 +1288,7 @@
}
}
},
- "WatchBlocksCactusTransactionsEventV1": {
+ "CactiBlockTransactionEventV1": {
"type": "object",
"description": "Transaction summary from commited block.",
"required": [
@@ -1247,21 +1324,33 @@
}
}
},
- "WatchBlocksCactusTransactionsResponseV1": {
+ "CactiBlockTransactionsResponseV1": {
"type": "object",
"description": "Custom response containing block transactions summary. Compatible with legacy fabric-socketio connector monitoring.",
- "required": ["cactusTransactionsEvents"],
+ "required": ["cactiTransactionsEvents"],
"properties": {
- "cactusTransactionsEvents": {
+ "cactiTransactionsEvents": {
"description": "List of transactions summary",
"type": "array",
"items": {
- "$ref": "#/components/schemas/WatchBlocksCactusTransactionsEventV1",
+ "$ref": "#/components/schemas/CactiBlockTransactionEventV1",
"nullable": false
}
}
}
},
+ "CactiBlockFullResponseV1": {
+ "type": "object",
+ "description": "Custom response containing full block summary.",
+ "required": ["cactiFullEvents"],
+ "properties": {
+ "cactiFullEvents": {
+ "description": "Full parsed block with transactions.",
+ "$ref": "#/components/schemas/CactiBlockFullEventV1",
+ "nullable": false
+ }
+ }
+ },
"WatchBlocksFullResponseV1": {
"type": "object",
"description": "Response that corresponds to Fabric SDK 'full' EventType.",
@@ -1295,6 +1384,200 @@
}
}
},
+ "FabricX509CertificateV1": {
+ "type": "object",
+ "description": "Transaction endorser certificate object",
+ "required": [
+ "issuer",
+ "serialNumber",
+ "subject",
+ "subjectAltName",
+ "validFrom",
+ "validTo",
+ "pem"
+ ],
+ "properties": {
+ "issuer": {
+ "nullable": false,
+ "type": "string"
+ },
+ "serialNumber": {
+ "nullable": false,
+ "type": "string"
+ },
+ "subject": {
+ "nullable": false,
+ "type": "string"
+ },
+ "subjectAltName": {
+ "nullable": false,
+ "type": "string"
+ },
+ "validFrom": {
+ "nullable": false,
+ "type": "string"
+ },
+ "validTo": {
+ "nullable": false,
+ "type": "string"
+ },
+ "pem": {
+ "nullable": false,
+ "type": "string"
+ }
+ }
+ },
+ "FabricCertificateIdentityV1": {
+ "type": "object",
+ "description": "Combination of certificate and it's MSP ID used to identify fabric actors.",
+ "required": ["mspid", "cert"],
+ "properties": {
+ "mspid": {
+ "nullable": false,
+ "type": "string"
+ },
+ "cert": {
+ "$ref": "#/components/schemas/FabricX509CertificateV1",
+ "nullable": false
+ }
+ }
+ },
+ "FullBlockTransactionEndorsementV1": {
+ "type": "object",
+ "description": "Transaction endorsment object returned from fabric block.",
+ "required": ["signer", "signature"],
+ "properties": {
+ "signer": {
+ "$ref": "#/components/schemas/FabricCertificateIdentityV1",
+ "nullable": false
+ },
+ "signature": {
+ "nullable": false,
+ "type": "string"
+ }
+ }
+ },
+ "FullBlockTransactionActionV1": {
+ "type": "object",
+ "description": "Transaction action returned from fabric block.",
+ "required": [
+ "functionName",
+ "functionArgs",
+ "chaincodeId",
+ "creator",
+ "endorsements"
+ ],
+ "properties": {
+ "functionName": {
+ "nullable": false,
+ "type": "string"
+ },
+ "functionArgs": {
+ "type": "array",
+ "items": {
+ "nullable": false,
+ "type": "string"
+ }
+ },
+ "chaincodeId": {
+ "nullable": false,
+ "type": "string"
+ },
+ "creator": {
+ "$ref": "#/components/schemas/FabricCertificateIdentityV1",
+ "nullable": false
+ },
+ "endorsements": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/FullBlockTransactionEndorsementV1",
+ "nullable": false
+ }
+ }
+ }
+ },
+ "FullBlockTransactionEventV1": {
+ "type": "object",
+ "description": "Transaction returned from fabric block.",
+ "required": [
+ "hash",
+ "channelId",
+ "timestamp",
+ "protocolVersion",
+ "transactionType",
+ "epoch",
+ "actions"
+ ],
+ "properties": {
+ "hash": {
+ "nullable": false,
+ "type": "string"
+ },
+ "channelId": {
+ "nullable": false,
+ "type": "string"
+ },
+ "timestamp": {
+ "nullable": false,
+ "type": "string"
+ },
+ "protocolVersion": {
+ "nullable": false,
+ "type": "number"
+ },
+ "transactionType": {
+ "nullable": false,
+ "type": "string"
+ },
+ "epoch": {
+ "nullable": false,
+ "type": "number"
+ },
+ "actions": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/FullBlockTransactionActionV1",
+ "nullable": false
+ }
+ }
+ }
+ },
+ "CactiBlockFullEventV1": {
+ "type": "object",
+ "description": "Custom format full fabric block with transactions",
+ "required": [
+ "blockNumber",
+ "blockHash",
+ "previousBlockHash",
+ "transactionCount",
+ "cactiTransactionsEvents"
+ ],
+ "properties": {
+ "blockNumber": {
+ "nullable": false,
+ "type": "number"
+ },
+ "blockHash": {
+ "nullable": false,
+ "type": "string"
+ },
+ "previousBlockHash": {
+ "nullable": false,
+ "type": "string"
+ },
+ "transactionCount": {
+ "nullable": false,
+ "type": "number"
+ },
+ "cactiTransactionsEvents": {
+ "type": "array",
+ "items": {
+ "$ref": "#/components/schemas/FullBlockTransactionEventV1",
+ "nullable": false
+ }
+ }
+ }
+ },
"WatchBlocksCactusErrorResponseV1": {
"type": "object",
"description": "Error response from WatchBlocks operation.",
@@ -1314,7 +1597,11 @@
"description": "Response block from WatchBlocks endpoint. Depends on 'type' passed in subscription options.",
"oneOf": [
{
- "$ref": "#/components/schemas/WatchBlocksCactusTransactionsResponseV1",
+ "$ref": "#/components/schemas/CactiBlockTransactionsResponseV1",
+ "nullable": false
+ },
+ {
+ "$ref": "#/components/schemas/CactiBlockFullResponseV1",
"nullable": false
},
{
@@ -1617,6 +1904,50 @@
}
}
},
+ "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info": {
+ "post": {
+ "operationId": "getChainInfoV1",
+ "summary": "Get fabric ledger chain info.",
+ "x-hyperledger-cacti": {
+ "http": {
+ "verbLowerCase": "post",
+ "path": "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info"
+ }
+ },
+ "parameters": [],
+ "requestBody": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/GetChainInfoRequestV1"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "OK",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/GetChainInfoResponseV1"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ErrorExceptionResponseV1"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics": {
"get": {
"x-hyperledger-cacti": {
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES
index 60dc2bf86b..b88f5e8810 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/.openapi-generator/FILES
@@ -21,6 +21,10 @@ src/main/kotlin/org/openapitools/client/infrastructure/ResponseExtensions.kt
src/main/kotlin/org/openapitools/client/infrastructure/Serializer.kt
src/main/kotlin/org/openapitools/client/infrastructure/URIAdapter.kt
src/main/kotlin/org/openapitools/client/infrastructure/UUIDAdapter.kt
+src/main/kotlin/org/openapitools/client/models/CactiBlockFullEventV1.kt
+src/main/kotlin/org/openapitools/client/models/CactiBlockFullResponseV1.kt
+src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionEventV1.kt
+src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionsResponseV1.kt
src/main/kotlin/org/openapitools/client/models/ChainCodeLanguageRuntime.kt
src/main/kotlin/org/openapitools/client/models/ChainCodeLifeCycleCommandResponses.kt
src/main/kotlin/org/openapitools/client/models/ChainCodeProgrammingLanguage.kt
@@ -36,10 +40,15 @@ src/main/kotlin/org/openapitools/client/models/DeployContractV1Response.kt
src/main/kotlin/org/openapitools/client/models/DeploymentTargetOrgFabric2x.kt
src/main/kotlin/org/openapitools/client/models/DeploymentTargetOrganization.kt
src/main/kotlin/org/openapitools/client/models/ErrorExceptionResponseV1.kt
+src/main/kotlin/org/openapitools/client/models/FabricCertificateIdentityV1.kt
src/main/kotlin/org/openapitools/client/models/FabricContractInvocationType.kt
src/main/kotlin/org/openapitools/client/models/FabricSigningCredential.kt
src/main/kotlin/org/openapitools/client/models/FabricSigningCredentialType.kt
+src/main/kotlin/org/openapitools/client/models/FabricX509CertificateV1.kt
src/main/kotlin/org/openapitools/client/models/FileBase64.kt
+src/main/kotlin/org/openapitools/client/models/FullBlockTransactionActionV1.kt
+src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEndorsementV1.kt
+src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEventV1.kt
src/main/kotlin/org/openapitools/client/models/GatewayDiscoveryOptions.kt
src/main/kotlin/org/openapitools/client/models/GatewayEventHandlerOptions.kt
src/main/kotlin/org/openapitools/client/models/GatewayOptions.kt
@@ -49,7 +58,10 @@ src/main/kotlin/org/openapitools/client/models/GetBlockRequestV1Query.kt
src/main/kotlin/org/openapitools/client/models/GetBlockRequestV1QueryBlockHash.kt
src/main/kotlin/org/openapitools/client/models/GetBlockResponseDecodedV1.kt
src/main/kotlin/org/openapitools/client/models/GetBlockResponseEncodedV1.kt
+src/main/kotlin/org/openapitools/client/models/GetBlockResponseTypeV1.kt
src/main/kotlin/org/openapitools/client/models/GetBlockResponseV1.kt
+src/main/kotlin/org/openapitools/client/models/GetChainInfoRequestV1.kt
+src/main/kotlin/org/openapitools/client/models/GetChainInfoResponseV1.kt
src/main/kotlin/org/openapitools/client/models/GetTransactionReceiptResponse.kt
src/main/kotlin/org/openapitools/client/models/RunDelegatedSignTransactionRequest.kt
src/main/kotlin/org/openapitools/client/models/RunTransactionRequest.kt
@@ -61,8 +73,6 @@ src/main/kotlin/org/openapitools/client/models/TransactReceiptTransactionCreator
src/main/kotlin/org/openapitools/client/models/TransactReceiptTransactionEndorsement.kt
src/main/kotlin/org/openapitools/client/models/VaultTransitKey.kt
src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusErrorResponseV1.kt
-src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsEventV1.kt
-src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsResponseV1.kt
src/main/kotlin/org/openapitools/client/models/WatchBlocksDelegatedSignOptionsV1.kt
src/main/kotlin/org/openapitools/client/models/WatchBlocksFilteredResponseV1.kt
src/main/kotlin/org/openapitools/client/models/WatchBlocksFullResponseV1.kt
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/README.md b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/README.md
index b53638d3dd..b6cce4d18a 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/README.md
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/README.md
@@ -47,6 +47,7 @@ Class | Method | HTTP request | Description
*DefaultApi* | [**deployContractGoSourceV1**](docs/DefaultApi.md#deploycontractgosourcev1) | **POST** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/deploy-contract-go-source | Deploys a chaincode contract in the form of a go sources.
*DefaultApi* | [**deployContractV1**](docs/DefaultApi.md#deploycontractv1) | **POST** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/deploy-contract | Deploys a chaincode contract from a set of source files. Note: This endpoint only supports Fabric 2.x. The 'v1' suffix in the method name refers to the Cactus API version, not the supported Fabric ledger version.
*DefaultApi* | [**getBlockV1**](docs/DefaultApi.md#getblockv1) | **POST** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-block | Get block from the channel using one of selectors from the input. Works only on Fabric 2.x.
+*DefaultApi* | [**getChainInfoV1**](docs/DefaultApi.md#getchaininfov1) | **POST** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info | Get fabric ledger chain info.
*DefaultApi* | [**getPrometheusMetricsV1**](docs/DefaultApi.md#getprometheusmetricsv1) | **GET** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics | Get the Prometheus Metrics
*DefaultApi* | [**getTransactionReceiptByTxIDV1**](docs/DefaultApi.md#gettransactionreceiptbytxidv1) | **POST** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-transaction-receipt-by-txid | get a transaction receipt by tx id on a Fabric ledger.
*DefaultApi* | [**runDelegatedSignTransactionV1**](docs/DefaultApi.md#rundelegatedsigntransactionv1) | **POST** /api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/run-delegated-sign-transaction | Runs a transaction on a Fabric ledger using user-provided signing callback.
@@ -56,6 +57,10 @@ Class | Method | HTTP request | Description
## Documentation for Models
+ - [org.openapitools.client.models.CactiBlockFullEventV1](docs/CactiBlockFullEventV1.md)
+ - [org.openapitools.client.models.CactiBlockFullResponseV1](docs/CactiBlockFullResponseV1.md)
+ - [org.openapitools.client.models.CactiBlockTransactionEventV1](docs/CactiBlockTransactionEventV1.md)
+ - [org.openapitools.client.models.CactiBlockTransactionsResponseV1](docs/CactiBlockTransactionsResponseV1.md)
- [org.openapitools.client.models.ChainCodeLanguageRuntime](docs/ChainCodeLanguageRuntime.md)
- [org.openapitools.client.models.ChainCodeLifeCycleCommandResponses](docs/ChainCodeLifeCycleCommandResponses.md)
- [org.openapitools.client.models.ChainCodeProgrammingLanguage](docs/ChainCodeProgrammingLanguage.md)
@@ -71,10 +76,15 @@ Class | Method | HTTP request | Description
- [org.openapitools.client.models.DeploymentTargetOrgFabric2x](docs/DeploymentTargetOrgFabric2x.md)
- [org.openapitools.client.models.DeploymentTargetOrganization](docs/DeploymentTargetOrganization.md)
- [org.openapitools.client.models.ErrorExceptionResponseV1](docs/ErrorExceptionResponseV1.md)
+ - [org.openapitools.client.models.FabricCertificateIdentityV1](docs/FabricCertificateIdentityV1.md)
- [org.openapitools.client.models.FabricContractInvocationType](docs/FabricContractInvocationType.md)
- [org.openapitools.client.models.FabricSigningCredential](docs/FabricSigningCredential.md)
- [org.openapitools.client.models.FabricSigningCredentialType](docs/FabricSigningCredentialType.md)
+ - [org.openapitools.client.models.FabricX509CertificateV1](docs/FabricX509CertificateV1.md)
- [org.openapitools.client.models.FileBase64](docs/FileBase64.md)
+ - [org.openapitools.client.models.FullBlockTransactionActionV1](docs/FullBlockTransactionActionV1.md)
+ - [org.openapitools.client.models.FullBlockTransactionEndorsementV1](docs/FullBlockTransactionEndorsementV1.md)
+ - [org.openapitools.client.models.FullBlockTransactionEventV1](docs/FullBlockTransactionEventV1.md)
- [org.openapitools.client.models.GatewayDiscoveryOptions](docs/GatewayDiscoveryOptions.md)
- [org.openapitools.client.models.GatewayEventHandlerOptions](docs/GatewayEventHandlerOptions.md)
- [org.openapitools.client.models.GatewayOptions](docs/GatewayOptions.md)
@@ -84,7 +94,10 @@ Class | Method | HTTP request | Description
- [org.openapitools.client.models.GetBlockRequestV1QueryBlockHash](docs/GetBlockRequestV1QueryBlockHash.md)
- [org.openapitools.client.models.GetBlockResponseDecodedV1](docs/GetBlockResponseDecodedV1.md)
- [org.openapitools.client.models.GetBlockResponseEncodedV1](docs/GetBlockResponseEncodedV1.md)
+ - [org.openapitools.client.models.GetBlockResponseTypeV1](docs/GetBlockResponseTypeV1.md)
- [org.openapitools.client.models.GetBlockResponseV1](docs/GetBlockResponseV1.md)
+ - [org.openapitools.client.models.GetChainInfoRequestV1](docs/GetChainInfoRequestV1.md)
+ - [org.openapitools.client.models.GetChainInfoResponseV1](docs/GetChainInfoResponseV1.md)
- [org.openapitools.client.models.GetTransactionReceiptResponse](docs/GetTransactionReceiptResponse.md)
- [org.openapitools.client.models.RunDelegatedSignTransactionRequest](docs/RunDelegatedSignTransactionRequest.md)
- [org.openapitools.client.models.RunTransactionRequest](docs/RunTransactionRequest.md)
@@ -96,8 +109,6 @@ Class | Method | HTTP request | Description
- [org.openapitools.client.models.TransactReceiptTransactionEndorsement](docs/TransactReceiptTransactionEndorsement.md)
- [org.openapitools.client.models.VaultTransitKey](docs/VaultTransitKey.md)
- [org.openapitools.client.models.WatchBlocksCactusErrorResponseV1](docs/WatchBlocksCactusErrorResponseV1.md)
- - [org.openapitools.client.models.WatchBlocksCactusTransactionsEventV1](docs/WatchBlocksCactusTransactionsEventV1.md)
- - [org.openapitools.client.models.WatchBlocksCactusTransactionsResponseV1](docs/WatchBlocksCactusTransactionsResponseV1.md)
- [org.openapitools.client.models.WatchBlocksDelegatedSignOptionsV1](docs/WatchBlocksDelegatedSignOptionsV1.md)
- [org.openapitools.client.models.WatchBlocksFilteredResponseV1](docs/WatchBlocksFilteredResponseV1.md)
- [org.openapitools.client.models.WatchBlocksFullResponseV1](docs/WatchBlocksFullResponseV1.md)
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt
index 7f3d897bb5..121dac0591 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/apis/DefaultApi.kt
@@ -27,6 +27,8 @@ import org.openapitools.client.models.DeployContractV1Response
import org.openapitools.client.models.ErrorExceptionResponseV1
import org.openapitools.client.models.GetBlockRequestV1
import org.openapitools.client.models.GetBlockResponseV1
+import org.openapitools.client.models.GetChainInfoRequestV1
+import org.openapitools.client.models.GetChainInfoResponseV1
import org.openapitools.client.models.GetTransactionReceiptResponse
import org.openapitools.client.models.RunDelegatedSignTransactionRequest
import org.openapitools.client.models.RunTransactionRequest
@@ -272,6 +274,78 @@ class DefaultApi(basePath: kotlin.String = defaultBasePath, client: OkHttpClient
)
}
+ /**
+ * Get fabric ledger chain info.
+ *
+ * @param getChainInfoRequestV1 (optional)
+ * @return GetChainInfoResponseV1
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ * @throws UnsupportedOperationException If the API returns an informational or redirection response
+ * @throws ClientException If the API returns a client error response
+ * @throws ServerException If the API returns a server error response
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class, UnsupportedOperationException::class, ClientException::class, ServerException::class)
+ fun getChainInfoV1(getChainInfoRequestV1: GetChainInfoRequestV1? = null) : GetChainInfoResponseV1 {
+ val localVarResponse = getChainInfoV1WithHttpInfo(getChainInfoRequestV1 = getChainInfoRequestV1)
+
+ return when (localVarResponse.responseType) {
+ ResponseType.Success -> (localVarResponse as Success<*>).data as GetChainInfoResponseV1
+ ResponseType.Informational -> throw UnsupportedOperationException("Client does not support Informational responses.")
+ ResponseType.Redirection -> throw UnsupportedOperationException("Client does not support Redirection responses.")
+ ResponseType.ClientError -> {
+ val localVarError = localVarResponse as ClientError<*>
+ throw ClientException("Client error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ ResponseType.ServerError -> {
+ val localVarError = localVarResponse as ServerError<*>
+ throw ServerException("Server error : ${localVarError.statusCode} ${localVarError.message.orEmpty()}", localVarError.statusCode, localVarResponse)
+ }
+ }
+ }
+
+ /**
+ * Get fabric ledger chain info.
+ *
+ * @param getChainInfoRequestV1 (optional)
+ * @return ApiResponse
+ * @throws IllegalStateException If the request is not correctly configured
+ * @throws IOException Rethrows the OkHttp execute method exception
+ */
+ @Suppress("UNCHECKED_CAST")
+ @Throws(IllegalStateException::class, IOException::class)
+ fun getChainInfoV1WithHttpInfo(getChainInfoRequestV1: GetChainInfoRequestV1?) : ApiResponse {
+ val localVariableConfig = getChainInfoV1RequestConfig(getChainInfoRequestV1 = getChainInfoRequestV1)
+
+ return request(
+ localVariableConfig
+ )
+ }
+
+ /**
+ * To obtain the request config of the operation getChainInfoV1
+ *
+ * @param getChainInfoRequestV1 (optional)
+ * @return RequestConfig
+ */
+ fun getChainInfoV1RequestConfig(getChainInfoRequestV1: GetChainInfoRequestV1?) : RequestConfig {
+ val localVariableBody = getChainInfoRequestV1
+ val localVariableQuery: MultiValueMap = mutableMapOf()
+ val localVariableHeaders: MutableMap = mutableMapOf()
+ localVariableHeaders["Content-Type"] = "application/json"
+ localVariableHeaders["Accept"] = "application/json"
+
+ return RequestConfig(
+ method = RequestMethod.POST,
+ path = "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info",
+ query = localVariableQuery,
+ headers = localVariableHeaders,
+ requiresAuthentication = false,
+ body = localVariableBody
+ )
+ }
+
/**
* Get the Prometheus Metrics
*
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockFullEventV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockFullEventV1.kt
new file mode 100644
index 0000000000..787a3429ae
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockFullEventV1.kt
@@ -0,0 +1,52 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.FullBlockTransactionEventV1
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Custom format full fabric block with transactions
+ *
+ * @param blockNumber
+ * @param blockHash
+ * @param previousBlockHash
+ * @param transactionCount
+ * @param cactiTransactionsEvents
+ */
+
+
+data class CactiBlockFullEventV1 (
+
+ @Json(name = "blockNumber")
+ val blockNumber: java.math.BigDecimal,
+
+ @Json(name = "blockHash")
+ val blockHash: kotlin.String,
+
+ @Json(name = "previousBlockHash")
+ val previousBlockHash: kotlin.String,
+
+ @Json(name = "transactionCount")
+ val transactionCount: java.math.BigDecimal,
+
+ @Json(name = "cactiTransactionsEvents")
+ val cactiTransactionsEvents: kotlin.collections.List
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockFullResponseV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockFullResponseV1.kt
new file mode 100644
index 0000000000..f01837075d
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockFullResponseV1.kt
@@ -0,0 +1,36 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.CactiBlockFullEventV1
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Custom response containing full block summary.
+ *
+ * @param cactiFullEvents
+ */
+
+
+data class CactiBlockFullResponseV1 (
+
+ @Json(name = "cactiFullEvents")
+ val cactiFullEvents: CactiBlockFullEventV1
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsEventV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionEventV1.kt
similarity index 95%
rename from packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsEventV1.kt
rename to packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionEventV1.kt
index c504d8dc1a..b8769ce0af 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsEventV1.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionEventV1.kt
@@ -29,7 +29,7 @@ import com.squareup.moshi.JsonClass
*/
-data class WatchBlocksCactusTransactionsEventV1 (
+data class CactiBlockTransactionEventV1 (
/* ChainCode containing function that was executed. */
@Json(name = "chaincodeId")
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsResponseV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionsResponseV1.kt
similarity index 62%
rename from packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsResponseV1.kt
rename to packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionsResponseV1.kt
index c79b366efb..cde44f8ed0 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksCactusTransactionsResponseV1.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/CactiBlockTransactionsResponseV1.kt
@@ -15,7 +15,7 @@
package org.openapitools.client.models
-import org.openapitools.client.models.WatchBlocksCactusTransactionsEventV1
+import org.openapitools.client.models.CactiBlockTransactionEventV1
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@@ -23,15 +23,15 @@ import com.squareup.moshi.JsonClass
/**
* Custom response containing block transactions summary. Compatible with legacy fabric-socketio connector monitoring.
*
- * @param cactusTransactionsEvents List of transactions summary
+ * @param cactiTransactionsEvents List of transactions summary
*/
-data class WatchBlocksCactusTransactionsResponseV1 (
+data class CactiBlockTransactionsResponseV1 (
/* List of transactions summary */
- @Json(name = "cactusTransactionsEvents")
- val cactusTransactionsEvents: kotlin.collections.List
+ @Json(name = "cactiTransactionsEvents")
+ val cactiTransactionsEvents: kotlin.collections.List
)
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FabricCertificateIdentityV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FabricCertificateIdentityV1.kt
new file mode 100644
index 0000000000..f08a5362aa
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FabricCertificateIdentityV1.kt
@@ -0,0 +1,40 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.FabricX509CertificateV1
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Combination of certificate and it's MSP ID used to identify fabric actors.
+ *
+ * @param mspid
+ * @param cert
+ */
+
+
+data class FabricCertificateIdentityV1 (
+
+ @Json(name = "mspid")
+ val mspid: kotlin.String,
+
+ @Json(name = "cert")
+ val cert: FabricX509CertificateV1
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FabricX509CertificateV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FabricX509CertificateV1.kt
new file mode 100644
index 0000000000..e995cc65f0
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FabricX509CertificateV1.kt
@@ -0,0 +1,59 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Transaction endorser certificate object
+ *
+ * @param issuer
+ * @param serialNumber
+ * @param subject
+ * @param subjectAltName
+ * @param validFrom
+ * @param validTo
+ * @param pem
+ */
+
+
+data class FabricX509CertificateV1 (
+
+ @Json(name = "issuer")
+ val issuer: kotlin.String,
+
+ @Json(name = "serialNumber")
+ val serialNumber: kotlin.String,
+
+ @Json(name = "subject")
+ val subject: kotlin.String,
+
+ @Json(name = "subjectAltName")
+ val subjectAltName: kotlin.String,
+
+ @Json(name = "validFrom")
+ val validFrom: kotlin.String,
+
+ @Json(name = "validTo")
+ val validTo: kotlin.String,
+
+ @Json(name = "pem")
+ val pem: kotlin.String
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionActionV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionActionV1.kt
new file mode 100644
index 0000000000..1e0dd13b4e
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionActionV1.kt
@@ -0,0 +1,53 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.FabricCertificateIdentityV1
+import org.openapitools.client.models.FullBlockTransactionEndorsementV1
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Transaction action returned from fabric block.
+ *
+ * @param functionName
+ * @param functionArgs
+ * @param chaincodeId
+ * @param creator
+ * @param endorsements
+ */
+
+
+data class FullBlockTransactionActionV1 (
+
+ @Json(name = "functionName")
+ val functionName: kotlin.String,
+
+ @Json(name = "functionArgs")
+ val functionArgs: kotlin.collections.List,
+
+ @Json(name = "chaincodeId")
+ val chaincodeId: kotlin.String,
+
+ @Json(name = "creator")
+ val creator: FabricCertificateIdentityV1,
+
+ @Json(name = "endorsements")
+ val endorsements: kotlin.collections.List
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEndorsementV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEndorsementV1.kt
new file mode 100644
index 0000000000..e85c781fca
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEndorsementV1.kt
@@ -0,0 +1,40 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.FabricCertificateIdentityV1
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Transaction endorsment object returned from fabric block.
+ *
+ * @param signer
+ * @param signature
+ */
+
+
+data class FullBlockTransactionEndorsementV1 (
+
+ @Json(name = "signer")
+ val signer: FabricCertificateIdentityV1,
+
+ @Json(name = "signature")
+ val signature: kotlin.String
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEventV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEventV1.kt
new file mode 100644
index 0000000000..9f5031b74e
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/FullBlockTransactionEventV1.kt
@@ -0,0 +1,60 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.FullBlockTransactionActionV1
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Transaction returned from fabric block.
+ *
+ * @param hash
+ * @param channelId
+ * @param timestamp
+ * @param protocolVersion
+ * @param transactionType
+ * @param epoch
+ * @param actions
+ */
+
+
+data class FullBlockTransactionEventV1 (
+
+ @Json(name = "hash")
+ val hash: kotlin.String,
+
+ @Json(name = "channelId")
+ val channelId: kotlin.String,
+
+ @Json(name = "timestamp")
+ val timestamp: kotlin.String,
+
+ @Json(name = "protocolVersion")
+ val protocolVersion: java.math.BigDecimal,
+
+ @Json(name = "transactionType")
+ val transactionType: kotlin.String,
+
+ @Json(name = "epoch")
+ val epoch: java.math.BigDecimal,
+
+ @Json(name = "actions")
+ val actions: kotlin.collections.List
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockRequestV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockRequestV1.kt
index bdb130a869..a2224e88cf 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockRequestV1.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockRequestV1.kt
@@ -17,6 +17,7 @@ package org.openapitools.client.models
import org.openapitools.client.models.GatewayOptions
import org.openapitools.client.models.GetBlockRequestV1Query
+import org.openapitools.client.models.GetBlockResponseTypeV1
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@@ -28,7 +29,7 @@ import com.squareup.moshi.JsonClass
* @param gatewayOptions
* @param query
* @param connectionChannelName Fabric channel we want to connect to. If not provided, then one from channelName parameter will be used
- * @param skipDecode If true, encoded buffer will be returned. Otherwise, entire block object is returned.
+ * @param responseType
*/
@@ -48,9 +49,8 @@ data class GetBlockRequestV1 (
@Json(name = "connectionChannelName")
val connectionChannelName: kotlin.String? = null,
- /* If true, encoded buffer will be returned. Otherwise, entire block object is returned. */
- @Json(name = "skipDecode")
- val skipDecode: kotlin.Boolean? = false
+ @Json(name = "responseType")
+ val responseType: GetBlockResponseTypeV1? = GetBlockResponseTypeV1.Full
)
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseTypeV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseTypeV1.kt
new file mode 100644
index 0000000000..22f8ae1050
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseTypeV1.kt
@@ -0,0 +1,69 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Response type from GetBlock.
+ *
+ * Values: Full,Encoded,CactiTransactions,CactiFullBlock
+ */
+
+@JsonClass(generateAdapter = false)
+enum class GetBlockResponseTypeV1(val value: kotlin.String) {
+
+ @Json(name = "full")
+ Full("full"),
+
+ @Json(name = "encoded")
+ Encoded("encoded"),
+
+ @Json(name = "cacti:transactions")
+ CactiTransactions("cacti:transactions"),
+
+ @Json(name = "cacti:full-block")
+ CactiFullBlock("cacti:full-block");
+
+ /**
+ * Override [toString()] to avoid using the enum variable name as the value, and instead use
+ * the actual value defined in the API spec file.
+ *
+ * This solves a problem when the variable name and its value are different, and ensures that
+ * the client sends the correct enum values to the server always.
+ */
+ override fun toString(): String = value
+
+ companion object {
+ /**
+ * Converts the provided [data] to a [String] on success, null otherwise.
+ */
+ fun encode(data: kotlin.Any?): kotlin.String? = if (data is GetBlockResponseTypeV1) "$data" else null
+
+ /**
+ * Returns a valid [GetBlockResponseTypeV1] for [data], null otherwise.
+ */
+ fun decode(data: kotlin.Any?): GetBlockResponseTypeV1? = data?.let {
+ val normalizedData = "$it".lowercase()
+ values().firstOrNull { value ->
+ it == value || normalizedData == "$value".lowercase()
+ }
+ }
+ }
+}
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseV1.kt
index 967461afd3..c19a2c8cbe 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseV1.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetBlockResponseV1.kt
@@ -15,6 +15,10 @@
package org.openapitools.client.models
+import org.openapitools.client.models.CactiBlockFullEventV1
+import org.openapitools.client.models.CactiBlockFullResponseV1
+import org.openapitools.client.models.CactiBlockTransactionEventV1
+import org.openapitools.client.models.CactiBlockTransactionsResponseV1
import org.openapitools.client.models.GetBlockResponseDecodedV1
import org.openapitools.client.models.GetBlockResponseEncodedV1
@@ -24,6 +28,8 @@ import com.squareup.moshi.JsonClass
/**
* Response from GetBlock endpoint.
*
+ * @param cactiTransactionsEvents List of transactions summary
+ * @param cactiFullEvents
* @param decodedBlock Full hyperledger fabric block data.
* @param encodedBlock
*/
@@ -31,6 +37,13 @@ import com.squareup.moshi.JsonClass
data class GetBlockResponseV1 (
+ /* List of transactions summary */
+ @Json(name = "cactiTransactionsEvents")
+ val cactiTransactionsEvents: kotlin.collections.List,
+
+ @Json(name = "cactiFullEvents")
+ val cactiFullEvents: CactiBlockFullEventV1,
+
/* Full hyperledger fabric block data. */
@Json(name = "decodedBlock")
val decodedBlock: kotlin.Any?,
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetChainInfoRequestV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetChainInfoRequestV1.kt
new file mode 100644
index 0000000000..71b1d92cf3
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetChainInfoRequestV1.kt
@@ -0,0 +1,46 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+import org.openapitools.client.models.GatewayOptions
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Request for GetChainInfo endpoint.
+ *
+ * @param channelName Fabric channel which we want to query.
+ * @param gatewayOptions
+ * @param connectionChannelName Fabric channel we want to connect to. If not provided, then one from channelName parameter will be used
+ */
+
+
+data class GetChainInfoRequestV1 (
+
+ /* Fabric channel which we want to query. */
+ @Json(name = "channelName")
+ val channelName: kotlin.String,
+
+ @Json(name = "gatewayOptions")
+ val gatewayOptions: GatewayOptions,
+
+ /* Fabric channel we want to connect to. If not provided, then one from channelName parameter will be used */
+ @Json(name = "connectionChannelName")
+ val connectionChannelName: kotlin.String? = null
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetChainInfoResponseV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetChainInfoResponseV1.kt
new file mode 100644
index 0000000000..81201ab222
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/GetChainInfoResponseV1.kt
@@ -0,0 +1,46 @@
+/**
+ *
+ * Please note:
+ * This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
+ * Do not edit this file manually.
+ *
+ */
+
+@file:Suppress(
+ "ArrayInDataClass",
+ "EnumEntryName",
+ "RemoveRedundantQualifierName",
+ "UnusedImport"
+)
+
+package org.openapitools.client.models
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+/**
+ * Response from GetChainInfo endpoint.
+ *
+ * @param height Current height of fabric ledger
+ * @param currentBlockHash Current block hash of fabric ledger
+ * @param previousBlockHash Previous block hash of fabric ledger
+ */
+
+
+data class GetChainInfoResponseV1 (
+
+ /* Current height of fabric ledger */
+ @Json(name = "height")
+ val height: java.math.BigDecimal,
+
+ /* Current block hash of fabric ledger */
+ @Json(name = "currentBlockHash")
+ val currentBlockHash: kotlin.String,
+
+ /* Previous block hash of fabric ledger */
+ @Json(name = "previousBlockHash")
+ val previousBlockHash: kotlin.String
+
+)
+
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksListenerTypeV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksListenerTypeV1.kt
index 42a5adf2c8..5656a4b7ec 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksListenerTypeV1.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksListenerTypeV1.kt
@@ -20,9 +20,9 @@ import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
- * Response type from WatchBlocks. 'Cactus*' are custom views, others correspond to fabric SDK call.
+ * Response type from WatchBlocks. 'Cacti*' are custom views, others correspond to fabric SDK call.
*
- * Values: Filtered,Full,Private,CactusTransactions
+ * Values: Filtered,Full,Private,CactiTransactions,CactiFullBlock
*/
@JsonClass(generateAdapter = false)
@@ -37,8 +37,11 @@ enum class WatchBlocksListenerTypeV1(val value: kotlin.String) {
@Json(name = "private")
Private("private"),
- @Json(name = "cactus:transactions")
- CactusTransactions("cactus:transactions");
+ @Json(name = "cacti:transactions")
+ CactiTransactions("cacti:transactions"),
+
+ @Json(name = "cacti:full-block")
+ CactiFullBlock("cacti:full-block");
/**
* Override [toString()] to avoid using the enum variable name as the value, and instead use
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksResponseV1.kt b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksResponseV1.kt
index 4939f4c2f1..0fff884ce6 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksResponseV1.kt
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/kotlin/generated/openapi/kotlin-client/src/main/kotlin/org/openapitools/client/models/WatchBlocksResponseV1.kt
@@ -15,9 +15,11 @@
package org.openapitools.client.models
+import org.openapitools.client.models.CactiBlockFullEventV1
+import org.openapitools.client.models.CactiBlockFullResponseV1
+import org.openapitools.client.models.CactiBlockTransactionEventV1
+import org.openapitools.client.models.CactiBlockTransactionsResponseV1
import org.openapitools.client.models.WatchBlocksCactusErrorResponseV1
-import org.openapitools.client.models.WatchBlocksCactusTransactionsEventV1
-import org.openapitools.client.models.WatchBlocksCactusTransactionsResponseV1
import org.openapitools.client.models.WatchBlocksFilteredResponseV1
import org.openapitools.client.models.WatchBlocksFullResponseV1
import org.openapitools.client.models.WatchBlocksPrivateResponseV1
@@ -28,7 +30,8 @@ import com.squareup.moshi.JsonClass
/**
* Response block from WatchBlocks endpoint. Depends on 'type' passed in subscription options.
*
- * @param cactusTransactionsEvents List of transactions summary
+ * @param cactiTransactionsEvents List of transactions summary
+ * @param cactiFullEvents
* @param fullBlock Full commited block.
* @param filteredBlock Filtered commited block.
* @param privateBlock Private commited block.
@@ -40,8 +43,11 @@ import com.squareup.moshi.JsonClass
data class WatchBlocksResponseV1 (
/* List of transactions summary */
- @Json(name = "cactusTransactionsEvents")
- val cactusTransactionsEvents: kotlin.collections.List,
+ @Json(name = "cactiTransactionsEvents")
+ val cactiTransactionsEvents: kotlin.collections.List,
+
+ @Json(name = "cactiFullEvents")
+ val cactiFullEvents: CactiBlockFullEventV1,
/* Full commited block. */
@Json(name = "fullBlock")
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/api-client/fabric-api-client.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/api-client/fabric-api-client.ts
index c3ae330dde..c43a047641 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/api-client/fabric-api-client.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/api-client/fabric-api-client.ts
@@ -15,8 +15,8 @@ import {
WatchBlocksOptionsV1,
WatchBlocksResponseV1,
WatchBlocksDelegatedSignOptionsV1,
- WatchBlocksCactusTransactionsResponseV1,
- WatchBlocksCactusTransactionsEventV1,
+ CactiBlockTransactionsResponseV1,
+ CactiBlockTransactionEventV1,
} from "../generated/openapi/typescript-axios";
import { Configuration } from "../generated/openapi/typescript-axios/configuration";
@@ -181,56 +181,54 @@ export class FabricApiClient
* @warning: Remember to use timeout mechanism on production
*
* @param txId transactionId to wait for.
- * @param monitorObservable Block observable in CactusTransactions mode (important - other mode will not work!)
- * @returns `WatchBlocksCactusTransactionsEventV1` of specified transaction.
+ * @param monitorObservable Block observable in CactiTransactions mode (important - other mode will not work!)
+ * @returns `CactiBlockTransactionEventV1` of specified transaction.
*/
public async waitForTransactionCommit(
txId: string,
- monitorObservable: Observable,
+ monitorObservable: Observable,
) {
this.log.info("waitForTransactionCommit()", txId);
- return new Promise(
- (resolve, reject) => {
- const subscription = monitorObservable.subscribe({
- next: (event) => {
- try {
- this.log.debug(
- "waitForTransactionCommit() Received event:",
- JSON.stringify(event),
- );
- if (!("cactusTransactionsEvents" in event)) {
- throw new Error("Invalid event type received!");
- }
+ return new Promise((resolve, reject) => {
+ const subscription = monitorObservable.subscribe({
+ next: (event) => {
+ try {
+ this.log.debug(
+ "waitForTransactionCommit() Received event:",
+ JSON.stringify(event),
+ );
+ if (!("cactiTransactionsEvents" in event)) {
+ throw new Error("Invalid event type received!");
+ }
- const foundTransaction = event.cactusTransactionsEvents.find(
- (tx) => tx.transactionId === txId,
- );
- if (foundTransaction) {
- this.log.info(
- "waitForTransactionCommit() Found transaction with txId",
- txId,
- );
- subscription.unsubscribe();
- resolve(foundTransaction);
- }
- } catch (err) {
- this.log.error(
- "waitForTransactionCommit() event check error:",
- err,
+ const foundTransaction = event.cactiTransactionsEvents.find(
+ (tx) => tx.transactionId === txId,
+ );
+ if (foundTransaction) {
+ this.log.info(
+ "waitForTransactionCommit() Found transaction with txId",
+ txId,
);
subscription.unsubscribe();
- reject(err);
+ resolve(foundTransaction);
}
- },
- error: (err) => {
- this.log.error("waitForTransactionCommit() error:", err);
+ } catch (err) {
+ this.log.error(
+ "waitForTransactionCommit() event check error:",
+ err,
+ );
subscription.unsubscribe();
reject(err);
- },
- });
- },
- );
+ }
+ },
+ error: (err) => {
+ this.log.error("waitForTransactionCommit() error:", err);
+ subscription.unsubscribe();
+ reject(err);
+ },
+ });
+ });
}
/**
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/query-system-chain-code.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/query-system-chain-code.ts
index da84cd81f0..0b26fca384 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/query-system-chain-code.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/query-system-chain-code.ts
@@ -1,6 +1,4 @@
import { Gateway } from "fabric-network";
-// BlockDecoder is not exported in ts definition so we need to use legacy import.
-const { BlockDecoder } = require("fabric-common");
const QSCC_ContractName = "qscc";
@@ -10,7 +8,6 @@ const QSCC_ContractName = "qscc";
export interface QuerySystemChainCodeConfig {
gateway: Gateway;
connectionChannelName: string; // used to connect to the network
- skipDecode?: boolean;
}
/**
@@ -19,14 +16,15 @@ export interface QuerySystemChainCodeConfig {
* @param config Configuration of `querySystemChainCode` method itself.
* @param functionName Method on `qscc` to call.
* @param args Args to method from `functionName`
- * @returns Encoded `Buffer` or decoded `JSON string` response from the ledger.
+ *
+ * @returns Encoded `Buffer` response from the ledger.
*/
export async function querySystemChainCode(
config: QuerySystemChainCodeConfig,
functionName: string,
...args: (string | Buffer)[]
-): Promise {
- const { gateway, connectionChannelName, skipDecode } = config;
+): Promise {
+ const { gateway, connectionChannelName } = config;
const network = await gateway.getNetwork(connectionChannelName);
const contract = network.getContract(QSCC_ContractName);
@@ -38,9 +36,5 @@ export async function querySystemChainCode(
throw new Error(`Received empty response from qscc call ${functionName}`);
}
- if (skipDecode) {
- return resultBuffer;
- }
-
- return BlockDecoder.decode(resultBuffer);
+ return resultBuffer;
}
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/utils.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/utils.ts
index ac71ac1ced..b1679192f3 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/utils.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/common/utils.ts
@@ -1,3 +1,5 @@
+import Long from "long";
+
/**
* Check if provided variable is a function. Throws otherwise.
* To be used with unsafe `require()` imports from fabric SDK packages.
@@ -29,3 +31,25 @@ export function asBuffer(bytes: Uint8Array | null | undefined): Buffer {
return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength); // Create a Buffer view to avoid copying
}
+
+export type FabricLong = {
+ low: number;
+ hight: number | undefined;
+ unsigned: boolean | undefined;
+};
+
+/**
+ * Convert Long value returned by some low-level fabric API to regular number.
+ *
+ * @param longNumberObject Long object (with low and hight fields)
+ *
+ * @returns number
+ */
+export function fabricLongToNumber(longNumberObject: FabricLong) {
+ const longValue = new Long(
+ longNumberObject.low,
+ longNumberObject.hight,
+ longNumberObject.unsigned,
+ );
+ return longValue.toNumber();
+}
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios/api.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios/api.ts
index 52dca973d9..b920c7fb43 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios/api.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios/api.ts
@@ -23,6 +23,100 @@ import type { RequestArgs } from './base';
// @ts-ignore
import { BASE_PATH, COLLECTION_FORMATS, BaseAPI, RequiredError } from './base';
+/**
+ * Custom format full fabric block with transactions
+ * @export
+ * @interface CactiBlockFullEventV1
+ */
+export interface CactiBlockFullEventV1 {
+ /**
+ *
+ * @type {number}
+ * @memberof CactiBlockFullEventV1
+ */
+ 'blockNumber': number;
+ /**
+ *
+ * @type {string}
+ * @memberof CactiBlockFullEventV1
+ */
+ 'blockHash': string;
+ /**
+ *
+ * @type {string}
+ * @memberof CactiBlockFullEventV1
+ */
+ 'previousBlockHash': string;
+ /**
+ *
+ * @type {number}
+ * @memberof CactiBlockFullEventV1
+ */
+ 'transactionCount': number;
+ /**
+ *
+ * @type {Array}
+ * @memberof CactiBlockFullEventV1
+ */
+ 'cactiTransactionsEvents': Array;
+}
+/**
+ * Custom response containing full block summary.
+ * @export
+ * @interface CactiBlockFullResponseV1
+ */
+export interface CactiBlockFullResponseV1 {
+ /**
+ *
+ * @type {CactiBlockFullEventV1}
+ * @memberof CactiBlockFullResponseV1
+ */
+ 'cactiFullEvents': CactiBlockFullEventV1;
+}
+/**
+ * Transaction summary from commited block.
+ * @export
+ * @interface CactiBlockTransactionEventV1
+ */
+export interface CactiBlockTransactionEventV1 {
+ /**
+ * ChainCode containing function that was executed.
+ * @type {string}
+ * @memberof CactiBlockTransactionEventV1
+ */
+ 'chaincodeId': string;
+ /**
+ * Transaction identifier.
+ * @type {string}
+ * @memberof CactiBlockTransactionEventV1
+ */
+ 'transactionId': string;
+ /**
+ * Function name that was executed.
+ * @type {string}
+ * @memberof CactiBlockTransactionEventV1
+ */
+ 'functionName': string;
+ /**
+ * List of function arguments.
+ * @type {Array}
+ * @memberof CactiBlockTransactionEventV1
+ */
+ 'functionArgs': Array;
+}
+/**
+ * Custom response containing block transactions summary. Compatible with legacy fabric-socketio connector monitoring.
+ * @export
+ * @interface CactiBlockTransactionsResponseV1
+ */
+export interface CactiBlockTransactionsResponseV1 {
+ /**
+ * List of transactions summary
+ * @type {Array}
+ * @memberof CactiBlockTransactionsResponseV1
+ */
+ 'cactiTransactionsEvents': Array;
+}
/**
* Enumerates the supported programming language runtimes of Hyperledger Fabric
* @export
@@ -554,6 +648,25 @@ export interface ErrorExceptionResponseV1 {
*/
'error': string;
}
+/**
+ * Combination of certificate and it\'s MSP ID used to identify fabric actors.
+ * @export
+ * @interface FabricCertificateIdentityV1
+ */
+export interface FabricCertificateIdentityV1 {
+ /**
+ *
+ * @type {string}
+ * @memberof FabricCertificateIdentityV1
+ */
+ 'mspid': string;
+ /**
+ *
+ * @type {FabricX509CertificateV1}
+ * @memberof FabricCertificateIdentityV1
+ */
+ 'cert': FabricX509CertificateV1;
+}
/**
*
* @export
@@ -623,6 +736,55 @@ export const FabricSigningCredentialType = {
export type FabricSigningCredentialType = typeof FabricSigningCredentialType[keyof typeof FabricSigningCredentialType];
+/**
+ * Transaction endorser certificate object
+ * @export
+ * @interface FabricX509CertificateV1
+ */
+export interface FabricX509CertificateV1 {
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'issuer': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'serialNumber': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'subject': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'subjectAltName': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'validFrom': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'validTo': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FabricX509CertificateV1
+ */
+ 'pem': string;
+}
/**
* Represents a file-system file that has a name and a body which holds the file contents as a Base64 encoded string
* @export
@@ -648,6 +810,111 @@ export interface FileBase64 {
*/
'filepath'?: string;
}
+/**
+ * Transaction action returned from fabric block.
+ * @export
+ * @interface FullBlockTransactionActionV1
+ */
+export interface FullBlockTransactionActionV1 {
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionActionV1
+ */
+ 'functionName': string;
+ /**
+ *
+ * @type {Array}
+ * @memberof FullBlockTransactionActionV1
+ */
+ 'functionArgs': Array;
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionActionV1
+ */
+ 'chaincodeId': string;
+ /**
+ *
+ * @type {FabricCertificateIdentityV1}
+ * @memberof FullBlockTransactionActionV1
+ */
+ 'creator': FabricCertificateIdentityV1;
+ /**
+ *
+ * @type {Array}
+ * @memberof FullBlockTransactionActionV1
+ */
+ 'endorsements': Array;
+}
+/**
+ * Transaction endorsment object returned from fabric block.
+ * @export
+ * @interface FullBlockTransactionEndorsementV1
+ */
+export interface FullBlockTransactionEndorsementV1 {
+ /**
+ *
+ * @type {FabricCertificateIdentityV1}
+ * @memberof FullBlockTransactionEndorsementV1
+ */
+ 'signer': FabricCertificateIdentityV1;
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionEndorsementV1
+ */
+ 'signature': string;
+}
+/**
+ * Transaction returned from fabric block.
+ * @export
+ * @interface FullBlockTransactionEventV1
+ */
+export interface FullBlockTransactionEventV1 {
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'hash': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'channelId': string;
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'timestamp': string;
+ /**
+ *
+ * @type {number}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'protocolVersion': number;
+ /**
+ *
+ * @type {string}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'transactionType': string;
+ /**
+ *
+ * @type {number}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'epoch': number;
+ /**
+ *
+ * @type {Array}
+ * @memberof FullBlockTransactionEventV1
+ */
+ 'actions': Array;
+}
/**
*
* @export
@@ -781,12 +1048,14 @@ export interface GetBlockRequestV1 {
*/
'query': GetBlockRequestV1Query;
/**
- * If true, encoded buffer will be returned. Otherwise, entire block object is returned.
- * @type {boolean}
+ *
+ * @type {GetBlockResponseTypeV1}
* @memberof GetBlockRequestV1
*/
- 'skipDecode'?: boolean;
+ 'responseType'?: GetBlockResponseTypeV1;
}
+
+
/**
* Query selector, caller must provide at least one of them. First found will be used, rest will be ignored, so it\'s recommended to pass single selector.
* @export
@@ -857,13 +1126,79 @@ export interface GetBlockResponseEncodedV1 {
*/
'encodedBlock': string;
}
+/**
+ * Response type from GetBlock.
+ * @export
+ * @enum {string}
+ */
+
+export const GetBlockResponseTypeV1 = {
+ Full: 'full',
+ Encoded: 'encoded',
+ CactiTransactions: 'cacti:transactions',
+ CactiFullBlock: 'cacti:full-block'
+} as const;
+
+export type GetBlockResponseTypeV1 = typeof GetBlockResponseTypeV1[keyof typeof GetBlockResponseTypeV1];
+
+
/**
* @type GetBlockResponseV1
* Response from GetBlock endpoint.
* @export
*/
-export type GetBlockResponseV1 = GetBlockResponseDecodedV1 | GetBlockResponseEncodedV1;
+export type GetBlockResponseV1 = CactiBlockFullResponseV1 | CactiBlockTransactionsResponseV1 | GetBlockResponseDecodedV1 | GetBlockResponseEncodedV1;
+/**
+ * Request for GetChainInfo endpoint.
+ * @export
+ * @interface GetChainInfoRequestV1
+ */
+export interface GetChainInfoRequestV1 {
+ /**
+ * Fabric channel which we want to query.
+ * @type {string}
+ * @memberof GetChainInfoRequestV1
+ */
+ 'channelName': string;
+ /**
+ * Fabric channel we want to connect to. If not provided, then one from channelName parameter will be used
+ * @type {string}
+ * @memberof GetChainInfoRequestV1
+ */
+ 'connectionChannelName'?: string;
+ /**
+ *
+ * @type {GatewayOptions}
+ * @memberof GetChainInfoRequestV1
+ */
+ 'gatewayOptions': GatewayOptions;
+}
+/**
+ * Response from GetChainInfo endpoint.
+ * @export
+ * @interface GetChainInfoResponseV1
+ */
+export interface GetChainInfoResponseV1 {
+ /**
+ * Current height of fabric ledger
+ * @type {number}
+ * @memberof GetChainInfoResponseV1
+ */
+ 'height': number;
+ /**
+ * Current block hash of fabric ledger
+ * @type {string}
+ * @memberof GetChainInfoResponseV1
+ */
+ 'currentBlockHash': string;
+ /**
+ * Previous block hash of fabric ledger
+ * @type {string}
+ * @memberof GetChainInfoResponseV1
+ */
+ 'previousBlockHash': string;
+}
/**
*
* @export
@@ -1258,50 +1593,6 @@ export interface WatchBlocksCactusErrorResponseV1 {
*/
'errorMessage': string;
}
-/**
- * Transaction summary from commited block.
- * @export
- * @interface WatchBlocksCactusTransactionsEventV1
- */
-export interface WatchBlocksCactusTransactionsEventV1 {
- /**
- * ChainCode containing function that was executed.
- * @type {string}
- * @memberof WatchBlocksCactusTransactionsEventV1
- */
- 'chaincodeId': string;
- /**
- * Transaction identifier.
- * @type {string}
- * @memberof WatchBlocksCactusTransactionsEventV1
- */
- 'transactionId': string;
- /**
- * Function name that was executed.
- * @type {string}
- * @memberof WatchBlocksCactusTransactionsEventV1
- */
- 'functionName': string;
- /**
- * List of function arguments.
- * @type {Array}
- * @memberof WatchBlocksCactusTransactionsEventV1
- */
- 'functionArgs': Array;
-}
-/**
- * Custom response containing block transactions summary. Compatible with legacy fabric-socketio connector monitoring.
- * @export
- * @interface WatchBlocksCactusTransactionsResponseV1
- */
-export interface WatchBlocksCactusTransactionsResponseV1 {
- /**
- * List of transactions summary
- * @type {Array}
- * @memberof WatchBlocksCactusTransactionsResponseV1
- */
- 'cactusTransactionsEvents': Array;
-}
/**
* Options passed when subscribing to block monitoring with delegated signing.
* @export
@@ -1374,7 +1665,7 @@ export interface WatchBlocksFullResponseV1 {
'fullBlock': any;
}
/**
- * Response type from WatchBlocks. \'Cactus*\' are custom views, others correspond to fabric SDK call.
+ * Response type from WatchBlocks. \'Cacti*\' are custom views, others correspond to fabric SDK call.
* @export
* @enum {string}
*/
@@ -1383,7 +1674,8 @@ export const WatchBlocksListenerTypeV1 = {
Filtered: 'filtered',
Full: 'full',
Private: 'private',
- CactusTransactions: 'cactus:transactions'
+ CactiTransactions: 'cacti:transactions',
+ CactiFullBlock: 'cacti:full-block'
} as const;
export type WatchBlocksListenerTypeV1 = typeof WatchBlocksListenerTypeV1[keyof typeof WatchBlocksListenerTypeV1];
@@ -1440,7 +1732,7 @@ export interface WatchBlocksPrivateResponseV1 {
* Response block from WatchBlocks endpoint. Depends on \'type\' passed in subscription options.
* @export
*/
-export type WatchBlocksResponseV1 = WatchBlocksCactusErrorResponseV1 | WatchBlocksCactusTransactionsResponseV1 | WatchBlocksFilteredResponseV1 | WatchBlocksFullResponseV1 | WatchBlocksPrivateResponseV1;
+export type WatchBlocksResponseV1 = CactiBlockFullResponseV1 | CactiBlockTransactionsResponseV1 | WatchBlocksCactusErrorResponseV1 | WatchBlocksFilteredResponseV1 | WatchBlocksFullResponseV1 | WatchBlocksPrivateResponseV1;
/**
* Websocket requests for monitoring new blocks.
@@ -1588,6 +1880,40 @@ export const DefaultApiAxiosParamCreator = function (configuration?: Configurati
options: localVarRequestOptions,
};
},
+ /**
+ *
+ * @summary Get fabric ledger chain info.
+ * @param {GetChainInfoRequestV1} [getChainInfoRequestV1]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getChainInfoV1: async (getChainInfoRequestV1?: GetChainInfoRequestV1, options: AxiosRequestConfig = {}): Promise => {
+ const localVarPath = `/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-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(getChainInfoRequestV1, localVarRequestOptions, configuration)
+
+ return {
+ url: toPathString(localVarUrlObj),
+ options: localVarRequestOptions,
+ };
+ },
/**
*
* @summary Get the Prometheus Metrics
@@ -1769,6 +2095,17 @@ export const DefaultApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.getBlockV1(getBlockRequestV1, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
+ /**
+ *
+ * @summary Get fabric ledger chain info.
+ * @param {GetChainInfoRequestV1} [getChainInfoRequestV1]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ async getChainInfoV1(getChainInfoRequestV1?: GetChainInfoRequestV1, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> {
+ const localVarAxiosArgs = await localVarAxiosParamCreator.getChainInfoV1(getChainInfoRequestV1, options);
+ return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
+ },
/**
*
* @summary Get the Prometheus Metrics
@@ -1852,6 +2189,16 @@ export const DefaultApiFactory = function (configuration?: Configuration, basePa
getBlockV1(getBlockRequestV1?: GetBlockRequestV1, options?: any): AxiosPromise {
return localVarFp.getBlockV1(getBlockRequestV1, options).then((request) => request(axios, basePath));
},
+ /**
+ *
+ * @summary Get fabric ledger chain info.
+ * @param {GetChainInfoRequestV1} [getChainInfoRequestV1]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ */
+ getChainInfoV1(getChainInfoRequestV1?: GetChainInfoRequestV1, options?: any): AxiosPromise {
+ return localVarFp.getChainInfoV1(getChainInfoRequestV1, options).then((request) => request(axios, basePath));
+ },
/**
*
* @summary Get the Prometheus Metrics
@@ -1937,6 +2284,18 @@ export class DefaultApi extends BaseAPI {
return DefaultApiFp(this.configuration).getBlockV1(getBlockRequestV1, options).then((request) => request(this.axios, this.basePath));
}
+ /**
+ *
+ * @summary Get fabric ledger chain info.
+ * @param {GetChainInfoRequestV1} [getChainInfoRequestV1]
+ * @param {*} [options] Override http request option.
+ * @throws {RequiredError}
+ * @memberof DefaultApi
+ */
+ public getChainInfoV1(getChainInfoRequestV1?: GetChainInfoRequestV1, options?: AxiosRequestConfig) {
+ return DefaultApiFp(this.configuration).getChainInfoV1(getChainInfoRequestV1, options).then((request) => request(this.axios, this.basePath));
+ }
+
/**
*
* @summary Get the Prometheus Metrics
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/cacti-block-formatters.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/cacti-block-formatters.ts
new file mode 100644
index 0000000000..92c00aba10
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/cacti-block-formatters.ts
@@ -0,0 +1,202 @@
+import { BinaryLike, X509Certificate } from "node:crypto";
+import fabricProtos from "fabric-protos";
+
+import {
+ LoggerProvider,
+ safeStringifyException,
+} from "@hyperledger/cactus-common";
+
+import {
+ CactiBlockFullResponseV1,
+ CactiBlockTransactionEventV1,
+ CactiBlockTransactionsResponseV1,
+ FabricX509CertificateV1,
+ FullBlockTransactionActionV1,
+ FullBlockTransactionEndorsementV1,
+ FullBlockTransactionEventV1,
+} from "../generated/openapi/typescript-axios";
+import { fabricLongToNumber } from "../common/utils";
+
+const level = "INFO";
+const label = "cacti-block-formatters";
+const log = LoggerProvider.getOrCreate({ level, label });
+
+/**
+ * Convert certificate binary received from fabric ledger to object representation.
+ *
+ * @param certBuffer fabric X.509 certificate buffer
+ *
+ * @returns `FabricX509CertificateV1`
+ */
+function parseX509CertToObject(
+ certBuffer: BinaryLike,
+): FabricX509CertificateV1 {
+ const cert = new X509Certificate(certBuffer);
+
+ return {
+ serialNumber: cert.serialNumber,
+ subject: cert.subject,
+ issuer: cert.issuer,
+ subjectAltName: cert.subjectAltName ?? "",
+ validFrom: cert.validFrom,
+ validTo: cert.validTo,
+ pem: cert.toString(),
+ };
+}
+
+/**
+ * Extract full block summary from a fabric. More data can be added here in the future
+ * if there's a need for it.
+ *
+ * @param blockEvent full block event
+ *
+ * @returns parsed block data including transactions, actions, endorsements, signatures.
+ */
+export function formatCactiFullBlockResponse(
+ blockEvent: fabricProtos.common.IBlock,
+): CactiBlockFullResponseV1 {
+ const transactionData = (blockEvent.data?.data ?? []) as any[];
+
+ const header = blockEvent.header;
+ if (!header) {
+ log.warn(
+ "Received block event without a header:",
+ JSON.stringify(blockEvent),
+ );
+ }
+ const blockNumber = header ? fabricLongToNumber(header.number) : -1;
+ const blockHash =
+ "0x" + Buffer.from(blockEvent.header?.data_hash ?? "").toString("hex");
+ const previousBlockHash =
+ "0x" + Buffer.from(blockEvent.header?.previous_hash ?? "").toString("hex");
+ const transactionCount = transactionData.length;
+
+ const transactions: FullBlockTransactionEventV1[] = [];
+ for (const data of transactionData) {
+ try {
+ const payload = data.payload;
+ const channelHeader = payload.header.channel_header;
+ const transaction = payload.data;
+
+ const transactionActions: FullBlockTransactionActionV1[] = [];
+ for (const action of transaction.actions) {
+ const actionPayload = action.payload;
+ const proposalPayload = actionPayload.chaincode_proposal_payload;
+ const invocationSpec = proposalPayload.input;
+ const actionCreatorCert = parseX509CertToObject(
+ action.header.creator.id_bytes,
+ );
+ const actionCreatorMspId = action.header.creator.mspid;
+
+ // Decode args and function name
+ const rawArgs = invocationSpec.chaincode_spec.input.args as Buffer[];
+ const decodedArgs = rawArgs.map((arg: Buffer) => arg.toString("utf8"));
+ const functionName = decodedArgs.shift() ?? "";
+ const chaincodeId = invocationSpec.chaincode_spec.chaincode_id.name;
+
+ const endorsements = actionPayload.action.endorsements.map((e: any) => {
+ return {
+ signer: {
+ mspid: e.endorser.mspid,
+ cert: parseX509CertToObject(e.endorser.id_bytes),
+ },
+ signature: "0x" + Buffer.from(e.signature).toString("hex"),
+ } as FullBlockTransactionEndorsementV1;
+ });
+
+ transactionActions.push({
+ functionName,
+ functionArgs: decodedArgs,
+ chaincodeId,
+ creator: {
+ mspid: actionCreatorMspId,
+ cert: actionCreatorCert,
+ },
+ endorsements,
+ });
+ }
+
+ transactions.push({
+ hash: channelHeader.tx_id,
+ channelId: channelHeader.channel_id,
+ timestamp: channelHeader.timestamp,
+ protocolVersion: channelHeader.version,
+ transactionType: channelHeader.typeString,
+ epoch: fabricLongToNumber(channelHeader.epoch),
+ actions: transactionActions,
+ });
+ } catch (error) {
+ log.warn(
+ "Could not retrieve transaction from received block. Error:",
+ safeStringifyException(error),
+ );
+ }
+ }
+
+ return {
+ cactiFullEvents: {
+ blockNumber,
+ blockHash,
+ previousBlockHash,
+ transactionCount,
+ cactiTransactionsEvents: transactions,
+ },
+ };
+}
+
+/**
+ * Extract transaction summary from a fabric block.
+ *
+ * @param blockEvent full block event
+ *
+ * @returns actions summary, including function name, args, and chaincode.
+ */
+export function formatCactiTransactionsBlockResponse(
+ blockEvent: fabricProtos.common.IBlock,
+): CactiBlockTransactionsResponseV1 {
+ const transactionData = blockEvent.data?.data as any[];
+ if (!transactionData) {
+ log.debug("Block transaction data empty - ignore...");
+ return {
+ cactiTransactionsEvents: [],
+ };
+ }
+
+ const transactions: CactiBlockTransactionEventV1[] = [];
+ for (const data of transactionData) {
+ try {
+ const payload = data.payload;
+ const transaction = payload.data;
+ for (const action of transaction.actions) {
+ const actionPayload = action.payload;
+ const proposalPayload = actionPayload.chaincode_proposal_payload;
+ const invocationSpec = proposalPayload.input;
+
+ // Decode args and function name
+ const rawArgs = invocationSpec.chaincode_spec.input.args as Buffer[];
+ const decodedArgs = rawArgs.map((arg: Buffer) => arg.toString("utf8"));
+ const functionName = decodedArgs.shift() ?? "";
+
+ const chaincodeId = invocationSpec.chaincode_spec.chaincode_id.name;
+ const channelHeader = payload.header.channel_header;
+ const transactionId = channelHeader.tx_id;
+
+ transactions.push({
+ chaincodeId,
+ transactionId,
+ functionName,
+ functionArgs: decodedArgs,
+ });
+ }
+ } catch (error) {
+ log.warn(
+ "Could not retrieve transaction from received block. Error:",
+ safeStringifyException(error),
+ );
+ }
+ }
+
+ return {
+ cactiTransactionsEvents: transactions,
+ };
+}
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/get-block-endpoint-v1.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/get-block-endpoint-v1.ts
index 763ed05573..b9399d5f51 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/get-block-endpoint-v1.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-block/get-block-endpoint-v1.ts
@@ -6,7 +6,6 @@ import {
LogLevelDesc,
Checks,
IAsyncProvider,
- safeStringifyException,
} from "@hyperledger/cactus-common";
import {
@@ -15,7 +14,10 @@ import {
IEndpointAuthzOptions,
} from "@hyperledger/cactus-core-api";
-import { registerWebServiceEndpoint } from "@hyperledger/cactus-core";
+import {
+ handleRestEndpointException,
+ registerWebServiceEndpoint,
+} from "@hyperledger/cactus-core";
import { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
import OAS from "../../json/openapi.json";
@@ -88,11 +90,8 @@ export class GetBlockEndpointV1 implements IWebServiceEndpoint {
try {
res.status(200).send(await this.opts.connector.getBlock(req.body));
} catch (error) {
- this.log.error(`Crash while serving ${fnTag}`, error);
- res.status(500).json({
- message: "Internal Server Error",
- error: safeStringifyException(error),
- });
+ const errorMsg = `Crash while serving ${fnTag}`;
+ handleRestEndpointException({ errorMsg, log: this.log, error, res });
}
}
}
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-chain-info/get-chain-info-endpoint-v1.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-chain-info/get-chain-info-endpoint-v1.ts
new file mode 100644
index 0000000000..122439dde9
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/get-chain-info/get-chain-info-endpoint-v1.ts
@@ -0,0 +1,97 @@
+import { 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 { PluginLedgerConnectorFabric } from "../plugin-ledger-connector-fabric";
+import OAS from "../../json/openapi.json";
+
+export interface IGetChainInfoEndpointV1Options {
+ logLevel?: LogLevelDesc;
+ connector: PluginLedgerConnectorFabric;
+}
+
+export class GetChainInfoEndpointV1 implements IWebServiceEndpoint {
+ private readonly log: Logger;
+
+ constructor(public readonly opts: IGetChainInfoEndpointV1Options) {
+ const fnTag = "GetChainInfoEndpointV1#constructor()";
+
+ Checks.truthy(opts, `${fnTag} options`);
+ Checks.truthy(opts.connector, `${fnTag} options.connector`);
+
+ this.log = LoggerProvider.getOrCreate({
+ label: "get-chain-info-endpoint-v1",
+ level: opts.logLevel || "INFO",
+ });
+ }
+
+ 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 getOasPath(): (typeof OAS.paths)["/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info"] {
+ return OAS.paths[
+ "/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-chain-info"
+ ];
+ }
+
+ public getPath(): string {
+ const apiPath = this.getOasPath();
+ return apiPath.post["x-hyperledger-cacti"].http.path;
+ }
+
+ public getVerbLowerCase(): string {
+ const apiPath = this.getOasPath();
+ return apiPath.post["x-hyperledger-cacti"].http.verbLowerCase;
+ }
+
+ public getOperationId(): string {
+ return this.getOasPath().post.operationId;
+ }
+
+ public async registerExpress(
+ expressApp: Express,
+ ): Promise {
+ await registerWebServiceEndpoint(expressApp, this);
+ return this;
+ }
+
+ async handleRequest(req: Request, res: Response): Promise {
+ const fnTag = "GetChainInfoEndpointV1#handleRequest()";
+ this.log.debug(`POST ${this.getPath()}`);
+
+ try {
+ res.status(200).send(await this.opts.connector.getChainInfo(req.body));
+ } catch (error) {
+ const errorMsg = `Crash while serving ${fnTag}`;
+ handleRestEndpointException({ errorMsg, log: this.log, error, res });
+ }
+ }
+}
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts
index 6302c3ad85..b0f2fe0c07 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/plugin-ledger-connector-fabric.ts
@@ -35,6 +35,9 @@ import {
Endorser,
ICryptoKey,
} from "fabric-common";
+// BlockDecoder is not exported in ts definition so we need to use legacy import.
+const { BlockDecoder } = require("fabric-common");
+import fabricProtos from "fabric-protos";
import {
ConsensusAlgorithmFamily,
@@ -95,12 +98,15 @@ import {
GetTransactionReceiptResponse,
GatewayOptions,
GetBlockRequestV1,
- GetBlockResponseV1,
WatchBlocksV1,
WatchBlocksOptionsV1,
RunDelegatedSignTransactionRequest,
RunTransactionResponseType,
WatchBlocksDelegatedSignOptionsV1,
+ GetBlockResponseTypeV1,
+ GetBlockResponseV1,
+ GetChainInfoRequestV1,
+ GetChainInfoResponseV1,
} from "./generated/openapi/typescript-axios/index";
import {
@@ -137,10 +143,19 @@ import {
getTransactionReceiptByTxID,
IGetTransactionReceiptByTxIDOptions,
} from "./common/get-transaction-receipt-by-tx-id";
+import {
+ formatCactiFullBlockResponse,
+ formatCactiTransactionsBlockResponse,
+} from "./get-block/cacti-block-formatters";
import { GetBlockEndpointV1 } from "./get-block/get-block-endpoint-v1";
+import { GetChainInfoEndpointV1 } from "./get-chain-info/get-chain-info-endpoint-v1";
import { querySystemChainCode } from "./common/query-system-chain-code";
import { isSshExecOk } from "./common/is-ssh-exec-ok";
-import { asBuffer, assertFabricFunctionIsAvailable } from "./common/utils";
+import {
+ asBuffer,
+ assertFabricFunctionIsAvailable,
+ fabricLongToNumber,
+} from "./common/utils";
import { findAndReplaceFabricLoggingSpec } from "./common/find-and-replace-fabric-logging-spec";
import { deployContractGoSourceImplFabricV256 } from "./deploy-contract-go-source/deploy-contract-go-source-impl-fabric-v2-5-6";
@@ -836,6 +851,14 @@ export class PluginLedgerConnectorFabric
endpoints.push(endpoint);
}
+ {
+ const endpoint = new GetChainInfoEndpointV1({
+ connector: this,
+ logLevel: this.opts.logLevel,
+ });
+ endpoints.push(endpoint);
+ }
+
{
const opts: IGetPrometheusExporterMetricsEndpointV1Options = {
connector: this,
@@ -1506,15 +1529,14 @@ export class PluginLedgerConnectorFabric
);
const gateway = await this.createGatewayWithOptions(req.gatewayOptions);
- const { channelName, skipDecode } = req;
+ const { channelName, responseType } = req;
const connectionChannelName = req.connectionChannelName ?? channelName;
const queryConfig = {
gateway,
connectionChannelName,
- skipDecode,
};
- let responseData: unknown;
+ let responseData: Buffer;
if (req.query.blockNumber) {
this.log.debug("getBlock by it's blockNumber:", req.query.blockNumber);
responseData = await querySystemChainCode(
@@ -1554,25 +1576,69 @@ export class PluginLedgerConnectorFabric
);
}
- this.log.debug("responseData:", responseData);
if (!responseData) {
const eMsg = `${fnTag} - expected string as GetBlockByTxID response from Fabric system chaincode but received a falsy value instead...`;
throw new RuntimeError(eMsg);
}
- if (skipDecode) {
- if (!(responseData instanceof Buffer)) {
- const eMsg = `${fnTag} - expected Buffer as GetBlockByTxID response from Fabric system chaincode but received ${typeof responseData} instead...`;
- throw new RuntimeError(eMsg);
- }
+ if (responseType === GetBlockResponseTypeV1.Encoded) {
const encodedBlockB64 = responseData.toString("base64");
return {
encodedBlock: encodedBlockB64,
};
}
+ const decodedBlock = BlockDecoder.decode(responseData);
+ switch (responseType) {
+ case GetBlockResponseTypeV1.CactiTransactions:
+ return formatCactiTransactionsBlockResponse(decodedBlock);
+ case GetBlockResponseTypeV1.CactiFullBlock:
+ return formatCactiFullBlockResponse(decodedBlock);
+ case GetBlockResponseTypeV1.Full:
+ default:
+ return {
+ decodedBlock,
+ };
+ }
+ }
+
+ /**
+ * Get fabric block from a channel, using one of selectors.
+ *
+ * @param req input parameters
+ * @returns Entire block object or encoded buffer (if req.skipDecode is true)
+ */
+ public async getChainInfo(
+ req: GetChainInfoRequestV1,
+ ): Promise {
+ const { channelName } = req;
+ this.log.debug("getChainInfo() called, channelName:", channelName);
+
+ const gateway = await this.createGatewayWithOptions(req.gatewayOptions);
+ const connectionChannelName = req.connectionChannelName ?? channelName;
+ const queryConfig = {
+ gateway,
+ connectionChannelName,
+ };
+
+ const responseData = await querySystemChainCode(
+ queryConfig,
+ "GetChainInfo",
+ channelName,
+ );
+
+ const decodedResponse =
+ fabricProtos.common.BlockchainInfo.decode(responseData);
+ if (!decodedResponse) {
+ throw new RuntimeError("Could not decode BlockchainInfo");
+ }
+
return {
- decodedBlock: responseData,
+ height: fabricLongToNumber(decodedResponse.height),
+ currentBlockHash:
+ "0x" + Buffer.from(decodedResponse.currentBlockHash).toString("hex"),
+ previousBlockHash:
+ "0x" + Buffer.from(decodedResponse.previousBlockHash).toString("hex"),
};
}
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/watch-blocks/watch-blocks-v1-endpoint.ts b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/watch-blocks/watch-blocks-v1-endpoint.ts
index a5dea07ddc..4e22246cc3 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/watch-blocks/watch-blocks-v1-endpoint.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/watch-blocks/watch-blocks-v1-endpoint.ts
@@ -25,9 +25,12 @@ import {
WatchBlocksResponseV1,
WatchBlocksListenerTypeV1,
WatchBlocksOptionsV1,
- WatchBlocksCactusTransactionsEventV1,
WatchBlocksDelegatedSignOptionsV1,
} from "../generated/openapi/typescript-axios";
+import {
+ formatCactiFullBlockResponse,
+ formatCactiTransactionsBlockResponse,
+} from "../get-block/cacti-block-formatters";
const {
newFilteredBlockEvent,
@@ -82,66 +85,53 @@ export class WatchBlocksV1Endpoint {
}
/**
- * Callback executed when receiving block with custom cactus type "cactus:transactions"
+ * Callback executed when receiving block with custom cacti type "cacti:full-block"
* Sends WatchBlocksV1.Next with new block to the client.
*
* @param blockEvent full block
*
* @returns Nothing.
*/
- private monitorCactusTransactionsCallback(blockEvent: BlockEvent) {
+ private monitorCactiFullBlockCallback(blockEvent: BlockEvent) {
const { socket, log } = this;
const clientId = socket.id;
log.debug(
- `CactusTransactions BlockEvent received: #${blockEvent.blockNumber.toString()}, client: ${clientId}`,
+ `CactiFullBlock BlockEvent received: #${blockEvent.blockNumber.toString()}, client: ${clientId}`,
);
if (!("data" in blockEvent.blockData)) {
- log.error("Wrong blockEvent type received - should not happen!");
- return;
+ throw new Error("Wrong blockEvent type received - should not happen!");
}
- const blockData = blockEvent.blockData.data?.data as any;
- if (!blockData) {
- log.debug("Block data empty - ignore...");
- return;
- }
+ socket.emit(
+ WatchBlocksV1.Next,
+ formatCactiFullBlockResponse(blockEvent.blockData),
+ );
+ }
- const transactions: WatchBlocksCactusTransactionsEventV1[] = [];
- for (const data of blockData) {
- try {
- const payload = data.payload;
- const transaction = payload.data;
- const actionPayload = transaction.actions[0].payload;
- const proposalPayload = actionPayload.chaincode_proposal_payload;
- const invocationSpec = proposalPayload.input;
-
- // Decode args and function name
- const rawArgs = invocationSpec.chaincode_spec.input.args as Buffer[];
- const decodedArgs = rawArgs.map((arg: Buffer) => arg.toString("utf8"));
- const functionName = decodedArgs.shift() ?? "";
-
- const chaincodeId = invocationSpec.chaincode_spec.chaincode_id.name;
- const channelHeader = payload.header.channel_header;
- const transactionId = channelHeader.tx_id;
-
- transactions.push({
- chaincodeId,
- transactionId,
- functionName,
- functionArgs: decodedArgs,
- });
- } catch (error) {
- log.warn(
- "Could not retrieve transaction from received block. Error:",
- safeStringifyException(error),
- );
- }
+ /**
+ * Callback executed when receiving block with custom cacti type "cacti:transactions"
+ * Sends WatchBlocksV1.Next with new block to the client.
+ *
+ * @param blockEvent full block
+ *
+ * @returns Nothing.
+ */
+ private monitorCactiTransactionsCallback(blockEvent: BlockEvent) {
+ const { socket, log } = this;
+ const clientId = socket.id;
+ log.debug(
+ `CactiTransactions BlockEvent received: #${blockEvent.blockNumber.toString()}, client: ${clientId}`,
+ );
+
+ if (!("data" in blockEvent.blockData)) {
+ throw new Error("Wrong blockEvent type received - should not happen!");
}
- socket.emit(WatchBlocksV1.Next, {
- cactusTransactionsEvents: transactions,
- });
+ socket.emit(
+ WatchBlocksV1.Next,
+ formatCactiTransactionsBlockResponse(blockEvent.blockData),
+ );
}
/**
@@ -223,7 +213,7 @@ export class WatchBlocksV1Endpoint {
* Get block listener callback and listener type it's expect.
* Returns separate function object each time it's called (this is required y fabric node SDK).
*
- * @param type requested listener type (including custom Cactus ones).
+ * @param type requested listener type (including custom Cacti ones).
*
* @returns listener: BlockListener;
* @returns listenerType: BlockType;
@@ -247,11 +237,17 @@ export class WatchBlocksV1Endpoint {
this.monitorPrivateCallback(blockEvent);
listenerType = "private";
break;
- case WatchBlocksListenerTypeV1.CactusTransactions:
+ case WatchBlocksListenerTypeV1.CactiTransactions:
listener = async (blockEvent) =>
- this.monitorCactusTransactionsCallback(blockEvent);
+ this.monitorCactiTransactionsCallback(blockEvent);
listenerType = "full";
break;
+ case WatchBlocksListenerTypeV1.CactiFullBlock:
+ listener = async (blockEvent) =>
+ this.monitorCactiFullBlockCallback(blockEvent);
+ listenerType = "full";
+ break;
+
default:
// Will not compile if any type was not handled by above switch.
const unknownType: never = type;
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/delegate-signing-methods.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/delegate-signing-methods.test.ts
index c6964fccd1..3b995767f2 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/delegate-signing-methods.test.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/delegate-signing-methods.test.ts
@@ -59,8 +59,8 @@ import {
FabricApiClient,
signProposal,
WatchBlocksListenerTypeV1,
- WatchBlocksCactusTransactionsResponseV1,
FabricSigningCredential,
+ CactiBlockTransactionsResponseV1,
} from "../../../../main/typescript/public-api";
import { Observable } from "rxjs";
@@ -296,11 +296,11 @@ describe("Delegated signing tests", () => {
const committedTx = await apiClient.waitForTransactionCommit(
txId,
apiClient.watchBlocksDelegatedSignV1({
- type: WatchBlocksListenerTypeV1.CactusTransactions,
+ type: WatchBlocksListenerTypeV1.CactiTransactions,
signerCertificate: adminIdentity.credentials.certificate,
signerMspID: adminIdentity.mspId,
channelName: ledgerChannelName,
- }) as Observable,
+ }) as Observable,
);
mockSignCallback.mockClear();
return committedTx;
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-delegated-sign-v1-endpoint.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-delegated-sign-v1-endpoint.test.ts
index d45b2c2fa9..bcbca461c2 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-delegated-sign-v1-endpoint.test.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-delegated-sign-v1-endpoint.test.ts
@@ -386,22 +386,22 @@ describe("watchBlocksDelegatedSignV1 of fabric connector tests", () => {
});
/**
- * Check Cactus custom transactions summary block monitoring.
+ * Check Cacti custom transactions summary block monitoring.
*/
- test("Monitoring with type CactusTransactions returns transactions summary", async () => {
+ test("Monitoring with type CactiTransactions returns transactions summary", async () => {
const monitorPromise = testWatchBlock(
- "CactusTransactionsTest",
- WatchBlocksListenerTypeV1.CactusTransactions,
+ "CactiTransactionsTest",
+ WatchBlocksListenerTypeV1.CactiTransactions,
(event) => {
expect(event).toBeTruthy();
- if (!("cactusTransactionsEvents" in event)) {
+ if (!("cactiTransactionsEvents" in event)) {
throw new Error(
`Unexpected response from the connector: ${JSON.stringify(event)}`,
);
}
- const eventData = event.cactusTransactionsEvents;
+ const eventData = event.cactiTransactionsEvents;
expect(eventData.length).toBeGreaterThan(0);
expect(eventData[0].chaincodeId).toBeTruthy();
expect(eventData[0].transactionId).toBeTruthy();
@@ -413,9 +413,66 @@ describe("watchBlocksDelegatedSignV1 of fabric connector tests", () => {
await monitorPromise;
});
+ /**
+ * Check Cacti custom full block summary block monitoring.
+ */
+ test("Monitoring with type CactiFullBlock returns block summary", async () => {
+ const monitorPromise = testWatchBlock(
+ "CactiFullBlockTest",
+ WatchBlocksListenerTypeV1.CactiFullBlock,
+ (event) => {
+ expect(event).toBeTruthy();
+
+ if (!("cactiFullEvents" in event)) {
+ throw new Error(
+ `Unexpected response from the connector: ${JSON.stringify(event)}`,
+ );
+ }
+
+ const cactiFullBlock = event.cactiFullEvents;
+
+ // Check block fields
+ expect(cactiFullBlock).toBeTruthy();
+ expect(cactiFullBlock.blockNumber).toBeDefined();
+ expect(cactiFullBlock.blockHash).toBeTruthy();
+ expect(cactiFullBlock.previousBlockHash).toBeTruthy();
+ expect(cactiFullBlock.transactionCount).toBeDefined();
+
+ // Check transaction fields
+ for (const tx of cactiFullBlock.cactiTransactionsEvents) {
+ expect(tx.hash).toBeTruthy();
+ expect(tx.channelId).toBeTruthy();
+ expect(tx.timestamp).toBeTruthy();
+ expect(tx.transactionType).toBeTruthy();
+ expect(tx.protocolVersion).not.toBeUndefined();
+ expect(tx.epoch).not.toBeUndefined();
+
+ // Check transaction actions fields
+ for (const action of tx.actions) {
+ expect(action.functionName).toBeTruthy();
+ expect(action.functionArgs).toBeTruthy();
+ expect(action.functionArgs.length).toEqual(5);
+ expect(action.chaincodeId).toBeTruthy();
+ expect(action.creator.mspid).toBeTruthy();
+ expect(action.creator.cert).toBeTruthy();
+
+ // Check transaction action endorsement fields
+ for (const endorsement of action.endorsements) {
+ expect(endorsement.signature).toBeTruthy();
+ expect(endorsement.signer.mspid).toBeTruthy();
+ expect(endorsement.signer.cert).toBeTruthy();
+ }
+ }
+ }
+ },
+ );
+
+ await monitorPromise;
+ });
+
test("Invalid WatchBlocksListenerTypeV1 value gets knocked down", async () => {
const monitorPromise = testWatchBlock(
- "CactusTransactionsTest",
+ "InvalidTypeTest",
"Some_INVALID_WatchBlocksListenerTypeV1" as WatchBlocksListenerTypeV1,
() => undefined, // will never reach this because it is meant to error out
false,
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-v1-endpoint.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-v1-endpoint.test.ts
index 1b85a6930b..f2f5a66799 100644
--- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-v1-endpoint.test.ts
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-v1-endpoint.test.ts
@@ -60,8 +60,8 @@ const ledgerChannelName = "mychannel";
const ledgerContractName = "basic";
// Log settings
-const testLogLevel: LogLevelDesc = "TRACE"; // default: info
-const sutLogLevel: LogLevelDesc = "TRACE"; // default: info
+const testLogLevel: LogLevelDesc = "info"; // default: info
+const sutLogLevel: LogLevelDesc = "info"; // default: info
// Logger setup
const log: Logger = LoggerProvider.getOrCreate({
@@ -384,22 +384,22 @@ describe("watchBlocksV1 of fabric connector tests", () => {
});
/**
- * Check Cactus custom transactions summary block monitoring.
+ * Check Cacti custom transactions summary block monitoring.
*/
- test("Monitoring with type CactusTransactions returns transactions summary", async () => {
+ test("Monitoring with type CactiTransactions returns transactions summary", async () => {
const monitorPromise = testWatchBlock(
- "CactusTransactionsTest",
- WatchBlocksListenerTypeV1.CactusTransactions,
+ "CactiTransactionsTest",
+ WatchBlocksListenerTypeV1.CactiTransactions,
(event) => {
expect(event).toBeTruthy();
- if (!("cactusTransactionsEvents" in event)) {
+ if (!("cactiTransactionsEvents" in event)) {
throw new Error(
`Unexpected response from the connector: ${JSON.stringify(event)}`,
);
}
- const eventData = event.cactusTransactionsEvents;
+ const eventData = event.cactiTransactionsEvents;
expect(eventData.length).toBeGreaterThan(0);
expect(eventData[0].chaincodeId).toBeTruthy();
expect(eventData[0].transactionId).toBeTruthy();
@@ -411,9 +411,66 @@ describe("watchBlocksV1 of fabric connector tests", () => {
await monitorPromise;
});
+ /**
+ * Check Cacti custom full block summary block monitoring.
+ */
+ test("Monitoring with type CactiFullBlock returns block summary", async () => {
+ const monitorPromise = testWatchBlock(
+ "CactiFullBlockTest",
+ WatchBlocksListenerTypeV1.CactiFullBlock,
+ (event) => {
+ expect(event).toBeTruthy();
+
+ if (!("cactiFullEvents" in event)) {
+ throw new Error(
+ `Unexpected response from the connector: ${JSON.stringify(event)}`,
+ );
+ }
+
+ const cactiFullBlock = event.cactiFullEvents;
+
+ // Check block fields
+ expect(cactiFullBlock).toBeTruthy();
+ expect(cactiFullBlock.blockNumber).toBeDefined();
+ expect(cactiFullBlock.blockHash).toBeTruthy();
+ expect(cactiFullBlock.previousBlockHash).toBeTruthy();
+ expect(cactiFullBlock.transactionCount).toBeDefined();
+
+ // Check transaction fields
+ for (const tx of cactiFullBlock.cactiTransactionsEvents) {
+ expect(tx.hash).toBeTruthy();
+ expect(tx.channelId).toBeTruthy();
+ expect(tx.timestamp).toBeTruthy();
+ expect(tx.transactionType).toBeTruthy();
+ expect(tx.protocolVersion).not.toBeUndefined();
+ expect(tx.epoch).not.toBeUndefined();
+
+ // Check transaction actions fields
+ for (const action of tx.actions) {
+ expect(action.functionName).toBeTruthy();
+ expect(action.functionArgs).toBeTruthy();
+ expect(action.functionArgs.length).toEqual(5);
+ expect(action.chaincodeId).toBeTruthy();
+ expect(action.creator.mspid).toBeTruthy();
+ expect(action.creator.cert).toBeTruthy();
+
+ // Check transaction action endorsement fields
+ for (const endorsement of action.endorsements) {
+ expect(endorsement.signature).toBeTruthy();
+ expect(endorsement.signer.mspid).toBeTruthy();
+ expect(endorsement.signer.cert).toBeTruthy();
+ }
+ }
+ }
+ },
+ );
+
+ await monitorPromise;
+ });
+
test("Invalid WatchBlocksListenerTypeV1 value gets knocked down", async () => {
const monitorPromise = testWatchBlock(
- "CactusTransactionsTest",
+ "CactiInvalidTest",
"Some_INVALID_WatchBlocksListenerTypeV1" as WatchBlocksListenerTypeV1,
() => undefined, // will never reach this because it is meant to error out
false,
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/get-block.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/get-block.test.ts
deleted file mode 100644
index 37fbdbec51..0000000000
--- a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/get-block.test.ts
+++ /dev/null
@@ -1,431 +0,0 @@
-import "jest-extended";
-import http from "http";
-import { AddressInfo } from "net";
-import { v4 as uuidv4 } from "uuid";
-import bodyParser from "body-parser";
-import express from "express";
-import { DiscoveryOptions } from "fabric-network";
-// BlockDecoder is not exported in ts definition so we need to use legacy import.
-const { BlockDecoder } = require("fabric-common");
-
-import {
- DEFAULT_FABRIC_2_AIO_IMAGE_NAME,
- FABRIC_25_LTS_AIO_FABRIC_VERSION,
- FABRIC_25_LTS_AIO_IMAGE_VERSION,
- FabricTestLedgerV1,
- pruneDockerAllIfGithubAction,
-} from "@hyperledger/cactus-test-tooling";
-
-import {
- LogLevelDesc,
- LoggerProvider,
- Logger,
- IListenOptions,
- Servers,
-} from "@hyperledger/cactus-common";
-
-import { Configuration } from "@hyperledger/cactus-core-api";
-
-import { PluginRegistry } from "@hyperledger/cactus-core";
-
-import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory";
-
-import {
- PluginLedgerConnectorFabric,
- DefaultEventHandlerStrategy,
- DefaultApi as FabricApi,
- GatewayOptions,
- GetBlockRequestV1,
- FabricContractInvocationType,
- FabricSigningCredential,
-} from "../../../../main/typescript/public-api";
-
-/**
- * Functional test of GetBlockEndpointV1 on connector-fabric (packages/cactus-plugin-ledger-connector-fabric)
- * Assumes sample CC was already deployed on the test ledger.
- */
-
-//////////////////////////////////
-// Constants
-//////////////////////////////////
-
-// Ledger settings
-const imageName = DEFAULT_FABRIC_2_AIO_IMAGE_NAME;
-const imageVersion = FABRIC_25_LTS_AIO_IMAGE_VERSION;
-const fabricEnvVersion = FABRIC_25_LTS_AIO_FABRIC_VERSION;
-const fabricEnvCAVersion = "1.4.9";
-const ledgerChannelName = "mychannel";
-const ledgerContractName = "basic";
-
-// Log settings
-const testLogLevel: LogLevelDesc = "debug"; // default: info
-const sutLogLevel: LogLevelDesc = "debug"; // default: info
-
-// Logger setup
-const log: Logger = LoggerProvider.getOrCreate({
- label: "get-block.test",
- level: testLogLevel,
-});
-
-/**
- * Main test suite
- */
-describe("Get Block endpoint tests", () => {
- let ledger: FabricTestLedgerV1;
- let gatewayOptions: GatewayOptions;
- let fabricConnectorPlugin: PluginLedgerConnectorFabric;
- let connectorServer: http.Server;
- let apiClient: FabricApi;
-
- //////////////////////////////////
- // Environment Setup
- //////////////////////////////////
-
- beforeAll(async () => {
- log.info("Prune Docker...");
- await pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
-
- // Start Ledger
- log.info("Start FabricTestLedgerV1...");
- log.debug("Version:", fabricEnvVersion, "CA Version:", fabricEnvCAVersion);
- ledger = new FabricTestLedgerV1({
- emitContainerLogs: false,
- publishAllPorts: true,
- logLevel: testLogLevel,
- imageName,
- imageVersion,
- envVars: new Map([
- ["FABRIC_VERSION", fabricEnvVersion],
- ["CA_VERSION", fabricEnvCAVersion],
- ]),
- });
- log.debug("Fabric image:", ledger.getContainerImageName());
- await ledger.start({ omitPull: false });
-
- // Get connection profile
- log.info("Get fabric connection profile for Org1...");
- const connectionProfile = await ledger.getConnectionProfileOrg1();
- expect(connectionProfile).toBeTruthy();
-
- // Enroll admin and user
- const enrollAdminOut = await ledger.enrollAdmin();
- const adminWallet = enrollAdminOut[1];
- const [userIdentity] = await ledger.enrollUser(adminWallet);
-
- // Create Keychain Plugin
- const keychainId = uuidv4();
- const keychainEntryKey = "user2";
- const keychainPlugin = new PluginKeychainMemory({
- instanceId: uuidv4(),
- keychainId,
- logLevel: sutLogLevel,
- backend: new Map([[keychainEntryKey, JSON.stringify(userIdentity)]]),
- });
-
- gatewayOptions = {
- identity: keychainEntryKey,
- wallet: {
- keychain: {
- keychainId,
- keychainRef: keychainEntryKey,
- },
- },
- };
-
- // Create Connector Plugin
- const discoveryOptions: DiscoveryOptions = {
- enabled: true,
- asLocalhost: true,
- };
- fabricConnectorPlugin = new PluginLedgerConnectorFabric({
- instanceId: uuidv4(),
- pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }),
- sshConfig: await ledger.getSshConfig(),
- cliContainerEnv: {},
- peerBinary: "/fabric-samples/bin/peer",
- logLevel: sutLogLevel,
- connectionProfile,
- discoveryOptions,
- eventHandlerOptions: {
- strategy: DefaultEventHandlerStrategy.NetworkScopeAnyfortx,
- commitTimeout: 300,
- },
- });
-
- // Run http server
- const expressApp = express();
- expressApp.use(bodyParser.json({ limit: "250mb" }));
- connectorServer = http.createServer(expressApp);
- const listenOptions: IListenOptions = {
- hostname: "127.0.0.1",
- port: 0,
- server: connectorServer,
- };
- const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo;
- const apiHost = `http://${addressInfo.address}:${addressInfo.port}`;
-
- // Register services
- await fabricConnectorPlugin.getOrCreateWebServices();
- await fabricConnectorPlugin.registerWebServices(expressApp);
-
- // Create ApiClient
- const apiConfig = new Configuration({ basePath: apiHost });
- apiClient = new FabricApi(apiConfig);
- });
-
- afterAll(async () => {
- log.info("FINISHING THE TESTS");
-
- if (fabricConnectorPlugin) {
- log.info("Close ApiClient connections...");
- fabricConnectorPlugin.shutdown();
- }
-
- if (connectorServer) {
- log.info("Stop the HTTP server connector...");
- await new Promise((resolve) =>
- connectorServer.close(() => resolve()),
- );
- }
-
- if (ledger) {
- log.info("Stop the fabric ledger...");
- await ledger.stop();
- await ledger.destroy();
- }
-
- log.info("Prune Docker...");
- await pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
- });
-
- //////////////////////////////////
- // Helpers
- //////////////////////////////////
-
- /**
- * Run get block endpoint using block number, do basic response checks.
- * Can be reused throughout the tests.
- *
- * @param blockNumber string number of the block
- * @param skipDecode true to return encoded, false to return decoded
- * @returns block object / block buffer
- */
- async function getBlockByNumber(
- blockNumber = "0",
- skipDecode = false,
- ): Promise {
- const getBlockReq = {
- channelName: ledgerChannelName,
- gatewayOptions,
- query: {
- blockNumber,
- },
- skipDecode,
- };
-
- const getBlockResponse = await apiClient.getBlockV1(getBlockReq);
- log.debug("getBlockResponse=%o", getBlockResponse);
-
- expect(getBlockResponse).toBeTruthy();
- expect(getBlockResponse.status).toEqual(200);
- expect(getBlockResponse.data).toBeTruthy();
-
- if (!skipDecode) {
- // Decoded check
- if (!("decodedBlock" in getBlockResponse.data)) {
- throw new Error(
- "Wrong response received - expected decoded, received encoded.",
- );
- }
- expect(getBlockResponse.data.decodedBlock).toBeTruthy();
- return getBlockResponse.data.decodedBlock;
- } else {
- // Encoded check
- if (!("encodedBlock" in getBlockResponse.data)) {
- throw new Error(
- "Wrong response received - expected encoded, received decoded.",
- );
- }
- expect(getBlockResponse.data.encodedBlock).toBeTruthy();
- return getBlockResponse.data.encodedBlock;
- }
- }
-
- /**
- * Create new asset on the ledger to trigger new transaction creation.
- *
- * @param assetName unique asset name to create
- * @returns committed transaction id.
- */
- async function sendTransactionOnFabric(assetName: string) {
- const createAssetResponse = await apiClient.runTransactionV1({
- signingCredential: gatewayOptions.wallet
- .keychain as FabricSigningCredential,
- channelName: ledgerChannelName,
- invocationType: FabricContractInvocationType.Send,
- contractName: ledgerContractName,
- methodName: "CreateAsset",
- params: [assetName, "green", "111", "someOwner", "299"],
- });
- expect(createAssetResponse).toBeTruthy();
- expect(createAssetResponse.status).toEqual(200);
- expect(createAssetResponse.data).toBeTruthy();
- const txId = createAssetResponse.data.transactionId;
- expect(txId).toBeTruthy();
-
- log.debug("Crated new transaction, txId:", txId);
- return txId;
- }
-
- //////////////////////////////////
- // Tests
- //////////////////////////////////
-
- /**
- * GetBlock endpoint using block number
- */
- test("Get first block by it's number - decoded.", async () => {
- // Check decoded
- const decodedFirstBlock = await getBlockByNumber("0", false);
- log.debug("Received decodedFirstBlock:", decodedFirstBlock);
- expect(decodedFirstBlock.header).toBeTruthy();
- expect(decodedFirstBlock.header.number.low).toBe(0);
- expect(decodedFirstBlock.header.number.high).toBe(0);
- expect(decodedFirstBlock.data).toBeTruthy();
- expect(decodedFirstBlock.metadata).toBeTruthy();
- });
-
- test("Get first block by it's number - encoded.", async () => {
- // Check decoded
- const encodedFirstBlock = await getBlockByNumber("0", true);
- const decodedFirstBlockBuffer = Buffer.from(encodedFirstBlock, "base64");
- const decodedFirstBlock = BlockDecoder.decode(decodedFirstBlockBuffer);
- log.debug("Received decodedFirstBlock:", decodedFirstBlock);
- expect(decodedFirstBlock.header).toBeTruthy();
- expect(decodedFirstBlock.header.number.low).toBe(0);
- expect(decodedFirstBlock.header.number.high).toBe(0);
- expect(decodedFirstBlock.data).toBeTruthy();
- expect(decodedFirstBlock.metadata).toBeTruthy();
- });
-
- /**
- * GetBlock endpoint using transactionId
- */
- test("Get a block by transactionId it contains", async () => {
- // Run some transaction
- const txId = await sendTransactionOnFabric("getBlockTx");
-
- // Get block using transactionId we've just sent
- const getBlockByTxId = {
- channelName: ledgerChannelName,
- gatewayOptions,
- query: {
- transactionId: txId,
- },
- };
-
- const getBlockResponse = await apiClient.getBlockV1(getBlockByTxId);
- if (!("decodedBlock" in getBlockResponse.data)) {
- // narrow the type
- throw new Error(
- "Wrong response received - expected decoded, received encoded.",
- );
- }
- const { decodedBlock } = getBlockResponse.data;
- expect(decodedBlock).toBeTruthy();
- expect(decodedBlock.header).toBeTruthy();
- expect(decodedBlock.data).toBeTruthy();
- expect(decodedBlock.metadata).toBeTruthy();
- });
-
- /**
- * GetBlock endpoint using block hash
- */
- test("Get block by it's hash.", async () => {
- // Run transaction to ensure more than one block is present
- await sendTransactionOnFabric("txForNewBlock");
-
- // Get second block by it's number
- const decodedSecondBlock = await getBlockByNumber("1", false);
- expect(decodedSecondBlock.header).toBeTruthy();
- const firstBlockHashJSON = decodedSecondBlock.header.previous_hash;
- expect(firstBlockHashJSON).toBeTruthy();
-
- // Get using default JSON hash representation
- log.info("Get by JSON hash:", firstBlockHashJSON);
- const getBlockByJsonHashReq = {
- channelName: ledgerChannelName,
- gatewayOptions,
- query: {
- blockHash: {
- buffer: firstBlockHashJSON,
- },
- },
- };
- const getBlockByJsonHashResponse = await apiClient.getBlockV1(
- getBlockByJsonHashReq,
- );
- if (!("decodedBlock" in getBlockByJsonHashResponse.data)) {
- // narrow the type
- throw new Error(
- "Wrong response received - expected decoded, received encoded.",
- );
- }
- const { decodedBlock } = getBlockByJsonHashResponse.data;
- expect(decodedBlock).toBeTruthy();
- expect(decodedBlock.header).toBeTruthy();
- expect(decodedBlock.header.number.low).toBe(0);
- expect(decodedBlock.header.number.high).toBe(0);
- expect(decodedBlock.data).toBeTruthy();
- expect(decodedBlock.metadata).toBeTruthy();
-
- // Get using HEX encoded hash representation
- const firstBlockHashHex = Buffer.from(firstBlockHashJSON).toString("hex");
- log.info("Get by HEX hash:", firstBlockHashHex);
- const getBlockByHexHashReq: GetBlockRequestV1 = {
- channelName: ledgerChannelName,
- gatewayOptions,
- query: {
- blockHash: {
- encoding: "hex",
- buffer: firstBlockHashHex,
- },
- },
- };
- const getBlockByHexHashResponse =
- await apiClient.getBlockV1(getBlockByHexHashReq);
- if (!("decodedBlock" in getBlockByHexHashResponse.data)) {
- // narrow the type
- throw new Error(
- "Wrong response received - expected decoded, received encoded.",
- );
- }
- const decodedBlockHex = getBlockByHexHashResponse.data.decodedBlock;
- expect(decodedBlockHex).toBeTruthy();
- expect(decodedBlockHex.header).toBeTruthy();
- expect(decodedBlockHex.header.number.low).toBe(0);
- expect(decodedBlockHex.header.number.high).toBe(0);
- expect(decodedBlockHex.data).toBeTruthy();
- expect(decodedBlockHex.metadata).toBeTruthy();
- });
-
- /**
- * Check error handling
- */
- test("Reading block with invalid number returns an error.", async () => {
- const getBlockReq = {
- channelName: ledgerChannelName,
- gatewayOptions,
- query: {
- blockNumber: "foo", // non existent block
- },
- };
-
- try {
- await apiClient.getBlockV1(getBlockReq);
- expect(true).toBe(false); // above call should always throw
- } catch (err) {
- expect(err).toBeTruthy();
- }
- });
-});
diff --git a/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/query-system-chain-methods.test.ts b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/query-system-chain-methods.test.ts
new file mode 100644
index 0000000000..da7f03ee7c
--- /dev/null
+++ b/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/query-system-chain-methods.test.ts
@@ -0,0 +1,539 @@
+import "jest-extended";
+import http from "http";
+import { AddressInfo } from "net";
+import { v4 as uuidv4 } from "uuid";
+import bodyParser from "body-parser";
+import express from "express";
+import { DiscoveryOptions } from "fabric-network";
+// BlockDecoder is not exported in ts definition so we need to use legacy import.
+const { BlockDecoder } = require("fabric-common");
+
+import {
+ DEFAULT_FABRIC_2_AIO_IMAGE_NAME,
+ FABRIC_25_LTS_AIO_FABRIC_VERSION,
+ FABRIC_25_LTS_AIO_IMAGE_VERSION,
+ FabricTestLedgerV1,
+ pruneDockerAllIfGithubAction,
+} from "@hyperledger/cactus-test-tooling";
+import {
+ LogLevelDesc,
+ LoggerProvider,
+ Logger,
+ IListenOptions,
+ Servers,
+} from "@hyperledger/cactus-common";
+import { Configuration } from "@hyperledger/cactus-core-api";
+import { PluginRegistry } from "@hyperledger/cactus-core";
+import { PluginKeychainMemory } from "@hyperledger/cactus-plugin-keychain-memory";
+
+import {
+ PluginLedgerConnectorFabric,
+ DefaultEventHandlerStrategy,
+ DefaultApi as FabricApi,
+ GatewayOptions,
+ FabricContractInvocationType,
+ FabricSigningCredential,
+ GetBlockResponseTypeV1,
+ GetBlockRequestV1Query,
+ CactiBlockFullEventV1,
+} from "../../../../main/typescript/public-api";
+
+/**
+ * Functional test of GetBlockEndpointV1 on connector-fabric (packages/cactus-plugin-ledger-connector-fabric)
+ * Assumes sample CC was already deployed on the test ledger.
+ */
+
+//////////////////////////////////
+// Constants
+//////////////////////////////////
+
+// Ledger settings
+const imageName = DEFAULT_FABRIC_2_AIO_IMAGE_NAME;
+const imageVersion = FABRIC_25_LTS_AIO_IMAGE_VERSION;
+const fabricEnvVersion = FABRIC_25_LTS_AIO_FABRIC_VERSION;
+const fabricEnvCAVersion = "1.4.9";
+const ledgerChannelName = "mychannel";
+const ledgerContractName = "basic";
+
+// For development on local sawtooth network
+// 1. leaveLedgerRunning = true, useRunningLedger = false to run ledger and leave it running after test finishes.
+// 2. leaveLedgerRunning = true, useRunningLedger = true to use that ledger in future runs.
+const useRunningLedger = false;
+const leaveLedgerRunning = false;
+
+// Log settings
+const testLogLevel: LogLevelDesc = "info"; // default: info
+const sutLogLevel: LogLevelDesc = "info"; // default: info
+
+// Logger setup
+const log: Logger = LoggerProvider.getOrCreate({
+ label: "query-system-chain-methods.test",
+ level: testLogLevel,
+});
+
+/**
+ * Main test suite
+ */
+describe("Query system chain methods and endpoints tests", () => {
+ let ledger: FabricTestLedgerV1;
+ let gatewayOptions: GatewayOptions;
+ let fabricConnectorPlugin: PluginLedgerConnectorFabric;
+ let connectorServer: http.Server;
+ let apiClient: FabricApi;
+
+ //////////////////////////////////
+ // Environment Setup
+ //////////////////////////////////
+
+ beforeAll(async () => {
+ log.info("Prune Docker...");
+ await pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
+
+ // Start Ledger
+ log.info("Start FabricTestLedgerV1...");
+ log.debug("Version:", fabricEnvVersion, "CA Version:", fabricEnvCAVersion);
+ ledger = new FabricTestLedgerV1({
+ emitContainerLogs: false,
+ publishAllPorts: true,
+ logLevel: testLogLevel,
+ imageName,
+ imageVersion,
+ envVars: new Map([
+ ["FABRIC_VERSION", fabricEnvVersion],
+ ["CA_VERSION", fabricEnvCAVersion],
+ ]),
+ useRunningLedger,
+ });
+ log.debug("Fabric image:", ledger.getContainerImageName());
+ await ledger.start({ omitPull: false });
+
+ // Get connection profile
+ log.info("Get fabric connection profile for Org1...");
+ const connectionProfile = await ledger.getConnectionProfileOrg1();
+ expect(connectionProfile).toBeTruthy();
+
+ // Enroll admin and user
+ const userOrg = "org1";
+ const enrollAdminOut = await ledger.enrollAdminV2({
+ organization: userOrg,
+ });
+ log.debug("Enrolled admin OK.");
+ const adminWallet = enrollAdminOut[1];
+ const userId = `testUser_${(Math.random() + 1).toString(36).substring(2)}`;
+ const [userIdentity] = await ledger.enrollUserV2({
+ enrollmentID: userId,
+ organization: userOrg,
+ wallet: adminWallet,
+ });
+ log.debug(`Enrolled user '${userId}' OK.`);
+
+ // Create Keychain Plugin
+ const keychainId = uuidv4();
+ const keychainEntryKey = userId;
+ const keychainPlugin = new PluginKeychainMemory({
+ instanceId: uuidv4(),
+ keychainId,
+ logLevel: sutLogLevel,
+ backend: new Map([[keychainEntryKey, JSON.stringify(userIdentity)]]),
+ });
+
+ gatewayOptions = {
+ identity: keychainEntryKey,
+ wallet: {
+ keychain: {
+ keychainId,
+ keychainRef: keychainEntryKey,
+ },
+ },
+ };
+
+ // Create Connector Plugin
+ const discoveryOptions: DiscoveryOptions = {
+ enabled: true,
+ asLocalhost: true,
+ };
+ fabricConnectorPlugin = new PluginLedgerConnectorFabric({
+ instanceId: uuidv4(),
+ pluginRegistry: new PluginRegistry({ plugins: [keychainPlugin] }),
+ sshConfig: await ledger.getSshConfig(),
+ cliContainerEnv: {},
+ peerBinary: "/fabric-samples/bin/peer",
+ logLevel: sutLogLevel,
+ connectionProfile,
+ discoveryOptions,
+ eventHandlerOptions: {
+ strategy: DefaultEventHandlerStrategy.NetworkScopeAnyfortx,
+ commitTimeout: 300,
+ },
+ });
+
+ // Run http server
+ const expressApp = express();
+ expressApp.use(bodyParser.json({ limit: "250mb" }));
+ connectorServer = http.createServer(expressApp);
+ const listenOptions: IListenOptions = {
+ hostname: "127.0.0.1",
+ port: 0,
+ server: connectorServer,
+ };
+ const addressInfo = (await Servers.listen(listenOptions)) as AddressInfo;
+ const apiHost = `http://${addressInfo.address}:${addressInfo.port}`;
+
+ // Register services
+ await fabricConnectorPlugin.getOrCreateWebServices();
+ await fabricConnectorPlugin.registerWebServices(expressApp);
+
+ // Create ApiClient
+ const apiConfig = new Configuration({ basePath: apiHost });
+ apiClient = new FabricApi(apiConfig);
+ });
+
+ afterAll(async () => {
+ log.info("FINISHING THE TESTS");
+
+ if (fabricConnectorPlugin) {
+ log.info("Close ApiClient connections...");
+ fabricConnectorPlugin.shutdown();
+ }
+
+ if (connectorServer) {
+ log.info("Stop the HTTP server connector...");
+ await new Promise((resolve) =>
+ connectorServer.close(() => resolve()),
+ );
+ }
+
+ if (ledger && !leaveLedgerRunning) {
+ log.info("Stop the fabric ledger...");
+ await ledger.stop();
+ await ledger.destroy();
+ }
+
+ log.info("Prune Docker...");
+ await pruneDockerAllIfGithubAction({ logLevel: testLogLevel });
+ });
+
+ //////////////////////////////////
+ // Helpers
+ //////////////////////////////////
+
+ /**
+ * Run get block endpoint using a query, do basic response checks.
+ * Can be reused throughout the tests.
+ *
+ * @param query how to find requested block
+ * @param type response type requested
+ *
+ * @returns block object / block buffer
+ */
+ async function getBlock(
+ query: GetBlockRequestV1Query,
+ type: GetBlockResponseTypeV1 = GetBlockResponseTypeV1.Full,
+ ): Promise {
+ const getBlockReq = {
+ channelName: ledgerChannelName,
+ gatewayOptions,
+ query,
+ type,
+ };
+
+ const getBlockResponse = await apiClient.getBlockV1(getBlockReq);
+ log.debug(
+ "getBlockResponse = ",
+ getBlockResponse.status,
+ getBlockResponse.data,
+ );
+
+ expect(getBlockResponse).toBeTruthy();
+ expect(getBlockResponse.status).toEqual(200);
+ expect(getBlockResponse.data).toBeTruthy();
+
+ switch (type) {
+ case GetBlockResponseTypeV1.Full:
+ if (!("decodedBlock" in getBlockResponse.data)) {
+ throw new Error(
+ `Wrong response received - expected decoded, got: ${getBlockResponse.data}`,
+ );
+ }
+ expect(getBlockResponse.data.decodedBlock).toBeTruthy();
+ return getBlockResponse.data.decodedBlock;
+ case GetBlockResponseTypeV1.Encoded:
+ if (!("encodedBlock" in getBlockResponse.data)) {
+ throw new Error(
+ `Wrong response received - expected encoded, got: ${getBlockResponse.data}`,
+ );
+ }
+ expect(getBlockResponse.data.encodedBlock).toBeTruthy();
+ return getBlockResponse.data.encodedBlock;
+ case GetBlockResponseTypeV1.CactiTransactions:
+ if (!("cactiTransactionsEvents" in getBlockResponse.data)) {
+ throw new Error(
+ `Wrong response received - expected CactiTransactions, got: ${getBlockResponse.data}`,
+ );
+ }
+ expect(getBlockResponse.data.cactiTransactionsEvents).toBeTruthy();
+ return getBlockResponse.data.cactiTransactionsEvents;
+ case GetBlockResponseTypeV1.CactiFullBlock:
+ if (!("cactiFullEvents" in getBlockResponse.data)) {
+ throw new Error(
+ `Wrong response received - expected CactiFullBlock, got: ${getBlockResponse.data}`,
+ );
+ }
+ expect(getBlockResponse.data.cactiFullEvents).toBeTruthy();
+ return getBlockResponse.data.cactiFullEvents;
+ default:
+ // Will not compile if any type was not handled by above switch.
+ const unknownType: never = type;
+ const validTypes = Object.keys(GetBlockResponseTypeV1).join(";");
+ const errorMessage = `Unknown get block response type '${unknownType}'. Accepted types for GetBlockResponseTypeV1 are: [${validTypes}]`;
+ throw new Error(errorMessage);
+ }
+ }
+
+ /**
+ * Create new asset on the ledger to trigger new transaction creation.
+ *
+ * @param assetName unique asset name to create
+ * @returns committed transaction id.
+ */
+ async function sendTransactionOnFabric(assetName: string) {
+ const createAssetResponse = await apiClient.runTransactionV1({
+ signingCredential: gatewayOptions.wallet
+ .keychain as FabricSigningCredential,
+ channelName: ledgerChannelName,
+ invocationType: FabricContractInvocationType.Send,
+ contractName: ledgerContractName,
+ methodName: "CreateAsset",
+ params: [assetName, "green", "111", "someOwner", "299"],
+ });
+ expect(createAssetResponse).toBeTruthy();
+ expect(createAssetResponse.status).toEqual(200);
+ expect(createAssetResponse.data).toBeTruthy();
+ const txId = createAssetResponse.data.transactionId;
+ expect(txId).toBeTruthy();
+
+ log.debug("Crated new transaction, txId:", txId);
+ return txId;
+ }
+
+ //////////////////////////////////
+ // GetBlockV1 Endpoint Tests
+ //////////////////////////////////
+
+ describe("GetBlockV1 endpoint tests", () => {
+ /**
+ * GetBlock endpoint using block number
+ */
+ test("Get first block by it's number - decoded.", async () => {
+ // Check decoded
+ const decodedFirstBlock = await getBlock(
+ { blockNumber: "0" },
+ GetBlockResponseTypeV1.Full,
+ );
+ log.debug("Received decodedFirstBlock:", decodedFirstBlock);
+ expect(decodedFirstBlock.header).toBeTruthy();
+ expect(decodedFirstBlock.header.number.low).toBe(0);
+ expect(decodedFirstBlock.header.number.high).toBe(0);
+ expect(decodedFirstBlock.data).toBeTruthy();
+ expect(decodedFirstBlock.metadata).toBeTruthy();
+ });
+
+ test("Get first block by it's number - encoded.", async () => {
+ // Check decoded
+ const encodedFirstBlock = await getBlock(
+ { blockNumber: "0" },
+ GetBlockResponseTypeV1.Encoded,
+ );
+ const decodedFirstBlockBuffer = Buffer.from(encodedFirstBlock, "base64");
+ const decodedFirstBlock = BlockDecoder.decode(decodedFirstBlockBuffer);
+ log.debug("Received decodedFirstBlock:", decodedFirstBlock);
+ expect(decodedFirstBlock.header).toBeTruthy();
+ expect(decodedFirstBlock.header.number.low).toBe(0);
+ expect(decodedFirstBlock.header.number.high).toBe(0);
+ expect(decodedFirstBlock.data).toBeTruthy();
+ expect(decodedFirstBlock.metadata).toBeTruthy();
+ });
+
+ /**
+ * GetBlock endpoint using transactionId
+ */
+ test("Get a block by transactionId it contains", async () => {
+ // Run some transaction
+ const assetName = `getBlockTx_${(Math.random() + 1).toString(36).substring(2)}`;
+ const txId = await sendTransactionOnFabric(assetName);
+
+ // Get block using transactionId we've just sent
+ const blockByTx = await getBlock(
+ { transactionId: txId },
+ GetBlockResponseTypeV1.Full,
+ );
+ expect(blockByTx).toBeTruthy();
+ expect(blockByTx.header).toBeTruthy();
+ expect(blockByTx.data).toBeTruthy();
+ expect(blockByTx.metadata).toBeTruthy();
+ });
+
+ test("Get a block by transactionId it contains - cacti transactions summary", async () => {
+ // Run some transaction
+ const assetName = `cactiTx_${(Math.random() + 1).toString(36).substring(2)}`;
+ const txId = await sendTransactionOnFabric(assetName);
+
+ // Get block using transactionId we've just sent
+ const cactiTxList = await getBlock(
+ { transactionId: txId },
+ GetBlockResponseTypeV1.CactiTransactions,
+ );
+ expect(cactiTxList).toBeTruthy();
+ expect(cactiTxList.length).toBeGreaterThanOrEqual(1);
+ const cactiTx = cactiTxList[0];
+ expect(cactiTx).toBeTruthy();
+ expect(cactiTx.chaincodeId).toBeTruthy();
+ expect(cactiTx.transactionId).toBeTruthy();
+ expect(cactiTx.functionName).toBeTruthy();
+ expect(cactiTx.functionArgs).toBeTruthy();
+ expect(cactiTx.functionArgs.length).toEqual(5);
+ });
+
+ test("Get a block by transactionId it contains - cacti full block summary", async () => {
+ // Run some transaction
+ const assetName = `cactiTx_${(Math.random() + 1).toString(36).substring(2)}`;
+ const txId = await sendTransactionOnFabric(assetName);
+
+ // Get block using transactionId we've just sent
+ const cactiFullBlock = (await getBlock(
+ { transactionId: txId },
+ GetBlockResponseTypeV1.CactiFullBlock,
+ )) as CactiBlockFullEventV1;
+
+ // Check block fields
+ expect(cactiFullBlock).toBeTruthy();
+ expect(cactiFullBlock.blockNumber).toBeDefined();
+ expect(cactiFullBlock.blockHash).toBeTruthy();
+ expect(cactiFullBlock.previousBlockHash).toBeTruthy();
+ expect(cactiFullBlock.transactionCount).toBeGreaterThanOrEqual(1);
+
+ // Check transaction fields
+ for (const tx of cactiFullBlock.cactiTransactionsEvents) {
+ expect(tx.hash).toBeTruthy();
+ expect(tx.channelId).toBeTruthy();
+ expect(tx.timestamp).toBeTruthy();
+ expect(tx.transactionType).toBeTruthy();
+ expect(tx.protocolVersion).not.toBeUndefined();
+ expect(tx.epoch).not.toBeUndefined();
+
+ // Check transaction actions fields
+ for (const action of tx.actions) {
+ expect(action.functionName).toBeTruthy();
+ expect(action.functionArgs).toBeTruthy();
+ expect(action.functionArgs.length).toEqual(5);
+ expect(action.chaincodeId).toBeTruthy();
+ expect(action.creator.mspid).toBeTruthy();
+ expect(action.creator.cert).toBeTruthy();
+
+ // Check transaction action endorsement fields
+ for (const endorsement of action.endorsements) {
+ expect(endorsement.signature).toBeTruthy();
+ expect(endorsement.signer.mspid).toBeTruthy();
+ expect(endorsement.signer.cert).toBeTruthy();
+ }
+ }
+ }
+ });
+
+ /**
+ * GetBlock endpoint using block hash
+ */
+ test("Get block by it's hash.", async () => {
+ // Run transaction to ensure more than one block is present
+ const assetName = `txForNewBlock_${(Math.random() + 1).toString(36).substring(2)}`;
+ await sendTransactionOnFabric(assetName);
+
+ // Get second block by it's number
+ const decodedSecondBlock = await getBlock(
+ { blockNumber: "1" },
+ GetBlockResponseTypeV1.Full,
+ );
+ expect(decodedSecondBlock.header).toBeTruthy();
+ const firstBlockHashJSON = decodedSecondBlock.header.previous_hash;
+ expect(firstBlockHashJSON).toBeTruthy();
+
+ // Get using default JSON hash representation
+ log.info("Get by JSON hash:", firstBlockHashJSON);
+
+ const decodedFirstBlock = await getBlock(
+ {
+ blockHash: {
+ buffer: firstBlockHashJSON,
+ },
+ },
+ GetBlockResponseTypeV1.Full,
+ );
+ expect(decodedFirstBlock).toBeTruthy();
+ expect(decodedFirstBlock.header).toBeTruthy();
+ expect(decodedFirstBlock.header.number.low).toBe(0);
+ expect(decodedFirstBlock.header.number.high).toBe(0);
+ expect(decodedFirstBlock.data).toBeTruthy();
+ expect(decodedFirstBlock.metadata).toBeTruthy();
+
+ // Get using HEX encoded hash representation
+ const firstBlockHashHex = Buffer.from(firstBlockHashJSON).toString("hex");
+ log.info("Get by HEX hash:", firstBlockHashHex);
+
+ const decodedBlockHex = await getBlock(
+ {
+ blockHash: {
+ encoding: "hex",
+ buffer: firstBlockHashHex,
+ },
+ },
+ GetBlockResponseTypeV1.Full,
+ );
+ expect(decodedBlockHex).toBeTruthy();
+ expect(decodedBlockHex.header).toBeTruthy();
+ expect(decodedBlockHex.header.number.low).toBe(0);
+ expect(decodedBlockHex.header.number.high).toBe(0);
+ expect(decodedBlockHex.data).toBeTruthy();
+ expect(decodedBlockHex.metadata).toBeTruthy();
+ });
+
+ /**
+ * Check error handling
+ */
+ test("Reading block with invalid number returns an error.", async () => {
+ const getBlockReq = {
+ channelName: ledgerChannelName,
+ gatewayOptions,
+ query: {
+ blockNumber: "foo", // non existent block
+ },
+ };
+
+ try {
+ await apiClient.getBlockV1(getBlockReq);
+ expect(true).toBe(false); // above call should always throw
+ } catch (err) {
+ expect(err).toBeTruthy();
+ }
+ });
+ });
+
+ //////////////////////////////////
+ // GetChainInfoV1 Endpoint Tests
+ //////////////////////////////////
+
+ describe("GetChainInfoV1 endpoint tests", () => {
+ test("Get test ledger chain info.", async () => {
+ const chainInfoResponse = await apiClient.getChainInfoV1({
+ channelName: ledgerChannelName,
+ gatewayOptions,
+ });
+
+ const chainInfo = chainInfoResponse.data;
+ expect(chainInfoResponse.status).toBe(200);
+ expect(chainInfo).toBeTruthy;
+ expect(chainInfo.height).toBeGreaterThanOrEqual(1);
+ expect(chainInfo.currentBlockHash).toBeTruthy;
+ expect(chainInfo.previousBlockHash).toBeTruthy;
+ });
+ });
+});
diff --git a/packages/cactus-plugin-persistence-fabric/src/main/typescript/plugin-persistence-fabric.ts b/packages/cactus-plugin-persistence-fabric/src/main/typescript/plugin-persistence-fabric.ts
index 7aae96952e..24168126c7 100644
--- a/packages/cactus-plugin-persistence-fabric/src/main/typescript/plugin-persistence-fabric.ts
+++ b/packages/cactus-plugin-persistence-fabric/src/main/typescript/plugin-persistence-fabric.ts
@@ -23,6 +23,7 @@ import {
FabricApiClient,
GetBlockResponseV1,
RunTransactionResponseType,
+ GetBlockResponseTypeV1,
} from "@hyperledger/cactus-plugin-ledger-connector-fabric";
import PostgresDatabaseClient from "./db-client/db-client";
@@ -416,7 +417,7 @@ export class PluginPersistenceFabric
query: {
blockNumber,
},
- skipDecode: false,
+ responseType: GetBlockResponseTypeV1.Full,
});
const tempBlockParse = block.data;
diff --git a/yarn.lock b/yarn.lock
index f0a25f31b0..1ce1009ec9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8733,6 +8733,7 @@ __metadata:
http-status-codes: "npm:2.1.4"
internal-ip: "npm:6.2.0"
jsrsasign: "npm:11.0.0"
+ long: "npm:5.2.3"
multer: "npm:1.4.5-lts.1"
ngo: "npm:2.7.0"
node-ssh: "npm:13.1.0"
@@ -35825,6 +35826,13 @@ __metadata:
languageName: node
linkType: hard
+"long@npm:5.2.3, long@npm:^5.0.0, long@npm:^5.2.3":
+ version: 5.2.3
+ resolution: "long@npm:5.2.3"
+ checksum: 10/9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6
+ languageName: node
+ linkType: hard
+
"long@npm:^4.0.0":
version: 4.0.0
resolution: "long@npm:4.0.0"
@@ -35832,13 +35840,6 @@ __metadata:
languageName: node
linkType: hard
-"long@npm:^5.0.0, long@npm:^5.2.3":
- version: 5.2.3
- resolution: "long@npm:5.2.3"
- checksum: 10/9167ec6947a825b827c30da169a7384eec6c0c9ec2f0b9c74da2e93d81159bbe39fb09c3f13dae9721d4b807ccfa09797a7dd1012f5d478e3e33ca3c78b608e6
- languageName: node
- linkType: hard
-
"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"