Skip to content

Payment Transaction

← Back to Transactions

This example demonstrates how to send ALGO between accounts using the transact package. It shows the low-level transaction construction pattern with:

  • Transaction class with TransactionType.Payment
  • PaymentTransactionFields for receiver and amount
  • assignFee() to set transaction fee from suggested params
  • generateAddressWithSigners for signing
  • LocalNet running (via algokit localnet start)

From the repository root:

Terminal window
cd examples
npm run example transact/01-payment-transaction.ts

View source on GitHub

01-payment-transaction.ts
/**
* Example: Payment Transaction
*
* This example demonstrates how to send ALGO between accounts using the transact package.
* It shows the low-level transaction construction pattern with:
* - Transaction class with TransactionType.Payment
* - PaymentTransactionFields for receiver and amount
* - assignFee() to set transaction fee from suggested params
* - generateAddressWithSigners for signing
*
* Prerequisites:
* - LocalNet running (via `algokit localnet start`)
*/
import { AlgorandClient } from '@algorandfoundation/algokit-utils'
import {
Transaction,
TransactionType,
assignFee,
type PaymentTransactionFields,
} from '@algorandfoundation/algokit-utils/transact'
import {
createAlgodClient,
formatAlgo,
getAccountBalance,
printHeader,
printInfo,
printStep,
printSuccess,
shortenAddress,
waitForConfirmation,
} from '../shared/utils.js'
/**
* Gets a funded account from LocalNet's KMD wallet
*/
async function getLocalNetFundedAccount(algorand: AlgorandClient) {
const dispenser = await algorand.account.kmd.getLocalNetDispenserAccount()
return dispenser
}
async function main() {
printHeader('Payment Transaction Example')
// Step 1: Initialize clients
printStep(1, 'Initialize Algod Client')
const algod = createAlgodClient()
const algorand = AlgorandClient.defaultLocalNet()
printInfo('Connected to LocalNet Algod')
// Step 2: Get a funded account from KMD (sender)
printStep(2, 'Get Funded Account from KMD')
const sender = await getLocalNetFundedAccount(algorand)
const senderBalance = await getAccountBalance(algorand, sender.addr.toString())
printInfo(`Sender address: ${shortenAddress(sender.addr.toString())}`)
printInfo(`Sender balance: ${formatAlgo(senderBalance.microAlgo)}`)
// Step 3: Generate a new receiver account using AlgorandClient helper
printStep(3, 'Generate Receiver Account')
const receiver = algorand.account.random()
printInfo(`Receiver address: ${shortenAddress(receiver.addr.toString())}`)
// Check initial receiver balance (should be 0)
let receiverBalanceBefore: bigint
try {
const info = await getAccountBalance(algorand, receiver.addr.toString())
receiverBalanceBefore = info.microAlgo
} catch {
// New accounts have 0 balance before being funded
receiverBalanceBefore = 0n
}
printInfo(`Receiver initial balance: ${formatAlgo(receiverBalanceBefore)}`)
// Step 4: Get suggested transaction parameters
printStep(4, 'Get Suggested Transaction Parameters')
const suggestedParams = await algod.suggestedParams()
printInfo(`First valid round: ${suggestedParams.firstValid}`)
printInfo(`Last valid round: ${suggestedParams.lastValid}`)
printInfo(`Min fee: ${suggestedParams.minFee} microALGO`)
// Step 5: Create payment transaction
printStep(5, 'Create Payment Transaction')
const paymentAmount = 1_000_000n // 1 ALGO in microALGO
// Define payment-specific fields
const paymentFields: PaymentTransactionFields = {
receiver: receiver.addr,
amount: paymentAmount,
}
// Create the transaction with all required fields
const transaction = new Transaction({
type: TransactionType.Payment,
sender: sender.addr,
firstValid: suggestedParams.firstValid,
lastValid: suggestedParams.lastValid,
genesisHash: suggestedParams.genesisHash,
genesisId: suggestedParams.genesisId,
payment: paymentFields,
})
printInfo(`Transaction type: ${transaction.type}`)
printInfo(`Amount: ${formatAlgo(paymentAmount)}`)
printInfo(`Receiver: ${shortenAddress(receiver.addr.toString())}`)
// Step 6: Assign fee using suggested params
printStep(6, 'Assign Transaction Fee')
const transactionWithFee = assignFee(transaction, {
feePerByte: suggestedParams.fee,
minFee: suggestedParams.minFee,
})
printInfo(`Assigned fee: ${transactionWithFee.fee} microALGO`)
// Step 7: Sign the transaction
printStep(7, 'Sign Transaction')
const signedTxns = await sender.signer([transactionWithFee], [0])
const txId = transactionWithFee.txId()
printInfo(`Transaction ID: ${txId}`)
printInfo('Transaction signed successfully')
// Step 8: Submit transaction and wait for confirmation
printStep(8, 'Submit Transaction and Wait for Confirmation')
await algod.sendRawTransaction(signedTxns)
printInfo('Transaction submitted to network')
// Wait for confirmation using the utility function
const pendingInfo = await waitForConfirmation(algod, txId)
printInfo(`Transaction confirmed in round: ${pendingInfo.confirmedRound}`)
// Step 9: Verify receiver balance increased
printStep(9, 'Verify Receiver Balance')
const receiverBalanceAfter = await getAccountBalance(algorand, receiver.addr.toString())
printInfo(`Receiver balance after: ${formatAlgo(receiverBalanceAfter.microAlgo)}`)
const balanceIncrease = receiverBalanceAfter.microAlgo - receiverBalanceBefore
printInfo(`Balance increase: ${formatAlgo(balanceIncrease)}`)
// Verify the balance increased by the sent amount
if (balanceIncrease === paymentAmount) {
printSuccess(`Payment of ${formatAlgo(paymentAmount)} completed successfully!`)
} else {
throw new Error(`Expected balance increase of ${paymentAmount}, but got ${balanceIncrease}`)
}
printSuccess('Payment transaction example completed!')
}
main().catch((error) => {
console.error('Error:', error)
process.exit(1)
})