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. Commented 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?– NulikCommented Oct 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/… Commented Oct 17, 2017 at 4:09 -
Do you need to specify the IP of the Ethereum node that you're sending this transaction to?– RagHavenCommented Jan 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 Commented 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 SCommented Sep 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
-
Any updated code is there?It not working on latest web3 Commented Feb 21, 2019 at 6:56
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)