0

We have an event being triggered in a contract and our listeners on the client cant receive the return value.

https://gist.github.com/stupeters187/9529b54fe0d48ee606ad06ced6b16031

Update: metamask version 3.12.1 fixed the problem

2 Answers 2

1

Answer: your call to newbook() cannot return a value in javascript because it changes state.

Explanation: Truffle distinguishes between functions that change state and functions that only read the blockchain. Every time you change state, you have to broadcast it to the network so that the miners can incorporate the change into the next block. In addition, every node has to update their copy of the blockchain. This is why state changes cost gas. It's also why you shouldn't expect a return value from a function that changes state because the operation is asynchronous and could take between 1 and 2 blocks to complete.

On the other hand, function calls that only read the existing state of the blockchain do not need to bother any miners or nodes. In fact if you run your own node then you need only query your local copy of the blockchain to execute such a function. This is why read only functions cost no gas. To signal to truffle that you're calling a free function (i.e. one that doesn't change state), you use the keyword call after the function call. E.G. Suppose you have a solidity function called getBalance() then you'd write

instance.getBalance.call()

in javascript.

In your example above, you'd need to separate the state change and the retrieval into 2 steps as follows:

ParentContract.deployed().then((instance) => { instance.NewBook().watch((err, res) => { if (err) console.log(err); console.log('contract address', res.address); }); instance.newBook(weiPrice, issues, rateFormatted, {from: window.web3.eth.accounts[0]}).then((res) => { console.log('TX', res); return instance.getLatestBookId.call(); }).then(res=>{ //res will have the id in there somewhere. }) .catch((err) => console.log(err) ); });

This assumes you have a solidity function called getLatestBookId() that looks something like

function getLatestBookId returns (uint id){ //DO NOT PUT STATE CHANGE OPERATIONS }

Just bear in mind that mappings don't have a concept of length so getting the latest from a mapping isn't possible. You might need to rejig your datastructures a bit to make this possible.

Also remember that when I say state change, I refer to storage on the blockchain only. You can do what you want with local variables to your heart's (or solidity's strict heart's) content without incurring gas costs.

1

Metamask Version 3.12.1

*Please note the bottom update (this was our problem)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.