# Amount Math

AmountMath methods

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 amountMathKinds, 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:

  • MathKind.NAT (nat): Used with fungible assets. amount values are natural numbers (non-negative BigInts).
  • MathKind.SET (set): Used with non-fungible assets. amount values are arrays with any number of strings, numbers, etc.

makeIssuerKit(allegedName, amountMathKind, displayInfo=) creates a new issuer, mint, and brand.

The second, optional, amountMathKind argument specifies which kind of amountMath is used for the brand in a one-to-one association with the new issuer. It defaults to MathKind.NAT.

The third, optional, displayInfo argument tells the UI how to display values associated with the created brand. It defaults to undefined.

For example:

makeIssuerKit('Quatloos'); // Defaults to MathKind.NAT
makeIssuerKit('Quatloos', MathKind.SET);

Note that many amountMath methods have a brand argument, either required or optional. For the ones with an optional brand argument, you should use it if you need to do an "absolute" check on the brand in the amount argument(s). In this case, you want to use the brand you got from the issuer (or from Zoe) as the optional parameter to compare the amount brand(s) to.

# 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.

  • Information Getting Methods
    • amountMath.getValue(brand, amount)
      • Returns the value of the amount argument. For fungible assets, this will be a BigInt.
      • const { brand: quatloosBrand } = makeIssuerKit('quatloos');
        const quatloos123 = amountMath.make(quatloosBrand, 123n);
        // returns 123
        const value = amountMath.getValue(quatloosBrand, quatloos123);
  • Comparison Methods
    • amountMath.isEmpty(amount, brand?)
      • Returns true if its amount argument is empty, otherwise false. Throws an error if the optional brand argument isn't the same as the amount argument brand.
      • const { brand: quatloosBrand } = makeIssuerKit('quatloos');
        const empty = amountMath.makeEmpty(quatloosBrand, MathKind.NAT);
        const quatloos1 = amountMath.make(quatloosBrand, 1n);
        // returns true
        amountMath.isEmpty(empty);
        // returns false
        amountMath.isEmpty(quatloos1);
    • amountMath.isGTE(leftAmount, rightAmount, brand?)
      • Returns true if the leftAmount argument is greater than or equal to the rightAmount argument, otherwise false. Throws an error if the optional brand argument isn't the same as the amount arguments brands.
      • const { brand: quatloosBrand } = makeIssuerKit('quatloos');
        const empty = amountMath.makeEmpty(quatloosBrand, MathKind.NAT);
        const quatloos1 = amountMath.make(quatloosBrand, 1n);
        // Returns true
        amountMath.isGTE(quatloos1, empty);
        // Returns false
        amountMath.isGTE(empty, quatloos1);
    • amountMath.isEqual(leftAmount, rightAmount, brand?)
      • Returns true if the leftAmount argument equals the rightAmount argument. Throws an error if the optional brand argument isn't the same as the amount arguments brands.
      • const { brand: quatloosBrand } = makeIssuerKit('quatloos');
        const empty = amountMath.makeEmpty(quatloosBrand, MathKind.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);
    • amountMath.coerce(brand, allegedAmount)
      • Takes an amount and returns it if it's a valid amount. If invalid, it throws an error.
      • const { brand: quatloosBrand } = makeIssuerKit('quatloos');
        const quatloos50 = amountMath.make(quatloosBrand, 50n);
        amountMath.coerce(quatloosBrand, quatloos50); // equal to quatloos50
  • Manipulator Methods
    • amountMath.add(leftAmount, rightAmount, brand?)
      • Returns an amount that is the union of the leftAmount and rightAmount amount arguments. For a fungible amount, this means add their values. For a non-fungible amount, it usually means including all elements from both leftAmount and rightAmount. Throws an error if the optional brand argument isn't the same as the amount arguments brands.
      • 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);
    • amountMath.subtract(leftAmount, rightAmount, brand?)
      • Returns a new amount that is the leftAmount argument minus the rightAmount argument (i.e. for strings or objects everything in leftAmount not in rightAmount). If leftAmount doesn't include the contents of rightAmount, it throws an error. It also throws an error if the optional brand argument isn't the same as the amount arguments brands.
      • const { brand: myItemsBrand } = makeIssuerKit('myItems', 'set');
        const listAmountA = amountMath.make(myItemsBrand, ['1', '2', '4']);
        const listAmountB = amountMath.make(myItemsBrand, ['3']);
        const listAmountC = amountMath.make(myItemsBrand, ['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/,
        });
  • Amount Creation Methods
    • amountMath.make(brand, allegedValue)
      • Takes a value argument and returns an amount by making a record with the value and the brand associated with the amountMath. The value argument should be represented as a BigInt e.g. 10n rather than 10.
      • 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);
    • amountMath.makeEmpty(brand, mathKind)
      • Returns an amount representing an empty amount, which is the identity element for the amountMath add() and subtract() operations. Note that this value varies depending on the brand and whether it is of kind MathKind.NAT or MathKind.SET.
      • 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, MathKind.NAT);
    • amountMath.makeEmptyFromAmount(amount)
      • Returns an amount representing an empty amount, using another amount as the template for the new empty amount's brand and mathKind.
      • 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, MathKind.NAT);
        // quatloosAmount837 = { value: 837n, brand: quatloos }
        const quatloosAmount837 = amountMath.make(quatloosBrand, 837n);
        // Returns an amount = { value: 0n, brand: quatloos }
        const quatloosAmount0 = amountMath.makeEmptyFromAmount(quatloosAmount837);

# Methods on other objects

These methods return a MathKind:

  • issuer.getAmountMathKind()
    • Returns the MathKind of the issuer's brand. (MathKind.NAT or MathKind.SET).
    •   const myAmountMathKind = quatloosIssuer.getAmountMathKind();
  • zcf.getMathKind(brand)
    • Returns the MathKind of the brand argument.
    •   const quatloosMathKind = zcf.getMathKind(quatloosBrand);