Skip to content

Transaction Types

The following sections describe the seven types of Algorand transactions through example transactions that represent common use cases. These transaction types form the fundamental building blocks of the Algorand blockchain, enabling everything from simple payments to complex decentralized applications.

The transaction types include Payment transactions for transferring Algo, Key Registration transactions for participating in consensus, Asset Configuration/Transfer/Freeze transactions for managing Algorand Standard Assets (ASAs), Application Call transactions for interacting with smart contracts, and State Proof transactions for consensus operations.

Payment Transaction

A Payment Transaction sends Algo, the Algorand blockchain’s native currency, from one account to another.

Send Algo

Here is an example transaction that sends 5 Algos (5,000,000 microAlgos) from sender address "EW64GC..." to receiver address "GD64YI...". The sender pays the minimum transaction fee of 1,000 microAlgos. The transaction includes an optional note field containing the base64-encoded text “Hello World”.

{
"txn": {
"amt": 5000000,
"fee": 1000,
"fv": 6000000,
"gen": "mainnet-v1.0",
"gh": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
"lv": 6001000,
"note": "SGVsbG8gV29ybGQ=",
"rcv": "GD64YIY3TWGDMCNPP553DZPPR6LDUSFQOIJVFDPPXWEG3FVOJCCDBBHU5A",
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "pay"
}
}

The "type": "pay" indicates that this is a payment transaction.

In this transaction, 5 Algo (5,000,000 microAlgo) are sent from sender address "EW64GC..." to receiver address "GD64YI...". The sender pays the minimum transaction fee of 1,000 microAlgos. The transaction includes an optional note field containing the base64-encoded text “Hello World”.

This transaction is valid on MainNet between rounds 6000000 and 6001000. The genesis hash uniquely identifies MainNet, while the genesis ID (mainnet-v1.0) is included for readability but should not be used for validation since it can be replicated on other private networks.

To implement payment transactions in your code, you can use the following examples:

/**
* Create a unsigned payment transaction sending 1 Algo from account_a to account_b
*
* Parameters for a payment transaction:
* - sender: The account or address of the account that will send the Algo
* - receiver: The account or address of the account that will receive the Algo
* - amount: Amount to send
*/
await algorand.createTransaction.payment({
sender: randomAccountA,
receiver: randomAccountB,
amount: algo(1),
})

Close an Account

Closing an account removes it from the Algorand ledger. Due to the minimum balance requirement for all accounts, the only way to completely remove an account is to use the close field, also known as Close Remainder To, as shown in the transaction below:

{
"txn": {
"close": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"fee": 1000,
"fv": 4695599,
"gen": "testnet-v1.0",
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 4696599,
"rcv": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"snd": "SYGHTA2DR5DYFWJE6D4T34P4AWGCG7JTNMY4VI6EDUVRMX7NG4KTA2WMDA",
"type": "pay"
}
}

In this transaction, the sender account "SYGHTA..." pays the transaction fee and transfers its remaining balance to the close-to account "EW64GC...". When no amount is specified, amt defaults to 0 Algo.

If an account has any assets, those holdings must be closed first by specifying an Asset Close Remainder To address in an Asset Transfer transaction before closing the Algorand account.

For rekeyed accounts, using the --close-to parameter removes the auth-addr field and returns signing authority to the original address. Keyholders of the auth-addr should use this parameter with caution as it permanently removes their control of the account.

To create a close account transaction in your code, refer to the following examples:

/**
* Close an Algorand account by transferring all remaining funds to another account
*
* Parameters:
* - sender: The address of the account to close
* - receiver: The address that will receive the closed account's remaining Algo balance
* - closeRemainderTo: The address that will receive all remaining Algo balance
*/
await algorand.createTransaction.payment({
sender: randomAccountA,
receiver: randomAccountB,
amount: algo(0),
closeRemainderTo: randomAccountB, // All remaining balance will be sent here
})

Key Registration Transaction

The purpose of a KeyRegistrationTx is to register an account as online or offline to participate and vote in Algorand Consensus.

Marking an account as online is only the first step for consensus participation. Before submitting a KeyReg transaction, a participation key must be generated for the account.

Register Account Online

This is an example of an online key registration transaction.

{
"txn": {
"fee": 2000,
"fv": 6002000,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 6003000,
"selkey": "X84ReKTmp+yfgmMCbbokVqeFFFrKQeFZKEXG89SXwm4=",
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "keyreg",
"votefst": 6000000,
"votekd": 1730,
"votekey": "eXq34wzh2UIxCZaI1leALKyAvSz/+XOe0wqdHagM+bw=",
"votelst": 9000000
}
}

What distinguishes this as a key registration transaction is "type": "keyreg" and what distinguishes it as an online key registration is the existence of the participation key-related fields, namely "votekey", "selkey", "votekd", "votefst", and "votelst". The values for these fields are retrieved from the participation key info stored on the node where the participation key lives. The sender ("EW64GC...") will pay a fee of 2000 microAlgos and its account state will change to online after this transaction is confirmed by the network. The transaction is valid between rounds 6,002,000 and 6,003,000 on TestNet.

To register an account online in your code, you can use the following examples:

/**
* Create an unsigned online key registration transaction
*
* Parameters for online key registration.
* - sender: The address of the account that will send the transaction
* - voteKey: The root participation public key
* - selectionKey: The VRF public key
* - voteFirst: The first round that the participation key is valid. Not to be confused with the firstValid round of the keyreg transaction
* - voteLast: The last round that the participation key is valid. Not to be confused with the lastValid round of the keyreg transaction
* - voteKeyDilution: This is the dilution for the 2-level participation key. It determines the interval (number of rounds) for generating new ephemeral keys
*/
await algorand.createTransaction.onlineKeyRegistration({
sender: randomAccountA,
voteKey: new Uint8Array(),
selectionKey: new Uint8Array(),
voteFirst: 1000n,
voteLast: 2000n,
voteKeyDilution: 10n,
})

Register Account Offline

Here is an example of an offline key registration transaction.

{
"txn": {
"fee": 1000,
"fv": 7000000,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 7001000,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "keyreg"
}
}

What distinguishes this from an online transaction is that it does not contain any participation key-related fields, since the account will no longer need a participation key if the transaction is confirmed. The sender ("EW64GC...") will pay a fee of 2000 microAlgo and its account state will change to offline after this transaction is confirmed by the network. This transaction is valid between rounds 7,000,000 ("fv") and 7,001,000 ("lv") on TestNet as per the Genesis Hash ("gh") value.

To register an account offline in your code, you can use the following examples:

/**
* Create an unsigned online key registration transaction
*
* Parameters for online key registration.
* - sender: The address of the account that will send the transaction
* - voteKey: The root participation public key
* - selectionKey: The VRF public key
* - voteFirst: The first round that the participation key is valid. Not to be confused with the firstValid round of the keyreg transaction
* - voteLast: The last round that the participation key is valid. Not to be confused with the lastValid round of the keyreg transaction
* - voteKeyDilution: This is the dilution for the 2-level participation key. It determines the interval (number of rounds) for generating new ephemeral keys
*/
await algorand.createTransaction.onlineKeyRegistration({
sender: randomAccountA,
voteKey: new Uint8Array(),
selectionKey: new Uint8Array(),
voteFirst: 1000n,
voteLast: 2000n,
voteKeyDilution: 10n,
})

Asset Configuration Transaction

An AssetConfigTx is used to create an asset, modify certain parameters of an asset, or destroy an asset.

Create an Asset

Here is an example asset creation transaction:

{
"txn": {
"apar": {
"am": "gXHjtDdtVpY7IKwJYsJWdCSrnUyRsX4jr3ihzQ2U9CQ=",
"an": "My New Coin",
"au": "developer.algorand.co",
"c": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"dc": 2,
"f": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"m": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"r": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"t": 50000000,
"un": "MNC"
},
"fee": 1000,
"fv": 6000000,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 6001000,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "acfg"
}
}

The "type": "acfg" distinguishes this as an Asset Configuration transaction. What makes this uniquely an asset creation transaction is that no asset ID ("caid") is specified and there exists an asset parameters struct ("apar") that includes all the initial configurations for the asset. The asset is named (an) “My New Coin”. the unitname ("un") is “MNC”. There are 50,000,000 total base units of this asset. Combine this with the decimals ("dc") value set to 2, means that there are 500,000.00 of this asset. There is an asset URL ("au") specified and a base64-encoded metadata hash ("am"). This specific value corresponds to the SHA512/256 hash of the string “My New Coin Certificate of Value”. The manager ("m"), freeze ("f"), clawback ("c"), and reserve ("r") are the same as the sender. The sender is also the creator.

This transaction is valid between rounds 6,000,000 ("fv") and 6,001,000 ("lv") on TestNet as per the Genesis Hash ("gh") value.

To create an asset creation transaction in your code, use the following examples:

/**
* Create an unsigned asset creation transaction to create a new Algorand Standard Asset (ASA)
*
* Parameters for asset creation:
* - sender: The account that will create and manage the asset
* - total: The total number of base units of the asset to create (e.g., 10_000_000)
* - decimals: The number of decimals for display purposes. If decimals is 6, then 1_000_000 base units = 1.000000 asset units
* - defaultFrozen: Whether accounts must be unfrozen by the freeze address before they can receive this asset
* - manager: The address that can manage the configuration of the asset. Can be permanently disabled by setting to undefined
* - reserve: The address holding reserve (non-minted) units of the asset. Can be permanently disabled by setting to undefined
* - freeze: The address that can freeze or unfreeze holder accounts. Can be permanently disabled by setting to undefined
* - clawback: The address that can clawback holdings of this asset. Can be permanently disabled by setting to undefined
* - unitName: The name of a unit of this asset (e.g., "MYA")
* - assetName: The name of the asset (e.g., "My Asset")
*/
await algorand.createTransaction.assetCreate({
sender: randomAccountA,
total: 10_000_000n,
decimals: 6,
defaultFrozen: false, // optional
manager: randomAccountA, // optional. Can be permanently disabled by setting to undefined
reserve: randomAccountA, // optional. Can be permanently disabled by setting to undefined
freeze: randomAccountA, // optional. Can be permanently disabled by setting to undefined
clawback: randomAccountA, // optional. Can be permanently disabled by setting to undefined
unitName: 'MYA',
assetName: 'My Asset',
})

Reconfigure an Asset

The asset manager can modify an existing asset’s configuration using a Reconfiguration Transaction.

Here’s an example transaction that changes the manager address for asset ID 168103:

{
"txn": {
"apar": {
"c": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"f": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"m": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"r": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4"
},
"caid": 168103,
"fee": 1000,
"fv": 6002000,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 6003000,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "acfg"
}
}

Unlike asset creation, a reconfiguration transaction requires an asset id. Only the manager, freeze, clawback, and reserve addresses can be modified, but all must be specified in the transaction even if they remain unchanged.

After confirmation, this transaction will change the manager of the asset from "EW64GC..." to "QC7XT7...". This transaction is valid on TestNet between rounds 6,002,000 and 6,003,000. A fee of 1000 microAlgo will be paid by the sender if confirmed.

To reconfigure an asset in your code, you can use the following examples:

/**
* Create an unsigned asset config transaction updating four mutable fields of an asset:
* manager, reserve, freeze, clawback. This operation is only possible if the sender is
* the asset manager and the asset has all four mutable fields set.
*
* Parameters for configuring an existing asset:
* - sender: The address of the account that will send the transaction
* - assetId: ID of the asset
* - manager: The address that can change the manager, reserve, clawback, and freeze addresses, defaults to undefined
* - reserve: The address that holds the uncirculated supply, defaults to undefined
* - freeze: The address that can freeze the asset in any account, defaults to undefined
* - clawback: The address that can clawback the asset from any account, defaults to undefined
*/
await algorand.createTransaction.assetConfig({
sender: randomAccountA,
assetId: 123n,
manager: randomAccountA,
reserve: randomAccountA,
freeze: randomAccountA,
clawback: randomAccountA,
})

Destroy an Asset

A Destroy Transaction is issued to remove an asset from the Algorand ledger. To destroy an existing asset on Algorand, the original creator must be in possession of all units of the asset and the manager must send and authorize the transaction.

Here is what an example transaction destroy transaction looks like:

{
"txn": {
"caid": 168103,
"fee": 1000,
"fv": 7000000,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 7001000,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "acfg"
}
}

This transaction differentiates itself from an Asset Creation transaction in that it contains an asset ID (caid) pointing to the asset to be destroyed. It differentiates itself from an Asset Reconfiguration transaction by the lack of any asset parameters.

To destroy an asset in your code, use the following examples:

/**
* Create an unsigned asset destroy transaction destroying an asset with asset id 1234
* All of the assets must be owned by the creator of the asset before the asset can be deleted.
*
* Parameters for destroying an asset:
* - sender: The address of the account that will send the transaction
* - assetId: ID of the asset
*/
await algorand.createTransaction.assetDestroy({
sender: randomAccountA,
assetId: 1234n,
})

Asset Transfer Transaction

An Asset Transfer Transaction enables accounts to opt in to, transfer, or revoke assets.

Opt-in to an Asset

Here is an example of an opt-in transaction:

{
"txn": {
"arcv": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"fee": 1000,
"fv": 6631154,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 6632154,
"snd": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"type": "axfer",
"xaid": 168103
}
}

The "type": "axfer" identifies this as an asset transfer transaction. This specific transaction is an opt-in because the same address ("QC7XT7...") appears as both sender and receiver, and the sender has no prior holdings of asset ID 168103. No asset amount is specified. The transaction is valid on TestNet between rounds 6,631,154 and 6,632,154.

To opt in to an asset in your code, you can use the following examples:

/**
* Create an unsigned asset opt in transaction for accountA opting in to asset with asset id 1234
*
* Parameters for an asset opt in transaction:
* - sender: The address of the account that will opt in to the asset
* - assetId: ID of the asset
*/
await algorand.createTransaction.assetOptIn({
sender: randomAccountA, // The address of the account that will opt in to the asset
assetId: 1234n, // ID of the asset
})

Opt-out of an Asset

Here is an example of an opt-out transaction:

{
"txn": {
"aclose": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"arcv": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"fee": 1000,
"fv": 6633154,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 6634154,
"snd": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"type": "axfer",
"xaid": 168103
}
}

This is an asset transfer transaction ("type": "axfer") that removes the asset from the sender’s account. The "aclose" field specifies where any remaining asset balance will be transferred before closing. After this transaction, the sender’s minimum balance requirement will be reduced and they will no longer be able to receive the asset without opting in again.

To opt out of an asset in your code, you can use the following examples:

/**
* Create an unsigned asset opt out transaction for accountA opting out of asset with asset id 1234
*
* Parameters for an asset opt out transaction:
* - sender: The address of the account that will opt out of the asset
* - assetId: ID of the asset
* - creator: The creator address of the asset
*/
await algorand.createTransaction.assetOptOut({
sender: randomAccountA,
assetId: 1234n,
creator: randomAccountB,
})

Transfer an Asset

Here is an example of an asset transfer transaction. This type of transaction moves ASAs between accounts, requiring both a valid asset ID and that the receiving account has already opted in to the asset:

{
"txn": {
"aamt": 1000000,
"arcv": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"fee": 3000,
"fv": 7631196,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 7632196,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "axfer",
"xaid": 168103
}
}

In this example, sender "EW64GC6..." transfers 1 million base units (10,000.00 units) of asset 168103 to "QC7XT7...", who must have already opted in to the asset. The transaction is valid on TestNet between rounds 7,631,196 and 7,632,196, with a fee of 3,000 microAlgos.

To transfer an asset in your code, you can use the following examples:

await algorand.createTransaction.assetTransfer({
sender: randomAccountA, // Account sending the asset
receiver: randomAccountB, // Account receiving the asset
assetId: 123n, // ID of the asset to transfer
amount: 1n, // Amount in smallest divisible units
})

Revoke an Asset

The clawback address has the unique authority to transfer assets from any holder of the asset to any other address. This feature can be used for asset recovery. Here is an example of a clawback transaction:

{
"txn": {
"aamt": 500000,
"arcv": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"asnd": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"fee": 1000,
"fv": 7687457,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 7688457,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "axfer",
"xaid": 168103
}
}

The "asnd" field indicates this is a clawback transaction. The clawback address ("EW64GC...") initiates the transaction, pays the 1,000 microAlgo fee, and specifies the account ("QC7XT7...") from which to revoke the assets. This transaction will transfer 500,000 base units of asset 168103 from "QC7XT7..." to "EW64GC...".

To revoke an asset in your code, you can use the following examples:

/**
* Create an unsigned asset clawback transaction. This allows an authorized clawback address
* to revoke assets from an account and send them to another.
*
* Parameters for asset clawback:
* - sender: The address of the clawback authority (must be the configured clawback address for the asset)
* - clawbackTarget: The address to clawback assets from
* - receiver: The address to send the clawed back assets to
* - assetId: ID of the asset
* - amount: The number of asset units to transfer
*/
await algorand.createTransaction.assetTransfer({
sender: randomAccountA,
clawbackTarget: randomAccountB,
receiver: randomAccountA,
assetId: 123n,
amount: 500000n,
})

Asset Freeze Transaction

An Asset Freeze Transaction allows the designated freeze address to control whether a specific account can transfer or receive a particular asset. When an asset is frozen, the affected account cannot send or receive that asset until it is unfrozen.

Freeze an Asset

{
"txn": {
"afrz": true,
"fadd": "QC7XT7QU7X6IHNRJZBR67RBMKCAPH67PCSX4LYH4QKVSQ7DQZ32PG5HSVQ",
"faid": 168103,
"fee": 1000,
"fv": 7687793,
"gh": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
"lv": 7688793,
"snd": "EW64GC6F24M7NDSC5R3ES4YUVE3ZXXNMARJHDCCCLIHZU6TBEOC7XRSBG4",
"type": "afrz"
}
}

This transaction is identified by "type": "afrz". The freeze manager ("EW64GC...") sets "afrz": true to freeze asset 168103 for account "QC7XT7...". Setting "afrz": false would unfreeze the asset instead.

To freeze an asset in your code, you can use the following examples:

/**
* Create a unsigned asset freeze transaction freezing an asset with asset id 1234
*
* Parameters for freezing an asset:
* - sender: The address of the account that will send the transaction
* - assetId: The ID of the asset
* - account: The account to freeze or unfreeze
* - frozen: Whether the assets in the account should be frozen
*/
await algorand.createTransaction.assetFreeze({
sender: randomAccountA,
assetId: 1234n,
account: randomAccountB,
frozen: true,
})

Application Call Transaction

An Application Call Transaction interacts with a smart contract (application) on the Algorand blockchain. These transactions allow users to create new applications, execute application logic, manage application state, and control user participation in the application. Each call includes an AppId to identify the target application and an OnComplete method that determines the type of interaction.

Application Call transactions may include other fields needed by the logic such as:

ApplicationArgs - To pass arbitrary arguments to an application (or in the future to call an ABI method)

Accounts - To pass accounts that may require some balance checking or opt-in status

ForeignApps - To pass apps and allow state access to an external application (or in the future to call an ABI method)

ForeignAssets - To pass ASAs for parameter checking

Boxes - To pass references to Application Boxes so the AVM can access the contents

Application Create Transaction

To create a new application, the transaction must include the Approval and Clear programs along with the state schema, but no AppId. The OnComplete method defaults to NoOp. The approval program can verify it’s being called during creation by checking if AppId equals 0.

{
"txn": {
"apap": "BYEB",
"apgs": {
"nbs": 1,
"nui": 1
},
"apls": {
"nbs": 1,
"nui": 1
},
"apsu": "BYEB",
"fee": 1000,
"fv": 12774,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 13774,
"note": "poeVkF5j4MU=",
"snd": "FOZF4CMXLU2KDWJ5QARE3J2U7XELSXL7MWGNWUHD7OPKGQAI4GPSMGNLCE",
"type": "appl"
}
}

This transaction contains the following key components:

  • The "apap" (Approval) and "apsu" (Clear) programs contain the minimal program #pragma version 5; int 1
  • Both global and local state schemas ("apgs" and "apls") specify one byte slice and one integer
  • The transaction uses the default NoOp for OnComplete, so the "apan" field is omitted

When this transaction is confirmed, it creates a new application with a unique AppId that can be referenced in subsequent calls.

To create an application in your code, you can use the following examples:

// Minimal TEAL program that just returns 1 (success)
const minimalTEAL = `
#pragma version 10
int 1
return
`
/**
* Create a unsigned application call transaction calling the hello method on the hello world contract
*
* Parameters for creating an application:
* - sender: The address of the account that will send the transaction
* - approvalProgram: The program to execute for all OnCompletes other than ClearState as raw TEAL (string)
* or compiled TEAL (bytes)
* - clearStateProgram: The program to execute for ClearState OnComplete as raw TEAL (string)
* or compiled TEAL (bytes)
*/
await algorand.send.appCreate({
sender: randomAccountA,
approvalProgram: minimalTEAL,
clearStateProgram: minimalTEAL,
})

Application Update Transaction

An Application Update Transaction modifies an existing application’s logic by providing new Approval and Clear programs. Only the current application’s Approval Program can authorize this update.

{
"txn": {
"apan": 4,
"apap": "BYEB",
"apid": 51,
"apsu": "BYEB",
"fee": 1000,
"fv": 12973,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 13973,
"note": "ATFKEwKGqLk=",
"snd": "FOZF4CMXLU2KDWJ5QARE3J2U7XELSXL7MWGNWUHD7OPKGQAI4GPSMGNLCE",
"type": "appl"
}
}

This transaction contains the following key components:

  • The "apid" field specifies the application to update (51)
  • The "apan" field is set to UpdateApplication (4)
  • New Approval and Clear programs are provided in "apap" and "apsu" fields

To update an application in your code, you can use the following examples:

/**
* Create a unsigned application update transaction updating the approval program and clear state program of an application
*
* Parameters for updating an application:
* - sender: The address of the account that will send the transaction
* - appId: ID of the application
* - approvalProgram: The program to execute for all OnCompletes other than ClearState as raw TEAL (string)
* or compiled TEAL (bytes)
* - clearStateProgram: The program to execute for ClearState OnComplete as raw TEAL (string)
* or compiled TEAL (bytes)
*/
await algorand.createTransaction.appUpdate({
sender: randomAccountA,
appId: 1234n,
approvalProgram: new Uint8Array(),
clearStateProgram: new Uint8Array(),
})

Application Delete Transaction

An Application Delete Transaction removes an application from the Algorand blockchain. The transaction can only succeed if the application’s Approval Program permits deletion.

{
"txn": {
"apan": 5,
"apid": 51,
"fee": 1000,
"fv": 13555,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 14555,
"note": "V/RAbQ57DnI=",
"snd": "FOZF4CMXLU2KDWJ5QARE3J2U7XELSXL7MWGNWUHD7OPKGQAI4GPSMGNLCE",
"type": "appl"
}
}

This transaction contains the following key components:

  • The "apid" field specifies the application to delete (51)
  • The "apan" field is set to DeleteApplication (5)

To delete an application in your code, you can use the following examples:

/**
* Create an unsigned application delete transaction deleting an application with app id 1234
*
* Parameters for deleting an application:
* - sender: The address of the account that will send the transaction
* - appId: ID of the application
*/
await algorand.createTransaction.appDelete({
sender: randomAccountA,
appId: 1234n,
})

Application Opt-In Transaction

An Application Opt-In Transaction enables an account to participate in an application by allocating local state. This transaction is only required if the application uses local state for the account.

{
"txn": {
"apan": 1,
"apid": 51,
"fee": 1000,
"fv": 13010,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 14010,
"note": "SEQpWAYkzoU=",
"snd": "LNTMAFSF43V7RQ7FBBRAWPXYZPVEBGKPNUELHHRFMCAWSARPFUYD2A623I",
"type": "appl"
}
}

This transaction contains the following key components:

  • The "apid" field specifies the application to opt into (51)
  • The "apan" field is set to OptIn (1)

To opt into an application in your code, you can use the following examples:

/**
* Create a unsigned application call transaction with the OptIn OnComplete action
*
* Parameters for calling an application:
* - sender: The address of the account that will send the transaction
* - onComplete: The OnComplete action
* - appId: ID of the application, defaults to undefined
*/
await algorand.createTransaction.appCall({
sender: randomAccountA,
appId: 1234n,
onComplete: OnApplicationComplete.OptInOC,
})

Application Close Out Transaction

An Application Close Out transaction is used when an account wants to opt out of a contract gracefully and remove its local state from its balance record. This transaction may fail according to the logic in the Approval program.

{
"txn": {
"apan": 2,
"apid": 51,
"fee": 1000,
"fv": 13166,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 14166,
"note": "HFL7S60gOdM=",
"snd": "LNTMAFSF43V7RQ7FBBRAWPXYZPVEBGKPNUELHHRFMCAWSARPFUYD2A623I",
"type": "appl"
}
}

This transaction contains the following key components:

  • The AppId (apid) is set to the app being closed out of (51 here)
  • The OnComplete (apan) is set to CloseOut (2)

Application Clear State Transaction

An Application Clear State Transaction forcibly removes an account’s local state. Unlike Close Out, this transaction always succeeds if properly formatted. The application’s Clear Program handles any necessary cleanup when removing the account’s state.

{
"txn": {
"apan": 3,
"apid": 51,
"fee": 1000,
"fv": 13231,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 14231,
"note": "U93ZQy24zJ0=",
"snd": "LNTMAFSF43V7RQ7FBBRAWPXYZPVEBGKPNUELHHRFMCAWSARPFUYD2A623I",
"type": "appl"
}
}

This transaction contains the following key components:

  • The AppId (apid) is set to the app being cleared (51 here)
  • The OnComplete (apan) is set to ClearState (3)

To clear an application’s state in your code, you can use the following examples:

/**
* Create a unsigned application call transaction with the ClearState OnComplete action
*
* Parameters for calling an application:
* - sender: The address of the account that will send the transaction
* - onComplete: The OnComplete action
* - appId: ID of the application, defaults to undefined
*/
await algorand.createTransaction.appCall({
sender: randomAccountA,
appId: 1234n,
onComplete: OnApplicationComplete.ClearStateOC,
})

Application NoOp Transaction

Application NoOp Transactions are the most common type of application calls. They execute the application’s logic without changing its lifecycle state. The application’s behavior is determined by the arguments and references provided in the transaction.

{
"txn": {
"apaa": ["ZG9jcw==", "AAAAAAAAAAE="],
"apas": [16],
"apat": ["4RLXQGPZVVRSXQF4VKZ74I6BCUD7TUVROOUBCVRKY37LQSHXORZV4KCAP4"],
"apfa": [10],
"apbx": [{ "i": 51, "n": "Y29vbF9ib3g=" }],
"apid": 51,
"fee": 1000,
"fv": 13376,
"gh": "ALXYc8IX90hlq7olIdloOUZjWfbnA3Ix1N5vLn81zI8=",
"lv": 14376,
"note": "vQXvgqySYPY=",
"snd": "LNTMAFSF43V7RQ7FBBRAWPXYZPVEBGKPNUELHHRFMCAWSARPFUYD2A623I",
"type": "appl"
}
}

This transaction contains the following key components:

  • The "apid" field specifies the application to call (51)
  • The "apaa" field contains application arguments: the string “docs” and the integer 1
  • The "apat" field references an external account
  • The "apas" field references ASA ID 16
  • The "apfa" field references application ID 10
  • The "apbx" field references a box named “cool_box” owned by the application
  • The OnComplete method defaults to NoOp (0), so the "apan" field is omitted

To make a NoOp call to an application in your code, you can use the following examples:

/**
* Create a unsigned application call transaction with the NoOp OnComplete actions
*
* Parameters for calling an application:
* - sender: The address of the account that will send the transaction
* - onComplete: The OnComplete action
* - appId: ID of the application, defaults to undefined
*/
await algorand.createTransaction.appCall({
sender: randomAccountA,
appId: 1234n,
onComplete: OnApplicationComplete.NoOpOC,
})

State Proof Transaction

State Proof Transactions are special consensus-related transactions that are generated by the network itself. They cannot be created by individual users or smart contracts.

{
"txn": {
"txn": {
"fv": 24192139,
"gh": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
"lv": 24193139,
"snd": "XM6FEYVJ2XDU2IBH4OT6VZGW75YM63CM4TC6AV6BD3JZXFJUIICYTVB5EU",
"sp": {},
"spmsg": {
"P": 2230170,
"b": "8LkpbqSqlWcsfUr9EgpxBmrTDqQBg2tcubN7cpcFRM8=",
"f": 24191745,
"l": 24192000,
"v": "drLLvXcg+sOqAhYIjqatF68QP7TeR0B/NljKtOtDit7Hv5Hk7gB9BgI5Ijz+tkmDkRoblcchwYDJ1RKzbapMAw=="
},
"type": "stpf"
}
}
}

Heartbeat Transaction

A Heartbeat Transaction allows participation nodes to signal they are operational, even when they haven’t proposed blocks recently. These transactions are particularly important for accounts with smaller stakes that might not frequently propose blocks.

{
"fee": 0,
"first-valid": 46514101,
"last-valid": 46514111,
"sender": "XM6FEYVJ2XDU2IBH4OT6VZGW75YM63CM4TC6AV6BD3JZXFJUIICYTVB5EU",
"genesis-hash": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
"heartbeat-transaction": {
"hb-address": "LNTMAFSF43V7RQ7FBBRAWPXYZPVEBGKPNUELHHRFMCAWSARPFUYD2A623I",
"hb-key-dilution": 1733,
"hb-proof": {
"hb-pk": "fS6sjbqtRseLgoRuWf3mJMWMJA6hZ1TemZCAmFg62SU=",
"hb-pk1sig": "NQC4OxD01CAog8VPee0lZHLkJhvCK8FHqgqrjlHgtyGVxJBfmFSGrvRyd7BXXBpXqtz2gmiRiwsOPi9kuOXvDA==",
"hb-pk2": "Oar7xcoAnGtGEicTlx864JiCVQS+GQIDNlt37MiCWa8=",
"hb-pk2sig": "YWXDN49q4s5Wywyn6ZDi5yu13wCHICW5YH9wc3tnOqmlz/tAlXvX5GO0ePz6FyTTIgqQp1SheLQopNpME43yAA==",
"hb-sig": "aMp1kUFzBAGcnUXo7dqko3BtiWi9624hj4Vu8un1cjDU0s4CAk69gxuaagxITd5rZla1Zaf+iX63DknMaIIXAA=="
},
"hb-seed": "H3u5wO+W/QvGxSr9h0Oz14rV0WFJ/le5hbi/2OvafzY=",
"hb-vote-id": "puFs2yVgp6oGrOU5DFs1QWkCk/S/cB7GMs/f9bx0gW8="
},
"tx-type": "hb"
}

We know this is a heartbeat transaction based on the "tx-type" field being set to "hb".

This transaction contains the following required fields:

  • The "hb-address" field specifies the account this transaction is proving onlineness for
  • The "hb-key-dilution" field specifies the key dilution value that must match the account’s current KeyDilution
  • The "hb-seed" field contains the block seed for this transaction’s firstValid block
  • The "hb-vote-id" field contains the vote ID that must match the account’s current VoteID
  • The "hb-proof" field contains the heartbeat proof structure

The transaction fee is zero when responding to a network challenge.