Skip to content

Instantly share code, notes, and snippets.

@horeaporutiu
Last active July 9, 2023 11:40
Show Gist options
  • Save horeaporutiu/a75704ceb85b2be032d81e1498fd0905 to your computer and use it in GitHub Desktop.
Save horeaporutiu/a75704ceb85b2be032d81e1498fd0905 to your computer and use it in GitHub Desktop.
a Hyperleger Smart Contract that is able to retrieve the history of updates for a certain key
'use strict';
const { Contract } = require('fabric-contract-api');
class MyContract extends Contract {
//add a member along with their email, name, address, and number
async addMember(ctx, email, name, address, phoneNumber) {
let member = {
name: name,
address: address,
number: phoneNumber,
email: email
};
await ctx.stub.putState(email, Buffer.from(JSON.stringify(member)));
return JSON.stringify(member);
}
// look up data by key
async query(ctx, key) {
console.info('querying for key: ' + key);
let returnAsBytes = await ctx.stub.getState(key);
let result = JSON.parse(returnAsBytes);
return JSON.stringify(result);
}
async retrieveHistory(ctx, key) {
console.info('getting history for key: ' + key);
let iterator = await ctx.stub.getHistoryForKey(key);
let result = [];
let res = await iterator.next();
while (!res.done) {
if (res.value) {
console.info(`found state update with value: ${res.value.value.toString('utf8')}`);
const obj = JSON.parse(res.value.value.toString('utf8'));
result.push(obj);
}
res = await iterator.next();
}
await iterator.close();
return result;
}
}
module.exports = MyContract;
{
"name": "jan22Test",
"version": "0.0.9",
"description": "My Smart Contract",
"main": "index.js",
"engines": {
"node": ">=8",
"npm": ">=5"
},
"scripts": {
"lint": "eslint .",
"pretest": "npm run lint",
"test": "nyc mocha --recursive",
"start": "fabric-chaincode-node start"
},
"engineStrict": true,
"author": "John Doe",
"license": "Apache-2.0",
"dependencies": {
"fabric-contract-api": "1.4.0",
"fabric-shim": "1.4.0"
},
"devDependencies": {
"chai": "^4.2.0",
"eslint": "^5.9.0",
"mocha": "^5.2.0",
"nyc": "^13.1.0",
"sinon": "^7.1.1",
"sinon-chai": "^3.3.0"
},
"nyc": {
"exclude": [
"coverage/**",
"test/**"
],
"reporter": [
"text-summary",
"html"
],
"all": true,
"check-coverage": true,
"statements": 100,
"branches": 100,
"functions": 100,
"lines": 100
}
}
@jackyhieu1211-hn
Copy link

@horeaporutiu hello admin. When I get list history. I received the last 1 transaction missing.
Example.
Change status A -> change status B -> change status C. But when I get. I received transaction of A and B. not C
Change status A -> change status B -> change status C -> Change status D. I received transaction of A, B, C. not D
Why?. Please help me fix it.

app.js

app.get("/queryHistorySingleCar", (req, res) => {
  console.log(req.query.key);
  network.queryHistorySingleCar(req.query.key).then(response => {
    let carsRecord = JSON.parse(response);
    res.send(carsRecord);
  });
});

network.js

exports.queryHistorySingleCar = async function(key) {
  let response = {};
  try {
    console.log("queryHistorySingleCar");

    // Create a new file system based wallet for managing identities.
    const walletPath = path.join(process.cwd(), "/wallet");
    const wallet = new FileSystemWallet(walletPath);
    console.log(`Wallet path: ${walletPath}`);

    // Check to see if we've already enrolled the user.
    const userExists = await wallet.exists(userName);
    if (!userExists) {
      console.log(
        "An identity for the user " + userName + " does not exist in the wallet"
      );
      console.log("Run the registerUser.js application before retrying");
      response.error =
        "An identity for the user " +
        userName +
        " does not exist in the wallet. Register " +
        userName +
        " first";
      return response;
    }

    // Create a new gateway for connecting to our peer node.
    const gateway = new Gateway();
    await gateway.connect(ccp, {
      wallet,
      identity: userName,
      discovery: gatewayDiscovery
    });

    // Get the network (channel) our contract is deployed to.
    const network = await gateway.getNetwork("mychannel");

    // Get the contract from the network.
    const contract = network.getContract("fabcar");

    // Evaluate the specified transaction.
    // queryCar transaction - requires 1 argument, ex: 'querySingleCar('CAR0')'
    console.log(key);
    const result = await contract.evaluateTransaction("queryHistorySingleCar", key);
    //console.log(`Transaction has been evaluated, result is: ${result.toString()}`);

    return result;
  } catch (error) {
    console.error(`Failed to evaluate transaction: ${error}`);
    response.error = error.message;
    return response;
  }
};

smartcontract.js

async queryHistorySingleCar(ctx, key) {
  console.info('getting history for key: ' + key);
  let iterator = await ctx.stub.getHistoryForKey(key);
  let result = [];
  let res = await iterator.next();
  while (!res.done) {
    if (res.value) {
      console.info(`found state update with value: ${res.value.value.toString('utf8')}`);
      const obj = JSON.parse(res.value.value.toString('utf8'));
      result.push(obj);
    }
    res = await iterator.next();
  }
  await iterator.close();
  return result;
}

@jackyhieu1211-hn
Copy link

Oh. sorry. I think history includes the latest and old deals. But I was wrong. History is just old deals. There is no latest.
This is code worked good. thank you @horeaporutiu

@sanjivrt2000
Copy link

Hi, using ctx.stub.getHistoryForKey(ctx, key) i am not being able to get transaction id. On changing owner it gives output as :
[
{
"color":"black",
"make":"Tesla",
"model":"S",
"owner":"Adriana",
"docType":"car"
},
{
"color":"black",
"docType":"car",
"make":"Tesla",
"model":"S",
"owner":"Sanjiv Ranjit"
}
]

How shall i retrieve transaction id as well?

Regards,
Sanjiv Ranjit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment