ether-unit-converter
Version:
The utility functions provide a conversation assortment of common utility functions, and can easily convert Wei to value and value to Wei without a round number.
193 lines (164 loc) • 5.16 kB
JavaScript
/*
Primary Attribution
Richard Moore <ricmoo@me.com>
https://github.com/ethers-io
Note, Richard is a god of ether gods. Follow and respect him, and use Ethers.io!
*/
const BN = require('bn.js');
const numberToBN = require('number-to-bn');
const zero = new BN(0);
const negative1 = new BN(-1);
// complete ethereum unit map
const unitMap = {
0: '0', // eslint-disable-line
1: '10', // eslint-disable-line
2: '100', // eslint-disable-line
3: '1000', // eslint-disable-line
4: '10000', // eslint-disable-line
5: '100000', // eslint-disable-line
6: '1000000', // eslint-disable-line
7: '10000000', // eslint-disable-line
8: '100000000', // eslint-disable-line
9: '1000000000', // eslint-disable-line
10: '10000000000', // eslint-disable-line
11: '100000000000', // eslint-disable-line
12: '1000000000000', // eslint-disable-line
13: '10000000000000', // eslint-disable-line
14: '100000000000000', // eslint-disable-line
15: '1000000000000000', // eslint-disable-line
16: '10000000000000000', // eslint-disable-line
17: '100000000000000000', // eslint-disable-line
18: '1000000000000000000', // eslint-disable-line
19: '10000000000000000000', // eslint-disable-line
20: '100000000000000000000', // eslint-disable-line
21: '1000000000000000000000', // eslint-disable-line
22: '10000000000000000000000', // eslint-disable-line
23: '100000000000000000000000', // eslint-disable-line
24: '1000000000000000000000000', // eslint-disable-line
};
/**
* Returns value of unit in Wei
*
* @method getValueOfUnit
* @param {String} unit the unit to convert to, default ether
* @returns {BigNumber} value of the unit (in Wei)
* @throws error if the unit is not correct:w
*/
function getValueOfUnit(unitInput) {
const unit = unitInput ? unitInput : 18;
var unitValue = unitMap[unit]; // eslint-disable-line
if (typeof unitValue !== 'string') {
throw new Error(
`[ethjs-unit] the unit provided ${unitInput} doesn't exists, please use the one of the following units ${JSON.stringify(
unitMap,
null,
2,
)}`,
);
}
return new BN(unitValue, 10);
}
function numberToString(arg) {
if (typeof arg === 'string') {
if (!arg.match(/^-?[0-9.]+$/)) {
throw new Error(
`while converting number to string, invalid number value '${arg}', should be a number matching (^-?[0-9.]+).`,
);
}
return arg;
} else if (typeof arg === 'number') {
return String(arg);
} else if (
typeof arg === 'object' &&
arg.toString &&
(arg.toTwos || arg.dividedToIntegerBy)
) {
if (arg.toPrecision) {
return String(arg.toPrecision());
} else {
// eslint-disable-line
return arg.toString(10);
}
}
throw new Error(
`while converting number to string, invalid number value '${arg}' type ${typeof arg}.`,
);
}
function fromWei(weiInput, unit, optionsInput) {
var wei = numberToBN(weiInput); // eslint-disable-line
var negative = wei.lt(zero); // eslint-disable-line
const base = getValueOfUnit(unit);
const baseLength = unitMap[unit].length - 1 || 1;
const options = optionsInput || {};
if (negative) {
wei = wei.mul(negative1);
}
var fraction = wei.mod(base).toString(10); // eslint-disable-line
while (fraction.length < baseLength) {
fraction = `0${fraction}`;
}
if (!options.pad) {
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];
}
var whole = wei.div(base).toString(10); // eslint-disable-line
if (options.commify) {
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
var value = `${whole}${fraction == '0' ? '' : `.${fraction}`}`; // eslint-disable-line
if (negative) {
value = `-${value}`;
}
return value;
}
function toWei(etherInput, unit) {
var ether = numberToString(etherInput); // eslint-disable-line
const base = getValueOfUnit(unit);
const baseLength = unitMap[unit].length - 1 || 1;
// Is it negative?
var negative = ether.substring(0, 1) === '-'; // eslint-disable-line
if (negative) {
ether = ether.substring(1);
}
if (ether === '.') {
throw new Error(
`[ethjs-unit] while converting number ${etherInput} to wei, invalid value`,
);
}
// Split it into a whole and fractional part
var comps = ether.split('.'); // eslint-disable-line
if (comps.length > 2) {
throw new Error(
`[ethjs-unit] while converting number ${etherInput} to wei, too many decimal points`,
);
}
var whole = comps[0],
fraction = comps[1]; // eslint-disable-line
if (!whole) {
whole = '0';
}
if (!fraction) {
fraction = '0';
}
if (fraction.length > baseLength) {
throw new Error(
`[ethjs-unit] while converting number ${etherInput} to wei, too many decimal places`,
);
}
while (fraction.length < baseLength) {
fraction += '0';
}
whole = new BN(whole);
fraction = new BN(fraction);
var wei = whole.mul(base).add(fraction); // eslint-disable-line
if (negative) {
wei = wei.mul(negative1);
}
return new BN(wei.toString(10), 10);
}
module.exports = {
unitMap,
numberToString,
getValueOfUnit,
fromWei,
toWei,
};