# Issuer

An issuer is the authority on what holds digital assets of its kind. While it cannot create new value by creating digital assets like a mint, it recognizes and identifies purses and payments that carry actual value. It can create empty purses and transform payments (by splitting, combining, burning, or exclusively claiming).

An issuer has an unchangeable one-to-one relationship with the mint and brand that were created with it. For any brand for which you will accept payments in, you should obtain its issuer from a trusted source. You can then rely on that issuer as the authority to validate an untrusted payment of that brand.

Note: You should not create an Issuer in a deploy script. Deploy scripts are ephemeral, so any object created there dies as soon as the script stops.

# makeIssuerKit(allegedName, assetKind, displayInfo)

  • allegedName {String}
  • assetKind {AssetKind} - optional, defaults to AssetKind.NAT
  • displayInfo {DisplayInfo} - optional, defaults to undefined
  • Returns {IssuerKit}

IssuerKit, the return type, has these properties:

  • mint {Mint}
  • issuer {Issuer}
  • brand {Brand}

Makes a new issuer as well as its one-to-one associated ERTP objects; a mint and a brand. All are in unchangeable one-to-one relationships with each other.

The allegedName becomes part of the brand in asset descriptions. It doesn't have to be a string, but it will only be used for its value. It is useful for debugging and double-checking assumptions, but should not be trusted.

The optional displayInfo tells the UI how to display amounts of this brand.

The optional assetKind specifies the kind of math to use with the digital assets. Each implements all of the same set of API methods (i.e. AmountMath methods are polymorphic). We recommend you import and use the AssetKind values from @agoric/ertp instead of using strings.

  • AssetKind.NAT (nat): Used with fungible assets. amount values are natural numbers (non-negative BigInts). Default value.
  • AssetKind.SET (set): Used with non-fungible assets. amount values are arrays that can include strings, numbers, objects, or anything comparable. But not promises, purses, or payments.
import { AssetKind, makeIssuerKit } from '@agoric/ertp';
makeIssuerKit('quatloos'); // Defaults to AssetKind.NAT
makeIssuerKit('title', AssetKind.SET);
const { issuer: quatloosIssuer, mint: quatloosMint, brand: quatloosBrand } = 
      makeIssuerKit('quatloos');
// This is merely an amount, describing assets, not minting assets
const quatloos2 = AmountMath.make(quatloosBrand, 2n);

const { issuer: titleIssuer, mint: titleMint, brand: titleBrand } = 
      makeIssuerKit('propertyTitle');
// These are merely amounts describing digital assets, not minting assets.
const cornerProperty = AmountMath.make(propertyTitleBrand, ['1292826']);
const adjacentProperty = AmountMath.make(propertyTitleBrand, ['1028393']);
const combinedProperty = AmountMath.make(propertyTitleBrand, ['1292826', '1028393']);

# issuer.getAllegedName()

  • Returns: {allegedName}

Returns the allegedName for this issuer.

An alleged name is a human-readable string name of a kind of digital asset. An alleged name should not be trusted as accurate since there is no public registry or expectation of uniqueness. This means there can be multiple issuers/mints/brands with the same alleged name, and thus the name by itself does not uniquely identify an issuer. Rather, the brand object does that.

To put it another way, nothing stops different people from creating multiple issuers with the alleged name Quatloos...but that doesn't make any of them the Quatloos issuer. The alleged name is just a human readable version which is helpful for debugging.

const { issuer: quatloosIssuer } = makeIssuerKit('quatloos');
const quatloosIssuerAllegedName = quatloosIssuer.getAllegedName();
// quatloosIssuerAllegedName === 'quatloos'

# issuer.getAssetKind()

  • Returns: {AssetKind}

Get the kind of this issuer's asset. It returns one of AssetKind.NAT (nat) or AssetKind.SET (set).

The assetKind value specifies what kind of values are used in amounts for this issuer. AmountMath works for all the different kinds of values.

  • AssetKind.NAT (nat): Used with fungible assets. amount values are natural numbers (non-negative BigInts). Default value.
  • AssetKind.SET (set): Used with non-fungible assets. amount values are arrays that can include strings, numbers, objects, or anything comparable. But not promises, purses, or payments.
const { issuer: quatloosIssuer } = makeIssuerKit('quatloos');
quatloosIssuer.getAssetKind(); // Returns 'nat', also known as AssetKind.NAT, the default value.
const { issuer: moolaIssuer } = makeIssuerKit('moola', AssetKind.SET);
moolaIssuer.getAssetKind(); // Returns 'set', also known as 'AssetKind.SET`

# issuer.getAmountOf(payment)

  • payment {Payment}
  • Returns: {Amount}

Get the payment's balance. Because the payment is not trusted, we cannot trust it to provide its true value, and must rely on the issuer to validate the payment's brand and tell us how much it contains.

const { issuer: quatloosIssuer, mint: quatloosMint, brand: quatloosBrand} = makeIssuerKit('quatloos');
const quatloosPayment = quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 100n));
quatloosIssuer.getAmountOf(quatloosPayment); // returns an amount of 100 Quatloos 

# issuer.getBrand()

  • Returns: {Brand}

Returns the brand for this issuer. The brand indicates the kind of digital asset and is the same for the issuer's associated mint, and any purses and payments of this particular kind. The brand is not closely held, so this function should not be trusted to identify an issuer alone. Fake digital assets and amounts can use another issuer's brand.

const { issuer: quatloosIssuer, brand: quatloosBrand } = makeIssuerKit('quatloos');
const quatloosBrand = quatloosIssuer.getBrand();
// brand === quatloosBrand

# issuer.makeEmptyPurse()

  • Returns: {Purse}

Make and return an empty purse that holds assets of the brand associated with the issuer.

const { issuer: quatloosIssuer } = makeIssuerKit('quatloos');
const quatloosPurse = quatloosIssuer.makeEmptyPurse();

# issuer.burn(payment, optAmount)

  • payment {Payment}
  • optAmount {Amount} - Optional
  • Returns: {Amount}

Burn (destroy) all of the digital assets in the payment and return an amount of what was burned.

optAmount is optional. If optAmount is present, the code insists the payment balance is equal to optAmount, to prevent sending the wrong payment and other confusion.

If payment is a promise for a payment, the operation proceeds after the promise resolves.

const { issuer: quatloosIssuer, mint: quatloosMint, brand: quatloosBrand } = 
      makeIssuerKit('quatloos');     
const amountToBurn = AmountMath.make(quatloosBrand, 10n);
const paymentToBurn = quatloosMint.mintPayment(amountToBurn);

// burntAmount should equal 10 Quatloos
const burntAmount = quatloosIssuer.burn(paymentToBurn, amountToBurn);

# issuer.claim(payment, optAmount)

  • payment {Payment}
  • optAmount {Amount}
  • Returns: {Payment}

Transfer all digital assets from payment to a new payment and burn the original. This allows the owner to be sure no other references to this payment survive, so they are the exclusive owner.

optAmount is optional. If optAmount is present, payment's balance must be equal to optAmount, to prevent sending the wrong payment and other confusion. If optAmount does not equal the balance in the original payment then it throws an error.

If a payment is a promise for a payment, the operation will proceed after the promise resolves. Since you might also have a promise returned, it might take a bit of time for the whole operation to resolve.

const { mint: quatloosMint, issuer: quatloosIssuer, brand: quatloosBrand } = makeIssuerKit('quatloos');
const amountExpectedToTransfer = AmountMath.make(quatloosBrand, 2n);
const originalPayment = quatloosMint.mintPayment(amountExpectedToTransfer);

const newPayment = quatloosIssuer.claim(originalPayment, amountToTransfer);

# issuer.combine(paymentsArray, optTotalAmount)

  • paymentsArray {Array <Payment>}
  • optTotalAmount {Amount} - Optional.
  • Returns: {Payment}

Combines multiple payments into one payment. If any payment in paymentsArray is a promise, the operation proceeds after all the payments resolve. The payments in paymentsArray are burned.

If the optional optTotalAmount is present, the total of all the payment amounts in the array must equal optTotalAmount or it throws an error.

If a payment is a promise for a payment, the operation will proceed after the promise resolves. Since you might also have a promise returned, it might take a bit of time for the whole operation to resolve.

const { mint: quatloosMint, issuer: quatloosIssuer, brand: quatloosBrand } = makeIssuerKit('quatloos');
// create an array of 100 payments of 1 quatloo each
const payments = [];
for (let i = 0; i < 100; i += 1) {
  payments.push(quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 1n)));
}

// combinedPayment equals 100
const combinedPayment = quatloosIssuer.combine(payments);

Note: You cannot combine payments from different mints (as they are of different brands):

const { mint: otherMint, issuer: otherIssuer, brand: otherBrand } = makeIssuerKit('other');
const otherPayment = otherMint.mintPayment(AmountMath.make(otherBrand, 10n));
payments.push(otherPayment); // using the payments array from the above code

// throws error
const badPayment = quatloosIssuer.combine(payments);

# issuer.split(payment, paymentAmountA)

  • payment {Payment}
  • paymentAmountA {Amount}
  • Returns: {Array <Payment>}

Split a single payment into two new payments, A and B, according to paymentAmountA. For example, if the payment is for 10 Quatloos, and paymentAmountA is 3 Quatloos, it returns an array of two payments with balances of 3 Quatloos and 7 Quatloos.

The original payment is burned.

If the original payment is a promise for a payment, the operation will proceed after the promise resolves. Since you might also have a promise returned, it might take a bit of time for the whole operation to resolve.

const { mint: quatloosMint, issuer: quatloosIssuer, brand: quatloosBrand } = makeIssuerKit('quatloos');
const oldPayment = quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 20n));
// After the split, paymentA has 5 quatloos and paymentB has 15.
const [paymentA, paymentB] = quatloosIssuer.split(oldPayment, AmountMath.make(quatloosBrand, 5n));

# issuer.splitMany(payment, amountArray)

  • payment {Payment}
  • amountArray {Array <Amount>}
  • Returns: {Array <Payment>}

Split a single payment into multiple payments. The resulting array of payments is as long as amountArray, and the payments will have amounts corresponding to the amountArray contents. The original payment is burned. If the original payment is a promise, the operation proceeds after the promise resolves. If the amounts in amountArray don't add up to the value of payment, the operation fails. The brands of the amountArray amounts must all be the same as the payment brand.

const { mint: quatloosMint, issuer: quatloosIssuer, brand: quatloosBrand} = makeIssuerKit('quatloos');
const oldPayment = quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 100n));
const goodAmounts = Array(10).fill(AmountMath.make(quatloosBrand, 10n));

const arrayOfNewPayments = quatloos.Issuer.splitMany(oldPayment, goodAmounts);

// The total amount in the amountArray must equal the original payment amount
// Set original amount to 1000n
const payment = quatloosMint.mintPayment(AmountMath.make(quatloosBrand, 1000n));

// Total amounts in badAmounts equal 20n, when it should equal 1000n
const badAmounts = Array(2).fill(AmountMath.make(quatloosBrand, 10n));

// 20n does not equal 1000n, so throws error
quatloosIssuer.splitMany(payment, badAmounts);

# issuer.isLive(payment)

  • payment {Payment}
  • Returns: {Boolean}

Returns true if the payment was created by the issuer and has not yet been destroyed. If payment is a promise, the operation proceeds upon resolution.