Search code examples
ethereumblockchainpolygonweb3jsinfura

Error: Returned error: The method eth_sendTransaction does not exist/is not available


I have a method deployed under smart contract on polygon network:

function transfer(address _to, uint256 _value) public returns (bool) {
    require(_value <= balances[msg.sender]);
    require(_to != address(0));

    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    return true;
  }

But, whenever I try to call the method from my application backend using the line of code:

contractSending.methods.transfer(to, amountSLVD).send({ from: from, gas: 100000 });

I get this error:

The method eth_sendTransaction does not exist/is not available

I have added multiple wallets with private keys:

const polygon = new Web3(Config.polygonNodeUrl);
const accountPolygon = polygon.eth.accounts.privateKeyToAccount('0x' + Config.walletPrivateKey);
polygon.eth.accounts.wallet.add(accountPolygon);
polygon.eth.accounts.wallet.add(polygon.eth.accounts.privateKeyToAccount('0x' + Config.privateKeyAddress1));
polygon.eth.accounts.wallet.add(polygon.eth.accounts.privateKeyToAccount('0x' + Config.privateKeyAddress2));
polygon.eth.accounts.wallet.add(polygon.eth.accounts.privateKeyToAccount('0x' + Config.privateKeyAddress3));
polygon.eth.accounts.wallet.add(polygon.eth.accounts.privateKeyToAccount('0x' + Config.privateKeyAddress4));
polygon.eth.accounts.wallet.add(polygon.eth.accounts.privateKeyToAccount('0x' + Config.privateKeyAddress5));

I am using Infura for this project

I'm guessing that you're connected directly to Infura, which doesn't support eth_sendTransaction. (For it to support that, it would need to know your private key, but it's a shared public node.)

You need to either sign the transaction yourself and then send via eth_sendRawTransaction or use a provider that can hold private keys like MetaMask in the browser.

I found this fix on the stack overflow: https://stackoverflow.com/questions/55154713/error-the-method-eth-sendtransaction-does-not-exist-is-not-available

But, doesn't exactly know how to implement this.


Solution

  • From here

    The eth_sendTransaction JSON-RPC method is not supported because Infura doesn't store the user's private key required to sign the transaction. Use eth_sendRawTransaction instead.

    key point is Infura doesn't store the user's private key, if there is no private key, you cannot sign it. Infura's policy of not storing private keys enhances security by ensuring that this sensitive information is not vulnerable to potential breaches. The eth_sendTransaction method expects the Ethereum node to have access to the sender's private key to sign the transaction. Since Infura cannot store private keys, it cannot support this method directly. so you have to write code to sign the transaction. from infura docs how to send transaction web3.js

    const { Web3 } = require("web3");
    const { ETH_DATA_FORMAT, DEFAULT_RETURN_FORMAT } = require("web3");
    async function main() {
      // Configuring the connection to an Ethereum node
      const network = process.env.ETHEREUM_NETWORK;
      const web3 = new Web3(
        new Web3.providers.HttpProvider(
          `https://${network}.infura.io/v3/${process.env.INFURA_API_KEY}`,
        ),
      );
      // Creating a signing account from a private key
      const signer = web3.eth.accounts.privateKeyToAccount(
        process.env.SIGNER_PRIVATE_KEY,
      );
      web3.eth.accounts.wallet.add(signer);
      await web3.eth
        .estimateGas(
          {
            from: signer.address,
            to: "0xAED01C776d98303eE080D25A21f0a42D94a86D9c",
            value: web3.utils.toWei("0.0001", "ether"),
          },
          "latest",
          ETH_DATA_FORMAT,
        )
        .then((value) => {
          limit = value;
        });
    
      // Creating the transaction object
      const tx = {
        from: signer.address,
        to: "0xAED01C776d98303eE080D25A21f0a42D94a86D9c",
        value: web3.utils.toWei("0.0001", "ether"),
        gas: limit,
        nonce: await web3.eth.getTransactionCount(signer.address),
        maxPriorityFeePerGas: web3.utils.toWei("3", "gwei"),
        maxFeePerGas: web3.utils.toWei("3", "gwei"),
        chainId: 11155111,
        type: 0x2,
      };
      signedTx = await web3.eth.accounts.signTransaction(tx, signer.privateKey);
      console.log("Raw transaction data: " + signedTx.rawTransaction);
      // Sending the transaction to the network
      const receipt = await web3.eth
        .sendSignedTransaction(signedTx.rawTransaction)
        .once("transactionHash", (txhash) => {
          console.log(`Mining transaction ...`);
          console.log(`https://${network}.etherscan.io/tx/${txhash}`);
        });
      // The transaction is now on chain!
      console.log(`Mined in block ${receipt.blockNumber}`);
    }
    require("dotenv").config();
    main();