ethers.js/docs.wrm/api/utils/bignumber.wrm
2020-07-03 01:44:17 -04:00

288 lines
9.5 KiB
Plaintext

_section: BigNumber @<BigNumber>
Many operations in Ethereum operation on numbers which are
[outside the range of safe values](BigNumber--notes-safenumbers) to use
in JavaScript.
A **BigNumber** is an object which safely allows mathematic operations
on numbers of any magnitude.
Most operations which need to return a value will return a **BigNumber**
and parameters which accept values will generally accept them.
_subsection: Types @<BigNumber--types>
_heading: BigNumberish @<BigNumberish>
Many functions and methods in this library take in values which
can be non-ambiguously and safely converted to a BigNumber. These
values can be sepcified as:
_definition: **//string//**
A [[HexString]] or a decimal string, either of which may
be negative.
_definition: **//BytesLike//**
A [[BytesLike]] Object, such as an Array or Uint8Array.
_definition: **//BigNumber//**
An existing [[BigNumber]] instance.
_definition: **//number//**
A number that is within the [safe range](link-js-maxsafe) for JavaScript numbers.
_definition: **//BigInt//**
A JavaScript [BigInt](link-js-bigint)
object, on environments that support BigInt.
_subsection: Creating Instances @<BigNumber--creating>
The constructor of BigNumber cannot be called directly. Instead, Use the static ``BigNumber.from``.
_property: ethers.BigNumber.from(aBigNumberish) => [[BigNumber]]
Returns an instance of a **BigNumber** for //aBigNumberish//.
_heading: Examples: @<>
_code: @lang<javascript>
// From a decimal string...
BigNumber.from("42")
//!
// From a HexString...
BigNumber.from("0x2a")
//!
// From a negative HexString...
BigNumber.from("-0x2a")
//!
// From an Array (or Uint8Array)...
BigNumber.from([ 42 ])
//!
// From an existing BigNumber...
let one1 = constants.One;
let one2 = BigNumber.from(one1)
one2
//!
// ...which returns the same instance
one1 === one2
//!
// From a (safe) number...
BigNumber.from(42)
//!
// From a ES2015 BigInt... (only on platforms with BigInt support)
BigNumber.from(42n)
//!
// Numbers outside the safe range fail:
BigNumber.from(Number.MAX_SAFE_INTEGER);
//! error
_subsection: Methods @<BigNumber--methods>
The BigNumber class is immutable, so no operations can change the value
it represents.
_heading: Math Operations
_property: BigNumber.add(otherValue) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// **+** //otherValue//.
_property: BigNumber.sub(otherValue) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// **-** //otherValue//.
_property: BigNumber.mul(otherValue) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// **&times;** //otherValue//.
_property: BigNumber.div(divisor) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// **&div;** //divisor//.
_property: BigNumber.mod(divisor) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of the **remainder** of //BigNumber// &div; //divisor//.
_property: BigNumber.pow(exponent) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// to the power of //exponent//.
_property: BigNumber.abs() => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the absolute value of //BigNumber//.
_property: BigNumber.mask(bitcount) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// with bits beyond
the //bitcount// least significant bits set to zero.
_heading: Two's Compliment
[Two's Complicment](link-wiki-twoscomplement)
is an elegant method used to encode and decode fixed-width signed values
while efficiently preserving mathematic operations.
Most users will not need to interact with these.
_property: BigNumber.fromTwos(bitwidth) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// converted from twos-compliment with //bitwidth//.
_property: BigNumber.toTwos(bitwidth) => [[BigNumber]] @SRC<bignumber>
Returns a BigNumber with the value of //BigNumber// converted to twos-compliment with //bitwidth//.
_heading: Comparison and Equivalence
_property: BigNumber.eq(otherValue) => boolean @SRC<bignumber>
Returns true if and only if the value of //BigNumber// is equal to //otherValue//.
_property: BigNumber.lt(otherValue) => boolean @SRC<bignumber>
Returns true if and only if the value of //BigNumber// **<** //otherValue//.
_property: BigNumber.lte(otherValue) => boolean @SRC<bignumber>
Returns true if and only if the value of //BigNumber// **&le;** //otherValue//.
_property: BigNumber.gt(otherValue) => boolean @SRC<bignumber>
Returns true if and only if the value of //BigNumber// **>** //otherValue//.
_property: BigNumber.gte(otherValue) => boolean @SRC<bignumber>
Returns true if and only if the value of //BigNumber// **&ge;** //otherValue//.
_property: BigNumber.isZero() => boolean @SRC<bignumber:BigNumber.isZero>
Returns true if and only if the value of //BigNumber// is zero.
_heading: Conversion
_property: BigNumber.toNumber() => number @SRC<bignumber>
Returns the value of //BigNumber// as a JavaScript value.
This will **throw an error**
if the value is greater than or equal to //Number.MAX_SAFE_INTEGER// or less than or
equal to //Number.MIN_SAFE_INTEGER//.
_property: BigNumber.toString() => string @SRC<bignumber:BigNumber.toString>
Returns the value of //BigNumber// as a base-10 string.
_property: BigNumber.toHexString() => string<[[DataHexString]]> @SRC<bignumber:BigNumber.toHexString>
Returns the value of //BigNumber// as a base-16, ``0x``-prefixed [[DataHexString]].
_heading: Inspection
_property: ethers.BigNumnber.isBigNumber(object) => boolean @SRC<bignumber>
Returns true if and only if the //object// is a BigNumber object.
_heading: Examples
_code: @lang<javascript>
let a = BigNumber.from(42);
let b = BigNumber.from("91");
a.mul(b);
//!
_subsection: Notes @<BigNumber--notes>
This section is a for a couple of questions that come up frequently.
_heading: Why can't I just use numbers? @<BigNumber--notes-safenumbers>
The first problem many encounter when dealing with Ethereum is
the concept of numbers. Most common currencies are broken down
with very little granularity. For example, there are only 100
cents in a single dollar. However, there are 10^^18^^ **wei** in a
single **ether**.
JavaScript uses [IEEE 754 double-precision binary floating point](link-wiki-ieee754)
numbers to represent numeric values. As a result, there are //holes//
in the integer set after 9,007,199,254,740,991; which is
problematic for //Ethereum// because that is only around 0.009
ether (in wei), which means any value over that will begin to
experience rounding errors.
To demonstrate how this may be an issue in your code, consider:
_code: @lang<javascript>
(Number.MAX_SAFE_INTEGER + 2 - 2) == (Number.MAX_SAFE_INTEGER)
//!
_null:
To remedy this, all numbers (which can be large) are stored
and manipulated as [Big Numbers](BigNumber).
The functions [parseEther( etherString )](utils-parseEther) and
[formatEther( wei )](utils-formatEther) can be used to convert
between string representations, which are displayed to or entered
by the user and Big Number representations which can have
mathematical operations handled safely.
_heading: Why not BigNumber.js, BN.js, BigDecimal, etc?
Everyone has their own favourite Big Number library, and once someone
has choosen one, it becomes part of their identity, like their editor,
vi vs emacs. There are over 100 Big Number libraries on [npm](link-npm-query-bignumber).
One of the biggest differences between the Ethers [[BigNumber]] object and
other libraries is that it is immutable, which is very important when
dealing with the asynchronous nature of the blockchain.
Capturing the value is not safe in async functions, so immutability
protects us from easy to make mistakes, which is not possible on the
low-level library's objects which supports myriad in-place operations.
Second, the Ethers [[BigNumber]] provides all the functionality required
internally and should generally be sufficient for most developers while
not exposing some of the more advanced and rare functionality. So it will
be eaiser to swap out the underlying library without impacting consumers.
For example, if [[link-npm-bnjs]] was exposed, someone may use the
greatest-common-denominator functions, which would then be functionality
the replacing library should also provide to ensure anyone depending on
that functionality is not broken.
_heading: Why BN.js??
The reason why [[link-npm-bnjs]] is used internally as the big
number is because that is the library used by [[link-npm-elliptic]].
Therefore it **must** be included regardless, so we leverage that
library rather than adding another Big Number library, which would
mean two different libraries offering the same functionality.
This has saved about 85kb (80% of this library size) of library size
over other libraries which include separate Big Number libraries for
various purposes.
_heading: Allow us to set a global Big Number library?
Another comment that comes up frequently is tha desire to specify a
global user-defined Big Number library, which all functions would
return.
This becomes problematic since your code may live along side other
libraries or code that use Ethers. In fact, even Ethers uses a lot
of the public functions internally.
If you, for example, used a library that used ``a.plus(b)`` instead
of ``a.add(b)``, this would break Ethers when it tries to compute
fees internally, and other libraries likely have similar logic.
But, the [[BigNumber]] prototype is exposed, so you can always add a
``toMyCustomBigNumber()`` method to all [[BigNumber]]'s globally
which is safe.