From 9817007164f0f4e115fbbc9fcb16c4f5a72a2688 Mon Sep 17 00:00:00 2001 From: Ati G Date: Thu, 11 Oct 2018 16:50:34 +0530 Subject: [PATCH 1/2] Added a new function to query tuna History Signed-off-by: Ati G --- .../chaincode/tuna-app/tuna-chaincode.go | 70 +++++++++++++++ .../fabric-material/tuna-app/client/app.js | 19 +++++ .../tuna-app/client/index.html | 52 ++++++++++++ .../fabric-material/tuna-app/controller.js | 73 ++++++++++++++++ LFS171x/fabric-material/tuna-app/routes.js | 3 + .../tuna-app/src/queryTunaHistory.js | 85 +++++++++++++++++++ 6 files changed, 302 insertions(+) create mode 100644 LFS171x/fabric-material/tuna-app/src/queryTunaHistory.js diff --git a/LFS171x/fabric-material/chaincode/tuna-app/tuna-chaincode.go b/LFS171x/fabric-material/chaincode/tuna-app/tuna-chaincode.go index 4f52a5cc..cd949132 100644 --- a/LFS171x/fabric-material/chaincode/tuna-app/tuna-chaincode.go +++ b/LFS171x/fabric-material/chaincode/tuna-app/tuna-chaincode.go @@ -19,6 +19,7 @@ import ( "encoding/json" "fmt" "strconv" + "time" "github.com/hyperledger/fabric/core/chaincode/shim" sc "github.com/hyperledger/fabric/protos/peer" @@ -68,6 +69,8 @@ func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response return s.queryAllTuna(APIstub) } else if function == "changeTunaHolder" { return s.changeTunaHolder(APIstub, args) + } else if function == "queryTunaHistory" { + return s.queryTunaHistory(APIstub, args) } return shim.Error("Invalid Smart Contract function name.") @@ -222,6 +225,73 @@ func (s *SmartContract) changeTunaHolder(APIstub shim.ChaincodeStubInterface, ar return shim.Success(nil) } +/* + * The queryTunaHistory method * +Used to view the transcation history of one particular tuna +It takes one argument -- the key for the tuna in question + */ +func (s *SmartContract) queryTunaHistory(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { + + if len(args) != 1 { + return shim.Error("Incorrect number of arguments. Expecting 1") + } + + resultsIterator, err := APIstub.GetHistoryForKey(args[0]) + if err != nil { + return shim.Error(err.Error()) + } + defer resultsIterator.Close() + + // buffer is a JSON array containing QueryResults + var buffer bytes.Buffer + buffer.WriteString("[") + + bArrayMemberAlreadyWritten := false + for resultsIterator.HasNext() { + queryResponse, err := resultsIterator.Next() + if err != nil { + return shim.Error(err.Error()) + } + // Add comma before array members,suppress it for the first array member + if bArrayMemberAlreadyWritten == true { + buffer.WriteString(",") + } + + buffer.WriteString("{\"TxId\":") + buffer.WriteString("\"") + buffer.WriteString(queryResponse.TxId) + buffer.WriteString("\"") + + buffer.WriteString(", \"Value\":") + // if it was a delete operation on given key, then we need to set the + //corresponding value null. Else, we will write the response.Value + //as-is (as the Value itself a JSON marble) + if queryResponse.IsDelete { + buffer.WriteString("null") + } else { + buffer.WriteString(string(queryResponse.Value)) + } + + buffer.WriteString(", \"Timestamp\":") + buffer.WriteString("\"") + buffer.WriteString(time.Unix(queryResponse.Timestamp.Seconds, 0).String()) + buffer.WriteString("\"") + + buffer.WriteString(", \"IsDelete\":") + buffer.WriteString("\"") + buffer.WriteString(strconv.FormatBool(queryResponse.IsDelete)) + buffer.WriteString("\"") + + buffer.WriteString("}") + bArrayMemberAlreadyWritten = true + } + buffer.WriteString("]") + + fmt.Printf("- queryTunaHistory:\n%s\n", buffer.String()) + + return shim.Success(buffer.Bytes()) +} + /* * main function * calls the Start function diff --git a/LFS171x/fabric-material/tuna-app/client/app.js b/LFS171x/fabric-material/tuna-app/client/app.js index 4700061e..f6b3d828 100644 --- a/LFS171x/fabric-material/tuna-app/client/app.js +++ b/LFS171x/fabric-material/tuna-app/client/app.js @@ -66,6 +66,19 @@ app.controller('appController', function($scope, appFactory){ }); } + $scope.queryTunaHistory = function () { + + var id = $scope.tuna_id_history; + + appFactory.queryTunaHistory(id, function (data) { + + var array = []; + for (var i = 0; i < data.length; i++) { + array.push(data[i]); + } + $scope.query_tuna_history = array; + }); + } }); // Angular Factory @@ -106,6 +119,12 @@ app.factory('appFactory', function($http){ }); } + factory.queryTunaHistory = function (id, callback) { + $http.get('/get_tuna_history/' + id).success(function (output) { + callback(output) + }); + } + return factory; }); diff --git a/LFS171x/fabric-material/tuna-app/client/index.html b/LFS171x/fabric-material/tuna-app/client/index.html index e4c3fe8d..b6105f46 100644 --- a/LFS171x/fabric-material/tuna-app/client/index.html +++ b/LFS171x/fabric-material/tuna-app/client/index.html @@ -117,6 +117,58 @@
Error: Please enter a va +
+
+ + Enter a catch number: + +
+ + + + + + + + + + + + + + + + + + +
TxIDVesselLocationHolderTimestamp
{{tuna.TxId}}{{tuna.Value.vessel}}{{tuna.Value.location}}{{tuna.Value.holder}}{{tuna.Timestamp}}
+ +
+
+ + Enter a catch number: + +
+ + + + + + + + + + + + + + + + + + +
TxIDVesselLocationHolderTimestamp
{{tuna.TxId}}{{tuna.Value.vessel}}{{tuna.Value.location}}{{tuna.Value.holder}}{{tuna.Timestamp}}
+
Success! Tx ID: {{create_tuna}}
diff --git a/LFS171x/fabric-material/tuna-app/controller.js b/LFS171x/fabric-material/tuna-app/controller.js index a7f83a05..edefb802 100644 --- a/LFS171x/fabric-material/tuna-app/controller.js +++ b/LFS171x/fabric-material/tuna-app/controller.js @@ -468,6 +468,79 @@ return{ res.send("Error: no tuna catch found"); }); + }, + get_tuna_history: function (req, res) { + + var fabric_client = new Fabric_Client(); + var key = req.params.id + + // setup the fabric network + var channel = fabric_client.newChannel('mychannel'); + var peer = fabric_client.newPeer('grpc://localhost:7051'); + channel.addPeer(peer); + + // + var member_user = null; + var store_path = path.join(os.homedir(), '.hfc-key-store'); + console.log('Store path:' + store_path); + var tx_id = null; + + // create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting + Fabric_Client.newDefaultKeyValueStore({ + path: store_path + }).then((state_store) => { + // assign the store to the fabric client + fabric_client.setStateStore(state_store); + var crypto_suite = Fabric_Client.newCryptoSuite(); + // use the same location for the state store (where the users' certificate are kept) + // and the crypto store (where the users' keys are kept) + var crypto_store = Fabric_Client.newCryptoKeyStore({ + path: store_path + }); + crypto_suite.setCryptoKeyStore(crypto_store); + fabric_client.setCryptoSuite(crypto_suite); + + // get the enrolled user from persistence, this user will sign all requests + return fabric_client.getUserContext('user1', true); + }).then((user_from_store) => { + if (user_from_store && user_from_store.isEnrolled()) { + console.log('Successfully loaded user1 from persistence'); + member_user = user_from_store; + } else { + throw new Error('Failed to get user1.... run registerUser.js'); + } + + // queryTuna - requires 1 argument, ex: args: ['4'], + const request = { + chaincodeId: 'tuna-app', + txId: tx_id, + fcn: 'queryTunaHistory', + args: [key] + }; + + // send the query proposal to the peer + return channel.queryByChaincode(request); + }).then((query_responses) => { + console.log("Query has completed, checking results"); + console.log("Full result" + query_responses); + // query_responses could have more than one results if there multiple peers were used as targets + if (query_responses && query_responses.length == 1) { + if (query_responses[0] instanceof Error) { + console.error("error from query = ", query_responses[0]); + res.send("Could not locate tuna") + + } else { + console.log("Response is ", query_responses[0].toString()); + res.send(query_responses[0].toString()) + } + } else { + console.log("No payloads were returned from query"); + res.send("Could not locate tuna") + } + }).catch((err) => { + console.error('Failed to query successfully :: ' + err); + res.send("Could not locate tuna") + }); } } diff --git a/LFS171x/fabric-material/tuna-app/routes.js b/LFS171x/fabric-material/tuna-app/routes.js index 59ebce1c..09a8b660 100644 --- a/LFS171x/fabric-material/tuna-app/routes.js +++ b/LFS171x/fabric-material/tuna-app/routes.js @@ -16,4 +16,7 @@ module.exports = function(app){ app.get('/change_holder/:holder', function(req, res){ tuna.change_holder(req, res); }); + app.get('/get_tuna_history/:id', function (req, res) { + tuna.get_tuna_history(req, res); + }); } diff --git a/LFS171x/fabric-material/tuna-app/src/queryTunaHistory.js b/LFS171x/fabric-material/tuna-app/src/queryTunaHistory.js new file mode 100644 index 00000000..bdc61190 --- /dev/null +++ b/LFS171x/fabric-material/tuna-app/src/queryTunaHistory.js @@ -0,0 +1,85 @@ +'use strict'; +/* +* SPDX-License-Identifier: Apache-2.0 + +Hyperledger Fabric Sample Query Program for tuna-app: Chaincode Invoke + +This code is based on code written by the Hyperledger Fabric community. +Original code can be found here: https://github.com/hyperledger/fabric-samples/blob/release/fabcar/query.js + */ + +var Fabric_Client = require('fabric-client'); +var path = require('path'); +var util = require('util'); +var os = require('os'); + +var fabric_client = new Fabric_Client(); +var key = req.params.id + +// setup the fabric network +var channel = fabric_client.newChannel('mychannel'); +var peer = fabric_client.newPeer('grpc://localhost:7051'); +channel.addPeer(peer); + +// +var member_user = null; +var store_path = path.join(os.homedir(), '.hfc-key-store'); +console.log('Store path:' + store_path); +var tx_id = null; + +// create the key value store as defined in the fabric-client/config/default.json 'key-value-store' setting +Fabric_Client.newDefaultKeyValueStore({ + path: store_path +}).then((state_store) => { + // assign the store to the fabric client + fabric_client.setStateStore(state_store); + var crypto_suite = Fabric_Client.newCryptoSuite(); + // use the same location for the state store (where the users' certificate are kept) + // and the crypto store (where the users' keys are kept) + var crypto_store = Fabric_Client.newCryptoKeyStore({ + path: store_path + }); + crypto_suite.setCryptoKeyStore(crypto_store); + fabric_client.setCryptoSuite(crypto_suite); + + // get the enrolled user from persistence, this user will sign all requests + return fabric_client.getUserContext('user1', true); +}).then((user_from_store) => { + if (user_from_store && user_from_store.isEnrolled()) { + console.log('Successfully loaded user1 from persistence'); + member_user = user_from_store; + } else { + throw new Error('Failed to get user1.... run registerUser.js'); + } + + // queryTuna - requires 1 argument, ex: args: ['4'], + const request = { + chaincodeId: 'tuna-app', + txId: tx_id, + fcn: 'queryTunaHistory', + args: [key] + }; + + // send the query proposal to the peer + return channel.queryByChaincode(request); +}).then((query_responses) => { + console.log("Query has completed, checking results"); + console.log("Full result" + query_responses); + // query_responses could have more than one results if there multiple peers were used as targets + if (query_responses && query_responses.length == 1) { + if (query_responses[0] instanceof Error) { + console.error("error from query = ", query_responses[0]); + res.send("Could not locate tuna") + + } else { + console.log("Response is ", query_responses[0].toString()); + res.send(query_responses[0].toString()) + } + } else { + console.log("No payloads were returned from query"); + res.send("Could not locate tuna") + } +}).catch((err) => { + console.error('Failed to query successfully :: ' + err); + res.send("Could not locate tuna") +}); \ No newline at end of file From 8983452fd3d55782941ba0913ae352a799512aae Mon Sep 17 00:00:00 2001 From: Ati G Date: Thu, 11 Oct 2018 16:56:23 +0530 Subject: [PATCH 2/2] Added a new function to query tuna History - removed extra history from view Signed-off-by: Ati G --- .../tuna-app/client/index.html | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/LFS171x/fabric-material/tuna-app/client/index.html b/LFS171x/fabric-material/tuna-app/client/index.html index b6105f46..755b2d78 100644 --- a/LFS171x/fabric-material/tuna-app/client/index.html +++ b/LFS171x/fabric-material/tuna-app/client/index.html @@ -124,32 +124,6 @@
Error: Please enter a va
- - - - - - - - - - - - - - - - - -
TxIDVesselLocationHolderTimestamp
{{tuna.TxId}}{{tuna.Value.vessel}}{{tuna.Value.location}}{{tuna.Value.holder}}{{tuna.Timestamp}}
- -
-
- - Enter a catch number: - -
-