Skip to content

Commit 571d1e5

Browse files
mbwhiteheatherlp
authored andcommitted
[FAB-14260] Update jsdoc
Change-Id: I5fda5e95126f17633ad5ce0e0c4e22ee501b4fcf Signed-off-by: Matthew B. White <whitemat@uk.ibm.com>
1 parent 6946d91 commit 571d1e5

File tree

5 files changed

+224
-46
lines changed

5 files changed

+224
-46
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
## Hyperledger Fabric Shim for node.js chaincodes
22

3-
This is the project for the fabric shim for node.js chaincodes development. The following instructions are oriented to a contributor or an early adopter and describes the steps to build and test the library.
3+
This is the project to support the writing of Chaincode within the node.js runtime. The following instructions are orientated to a contributor or an early adopter and therefore describes the steps to build and test the library.
44

5-
As an application developer, to learn about how to implement **"Smart Contracts"** for the Hyperledger Fabric using Node.js, Please visit the [documentation](https://fabric-shim.github.io/).
5+
As an application developer, to learn about how to implement **"Smart Contracts"** for Hyperledger Fabric using Node.js, please visit the [documentation](https://fabric-shim.github.io/).
66

77
This project publishes `fabric-shim` public npm package for developers consumption.
88

99
### Folder structure
1010

11-
The "src" folder contains the resources to become part of the npm package, including javascript files, protobuf definition files (.proto) that the code depends on, and a package.json to describe the package.
12-
1311
The "build" folder contains the "build" steps. This being javascript there's no need to compile, but special build steps are still needed to accomplish the following:
1412
* linting: to make sure we enforce a somewhat consistent coding style
1513

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# How are data types handling with Contracts?
2+
This document deals with JavaScript and TypeScript contracts
3+
4+
## Function parameters
5+
6+
### JavaScript - no metadata
7+
8+
This is the lowest common denominator; all data that is sent to the transaction function from the client is represented as strings.
9+
Therefore the conversion that takes place in the lack of any metadata is
10+
11+
```
12+
json = JSON.parse(data.toString());
13+
```
14+
15+
If the json has a property of 'type' and that equals 'Buffer' then a byte buffer is constructed. The standard JSON.stringify() form of a byte buffer is to add the type field.
16+
17+
It is then left to JavaScript to be able to coerce the data as per standard language rules
18+
19+
### JavaScript - with metadata
20+
21+
If the metadata for the property specifies a String or a Number, then conversion to a String or Number takes place.
22+
Otherwise, the same conversion takes place as with 'no-metadata'
23+
24+
25+
### Typescript
26+
Typescript needs to have no annotations for types, (other than arrays). The metadata is inferred with sufficient detail.
27+
For arrays, the `@Param(<name>,<array type>,[<description>])` needs to be used to mark the type that is in the array.
28+
29+
30+
## Return types
31+
32+
A transaction function is free to return anything it wishes. (Strictly speaking it must return a promise, and that can be resolved or rejected with anything).
33+
34+
With the Node.js runtime, either JavaScript or TypeScript can be used. For both languages you can supply additional metadata, either as annotations, or as a JSON file.
35+
36+
### JavaScript - no metadata
37+
38+
This is the lowest common denominator; if no metadata is either provided by annotations, file, or inferred by introspection this is behaviour.
39+
All return values will be processed as follows:
40+
41+
```javascript
42+
Buffer.from(JSON.stringify(functionsReturnValue))
43+
```
44+
45+
The data will be stringified, then converted to a buffer to be returned. The buffer conversion is required by the shim api to communicate with the peer. This will be 'reversed' in the client SDK so that clients are given a string.
46+
47+
### JavaScript with metadata
48+
49+
It is beneficial to supply metadata; specifically in the case of JavaScript to identify strings and numbers from objects.
50+
51+
By doing this means that the transaction functions can
52+
53+
- Return strings and numbers directly. Numbers are converted to their textual form eg 42 becomes "42"
54+
- Anything else is returned by being stringified first
55+
56+
## Typescript
57+
58+
Without the '@return' annotations and/or metadata Typescript introspection can not provide enough details about the return type. Primarily as this is a Promise that resolves a type introspection only indicates the promise aspect.
59+
60+
Metadata can be explicitly provided or the `@Returns(<string of type name>)` can be used to indicate the type. The annotation needs to have the type name specified as a string value.
61+
62+
63+
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Details on the programming model
2+
3+
Smart Contract packages consist of a set of code that contains the implementations of the code you want to run. Taken as a whole Hyperledger refers to this code as *chaincode*; a single chaincode is run within a docker container that is created and started by each peer. Depending on the language, a nodejs, Java or Go runtime might be used within the docker containers.
4+
5+
## Node.js project structure
6+
7+
Each Smart Contract package is, from a node perspective, a NPM module.
8+
9+
- package.json
10+
- This needs to import the `fabric-contract-api` and `fabric-shim` npm modules
11+
- The 'start' script must be set to `fabric-chaincode-node-start` - this has to be present for the peer to call the node module to start
12+
- It is recommended to have a 'start:dev' script that can be used for development (details on this later)
13+
- A 'main' entry to point to your `index.js` file contain the exports of the node module
14+
15+
- index.js
16+
- It is mandatory to have a `contracts` element exported that is a array of classes.
17+
- Each of these classes must extend the `Contract` class from the `fabric-contract-api` module
18+
- Optionally, a custom `serializer` may be defined to control how data is converted for transmission between chaincode, peer and ultimately client applications.
19+
20+
*JavaScript example index.js*
21+
22+
```javascript
23+
const cpcontract = require('./lib/papernet/papercontract.js');
24+
module.exports.contracts = [cpcontract];
25+
26+
module.exports.CommercialPaper = require('./lib/papernet/paper.js');
27+
```
28+
29+
*TypeScript example index.ts*
30+
31+
```typescript
32+
import { GreetingContract } from './greetingcontract';
33+
export { GreetingContract } from './greetingcontract';
34+
35+
export const contracts: any[] = [ GreetingContract ];
36+
```
37+
38+
- contract-metadata/metadata.json
39+
40+
This file describes the *external* api that is exposed from these Smart Contracts; these are the functions that can be invoked by client applications. It describes all details about what is callable, and the datatypes of parameter and return values. It can also include information about documentation and licensing.
41+
42+
It describes the callable interface, and does not make any assertions about how the code is implemented.
43+
44+
## Defining your contract classes
45+
46+
The node module must export an array of one or more contract classes in the `contracts` property.
47+
Each of these class must extend the correct type. At runtime each of these will have a single instance created, and will persist for the lifetime of the chaincode container.
48+
49+
> Each function MUST NOT use the instance to store data; all data MUST be stored within either the ledger, or within the transaction context
50+
51+
```typescript
52+
import { Contract } from 'fabric-contract-api';
53+
54+
export class GreetingContract extends Contract {
55+
56+
public constructor() {
57+
super('Greeting');
58+
}
59+
}
60+
```
61+
62+
The constructor must call super, the argument is optional but is used to name this instance, and is used to refer to this instance when it is called by client . applications. If no argument is supplied, then the name of the class is used (in this case GreetingContract ). If an empty string is supplied that is valid, but not recommended.
63+
64+
It is not recommended to supply the same name, the behaviour if function names within the two contracts overlap is undefined.
65+
66+
### Transaction Functions
67+
68+
Within each contract instance, you may has few or many functions as you wish. Each of them is eligible to a transaction function that is callable by applications.
69+
If a function name is prefixed with a _ it will be ignored. For Javascript all the functions will be eligible, but for Typescript the functions that are required must have a `@Transaction()` decorator
70+
71+
Each transaction must take as it's first parameter the transaction context
72+
73+
### Context
74+
75+
The first parameter is the 'transaction context' - it is quite plausible for several transactions to be invoked concurrently; the transaction context is required to give information specific to the transaction that is currently being executed.
76+
77+
Currently the 'stub' api for handling world state, and the 'Client Identity' is available from the context.
78+
Each contract has a 'createContext' method that can be overridden by specific implementations to provide specific control to add information to the
79+
80+
81+
### Before, After and Unknown Functions
82+
83+
The Contract class defines three functions that can be overridden by specific implementations.
84+
85+
```javascript
86+
async beforeTransaction(ctx) {
87+
// default implementation is do nothing
88+
}
89+
90+
async afterTransaction(ctx, result) {
91+
// default implementation is do nothing
92+
}
93+
```
94+
95+
Before is called immediately before the transaction function, and after immediately afterwards. Note that before does not get the arguments to the function (note this was the subject of debate, opinions welcomed). After gets the result from the transaction function (this is the result returned from transaction function without any processing).
96+
97+
If the transaction function throws an Error then the whole transaction fails, likewise if the before or after throws an Error then the transaction fails. (note that if say before throws an error the transaction function is never called, nor the after. Similarly if transaction function throws an Error, after is not called. )
98+
99+
Typical use cases of these functions would be
100+
101+
- logging of the functions called
102+
- checks of the identity of the caller
103+
104+
The unknown function is called if the requested function is not known; the default implementation is to throw an error. `You've asked to invoke a function that does not exist: {requested function}`
105+
However you can implement an `unkownTransition` function - this can return a successful or throw an error as you wish.
106+
107+
```javascript
108+
async unknownTransaction(ctx) {
109+
// throw an error here or return succesfully if you wish
110+
}
111+
```
112+
113+
## Metadata
114+
115+
### Supplying your own metadata
116+
A correctly specified metadata file, at the top level has this structure
117+
118+
```json
119+
{
120+
"$schema" : "https://fabric-shim.github.io/release-1.4/contract-schema.json",
121+
"info" : {
122+
123+
},
124+
"contracts" : {
125+
126+
},
127+
"components" : {
128+
129+
}
130+
}
131+
```
132+
133+
The metadata file that the user specifies has precedence over the information generated from the code, on a per section basis. If the user has not specified any of the above sections, then the 'gap' will be filled with auto generated values.

docs/tutorials/using-contractinterface.md

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,9 @@ This outlines the theory of the how the new node module works; with the fabric s
66

77
### 1: Chaincode is created as an npm module.
88

9-
An initial `package.json` is as follows - the only runtime dependency as far as anything blockchain is concerned is the `fabric-chaincode-api`. This provides the API definition that can be used for development, and also unit test.
9+
An initial `package.json` is as follows;
1010

11-
For development an implementation of the `fabric-shim` and specifically the CLI that accompanies it is required
12-
13-
**NOTE: for Fabric 1.4, this will need to be made a development dependency of the node module, and the `npm start` will need to call a defined app to start**
11+
The dependencies of `fabric-chaincode-api` and `fabric-shim` will be required.
1412

1513
```
1614
{
@@ -30,26 +28,22 @@ For development an implementation of the `fabric-shim` and specifically the CLI
3028
"author": "",
3129
"license": "ISC",
3230
"dependencies": {
33-
"fabric-chaincode-api: "^1.3.0"
31+
"fabric-chaincode-api": "^1.4.0",
32+
"fabric-shim": "^1.4.0"
3433
}
3534
}
3635
3736
```
38-
Remember to add in any additional business logic, and testing libraries needed.
37+
Remember to add in any additional business logic, and testing libraries needed
3938

40-
Please also add in `fabric-shim` as a dependency, and `fabric-chaincode-node` as the script to run for `npm start`. Therefore this would include
39+
Adding `fabric-shim` as a dependency, gives a command `fabric-chaincode-node` that is the script to run for `npm start`.
4140

4241
```
4342
"scripts": {
4443
"start": "fabric-chaincode-node start",
4544
"test": "nyc mocha test",
4645
....
4746
},
48-
"dependencies": {
49-
"fabric-contract-api": "^1.4.0-snapshot.1",
50-
"fabric-shim": "^1.4.0-snapshot.1",
51-
....
52-
},
5347
```
5448

5549

@@ -58,11 +52,14 @@ Please also add in `fabric-shim` as a dependency, and `fabric-chaincode-node` as
5852
Chaincode is deployed by the peer in response to issuing a number of (usually CLI) commands. For node.js chaincode the location of the chaincode npm project is required (the directory that the package.json is in). This does not need to be an installed project, but has to have all the code, and the package.json.
5953

6054
A docker image is built for this chaincode, the package.json and code copied in. and `npm install` run.
61-
> It is important to make sure that you have a `package-lock.json` to ensure the correct packages are imported.
6255

6356
After the install there is a 'bootstrap' process that starts the chaincode up (more details later). The constructors of the exported Contracts will be run at this point; these constructors are for setting the name and optional setup of the 'error/monitoring functions', (again more later). This instance of the contract will existing whilst this chaincode docker image is up.
6457

65-
When chaincode is instantiated or updated, the `init()` function is the chaincode is called. As with the `invoke()` call from the client, a fn name and parameters can be passed. Remember therefore to have specific functions to call on `init()` and `update()` in order to do any data initialization or migration that might be needed. These two functions have been abstracted away to focus on specific function implementations.
58+
When chaincode is instantiated or updated, the `init()` function is the chaincode is called. As with the `invoke()` call from the client, a fn name and parameters can be passed. Remember therefore to have specific functions to call on `init()` and `update()` in order to do any data initialisation or migration that might be needed. These two functions have been abstracted away to focus on specific function implementations.
59+
60+
It is strongly recommended to use the npm shrinkwrap mechanism so the versions of the modules that are used are fixed.
61+
62+
Within the class you can defined as many or functions as you wish. These transaction functions will form the basis of the business logic you contract needs to execute. These are `async` functions, and can take parameters and return values. There is a single mandatory parameter of the 'transaction context'; this represents the currently executing transaction and is the way functions can access the world state, and other APIs.
6663

6764
### 3: What needs to be exported?
6865

@@ -77,7 +74,7 @@ In this example we have a single value that can be queried and updated. This has
7774
const UpdateValues = require('./updatevalues')
7875
const RemoveValues = require('./removevalues')
7976
80-
module.exports.contracts = ['UpdateValues','RemoveValues'];
77+
module.exports.contracts = [UpdateValues,RemoveValues];
8178
```
8279

8380
This exports two classes that together form the Contract. There can be other code that within the model that is used in a support role.
@@ -123,28 +120,13 @@ class UpdateValues extends Contract
123120
module.exports = UpdateValues;
124121
```
125122

126-
Note that ALL the functions defined in these modules will be called by the client SDK.
123+
Note that ALL the functions defined in these modules will be called by the client SDK.
127124

128125
- There are 3 functions `setup` `setNewAssetValue` and `doubleAssetValue` that can be called by issuing the appropriate invoke client side
129126
- The `ctx` in the function is a transaction context; each time a invoke is called this will be a new instance that can be used by the function implementation to access apis such as the world state of information on invoking identity.
130127
- The arguments are split out from the array passed on the invoke.
131128
- The constructor contains a 'name' to help identify the sets of functions
132129

133-
134-
### 5: Alternative ways of specifying the contracts
135-
136-
*package.json*
137-
138-
Instead of providing the Smart Contracts as exports, you can add details to the package.json. Using the above functions add this to the package.json
139-
140-
```
141-
"contracts":{
142-
"classes": ["removevalues.js","updatevalues.js"]
143-
}
144-
```
145-
146-
If present this takes precedence over the exports.
147-
148130
## Running chaincode in development mode
149131

150132
This is quite easy - as you need to run the startChaincode command.
@@ -217,7 +199,7 @@ For example
217199

218200
### Structure of the Transaction Context
219201

220-
In Fabric 1.2, there is a *stub* api that provides chaincode with functionality.
202+
In Fabric, there is a *stub* api that provides chaincode with functionality.
221203
No functionality has been removed, but a new approach to providing abstractions on this to facilitate programming.
222204

223205
*user additions*: additional properties can be added to the object to support for example common handling of the data serialization.

0 commit comments

Comments
 (0)