[Ethereum] NodeJS+web3 – contract method call not a function

ethereumjsnodejsweb3js

I trying to use nodejs with web3.js to do the full process of compile,delpoly and method call.After read the api here. I found the contract-methods.

myContractReturned.call().getCount();

But when I use it like this, I always got following error:

myContractReturned.call().getCount();
                   ^


TypeError: myContractReturned.call is not a function
    at Object.<anonymous> (/Users/admin/develop/blockchain_workspace/truffle3/main/web3InAction.js:70:20)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:420:7)
    at startup (bootstrap_node.js:139:9)
    at bootstrap_node.js:535:3

After search the internet,I found here that web3.js with javascript seems good.Did anybody have used nodejs with web3.js,any help will appreciate.Environment are as following:

$ node -v
v7.2.0
$ testrpc
EthereumJS TestRPC v3.0.3

Solidity source here:

pragma solidity ^0.4.0;

contract Calc{
  //simple storage
  uint count;

  //change state
  function add(uint a, uint b) returns(uint){
    count++;
    return a + b;
  }

  //no state change
  function getCount() constant returns (uint){
    return count;
  }
}

Full code as following:

let Web3 = require('web3');
let web3;

if (typeof web3 !== 'undefined') {
    web3 = new Web3(web3.currentProvider);
} else {
    // set the provider you want from Web3.providers
    web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}

let from = web3.eth.accounts[0];

let source = "pragma solidity ^0.4.0;contract Calc{ uint count;  function add(uint a, uint b) returns(uint){    count++;    return a + b;  }  function getCount() returns (uint){    return count;  }}";

let calcCompiled = web3.eth.compile.solidity(source);

console.log(calcCompiled);
console.log("ABI definition:");
console.log(calcCompiled["info"]["abiDefinition"]);

let abiDefinition = calcCompiled["info"]["abiDefinition"];
let calcContract = web3.eth.contract(abiDefinition);

let deployCode = calcCompiled["code"];

let deployeAddr = web3.eth.accounts[0];

let myContractReturned = calcContract.new({
    data: deployCode,
    from: deployeAddr
}, function(err, myContract) {
    if (!err) {

        if (!myContract.address) {
            console.log("contract deploy transaction hash: " + myContract.transactionHash) 

        } else {
            console.log("contract deploy address: " + myContract.address) 
        }
    }
});


console.log("returned deployed didn't have address now: " + myContractReturned.address);

//nodeJS?
myContractReturned.call().getCount();

Best Answer

A few things:

  1. Your function getCount should be constant (function getCount() constant returns (uint) should be constant. Otherwise

    a) you pay for gas and

    b) since you anyway don't change any state, this doesn't even make sense

    c) in web3.js you get a transaction hash back when calling a non-constant function and not a return value, I don't think you want that.

  2. You don't need call. You invoke a smart contract function call via myContractReturned.getCount(function(error, result) { console.log('result: ' + result + , error: ' + error); } ); as described

  3. You need to place this inside the callback handler function(err, myContract) { and check if you got an address. spoiler alert: the callback handler is being called twice: first time when you got a txHash, second time when your contract get mined! Check the example in the doc and basically check that you got an address. Only then proceed to interacting with the contract.

Related Topic