Asset Information¶
In addition to manipulating state on the blockchain, stateful smart contracts can also look up information about assets and account balances.
Algo Balances¶
The Balance
expression can be used to look up an account’s balance in microAlgos (1 Algo = 1,000,000 microAlgos).
For example,
senderBalance = Balance(Txn.sender()) # get the balance of the sender
account1Balance = Balance(Txn.accounts[1]) # get the balance of Txn.accounts[1]
The MinBalance
expression can be used to find an account’s minimum balance.
This amount is also in microAlgos. For example,
senderMinBalance = MinBalance(Txn.sender()) # get the minimum balance of the sender by passing the account address (bytes)
account1MinBalance = MinBalance(Txn.accounts[1]) # get the minimum balance of Txn.accounts[1] by passing the account address (bytes)
Additionally, Balance
and MinBalance
can be used together to calculate how many Algos
an account can spend without closing. For example,
senderSpendableBalance = Balance(Txn.sender()) - MinBalance(Txn.sender()) # calculate how many Algos the sender can spend
account1SpendableBalance = Balance(Txn.accounts[1]) - MinBalance(Txn.accounts[1]) # calculate how many Algos Txn.accounts[1] can spend
Asset Holdings¶
In addition to Algos, the Algorand blockchain also supports additional on-chain assets called Algorand Standard Assets (ASAs).
The AssetHolding
group of expressions can be used to look up information about the ASAs that
an account holds.
Similar to external state expressions, these expression return a MaybeValue
.
This value cannot be used directly, but has methods MaybeValue.hasValue()
and MaybeValue.value()
.
If the account has opted into the asset being looked up, hasValue()
will return 1
and value()
will return the value being looked up (either the asset’s balance or frozen status).
Otherwise, hasValue()
and value()
will return 0
.
Balances¶
The AssetHolding.balance
expression can be used to look up how many units of an asset an
account holds. For example,
# get the balance of the sender for asset `Txn.assets[0]`
# if the account is not opted into that asset, returns 0
senderAssetBalance = AssetHolding.balance(Txn.sender(), Txn.assets[0])
program = Seq([
senderAssetBalance,
senderAssetBalance.value()
])
# get the balance of Txn.accounts[1] for asset `Txn.assets[1]`
# if the account is not opted into that asset, exit with an error
account1AssetBalance = AssetHolding.balance(Txn.accounts[1], Txn.assets[1])
program = Seq([
account1AssetBalance,
Assert(account1AssetBalance.hasValue()),
account1AssetBalance.value()
])
Frozen¶
The AssetHolding.frozen
expression can be used to check if an asset is frozen for an account.
A value of 1
indicates frozen and 0
indicates not frozen. For example,
# get the frozen status of the sender for asset `Txn.assets[0]`
# if the account is not opted into that asset, returns 0
senderAssetFrozen = AssetHolding.frozen(Txn.sender(), Txn.assets[0])
program = Seq([
senderAssetFrozen,
senderAssetFrozen.value()
])
# get the frozen status of Txn.accounts[1] for asset `Txn.assets[1]`
# if the account is not opted into that asset, exit with an error
account1AssetFrozen = AssetHolding.frozen(Txn.accounts[1], Txn.assets[1])
program = Seq([
account1AssetFrozen,
Assert(account1AssetFrozen.hasValue()),
account1AssetFrozen.value()
])
Asset Parameters¶
Every ASA has parameters that contain information about the asset and how it behaves. These
parameters can be read by TEAL applications for any asset in the Txn.assets
array.
The AssetParam
group of expressions are used to access asset parameters. Like AssetHolding
,
these expressions return a MaybeValue
.
The hasValue()
method will return 0
only if the asset being looked up does not exist
(i.e. the ID in Txn.assets
does not represent an asset).
For optional parameters that are not set, hasValue()
will still return 1
and value()
will return a zero-length byte string (all optional parameters are TealType.bytes
).
The different parameters that can be accessed are summarized by the table below. More information about each parameter can be found on the Algorand developer website.
Expression | Type | Description |
---|---|---|
AssetParam.total() |
TealType.uint64 |
The total number of units of the asset. |
AssetParam.decimals() |
TealType.uint64 |
The number of decimals the asset should be formatted with. |
AssetParam.defaultFrozen() |
TealType.uint64 |
Whether the asset is frozen by default. |
AssetParam.unitName() |
TealType.bytes |
The name of the asset’s units. |
AssetParam.name() |
TealType.bytes |
The name of the asset. |
AssetParam.url() |
TealType.bytes |
A URL associated with the asset. |
AssetParam.metadataHash() |
TealType.bytes |
A 32-byte hash associated with the asset. |
AssetParam.manager() |
TealType.bytes |
The address of the asset’s manager account. |
AssetParam.reserve() |
TealType.bytes |
The address of the asset’s reserve account. |
AssetParam.freeze() |
TealType.bytes |
The address of the asset’s freeze account. |
AssetParam.clawback() |
TealType.bytes |
The address of the asset’s clawback account. |
Here’s an example that uses an asset parameter:
# get the total number of units for asset `Txn.assets[0]`
# if the asset is invalid, exit with an error
assetTotal = AssetParam.total(Txn.assets[0])
program = Seq([
assetTotal,
Assert(assetTotal.hasValue()),
assetTotal.value()
])