diff --git a/README.md b/README.md index 32a2753..a32a9c2 100644 --- a/README.md +++ b/README.md @@ -101,3 +101,169 @@ const id = await aoCredToken.transfer( console.log("The transfer ID is", id); ``` + +### Quantities + +The `Quantity` class is an implementation of floating point numbers with extreme precision. It works by storing a `bigint` instance as the raw value for token quantities. This is the same value the token process works with, so it makes operations and calculations extremely easy. It helps implementing logic for tokens on the front-end by abstracting calculations with the token denomination away from the developer, executing these within the library. + +A quantity first needs to be initialised with the raw quantity provided by the token process (or `0`) and the token denomination: + +```ts +// init 0 quantity for a specific denomination +const quantity = new Quantity(0n, token.info.Denomination); +``` + +If you already have a `Token` instance in scope, you can also use the shortcut [mentioned above](#token-quantity) to initialise a new quantity that belongs to the token process. + +#### Raw + +This is one of the most important fields of the `Quantity` class. It is a raw `bigint` value that must be used when communicating with a token process, as this is in the same format that token processes use internally for managing balances. For example, if you want to use [`@permaweb/aoconnect`](https://npmjs.com/@permaweb/aoconnect) to transfer tokens, instead of the [built in transfer](#transfer) function, you need to provide the raw value to the message: + +```ts +// 751.34 CRED tokens +const quantity = aoCredToken.Quantity.fromString("752.34"); + +// send these tokens to someone +await message({ + // token process ID + process: "Sa0iBLPNyJQrwpTTG-tWLQU-1QeUAJA73DdxGGiKoJc", + // browser wallet signer + signer: createDataItemSigner(window.arweaveWallet), + tags: [ + { name: "Action", value: "Transfer" }, + { name: "Recipient", value: "XjvCPN31XCLPFBo9FUeB7vAK0VC6TwY52MCS-6Iho8h" }, + // + // notice how we use the raw value + { name: "Quantity", value: quantity.raw.toString() } + // + ] +}); +``` + +#### Other getters + +These getters are also accessible from a `Quantity` instance. + +- `integer`: Get the integer/whole part of the quantity (for e.g. for `115.67` this will return `115n`) +- `fractional`: Get the fractional part of the quantity in integer (for e.g. for `115.67` this will return `67n`) +- `denomination`: The token denomination this instance uses for calculations + +#### `isQuantity()` + +Get if a provided value is a valid `Quantity` instance: + +```ts +// will return false +Quantity.isQuantity(15); + +// wil return true +Quantity.isQuantity(new Quantity(15n, 4n)); +``` + +#### `isQuantityOf()` + +Get if a provided value is a valid `Quantity` of a `Token` instance. This will compare the denomination used in the provided `Quantity` instance: + + +```ts +// CRED has a denomination of 3 + +// this will return false +Quantity.isQuantityOf(new Quantity(345n, 12n), aoCredToken); + +// this will return true +Quantity.isQuantityOf(new Quantity(9456n, 3n), aoCredToken); +``` + +#### `fromString()` + +Parse a quantity from a string: + +```ts +aoCredToken.Quantity.fromString("256.8"); +``` + +#### `fromNumber()` + +Parse a quantity from a JS number: + +```ts +aoCredToken.Quantity.fromNumber(256.8); +``` + +#### `toString()` + +Get the stringified quantity: + +```ts +const qty = aoCredToken.Quantity.fromNumber(74.089); + +// prints "74.089" +console.log(qty.toString()); +``` + +#### `toLocaleString()` + +Print formatted string according to the provided/default locale: + +```ts +const qty = aoCredToken.Quantity.fromNumber(1474.089); + +// prints "1,474.089" +console.log(qty.toString()); +``` + +#### `toNumber()` + +Get JS native floating point value held in a quantity. This can cause precision loss: + +```ts +qty.toNumber(); +``` + +#### `clone()` + +Clone the `Quantity` instance. This will keep the same value and denomination: + +```ts +// 1.2 with 1 as the denomination +const qty = new Quantity(12n, 1n); + +const qty2 = qty.clone(); +qty2.fromNumber(4); + +// prints "1.2" +console.log("qty is", qty.toString()); + +// prints "4" +console.log("qty2 is", qty2.toString()); +``` + +#### Math and utilities + +These functions have both static and non-static implementations. Static implementations will always start with two "`_`" and create new `Quantity` instances. Non-static implementations start with one "`_`" and modify themselves (the instances they are associated with). + +##### Math operators + +- `eq()`: Check if two quantities are equal +- `lt()`: Check if the first quantity is less than the second +- `le()`: Check if the first quantity is less or equal than the second +- `_add()` and `__add`: Add together two quantities +- `_sub()` and `__sub`: Subtract one quantity from another +- `_mul()` and `__mul()`: Multiply two quantities +- `_div()` and `__div()`: Divide one quantity by another +- `_pow()` and `__pow()`: Raise one quantity to the power of an integer +- `_mod()` and `__mod()`: Get the remainder of the division of one quantity by another +- `_neg()` and `__neg()`: Get the negation of a quantity +- `_abs()` and `__abs()`: Get the absolute value of a quantity +- `_trunc()` and `__trunc()`: Truncate a quantity +- `_floor()` and `__floor()`: Round down a quantity +- `_ceil()` and `__ceil()`: Round up a quantity + +##### Utilities + +- `_one()` and `__one()`: Shortcut to "1" according to the denomination +- `_convert()` and `__convert()`: Convert to a different denomination +- `sameDenomination()`: Ensure that the provided quantities all have the same denomination. Returns an array of quantities converted to the largest denomination from the provided quantities. +- `min()`: Get the minimum of a list of quantities +- `max()`: Get the maximum of a list of quantities