Hyperledger Composer - can't find transaction error - node.js

I am making a blockchain application using hyperledger composer and have written my cto, with on transaction, and the script file with no visible errors. However, when i try submit a transaction it returns this error: Error: Could not find any transactions to execute for org.evidence.net.evidenceDeposit.
Here is my CTO file:
namespace org.evidence.net
enum type {
o storage
o device
o physical
}
enum status {
o collected
o stored
o withdrawn
}
asset EvidenceItem identified by evidenceItemId {
o String evidenceItemId
o String caseNo
o type Type
o status Status
o String optionalHash optional
--> person Holder
}
abstract participant person identified by id {
o String id
o String firstName
o String lastName
}
participant Investigator extends person {
}
participant EvidenceManager extends person {
}
participant FRT extends person {
}
transaction evidenceDeposit {
--> EvidenceItem EvidenceItem
--> EvidenceManager EvidenceManager
}
event FirstDeposit {
o String evidenceItemId
o String id
}
And here is my script file:
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Transfer evidence from FRT to Evidence Manager
* #param (org.evidence.net.evidenceDeposit} tx - the evidenceDeposit transaction
* #transaction
*/
const NS = 'org.evidence.net';
async function evidenceDeposit(tx) {
// get asset registry for evidenceItem
const evidenceItemRegistry = await getAssetRegistry(NS + '.evidenceItem');
//Get participant registry for Evidence Manager
const EvidenceManagerRegistry = await getParticipantRegistry(NS + '.EvidenceManager');
const evidenceItem = await evidenceItemRegistry.get(tx.evidenceItem.getIdentifier());
//Make sure that the evidenceItem exists
if (!evidenceItem) {
throw new Error(' Evidence with id ${tx.evidenceItem.getIdentifier()} does not exist');
exit();
}
if (evidenceItem.status !== 'collected') {
throw new Error('Evidence with id ${tx.evidenceItem.getIdentifier()} is not in collected status');
}
// Get Evidence Manager ID
const EvidenceManagerID = tx.EvidenceManager.getIdentifier();
//Make sure Evidence Manager exists
const EvidenceManager = await EvidenceManagerRegistry.get(EvidenceManagerID);
if(!EvidenceManager) {
throw new Error('Evidence Manager with id ${EvidenceManagerID} does not exist');
}
//Update evidenceItem with new owner
tx.evidenceItem.holder = tx.EvidenceManager;
tx.evidenceItem.status = 'stored';
//Update the asset in the asset registry
await evidenceItemRegistry.update(tx.evidenceItem);
//Create deposit event
let FirstDepositEvent = getFactory().newEvent(NS, 'FirstDeposit');
FirstDepositEvent.evidenceItemId = tx.evidenceItem.evidenceItemId;
FirstDepositEvent.id = tx.EvidenceManager.id;
// Emit the Event
emit(FirstDepositEvent);
}
I have looked around and can't seem to find the problem. Any help is appreciated.

Please see the readme below as Hyperledger Composer has been deprecated for over a year.
https://github.com/hyperledger/composer/blob/master/README.md

Related

How to add two transaction function in a script file?

I am a beginner in hyperledger. My model.cto file has two transaction processor function one for transferring the car from manufacturer to the showroom and another one is for transferring the car from showroom to owner. model.cto file is given below,
namespace org.manufacturer.network
asset Car identified by carID {
o String carID
o String name
o String chasisNumber
--> Showroom showroom
--> Owner owner
}
participant Showroom identified by showroomID {
o String showroomID
o String name
}
participant Owner identified by ownerID {
o String ownerID
o String firstName
o String lastName
}
transaction Allocate {
--> Car car
--> Showroom newShowroom
}
transaction Purchase {
--> Showroom showroom
--> Owner newOwner
}
So, I want to add two functions in my script.js file, so that I could perform my transactions. My script.js file is given below
/**
* New script file
* #param {org.manufacturer.network.Allocate} allocate - allocating the car from manufacturer to showroom
* #param {org.manufacturer.network.Purchase} purchase - purchase the car by owner from showroom
* #transaction
*/
async function transferCar(allocate){
allocate.car.showroom = allocate.newShowroom;
let assetRegistry = await getAssetRegistry('org.manufacturer.network.Car');
await assetRegistry.update(allocate.car);
}
async function purchaseCar(purchase){
purchase.car.owner = purchase.newOwner;
let assetRegistry = await getAssetRegistry('org.manufacturer.network.Car');
await assetRegistry.update(purchase.car);
}
But the script file is giving error as Transaction processing function transferCar must have 1 function argument of type transaction.
How to add multiple transaction processor functions in a single script.js file?
Is that possible or I have to create two script.js file to handle the transactions?
That is not the correct way to define two transactions in the script.js file.
Your script.js file should be like this:
/**
* New script file
* #param {org.manufacturer.network.Allocate} allocate - allocating the car from manufacturer to showroom
* #transaction
*/
async function transferCar(allocate){
allocate.car.showroom = allocate.newShowroom;
let assetRegistry = await getAssetRegistry('org.manufacturer.network.Car');
await assetRegistry.update(allocate.car);
}
/**
* New script file
* #param {org.manufacturer.network.Purchase} purchase - purchase the car by owner from showroom
* #transaction
*/
async function purchaseCar(purchase){
purchase.car.owner = purchase.newOwner;
let assetRegistry = await getAssetRegistry('org.manufacturer.network.Car');
await assetRegistry.update(purchase.car);
}
This is how you can add more than one transaction in the script.js file.
I hope it will help you.

Composer Rest Server not returning what is annotated in model file

I have a Hyperledger Composer project where I want to return a generated id from a transaction. Here is the relevant portion of the model.cto file:
#returns(String)
transaction SetupGame {
o PlayerTotem[] players
}
And here is the transaction in script.js:
/**
* Setup Game transaction
* #param {org.pandemic.board.SetupGame} txData
* #returns {String} The string
* #transaction
*/
function setupGame(txData) {
let totems = txData.players;
return getAssetRegistry('org.pandemic.board.Board').then((registry) => {
let factory = getFactory();
let NS = 'org.pandemic.board';
let boardId = generateId();
let board = factory.newResource(NS, 'Board', boardId);
let boardCities = buildBoardCities(factory, NS);
board.cities = boardCities;
let infectionCards = buildInfectionCards(factory, NS);
board.infectionCards = shuffle(infectionCards);
let playerCards = buildPlayerCards(factory, NS);
board.playerCards = shuffle(playerCards);
let playerTotems = buildPlayerTotems(totems, factory, NS);
board.players = playerTotems;
return registry.add(board).then(() => {
return Promise.resolve(boardId);
});
});
}
I tried to follow the convention set forth in the Composer reference for how the JSDoc should be in script file here:
/**
* Setup Game transaction
* #param {org.pandemic.board.SetupGame} txData
* #returns [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/string) The string
* #transaction
*/
But when I had the #returns annotation set up like that, composer archive create would throw a malformed JSDoc error, so I changed it to #returns {String} The string
I expect to get the boardId back as the result of the transaction, but instead I just get the transaction back:
{
"$class": "org.pandemic.board.SetupGame",
"players": [
{
"$class": "org.pandemic.board.PlayerTotem",
"totemName": "Daniel",
"currentLocation": "Atlanta",
"role": "MEDIC",
"cards": [],
"actionsRemaining": "4"
}
],
"transactionId": "a87b071c78e00617430ca4e6e189a984feb41a8e2f5ae101e0d73eb4d172d927"
}
Please see this issue in GitHub about the same problem.
https://github.com/hyperledger/composer/issues/4245
The code provided by the contributer has been merged so it will appear in a Composer release soon. Possibly later this week or otherwise next week.

Error when submitting transaction

I have a little bit unusual problem. Following code works in online playground, but id doesn't work when i'm using generated API on rest server deployed locally. When trying to post transaction i get an error.
cto file:
namespace org.dps.track
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> BU owner
--> Item [] items optional
}
participant BU identified by buId{
o String buId
o String name
o String country
o String city
}
participant Assembler extends BU{
}
participant Manufacturer extends BU{
}
transaction Trade{
--> Item item
--> BU newOwner
}
enum status{
o IN_TRANSIT
o DEPARTURED
o DELIVERED
}
chaincode:
/**
* Sample transaction processor function.
* #param {org.dps.track.Trade } trade - the sample transaction instance.
* #transaction
*/
async function tradeCommodity(trade) {
const factory = getFactory();
trade.item.owner = trade.newOwner;
var list = [];
if (trade.item.items && trade.item.items.length > 0) {
trade.item.items.forEach((asset) => {
list.push(asset);
});
}
const assetRegistry = await getAssetRegistry('org.dps.track.Item');
// persist the state of the current ITEM
await assetRegistry.update(trade.item);
for (var i = 0; i < list.length; ++i) {
let res = await assetRegistry.get(list[i].getIdentifier());
res.owner = factory.newRelationship('org.dps.track', 'Assembler', trade.newOwner.getIdentifier());
// persist the state of the ITEM with new owner as a relationship
await assetRegistry.update(res);
}
}
When trying to post transaction via Rest API i get error:
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "Error trying invoke business network. Error: No valid responses from any peers.\nResponse from attempted peer comms was an error: Error: transaction returned with failure: Error: Could not find any functions to execute for transaction org.dps.track.Trade#e4764be8e037c7186774512860c0cde6d7eaed5c301ddf36c4c1ab560577861a",
"stack": "Error: Error trying invoke business network. Error: No valid responses from any peers.\nResponse from attempted peer comms was an error: Error: transaction returned with failure: Error: Could not find any functions to execute for transaction org.dps.track.Trade#e4764be8e037c7186774512860c0cde6d7eaed5c301ddf36c4c1ab560577861a\n at HLFConnection.invokeChainCode (/home/bryczek/.nvm/versions/node/v8.11.3/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:1002:30)\n at <anonymous>"
}
}
Has anyone an idea what is wrong? I would be really thankful for help.
Your problem is your model file, not the transaction code. You need Assembler not BU in the relationship field for Item and for Trade
Your asset should be:
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> Assembler owner
--> Item [] items optional
}
as Assembler is the resource class (not BU, which is an extended class - there is no registry for this).
Your transaction Trade should also reflect the same resource ie (not BU) :
transaction Trade{
--> Item item
--> Assembler newOwner
}
Other than that, it should work fine with your existing code (have tested it against a Fabric network, using the following example Trade transaction in my REST API, where previous owner was Assembler#1 and it changes related Items from the items array for Item #1)
{
"$class": "org.dps.track.Trade",
"item":"resource:org.dps.track.Item#1",
"newOwner":"resource:org.dps.track.Assembler#2"
}
I modified model file and now whe n trying to generate rest API i only get System(General business network methods), no Item, BU and Trade API, why is this happening?
cto:
/**
* New model file
*/
namespace org.dps.track
//asset section
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> BU owner
--> Item [] items optional
}
//participant section
participant BU identified by buId{
o String buId
o String name
o String country
o String city
o participantType type
}
//tranasaction section
transaction Trade{
-->Item item
-->BU newOwner
}
enum status {
o IN_TRANSIT
o DEPARTURED
o DELIVERED
}
enum participantType{
o Manufacturer
o Assembler
}
cc:
/**
* Sample transaction processor function.
* #param {org.dps.track.Trade } trade - the sample transaction instance.
* #transaction
*/
async function tradeCommodity(trade) {
const factory = getFactory();
trade.item.owner = trade.newOwner;
var list = [];
if (trade.item.items && trade.item.items.length > 0) {
trade.item.items.forEach((asset) => {
list.push(asset);
});
}
const assetRegistry = await getAssetRegistry('org.dps.track.Item');
// persist the state of the current ITEM
await assetRegistry.update(trade.item);
for (var i = 0; i < list.length; ++i) {
let res = await assetRegistry.get(list[i].getIdentifier());
res.owner = factory.newRelationship('org.dps.track', 'BU', trade.newOwner.getIdentifier());
// persist the state of the ITEM with new owner as a relationship
await assetRegistry.update(res);
}
}

while adding an asset to hyperledger got error that particular field is missing

i made a business network using hyperledger composer playground i want add an asset in the registry but while adding it is saying that t: Instance com.acn.hps.aops.ims.EvidenceDoc#4439 missing required field owner
.cto file
asset EvidenceDoc identified by evidenceId{
o String evidenceId
o Owner owner
}
participant Owner identified by AuthorityId{
o String AuthorityId
}
transaction addasset{
o EvidenceDoc evidenceDocJson
}
.qry file
.qry file
enter code here
query getOwnerbyId{
description: "Get owner of the evidence asset by its ID"
statement:
SELECT com.acn.hps.aops.ims.Superuser
WHERE (AuthorityId == _$AuthorityId)
}
logic.js file
/**
* #param {com.acn.hps.aops.ims.AddEvidence} addAsset
* #transaction
*/
function AddingEvidence(addAsset){
return getAssetRegistry('com.acn.hps.aops.ims.EvidenceDoc')
.then(function (AssetRegistry) {
// Get the factory for creating new asset instances.
var factory = getFactory();
var result = query('getOwnerbyId',
{AuthorityId:'1'/*addAsset.evidenceDocJson.owner.AuthorityId*/});
// Create the Evidence.
var evidence = factory.newResource('com.acn.hps.aops.ims', 'EvidenceDoc',
addAsset.evidenceDocJson.evidenceId);
evidence.owner = result[0]
// Add the asset to the asset registry.
return AssetRegistry.add(evidence);
})
}
I don't think the query is needed here. Try this.
.cto
namespace com.acn.hps.aops.ims
asset EvidenceDoc identified by evidenceId{
o String evidenceId
o Owner owner
}
participant Owner identified by AuthorityId{
o String AuthorityId
}
transaction addasset{
o EvidenceDoc evidenceDocJson
}
script.js
/**
* #param {com.acn.hps.aops.ims.addasset} addAsset
* #transaction
*/
function AddingEvidence(addAsset){
return getAssetRegistry('com.acn.hps.aops.ims.EvidenceDoc')
.then(function (AssetRegistry) {
// Get the factory for creating new asset instances.
var factory = getFactory();
// Create the Evidence.
var evidence = factory.newResource('com.acn.hps.aops.ims', 'EvidenceDoc',
addAsset.evidenceDocJson.evidenceId);
evidence.owner = addAsset.evidenceDocJson.owner
// Add the asset to the asset registry.
return AssetRegistry.add(evidence);
})
}
So your transaction name needs to match the param section ('addAsset' uppercase) in your transaction logic:
Also would suggest to pass owner as relationship to transaction
In your model
transaction addAsset {
o String evidenceId
--> Owner owner
}
In your transaction code (something like):
/**
* #param {com.acn.hps.aops.ims.addasset} addAsset
* #transaction
*/
function AddingEvidence(addAsset){
console.log('participant is ' + addAsset.owner.AuthorityID);
console.log('getCurrentparticipant is ' + getCurrentParticipant());
// Get the factory for creating new asset instances.
var factory = getFactory();
// Create the Evidence.
var evidence = factory.newResource('com.acn.hps.aops.ims', 'EvidenceDoc', addAsset.evidenceId);
evidence.owner.ID = addAsset.owner.AuthorityID;
return getAssetRegistry('com.acn.hps.aops.ims.EvidenceDoc')
.then(function (registry) {
return registry.add(evidence );
});
}

Hyperledger getParticipants

function Exchange(exchange){
// We do the actual exchange here:
// We first need to get both actual nodes:
var nodeIdFrom=exchange.nodeIdFrom;
var quantity =exchange.quantity;
var price = exchange.price;
var nodeIdTo =exchange.nodeIdTo;
return getParticipantRegistry('org.acme.mynetwork.Node')
.then(function(ParticipantRegistry){
ParticipantRegistry.get(nodeIdFrom)
.then(function(Participant){
Participant.Need=Participant.Need+quantity;
Participant.Balance_account=Participant.Balance_account+quantity*price;
return ParticipantRegistry.update(Participant);
});
});
I'm trying to execute a transaction defined as:
transaction Exchange{
o String nodeIdFrom
o String nodeIdTo
o Double quantity
o Double Price
}
To execute a transaction (we take money somewhere and put it somewhere else). With only the ids of the nodes as a parameter.
But right now that function does not work, you can execute it on the playground but my node is not modified.
Is it possible to apply a transaction without giving node as Node (node is a Participant).
it should work - here's an example (Using a fictitious sample 'Trader' Network and like you, I have defined 'qty' as a 'Double' in the Transaction model definition itself) of updating an Asset by a specific identifier (you're doing something similar - Participant by ID) and then - updating the asset's quantity using the Promises chain below. Suggest to use console.log() for outputs too when debugging.
So - given Transaction model:
transaction TraderById {
o String tradeId
o String tradingSymbol
o Double qty
}
and an Asset modeled as:
asset Commodity identified by tradingSymbol {
o String tradingSymbol
o String description
o String mainExchange
o Double quantity
--> Trader owner
}
you can update the Asset quantity ('quantity') as follows:
/**
*
* #param {org.acme.trading.TraderById} tradeById - the trade to be processed
* #transaction
*/
function TradeById(tradeById){
var commodityRegistry;
return getAssetRegistry('org.acme.trading.Commodity')
.then(function(registry){
commodityRegistry=registry;
return commodityRegistry.get(tradeById.tradingSymbol);
})
.then(function(result){
result.quantity-=tradeById.qty;
return commodityRegistry.update(result);
});
}

Resources