This may be a very basic question, I don't know why but I am unable to find correct solution to how can I call my contract's method using sendTransaction
. I have a transfer(address, uint256)
function which I want to call using sendTransaction
and callTransaction
. I have my contract compiled and I have it's abi and address. Now, how can I call different metrhods of the contract using sendTransaction
?
I was reading the question Syntax for calling contract state changing methods, and I got explanations for function having single parameter but what if it has more than a parameter of different types, like here transfer()
function accepts 2 parameters.
5 Answers
Posting solution to my own question for anyone who needs it.
To call a contract function from geth
:
const contractAbi = eth.contract(AbiOfContract);
const myContract = contractAbi.at(contractAddress);
// suppose you want to call a function named myFunction of myContract
const getData = myContract.myFunction.getData(function_parameters);
// finally pass this data parameter to send Transaction
web3.eth.sendTransaction({ to:Contractaddress, from:Accountaddress, data: getData });
Note: You can add other fields in sendTransaction
like value etcetera, I have skipped that for simplicity to new use users.
To all the users who face challanges with signing data using private key. The pseudo code for signing and sending a transaction to contract using private key:
const Tx = require('ethereumjs-tx')
const web3 = new Web3()
web3.setProvider(new web3.providers.HttpProvider(web3RpcAddr))
const yourContract = new web3.eth.Contract(yourContract.abi, yourContract.address)
function sendCoin(toAddress, amount) {
const nonce = await web3.eth.getTransactionCount(fromAddress, 'pending')
const extraData = await yourContract.methods.transfer(toAddress, amount)
const data = extraData.encodeABI()
const txObj = {
from: adminAddress,
to: yourContractAddress,
data,
value: '0',
gas: gasSent, // calculation of gas and gas Price is skipped here
gasPrice: gasPriceSent,
privKey: adminPvtKey,
nonce
}
let signedTx = await signTx(txObj)
signedTx = "0x" + signedTx.serialize().toString('hex')
await submitSignedTx(signedTx)
}
async function signTx(payload) {
let { from, to, data, value, gas, gasPrice, privKey, nonce } = payload
let txParams = {
to,
data,
value: web3.utils.toHex(value),
gasPrice: web3.utils.toHex(gasPrice),
gas: web3.utils.toHex(gas),
nonce: web3.utils.toHex(nonce)
}
const tx = new Tx(txParams)
privKey = await _validatePrivKey(privKey)
privKey = new Buffer(privKey, 'hex')
tx.sign(privKey)
privKey = null
return tx
}
async function submitSignedTx(serializedTx) {
return new Promise((fullfill, reject) => {
web3.eth.sendSignedTransaction(serializedTx)
.on('transactionHash', txHash => {
l.info('transaction sent. hash =>', txHash)
return fullfill({success: true, txHash : txHash})
})
.on('error', e => {
// console.log('unable to send tx', e)
l.error(logmsg, e.message)
return fullfill({success: false, message: e})
})
})
}
-
1this is an excellent answer! worked for me- remember to put the addresses in quotes. Jul 31, 2017 at 21:29
-
it is not clear what is getData() method doing. is it a builtin method or has to be created by the developer who wrote the contract?– NulikOct 16, 2017 at 15:24
-
You need not implement
getData
method.It is used to retrieve the value of data in state storage. You can read more here: solidity.readthedocs.io/en/develop/… Oct 17, 2017 at 4:09 -
Do you need to specify the IP of the Ethereum node that you're sending this transaction to?– RagHavenJan 20, 2018 at 4:27
-
Yes, you need to specify that. That is while making the connection to web3. Keep in mind not to expose
personal
over RPC Jan 20, 2018 at 6:43
Have you tried:
// In Javascript myContract.transfer(otherAddress, aNumber, { from: myAccount }); // Or myContract.transfer.sendTransaction(otherAddress, aNumber, { from: myAccount }); // Or myContract.transfer.call(otherAddress, aNumber, { from: myAccount });
-
correct for web3.js, but please provide references to the documentation.– Paul SSep 20, 2016 at 18:19
Improving @Prashant Prabhakar Singh answer:
var contractAbi = eth.contract(AbiOfContract);
var myContract = contractAbi.at(contractAddress);
// suppose you want to call a function named myFunction of myContract
var getData = myContract.myFunction.getData("1","boy");//just parameters you pass to myFunction
// And that is where all the magic happens
web3.eth.sendTransaction({
to:ContractAddress,//contracts address
from:web3.eth.accounts[0],
data: getData,
value: web3.toWei(EtherAmount, 'ether')//EtherAmount=>how much ether you want to move
},function (error, result){
if(!error){
console.log(result);//transaction successful
} else{
console.log(error);//transaction failed
}
});
var abi=[//your abi array];
var contractAddress = "//your contract address";
var contract = web3.eth.contract(abi).at(contractAddress);
contract.functionName.sendTransaction(parameter_1,parameter_2,parameter_n,{
from:web3.eth.accounts[0],
gas:4000000},function (error, result){ //get callback from function which is your transaction key
if(!error){
console.log(result);
} else{
console.log(error);
}
});
you can then try to get transaction receipt by using
var receipt=web3.eth.getTransactionReceipt(trHash);
-if you get receipt as null that means your transaction is not mined, you can keep trying after some time until you get receipt values. -You can check in the receipt that all the provided gas is used or not, all gas used indicated your transaction is failed
With Etherjs utilities data can be created as follows which can be directly sent to sendTransaction function.
//ethereum provider instance creation
let ethereum = window.ethereum;
// Request account access if needed
await ethereum.enable();
let provider = new ethers.providers.Web3Provider(ethereum);
//Get method id (transfer function method id)
const METHOD_ID = "0x05555555"; //replace with actual transfer function method id
//creating encoded data
let encodedData = ethers.utils.hexConcat([
METHOD_ID,
ethers.utils.defaultAbiCoder.encode(
["address", "uint256"],
[receiverAddress, amount] //replace with receiver and amount to be transferred
),
]);
//Create raw transaction param
const param = {
from: sender, //replace with sender wallet address
to: ERC20_CONTRACT_ADDRESS, //replace with your contract address
data: encodedData
};
//Send Transaction using etherjs
const transactionHash = await provider.send('eth_sendTransaction', params)