Skip to content
Algorand Developer Portal

ABI Address Type

← Back to ABI Encoding

This example demonstrates how to encode and decode Algorand addresses using ABIAddressType:

  • Encoding address strings (base32 format) to 32 bytes
  • Encoding raw 32-byte public key (Uint8Array)
  • Decoding bytes back to address string
  • Verifying address encoding is exactly 32 bytes (no length prefix)
  • Understanding relationship between Algorand address and public key bytes Algorand addresses are 58 characters in base32 encoding, which includes:
  • 32 bytes of public key
  • 4 bytes of checksum (computed from public key) The ABI encoding is just the raw 32-byte public key without checksum.
  • No LocalNet required

From the repository root:

Terminal window
cd examples
npm run example abi/03-address-type.ts

View source on GitHub

03-address-type.ts
/**
* Example: ABI Address Type
*
* This example demonstrates how to encode and decode Algorand addresses using ABIAddressType:
* - Encoding address strings (base32 format) to 32 bytes
* - Encoding raw 32-byte public key (Uint8Array)
* - Decoding bytes back to address string
* - Verifying address encoding is exactly 32 bytes (no length prefix)
* - Understanding relationship between Algorand address and public key bytes
*
* Algorand addresses are 58 characters in base32 encoding, which includes:
* - 32 bytes of public key
* - 4 bytes of checksum (computed from public key)
*
* The ABI encoding is just the raw 32-byte public key without checksum.
*
* Prerequisites:
* - No LocalNet required
*/
import { Address, ALGORAND_ZERO_ADDRESS_STRING } from '@algorandfoundation/algokit-utils';
import { ABIAddressType } from '@algorandfoundation/algokit-utils/abi';
import {
formatBytes,
formatHex,
printHeader,
printInfo,
printStep,
printSuccess,
} from '../shared/utils.js';
function main() {
printHeader('ABI Address Type Example');
// Step 1: Create ABIAddressType and inspect properties
printStep(1, 'ABIAddressType Properties');
const addressType = new ABIAddressType();
printInfo(`Type name: ${addressType.toString()}`);
printInfo(`Byte length: ${addressType.byteLen()} bytes`);
printInfo(`Is dynamic: ${addressType.isDynamic()}`);
// Step 2: Encode a base32 address string to bytes
printStep(2, 'Encode Address String (Base32) to Bytes');
// Example address - the zero address
const zeroAddressString = ALGORAND_ZERO_ADDRESS_STRING;
printInfo(`Zero address string: ${zeroAddressString}`);
printInfo(`Address string length: ${zeroAddressString.length} characters`);
const zeroEncoded = addressType.encode(zeroAddressString);
printInfo(`Encoded bytes: ${formatHex(zeroEncoded)}`);
printInfo(`Encoded length: ${zeroEncoded.length} bytes (exactly 32, no length prefix)`);
// Verify the zero address encodes to all zeros
const allZeros = zeroEncoded.every(byte => byte === 0);
printInfo(`All bytes are zero: ${allZeros}`);
// Step 3: Encode another address string
printStep(3, 'Encode a Real Address String');
// Create a sample address from a known public key (32 bytes of incrementing values)
const samplePublicKey = new Uint8Array(32);
for (let i = 0; i < 32; i++) {
samplePublicKey[i] = i;
}
// Create Address object from public key to get base32 string
const sampleAddress = new Address(samplePublicKey);
const sampleAddressString = sampleAddress.toString();
printInfo(`Sample address string: ${sampleAddressString}`);
printInfo(`Address string length: ${sampleAddressString.length} characters`);
const sampleEncoded = addressType.encode(sampleAddressString);
printInfo(`Encoded bytes: ${formatBytes(sampleEncoded, 16)}`);
printInfo(`Encoded as hex: ${formatHex(sampleEncoded)}`);
printInfo(`Encoded length: ${sampleEncoded.length} bytes`);
// Step 4: Encode from raw 32-byte public key (Uint8Array)
printStep(4, 'Encode from Raw 32-Byte Public Key');
// ABIAddressType can also encode directly from a Uint8Array
const rawPublicKey = new Uint8Array([
0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89,
0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89,
]);
printInfo(`Raw public key: ${formatHex(rawPublicKey)}`);
const encodedFromRaw = addressType.encode(rawPublicKey);
printInfo(`Encoded from raw: ${formatHex(encodedFromRaw)}`);
// Verify encoding from raw bytes returns the same bytes
const rawBytesMatch = encodedFromRaw.every((byte, index) => byte === rawPublicKey[index]);
printInfo(`Raw bytes match encoded: ${rawBytesMatch}`);
// Step 5: Decode bytes back to address string
printStep(5, 'Decode Bytes Back to Address String');
// Decode the sample encoded bytes back to address string
const decodedSampleAddress = addressType.decode(sampleEncoded);
printInfo(`Original address: ${sampleAddressString}`);
printInfo(`Decoded address: ${decodedSampleAddress}`);
printInfo(`Round-trip verified: ${decodedSampleAddress === sampleAddressString}`);
// Decode zero address
const decodedZeroAddress = addressType.decode(zeroEncoded);
printInfo(`\nOriginal zero address: ${zeroAddressString}`);
printInfo(`Decoded zero address: ${decodedZeroAddress}`);
printInfo(`Round-trip verified: ${decodedZeroAddress === zeroAddressString}`);
// Decode the raw public key
const decodedFromRawAddress = addressType.decode(encodedFromRaw);
printInfo(`\nRaw public key as address: ${decodedFromRawAddress}`);
// Step 6: Relationship between Algorand address and public key bytes
printStep(6, 'Address vs Public Key Relationship');
printInfo('Algorand address format:');
printInfo(' - Base32 encoded string');
printInfo(' - 58 characters long');
printInfo(' - Contains: 32-byte public key + 4-byte checksum');
printInfo('\nABI address encoding:');
printInfo(' - Just the raw 32-byte public key');
printInfo(' - No checksum included');
printInfo(' - No length prefix (unlike ABI string type)');
printInfo(' - Fixed size, not dynamic');
// Demonstrate using Address class directly
printInfo('\nUsing Address class:');
const addr = Address.fromString(sampleAddressString);
printInfo(` Address.fromString('${sampleAddressString.substring(0, 20)}...')`);
printInfo(` .publicKey: ${formatBytes(addr.publicKey, 8)}`);
printInfo(` .toString(): ${addr.toString()}`);
// Show that ABIAddressType encoding equals Address.publicKey
const publicKeyMatches = addr.publicKey.every((byte, index) => byte === sampleEncoded[index]);
printInfo(`\nABI encoding equals Address.publicKey: ${publicKeyMatches}`);
// Step 7: Encoding Address object directly
printStep(7, 'Encode Address Object Directly');
// ABIAddressType can also accept Address objects
const addressObject = new Address(rawPublicKey);
const encodedFromAddressObject = addressType.encode(addressObject);
printInfo(`Address object: ${addressObject.toString()}`);
printInfo(`Encoded from Address object: ${formatHex(encodedFromAddressObject)}`);
const addressObjectMatches = encodedFromAddressObject.every(
(byte, index) => byte === rawPublicKey[index],
);
printInfo(`Encoding matches raw public key: ${addressObjectMatches}`);
// Step 8: Summary - all encoding methods produce 32 bytes
printStep(8, 'Summary - All Encoding Methods');
printInfo('ABIAddressType accepts:');
printInfo(' 1. Address string (base32 format, 58 chars) -> extracts public key');
printInfo(' 2. Uint8Array (32 bytes) -> uses directly');
printInfo(' 3. Address object -> extracts publicKey property');
printInfo('\nAll methods produce exactly 32 bytes (no length prefix):');
printInfo(` From string: ${addressType.encode(sampleAddressString).length} bytes`);
printInfo(` From Uint8Array: ${addressType.encode(rawPublicKey).length} bytes`);
printInfo(` From Address: ${addressType.encode(addressObject).length} bytes`);
printInfo('\nDecode always returns base32 address string (58 chars)');
printSuccess('ABI Address Type example completed successfully!');
}
main();