Skip to content

Commit

Permalink
[FAB-2065] Update balance-transfer sample app
Browse files Browse the repository at this point in the history
Update balance-transfer sample app to encourage best practices
 and remove temporary workaround.

move the event listener registration earlier in the code logic before
the transaction is sent out, and use Promise.all() to manage the promise
resolution

Change-Id: If7b04a0bac8f64356a748dbe364def13327e6a14
Signed-off-by: ratnakar <asara.ratnakar@gmail.com>
  • Loading branch information
asararatnakar committed Feb 8, 2017
1 parent e64871f commit 56c54ee
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 26 deletions.
110 changes: 110 additions & 0 deletions examples/balance-transfer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
##Balance transfer

A sample node-based app to demonstrate ***fabric-client*** & ***fabric-ca-client*** Node SDK APIs

###Prerequisites and setup:
Follow the [Getting Started](http://hyperledger-fabric.readthedocs.io/en/latest/gettingstarted/#getting-started-with-v10-hyperledger-fabric-app-developers) instructions in the Hyperledger Fabric documentation.

Once you have completed the above setup, you will be provisioned a local network with following configuration:
- 3 **peers**, a **solo orderer**, and a **CA server**
- A channel - `myc1` - and a corresponding genesis block - `myc1.block`
- With the peers - `peer0`, `peer1`, and `peer2` - automatically joined to the channel.

###Running the sample program:
The step-by-step instructions for executing the sample program are outlined in the [Getting Started](http://hyperledger-fabric.readthedocs.io/en/latest/gettingstarted/#use-node-sdk-to-registerenroll-user-and-deployinvokequery) documentation.

**NOTE**: If you want to run the app from this directory, ensure that you set the `GOPATH`
variable to the correct folder during deployment execution:

```
GOPATH=$PWD/../../test/fixtures node deploy.js
```

###Configuration considerations

You have the ability to change configuration parameters by editing the **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 **config.json** file. The four paths shown below will
need to be adjusted to match your docker-compose yaml file.

```
"orderer":{
"orderer_url":"grpc://x.x.x.x:7050"
},
"peers":[
{
"peer_url":"grpc://x.x.x.x:7051"
},
{
"peer_url":"grpc://x.x.x.x:8051"
},
{
"peer_url":"grpc://x.x.x.x:9051"
}
],
```

####Discover IP Address
To retrieve the IP Address for one of your network entities, issue the following command:
```bash
# this will return the IP Address for peer0
docker inspect peer0 | grep IPAddress
```

####Channel name

You can manually create your own channel from the cli container. If you choose to do so,
the `ChannelID` field must also be updated in **config.json** to match your channel name.
For example:
```bash

"chainName":"fabric-client1",
"chaincodeID":"mycc",
"channelID":"YOUR_CHANNEL_NAME",
"goPath":"../../test/fixtures",
```


####Chaincode name
If you want to deploy a chaincode with a different name, then you must also update the
`chaincodeID` field in **config.json** to match your chaincode name. For example:

```bash

"chainName":"fabric-client1",
"chaincodeID":"YOUR_CHAINCODE_NAME",
"channelID":"YOUR_CHANNEL_NAME",
"goPath":"../../test/fixtures",
```

####Chaincode path
The `chaincodePath` parameter tells the node program where to look when you execute
the deployment. The default setup places the go code in `/src/github.com/example_cc`
path. You can modify this path with a new name and your own go code. For example:

```
"chaincodePath":"github.com/my_chaincode",
```

#### Transaction/Query payload information

You can modify payload information based on your chaincode implementation. For instance,
if you want to create a marble using [marbles02](https://github.com/hyperledger/fabric/blob/master/examples/chaincode/go/marbles02/marbles_chaincode.go)
chaincode, change your `invokeRequest` in **config.json** as shown below:


```
"invokeRequest":{
"functionName":"initMarble",
"args":[
"marble1",
"blue",
"33",
"JohnDoe"
]
},
```
1 change: 0 additions & 1 deletion examples/balance-transfer/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"secret":"adminpw"
}
],
"dockerfile_contents": "from hyperledger/fabric-ccenv\n COPY . $GOPATH/src/build-chaincode/\n WORKDIR $GOPATH\n\n RUN go install build-chaincode && mv $GOPATH/bin/build-chaincode $GOPATH/bin/%s",
"deployRequest":{
"functionName":"init",
"args":[
Expand Down
14 changes: 2 additions & 12 deletions examples/balance-transfer/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,29 +75,19 @@ hfc.newDefaultKeyValueStore({
chainId: config.channelID,
txId: tx_id,
nonce: nonce,
'dockerfile-contents': config.dockerfile_contents
};
return chain.sendDeploymentProposal(request);
}
).then(
function(results) {
logger.info('Successfully obtained proposal responses from endorsers');
return helper.processProposal(chain, results, 'deploy');
return helper.processProposal(tx_id, eventhub, chain, results, 'deploy');
}
).then(
function(response) {
if (response.status === 'SUCCESS') {
logger.info('Successfully sent deployment transaction to the orderer.');
var handle = setTimeout(() => {
logger.error('Failed to receive transaction notification within the timeout period');
process.exit(1);
}, parseInt(config.waitTime));

eventhub.registerTxEvent(tx_id.toString(), (tx) => {
logger.info('The chaincode transaction has been successfully committed');
clearTimeout(handle);
eventhub.disconnect();
});
process.exit();
} else {
logger.error('Failed to order the deployment endorsement. Error code: ' + response.status);
}
Expand Down
25 changes: 23 additions & 2 deletions examples/balance-transfer/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ module.exports.getSubmitter = function(client) {
}
});
};
module.exports.processProposal = function(chain, results, proposalType) {
module.exports.processProposal = function(tx_id, eventhub, chain, results, proposalType) {
var proposalResponses = results[0];
//logger.debug('deploy proposalResponses:'+JSON.stringify(proposalResponses));
var proposal = results[1];
Expand Down Expand Up @@ -92,7 +92,28 @@ module.exports.processProposal = function(chain, results, proposalType) {
proposal: proposal,
header: header
};
return chain.sendTransaction(request);

// set the transaction listener and set a timeout of 30sec
// if the transaction did not get committed within the timeout period,
// fail the test
var deployId = tx_id.toString();
var txPromise = new Promise((resolve, reject) => {
var handle = setTimeout(reject, config.waitTime);

eventhub.registerTxEvent(deployId, (tx) => {
logger.info('The chaincode'+(proposalType == 'deploy' ? proposalType: '')+' transaction has been successfully committed');
clearTimeout(handle);
eventhub.unregisterTxEvent(deployId);
resolve();
});
});

var sendPromise = chain.sendTransaction(request);
return Promise.all([sendPromise, txPromise]).then((results) => {
return results[0]; // the first returned value is from the 'sendPromise' which is from the 'sendTransaction()' call
}).catch((err) => {
logger.error('Failed to send transaction and get notifications within the timeout period. ' + err.stack ? err.stack : err);
});
} else {
logger.error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...');
throw new Error('Problems happened when examining proposal responses');
Expand Down
14 changes: 3 additions & 11 deletions examples/balance-transfer/invoke.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,13 @@ hfc.newDefaultKeyValueStore({
function(results) {
logger.info('Successfully obtained proposal responses from endorsers');

return helper.processProposal(chain, results, 'move');
return helper.processProposal(tx_id, eventhub, chain, results, 'move');
}
).then(
function(response) {
if (response.status === 'SUCCESS') {
var handle = setTimeout(() => {
logger.error('Failed to receive transaction notification within the timeout period');
process.exit(1);
}, parseInt(config.waitTime));

eventhub.registerTxEvent(tx_id.toString(), (tx) => {
logger.info('The chaincode transaction has been successfully committed');
clearTimeout(handle);
eventhub.disconnect();
});
logger.info('The chaincode transaction has been successfully committed');
process.exit();
}
}
).catch(
Expand Down

0 comments on commit 56c54ee

Please sign in to comment.