Skip to content
Algorand Developer Portal

Address Encoding

← Back to Common Utilities

This example demonstrates how to encode and decode addresses between different formats and compute application addresses:

  • encodeAddress() to convert 32-byte public key to base32 string
  • decodeAddress() to convert base32 string to Address object
  • getApplicationAddress() to compute an app’s escrow address from app ID
  • getAddress() helper that accepts string, Address, or Addressable
  • Round-trip verification: encode(decode(address)) equals original
  • Understanding the relationship between public key bytes and checksum
  • No LocalNet required

From the repository root:

Terminal window
cd examples
npm run example common/02-address-encoding.ts

View source on GitHub

02-address-encoding.ts
/**
* Example: Address Encoding
*
* This example demonstrates how to encode and decode addresses between different formats
* and compute application addresses:
* - encodeAddress() to convert 32-byte public key to base32 string
* - decodeAddress() to convert base32 string to Address object
* - getApplicationAddress() to compute an app's escrow address from app ID
* - getAddress() helper that accepts string, Address, or Addressable
* - Round-trip verification: encode(decode(address)) equals original
* - Understanding the relationship between public key bytes and checksum
*
* Prerequisites:
* - No LocalNet required
*/
import {
Address,
decodeAddress,
encodeAddress,
getAddress,
getApplicationAddress,
} from '@algorandfoundation/algokit-utils/common';
import {
formatBytes,
formatHex,
printHeader,
printInfo,
printStep,
printSuccess,
} from '../shared/utils.js';
function main() {
printHeader('Address Encoding Example');
// Step 1: encodeAddress() - Convert 32-byte public key to base32 string
printStep(1, 'encodeAddress() - Public Key to Base32 String');
// Create a 32-byte public key (bytes 0-31)
const publicKey = new Uint8Array(32);
for (let i = 0; i < 32; i++) {
publicKey[i] = i;
}
printInfo(`Input: 32-byte public key`);
printInfo(`Public key bytes: ${formatBytes(publicKey, 8)}`);
printInfo(`Public key (hex): ${formatHex(publicKey)}`);
const encodedAddress = encodeAddress(publicKey);
printInfo(`\nOutput: Base32 encoded address`);
printInfo(`Encoded address: ${encodedAddress}`);
printInfo(`Address length: ${encodedAddress.length} characters`);
// Step 2: decodeAddress() - Convert base32 string to Address object
printStep(2, 'decodeAddress() - Base32 String to Address Object');
printInfo(`Input: "${encodedAddress}"`);
const decodedAddress = decodeAddress(encodedAddress);
printInfo(`\nOutput: Address object`);
printInfo(`Type: ${decodedAddress.constructor.name}`);
printInfo(`Public key length: ${decodedAddress.publicKey.length} bytes`);
printInfo(`Public key bytes: ${formatBytes(decodedAddress.publicKey, 8)}`);
// Step 3: Round-trip verification
printStep(3, 'Round-Trip Verification');
// encode(decode(address)) === address
const originalAddress = 'AAAQEAYEAUDAOCAJBIFQYDIOB4IBCEQTCQKRMFYYDENBWHA5DYP7MUPJQE';
printInfo(`Original address: ${originalAddress}`);
const decoded = decodeAddress(originalAddress);
const reEncoded = encodeAddress(decoded.publicKey);
printInfo(`After decode → encode: ${reEncoded}`);
printInfo(`Round-trip matches: ${originalAddress === reEncoded}`);
// decode(encode(publicKey)).publicKey === publicKey
printInfo(`\nVerifying bytes round-trip:`);
const encoded = encodeAddress(publicKey);
const decodedBack = decodeAddress(encoded);
const bytesMatch = publicKey.every(
(byte: number, i: number) => byte === decodedBack.publicKey[i],
);
printInfo(`Original public key matches decoded: ${bytesMatch}`);
// Step 4: Public Key Bytes and Checksum Relationship
printStep(4, 'Public Key Bytes and Checksum Relationship');
printInfo('An Algorand address consists of:');
printInfo(' - 32 bytes: public key');
printInfo(' - 4 bytes: checksum (last 4 bytes of SHA512/256 hash of public key)');
printInfo(' - Encoded together as 58 character base32 string');
printInfo(`\nFor our sample address:`);
printInfo(` Public key (32 bytes): ${formatHex(decodedAddress.publicKey)}`);
const checksum = decodedAddress.checksum();
printInfo(` Checksum (4 bytes): ${formatHex(checksum)}`);
// Show how the checksum appears at the end of the address
printInfo(`\nThe checksum is computed by:`);
printInfo(` 1. Taking SHA512/256 hash of the public key`);
printInfo(` 2. Using the last 4 bytes of that hash`);
// Demonstrate with zero address
const zeroAddress = Address.zeroAddress();
const zeroChecksum = zeroAddress.checksum();
printInfo(`\nZero address example:`);
printInfo(` Public key: ${formatHex(zeroAddress.publicKey.slice(0, 8))}... (all zeros)`);
printInfo(` Checksum: ${formatHex(zeroChecksum)}`);
printInfo(` Full address: ${zeroAddress.toString()}`);
// Step 5: getApplicationAddress() - Compute App Escrow Address
printStep(5, 'getApplicationAddress() - Application Escrow Address');
printInfo('Every application has an escrow address derived from its app ID.');
printInfo('This address can hold Algos and ASAs for the application.');
// Compute addresses for some app IDs
const appIds = [1n, 123n, 1234567890n];
for (const appId of appIds) {
const appAddress = getApplicationAddress(appId);
printInfo(`\nApp ID ${appId}:`);
printInfo(` Escrow address: ${appAddress.toString()}`);
printInfo(` Public key (first 8 bytes): ${formatHex(appAddress.publicKey.slice(0, 8))}...`);
}
printInfo(`\nThe address is computed by:`);
printInfo(` 1. Concatenating "appID" prefix with 8-byte big-endian app ID`);
printInfo(` 2. Taking SHA512/256 hash of the result`);
printInfo(` 3. Using the 32-byte hash as the public key`);
// Step 6: getAddress() - Flexible Address Helper
printStep(6, 'getAddress() - Flexible Address Helper');
printInfo('getAddress() accepts multiple input types and returns an Address object:');
printInfo(' - string: parses as base32 address');
printInfo(' - Address: returns as-is');
printInfo(' - Addressable: extracts the .addr property');
// From string
const fromString = getAddress('AAAQEAYEAUDAOCAJBIFQYDIOB4IBCEQTCQKRMFYYDENBWHA5DYP7MUPJQE');
printInfo(`\nFrom string: ${fromString.toString()}`);
// From Address object
const addressObj = Address.fromString(
'AAAQEAYEAUDAOCAJBIFQYDIOB4IBCEQTCQKRMFYYDENBWHA5DYP7MUPJQE',
);
const fromAddress = getAddress(addressObj);
printInfo(`From Address object: ${fromAddress.toString()}`);
printInfo(`Same object returned: ${fromAddress === addressObj}`);
// From Addressable (object with .addr property)
const addressable = { addr: addressObj };
const fromAddressable = getAddress(addressable);
printInfo(`From Addressable: ${fromAddressable.toString()}`);
printInfo(`Extracted .addr property: ${fromAddressable === addressObj}`);
// All three produce equal addresses
printInfo(
`\nAll inputs produce equal addresses: ${fromString.equals(fromAddress) && fromAddress.equals(fromAddressable)}`,
);
// Step 7: Practical Use Cases
printStep(7, 'Practical Use Cases');
printInfo('Common scenarios for address encoding/decoding:');
printInfo('\n1. Converting wallet public keys to displayable addresses:');
const walletPubKey = new Uint8Array(32).fill(42); // Simulated wallet public key
const walletAddress = encodeAddress(walletPubKey);
printInfo(` Public key → Address: ${walletAddress.substring(0, 30)}...`);
printInfo('\n2. Extracting public key from address for cryptographic operations:');
const someAddress = 'AAAQEAYEAUDAOCAJBIFQYDIOB4IBCEQTCQKRMFYYDENBWHA5DYP7MUPJQE';
const extracted = decodeAddress(someAddress);
printInfo(` Address → Public key: ${formatHex(extracted.publicKey.slice(0, 8))}...`);
printInfo('\n3. Computing application escrow for sending funds:');
const myAppId = 12345n;
const escrow = getApplicationAddress(myAppId);
printInfo(` App ${myAppId} escrow: ${escrow.toString().substring(0, 30)}...`);
printInfo('\n4. Normalizing address inputs in functions:');
printInfo(' function sendPayment(to: ReadableAddress) {');
printInfo(' const toAddress = getAddress(to) // Works with string, Address, or Addressable');
printInfo(' // ... rest of implementation');
printInfo(' }');
// Step 8: Summary
printStep(8, 'Summary');
printInfo('Encoding/Decoding Functions:');
printInfo(' - encodeAddress(publicKey) - 32-byte Uint8Array → 58-char base32 string');
printInfo(' - decodeAddress(address) - 58-char base32 string → Address object');
printInfo('\nApplication Address:');
printInfo(' - getApplicationAddress(appId) - App ID → Escrow Address');
printInfo('\nFlexible Helper:');
printInfo(' - getAddress(addr) - string | Address | Addressable → Address');
printInfo('\nAddress Structure:');
printInfo(' - 32 bytes public key + 4 bytes checksum = 36 bytes');
printInfo(' - Base32 encoded to 58 character string');
printSuccess('Address Encoding example completed successfully!');
}
main();