2

The docs mention using

MyContract.methods.myFunction().call().then(console.log);

but methids methods I get the error then I get the error that the function is undefined.

The code below doesn't give errors but only returns null in the browser console.

$('#getKidneyIds').click(async () => {
  await contract.getKidneyIds(err => console.log(err));
});

This is my contract This is the javascript

3
  • 1
    Please share some of your contract code, or all of it, and maybe a deployed instance address.
    – Utgarda
    Commented Oct 9, 2018 at 20:58
  • Updated the post. Commented Oct 9, 2018 at 21:28
  • 2
    I generally use the format contract.getKidneyIds.call().then(function(id){whatever}). It should be adaptable to use await. Commented Oct 9, 2018 at 23:53

3 Answers 3

3

In a project I'm working on I was able to read a return parameter (a transaction "counter") I created in a smart contract by parsing the transaction log with these steps:

  1. Web3: Send method to smart contract which emits the counter. This will return the transaction log which is a flat JSON file. Get transaction hash code from: [https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#methods-mymethod-send][1]
  2. Read the logfile to get the parameter (in my case the counter) into a variable

Javascript code:

async function defineTransport (){
 const transportContract = new web3.eth.Contract(ABI, addressContract);
 ethereum.enable();

 /* STEP 1: Send method */
 var transactionLog = await transportContract.methods.defineTransport(temperatureBond)
      .send({from: address1});

 /* STEP 2: Parse logfile for variable "counter" */
 var counter = transactionCounter.events.newTransport.returnValues.counter;     
 document.getElementById("counter").innerHTML = `Transport number:&nbsp;<strong>${counter}</strong>`;
 console.log(`counter: ${counter}`);}

Simplified smart contract code:

pragma solidity>0.4.99<0.6.0;

contract TransportContracts{
     uint counter;
     uint temperatureBond;

     event newTransport(uint counter);

     function defineTransport (uint _temperatureBond) public {
         counter++;
         temperatureBond = _temperatureBond;
         emit newTransport(counter);}} 
2

You have a typo. You should remove one set of (): MyContract.methods.myFunction.call().then(console.log);.

This is the standard way of getting return values when you do not send a transaction.

When your function call was part of a transaction known by its hash txHash and you want the return value, you can still get it, but it is a bit more involved. If you are in control of the smart contract code, you may want to add events to make your life easier. But if you don't, here it goes:

  • First, you need to start Geth with the --rpcapi "debug" flag.
  • Second, you add a function to web3:
    
    web3.debug.traceTransaction = function(txHash, callback) {
        web3.currentProvider.sendAsync(
            {
                jsonrpc: "2.0",
                method: "debug_traceTransaction",
                params: [ txHash ],
                id: new Date().getTime()
            },
            (error, result) => {
                callback(error, error ? result : result.result);
            });
    };
    
  • Then you call it:
    
    web3.debug.traceTransaction(txHash, function(error, trace) {
        console.log(trace.returnValue);
    });
    

This trace.returnValue will be the unformatted, raw, return value.

See the full example repo here.

1

First off, take a look at the web3.js documentation on Contract methods. Next, make sure that you're working with an instance of your contract (e.g. MyContract = web3.eth.contract(abiArray).at(deployedAddress)). Assuming that's all set, it depends on whether your contract function is modifying state.

If you aren't modifying state, then the syntax described by @sfmiller940 ought to work fine: MyContract.getKidneyIds().then(function(ids){ //do your thing}). async/await might not be supported in your browser console, so try using the callback syntax instead.

If you are modifying state, then that's a different story. When you modify state, that has to be a transaction, so it isn't confirmed immediately -- no way to definitely get return values. The easiest way to get a return value from a transaction is to emit an event with the information you need -- that event and its arguments will be present in the logs of your transaction receipt:

MyContract.stateModifyingFunction(arg1, arg2, function(err, txHash){ let txReceipt = web3.eth.getTransactionReceipt(txHash); // txReceipt.logs contains an array of all events fired while calling your fxn });

2
  • I just get Uncaught TypeError: Cannot read property 'then' of undefined Mycontract .getKidneyIds((err) => { console.log(err); }) .then(ids => { console.log(ids); }); Commented Oct 10, 2018 at 4:08
  • Try using callbacks instead of the .then() syntax: MyContract .getKidneyIds((err, ids) => { console.log(ids); })
    – ohsully
    Commented Oct 10, 2018 at 15:28

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.