Contract Function Call – Using sendTransaction in Solidity

contract-developmentweb3js

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.

Best Answer

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})
      })
  })
}