How to call my contract's function using sendTransaction

  • 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.

  • Posting solution to my own question for anyone who needs it. To call a contract function from geth:

    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(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')
    var web3 = new Web3();t
    web3.setProvider(new web3.providers.HttpProvider(web3RpcAddr))
    const yourContract = new web3.eth.Contract(yourContract.abi, yourContract.address)
    
    function sendCoin(toAddress, amount){
      let nonce = await web3.eth.getTransactionCount(fromAddress, 'pending')
      let extraData =  await yourContract.methods.transfer(toAddress, amount)
      let data = extraData.encodeABI()
      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)
      }
      var 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})
          })
      })
    } 
    

    this is an excellent answer! worked for me- remember to put the addresses in quotes.

    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?

    You need not implement `getData` method.It is used to retrieve the value of data in state storage. You can read more here: http://solidity.readthedocs.io/en/develop/contracts.html#visibility-and-getters

    Do you need to specify the IP of the Ethereum node that you're sending this transaction to?

    Yes, you need to specify that. That is while making the connection to web3. Keep in mind not to expose `personal` over RPC

    @PrashantPrabhakarSingh `getData()` is the function that generates `input` variable that is being sent to evm.Call(). `getData()` does not access the storage at State, it uses the ABI of the contract to generate the input, particulary, using abi.Pack() located in accounts/abi/abi.go . But in transaction scope , this `input` is called `data`

    Can you post a similar solution but using Infura and returning the contract function output, please?

    @kitsune Added details for using the same solution with Infura. The output depends on the type of event you choose to be triggered like transacationHash, confirmation, receipt, error etc. See example here

    @PrashantPrabhakarSingh thanks for your explanation, I have not clear with the data comes from, is it from the extraData?

    yes. Let me update the answer as well :)

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM