0

I am using web3 v1.0.27 and trying to send erc20 tokens. These tokens have a decimal of 18 but might have a different decimal. Trying to keep it generic. I have tried the following.

  const amountToSendinDecimal = amountToSend * Math.pow(10, decimal);
  const amountToSendinDecimalBN = new BigNumber(amountToSendinDecimal);

With a decimal of 18 and value of 3178.44. I keep on getting the following error.

[BigNumber Error] Number primitive has more than 15 significant digits: 3.1784400000000003e+21

Cannot seems to find a work around for it.

Any suggestions.

1

When you have web3 js, you can do it with either of the following ways.

var amountToSend = 2;
var weiAmout = amountToSend * 1e18;
var weiAmount2 = web3.toWei(amountToSend);
  • Thanks. I used a mixture or your solution and BigNumber utils. – A Gilani Mar 3 '18 at 12:14
2

The following code does this conversion carefully. It takes a BN constructor because I/you don't want to pull in a separate BN library or build web3, so you should pass it (for example) toBaseUnit("0.01", 18, web3.utils.BN)

function isString(s) {
  return (typeof s === 'string' || s instanceof String)
}

export function toBaseUnit(value, decimals, BN) {
  if (!isString(value)) {
    throw new Error('Pass strings to prevent floating point precision issues.')
  }
  const ten = new BN(10);
  const base = ten.pow(new BN(decimals));

  // Is it negative?
  let negative = (value.substring(0, 1) === '-');
  if (negative) {
    value = value.substring(1);
  }

  if (value === '.') { 
    throw new Error(
    `Invalid value ${value} cannot be converted to`
    + ` base unit with ${decimals} decimals.`); 
  }

  // Split it into a whole and fractional part
  let comps = value.split('.');
  if (comps.length > 2) { throw new Error('Too many decimal points'); }

  let whole = comps[0], fraction = comps[1];

  if (!whole) { whole = '0'; }
  if (!fraction) { fraction = '0'; }
  if (fraction.length > decimals) { 
    throw new Error('Too many decimal places'); 
  }

  while (fraction.length < decimals) {
    fraction += '0';
  }

  whole = new BN(whole);
  fraction = new BN(fraction);
  let wei = (whole.mul(base)).add(fraction);

  if (negative) {
    wei = wei.neg();
  }

  return new BN(wei.toString(10), 10);
}
  • noice. This handles big values nicely – alsco77 Nov 22 '18 at 6:36
-1

I used the following code to come around the issue

private _fromDecimal = (value) => { const decimal = 18; const amountToSendinDecimal = value * ( 10 ** decimal) ; return this.toBigNumber(amountToSendinDecimal); };

  • In this example value must be divided, not multiplied. Also, it will fail on some values as was specified in original question. – Aldekein Aug 2 at 13:49

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.