I'm trying to get a deployed HelloWorld contract to run within a node app. I want to run the call()
function to check it like this:
const deployed = helloWorldContract.new({
from: acct1,
data: compiled.contracts[':HelloWorld'].bytecode,
gas: 151972,
gasPrice: 5
}, (error, contract) => {
if(!error){
console.log(contract.displayMessage.call());
} else {
console.log(error);
}
});
Here is the contract for reference:
contract HelloWorld {
function displayMessage() public constant returns (string){
return "hello from smart contract - {name}";
}
}
When I try console.log(contract.displayMessage.call())
in the callback, that returns: TypeError: Cannot read property 'call' of undefined
, but, when I log console.log(contract.displayMessage)
it returns this:
{ [Function: bound ]
request: [Function: bound ],
call: [Function: bound ],
sendTransaction: [Function: bound ],
estimateGas: [Function: bound ],
getData: [Function: bound ],
'': [Circular] }
What am I doing wrong here? How can I run the function call
within the deployed contract?
I think your issue may be caused by the .new
constructor. I personally don't recommend using it because it is weird. Instead, you should deploy the bytecode as a standard transaction.
Anyways, if you look at the source code of .new
you'll see that the callback is actually called twice. It is completely non standard and as far as I know, undocumented.
The first time the callback is called after the transaction is sent, and the contract
object will have transactionHash
set.
The second time the callback is called, the contract
object should have the address
property set. This is what you want, because without the address property, you cannot invoke the contract methods.
In short, try this
const deployed = helloWorldContract.new({
from: acct1,
data: compiled.contracts[':HelloWorld'].bytecode,
gas: 151972,
gasPrice: 5
}, (error, contract) => {
if (error){
console.error(error);
} else {
console.log(contract);
if (contract.address) {
console.log(contract.displayMessage());
}
}
});
To deploy a contract without using .new
method, you first need to generate the contract bytecode and ABI. You can get it from using solc or online solidity compiler or whatever other way.
Then to deploy the contract you use web3.eth.sendTransaction
with data
parameter set to the bytecode, and an empty to
address. sendTransaction
will return you a transactionHash
, which you need to wait to be mined and confirmed. The easiest way to do this is through polling - a good starting point can be this method I wrote - https://gist.github.com/gaiazov/17c9fc7fdedf297e82386b74b34c61cd
If your contract takes constructor arguments, they are appended to the bytecode, e.g. data: bytecode + encodedConstructorArguments
.