¿Cómo declarar claves privadas al usar node.js y ethereum para ejecutar un contrato?

Tengo que ejecutar node.js para ejecutar contratos inteligentes. Mi pregunta es sobre las llaves.

He visto esto en los documentos:

1. Código para firmar
2. Código a ejecutar

Pero no estoy seguro de cómo se combinan los dos. ¿Alguien podría aclarar esto?

Tengo un contrato implementado que tiene esta función:

function addBonus( string bonusType, uint bonusTarget, uint bonusEndYear,
        uint bonoEndMonth, uint bonoEndDay,
        string bonusToken, uint bonusAmount, string bonusName, uint ineq ) public {
// Procesando
}

De los documentos -

var Tx = require('ethereumjs-tx');
var llave privada = nuevo búfer ('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex')
var rawTx = {  
una vez: '0x00',  
precio del gas: '0x09184e72a000',   
límite de gas: '0x2710',  
a: '0x00000000000000000000000000000000000000000',
valor: '0x00',   
datos: '0x7f74657374320000000000000000000000000000000000000000000000000000000600057' }
var tx = nuevo Tx(rawTx);
tx.sign(clave privada);
var serializedTx = tx.serialize();  
web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {  
si (! error)    
consola.log(hash); // "0x7f9fade1c0d57a7af66ab4ead79fade1c0d57a7af66ab4ead7c2c2eb7b11a91385" });

Y esto -

// contrato abi
var abi = [{
    nombre: 'miMetodoConstante',
    tipo: 'función',
    constante: cierto,
    entradas: [{ nombre: 'a', tipo: 'cadena' }],
    salidas: [{nombre: 'd', tipo: 'cadena' }]
}, {
    nombre: 'myStateChangingMethod',
    tipo: 'función',
    constante: falso,
    entradas: [{ nombre: 'a', tipo: 'cadena' }, { nombre: 'b', tipo: 'int' }],
    salidas: []
}, {
    nombre: 'miEvento',
    tipo: 'evento',
    entradas: [{nombre: 'a', tipo: 'int', indexado: verdadero},{nombre: 'b', tipo: 'bool', indexado: falso}]
}];
// creación del objeto del contrato
var MiContrato = web3.eth.contrato(abi);
// iniciar contrato para una dirección
var myContractInstance = MyContract.at('0xc4abd0339eb8d57087278718986382264244252f');
// llamar a la función constante
var result = myContractInstance.myConstantMethod('myParam');
consola.log(resultado) // '0x25434534534'
// enviar una transacción a una función
myContractInstance.myStateChangingMethod('someParam1', 23, {value: 200, gas: 2000});
// estilo de mano corta
web3.eth.contract(abi).at(dirección).myAwesomeMethod(...);
// crear filtro
var filter = myContractInstance.myEvent({a: 5}, función (error, resultado) {
 si (! error)
   consola.log(resultado);
   /*
   {
       dirección: '0x8718986382264244252fc4abd0339eb8d5708727',
       temas: "0x12345678901234567890123456789012", "0x000000000000000000000000000000000000000000000000000000000000000005",
       datos: "0x000000000000000000000000000000000000000000000000000000000000000001",
       ...
   }
   */
});

Supongo que tenemos que combinar estas dos ideas expresadas de alguna manera. No puedo ver ninguna clave privada en el segundo ejemplo y el primero no tiene ningún ejemplo de ejecución de un contrato.

Tu pregunta es un poco confusa, no estoy seguro exactamente de lo que estás preguntando. El fragmento que publicó que involucraba una clave privada realizó una transacción para crear un contrato, mientras que el segundo fragmento realizó una transacción para llamar a una función en el contrato. Su segundo fragmento también usó web3, que tiene administración de cuentas integrada. Cuando llamaste .myStateChangingMethod, normalmente tendrías que incluir una fromdirección en ese último objeto. web3 dedujo que probablemente quería usar la primera dirección en el almacén de claves y obtuvo automáticamente su clave privada para firmar la transacción.
No estoy seguro de cómo usar web3 sin metamask. Usted afirma que tiene su propia aprobación, pero eso es cuando usa metamask, por ejemplo. Para usar web3, necesitamos firmar txns de alguna manera o proporcionar las claves privadas. Eso es lo que estoy preguntando.
Consulte la documentación de web3 para web.eth.accounts. Todo lo que hace Metamask es asociar un archivo de billetera con su cuenta de Google (IIRC). Si ya tiene una billetera con su dirección y claves, puede cargar la billetera y almacenará esas claves. También puede llamar wallet.createy creará una nueva billetera en la memoria que luego podrá guardar. Web3 se encarga de obtener las claves y firmar, solo necesita decirle dónde están las claves: MetaMask lo ha hecho por usted en el pasado.
Lo resolví ahora. Publicaré más tarde. Es mucho más complejo que revisar los documentos de web3.
Desearía haber entendido mejor tu problema y haberte ayudado más, ¡pero me alegra saber que lo solucionaste!
el problema es sobre autorizar los txns. Publicaré más tarde el código.

Respuestas (3)

   var infuraApiKey =process.env.INFURA_API_KEY;
  // var privateKey = process.env.PRIVATE_KEY;

   var web3js = new web3(new web3.providers.HttpProvider("https://kovan.infura.io/v3/"+infuraApiKey));

   web3js.eth.defaultAccount = myAddress;
   var privateKey=new Buffer(process.env.PRIVATE_KEY, 'hex');

//   var toAddress = 'ADRESS_TO_SEND_TRANSACTION';

   //contract abi is the array that you can get from the ethereum wallet or etherscan
   var contractABI =bonusABI;
   var contractAddress =bonusAddress;
   //creating contract object
   var contract =  web3js.eth.contract(contractABI).at(contractAddress);
   var count;
   var nounce;
   var errcode="";
   web3js.eth.getTransactionCount(myAddress, function(err, result) {
        nounce=result;
        var nounceHex = web3js.toHex(nounce);

        var rawTransaction = {"from":myAddress,
        "gasPrice":web3js.toHex(2*1e9),
        "gasLimit":web3js.toHex(920000),
        "to":contractAddress,
        "data":contract.addBonus.getData(bonusType, target, year, month, day, token, bonus, bonusName, ineq),
        "nonce":nounceHex}

        var transaction = new Tx(rawTransaction);
        transaction.sign(privateKey);

        var serializedTx = transaction.serialize();
        web3js.eth.sendRawTransaction('0x'+serializedTx.toString('hex'), function(err1, hash) {
           if (!err1) {
               errcode=hash;
          }
           else
               errcode=err1;
        });
  })

puede agregarlo a su archivo .env si solo está utilizando una cuenta para transferir fondos, o puede almacenarlo en forma cifrada en una base de datos https://www.npmjs.com/package/bcrypt .

Existe una forma mejor y más sencilla de firmar y ejecutar la función de contrato inteligente. Aquí su función es addBonus.

En primer lugar, crearemos la instancia de contrato inteligente:

 const createInstance = () => {
  const bscProvider = new Web3(
    new Web3.providers.HttpProvider(config.get('bscRpcURL')),
  );
  const web3BSC = new Web3(bscProvider);
  const transactionContractInstance = new web3BSC.eth.Contract(
    transactionSmartContractABI,
    transactionSmartContractAddress,
  );
  return { web3BSC, transactionContractInstance };
};

Ahora crearemos una nueva función para iniciar sesión y ejecutar la función addBonus

   const updateSmartContract = async (//parameters you need) => {
     try {
    const contractInstance = createInstance();
// need to calculate gas fees for the addBonus
    const gasFees =
      await contractInstance.transactionContractInstance.methods
        .addBonus(
         // all the parameters
        )
        .estimateGas({ from: publicAddress_of_your_desired_wallet });
   const tx = {
      // this is the address responsible for this transaction
      from: chainpalsPlatformAddress,
      // target address, this could be a smart contract address
      to: transactionSmartContractAddress,
      // gas fees for the transaction
      gas: gasFees,
      // this encodes the ABI of the method and the arguments
      data: await contractInstance.transactionContractInstance.methods
        .addBonus(
       // all the parameters
        )
        .encodeABI(),
    };
  // sign the transaction with a private key. It'll return messageHash, v, r, s, rawTransaction, transactionHash
    const signPromise =
       await contractInstance.web3BSC.eth.accounts.signTransaction(
        tx,
        config.get('WALLET_PRIVATE_KEY'),
      );
    // the rawTransaction here is already serialized so you don't need to serialize it again
    // Send the signed txn
    const sendTxn =
      await contractInstance.web3BSC.eth.sendSignedTransaction(
        signPromise.rawTransaction,
      );
    return Promise.resolve(sendTxn);
} catch(error) {
  throw error;
}
    }

Feliz codificación :)