Assets | Algorand Developer Portal

Assets

The Algorand Standard Asset (asset) management functions include creating, opting in and transferring assets, which are fundamental to asset interaction in a blockchain environment.

To see some usage examples check out the automated tests.

AssetManager

The AssetManager is a class that is used to manage asset information.

To get an instance of AssetManager, you can use either AlgorandClient via algorand.asset or instantiate it directly:

import { AssetManager } from '@algorandfoundation/algokit-utils/types/asset-manager'
import {TransactionComposer } from '@algorandfoundation/algokit-utils/types/composer'

const assetManager = new AssetManager(algod, () => new TransactionComposer({algod, () => signer, () => suggestedParams}))

Creation

To create an asset you can use algorand.send.assetCreate(params) (immediately send a single asset creation transaction), algorand.createTransaction.assetCreate(params) (construct an asset creation transaction), or algorand.newGroup().addAssetCreate(params) (add asset creation to a group of transactions) per AlgorandClient transaction semantics.

The base type for specifying an asset creation transaction is AssetCreateParams, which has the following parameters in addition to the common transaction parameters:

Examples

// Basic example
const result = await algorand.send.assetCreate({ sender: 'CREATORADDRESS', total: 100n });
const createdAssetId = result.assetId;

// Advanced example
await algorand.send.assetCreate({
  sender: 'CREATORADDRESS',
  total: 100n,
  decimals: 2,
  assetName: 'asset',
  unitName: 'unit',
  url: 'url',
  metadataHash: 'metadataHash',
  defaultFrozen: false,
  manager: 'MANAGERADDRESS',
  reserve: 'RESERVEADDRESS',
  freeze: 'FREEZEADDRESS',
  clawback: 'CLAWBACKADDRESS',
  lease: 'lease',
  note: 'note',
  firstValidRound: 1000n,
  validityWindow: 10,
  extraFee: (1000).microAlgo(),
  staticFee: (1000).microAlgo(),
  maxFee: (3000).microAlgo(),
  signer: transactionSigner,
  maxRoundsToWaitForConfirmation: 5,
  suppressLog: true,
});

Reconfigure

If you have a manager address set on an asset, that address can send a reconfiguration transaction to change the manager, reserve, freeze and clawback fields of the asset if they haven’t been set to empty.

[!WARNING] If you issue a reconfigure transaction and don’t set the existing values for any of the below fields then that field will be permanently set to empty.

To reconfigure an asset you can use algorand.send.assetConfig(params) (immediately send a single asset config transaction), algorand.createTransaction.assetConfig(params) (construct an asset config transaction), or algorand.newGroup().addAssetConfig(params) (add asset config to a group of transactions) per AlgorandClient transaction semantics.

The base type for specifying an asset creation transaction is AssetConfigParams, which has the following parameters in addition to the common transaction parameters:

Examples

// Basic example
await algorand.send.assetConfig({
  sender: 'MANAGERADDRESS',
  assetId: 123456n,
  manager: 'MANAGERADDRESS',
});

// Advanced example
await algorand.send.assetConfig({
  sender: 'MANAGERADDRESS',
  assetId: 123456n,
  manager: 'MANAGERADDRESS',
  reserve: 'RESERVEADDRESS',
  freeze: 'FREEZEADDRESS',
  clawback: 'CLAWBACKADDRESS',
  lease: 'lease',
  note: 'note',
  firstValidRound: 1000n,
  validityWindow: 10,
  extraFee: (1000).microAlgo(),
  staticFee: (1000).microAlgo(),
  maxFee: (3000).microAlgo(),
  signer: transactionSigner,
  maxRoundsToWaitForConfirmation: 5,
  suppressLog: true,
});

Transfer

To transfer unit(s) of an asset between accounts you can use algorand.send.assetTransfer(params) (immediately send a single asset transfer transaction), algorand.createTransaction.assetTransfer(params) (construct an asset transfer transaction), or algorand.newGroup().addAssetTransfer(params) (add asset transfer to a group of transactions) per AlgorandClient transaction semantics.

Note: For an account to receive an asset it needs to have opted-in.

The base type for specifying an asset transfer transaction is AssetTransferParams, which has the following parameters in addition to the common transaction parameters:

Examples

// Basic example
await algorand.send.assetTransfer({sender: 'HOLDERADDRESS', assetId: 123456n, amount: 1n, receiver: 'RECEIVERADDRESS' })

// Advanced example (with clawback and close asset to)
await algorand.send.assetTransfer({
  sender: 'CLAWBACKADDRESS',
  assetId: 123456n,
  amount: 1n,
  receiver: 'RECEIVERADDRESS',
  clawbackTarget: 'HOLDERADDRESS',
  closeAssetTo: 'ADDRESSTOCLOSETO',
  lease: 'lease',
  note: 'note',
  firstValidRound: 1000n,
  validityWindow: 10,
  extraFee: (1000).microAlgo(),
  staticFee: (1000).microAlgo(),
  maxFee: (3000).microAlgo(),
  signer: transactionSigner,
  maxRoundsToWaitForConfirmation: 5,
  suppressLog: true,
});

Opt-in/out

Before an account can receive a specific asset, it must opt-in to receive it. An opt-in transaction places an asset holding of 0 into the account and increases the minimum balance of that account by 100,000 microAlgos.

An account can opt out of an asset at any time by closing out its asset position to another account (usually to the asset creator). This means that the account will no longer hold the asset, and the account will no longer be able to receive the asset. The account also recovers the Minimum Balance Requirement for the asset (100,000 microAlgos).

When opting-out you generally want to be careful to ensure you have a zero-balance otherwise you will forfeit the balance you do have. AlgoKit Utils can protect you from making this mistake by checking you have a zero-balance before issuing the opt-out transaction. You can turn this check off if you want to avoid the extra calls to Algorand and are confident in what you are doing.

AlgoKit Utils gives you functions that allow you to do opt-ins and opt-outs in bulk or as a single operation. The bulk operations give you less control over the sending semantics as they automatically send the transactions to Algorand in the most optimal way using transaction groups of 16 at a time.

assetOptIn

To opt-in to an asset you can use algorand.send.assetOptIn(params) (immediately send a single asset opt-in transaction), algorand.createTransaction.assetOptIn(params) (construct an asset opt-in transaction), or algorand.newGroup().addAssetOptIn(params) (add asset opt-in to a group of transactions) per AlgorandClient transaction semantics.

The base type for specifying an asset opt-in transaction is AssetOptInParams, which has the following parameters in addition to the common transaction parameters:

// Basic example
await algorand.send.assetOptIn({ sender: 'SENDERADDRESS', assetId: 123456n });

// Advanced example
await algorand.send.assetOptIn({
  sender: 'SENDERADDRESS',
  assetId: 123456n,
  lease: 'lease',
  note: 'note',
  firstValidRound: 1000n,
  validityWindow: 10,
  extraFee: (1000).microAlgo(),
  staticFee: (1000).microAlgo(),
  maxFee: (3000).microAlgo(),
  signer: transactionSigner,
  maxRoundsToWaitForConfirmation: 5,
  suppressLog: true,
});

assetOptOut

To opt-out to an asset you can use algorand.send.assetOptOut(params) (immediately send a single asset opt-out transaction), algorand.createTransaction.assetOptOut(params) (construct an asset opt-out transaction), or algorand.newGroup().addAssetOptOut(params) (add asset opt-out to a group of transactions) per AlgorandClient transaction semantics.

The base type for specifying an asset opt-out transaction is AssetOptOutParams, which has the following parameters in addition to the common transaction parameters:

If you are using the send variant then there is an additional parameter:

[!WARNING] If you are using the transaction or addAssetOptOut variants then you need to take responsibility to ensure the asset holding balance is 0 to avoid losing assets.

// Basic example (without creator)
await algorand.send.assetOptOut({
  sender: 'SENDERADDRESS',
  assetId: 123456n,
  ensureZeroBalance: true,
});

// Basic example (with creator)
await algorand.send.assetOptOut({
  sender: 'SENDERADDRESS',
  creator: 'CREATORADDRESS',
  assetId: 123456n,
  ensureZeroBalance: true,
});

// Advanced example
await algorand.send.assetOptOut({
  sender: 'SENDERADDRESS',
  assetId: 123456n,
  creator: 'CREATORADDRESS',
  ensureZeroBalance: true,
  lease: 'lease',
  note: 'note',
  firstValidRound: 1000n,
  validityWindow: 10,
  extraFee: (1000).microAlgo(),
  staticFee: (1000).microAlgo(),
  maxFee: (3000).microAlgo(),
  signer: transactionSigner,
  maxRoundsToWaitForConfirmation: 5,
  suppressLog: true,
});

asset.bulkOptIn

The asset.bulkOptIn function facilitates the opt-in process for an account to multiple assets, allowing the account to receive and hold those assets.

// Basic example
algorand.asset.bulkOptIn('ACCOUNTADDRESS', [12345n, 67890n]);

// Advanced example
algorand.asset.bulkOptIn('ACCOUNTADDRESS', [12345n, 67890n], {
  maxFee: (1000).microAlgo(),
  suppressLog: true,
});

asset.bulkOptOut

The asset.bulkOptOut function facilitates the opt-out process for an account from multiple assets, permitting the account to discontinue holding a group of assets.

// Basic example
algorand.asset.bulkOptOut('ACCOUNTADDRESS', [12345n, 67890n]);

// Advanced example
algorand.asset.bulkOptOut('ACCOUNTADDRESS', [12345n, 67890n], {
  ensureZeroBalance: true,
  maxFee: (1000).microAlgo(),
  suppressLog: true,
});

Get information

Getting current parameters for an asset

You can get the current parameters of an asset from algod by using algorand.asset.getById(assetId).

const assetInfo = await assetManager.getById(12353n);

Getting current holdings of an asset for an account

You can get the current holdings of an asset for a given account from algod by using algorand.asset.getAccountInformation(accountAddress, assetId).

const address = 'XBYLS2E6YI6XXL5BWCAMOA4GTWHXWENZMX5UHXMRNWWUQ7BXCY5WC5TEPA';
const assetId = 123345n;
const accountInfo = await algorand.asset.getAccountInformation(address, assetId);