0

Using "web3": "1.0.0-beta.46" because doing a tutorial, and they recommended using all his versions to make sure everything works together.

Using Gnache and Truffle unit tests, I have tried two helper routines to get Eth balance for an address. URL to source of the code in comments inline below:

const Web3 = require('web3') 
const rpcURL = 'https://127.0.0.1:7545' 
const objWeb3 = new Web3(rpcURL);


//https://ethereum.stackexchange.com/questions/11444/web3-js-with-promisified-api/24238#24238
const promisify = (inner) =>
  new Promise((resolve, reject) =>
    inner((err, res) => {
      if (err) { reject(err) }
      resolve(res);
    })
  );

export const getBalance = (account, at) =>
  promisify(cb => objWeb3.eth.getBalance(account, at, cb)
           );


//https://github.com/shawntabrizi/ethbalance/blob/master/index.html
export function getBalance2(address) {
   console.log("debug: helpers/getBalance2-A"); 
    try {
        objWeb3.eth.getBalance(address, function (error, wei) {
            console.log("debug: helpers/getBalance2-B"); 
            if (!error) {
                console.log("debug: helpers/getBalance2-C: wei=" + wei)
                //var balance = web3.fromWei(wei, 'ether');
                return wei; 
            }
            else 
            {
                console.log("debug: helpers/getBalance2-D error=" + error); 
            }
        });
    } catch (err) {
        console.log("debug: helpers/getBalance2-E error=" + err);
    }
}

The promisfy solution gives me a timeout error:

Timeout of 300000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

The getBalance2 routine returns Undefined, as shown by these console.logs:

 depositing tokens
      success
debug: helpers/getBalance2-A
result.EtherWallet=undefined
        1) "before each" hook for "tracks the token deposit"
...

TypeError: Cannot read property 'toString' of undefined
  at EthToWei (e:/GitHub/NealWalters/DappUniversity/blockchain-developer-bootcamp/test/helpers.js:13:26)
  at _callee2$ (e:/GitHub/NealWalters/DappUniversity/blockchain-developer-bootcamp/test/Exchange.test.js:61:43)
  at tryCatch (node_modules\@babel\runtime\node_modules\regenerator-runtime\runtime.js:45:40)
  at Generator.invoke [as _invoke] (node_modules\@babel\runtime\node_modules\regenerator-runtime\runtime.js:271:22)
  at Generator.prototype.(anonymous function) [as next] (node_modules\@babel\runtime\node_modules\regenerator-runtime\runtime.js:97:21)
  at step (test\Exchange.test.js:7:191)
  at test\Exchange.test.js:7:361
  at process._tickCallback (internal/process/next_tick.js:68:7)

My ultimate goal is a function that shows the balance of user's wallet, then his token and ETH balance in my exchange contract:

async function GetAndShowUserBalances(description, userName, userAddr) 
{
  var result = {}; 
   result.Ether = await exchange.balanceOf(ETHER_ADDRESS, userAddr); 
   result.Tokens = await exchange.balanceOf(token.address, userAddr); 

   result.EtherWallet = await getBalance2(userAddr);
   console.log("result.EtherWallet=" + result.EtherWallet);
   //result.EtherWallet = await web3.eth.getBalance(userAddr); 

   result.TokenWallet = await token.balanceOf(user1Addr) 
   console.log("ShowUserBalances: " + description + " " + userName + 
                 " Contract: Ether=" + EthToWei(result.Ether) + 
                 " Tokens=" + EthToWei(result.Tokens) + 
                 " Wallet: Ether="  + EthToWei(result.EtherWallet) + 
                 " Tokens=" + EthToWei(result.TokenWallet) 
                 ); 

   return result; 

}

Update - what is minimal code in a Truffle test to prove this works or not. I tried calling it without "await", but if I use "await", then I have to put in "async" function.

const Web3 = require('web3') 
const rpcURL = 'https://127.0.0.1:7545' 
const objWeb3 = new Web3(rpcURL);

require('chai')
  .use(require('chai-as-promised'))
  .should() 

async function demo() {
    let user1Address = "0x1D41CB7d963a5B96687e80Be1b23320e40176F02"
    //let balance = getBalance3(user1Address); 
    //let balance = objWeb3.eth.getBalance(user1Address).then 
    //  (console.log);


    await objWeb3.eth.getBalance(user1Address).then (function (balance) {
           console.log("Balance=" + balance);
        }).catch (function(e) {
           console.log("Error=" + e);
    }); 

    await objWeb3.eth.getBalance(user1Address,function(error,result){

        if(error){
           console.log("Error=" + error)
        }
        else{
           console.log("result=" + result)
        }
     })

    console.log("End Function"); 

}

demo(); 
console.log("The end");

The above returns only:

Compiling your contracts...
===========================
> Compiling .\src\contracts\Exchange.sol
> Compiling .\src\contracts\Token.sol
> Artifacts written to C:\Users\nwalt\AppData\Local\Temp\test-119924-47264-1e1elx.7p1ik
> Compiled successfully using:
   - solc: 0.5.0+commit.1d4f565a.Emscripten.clang

The end

0 passing (2ms)

Ran the node below: node src/web3demo.js. It also runs without showing anything.

const Web3 = require('web3') 
console.log("Got the web3 module")
const rpcURL = 'https://127.0.0.1:7545' 
const web3 = new Web3(rpcURL);
console.log("Got web3 connection")

const address = '0x1D41CB7d963a5B96687e80Be1b23320e40176F02'
console.log ("attempting to show balance of ETH address: " + address)
web3.eth.getBalance(address, (err,balance) => console.log("Balance=" + web3.utils.balance))
console.log("The end"); 

Output:

Got the web3 module
Got web3 connection
attempting to show balance of ETH address: 0x1D41CB7d963a5B96687e80Be1b23320e40176F02
The end

2 Answers 2

3
+25

The issue with getBalance2 has to do with the asynchronous web3.eth.getBalance call. You need to make the entire function async and make that call await in order to correctly return a value to your callsite. The return wei line inside the callback is only returning from the callback, it does not propagate out as the return value to getBalance2. I think a fix would look something like this:

export async function getBalance2(address) {
   console.log("debug: helpers/getBalance2-A"); 
    try {
        return await objWeb3.eth.getBalance(address)
    } catch (err) {
        console.log("debug: helpers/getBalance2-E error=" + err);
    }
}

Edit: I was able to get a working version of your code here (the issue was with the rpcURL address -- it had to be http rather than https):

const Web3 = require('web3') 
const rpcURL = 'http://127.0.0.1:7545' 
const objWeb3 = new Web3(rpcURL);

async function getBalance(address) {
   console.log("debug: helpers/getBalance2-A"); 
    try {
        return await objWeb3.eth.getBalance(address)
    } catch (err) {
        console.log("debug: helpers/getBalance2-E error=" + err);
    }
}

async function demo() {
    const address = '0x1D41CB7d963a5B96687e80Be1b23320e40176F02';
    const balance = await getBalance(address);
    console.log(balance);
}

demo();

3
  • Tried your solution; I think I'm getting the timeout, as reported above with the promisify solution. Have to wait for the timeout about 9 times (2 or 3 minutes each) to actually see the error message. So maybe the problem is communicating with Ganache? Commented Oct 24, 2019 at 0:14
  • Error: Timeout of 300000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. The console.log in the catch(err) never displays either. Commented Oct 24, 2019 at 1:07
  • I copied your code over and tested with it. The issue is with this line: const rpcURL = 'https://127.0.0.1:7545' Ganache does not use https, so change that to http.
    – Mark Toda
    Commented Oct 24, 2019 at 20:14
0

The promisify solution looks like a total overkill.

Why not simply call await web3.eth.getBalance(account)?

In any case, the timeout error that you've reported implies that the problem is not in your code, but rather in your system configuration.

So to begin with, make sure that your Ganache process is listening on the same port used by Truffle.

For example, your Ganache configuration should look something like this:

ganache-cli                                                                                      
    --port=8545                                                                                  
    --gasPrice=20000000000                                                                       
    --gasLimit=6721975                                                                           
    --account=0x0000000000000000000000000000000000000000000000000000000000000001,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000002,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000003,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000004,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000005,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000006,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000007,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000008,1000000000000000
    --account=0x0000000000000000000000000000000000000000000000000000000000000009,1000000000000000
    --account=0x000000000000000000000000000000000000000000000000000000000000000a,1000000000000000

While your corresponding Truffle configuration (in file truffle-config.js or truffle.js) should look something like this:

module.exports = {
    networks: {
        development: {
            host:       "localhost",
            port:       8545,
            network_id: "*",         // Match any network id
            gasPrice:   20000000000, // Gas price used for deploys
            gas:        6721975      // Gas limit used for deploys
        }
    }
};

You can add this in order to ensure that your test doesn't fail on timeout:

    mocha: {
        enableTimeouts: false
    }
6
  • That's what I have except port 7545 which is what my Ganache shows. I have updated my question with more code, to try to bring this down to the smallest amount of code to test the eth.getBalance. That code runs, but doesn't show any balance, and no timeout. I could easily be lost in the world of async and promises. Later today, I want to try it in just a node.js program as well, but have to do some work on the job. Commented Oct 24, 2019 at 15:46
  • ethereum.stackexchange.com/questions/39746/… Does Ganache provide a web3 client? I tried installing this: npmjs.com/package/ganache-cli with npm, but it had conflicts with existing providers. Commented Oct 24, 2019 at 16:01
  • Using "web3": "1.0.0-beta.46" because doing a tutorial, and the recommended using all his versions to make sure everything works together. Commented Oct 24, 2019 at 18:10
  • Did a web3 test from Node, results added at bottom of my question. Commented Oct 24, 2019 at 18:21
  • @NealWalters: First, don't use any beta version other than 34 or 37. In fact, you may as well just use v1.2.1. Second, what is this: (err,balance) => console.log("Balance=" + web3.utils.balance)??? Do you understand this JS syntax? It is equivalent to function func(err,balance) {return console.log("Balance=" + web3.utils.balance);}. Note that you're not doing anything with either one of this function's input parameters. Also, what is web3.utils.balance??? I believe that this expression would be undefined. You probably just want to use the input parameter balance instead. Commented Oct 24, 2019 at 19:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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