This commit is contained in:
Mark S. Lewis 2026-02-25 17:22:13 +00:00 committed by GitHub
commit 1e786f9b5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
82 changed files with 17143 additions and 4521 deletions

View file

@ -6,16 +6,16 @@ inputs:
default: "lts/*" default: "lts/*"
just-version: just-version:
description: Just Version description: Just Version
default: "1.43.0" default: "1.46.0"
k9s-version: k9s-version:
description: k9s Version description: k9s Version
default: v0.50.15 default: v0.50.18
fabric-version: fabric-version:
description: Version of Hyperledger Fabric description: Version of Hyperledger Fabric
default: "2.5.14" default: "2.5.14"
ca-version: ca-version:
description: Version of Hyperledger Fabric CA description: Version of Hyperledger Fabric CA
default: "1.5.15" default: "1.5.17"
runs: runs:
using: "composite" using: "composite"

View file

@ -15,7 +15,7 @@ inputs:
default: 2.5.14 default: 2.5.14
ca-version: ca-version:
description: Version of Hyperledger Fabric CA description: Version of Hyperledger Fabric CA
default: 1.5.15 default: 1.5.17
runs: runs:
using: "composite" using: "composite"

1
.gitignore vendored
View file

@ -13,7 +13,6 @@ vendor/
.idea .idea
# Dependency directories # Dependency directories
node_modules/ node_modules/
package-lock.json
# Ignore Gradle build output directory # Ignore Gradle build output directory
build build
# Ignore Maven build output directory # Ignore Maven build output directory

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,11 @@
"@hyperledger/fabric-gateway": "^1.10.0" "@hyperledger/fabric-gateway": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.2", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.18.6", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4", "typescript": "~5.8",
"typescript-eslint": "^7.13.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,
@ -10,6 +10,6 @@
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true
}, },
"include": ["./src/**/*"], "include": ["src/"],
"exclude": ["./src/**/*.spec.ts"] "exclude": ["**/*.spec.*"]
} }

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -31,11 +31,11 @@
"sort-keys-recursive": "^2.1.0" "sort-keys-recursive": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.19.33", "@eslint/js": "^10.0.1",
"@eslint/js": "^9.3.0", "@tsconfig/node20": "^20.1.9",
"@tsconfig/node18": "^18.2.4", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,11 @@
"@hyperledger/fabric-gateway": "^1.10.0" "@hyperledger/fabric-gateway": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.2", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.18.6", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4", "typescript": "~5.8",
"typescript-eslint": "^7.13.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,
@ -10,6 +10,6 @@
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true
}, },
"include": ["./src/**/*"], "include": ["src/"],
"exclude": ["./src/**/*.spec.ts"] "exclude": ["**/*.spec.*"]
} }

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -3,6 +3,9 @@
"version": "0.0.1", "version": "0.0.1",
"description": "Hyperledger Fabric Asset Transfer Chaincode written in TypeScript", "description": "Hyperledger Fabric Asset Transfer Chaincode written in TypeScript",
"main": "dist/index.js", "main": "dist/index.js",
"engines": {
"node": ">=20"
},
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"lint": "eslint src", "lint": "eslint src",
@ -17,11 +20,11 @@
"sort-keys-recursive": "^2.1.0" "sort-keys-recursive": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.19.33", "@eslint/js": "^10.0.1",
"@eslint/js": "^9.3.0", "@tsconfig/node20": "^20.1.9",
"@tsconfig/node18": "^18.2.4", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -335,7 +335,7 @@ export class AssetTransferContract extends Contract {
const nanos = historyRecord.timestamp.nanos; const nanos = historyRecord.timestamp.nanos;
const secondsNumber = const secondsNumber =
typeof seconds === 'number' ? seconds : Number(seconds.low); typeof seconds === 'number' ? seconds : seconds.low;
const timestamp = new Date(secondsNumber * 1000 + nanos / 1e6); const timestamp = new Date(secondsNumber * 1000 + nanos / 1e6);
results.push({ results.push({
txId: historyRecord.txId, txId: historyRecord.txId,
@ -355,7 +355,7 @@ export class AssetTransferContract extends Contract {
@Returns('boolean') @Returns('boolean')
public async AssetExists(ctx: Context, assetID: string): Promise<boolean> { public async AssetExists(ctx: Context, assetID: string): Promise<boolean> {
const assetBytes = await ctx.stub.getState(assetID); const assetBytes = await ctx.stub.getState(assetID);
return !!(assetBytes.length > 0); return assetBytes.length > 0;
} }
// InitLedger creates the initial set of assets in the ledger. // InitLedger creates the initial set of assets in the ledger.
@ -436,7 +436,8 @@ export class AssetTransferContract extends Contract {
let record: Asset; let record: Asset;
try { try {
record = JSON.parse(strValue) as Asset; record = JSON.parse(strValue) as Asset;
} catch (err) { // eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (err) {
record = {} as Asset; record = {} as Asset;
} }
allResults.push(record); allResults.push(record);

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,11 @@
"@hyperledger/fabric-gateway": "^1.10.0" "@hyperledger/fabric-gateway": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.2", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.18.6", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4", "typescript": "~5.8",
"typescript-eslint": "^7.13.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -31,11 +31,11 @@
"sort-keys-recursive": "^2.1.10" "sort-keys-recursive": "^2.1.10"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.19.33", "@eslint/js": "^10.0.1",
"@eslint/js": "^9.3.0", "@tsconfig/node20": "^20.1.9",
"@tsconfig/node18": "^18.2.4", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -465,9 +465,7 @@ export class AssetTransfer extends Contract {
const b64ID = ctx.clientIdentity.getID(); const b64ID = ctx.clientIdentity.getID();
// base64.StdEncoding.DecodeString(b64ID); // base64.StdEncoding.DecodeString(b64ID);
const decodeID = Buffer.from(b64ID, 'base64').toString('binary'); return Buffer.from(b64ID, 'base64').toString('binary');
return String(decodeID);
} }
// verifyClientOrgMatchesPeerOrg is an internal function used verify client org id and matches peer org id. // verifyClientOrgMatchesPeerOrg is an internal function used verify client org id and matches peer org id.
public verifyClientOrgMatchesPeerOrg(ctx: Context): void { public verifyClientOrgMatchesPeerOrg(ctx: Context): void {

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -25,11 +25,11 @@
"fabric-shim": "~2.5" "fabric-shim": "~2.5"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^18.19.33", "@eslint/js": "^10.0.1",
"@eslint/js": "^9.3.0", "@tsconfig/node20": "^20.1.9",
"@tsconfig/node18": "^18.2.4", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,

View file

@ -1,4 +1,5 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,11 @@
"@hyperledger/fabric-gateway": "^1.10.0" "@hyperledger/fabric-gateway": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.2", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.18.6", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4", "typescript": "~5.8",
"typescript-eslint": "^7.13.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -5,7 +5,7 @@
*/ */
import { Contract } from '@hyperledger/fabric-gateway'; import { Contract } from '@hyperledger/fabric-gateway';
import { TextDecoder } from 'util'; import { TextDecoder } from 'util';
import { GREEN, parse, RED, RESET } from './utils'; import { GREEN, RED, RESET } from './utils';
import crypto from 'crypto'; import crypto from 'crypto';
import { mspIdOrg2 } from './connect'; import { mspIdOrg2 } from './connect';
@ -92,16 +92,16 @@ export class ContractWrapper {
const resultBytes = await this.#contract.evaluateTransaction('ReadAsset', assetKey); const resultBytes = await this.#contract.evaluateTransaction('ReadAsset', assetKey);
const result = this.#utf8Decoder.decode(resultBytes); const result = this.#utf8Decoder.decode(resultBytes);
if (result.length !== 0) { if (!result) {
const json = parse<AssetJSON>(result);
if (json.ownerOrg === ownerOrg) {
console.log(`*** Result from ${this.#org} - asset ${json.assetID} owned by ${json.ownerOrg} DESC: ${json.publicDescription}`);
} else {
console.log(`${RED}*** Failed owner check from ${this.#org} - asset ${json.assetID} owned by ${json.ownerOrg} DESC:${json.publicDescription}.${RESET}`);
}
} else {
throw new Error('No Asset Found'); throw new Error('No Asset Found');
} }
const json = JSON.parse(result) as AssetJSON;
if (json.ownerOrg === ownerOrg) {
console.log(`*** Result from ${this.#org} - asset ${json.assetID} owned by ${json.ownerOrg} DESC: ${json.publicDescription}`);
} else {
console.log(`${RED}*** Failed owner check from ${this.#org} - asset ${json.assetID} owned by ${json.ownerOrg} DESC:${json.publicDescription}.${RESET}`);
}
} }
public async getAssetPrivateProperties(assetKey: string, ownerOrg: string): Promise<void> { public async getAssetPrivateProperties(assetKey: string, ownerOrg: string): Promise<void> {
@ -113,7 +113,7 @@ export class ContractWrapper {
const resultBytes = await this.#contract.evaluateTransaction('GetAssetPrivateProperties', assetKey); const resultBytes = await this.#contract.evaluateTransaction('GetAssetPrivateProperties', assetKey);
const resultString = this.#utf8Decoder.decode(resultBytes); const resultString = this.#utf8Decoder.decode(resultBytes);
const json = parse<AssetPropertiesJSON>(resultString); const json = JSON.parse(resultString) as AssetPropertiesJSON;
const result: AssetProperties = { const result: AssetProperties = {
color: json.color, color: json.color,
size: json.size, size: json.size,
@ -167,16 +167,16 @@ export class ContractWrapper {
}); });
const resultString = this.#utf8Decoder.decode(resultBytes); const resultString = this.#utf8Decoder.decode(resultBytes);
if (resultString.length !== 0) { if (!resultString) {
const json = parse<AssetPropertiesJSON>(resultString);
if (typeof json === 'object') {
console.log(`*** Success VerifyAssetProperties, private information about asset ${assetId} has been verified by ${this.#org}`);
} else {
console.log(`*** Failed: VerifyAssetProperties, private information about asset ${assetId} has not been verified by ${this.#org}`);
}
} else {
throw new Error(`Private information about asset ${assetId} has not been verified by ${this.#org}`); throw new Error(`Private information about asset ${assetId} has not been verified by ${this.#org}`);
} }
const json = JSON.parse(resultString) as AssetPropertiesJSON;
if (typeof json === 'object') {
console.log(`*** Success VerifyAssetProperties, private information about asset ${assetId} has been verified by ${this.#org}`);
} else {
console.log(`*** Failed: VerifyAssetProperties, private information about asset ${assetId} has not been verified by ${this.#org}`);
}
} }
public async agreeToBuy(assetPrice: AssetPrice, privateData: AssetPrivateData): Promise<void> { public async agreeToBuy(assetPrice: AssetPrice, privateData: AssetPrivateData): Promise<void> {
@ -217,7 +217,7 @@ export class ContractWrapper {
const resultBytes = await this.#contract.evaluateTransaction('GetAssetSalesPrice', assetKey); const resultBytes = await this.#contract.evaluateTransaction('GetAssetSalesPrice', assetKey);
const resultString = this.#utf8Decoder.decode(resultBytes); const resultString = this.#utf8Decoder.decode(resultBytes);
const json = parse<AssetPriceJSON>(resultString); const json = JSON.parse(resultString) as AssetPriceJSON;
const result: AssetPrice = { const result: AssetPrice = {
assetId: json.assetID, assetId: json.assetID,
@ -238,7 +238,7 @@ export class ContractWrapper {
const resultBytes = await this.#contract.evaluateTransaction('GetAssetBidPrice', assetKey); const resultBytes = await this.#contract.evaluateTransaction('GetAssetBidPrice', assetKey);
const resultString = this.#utf8Decoder.decode(resultBytes); const resultString = this.#utf8Decoder.decode(resultBytes);
const json = parse<AssetPriceJSON>(resultString); const json = JSON.parse(resultString) as AssetPriceJSON;
const result: AssetPrice = { const result: AssetPrice = {
assetId: json.assetID, assetId: json.assetID,
price: json.price, price: json.price,

View file

@ -7,7 +7,3 @@
export const RED = '\x1b[31m\n'; export const RED = '\x1b[31m\n';
export const GREEN = '\x1b[32m\n'; export const GREEN = '\x1b[32m\n';
export const RESET = '\x1b[0m'; export const RESET = '\x1b[0m';
export function parse<T>(data: string): T {
return JSON.parse(data) as T;
}

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,

View file

@ -8,7 +8,7 @@ function print() {
echo -e "${GREEN}${1}${NC}" echo -e "${GREEN}${1}${NC}"
} }
dirs=("$(find . -name "*-typescript" -type d -not -path '*/.*')") dirs=("$(find . \( -name '.?*' -o -name 'node_modules' \) -prune -o -type d -name '*-typescript' -print)")
for dir in $dirs; do for dir in $dirs; do
print "Linting $dir" print "Linting $dir"
pushd $dir pushd $dir

View file

@ -8,7 +8,6 @@ coverage
# Dependencies # Dependencies
node_modules/ node_modules/
jspm_packages/ jspm_packages/
package-lock.json
# Compiled TypeScript files # Compiled TypeScript files
dist dist

View file

@ -10,7 +10,7 @@ This project is based on the [trader-typescript](../trader-typescript) sample Ga
## Prerequisites ## Prerequisites
The client application requires Node.js 16 or later. The client application requires Node.js 20 or later.
## Set up ## Set up

View file

@ -0,0 +1,14 @@
import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint';
export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: {
ecmaVersion: 2023,
sourceType: 'module',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: import.meta.dirname,
},
},
});

File diff suppressed because it is too large Load diff

View file

@ -10,7 +10,7 @@
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"build:watch": "tsc -w", "build:watch": "tsc -w",
"lint": "eslint ./src", "lint": "eslint src",
"prepare": "npm run build", "prepare": "npm run build",
"pretest": "npm run lint", "pretest": "npm run lint",
"start": "node ./dist/app", "start": "node ./dist/app",
@ -21,16 +21,16 @@
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.14.0", "@grpc/grpc-js": "^1.14.0",
"@hyperledger/fabric-gateway": "^1.10.0", "@hyperledger/fabric-gateway": "^1.10.0",
"axios": "^1.7.7", "axios": "^1.13.5",
"source-map-support": "^0.5.21" "source-map-support": "^0.5.21"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/node18": "^18.2.2", "@eslint/js": "^10.0.1",
"@types/node": "^18.18.6", "@tsconfig/node20": "^20.1.9",
"@types/node": "^20.19.33",
"@types/source-map-support": "^0.5.6", "@types/source-map-support": "^0.5.6",
"@typescript-eslint/eslint-plugin": "^6.9.0", "eslint": "^10.0.2",
"@typescript-eslint/parser": "^6.9.0", "typescript": "~5.8",
"eslint": "^8.52.0", "typescript-eslint": "^8.56.1"
"typescript": "~5.2.2"
} }
} }

View file

@ -13,6 +13,11 @@ import { ExpectedError } from './expectedError';
async function main(): Promise<void> { async function main(): Promise<void> {
const commandName = process.argv[2]; const commandName = process.argv[2];
if (!commandName) {
printUsage();
throw new Error('No command specified');
}
const args = process.argv.slice(3); const args = process.argv.slice(3);
const command = commands[commandName]; const command = commands[commandName];
@ -44,7 +49,7 @@ function printUsage(): void {
console.log(`\t${Object.keys(commands).sort().join('\n\t')}`); console.log(`\t${Object.keys(commands).sort().join('\n\t')}`);
} }
main().catch(error => { main().catch((error: unknown) => {
if (error instanceof ExpectedError) { if (error instanceof ExpectedError) {
console.log(error); console.log(error);
} else { } else {

View file

@ -7,10 +7,14 @@
import { Gateway } from '@hyperledger/fabric-gateway'; import { Gateway } from '@hyperledger/fabric-gateway';
import { CHAINCODE_NAME, CHANNEL_NAME } from '../config'; import { CHAINCODE_NAME, CHANNEL_NAME } from '../config';
import { AssetTransfer } from '../contract'; import { AssetTransfer } from '../contract';
import { assertAllDefined } from '../utils'; import { assertDefined } from '../utils';
const usage = 'Arguments: <assetId> <ownerName> <color>';
export default async function main(gateway: Gateway, args: string[]): Promise<void> { export default async function main(gateway: Gateway, args: string[]): Promise<void> {
const [assetId, owner, color] = assertAllDefined([args[0], args[1], args[2]], 'Arguments: <assetId> <ownerName> <color>'); const assetId = assertDefined(args[0], usage);
const owner = assertDefined(args[1], usage);
const color = assertDefined(args[2], usage);
const network = gateway.getNetwork(CHANNEL_NAME); const network = gateway.getNetwork(CHANNEL_NAME);
const contract = network.getContract(CHAINCODE_NAME); const contract = network.getContract(CHAINCODE_NAME);

View file

@ -7,10 +7,10 @@ import { ChaincodeEvent, checkpointers, Gateway } from '@hyperledger/fabric-gate
import * as path from 'path'; import * as path from 'path';
import { CHAINCODE_NAME, CHANNEL_NAME } from '../config'; import { CHAINCODE_NAME, CHANNEL_NAME } from '../config';
import { Asset } from '../contract'; import { Asset } from '../contract';
import { assertDefined } from '../utils'; import { assertDefined, randomElement } from '../utils';
import { TextDecoder } from 'util'; import { TextDecoder } from 'util';
import axios from 'axios'
const axios = require('axios');
const utf8Decoder = new TextDecoder(); const utf8Decoder = new TextDecoder();
const checkpointFile = path.resolve(process.env.CHECKPOINT_FILE ?? 'checkpoint.json'); const checkpointFile = path.resolve(process.env.CHECKPOINT_FILE ?? 'checkpoint.json');
@ -33,7 +33,7 @@ export default async function main(gateway: Gateway): Promise<void> {
const checkpointer = await checkpointers.file(checkpointFile); const checkpointer = await checkpointers.file(checkpointFile);
console.log(`Connecting to #discord webhook ${webhookURL}`); console.log(`Connecting to #discord webhook ${webhookURL}`);
console.log(`Starting event discording from block ${checkpointer.getBlockNumber() ?? startBlock}`); console.log(`Starting event discording from block ${String(checkpointer.getBlockNumber() ?? startBlock)}`);
console.log('Last processed transaction ID within block:', checkpointer.getTransactionId()); console.log('Last processed transaction ID within block:', checkpointer.getTransactionId());
const events = await network.getChaincodeEvents(CHAINCODE_NAME, { const events = await network.getChaincodeEvents(CHAINCODE_NAME, {
@ -58,7 +58,7 @@ export default async function main(gateway: Gateway): Promise<void> {
} }
// Relay a quick message to the discord webhook to indicate the transaction has been processed. // Relay a quick message to the discord webhook to indicate the transaction has been processed.
async function discord(webhookURL: string, event: ChaincodeEvent): Promise<void> { function discord(webhookURL: string, event: ChaincodeEvent): Promise<void> {
const asset = parseJson(event.payload); const asset = parseJson(event.payload);
console.log(`\n<-- Chaincode event received: ${event.eventName}: `, asset); console.log(`\n<-- Chaincode event received: ${event.eventName}: `, asset);
@ -66,11 +66,11 @@ async function discord(webhookURL: string, event: ChaincodeEvent): Promise<void>
// const message = boringLogMessage(event, asset); // const message = boringLogMessage(event, asset);
const message = splashyShoutMessage(event, asset); const message = splashyShoutMessage(event, asset);
deliverMessage(webhookURL, message); return deliverMessage(webhookURL, message);
} }
// Send an event to a discord webhook. // Send an event to a discord webhook.
async function deliverMessage(webhookURL: string, message: any): Promise<void> { async function deliverMessage(webhookURL: string, message: object): Promise<void> {
console.log('--> Sending to discord webhook: ' + webhookURL); console.log('--> Sending to discord webhook: ' + webhookURL);
console.log(JSON.stringify(message)); console.log(JSON.stringify(message));
@ -82,7 +82,8 @@ async function deliverMessage(webhookURL: string, message: any): Promise<void> {
} }
} }
function boringLogMessage(event: ChaincodeEvent, asset: Asset): any { // eslint-disable-next-line @typescript-eslint/no-unused-vars
function boringLogMessage(event: ChaincodeEvent, asset: Asset): object {
const owner = ownerNickname(asset); const owner = ownerNickname(asset);
const text = format(event, asset, owner); const text = format(event, asset, owner);
@ -93,9 +94,9 @@ function boringLogMessage(event: ChaincodeEvent, asset: Asset): any {
} }
} }
function splashyShoutMessage(event: ChaincodeEvent, asset: Asset): any { function splashyShoutMessage(event: ChaincodeEvent, asset: Asset): object {
const owner:any = JSON.parse(asset.Owner); const owner = JSON.parse(asset.Owner) as Owner;
if (event.eventName == 'CreateAsset') { if (event.eventName == 'CreateAsset') {
return { return {
@ -104,7 +105,7 @@ function splashyShoutMessage(event: ChaincodeEvent, asset: Asset): any {
content: `${bold(owner.user)} has caught a wild ${bold(asset.ID)}!` + getRandomEmoji(), content: `${bold(owner.user)} has caught a wild ${bold(asset.ID)}!` + getRandomEmoji(),
embeds: [ embeds: [
{ {
title: `${owner.org}`, title: owner.org,
image: { image: {
// an actual conga comic (sometimes png and sometimes jpg) // an actual conga comic (sometimes png and sometimes jpg)
// url: `https://congacomic.github.io/assets/img/blockheight-${offset}.png` // url: `https://congacomic.github.io/assets/img/blockheight-${offset}.png`
@ -140,7 +141,7 @@ function format(event: ChaincodeEvent, asset: Asset, owner: string): string {
function parseJson(jsonBytes: Uint8Array): Asset { function parseJson(jsonBytes: Uint8Array): Asset {
const json = utf8Decoder.decode(jsonBytes); const json = utf8Decoder.decode(jsonBytes);
return JSON.parse(json); return JSON.parse(json) as Asset;
} }
function quote(s: string): string { function quote(s: string): string {
@ -160,7 +161,7 @@ function snippet(s: string) {
} }
function ownerNickname(asset: Asset): string { function ownerNickname(asset: Asset): string {
const owner:any = JSON.parse(asset.Owner); const owner = JSON.parse(asset.Owner) as Owner;
return `${owner.org}, ${owner.user}`; return `${owner.org}, ${owner.user}`;
} }
@ -169,7 +170,10 @@ function ownerNickname(asset: Asset): string {
// Simple method that returns a random emoji from list // Simple method that returns a random emoji from list
function getRandomEmoji(): string { function getRandomEmoji(): string {
const emojiList = ['😭','😄','😌','🤓','😎','😤','🤖','😶‍🌫', '🌏','📸','💿','👋','🌊','✨']; const emojiList = ['😭','😄','😌','🤓','😎','😤','🤖','😶‍🌫', '🌏','📸','💿','👋','🌊','✨'];
return emojiList[Math.floor(Math.random() * emojiList.length)]; return randomElement(emojiList)
} }
interface Owner {
user: string;
org: string;
}

View file

@ -16,5 +16,7 @@ export default async function main(gateway: Gateway): Promise<void> {
const assets = await smartContract.getAllAssets(); const assets = await smartContract.getAllAssets();
const assetsJson = JSON.stringify(assets, undefined, 2); const assetsJson = JSON.stringify(assets, undefined, 2);
assetsJson.split('\n').forEach(line => console.log(line)); // Write line-by-line to avoid truncation assetsJson.split('\n').forEach(line => {
console.log(line);
}); // Write line-by-line to avoid truncation
} }

View file

@ -7,10 +7,14 @@
import { Gateway } from '@hyperledger/fabric-gateway'; import { Gateway } from '@hyperledger/fabric-gateway';
import { CHAINCODE_NAME, CHANNEL_NAME } from '../config'; import { CHAINCODE_NAME, CHANNEL_NAME } from '../config';
import { AssetTransfer } from '../contract'; import { AssetTransfer } from '../contract';
import { assertAllDefined } from '../utils'; import { assertDefined } from '../utils';
const usage = 'Arguments: <assetId> <newOwner> <newOwnerOrg>';
export default async function main(gateway: Gateway, args: string[]): Promise<void> { export default async function main(gateway: Gateway, args: string[]): Promise<void> {
const [assetId, newOwner, newOwnerOrg] = assertAllDefined([args[0], args[1], args[2]], 'Arguments: <assetId> <ownerName> <ownerMspId>'); const assetId = assertDefined(args[0], usage);
const newOwner = assertDefined(args[1], usage);
const newOwnerOrg = assertDefined(args[2], usage);
const network = gateway.getNetwork(CHANNEL_NAME); const network = gateway.getNetwork(CHANNEL_NAME);
const contract = network.getContract(CHAINCODE_NAME); const contract = network.getContract(CHAINCODE_NAME);

View file

@ -83,7 +83,7 @@ export class AssetTransfer {
} }
async function submitWithRetry<T>(submit: () => Promise<T>): Promise<T> { async function submitWithRetry<T>(submit: () => Promise<T>): Promise<T> {
let lastError: unknown | undefined; let lastError: unknown;
for (let retryCount = 0; retryCount < RETRIES; retryCount++) { for (let retryCount = 0; retryCount < RETRIES; retryCount++) {
try { try {

View file

@ -13,7 +13,8 @@ const utf8Decoder = new TextDecoder();
* @param values Candidate elements. * @param values Candidate elements.
*/ */
export function randomElement<T>(values: T[]): T { export function randomElement<T>(values: T[]): T {
return values[randomInt(values.length)]; const result = values[randomInt(values.length)];
return assertDefined(result, `Missing element in ${String(values)}`);
} }
/** /**
@ -47,7 +48,7 @@ export async function allFulfilled(promises: Promise<unknown>[]): Promise<void>
if (failures.length > 0) { if (failures.length > 0) {
const failMessages = '- ' + failures.join('\n- '); const failMessages = '- ' + failures.join('\n- ');
throw new Error(`${failures.length} failures:\n${failMessages}\n`); throw new Error(`${String(failures.length)} failures:\n${failMessages}\n`);
} }
} }
@ -61,11 +62,6 @@ export function printable<T extends object>(event: T): PrintView<T> {
) as PrintView<T>; ) as PrintView<T>;
} }
export function assertAllDefined<T>(values: (T | undefined)[], message: string | (() => string)): T[] {
values.forEach(value => assertDefined(value, message));
return values as T[];
}
export function assertDefined<T>(value: T | undefined, message: string | (() => string)): T { export function assertDefined<T>(value: T | undefined, message: string | (() => string)): T {
if (value == undefined) { if (value == undefined) {
throw new Error(typeof message === 'string' ? message : message()); throw new Error(typeof message === 'string' ? message : message());

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"declaration": true, "declaration": true,
"declarationMap": true, "declarationMap": true,
@ -8,12 +8,13 @@
"outDir": "dist", "outDir": "dist",
"rootDir": "src", "rootDir": "src",
"noUnusedLocals": false, "noUnusedLocals": false,
"noImplicitReturns": true "noImplicitReturns": true,
"noUncheckedIndexedAccess": true
}, },
"include": [ "include": [
"src/" "src/"
], ],
"exclude": [ "exclude": [
"src/**/*.spec.ts" "**/*.spec.*"
] ]
} }

View file

@ -8,7 +8,6 @@ coverage
# Dependencies # Dependencies
node_modules/ node_modules/
jspm_packages/ jspm_packages/
package-lock.json
# Compiled TypeScript files # Compiled TypeScript files
dist dist

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,11 @@
"@hyperledger/fabric-gateway": "^1.10.0" "@hyperledger/fabric-gateway": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.4", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.19.33", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -48,7 +48,7 @@ function getSimulatedFailureCount(): number {
const value = process.env.SIMULATED_FAILURE_COUNT ?? '0'; const value = process.env.SIMULATED_FAILURE_COUNT ?? '0';
const count = Math.floor(Number(value)); const count = Math.floor(Number(value));
if (isNaN(count) || count < 0) { if (isNaN(count) || count < 0) {
throw new Error(`Invalid SIMULATED_FAILURE_COUNT value: ${String(value)}`); throw new Error(`Invalid SIMULATED_FAILURE_COUNT value: ${value}`);
} }
return count; return count;

View file

@ -14,7 +14,7 @@ const utf8Decoder = new TextDecoder();
*/ */
export function randomElement<T>(values: T[]): T { export function randomElement<T>(values: T[]): T {
const result = values[randomInt(values.length)]; const result = values[randomInt(values.length)];
return assertDefined(result, `Missing element in {String(values)}`); return assertDefined(result, `Missing element in ${String(values)}`);
} }
/** /**

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,

View file

@ -12,7 +12,7 @@ RUN npm install
RUN npm run build && npm shrinkwrap RUN npm run build && npm shrinkwrap
FROM node:lts as prod-builder FROM node:lts AS prod-builder
WORKDIR /usr/src/app WORKDIR /usr/src/app
COPY --chown=node:node --from=builder /usr/src/app/dist ./dist COPY --chown=node:node --from=builder /usr/src/app/dist ./dist
COPY --chown=node:node --from=builder /usr/src/app/package.json ./ COPY --chown=node:node --from=builder /usr/src/app/package.json ./

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

View file

@ -31,14 +31,6 @@
"json-stringify-deterministic": "^1.0.7", "json-stringify-deterministic": "^1.0.7",
"sort-keys-recursive": "^2.1.7" "sort-keys-recursive": "^2.1.7"
}, },
"devDependencies": {
"@types/node": "^18.19.33",
"@eslint/js": "^9.3.0",
"@tsconfig/node18": "^18.2.4",
"eslint": "^8.57.0",
"typescript": "~5.4.5",
"typescript-eslint": "^7.11.0"
},
"nyc": { "nyc": {
"extension": [ "extension": [
".ts", ".ts",
@ -58,5 +50,13 @@
"branches": 100, "branches": 100,
"functions": 100, "functions": 100,
"lines": 100 "lines": 100
},
"devDependencies": {
"@eslint/js": "^10.0.1",
"@tsconfig/node20": "^20.1.9",
"@types/node": "^20.19.33",
"eslint": "^10.0.2",
"typescript": "~5.8",
"typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"$schema": "https://json.schemastore.org/tsconfig", "$schema": "https://json.schemastore.org/tsconfig",
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"experimentalDecorators": true, "experimentalDecorators": true,
"emitDecoratorMetadata": true, "emitDecoratorMetadata": true,
@ -8,10 +8,10 @@
"declarationMap": true, "declarationMap": true,
"sourceMap": true, "sourceMap": true,
"outDir": "dist", "outDir": "dist",
"strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true,
"isolatedModules": true
}, },
"include": ["src/"] "include": ["src/"]
} }

View file

@ -21,7 +21,7 @@ set -eo pipefail
set -x set -x
KIND_CLUSTER_NAME=kind KIND_CLUSTER_NAME=kind
KIND_CLUSTER_IMAGE=${KIND_CLUSTER_IMAGE:-kindest/node:v1.28.0} # Important! k8s v1.25.0 brings breaking changes. KIND_CLUSTER_IMAGE=${KIND_CLUSTER_IMAGE:-kindest/node:v1.35.1} # Important! k8s v1.25.0 brings breaking changes.
KIND_API_SERVER_ADDRESS=${KIND_API_SERVER_ADDRESS:-127.0.0.1} KIND_API_SERVER_ADDRESS=${KIND_API_SERVER_ADDRESS:-127.0.0.1}
KIND_API_SERVER_PORT=${KIND_API_SERVER_PORT:-8888} KIND_API_SERVER_PORT=${KIND_API_SERVER_PORT:-8888}
CONTAINER_REGISTRY_NAME=${CONTAINER_REGISTRY_NAME:-kind-registry} CONTAINER_REGISTRY_NAME=${CONTAINER_REGISTRY_NAME:-kind-registry}
@ -78,14 +78,27 @@ networking:
# create a cluster with the local registry enabled in containerd # create a cluster with the local registry enabled in containerd
containerdConfigPatches: containerdConfigPatches:
- |- - |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:${CONTAINER_REGISTRY_PORT}"] [plugins."io.containerd.grpc.v1.cri".registry]
endpoint = ["http://${CONTAINER_REGISTRY_NAME}:${CONTAINER_REGISTRY_PORT}"] config_path = "/etc/containerd/certs.d"
EOF EOF
# Configure registry for containerd 2.x using config_path mode
for node in $(kind get nodes --name $KIND_CLUSTER_NAME);
do
docker exec "$node" mkdir -p "/etc/containerd/certs.d/localhost:${CONTAINER_REGISTRY_PORT}"
docker exec "$node" sh -c "cat > /etc/containerd/certs.d/localhost:${CONTAINER_REGISTRY_PORT}/hosts.toml <<EOT
server = \"http://localhost:${CONTAINER_REGISTRY_PORT}\"
[host.\"http://${CONTAINER_REGISTRY_NAME}:${CONTAINER_REGISTRY_PORT}\"]
capabilities = [\"pull\", \"resolve\", \"push\"]
EOT"
done
# #
# Work around a bug in KIND where DNS is not always resolved correctly on machines with IPv6 # Work around a bug in KIND where DNS is not always resolved correctly on machines with IPv6
# #
for node in $(kind get nodes); for node in $(kind get nodes --name $KIND_CLUSTER_NAME);
do do
docker exec "$node" sysctl net.ipv4.conf.all.route_localnet=1; docker exec "$node" sysctl net.ipv4.conf.all.route_localnet=1;
done done

View file

@ -34,7 +34,7 @@ function context() {
} }
context FABRIC_VERSION 2.5.14 context FABRIC_VERSION 2.5.14
context FABRIC_CA_VERSION 1.5.15 context FABRIC_CA_VERSION 1.5.17
context CLUSTER_RUNTIME kind # or k3s for Rancher context CLUSTER_RUNTIME kind # or k3s for Rancher
context CONTAINER_CLI docker # or nerdctl for containerd context CONTAINER_CLI docker # or nerdctl for containerd
@ -78,7 +78,7 @@ context CA_IMAGE_LABEL ${FABRIC_CA_VERSION}
#context PEER_IMAGE ${FABRIC_CONTAINER_REGISTRY}/fabric-peer #context PEER_IMAGE ${FABRIC_CONTAINER_REGISTRY}/fabric-peer
#context PEER_IMAGE_LABEL ${FABRIC_VERSION} #context PEER_IMAGE_LABEL ${FABRIC_VERSION}
context PEER_IMAGE ghcr.io/hyperledger-labs/fabric-builder-k8s/k8s-fabric-peer context PEER_IMAGE ghcr.io/hyperledger-labs/fabric-builder-k8s/k8s-fabric-peer
context PEER_IMAGE_LABEL 0.11.0 # When using k8s-fabric-peer in Fabric v2.5+, 0.11.0+ should be specified context PEER_IMAGE_LABEL 0.15.1 # When using k8s-fabric-peer in Fabric v2.5+, 0.11.0+ should be specified
context ORDERER_IMAGE ${FABRIC_CONTAINER_REGISTRY}/fabric-orderer context ORDERER_IMAGE ${FABRIC_CONTAINER_REGISTRY}/fabric-orderer
context ORDERER_IMAGE_LABEL ${FABRIC_VERSION} context ORDERER_IMAGE_LABEL ${FABRIC_VERSION}
context OPERATOR_IMAGE ghcr.io/hyperledger-labs/fabric-operator context OPERATOR_IMAGE ghcr.io/hyperledger-labs/fabric-operator
@ -91,7 +91,7 @@ context COUCHDB_IMAGE couchdb
context COUCHDB_IMAGE_LABEL 3.4.2 context COUCHDB_IMAGE_LABEL 3.4.2
context CONSOLE_IMAGE ghcr.io/hyperledger-labs/fabric-console context CONSOLE_IMAGE ghcr.io/hyperledger-labs/fabric-console
context CONSOLE_IMAGE_LABEL latest context CONSOLE_IMAGE_LABEL latest
context DEPLOYER_IMAGE ghcr.io/ibm-blockchain/fabric-deployer context DEPLOYER_IMAGE ghcr.io/hyperledger-labs/fabric-deployer
context DEPLOYER_IMAGE_LABEL latest-amd64 context DEPLOYER_IMAGE_LABEL latest-amd64
export FABRIC_OPERATOR_IMAGE=${OPERATOR_IMAGE}:${OPERATOR_IMAGE_LABEL} export FABRIC_OPERATOR_IMAGE=${OPERATOR_IMAGE}:${OPERATOR_IMAGE_LABEL}

View file

@ -332,12 +332,12 @@ fabric-ca-client register \
--id.name $USERNAME \ --id.name $USERNAME \
--id.secret $PASSWORD \ --id.secret $PASSWORD \
--id.type client \ --id.type client \
--url https://$WORKSHOP_NAMESPACE-$ORG-ca-ca.$WORKSHOP_INGRESS_DOMAIN \ --url https://$WORKSHOP_NAMESPACE-$ORG-ca-ca.$WORKSHOP_INGRESS_DOMAIN:443 \
--tls.certfiles $WORKSHOP_CRYPTO/cas/$ORG-ca/tls-cert.pem \ --tls.certfiles $WORKSHOP_CRYPTO/cas/$ORG-ca/tls-cert.pem \
--mspdir $WORKSHOP_CRYPTO/enrollments/$ORG/users/rcaadmin/msp --mspdir $WORKSHOP_CRYPTO/enrollments/$ORG/users/rcaadmin/msp
fabric-ca-client enroll \ fabric-ca-client enroll \
--url https://$USERNAME:$PASSWORD@$WORKSHOP_NAMESPACE-$ORG-ca-ca.$WORKSHOP_INGRESS_DOMAIN \ --url https://$USERNAME:$PASSWORD@$WORKSHOP_NAMESPACE-$ORG-ca-ca.$WORKSHOP_INGRESS_DOMAIN:443 \
--tls.certfiles $WORKSHOP_CRYPTO/cas/$ORG-ca/tls-cert.pem \ --tls.certfiles $WORKSHOP_CRYPTO/cas/$ORG-ca/tls-cert.pem \
--mspdir $WORKSHOP_CRYPTO/enrollments/$ORG/users/$USERNAME/msp --mspdir $WORKSHOP_CRYPTO/enrollments/$ORG/users/$USERNAME/msp

View file

@ -1,3 +1,2 @@
dist/ dist/
node_modules/ node_modules/
package-lock.json

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -21,13 +21,12 @@
"@hyperledger/fabric-gateway": "^1.10.0" "@hyperledger/fabric-gateway": "^1.10.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.4", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.19.33", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"npm-run-all": "^4.1.5",
"rimraf": "^5.0.1", "rimraf": "^5.0.1",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,

View file

@ -1,7 +1,8 @@
import js from '@eslint/js'; import js from '@eslint/js';
import { defineConfig } from 'eslint/config';
import tseslint from 'typescript-eslint'; import tseslint from 'typescript-eslint';
export default tseslint.config(js.configs.recommended, ...tseslint.configs.strictTypeChecked, { export default defineConfig(js.configs.recommended, ...tseslint.configs.strictTypeChecked, {
languageOptions: { languageOptions: {
ecmaVersion: 2023, ecmaVersion: 2023,
sourceType: 'module', sourceType: 'module',

File diff suppressed because it is too large Load diff

View file

@ -23,11 +23,11 @@
"@hyperledger/fabric-protos": "^0.3.4" "@hyperledger/fabric-protos": "^0.3.4"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.3.0", "@eslint/js": "^10.0.1",
"@tsconfig/node18": "^18.2.4", "@tsconfig/node20": "^20.1.9",
"@types/node": "^18.19.33", "@types/node": "^20.19.33",
"eslint": "^8.57.0", "eslint": "^10.0.2",
"typescript": "~5.4.5", "typescript": "~5.8",
"typescript-eslint": "^7.11.0" "typescript-eslint": "^8.56.1"
} }
} }

View file

@ -240,7 +240,7 @@ function getSimulatedFailureCount(): number {
const value = process.env.SIMULATED_FAILURE_COUNT ?? '0'; const value = process.env.SIMULATED_FAILURE_COUNT ?? '0';
const count = Math.floor(Number(value)); const count = Math.floor(Number(value));
if (isNaN(count) || count < 0) { if (isNaN(count) || count < 0) {
throw new Error(`Invalid SIMULATED_FAILURE_COUNT value: ${String(value)}`); throw new Error(`Invalid SIMULATED_FAILURE_COUNT value: ${value}`);
} }
return count; return count;

View file

@ -1,5 +1,5 @@
{ {
"extends": "@tsconfig/node18/tsconfig.json", "extends": "@tsconfig/node20/tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "dist", "outDir": "dist",
"declaration": true, "declaration": true,
@ -10,6 +10,6 @@
"noUncheckedIndexedAccess": true, "noUncheckedIndexedAccess": true,
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true
}, },
"include": ["./src/**/*"], "include": ["src/"],
"exclude": ["./src/**/*.spec.ts"] "exclude": ["**/*.spec.*"]
} }

View file

@ -39,8 +39,8 @@ First, run the following command to verify that the environment variables are co
```shell ```shell
$ ./network $ ./network
Fabric image versions: Peer (3.1.1), CA (1.5.15) Fabric image versions: Peer (3.1.1), CA (1.5.17)
Fabric binary versions: Peer (3.1.1), CA (1.5.15) Fabric binary versions: Peer (3.1.1), CA (1.5.17)
--- Fabric Information --- Fabric Information
Fabric Version : 3.1 Fabric Version : 3.1

View file

@ -1,7 +1,7 @@
# default image tag, example: "2.5.13". "default" will download the latest. (-i) # default image tag, example: "2.5.13". "default" will download the latest. (-i)
IMAGETAG="default" IMAGETAG="default"
# default ca image tag, example: "1.5.15". "default" will download the latest. (-cai) # default ca image tag, example: "1.5.17". "default" will download the latest. (-cai)
CA_IMAGETAG="default" CA_IMAGETAG="default"
# Using crpto vs CA. default is cryptogen # Using crpto vs CA. default is cryptogen

View file

@ -18,7 +18,7 @@ function printHelp() {
println " Flags:" println " Flags:"
println " Used with \033[0;32mnetwork.sh prereq\033[0m:" println " Used with \033[0;32mnetwork.sh prereq\033[0m:"
println " -i FabricVersion (default: '2.5.14')" println " -i FabricVersion (default: '2.5.14')"
println " -cai Fabric CA Version (default: '1.5.15')" println " -cai Fabric CA Version (default: '1.5.17')"
println println
elif [ "$USAGE" == "up" ]; then elif [ "$USAGE" == "up" ]; then
println "Usage: " println "Usage: "
@ -160,7 +160,7 @@ function printHelp() {
println " Flags:" println " Flags:"
println " Used with \033[0;32mnetwork.sh prereq\033[0m" println " Used with \033[0;32mnetwork.sh prereq\033[0m"
println " -i FabricVersion (default: '2.5.14')" println " -i FabricVersion (default: '2.5.14')"
println " -cai Fabric CA Version (default: '1.5.15')" println " -cai Fabric CA Version (default: '1.5.17')"
println println
println " Used with \033[0;32mnetwork.sh up\033[0m, \033[0;32mnetwork.sh createChannel\033[0m:" println " Used with \033[0;32mnetwork.sh up\033[0m, \033[0;32mnetwork.sh createChannel\033[0m:"
println " -ca - Use Certificate Authorities to generate network crypto material" println " -ca - Use Certificate Authorities to generate network crypto material"