Send ERC20 token with web3

23,780

Solution 1

Take EOS token transfering as the example.

Below code need web3 and ethereumjs-tx. If you've not install them, install them with npm install web3 ethereumjs-tx

var Tx = require('ethereumjs-tx');
var Web3 = require('web3')
var web3 = new Web3(new Web3.providers.HttpProvider('http://127.0.0.1:8545/'))

// set token source, destination and amount
var myAddress = "0xaa597b7e8aaffe9f2a187bedb472ef3455957560"
var toAddress = "0xa013927bffe9e879134061b9330a01884a65497c"
var amount = web3.utils.toHex(1e16)

// get transaction count, later will used as nonce
web3.eth.getTransactionCount(myAddress).then(function(v){console.log(v); count = v})  

// set your private key here, we'll sign the transaction below
var privateKey = new Buffer('6d...', 'hex')  

// Get abi array here https://etherscan.io/address/0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0#code
var abiArray = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint128"}],"name":"push","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"name_","type":"bytes32"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"mint","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"wad","type":"uint128"}],"name":"pull","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"burn","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"start","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"guy","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"symbol_","type":"bytes32"}],"payable":false,"type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]
// Here you may get the abicode from a string or a file, here is a string case
// var abiArray = JSON.parse('[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"stop","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint128"}],"name":"push","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"name_","type":"bytes32"}],"name":"setName","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"mint","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"src","type":"address"},{"name":"wad","type":"uint128"}],"name":"pull","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"wad","type":"uint128"}],"name":"burn","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"start","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"src","type":"address"},{"name":"guy","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"symbol_","type":"bytes32"}],"payable":false,"type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]', 'utf-8')

var contractAddress = '0x86Fa049857E0209aa7D9e616F7eb3b3B78ECfdb0'
var contract = new web3.eth.Contract(abiArray, contractAddress, {from: myAddress})

var rawTransaction = {"from":myAddress, "gasPrice":web3.utils.toHex(2 * 1e9),"gasLimit":web3.utils.toHex(210000),"to":contractAddress,"value":"0x0","data":contract.methods.transfer(toAddress, amount).encodeABI(),"nonce":web3.utils.toHex(count)} 
var transaction = new Tx(rawTransaction)
transaction.sign(privateKey)

web3.eth.sendSignedTransaction('0x' + transaction.serialize().toString('hex'))

// check the balance
contract.methods.balanceOf(myAddress).call().then(function(balance){console.log(balance)})

You also can check the transaction with https://etherscan.io.

After the transaction send, you can check it with https://etherscan.io/address/0xaa597b7e8aaffe9f2a187bedb472ef3455957560#tokentxns, and you'll see the pending transaction as below on the Transactions filed, but you cannot see it in the Token Transfers field.

enter image description here

Wait about 1 minute, you can see the successed on both Transactions filed and the Token Transfers field.

enter image description here enter image description here

Solution 2

Error: Invalid JSON RPC response: "" means web3 cant connect to rpc node. Try running one with ::

-for testnet

geth --testnet --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpccorsdomain '*' --rpcapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --ws --wsaddr 127.0.0.1 --wsport 8546 --wsorigins '*' --wsapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --maxpeers 25 0 --gasprice 100

-for mainnet

geth --rpc --rpcaddr 127.0.0.1 --rpcport 8545 --rpccorsdomain '*' --rpcapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --ws --wsaddr 127.0.0.1 --wsport 8546 --wsorigins '*' --wsapi personal,admin,db,eth,net,web3,miner,shh,txpool,debug --maxpeers 25 0 --gasprice 100

Now in your case (using infura testnet node), get a id from infura.io. It should be like this ::

https://ropsten.infura.io/id

Solution 3

You need to call the transfer method of the ERC20 contract. e.g.:

myContractInstance.methods.transfer(toAddress, amount);

And in your raw transaction object:

  1. You don't need the amount
  2. To address should be to the contract (not the toAddress in the method call)

e.g.:

var rawTx = {
  from : defaultAccount,
  nonce : nonceHex,
  gasPrice : gasPriceHex,
  gas : gasHex,
  to : <contractAddress>,
  data : data

};

Share:
23,780
rachel_hong
Author by

rachel_hong

Updated on December 02, 2021

Comments

  • rachel_hong
    rachel_hong over 2 years

    I'm currently using 0.2x.x version of Web3 Javascript API. I deployed my custom ERC20 token by creating smart contract in solidity (on REMIX IDE). I installed the MetaMask and had a test on https://wallet.ethereum.org/ to send some custom ERC token to another my account. It worked well. I want to add the 'send custom ERC20 Token' function in my javascript code using Web3.

    Here is my code below.

    var http = require('http');
    var Web3 = require('web3');
    var Tx = require('ethereumjs-tx');
    
    var abi = [{"...."}]; 
    var data = '0x00..';
    var contract_addr = '0x00..';
    var owner = '0x00..';
    
    var web3 = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io/")); 
    web3.eth.getBlock("latest", (error, result) => {
    //console.log('error:', error);
    //console.log('results', result);
    });
    
    var myContract = web3.eth.contract(abi);
    var myContractInstance = myContract.at(address);
    
    eb3.eth.getDefaultAccount = owner;
    var defaultAccount = web3.eth.getDefaultAccount;
    console.log('DefaultAccount => ', defaultAccount); 
    
    var total = myContractInstance.totalSupply();
    var balance = myContractInstance.balanceOf(defaultAccount);
    
    console.log('DefulatAccount total => ',total);
    console.log('DefaultAccount balance => ',balance);
    
    var to = '0x00..';
    var isAddress = web3.isAddress(to);
    
    console.log('isAddress(to) => ',isAddress);
    console.log('balanceOf(to) => ',myContractInstance.balanceOf(to));
    

    I'm working on the 'Ropsten Testnet' and I sent some 'ether' for test using sendRawTransaction(). But what I want to do is just sending my custom ERC20 token. not the ether. How can I send my own token in this script? I have no idea. I tried to use sendTransaction() like below.

    var rawTx = {
        from : defaultAccount,
        nonce : nonceHex,
        gasPrice : gasPriceHex,
        gas : gasHex,
        to : to,
        value : 100,
        data : data
    };
    
    web3.eth.sendTransaction(rawTx, function(err, transactionHash) {
        if (!err)
            console.log('transactionHash => ',transactionHash);
        else
            console.log(err);
    });
    

    I continuously received the error.

    Error: Invalid JSON RPC response: ""
    at Object.InvalidResponse (/Users/rachel/dev/test/node_modules/web3/lib/web3/errors.js:38:16)
    at XMLHttpRequest.request.onreadystatechange (/Users/rachel/dev/test/node_modules/web3/lib/web3/httpprovider.js:119:24)
    at XMLHttpRequestEventTarget.dispatchEvent (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:64:18)
    at XMLHttpRequest._setReadyState (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:354:12)
    at XMLHttpRequest._onHttpResponseEnd (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:509:12)
    at IncomingMessage.<anonymous> (/Users/rachel/dev/test/node_modules/xhr2/lib/xhr2.js:469:24)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1056:12)
    at _combinedTickCallback (internal/process/next_tick.js:138:11)
    

    I really can't understand what is wrong with it. Please let me know some way to deal with this. Thanks!

  • LF00
    LF00 about 6 years
  • Paul Razvan Berg
    Paul Razvan Berg over 5 years
    As of July 2018, this post is rather misleading. Kris was referring to the canonical EOS ERC20 token on Ethereum. In the meantime, EOS has launched and they have their own native currency.
  • LF00
    LF00 over 5 years
    Here refer to EOS token on Ethereum, not EOS coin.
  • Okpo
    Okpo almost 3 years
    That's right; check your internet connection. I get that error when my internet is off