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
.