web-dev-qa-db-fra.com

Comment authentifier et envoyer une méthode de contrat à l'aide de web3.js 1.0

Je ne comprends pas comment exécuter une méthode de contrat avec la bibliothèque web3 1.0.

Ce code fonctionne (tant que je débloque d'abord le compte manuellement):

var contract = new web3.eth.Contract(contractJson, contractAddress);
contract.methods
  .transfer("0x0e0479bC23a96F6d701D003c5F004Bb0f28e773C", 1000)
  .send({
    from: "0x2EBd0A4729129b45b23aAd4656b98026cf67650A"
  })
  .on('confirmation', (confirmationNumber, receipt) => {
    io.emit('confirmation', confirmationNumber);
  });

Je reçois cette erreur (si je ne déverrouille pas d'abord manuellement): 

Erreur renvoyée: authentification requise: mot de passe ou déverrouillage

Le code ci-dessus est un noeud final d'API dans node.js. Je souhaite donc qu'il se déverrouille ou s'authentifie par programme.

Web3.js 1.0 ne contient aucune méthode pour déverrouiller le compte.

Je ne pense pas non plus que cela soit nécessaire (du moins c'est ce qui me rend confus). Comme je gère des comptes, je connais la clé privée.

Je pense que la transaction doit être signée avec la clé privée ?? Est-ce correct? Est-ce effectivement la même chose que "déverrouiller le compte"?

J'ai essayé de faire ceci:

var contract = new web3.eth.Contract(contractJson, contractAddress);

var tx = {
  from: "...{fromAddress -- address that has the private key below}",
  to: "...",
  value: ...
};

var signed = web3.eth.accounts.signTransaction(tx, 
  "...{privateKey}");

console.log(signed);

var promise = web3.eth.sendSignedTransaction(signed);

Je reçois cette erreur: 

Erreur renvoyée: la méthode net_version n'existe pas/n'est pas disponible

Quel est le moyen le plus simple d'authentifier et de soumettre une transaction?

Idéalement, je souhaite utiliser la première approche de mon exemple de code, car elle est la plus propre.

4
Nick Young

Ce code me permet de signer une transaction côté serveur (node.js) à l'aide de la clé privée du compte que j'ai créé (à l'aide de web3.eth.accounts.create ()) et d'envoyer la transaction signée au réseau sans avoir à déverrouiller le compte.

J'utilise Geth 1.7.1

  var contract = new web3.eth.Contract(contractJson, contractAddress);
  var transfer = contract.methods.transfer("0x...", 490);
  var encodedABI = transfer.encodeABI();

  var tx = {
    from: "0x...",
    to: contractAddress,
    gas: 2000000,
    data: encodedABI
  }; 

  web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
    var tran = web3.eth.sendSignedTransaction(signed.rawTransaction);

    tran.on('confirmation', (confirmationNumber, receipt) => {
      console.log('confirmation: ' + confirmationNumber);
    });

    tran.on('transactionHash', hash => {
      console.log('hash');
      console.log(hash);
    });

    tran.on('receipt', receipt => {
      console.log('reciept');
      console.log(receipt);
    });

    tran.on('error', console.error);
  });
18
Nick Young

Voici un exemple complet sur la façon de signer une transaction sans compte dans un portefeuille local. Particulièrement utile si vous utilisez Infura pour la transaction. Ceci a été écrit pour 

'use strict';
const Web3 = require('web3');

const wsAddress = 'wss://rinkeby.infura.io/ws';
const contractJson = '(taken from solc or remix online compiler)';
const privateKey = '0xOOOX';
const contractAddress = '0xOOOX';
const walletAddress = '0xOOOX';

const webSocketProvider = new Web3.providers.WebsocketProvider(wsAddress);
const web3 = new Web3(new Web3.providers.WebsocketProvider(webSocketProvider));
const contract = new web3.eth.Contract(
  JSON.parse(contractJson),
  contractAddress
);
// change this to whatever contract method you are trying to call, E.G. SimpleStore("Hello World")
const query = contract.methods.SimpleStore('Hello World');
const encodedABI = query.encodeABI();
const tx = {
  from: walletAddress,
  to: contractAddress,
  gas: 2000000,
  data: encodedABI,
};

const account = web3.eth.accounts.privateKeyToAccount(privateKey);
console.log(account);
web3.eth.getBalance(walletAddress).then(console.log);

web3.eth.accounts.signTransaction(tx, privateKey).then(signed => {
  const tran = web3.eth
    .sendSignedTransaction(signed.rawTransaction)
    .on('confirmation', (confirmationNumber, receipt) => {
      console.log('=> confirmation: ' + confirmationNumber);
    })
    .on('transactionHash', hash => {
      console.log('=> hash');
      console.log(hash);
    })
    .on('receipt', receipt => {
      console.log('=> reciept');
      console.log(receipt);
    })
    .on('error', console.error);
});

En utilisant

"web3": "1.0.0-beta.30"

3
Zibyl

Pour pouvoir appeler vos méthodes de contrat sans avoir à signer explicitement la transaction, procédez comme suit (web3js 1.0.0):

const privateKey = 'e0f3440344e4814d0dea8a65c1b9c488bab4295571c72fb879f5c29c8c861937';
const account = web3.eth.accounts.privateKeyToAccount('0x' + privateKey);
web3.eth.accounts.wallet.add(account);
web3.eth.defaultAccount = account.address;

// ...
contract = new web3.eth.Contract(JSON_INTERFACE, address);
contract.methods.myMethod(myParam1, myParam2)
        .send({
            from: this.web3.eth.defaultAccount,
            gas: myConfig.gas,
            gasPrice: myConfig.gasPrice
        })
1
Gediminas Rimsa