AmountMath
Depositing and withdrawing assets from a purse and manipulating payment amounts all require adding and subtracting digital assets. ERTP uses the AmountMath library for all these operations.
The AmountMath library functions work for both fungible and nonfungible tokens. There are two AssetKinds, each of which implements the same methods. Which kind is used for a particular brand depends on what was specified when the brand and its issuer were created. They are:
AssetKind.NAT("nat"): Used with fungible assets. Values are natural numbers using the JavaScript BigInt type to avoid overflow risks from using the usual JavaScriptNumbertype.AssetKind.SET("set"): Used with non-fungible assets. Values are copyArrays such as hardened arrays of strings.
AmountMath Methods
The following is a brief description and example of each AmountMath method. For more detail, click the method's name to go to its entry in the ERTP API Reference.
Note that many methods have a brand argument, either required or optional. Where optional, use the brand you got from an issuer (or from Zoe) to add verification that the brand of "amount" argument(s) corresponds with that brand.
- Information Getting Methods
- AmountMath.getValue(brand, amount)
- Returns the
valueof theamountargument. For fungible assets, this will be aBigInt. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); const quatloos123 = AmountMath.make(quatloosBrand, 123n); // returns 123 const value = AmountMath.getValue(quatloosBrand, quatloos123);
- Returns the
- AmountMath.getValue(brand, amount)
- Comparison Methods
- AmountMath.isEmpty(amount, brand?)
- Returns
trueif itsamountargument is empty, otherwisefalse. Throws an error if the optionalbrandargument isn't the same as theamountargument brand. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); const empty = AmountMath.makeEmpty(quatloosBrand, AssetKind.NAT); const quatloos1 = AmountMath.make(quatloosBrand, 1n); // returns true AmountMath.isEmpty(empty); // returns false AmountMath.isEmpty(quatloos1);
- Returns
- AmountMath.isGTE(leftAmount, rightAmount, brand?)
- Returns
trueif theleftAmountargument is greater than or equal to therightAmountargument, otherwisefalse. Throws an error if the optionalbrandargument isn't the same as theamountarguments brands. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); const empty = AmountMath.makeEmpty(quatloosBrand, AssetKind.NAT); const quatloos1 = AmountMath.make(quatloosBrand, 1n); // Returns true AmountMath.isGTE(quatloos1, empty); // Returns false AmountMath.isGTE(empty, quatloos1);
- Returns
- AmountMath.isEqual(leftAmount, rightAmount, brand?)
- Returns
trueif theleftAmountargument equals therightAmountargument. Throws an error if the optionalbrandargument isn't the same as theamountarguments brands. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); const empty = AmountMath.makeEmpty(quatloosBrand, AssetKind.NAT); const quatloos1 = AmountMath.make(quatloosBrand, 1n); const anotherQuatloos1 = AmountMath.make(quatloosBrand, 1n); // Returns true AmountMath.isEqual(quatloos1, anotherQuatloos1); // Returns false AmountMath.isEqual(empty, quatloos1);
- Returns
- AmountMath.coerce(brand, allegedAmount)
- Takes an
amountand returns it if it's a validamount. If invalid, it throws an error. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); const quatloos50 = AmountMath.make(quatloosBrand, 50n); AmountMath.coerce(quatloosBrand, quatloos50); // equal to quatloos50
- Takes an
- AmountMath.isEmpty(amount, brand?)
- Manipulator Methods
- AmountMath.add(leftAmount, rightAmount, brand?)
- Returns an
amountthat is the union of theleftAmountandrightAmountamountarguments. For a fungibleamount, this means add their values. For a non-fungibleamount, it usually means including all elements from bothleftAmountandrightAmount. Throws an error if the optionalbrandargument isn't the same as theamountarguments brands. - js
const { brand: myItemsBrand } = makeIssuerKit('myItems', 'set'); const listAmountA = AmountMath.make(myItemsBrand, harden(['1', '2', '4'])); const listAmountB = AmountMath.make(myItemsBrand, harden(['3'])); // Returns an amount containing all of ['1', '2', '4', '3'] const combinedList = AmountMath.add(listAmountA, listAmountB);
- Returns an
- AmountMath.subtract(leftAmount, rightAmount, brand?)
- Returns a new
amountthat is theleftAmountargument minus therightAmountargument (i.e., for strings or objects everything inleftAmountnot inrightAmount). IfleftAmountdoesn't include the contents ofrightAmount, it throws an error. It also throws an error if the optionalbrandargument isn't the same as theamountarguments brands. - js
const { brand: myItemsBrand } = makeIssuerKit('myItems', 'set'); const listAmountA = AmountMath.make(myItemsBrand, harden(['1', '2', '4'])); const listAmountB = AmountMath.make(myItemsBrand, harden(['3'])); const listAmountC = AmountMath.make(myItemsBrand, harden(['2'])); // Returns ['1', '4'] const subtractedList = AmountMath.subtract(listAmountA, listAmountC); // Throws error t.throws(() => AmountMath.subtract(listAmountA, listAmountB), { message: /right element .* was not in left/, });
- Returns a new
- AmountMath.add(leftAmount, rightAmount, brand?)
- Amount Creation Methods
- AmountMath.make(brand, allegedValue)
- Takes a
valueargument and returns anamountby making a record with thevalueand thebrandassociated with theAmountMath. Thevalueargument should be represented as aBigInte.g.10nrather than10. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); /// An `amount` with `value` = 837 and `brand` = Quatloos const quatloos837 = AmountMath.make(quatloosBrand, 837n); const anotherQuatloos837 = harden({ brand: quatloosBrand, value: 837n }); t.deepEqual(quatloos837, anotherQuatloos837);
- Takes a
- AmountMath.makeEmpty(brand, assetKind)
- Returns an
amountrepresenting an emptyamount, which is the identity element for theAmountMathadd()andsubtract()operations. Note that this value varies depending on thebrandand whether it is of kindAssetKind.NATorAssetKind.SET. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); // Returns an empty amount for this issuer. // Since this is a fungible amount it returns 0 const empty = AmountMath.makeEmpty(quatloosBrand, AssetKind.NAT);
- Returns an
- AmountMath.makeEmptyFromAmount(amount)
- Returns an
amountrepresenting an emptyamount, using anotheramountas the template for the new empty amount'sbrandandassetKind. - js
const { brand: quatloosBrand } = makeIssuerKit('quatloos'); // Returns an empty amount for this issuer. // Since this is a fungible amount it returns 0 const empty = AmountMath.makeEmpty(quatloosBrand, AssetKind.NAT); // quatloosAmount837 = { value: 837n, brand: quatloos } const quatloosAmount837 = AmountMath.make(quatloosBrand, 837n); // Returns an amount = { value: 0n, brand: quatloos } const quatloosAmount0 = AmountMath.makeEmptyFromAmount(quatloosAmount837);
- Returns an
- AmountMath.make(brand, allegedValue)
Methods On Other Objects
These methods return an AssetKind:
- anIssuer.getAssetKind()
- Returns the
AssetKindof theissuer'sbrand. (AssetKind.NATorAssetKind.SET). - js
const myAssetKind = quatloosIssuer.getAssetKind();
- Returns the
- zcf.getAssetKind(brand)
- Returns the
AssetKindof thebrandargument. - js
const quatloosAssetKind = zcf.getAssetKind(quatloosBrand);
- Returns the