Chaincode Client
The @gala-chain/client
package provides a client for interacting with the chaincode.
Currently, it supports the following client types:
* client for interacting directly with the Hyperledger Fabric network, built on top of the fabric-network
and fabric-ca-client
packages;
* client for interacting with the chaincode via REST API that meets the GalaChain REST API specification, used internally at GalaGames,
and is also compatible with the slightly different REST API exposed by Fablo REST.
All client types share the same API, so it is easy to switch between them, depending on your needs.
Also, @gala-chain/client
package is designed to be lightweight.
This is why fabric-network
and fabric-ca-client
dependencies are marked as optional peerDependencies
and should be installed separately.
Hyperledger Fabric Client
In order to connect to the Hyperledger Fabric network, you need to provide the following configuration:
1. HFClientParams
- information containing basic information about network topology and credentials for connecting to the network;
2. ContractConfig
- information about the chaincode that will be used to interact with the network.
3. Optionally, a custom API specification to make the client type-safe.
HFClientConfig
The HFClientConfig
interface defines parameters that are required to connect to the Hyperledger Fabric network.
```typescript
const params: HFClientConfig = {
orgMsp: "PartnerOrg1",
userId: "admin",
userSecret: "adminpw",
connectionProfilePath: path.resolve(networkRoot, "connection-profiles/cpp-partner.json")
};
orgMsp
- Hyperledger Fabric MSP name of the organization that the client will connect to;userId
- id of the user in Fabric CA that will be used to connect to the network;userSecret
- password/secret of the user in CA;connectionProfilePath
- path to the connection profile file that describes the network topology.
Both adminId
and adminPass
are required to authorize the client with the network.
If they are not provided, the client will try to get them from the environment variables ADMIN_ID
and ADMIN_PASS
respectively.
The connectionProfilePath
should refer to a valid connection profile JSON file.
For local development, you can use the connection profile provided in the <network-root>/connection-profiles
directory of the network generated by GalaChain CLI.
ContractConfig
The ContractConfig
interface defines parameters that are required to interact with the chaincode.
const contract: ContractConfig = {
channelName: "product-channel",
chaincodeName: "basic-product",
contractName: "PublicKeyContract"
};
channelName
- name of the channel that the client will connect to;chaincodeName
- name of the chaincode that the client will use to interact with the network;contractName
- name of the contract that the client will use to interact with the chaincode.
Creating the client
The client creation is a two-step process.
First, you need to create a client builder instance using the forConnectionProfile
method.
Then the forContract
method returns the actual client instance.
As a result, you get a ChainClient
instance that can be used to interact with the chaincode.
It supports evaluateTransaction
and submitTransaction
methods that are used to invoke chaincode functions.
After you end interacting with the chaincode, you should disconnect the client:
Otherwise, the client will keep the GRPC connection to the network open.
REST API Client
The REST API client is used to interact with the chaincode via REST API, that matches the specification of managed infrastructure of GalaChain.
In order to connect to the REST API, you need to provide the following configuration:
1. RestApiClientConfig
- information containing basic information about path mapping and credentials for connecting to the network;
2. ContractConfig
- information about the chaincode that will be used to interact with the network.
3. Optionally, a custom API specification to make the client type-safe.
RestApiClientConfig
The RestApiClientConfig
interface defines parameters that are required to connect to the REST API.
const params: RestApiClientConfig = {
apiUrl: "http://localhost:3000/api",
configPath: path.resolve(__dirname, "api-config.json")
};
orgMsp
- Hyperledger Fabric MSP name of the organization that the client will connect to;apiUrl
- URL of the REST API;configPath
- path to the configuration file that describes path mapping for channels, chaincodes, and contracts. Sample configuration file can be found in thee2e
directory of the chaincode generated from template by GalaChain CLI.
ContractConfig
The ContractConfig
interface defines parameters that are required to interact with the chaincode.
const contract: ContractConfig = {
channelName: "product-channel",
chaincodeName: "basic-product",
contractName: "PublicKeyContract"
};
channelName
- name of the channel that the client will connect to;chaincodeName
- name of the chaincode that the client will use to interact with the network;contractName
- name of the contract that the client will use to interact with the chaincode.
Creating the client
The client creation is a two-step process.
First, you need to create a client builder instance using the forConnectionProfile
method.
Then the forContract
method returns the actual client instance.
As a result, you get a ChainClient
instance that can be used to interact with the chaincode.
It supports evaluateTransaction
and submitTransaction
methods that are used to invoke chaincode functions.
After you end interacting with the chaincode, you should disconnect the client:
Builder and actual client
For all high-level operations, the client uses the Builder
pattern:
1. first, you create a builder instance using the forConnectionProfile
or forApiConfig
method;
2. then you configure the builder instance using the forContract
method.
Since all ChainClient
builders share the same interface, you can just parametrize the builder type and use the same code for all client types, for instance:
const builder: ChainClientBuilder = process.env.USE_REST_API === "true"
? gcclient.forApiConfig(...)
: gcclient.forConnectionProfile(...);
const client: ChainClient = builder.forContract(...);
Extending the client API
The @gala-chain/client
package provides a default API definition that is used to make the client type-safe.
By default ChainClient
defines evaluateTransaction
and submitTransaction
methods that are used to interact with the chaincode.
However, you can provide your own API definition, if you want to extend the client API or use a different API.
The API definition is a function that accepts a ChainClient
instance and returns an object with methods that will be added to the client.
function customAPI(client: ChainClient) {
return {
async GetProfile(privateKey: string) {
const dto = new GetMyProfileDto().signed(privateKey, false);
const response = await client.evaluateTransaction("GetMyProfile", dto, UserProfile);
if (GalaChainResponse.isError(response)) {
throw new Error(`Cannot get profile: ${response.Message} (${response.ErrorKey})`);
} else {
return response.Data as UserProfile;
}
}
};
}
Now, when you enhance the client with your custom API, you can use not only default methods but also the ones that you defined:
const client: ChainClient = ...;
client.evaluateTransaction(...); // available
client.submitTransaction(...); // available
client.GetProfile(...); // compilation error
const extendedClient = client.extend(customAPI);
client.evaluateTransaction(...); // available
client.submitTransaction(...); // available
client.GetProfile(...); // available