如何使用 web3.js 1.0 认证和发送合约方法

Posted

技术标签:

【中文标题】如何使用 web3.js 1.0 认证和发送合约方法【英文标题】:How to authenticate and send contract method using web3.js 1.0 【发布时间】:2018-03-18 13:51:45 【问题描述】:

我对如何使用 web3 1.0 库执行合约方法感到困惑。

此代码有效(只要我先手动解锁帐户):

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

我收到此错误(如果我没有先手动解锁):

返回错误:需要验证:密码或解锁

以上代码是 node.js 中的一个 API 端点,所以我希望它以编程方式解锁或验证。

web3.js 1.0 中没有解锁账号的方法。

我也不认为这是必要的(至少我对此感到困惑)。因为我在管理账户,所以我知道私钥是什么。

我认为交易需要用私钥签名??它是否正确?这实际上与“解锁帐户”相同吗?

我试过这样做:

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

我得到这个错误:

返回错误:方法net_version不存在/不可用

验证和提交交易的最简单方法是什么?

理想情况下,我想在我的代码示例中使用第一种方法,因为它是最干净的。

【问题讨论】:

我会使用 Parity,它会创建一个使用 ETH 运行的默认帐户(没有密码)用于开发,这是我放在一起的一个示例:github.com/leopoldjoy/react-ethereum-dapp-example 这样你就不用解锁账户了。下面是一个使用方法的例子:github.com/leopoldjoy/react-ethereum-dapp-example/blob/master/… 感谢您的示例。不过,我正在编写生产代码,并且需要对通过我正在构建的门户以编程方式创建的帐户进行操作。我设法弄清楚了......希望这是正确的做事方式。 【参考方案1】:

此代码允许我使用我创建的帐户(使用 web3.eth.accounts.create())中的 privateKey 签署交易服务器端(node.js),并将签署的交易发送到网络 无需解锁帐户。

我正在使用 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);
  );

【讨论】:

【参考方案2】:

一种无需显式签署交易即可调用合约方法的方法是(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
        )

【讨论】:

【参考方案3】:

这是一个完整示例,说明如何在没有本地钱包帐户的情况下签署交易。如果您使用 infura 进行交易,则特别有用。这是为

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

使用

“web3”:“1.0.0-beta.30”

【讨论】:

以上是关于如何使用 web3.js 1.0 认证和发送合约方法的主要内容,如果未能解决你的问题,请参考以下文章

使用 web3.js 的“发送”有啥问题?

在 Web3.js 中使用本地私钥

关于web3.js中与交易发送交易签名智能合约函数调用相关api的理解

使用 web3 js 调用智能合约函数

web3使用web3.js发布并执行智能合约

如何使用 web3.js 注销 MetaMask 帐户