fabric-samples/balance-transfer/README.md
Yuki Kondo 6cce07c440 [FAB-5155]Fix README.md in "balance-transfer" example
The README in "balance-transfer" should be fixed in the section:
https://github.com/hyperledger/fabric-samples/tree/master/
balance-transfer#running-the-sample-program

1. Broken link
There is a link to "Sample REST APIs Requests" which is broken.
This is linked to non-existent path on fabric-sdk-node repository.
I believe the intended link is to
https://github.com/hyperledger/fabric-samples/tree/master/
balance-transfer#sample-rest-apis-requests

2. Instruction to start node application.
There is no instruction to start node application.
If we execute the REST APIs according to the current README,
we can't get any responses since node application is not working.
We need to execute the following steps before calling REST APIs.

 - npm install
 - PORT=4000 node app

fix repo names

Change-Id: I9ec0ec18bb36addd6c8371481dc8cfe645053ec6
Signed-off-by: Yuki Kondo <yuki.kondo@hal.hitachi.com>
Signed-off-by: Christopher Ferris <chrisfer@us.ibm.com>
2017-07-19 12:00:51 -04:00

298 lines
10 KiB
Markdown

## Balance transfer
A sample Node.js app to demonstrate **__fabric-client__** & **__fabric-ca-client__** Node.js SDK APIs
### Prerequisites and setup:
* [Docker](https://www.docker.com/products/overview) - v1.12 or higher
* [Docker Compose](https://docs.docker.com/compose/overview/) - v1.8 or higher
* [Git client](https://git-scm.com/downloads) - needed for clone commands
* **Node.js** v6.9.0 - 6.10.0 ( __Node v7+ is not supported__ )
* Download docker images
```
cd fabric-samples/balance-transfer/
docker-compose -f artifacts/docker-compose.yaml pull
```
Once you have completed the above setup, you will have provisioned a local network with the following docker container configuration:
* 2 CAs
* A SOLO orderer
* 4 peers (2 peers per Org)
#### Artifacts
* Crypto material has been generated using the **cryptogen** tool from Hyperledger Fabric and mounted to all peers, the orderering node and CA containers. More details regarding the cryptogen tool are available [here](http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html#crypto-generator).
* An Orderer genesis block (genesis.block) and channel configuration transaction (mychannel.tx) has been pre generated using the **configtxgen** tool from Hyperledger Fabric and placed within the artifacts folder. More details regarding the configtxgen tool are available [here](http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html#configuration-transaction-generator).
## Running the sample program
There are two options available for running the balance-transfer sample
### Option 1:
##### Terminal Window 1
* Launch the network using docker-compose
```
docker-compose -f artifacts/docker-compose.yaml up
```
##### Terminal Window 2
* Install the fabric-client and fabric-ca-client node modules
```
npm install
```
* Start the node app on PORT 4000
```
PORT=4000 node app
```
##### Terminal Window 3
* Execute the REST APIs from the section [Sample REST APIs Requests](https://github.com/hyperledger/fabric-samples/tree/master/balance-transfer#sample-rest-apis-requests)
### Option 2:
##### Terminal Window 1
```
cd fabric-samples/balance-transfer
./runApp.sh
```
* This lauches the required network on your local machine
* Installs the fabric-client and fabric-ca-client node modules
* And, starts the node app on PORT 4000
##### Terminal Window 2
In order for the following shell script to properly parse the JSON, you must install ``jq``:
instructions [https://stedolan.github.io/jq/](https://stedolan.github.io/jq/)
With the application started in terminal 1, next, test the APIs by executing the script - **testAPIs.sh**:
```
cd fabric-samples/balance-transfer
./testAPIs.sh
```
## Sample REST APIs Requests
### Login Request
* Register and enroll new users in Organization - **Org1**:
`curl -s -X POST http://localhost:4000/users -H "content-type: application/x-www-form-urlencoded" -d 'username=Jim&orgName=org1'`
**OUTPUT:**
```
{
"success": true,
"secret": "RaxhMgevgJcm",
"message": "Jim enrolled Successfully",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI"
}
```
The response contains the success/failure status, an **enrollment Secret** and a **JSON Web Token (JWT)** that is a required string in the Request Headers for subsequent requests.
### Create Channel request
```
curl -s -X POST \
http://localhost:4000/channels \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"channelName":"mychannel",
"channelConfigPath":"../artifacts/channel/mychannel.tx"
}'
```
Please note that the Header **authorization** must contain the JWT returned from the `POST /users` call
### Join Channel request
```
curl -s -X POST \
http://localhost:4000/channels/mychannel/peers \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"peers": ["localhost:7051","localhost:7056"]
}'
```
### Install chaincode
```
curl -s -X POST \
http://localhost:4000/chaincodes \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"peers": ["localhost:7051","localhost:7056"],
"chaincodeName":"mycc",
"chaincodePath":"github.com/example_cc",
"chaincodeVersion":"v0"
}'
```
### Instantiate chaincode
```
curl -s -X POST \
http://localhost:4000/channels/mychannel/chaincodes \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"peers": ["localhost:7051"],
"chaincodeName":"mycc",
"chaincodeVersion":"v0",
"functionName":"init",
"args":["a","100","b","200"]
}'
```
### Invoke request
```
curl -s -X POST \
http://localhost:4000/channels/mychannel/chaincodes/mycc \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json" \
-d '{
"peers": ["localhost:7051", "localhost:7056"],
"fcn":"move",
"args":["a","b","10"]
}'
```
**NOTE:** Ensure that you save the Transaction ID from the response in order to pass this string in the subsequent query transactions.
### Chaincode Query
```
curl -s -X GET \
"http://localhost:4000/channels/mychannel/chaincodes/mycc?peer=peer1&fcn=query&args=%5B%22a%22%5D" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Query Block by BlockNumber
```
curl -s -X GET \
"http://localhost:4000/channels/mychannel/blocks/1?peer=peer1" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Query Transaction by TransactionID
```
curl -s -X GET http://localhost:4000/channels/mychannel/transactions/TRX_ID?peer=peer1 \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
**NOTE**: Here the TRX_ID can be from any previous invoke transaction
### Query ChainInfo
```
curl -s -X GET \
"http://localhost:4000/channels/mychannel?peer=peer1" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Query Installed chaincodes
```
curl -s -X GET \
"http://localhost:4000/chaincodes?peer=peer1&type=installed" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Query Instantiated chaincodes
```
curl -s -X GET \
"http://localhost:4000/chaincodes?peer=peer1&type=instantiated" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Query Channels
```
curl -s -X GET \
"http://localhost:4000/channels?peer=peer1" \
-H "authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0OTQ4NjU1OTEsInVzZXJuYW1lIjoiSmltIiwib3JnTmFtZSI6Im9yZzEiLCJpYXQiOjE0OTQ4NjE5OTF9.yWaJhFDuTvMQRaZIqg20Is5t-JJ_1BP58yrNLOKxtNI" \
-H "content-type: application/json"
```
### Network configuration considerations
You have the ability to change configuration parameters by editing the network-config.json file.
#### IP Address** and PORT information
If you choose to customize your docker-compose yaml file by hardcoding IP Addresses and PORT information for your peers and orderer, then you MUST also add the identical values into the network-config.json file. The paths shown below will need to be adjusted to match your docker-compose yaml file.
```
"orderer": {
"url": "grpcs://x.x.x.x:7050",
"server-hostname": "orderer0",
"tls_cacerts": "../artifacts/tls/orderer/ca-cert.pem"
},
"org1": {
"ca": "http://x.x.x.x:7054",
"peer1": {
"requests": "grpcs://x.x.x.x:7051",
"events": "grpcs://x.x.x.x:7053",
...
},
"peer2": {
"requests": "grpcs://x.x.x.x:7056",
"events": "grpcs://x.x.x.x:7058",
...
}
},
"org2": {
"ca": "http://x.x.x.x:8054",
"peer1": {
"requests": "grpcs://x.x.x.x:8051",
"events": "grpcs://x.x.x.x:8053",
... },
"peer2": {
"requests": "grpcs://x.x.x.x:8056",
"events": "grpcs://x.x.x.x:8058",
...
}
}
```
#### Discover IP Address
To retrieve the IP Address for one of your network entities, issue the following command:
```
# this will return the IP Address for peer0
docker inspect peer0 | grep IPAddress
```
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />This work is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.