Cómo llamar a la función de mi contrato usando sendTransaction

Esta puede ser una pregunta muy básica, no sé por qué, pero no puedo encontrar la solución correcta a cómo puedo llamar al método de mi contrato usando sendTransaction. Tengo una transfer(address, uint256)función a la que quiero llamar usando sendTransactiony callTransaction. Tengo mi contrato compilado y tengo su abi y dirección. Ahora, ¿cómo puedo llamar a diferentes métodos del contrato usando sendTransaction?
Estaba leyendo la pregunta Sintaxis para llamar a los métodos de cambio de estado del contrato , y obtuve explicaciones para que la función tenga un solo parámetro, pero ¿qué pasa si tiene más de un parámetro de diferentes tipos, como aquí transfer()la función acepta 2 parámetros?

Respuestas (5)

Publicando la solución a mi propia pregunta para cualquiera que la necesite. Para llamar a una función de contrato desde 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 });

Nota : puede agregar otros campos en sendTransactionvalores similares, etcétera, lo he omitido por simplicidad para los usuarios nuevos.


A todos los usuarios que enfrentan desafíos con la firma de datos usando una clave privada. El pseudocódigo para firmar y enviar una transacción a contratar usando clave privada:

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})
      })
  })
}
esta es una excelente respuesta! funcionó para mí, recuerde poner las direcciones entre comillas.
no está claro qué está haciendo el método getData(). ¿Es un método incorporado o tiene que ser creado por el desarrollador que escribió el contrato?
No necesita implementar getDatael método. Se utiliza para recuperar el valor de los datos en el almacenamiento de estado. Puede leer más aquí: solidity.readthedocs.io/en/develop/…
¿Necesita especificar la IP del nodo Ethereum al que está enviando esta transacción?
Sí, tienes que especificar eso. Eso es mientras se hace la conexión a web3. Tenga en cuenta no exponer personalsobre RPC
@PrashantPrabhakarSingh getData()es la función que genera la inputvariable que se envía a evm.Call(). getData()no accede al almacenamiento en State, usa la ABI del contrato para generar la entrada, en particular, usando abi.Pack() ubicado en accounts/abi/abi.go . Pero en el ámbito de la transacción, esto inputse llamadata
¿Puede publicar una solución similar pero usando Infura y devolviendo la salida de la función de contrato, por favor?
@kitsune Se agregaron detalles para usar la misma solución con Infura. La salida depende del tipo de evento que elija que se active, como transacationHash, confirmación, recibo, error, etc. Vea el ejemplo aquí
@PrashantPrabhakarSingh gracias por su explicación, no tengo claro de dónde provienen los datos, ¿son de extraData?
sí. Déjame actualizar la respuesta también :)
let contract = new web3.eth.Contract(require( ./contracts/abi.json), contractAddress); let aventurerosLogParameters = [2236813]; let getData = contract.methods.adventurers_log.getData(función adventurersLogParameters); Muestra un error de sintaxis en "adventurersLogParameters".
@emeraldhieu No necesita escribir la palabra clave "función" antes de pasar los argumentos. let data = contract.methods.adventurers_log.getData(adventurersLogParameters)Deberia trabajar.
¿Podría actualizar su respuesta para web3 1.x? Tiene muchos cambios de última hora. Como mencionó emeraldhieu, se accede a un contrato a través de const contract = new web3.eth.Contract(abi, contractAddress); no hay getData, pero podemos hacerlo const call = universeContract.methods[methodName](callParameters), pero no estoy seguro de cómo firmar la llamada y enviarla correctamente.

Has probado:

// En JavaScript
myContract.transfer(otherAddress, aNumber, { from: myAccount });
// O
myContract.transfer.sendTransaction(otherAddress, aNumber, { from: myAccount });
// O
myContract.transfer.call(otherAddress, aNumber, { from: myAccount });

Ver toda la documentación .

correcto para web3.js, pero proporcione referencias a la documentación.

Mejorando la respuesta de @Prashant Prabhakar Singh:

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

a continuación, puede intentar obtener el recibo de la transacción utilizando

var receipt=web3.eth.getTransactionReceipt(trHash);

-Si obtiene el recibo como nulo, eso significa que su transacción no está minada, puede seguir intentándolo después de un tiempo hasta que obtenga los valores del recibo. -Puede verificar en el recibo que todo el gas provisto se usó o no, todo el gas usado indicó que su transacción falló

¿Hay algún código actualizado? No funciona en la última web3

Con las utilidades de Etherjs, los datos se pueden crear de la siguiente manera, que se pueden enviar directamente a la función sendTransaction.

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