Search code examples
javascriptethereumweb3js

Web3.js BigNumber not working for large power exponent


I am getting the error

Uncaught (in promise) Error: Assertion failed

specifically where it's checking inside of BN.js:

function assert (val, msg) {
    if (!val) throw new Error(msg || 'Assertion failed');
}

I am receiving a number to the power of 29, which is meant to have 18 decimal places, that I want to convert into a "non-decimal" number similar with wei and eth:

const post_response_2 = await fetch('/balanceOf-TKN-by-addr', {method: 'POST', body: stringify_post_input, headers: { "content-type": "application/json" } });
var TKN_balance_response = await post_response_2.json(); 
console.log(TKN_balance_response);
var TKN_BN = await new BN(TKN_balance_response).toString();      //line giving error
var TKN_balance = await web3.utils.fromWei(TKN_BN, 'ether');
console.log("TKN_balance :: "+String(TKN_balance));

On my server side, I get the response of 988699999999999976500000000000, and in the client console.log above, I see 9.886999999999999e+29.

What am I doing wrong with BN.js?

Since there are 18 decimal places, I expect the answer for this that I console.log to be 988699999999.999976500000000000, then I'd round be able to round it, etc.


Solution

  • BN.js doesn't accept values in the exponential form (in your case the 9.886999999999999e+29).

    You can convert the expenential form to a string representing of the full number using the .toLocaleString() native function.

    // type `Number`
    const TKN_balance_response = 9.886999999999999e+29;
    // type `string`
    const TKN_balance_response_string = TKN_balance_response.toLocaleString('fullwide', {useGrouping:false});
    var TKN_BN = await new BN(TKN_balance_response_string).toString();
    console.log(TKN_BN);
    

    prints

    988699999999999900000000000000
    

    A cleaner solution would be to return the (large number) value from /balanceOf-TKN-by-addr endpoint already as a string (my guess based on the context is that it's returned as a Number or it's converted to Number by the json() function). Then you could pass it to the BN.js constructor as is:

    const TKN_balance_response = '988699999999999976500000000000';
    var TKN_BN = await new BN(TKN_balance_response).toString();