AlgoAmount Utility
Description
Section titled “Description”This example demonstrates how to use the AlgoAmount utility class to work with ALGO and microALGO amounts safely, avoiding floating point precision issues. Topics covered:
- Creating AlgoAmount using static factory methods
- Accessing values in ALGO and microALGO
- String formatting
- Arithmetic operations (addition, subtraction)
- Comparison operations
- Using AlgoAmount with payment transactions
- Avoiding floating point precision issues
Prerequisites
Section titled “Prerequisites”- No LocalNet required
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example algorand_client/02-algo-amount.ts/** * Example: AlgoAmount Utility * * This example demonstrates how to use the AlgoAmount utility class to work * with ALGO and microALGO amounts safely, avoiding floating point precision issues. * * Topics covered: * - Creating AlgoAmount using static factory methods * - Accessing values in ALGO and microALGO * - String formatting * - Arithmetic operations (addition, subtraction) * - Comparison operations * - Using AlgoAmount with payment transactions * - Avoiding floating point precision issues * * Prerequisites: * - No LocalNet required */
import { algo, ALGORAND_MIN_TX_FEE, AlgorandClient, algos, microAlgo, microAlgos, transactionFees } from '@algorandfoundation/algokit-utils'import { AlgoAmount } from '@algorandfoundation/algokit-utils/types/amount'import { printError, printHeader, printInfo, printStep, printSuccess, shortenAddress } from '../shared/utils.js'
async function main() { printHeader('AlgoAmount Utility Example')
// Step 1: Creating AlgoAmount using static factory methods printStep(1, 'Creating AlgoAmount using static factory methods') printInfo('AlgoAmount provides four static factory methods:') printInfo(' - AlgoAmount.Algo(amount) - Create from ALGO value') printInfo(' - AlgoAmount.Algos(amount) - Alias for Algo()') printInfo(' - AlgoAmount.MicroAlgo(amount) - Create from microALGO value') printInfo(' - AlgoAmount.MicroAlgos(amount) - Alias for MicroAlgo()')
// Create using AlgoAmount.Algo() const oneAndHalfAlgo = AlgoAmount.Algo(1.5) printInfo(`\nAlgoAmount.Algo(1.5): ${oneAndHalfAlgo.algo} ALGO = ${oneAndHalfAlgo.microAlgo} µALGO`)
// Create using AlgoAmount.Algos() - alias const twoAlgos = AlgoAmount.Algos(2) printInfo(`AlgoAmount.Algos(2): ${twoAlgos.algo} ALGO = ${twoAlgos.microAlgo} µALGO`)
// Create using AlgoAmount.MicroAlgo() const fiftyThousandMicroAlgo = AlgoAmount.MicroAlgo(50_000) printInfo(`AlgoAmount.MicroAlgo(50000): ${fiftyThousandMicroAlgo.algo} ALGO = ${fiftyThousandMicroAlgo.microAlgo} µALGO`)
// Create using AlgoAmount.MicroAlgos() - alias const hundredThousandMicroAlgo = AlgoAmount.MicroAlgos(100_000) printInfo(`AlgoAmount.MicroAlgos(100000): ${hundredThousandMicroAlgo.algo} ALGO = ${hundredThousandMicroAlgo.microAlgo} µALGO`)
printSuccess('Created AlgoAmount instances using all factory methods')
// Step 2: Using helper functions printStep(2, 'Using convenience helper functions') printInfo('The library exports helper functions for cleaner syntax:') printInfo(' - algo(amount) - Equivalent to AlgoAmount.Algo()') printInfo(' - algos(amount) - Equivalent to AlgoAmount.Algos()') printInfo(' - microAlgo(amount) - Equivalent to AlgoAmount.MicroAlgo()') printInfo(' - microAlgos(amount) - Equivalent to AlgoAmount.MicroAlgos()')
const threeAlgo = algo(3) printInfo(`\nalgo(3): ${threeAlgo.algo} ALGO = ${threeAlgo.microAlgo} µALGO`)
const fiveAlgos = algos(5) printInfo(`algos(5): ${fiveAlgos.algo} ALGO = ${fiveAlgos.microAlgo} µALGO`)
const tenMicroAlgo = microAlgo(10) printInfo(`microAlgo(10): ${tenMicroAlgo.algo} ALGO = ${tenMicroAlgo.microAlgo} µALGO`)
const twentyMicroAlgos = microAlgos(20) printInfo(`microAlgos(20): ${twentyMicroAlgos.algo} ALGO = ${twentyMicroAlgos.microAlgo} µALGO`)
// Transaction fees helper const threeTransactionFees = transactionFees(3) printInfo(`\ntransactionFees(3): ${threeTransactionFees.microAlgo} µALGO (covers 3 standard transactions)`) printInfo(`ALGORAND_MIN_TX_FEE: ${ALGORAND_MIN_TX_FEE.microAlgo} µALGO (minimum transaction fee)`)
printSuccess('Demonstrated convenience helper functions')
// Step 3: Accessing values in ALGO and microALGO printStep(3, 'Accessing values using .algo and .microAlgo properties') printInfo('AlgoAmount provides getter properties to access the value:') printInfo(' - .algo / .algos - Get value in ALGO (as number)') printInfo(' - .microAlgo / .microAlgos - Get value in µALGO (as bigint)')
const amount = AlgoAmount.Algo(2.5) printInfo(`\nFor amount = AlgoAmount.Algo(2.5):`) printInfo(` .algo: ${amount.algo} (type: ${typeof amount.algo})`) printInfo(` .algos: ${amount.algos} (alias for .algo)`) printInfo(` .microAlgo: ${amount.microAlgo} (type: ${typeof amount.microAlgo})`) printInfo(` .microAlgos: ${amount.microAlgos} (alias for .microAlgo)`)
printSuccess('Accessed values using all getter properties')
// Step 4: String formatting with toString() printStep(4, 'String formatting with toString()') printInfo('The toString() method formats the amount for human-readable display')
const formattedAmount = AlgoAmount.Algo(1.234567) printInfo(`\nAlgoAmount.Algo(1.234567).toString(): "${formattedAmount.toString()}"`)
const largeAmount = AlgoAmount.MicroAlgo(1_234_567_890) printInfo(`AlgoAmount.MicroAlgo(1234567890).toString(): "${largeAmount.toString()}"`)
// Custom formatting using properties printInfo('\nCustom formatting examples:') printInfo(` ${amount.algo.toFixed(2)} ALGO`) printInfo(` ${amount.microAlgo.toLocaleString('en-US')} µALGO`)
printSuccess('Demonstrated string formatting')
// Step 5: Arithmetic operations printStep(5, 'Arithmetic operations (addition, subtraction)') printInfo('AlgoAmount uses bigint internally for precision.') printInfo('Arithmetic is done by accessing .microAlgo and creating new AlgoAmount:')
const amountA = AlgoAmount.Algo(5) const amountB = AlgoAmount.Algo(2.5) printInfo(`\namountA = AlgoAmount.Algo(5): ${amountA.algo} ALGO`) printInfo(`amountB = AlgoAmount.Algo(2.5): ${amountB.algo} ALGO`)
// Addition const sum = AlgoAmount.MicroAlgo(amountA.microAlgo + amountB.microAlgo) printInfo(`\nAddition: amountA + amountB`) printInfo(` AlgoAmount.MicroAlgo(${amountA.microAlgo} + ${amountB.microAlgo})`) printInfo(` = ${sum.algo} ALGO (${sum.microAlgo} µALGO)`)
// Subtraction const difference = AlgoAmount.MicroAlgo(amountA.microAlgo - amountB.microAlgo) printInfo(`\nSubtraction: amountA - amountB`) printInfo(` AlgoAmount.MicroAlgo(${amountA.microAlgo} - ${amountB.microAlgo})`) printInfo(` = ${difference.algo} ALGO (${difference.microAlgo} µALGO)`)
// Adding transaction fees const amountWithFee = AlgoAmount.MicroAlgo(amountA.microAlgo + ALGORAND_MIN_TX_FEE.microAlgo) printInfo(`\nAdding transaction fee:`) printInfo(` ${amountA.algo} ALGO + ${ALGORAND_MIN_TX_FEE.microAlgo} µALGO fee = ${amountWithFee.algo} ALGO`)
printSuccess('Demonstrated arithmetic operations')
// Step 6: Comparison operations printStep(6, 'Comparison operations') printInfo('AlgoAmount implements valueOf() which enables comparison operators') printInfo('valueOf() returns the microAlgo value as a number')
const small = AlgoAmount.Algo(1) const medium = AlgoAmount.Algo(5) const large = AlgoAmount.Algo(10) const equalToMedium = AlgoAmount.MicroAlgo(5_000_000)
printInfo(`\nsmall = 1 ALGO, medium = 5 ALGO, large = 10 ALGO, equalToMedium = 5_000_000 µALGO`)
printInfo(`\nComparison results:`) printInfo(` small < medium: ${small < medium}`) printInfo(` medium < large: ${medium < large}`) printInfo(` large > small: ${large > small}`) printInfo(` medium >= equalToMedium: ${medium >= equalToMedium}`) printInfo(` medium <= equalToMedium: ${medium <= equalToMedium}`)
// Direct microAlgo comparison for exact equality (recommended) printInfo(`\nFor exact equality, compare microAlgo values (bigint):`) printInfo(` medium.microAlgo === equalToMedium.microAlgo: ${medium.microAlgo === equalToMedium.microAlgo}`)
printSuccess('Demonstrated comparison operations')
// Step 7: Avoiding floating point precision issues printStep(7, 'Avoiding floating point precision issues') printInfo('JavaScript floating point arithmetic has precision issues.') printInfo('AlgoAmount avoids this by using bigint internally.')
// Classic floating point problem const floatResult = 0.1 + 0.2 printInfo(`\nClassic floating point problem:`) printInfo(` 0.1 + 0.2 = ${floatResult} (not 0.3!)`) printInfo(` 0.1 + 0.2 === 0.3: ${floatResult === 0.3}`)
// AlgoAmount handles this correctly const algoA = AlgoAmount.Algo(0.1) const algoB = AlgoAmount.Algo(0.2) const algoSum = AlgoAmount.MicroAlgo(algoA.microAlgo + algoB.microAlgo)
printInfo(`\nUsing AlgoAmount:`) printInfo(` AlgoAmount.Algo(0.1).microAlgo = ${algoA.microAlgo}`) printInfo(` AlgoAmount.Algo(0.2).microAlgo = ${algoB.microAlgo}`) printInfo(` Sum in microAlgo: ${algoA.microAlgo} + ${algoB.microAlgo} = ${algoSum.microAlgo}`) printInfo(` Sum in Algo: ${algoSum.algo}`) printInfo(` ${algoSum.microAlgo} === ${AlgoAmount.Algo(0.3).microAlgo}: ${algoSum.microAlgo === AlgoAmount.Algo(0.3).microAlgo}`)
// Another precision example printInfo(`\nAnother example with 1.23456789 ALGO:`) const preciseAmount = AlgoAmount.Algo(1.23456789) printInfo(` AlgoAmount.Algo(1.23456789).microAlgo = ${preciseAmount.microAlgo}`) printInfo(` Stored as: 1,234,568 µALGO (rounded to 6 decimal places)`)
printSuccess('Demonstrated floating point precision handling')
// Step 8: Using AlgoAmount with payment transactions printStep(8, 'Using AlgoAmount with payment transactions') printInfo('AlgoAmount integrates seamlessly with AlgorandClient payment methods') printInfo('This step requires LocalNet to be running')
try { const algorand = AlgorandClient.defaultLocalNet()
// Verify connection await algorand.client.algod.status()
// Get accounts const dispenser = await algorand.account.dispenserFromEnvironment() const receiver = algorand.account.random()
printInfo(`\nSender (dispenser): ${shortenAddress(dispenser.addr.toString())}`) printInfo(`Receiver (random): ${shortenAddress(receiver.addr.toString())}`)
// Get initial balance const initialBalance = (await algorand.account.getInformation(dispenser.addr)).balance printInfo(`\nInitial sender balance: ${initialBalance.algo} ALGO`)
// Send payment using AlgoAmount const paymentAmount = AlgoAmount.Algo(1.5) printInfo(`\nSending ${paymentAmount.algo} ALGO (${paymentAmount.microAlgo} µALGO)...`)
const result = await algorand.send.payment({ sender: dispenser.addr, receiver: receiver.addr, amount: paymentAmount, })
printInfo(`Transaction ID: ${result.txIds[0]}`) printInfo(`Confirmed in round: ${result.confirmation.confirmedRound}`)
// Check balances after const senderBalance = (await algorand.account.getInformation(dispenser.addr)).balance const receiverBalance = (await algorand.account.getInformation(receiver.addr)).balance
printInfo(`\nFinal balances:`) printInfo(` Sender: ${senderBalance.algo} ALGO`) printInfo(` Receiver: ${receiverBalance.algo} ALGO (${receiverBalance.microAlgo} µALGO)`)
// Verify the receiver got exactly the right amount printInfo(`\nVerification:`) printInfo(` Expected receiver balance: ${paymentAmount.microAlgo} µALGO`) printInfo(` Actual receiver balance: ${receiverBalance.microAlgo} µALGO`) printInfo(` Match: ${receiverBalance.microAlgo === paymentAmount.microAlgo}`)
printSuccess('Payment transaction completed successfully!') } catch (error) { printError(`Failed to run payment example: ${error instanceof Error ? error.message : String(error)}`) printInfo('Make sure LocalNet is running (e.g., algokit localnet start)') printInfo('This step demonstrates AlgoAmount integration with transactions') }
// Step 9: Summary printStep(9, 'Summary') printInfo('AlgoAmount is a wrapper class for safe ALGO/µALGO handling:') printInfo('') printInfo('Factory methods:') printInfo(' - AlgoAmount.Algo(n) / AlgoAmount.Algos(n) - From ALGO') printInfo(' - AlgoAmount.MicroAlgo(n) / AlgoAmount.MicroAlgos(n) - From µALGO') printInfo(' - algo(n), algos(n), microAlgo(n), microAlgos(n) - Helper functions') printInfo('') printInfo('Properties:') printInfo(' - .algo / .algos - Get value in ALGO (number)') printInfo(' - .microAlgo / .microAlgos - Get value in µALGO (bigint)') printInfo('') printInfo('Operations:') printInfo(' - Arithmetic: Use .microAlgo + wrap result in AlgoAmount.MicroAlgo()') printInfo(' - Comparison: <, >, <=, >= work directly; use .microAlgo for ===') printInfo(' - Formatting: .toString() or access properties for custom format') printInfo('') printInfo('Best practices:') printInfo(' - Always use AlgoAmount for financial calculations') printInfo(' - Perform arithmetic on .microAlgo (bigint) to avoid precision loss') printInfo(' - Use helper functions (algo, microAlgo) for cleaner code') printInfo(' - Use transactionFees(n) when calculating fees for multiple transactions')
printSuccess('AlgoAmount Utility example completed!')}
main().catch((error) => { printError(`Unhandled error: ${error instanceof Error ? error.message : String(error)}`) process.exit(1)})Other examples in Algorand Client
Section titled “Other examples in Algorand Client”- Client Instantiation
- AlgoAmount Utility
- Signer Configuration
- Suggested Params Configuration
- Account Manager
- Send Payment
- Send Asset Operations
- Send Application Operations
- Create Transaction (Unsigned Transactions)
- Transaction Composer (Atomic Transaction Groups)
- Asset Manager
- App Manager
- App Deployer
- Client Manager
- Error Transformers
- Transaction Leases