¿Cómo ejecutar un método de contrato con clave privada/método de envío de firmas?

Me gustaría ejecutar un método de contrato erc20 sin desbloquear una billetera, firmando la transacción dentro de mi código. Así es como debería verse el código:

  public async send(sender: string, receiver: string, value: number, key: string)
    : PromiEvent<object> {
    return this.contract.methods.transfer(receiver, value)
      .send({ from: sender });
  }

el código actual no me permite firmar manualmente, se supone que la dirección del remitente está desbloqueada. ¿Cómo puedo firmar enviar manualmente?

Parece que esta es la solución con la que trabajaré stackoverflow.com/questions/46611117/…

Respuestas (3)

  public async send(sender: string, receiver: string, value: number, key: string)
    // @ts-ignore: PromiEvent extends Promise
    : PromiEvent<TransactionReceipt> {
    const query = this.contract.methods.transfer(receiver, value);
    const encodedABI = query.encodeABI();
    const signedTx = await this.web3.eth.accounts.signTransaction(
      {
        data: encodedABI,
        from: sender,
        gas: 2000000,
        to: this.contract.options.address,
      },
      key,
      false,
    );
    // @ts-ignore: property exists
    return this.web3.eth.sendSignedTransaction(signedTx.rawTransaction);
  }

Puede usar truffle-hdwallet-provider encima de su HttpProvider. Los proveedores de HDWallet luego firmarán la transacción antes de transmitirla al proveedor. Es solo un contenedor simple sobre un proveedor. A continuación se muestra mi index.js para obtener cualquier contrato.

let HDWalletProvider = require('truffle-hdwallet-provider')
  , Web3 = require('web3')
  , path = require('path');

let settings = require('../settings');

function getWeb3Provider() {
  return new HDWalletProvider(settings.mnemonic, 'https://network.infura.io/apikey');
}

async function getContract(abi) {
  let provider = getWeb3Provider();

  let web3 = new Web3(provider);
  let artifact = require(path.join(settings.artifactsDir, abi));
  let contract = new web3.eth.Contract(artifact.abi, artifact.networks[settings.networkId].address);
  contract.setProvider(provider);
  return contract
}

module.exports = {
  getContract
};

Luego puede usar sus funciones tal como están, todas estarán firmadas por la primera clave privada generada por la fase mnemotécnica antes de transmitirse. Si no tiene la fase mnemotécnica, es trivial bifurcar truffle-hdwallet-provider (es un módulo de 60 líneas) y hacer que tome una clave privada en lugar de una fase mnemotécnica.

hm... parece que no es la solución más sencilla, pero tal vez pueda encontrar algo útil en el código de trufas. Necesito usar una clave privada y no un mnemotécnico
@jeff truffle-hdwallet-provider es un módulo de 60 líneas y mi opinión personal es que es la forma más ordenada. No tiene que repetir la parte de firma de la transacción en cada función... ¡Hacer que el proveedor se ocupe de la firma es extremadamente reutilizable y no hay repetición de código! Podría tener una función genérica que se ocupe de la firma, pero aún tiene que llamar a esa función desde cualquier lugar, mientras que los proveedores de waller parecen más naturales.

Esta es mi implementación usando"@truffle/hdwallet-provider": "^2.0.3", "web3": "^1.6.1",


function getWeb3Provider() {
  return new HDWalletProvider({
    privateKeys: [NFT_MINTER_ACCOUNT_PRIVATE_KEY],
    providerOrUrl: BSC_RPC_ENDPOINT,
  });
}

const web3 = new Web3(BSC_RPC_ENDPOINT);
const contract = new web3.eth.Contract(
      jsonContractABI as unknown as AbiItem[],
      NFT_CONTRACT_ADDRESS
    );
contract.setProvider(getWeb3Provider());

luego en sendmétodos

contract.methods.safeMint(receiverAddress, itemUri).send({
      from: NFT_MINTER_ACCOUNT,
    });

en callmétodos

contract.methods.balanceOf(address).call();

Gracias, @manan-mehta