Wie führe ich eine Vertragsmethode mit privater Schlüssel-/Signatur-Sendemethode aus?

Ich möchte eine erc20-Vertragsmethode ausführen, ohne eine Brieftasche zu entsperren, und die Transaktion in meinem Code signieren. So sollte der Code aussehen:

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

Der aktuelle Code erlaubt mir nicht, manuell zu signieren, er geht davon aus, dass die Absenderadresse entsperrt ist. Wie kann ich manuell signieren?

Scheint, dass dies die Lösung ist, mit der ich arbeiten werde stackoverflow.com/questions/46611117/…

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

Sie können truffle-hdwallet-provider zusätzlich zu Ihrem HttpProvider verwenden. HDWallet-Anbieter signieren dann die Transaktion, bevor sie an den Anbieter gesendet werden. Es ist nur ein einfacher Wrapper auf einem Provider. Unten ist meine index.js, um einen Vertrag zu erhalten.

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

Sie können Ihre Funktionen dann so verwenden, wie sie sind, sie werden alle mit dem ersten privaten Schlüssel signiert, der von der mnemonischen Phase generiert wird, bevor sie gesendet werden. Wenn Sie die mnemonische Phase nicht haben, ist es trivial, truffle-hdwallet-provider (es ist ein Modul mit 60 Zeilen) zu forken und einen privaten Schlüssel anstelle einer mnemonischen Phase zu nehmen.

hm .. klingt nach nicht der einfachsten Lösung, aber vielleicht finde ich etwas Nützliches im Truffle-Code. Ich muss einen privaten Schlüssel und keine Mnemonik verwenden
@jeff truffle-hdwallet-provider ist ein 60-zeiliges Modul und meiner persönlichen Meinung nach ist es der sauberste Weg. Sie müssen den Signierungsteil der Transaktion dann nicht in jeder Funktion wiederholen ... Die Signierung durch den Anbieter ist extrem wiederverwendbar und keine Wiederholung des Codes! Sie könnten eine generische Funktion haben, die sich mit dem Signieren befasst, aber Sie müssen diese Funktion immer noch von überall aufrufen, während Waller-Anbieter natürlicher erscheinen.

Dies ist meine Implementierung mit"@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());

dann in sendMethoden

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

bei callMethoden

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

Danke @manan-mehta