Error: Returned error: The method eth_sendTransaction does not exist
Asked Answered
B

1

8

I am trying to transfer an erc20 token from contract address to an ETH address using this code:

var _from = "from Address";
var contAddress = "contract address";
var _to = "to address";

var _Amount = '50';
var txnObject = {
    "from": _from,
    "to": _to,
    "value": web3.utils.toWei(_Amount, 'ether'),
    // "gas": 21000,         (optional)
    // "gasPrice": 4500000,  (optional)
    // "data": 'For testing' (optional)
    // "nonce": 10           (optional)
}

web3.eth.sendTransaction(txnObject, function (error, result) {
    if (error) {
        console.log("Transaction error", error);
    }
    else {
        var txn_hash = result; //Get transaction hash
        //$('#Tx').text(txn_hash);
        alert(txn_hash);
    }
});

But I am receiving this error:

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

I have searched a lot and tried this code but it did not work. What could be the reason? Is this code wrong, or is something else?

I am using infura ropsten network node.

Bobinette answered 3/7, 2021 at 12:58 Comment(0)
J
9

Apart from the error message, there are few other issues related to your question.


Lets start with the error message.

The method eth_sendTransaction does not exist/is not available

eth_sendTransaction() is used when you want your node to sign the transaction for you (using an ulocked account). But you're connected to a node that doesn't support this method. Most likely Infura or other third-party node provider that doesn't hold the private keys to your accounts for you.

So you'll need to sign the transaction on your app and then broadcast the signed transaction to your node. There are few ways to achieve this.

For example you can sign the tx using web3.eth.signTransaction(), and then use web3.eth.sendSignedTransaction() to submit the (signed) tx to your node.

Or you can use the accounts.wallet.add() method and then a Contract instance send() method - see the middle part of the answer.


Your snippet creates a regular ETH transfer - it doesn't create a token transfer.

You can use the Web3 Contract methods to help you build the transaction that transfers ERC-20 tokens.

// this is one of the other ways to sign a transaction on your end
web3.eth.accounts.wallet.add(privateKeyToTheSenderAddress);

// for this case, you can use a generic ERC-20 ABI JSON interface
const myContract = new web3.eth.Contract(jsonInterface, contractAddress);

// invoke the `transfer()` method on the contract
// sign it using the private key corresponding to the `senderAddress`
// and broadcast the signed tx to your node
myContract.methods.transfer(toAddress, amount).send({from: senderAddress});

I'm not sure if this is just an incorrect wording of the question, or a logical error. But you can't transfer tokens that belong to the contract, unless the contract code allows you to do so.

Why? Because you need the private key of the sender to be able to transfer their tokens. It's because how the transfer() method is usually built:

function transfer(address _to, uint256 _amount) external returns (bool) {
    balances[msg.sender] -= _amount; // decreases balance of the transaction sender
    // ...
}

The transaction sender needs to sign the transaction using their private key. And if you want the sender to be the contract (to decrease token balance of the contract), you need to have its private key. Which you don't have (it's just practically impossible to know the contract's private key).

But maybe your contract allows decreasing it's balance if the transaction sender is an authorized address. Example:

function withdrawTokensFromContract(uint256 _amount) external {
    require(msg.sender == address(Ox123), 'Not authorized');
    balances[address(this)] -= _amount; // decreases balance of the contract
    // ...
}

In this case, it's possible to decrease the token balance of the contract, if you've signed the transaction using the private key that belongs to the authorized address.

Or maybe it was just an incorrect wording, and you simply want to transfer tokens (stored in the contract address) from Address A to Address B. In this case, you can safely use the transfer() method described in the middle part of the answer, and sign the transaction using private key that belongs to the Address A.

Jeu answered 3/7, 2021 at 20:8 Comment(3)
used the transfer method and it is saying "Cannot read property 'add' of undefined" while the web3 is linked like this "<script src="web3-v0.20.6.min.js"></script>"Bobinette
Oh I assumed you're using web3 on the backend JS (node.js). It seems that the wallet extension is not included in your web3 script. So you can either import another web3 script that includes the wallet functionality - or... It's generally unwise to define private keys in the frontend JS because anyone who displays the page can read the private key. In this case, you can use for example MetaMask browser extension which implements the Ethereum Provider API to sign the transaction without having to pass the private key in the code.Jeu
can you please suggest any web3 script in which all the necessary extensions are included?Bobinette

© 2022 - 2024 — McMap. All rights reserved.