I have the following application code in my Hyperledger composer environment (My question only pertains to the RequestT
transaction as I am yet to write the Respond
transaction code):
Model Code (.cto)
/*
* Defines a data model for chama transaction
*/
namespace org.acme.account.chama
enum responseType {
o YES
o NO
}
enum requestType{
o DEPOSIT
o WITHDRAW
}
enum State {
o PENDING_AUTHORIZATION
o AUTHORIZED
o DECLINED
}
participant User identified by id {
o String id
o Double balance
o String firstName
o String lastName
}
asset Request identified by id {
o String id
o requestType type
o State state
o Double amount
o Response[] responses
--> User user
}
asset Account identified by id {
o String id
o requestType transaction
o Double amount
--> Request request
--> User user
}
asset Response identified by id {
o String id
o responseType reply
--> Request request
--> User user
}
transaction Respond {
o responseType reply
--> Request request
--> User user
}
transaction RequestT{
o Request request
}
JavaScript code (.js)
var getAccountBalance = function(){
var accountQuery = buildQuery("SELECT org.acme.account.chama.Account \
WHERE (transaction == _$type)");
return query(accountQuery, { type: "DEPOSIT" })
// sum up the amounts of the deposits made
.then(function(deposits){
var depositedAmount = 0;
deposits.forEach(function(deposit){
depositedAmount += deposit.amount;
});
return depositedAmount;
})
.then(function(depositedAmount){
return query(accountQuery, { type: "WITHDRAW" })
// sum up the amounts of the withdrawals made
.then(function(withdrawals){
var withdrawnAmount = 0;
withdrawals.forEach(function(withdrawal){
withdrawnAmount += withdrawal.amount;
});
return withdrawnAmount;
})
// find the account's balance
.then(function(withdrawnAmount){
return depositedAmount - withdrawnAmount;
});
});
};
/**
* @param {org.acme.account.chama.RequestT} requestT
* @transaction
*/
function request(requestT){
var request = requestT.request;
var user = request.user;
// get the account's balance
getAccountBalance()
.then(function(balance){
// reject deposit if user has insufficient funds
if ((user.balance < request.amount) && (request.type === "DEPOSIT")){
throw new Error("ERROR: User has insufficient funds!");
}
// reject withdrawal if account has insufficient funds
if ((balance < request.amount) && (request.type === "WITHDRAW")){
throw new Error("ERROR: Account has insufficient funds!");
}
console.log("CHECKING VALIDITY");
return balance;
})
// get the users' registry
.then(function(){
console.log("GETTING USERS' REGISTRY");
return getParticipantRegistry("org.acme.account.chama.User");
})
// get all the users
.then(function(userRegistry){
console.log("GETTING ALL USERS");
return userRegistry.getAll();
})
.then(function(users){
console.log("USERS:", users);
// authorize the request if the requester is the sole user
if (users.length === 1){
request.state = "AUTHORIZED";
}
console.log("GETTING REQUESTS' REGISTRY");
// get the requests' registry
return getAssetRegistry("org.acme.account.chama.Request")
// save the request
.then(function(requestRegistry){
return requestRegistry.add(request)
// get all of the requests
.then(function(){ return requestRegistry.getAll(); })
// obtain the total number of requests made
.then(function(requests){ console.log("REQUESTS", requests);return requests.length; });
});
})
.then(function(length){
console.log("LENGTH:", length);
// if the request has been authorized
if (request.state === "AUTHORIZED"){
console.log("GETTING ACCOUNT REGISTRY");
return getAssetRegistry("org.acme.account.chama.Account")
.then(function(accountRegistry){
// create new deposit transaction
var factory = getFactory();
var depositTransaction = factory.newResource(
"org.acme.account.chama", "Account", user.id + length);
depositTransaction.transaction = request.type;
depositTransaction.amount = request.amount;
depositTransaction.user = request.user;
depositTransaction.request = request;
console.log("DEPO T:", depositTransaction);
console.log("ADDING DEPOSIT REQUEST TO REGISTRY");
// save deposit transaction
return accountRegistry.add(depositTransaction);
})
// update user's balance
.then(function(){
console.log("GETTING USER REGISTRY");
return getParticipantRegistry("org.acme.account.chama.User")
.then(function(userRegistry){
if (request.type === "WITHDRAW"){
user.balance += request.amount;
} else if (request.type === "DEPOSIT"){
user.balance -= request.amount;
}
console.log("UPDATING USER IN REGISTRY");
return userRegistry.update(user);
});
});
}
return true;
})
.catch(function(error){
alert(error);
});
}
On the Hyperledger Composer online playground, I create a new user asset with the following data:
{
"$class": "org.acme.account.chama.User",
"id": "id:1001",
"balance": 1000,
"firstName": "ONE",
"lastName": "ONE"
}
Now when I submit a RequestT
transaction with the following data:
{
"$class": "org.acme.account.chama.RequestT",
"request": {
"$class": "org.acme.account.chama.Request",
"id": "id:8729",
"type": "DEPOSIT",
"state": "PENDING_AUTHORIZATION",
"amount": 500,
"responses": [],
"user": "resource:org.acme.account.chama.User#id:1001"
}
}
All promises seem to be running and resolve without an error as depicted in the following image:
But the assets added in the JavaScript code do not get persisted to the registry. Any ideas why?
Your promise chain is more complex than it needs to be, but the reason that nothing appears to work is you have forgotten a return statement before the getAccountBalance, so you just need