5

The following code works for me to read Ether value from wallet:

var web3Instance =  new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

export async function readAccountEtherValue(address: string): Promise<number> {
    var balance = await web3Instance.eth.getBalance(address);
    return web3Instance.utils.fromWei(balance, "ether");
}

How can I read the values of all tokens from the wallet?

2

Token balances are not stored in a user's wallet. They are stored in the corresponding Token contract. Assuming the token you want to read the balance from is an ERC20 token, then you would have to instantiate the token contract and then call balanceOf(address) to get the address' balance. For example:

let token = await ERC20Basic.at(_tokenAddress);
let balance = await token.balanceOf(accounts[0]);
3
  • 1
    OMG that means I have to write a different code for each token in the entire world?
    – Alon
    Dec 7 '17 at 15:53
  • Not necessarily, tokens that are ERC20 compliant all follow the specification and have these common functions, for example balanceOf(). What you would need to do in order to read each one is just change the address of the token you want to get the balance of. You could write a function that loops through a list of token addresses and returns each one's balance for a particular user. Dec 7 '17 at 15:55
  • 1
    OK then how can I know which tokens implement ERC20, and how can I know all the existing tokens and know what's their interface? There are websites like etherscan.io that are able to read every existing token, even many tokens that are not listed on Coinmarketcap.
    – Alon
    Dec 7 '17 at 16:07
2

You could instead use the event Transfer to filter by that. You will probably need an almost full node:

const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider("http://127.0.0.1:8545"));
const transferEventTopic = web3.sha3("Transfer(address,address,uint256)");
const myAddress = "0x0000000000000000000000003f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be";
const fromBlock = 4647513;
const myBalances = {};

const filter = web3.eth.filter({
        fromBlock: fromBlock,
        topics: [ transferEventTopic ]
    });

filter.watch((err, obj) => {
        if (err) {
            console.error(err);
        } else {
            if (typeof myBalances[obj.address] === "undefined") {
                myBalances[obj.address] = web3.toBigNumber(0);
            }
            let message = "Token " + obj.address;
            let changed = false;
            if (obj.topics[1] == myAddress) {
                changed = true;
                myBalances[obj.address] = myBalances[obj.address].minus(obj.data);
                message += ", Sent " + web3.toBigNumber(obj.data).toString(10);
            } else if (obj.topics[2] == myAddress) {
                changed = true;
                myBalances[obj.address] = myBalances[obj.address].plus(obj.data);
                message += ", Received " + web3.toBigNumber(obj.data).toString(10);
            }
            if (changed) {
                message += ", Balance " + myBalances[obj.address].toString(10);
                console.log(message);
            }
        }
    });

process.on('SIGINT', () => {
    console.log("Stop watching");
    filter.stopWatching(console.log);
    process.exit();
});

If you only want the events that denote "receive", then replace the topics as topics: [ transferEventTopic, null, myAddress ].

If you only want the events that denote "send", then replace it is topics: [ transferEventTopic, myAddress ].

4
  • Does that code iterate all the wallets in the entire world until it finds mine?
    – Alon
    Dec 8 '17 at 5:01
  • 1
    That code iterates all the events and filters for your wallet. So yes, heavy. To be faster and less heavy, use the 2 filters listed at the bottom. Dec 8 '17 at 13:08
  • Well it seems that maybe blockchain is not such a great architecture after all. While I assume your code is the formally correct answer, I seriously consider using a workaround, like reading from a website that has already calculated my token balances. How long do you think it's going to take a program to iterate all the blocks ever since 4647513, as your code does? (I'm not cynical, I'm asking seriously in order to make a decision)
    – Alon
    Dec 10 '17 at 3:23
  • That would take a sizeable fraction of an hour, I reckon. But this only needs be done once, for all balances. You are correct, blockchain cannot satisfy all your db needs, its needs external aggregators. The benefit you get from these Transfer events is the certainty they happened. Dec 11 '17 at 10:24
0

I just recently wrote a smart contract and library for this, and put it into an NPM package. You can find the package here: https://www.npmjs.com/package/eth-balance-checker

The code would look like this, but you should read the README for that package to make sure you know how it works:

import { getAddressBalances } from 'eth-balance-checker/lib/web3';

const address = '<your_address_here>';
const tokens = ['<token>', '<addresses>', '<here>'];
getAddressBalances(web3, address, tokens).then(balances => {
  console.log(balances); // { "0x0": "100", "0x456...": "200" }
});

You can find lists of tokens to use in your project in various places. MyCrypto has a pretty comprehensive list: https://github.com/MyCryptoHQ/MyCrypto/blob/develop/common/config/tokens/eth.json

1
  • needs maintenance, does not work anymore due to old libraries used.
    – sed
    May 17 '21 at 2:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.