Unit conversion
Internally, we use Arbitrary-precision arithmetic (also known as Big Number arithmetic) to allow for the handling of large numbers and different assets.
On the Fuel network, we work with 9 decimals to represent amounts under a unit. This differs from chain to chain, so it is important to know the number of decimals used on the chain you are working with.
Note: The package
@fuels/assets
provides a list of assets and their decimals.
Below we will go over some common use cases for unit conversion.
Using our BN
class we can instantiate these numbers.
const myBigNumberOne = '100000000';
const resultOne = new BN('100000000').toString();
console.assert(resultOne === myBigNumberOne, 'BN is not equal to expected');
Or using our bn
utility function.
const resultTwo = bn('100000000').toString();
console.assert(resultTwo === myBigNumberTwo, 'BN is not equal to expected');
Contract calls
Generally, we will need to convert u64
and u256
numbers to a BN
object when passing them to a Sway program from JavaScript. More information on this can be found here.
// Let's deploy a contract that has a function that takes a u64 as input
const provider = await Provider.create(LOCAL_NETWORK_URL);
const wallet = await Wallet.fromPrivateKey(WALLET_PVT_KEY, provider);
const deployedContract = await new EchoValuesFactory(wallet).deploy();
const { contract } = await deployedContract.waitForResult();
const MAX_U64 = bn('18446744073709551615');
const { waitForResult } = await contract.functions.echo_u64(MAX_U64).call();
const { value } = await waitForResult();
console.assert(value.toString() === MAX_U64.toString(), 'BN is not equal to expected');
Note: If a contract call returns a number that is too large to be represented as a JavaScript number, you can convert it to a string using the
toString
method instead oftoNumber
.
Parsing
Parsing string-represented numbers (from user input) has never been easier, than using the parseUnits
function.
const resultThree = bn.parseUnits('0.000000001').toString();
console.assert(resultThree === myBigNumberThree, 'BN is not equal to expected');
We can parse large numbers.
const myBigNumberFour = '100100000000000';
const resultFour = bn.parseUnits('100100').toString();
console.assert(resultFour === myBigNumberFour, 'BN is not equal to expected');
Or numbers formatted for human readability.
const myBigNumberFive = '100100000200001';
const resultFive = bn.parseUnits('100,100.000200001').toString();
console.assert(resultFive === myBigNumberFive, 'BN is not equal to expected');
We can also parse numbers in other units of measure.
const myBigNumberSix = '1000000000';
const resultSix = bn.parseUnits('1', DECIMAL_GWEI).toString();
console.assert(resultSix === myBigNumberSix, 'BN is not equal to expected');
Formatting
We can format common units of measure using the format
function.
In the following example, we format a BigNumber representation of one Gwei, into units for the Fuel network (with 3 decimal place precision).
const myBigNumberSeven = '1.000';
const oneGwei = bn('1000000000');
const resultSeven = oneGwei.format();
console.assert(resultSeven === myBigNumberSeven, 'BN is not equal to expected');
We can also format numbers in other units of measure by specifying the units
variable.
const myBigNumberEight = '2.000';
const twoGwei = bn('2000000000');
const resultEight = twoGwei.format({ units: DECIMAL_GWEI });
console.assert(resultEight === myBigNumberEight, 'BN is not equal to expected');
A precision
variable will allow for the formatting of numbers with a specific number of decimal places.
const oneDecimalGwei = '1.0';
const formattedGwei = oneGwei.format({ precision: 1 });
console.assert(formattedGwei === oneDecimalGwei, 'BN is not equal to expected');
Format units
The formatUnits
function is a lesser alternative to the format
function, as it will maintain the same precision as the input value.
const myFormattedGwei = '1.000000000';
const formattedUnitsGwei = oneGwei.formatUnits();
console.assert(formattedUnitsGwei === myFormattedGwei, 'BN is not equal to expected');
We can also format numbers in other units of measure by specifying the units
variable.
const myFormattedKwei = '1.000000000000000';
const oneKwei = bn('1000000000000000');
const formattedUnitsKwei = oneKwei.formatUnits(DECIMAL_KWEI);
console.assert(formattedUnitsKwei === myFormattedKwei, 'BN is not equal to expected');
See also
Full Example
For the full example of unit conversion see the snippet below:
import { BN, DECIMAL_GWEI, DECIMAL_KWEI, bn, Provider, Wallet } from 'fuels';
import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from '../env';
import { EchoValuesFactory } from '../typegend/contracts/EchoValuesFactory';
const myBigNumberOne = '100000000';
const resultOne = new BN('100000000').toString();
console.assert(resultOne === myBigNumberOne, 'BN is not equal to expected');
const myBigNumberTwo = '100000000';
const resultTwo = bn('100000000').toString();
console.assert(resultTwo === myBigNumberTwo, 'BN is not equal to expected');
// Let's deploy a contract that has a function that takes a u64 as input
const provider = await Provider.create(LOCAL_NETWORK_URL);
const wallet = await Wallet.fromPrivateKey(WALLET_PVT_KEY, provider);
const deployedContract = await new EchoValuesFactory(wallet).deploy();
const { contract } = await deployedContract.waitForResult();
const MAX_U64 = bn('18446744073709551615');
const { waitForResult } = await contract.functions.echo_u64(MAX_U64).call();
const { value } = await waitForResult();
console.assert(value.toString() === MAX_U64.toString(), 'BN is not equal to expected');
const myBigNumberThree = '1';
const resultThree = bn.parseUnits('0.000000001').toString();
console.assert(resultThree === myBigNumberThree, 'BN is not equal to expected');
const myBigNumberFour = '100100000000000';
const resultFour = bn.parseUnits('100100').toString();
console.assert(resultFour === myBigNumberFour, 'BN is not equal to expected');
const myBigNumberFive = '100100000200001';
const resultFive = bn.parseUnits('100,100.000200001').toString();
console.assert(resultFive === myBigNumberFive, 'BN is not equal to expected');
const myBigNumberSix = '1000000000';
const resultSix = bn.parseUnits('1', DECIMAL_GWEI).toString();
console.assert(resultSix === myBigNumberSix, 'BN is not equal to expected');
const myBigNumberSeven = '1.000';
const oneGwei = bn('1000000000');
const resultSeven = oneGwei.format();
console.assert(resultSeven === myBigNumberSeven, 'BN is not equal to expected');
const myBigNumberEight = '2.000';
const twoGwei = bn('2000000000');
const resultEight = twoGwei.format({ units: DECIMAL_GWEI });
console.assert(resultEight === myBigNumberEight, 'BN is not equal to expected');
const oneDecimalGwei = '1.0';
const formattedGwei = oneGwei.format({ precision: 1 });
console.assert(formattedGwei === oneDecimalGwei, 'BN is not equal to expected');
const myFormattedGwei = '1.000000000';
const formattedUnitsGwei = oneGwei.formatUnits();
console.assert(formattedUnitsGwei === myFormattedGwei, 'BN is not equal to expected');
const myFormattedKwei = '1.000000000000000';
const oneKwei = bn('1000000000000000');
const formattedUnitsKwei = oneKwei.formatUnits(DECIMAL_KWEI);
console.assert(formattedUnitsKwei === myFormattedKwei, 'BN is not equal to expected');