Hyperledger Fabric Shim API
The `fabric-shim-api` package provides the Node.js API for Hyperledger Fabric chaincode shim, facilitating communication between endorsing peers and user-provided chaincodes. Its primary role is to offer TypeScript type definitions for the `fabric-shim` module, and it serves as a dependency for `fabric-contract-api`, enabling the use of annotations in client applications without pulling in unnecessary runtime dependencies. The current stable version is 2.5.8, part of the v2.5 LTS series. Releases typically follow the Hyperledger Fabric LTS cadence, with point releases addressing fixes and dependency updates. Key differentiators include its lightweight nature as a type-only package, its integral role in the Fabric Node.js chaincode ecosystem, and its support for modern Node.js runtimes (currently Node 22 for the latest versions).
Common errors
-
Error: The chaincode is not built with a compatible Node.js version.
cause The Node.js version used to build or run the chaincode container is older than the minimum required by the `fabric-shim` and `fabric-shim-api` versions.fixUpdate the Node.js version in your chaincode Dockerfile and local development environment to Node.js 18 or higher. For recent shim versions (2.5.5+), use Node.js 20 or Node.js 22. -
TypeError: stub.getHistory is not a function
cause Using an outdated `fabric-shim-api` (or `fabric-shim`) version that predates the introduction or stabilization of the `getHistory` API, or an incorrect `Stub` type.fixEnsure you are using `fabric-shim-api` and `fabric-shim` versions 2.5.2 or higher. Verify your `stub` variable is correctly typed as `Stub` from `fabric-shim-api`. -
Property 'someMethod' does not exist on type 'ChaincodeInterface'.
cause Attempting to call a custom chaincode method directly via `this[funcName]` without proper type assertions or ensuring the method is publicly accessible on the `ChaincodeInterface` implementation.fixIn your `Invoke` method, safely access custom functions using `(this as any)[ret.fcn]` or implement type guards to ensure the method exists and is callable. Alternatively, define an interface that extends `ChaincodeInterface` and includes your custom methods. -
Error: 14 UNAVAILABLE: No connection established
cause Issues with the gRPC communication layer between the chaincode and the peer, often due to network configuration, misconfigured `CORE_CHAINCODE_ID_NAME` or `CORE_PEER_ADDRESS`, or incompatible `grpc-js` versions.fixCheck network connectivity between the chaincode container and the peer. Verify `CORE_CHAINCODE_ID_NAME` and `CORE_PEER_ADDRESS` environment variables are correctly set. Ensure `fabric-shim` and `grpc-js` versions are compatible; upgrading to the latest `fabric-shim` (2.5.8+) often resolves underlying gRPC issues.
Warnings
- breaking The Node.js runtime requirement for chaincode has progressively increased. Fabric chaincodes using this shim API now require Node.js >=18, with recent versions (2.5.5+) targeting Node 20, and the latest v2.5.8+ targeting Node 22. Older Node.js versions will not be supported or may lead to runtime errors.
- breaking The `getHistory` API in the `Stub` interface was fixed in v2.5.2 to correctly return a JSON object rather than a raw byte buffer. Chaincodes relying on the previous raw buffer return for `getHistory` will need to adjust their parsing logic.
- gotcha A vulnerability (CVE-2024-37168) in the underlying `grpc-js` dependency was addressed in v2.5.6. While `fabric-shim-api` itself is a type package, the runtime `fabric-shim` depends on `grpc-js`.
- gotcha The `grpc-js` dependency had its version strictly locked to 1.8.1 in v2.5.1 due to issues, but this constraint was relaxed in v2.5.7. This could lead to different `grpc-js` versions being resolved depending on your `fabric-shim` version and other dependencies, potentially causing subtle behavioral differences or conflicts.
Install
-
npm install fabric-shim-api -
yarn add fabric-shim-api -
pnpm add fabric-shim-api
Imports
- ChaincodeInterface
const { ChaincodeInterface } = require('fabric-shim-api');import { ChaincodeInterface } from 'fabric-shim-api'; - Stub
const { Stub } = require('fabric-shim-api');import { Stub } from 'fabric-shim-api'; - Response
import { Response } from 'fabric-shim-api/lib/interfaces';import { SuccessResponse, ErrorResponse, Response } from 'fabric-shim-api';
Quickstart
import { ChaincodeInterface, Stub, SuccessResponse, ErrorResponse, ChaincodeResponse } from 'fabric-shim-api';
class MyChaincode implements ChaincodeInterface {
async Init(stub: Stub): Promise<ChaincodeResponse> {
console.info('=========== Instantiated MyChaincode ===========');
return SuccessResponse.newSuccess('Chaincode initialized successfully.');
}
async Invoke(stub: Stub): Promise<ChaincodeResponse> {
console.info('=========== Invoked MyChaincode ===========');
const ret = stub.getFunctionAndParameters();
const method = this[ret.fcn as keyof MyChaincode];
if (!method) {
console.error(`No method found for function: ${ret.fcn}`);
return ErrorResponse.newError(`Unknown function: ${ret.fcn}`);
}
try {
const payload = await method.apply(this, [stub, ret.params]);
return SuccessResponse.newSuccess(payload);
} catch (err: any) {
console.error(`Error calling function ${ret.fcn}: ${err.message}`);
return ErrorResponse.newError(err.message);
}
}
private async createAsset(stub: Stub, args: string[]): Promise<Buffer> {
if (args.length !== 2) {
throw new Error('Incorrect number of arguments. Expecting 2 (assetName, assetValue).');
}
const [assetName, assetValue] = args;
await stub.putState(assetName, Buffer.from(assetValue));
return Buffer.from(`Asset ${assetName} created with value ${assetValue}`);
}
}
// For demonstration, typically registered with chaincode-api or shim directly
// For a real chaincode, you'd usually pass this to start() from 'fabric-shim'
// For example: chaincode.start(new MyChaincode());
export { MyChaincode };