【问题标题】:Error: The method eth_sendTransaction does not exist/is not available错误:方法 eth_sendTransaction 不存在/不可用
【发布时间】:2019-08-04 21:17:24
【问题描述】:

调用已部署在 ropsten-infura 中的solidity 合约时显示错误。我正在使用 web3(@0.19.1) 调用合约。

有人遇到过同样的问题吗?

【问题讨论】:

  • 错误是什么?尝试使用 web3 版本 1 系列,例如 web3@1.0.0。 web3 版本 0 系列是基于回调的,这在大多数情况下令人困惑且难以跟踪错误。

标签: node.js blockchain ethereum solidity web3js


【解决方案1】:

我猜您直接连接到不支持eth_sendTransaction 的 Infura。 (为了支持它,它需要知道你的私钥,但它是一个共享的公共节点。)

您需要自己签署交易,然后通过eth_sendRawTransaction 发送,或者使用可以在浏览器中保存私钥的提供商,例如 MetaMask。

【讨论】:

    【解决方案2】:

    这是一个智能合约函数执行示例: 我们知道在以太坊网络中进行免费交易是不可能的,因此您可以通过联系账户委托支付费用

                                        const rawTx =
                                        {
                                            nonce: _hex_nonce,
                                            from: MainAccountAddress,
                                            to: contractAddress,
                                            gasPrice: _hex_gasPrice,
                                            gasLimit: _hex_gasLimit,
                                            gas: _hex_Gas,
                                            value: '0x0',
                                            data: contract.methods.transfer(toAddress, _hex_value).encodeABI()
                                        };
    
                                        const tx = new Tx(rawTx, { 'chain': 'ropsten' });
                                        tx.sign(privateKey);
    
                                        var serializedTx = '0x' + tx.serialize().toString('hex');
                                        web3.eth.sendSignedTransaction(serializedTx.toString('hex'), function (err, hash) {
                                            if (err) {
                                                reject(err);
                                            }
                                            else {
                                                resolve(hash);
                                            }
                                        })
    

    这里是执行智能合约的完整源代码,通过合约主账户委托:

    async function TransferERC20Token(toAddress, value) {
    return new Promise(function (resolve, reject) {
        try {
            web3.eth.getBlock("latest", false, (error, result) => {
                var _gasLimit = result.gasLimit;
                let contract = new web3.eth.Contract(contractABI, contractAddress);
    
                contract.methods.decimals().call().then(function (result) {
                    try {
                        var decimals = result;
                        let amount = parseFloat(value) * Math.pow(10, decimals);
                        web3.eth.getGasPrice(function (error, result) {
                            var _gasPrice = result;
                            try {
                                const Tx = require('ethereumjs-tx').Transaction;
                                const privateKey = Buffer.from(MainAccountPrivateKey, 'hex')
    
                                var _hex_gasLimit = web3.utils.toHex((_gasLimit + 1000000).toString());
                                var _hex_gasPrice = web3.utils.toHex(_gasPrice.toString());
                                var _hex_value = web3.utils.toHex(amount.toString());
                                var _hex_Gas = web3.utils.toHex('60000');
    
                                web3.eth.getTransactionCount(MainAccountAddress).then(
                                    nonce => {
                                        var _hex_nonce = web3.utils.toHex(nonce); 
    
                                        const rawTx =
                                        {
                                            nonce: _hex_nonce,
                                            from: MainAccountAddress,
                                            to: contractAddress,
                                            gasPrice: _hex_gasPrice,
                                            gasLimit: _hex_gasLimit,
                                            gas: _hex_Gas,
                                            value: '0x0',
                                            data: contract.methods.transfer(toAddress, _hex_value).encodeABI()
                                        };
    
                                        const tx = new Tx(rawTx, { 'chain': 'ropsten' });
                                        tx.sign(privateKey);
    
                                        var serializedTx = '0x' + tx.serialize().toString('hex');
                                        web3.eth.sendSignedTransaction(serializedTx.toString('hex'), function (err, hash) {
                                            if (err) {
                                                reject(err);
                                            }
                                            else {
                                                resolve(hash);
                                            }
                                        })
                                    });                                
                            } catch (error) {
                                reject(error);
                            }
                        });
                    } catch (error) {
                        reject(error);
                    }
                });
            });
        } catch (error) {
            reject(error);
        }
    })
    

    }

    【讨论】:

      【解决方案3】:

      您需要在之前签署交易,这就是我使用 web3 1.0.0 的方式。

      我使用了 MetaMask 的 web3-provider-engine:https://github.com/MetaMask/web3-provider-engine/blob/master/subproviders/hooked-wallet-ethtx.js

      getWalletEthTxSubprovider() {
          return new HookedWalletEthTxSubprovider({
              getAccounts: callback => {
                  callback(null, [this.web3.eth.defaultAccount]);
              },
              getPrivateKey: (address, callback) => {
                  if (address.toLowerCase() === this.web3.eth.defaultAccount.toLowerCase()) {
                      return callback(
                          null,
                          Buffer.from(
                              this.web3.eth.accounts.wallet[address].privateKey.replace('0x', ''),
                              'hex'
                          )
                      );
                  }
                  return callback(new Error('not private key supplied for that account'));
              }
          });
      }
      

      你可以在这里看到完整的代码https://github.com/SelfKeyFoundation/Identity-Wallet/blob/60733b208275119b31abf2cb3ab1f49f0b6801a3/src/main/blockchain/web3-service.js#L42-L76

      【讨论】:

        【解决方案4】:

        我通过将 ganache cli 指向 Infura fork 并在我的脚本中使用本地 ganache 网络地址解决了这个问题。

        @user94559 已经指出,如果您直接连接到 Infura,可能会发生这种情况。

        【讨论】:

          猜你喜欢
          • 2021-09-15
          • 2022-07-08
          • 2021-10-01
          • 2020-09-30
          • 2022-06-16
          • 2022-08-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多