Skip to content

ABI Address Type

← Back to ABI Encoding

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

  • Encoding address strings (base32 format) to 32 bytes
  • Encoding raw 32-byte public key (bytes)
  • 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 - pure ABI encoding/decoding

From the repository’s examples directory:

Terminal window
cd examples
uv run python abi/03_address_type.py

View source on GitHub

03_address_type.py
# ruff: noqa: N999, PLR0915
"""
Example: ABI Address Type
This example demonstrates how to encode and decode Algorand addresses using AddressType:
- Encoding address strings (base32 format) to 32 bytes
- Encoding raw 32-byte public key (bytes)
- 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 - pure ABI encoding/decoding
"""
from shared import format_bytes, format_hex, print_header, print_info, print_step, print_success
from algokit_abi import abi
from algokit_common import address_from_public_key, public_key_from_address
from algokit_common.constants import ZERO_ADDRESS
def main() -> None:
print_header("ABI Address Type Example")
# Step 1: Create AddressType and inspect properties
print_step(1, "AddressType Properties")
address_type = abi.AddressType()
print_info(f"Type name: {address_type}")
print_info(f"Byte length: {address_type.byte_len()} bytes")
print_info(f"Is dynamic: {address_type.is_dynamic()}")
# Step 2: Encode a base32 address string to bytes
print_step(2, "Encode Address String (Base32) to Bytes")
# Example address - the zero address
zero_address_string = ZERO_ADDRESS
print_info(f"Zero address string: {zero_address_string}")
print_info(f"Address string length: {len(zero_address_string)} characters")
zero_encoded = address_type.encode(zero_address_string)
print_info(f"Encoded bytes: {format_hex(zero_encoded)}")
print_info(f"Encoded length: {len(zero_encoded)} bytes (exactly 32, no length prefix)")
# Verify the zero address encodes to all zeros
all_zeros = all(byte == 0 for byte in zero_encoded)
print_info(f"All bytes are zero: {all_zeros}")
# Step 3: Encode another address string
print_step(3, "Encode a Real Address String")
# Create a sample address from a known public key (32 bytes of incrementing values)
sample_public_key = bytes(range(32))
# Create Address string from public key
sample_address_string = address_from_public_key(sample_public_key)
print_info(f"Sample address string: {sample_address_string}")
print_info(f"Address string length: {len(sample_address_string)} characters")
sample_encoded = address_type.encode(sample_address_string)
print_info(f"Encoded bytes: {format_bytes(sample_encoded, 16)}")
print_info(f"Encoded as hex: {format_hex(sample_encoded)}")
print_info(f"Encoded length: {len(sample_encoded)} bytes")
# Step 4: Encode from raw 32-byte public key (bytes)
print_step(4, "Encode from Raw 32-Byte Public Key")
# AddressType can also encode directly from bytes
raw_public_key = bytes(
[
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,
]
)
print_info(f"Raw public key: {format_hex(raw_public_key)}")
encoded_from_raw = address_type.encode(raw_public_key)
print_info(f"Encoded from raw: {format_hex(encoded_from_raw)}")
# Verify encoding from raw bytes returns the same bytes
raw_bytes_match = encoded_from_raw == raw_public_key
print_info(f"Raw bytes match encoded: {raw_bytes_match}")
# Step 5: Decode bytes back to address string
print_step(5, "Decode Bytes Back to Address String")
# Decode the sample encoded bytes back to address string
decoded_sample_address = address_type.decode(sample_encoded)
print_info(f"Original address: {sample_address_string}")
print_info(f"Decoded address: {decoded_sample_address}")
print_info(f"Round-trip verified: {decoded_sample_address == sample_address_string}")
# Decode zero address
decoded_zero_address = address_type.decode(zero_encoded)
print_info(f"\nOriginal zero address: {zero_address_string}")
print_info(f"Decoded zero address: {decoded_zero_address}")
print_info(f"Round-trip verified: {decoded_zero_address == zero_address_string}")
# Decode the raw public key
decoded_from_raw_address = address_type.decode(encoded_from_raw)
print_info(f"\nRaw public key as address: {decoded_from_raw_address}")
# Step 6: Relationship between Algorand address and public key bytes
print_step(6, "Address vs Public Key Relationship")
print_info("Algorand address format:")
print_info(" - Base32 encoded string")
print_info(" - 58 characters long")
print_info(" - Contains: 32-byte public key + 4-byte checksum")
print_info("\nABI address encoding:")
print_info(" - Just the raw 32-byte public key")
print_info(" - No checksum included")
print_info(" - No length prefix (unlike ABI string type)")
print_info(" - Fixed size, not dynamic")
# Demonstrate using public_key_from_address directly
print_info("\nUsing public_key_from_address:")
public_key = public_key_from_address(sample_address_string)
print_info(f" public_key_from_address('{sample_address_string[:20]}...')")
print_info(f" public_key: {format_bytes(public_key, 8)}")
print_info(f" address_from_public_key(): {address_from_public_key(public_key)}")
# Show that AddressType encoding equals public_key_from_address
public_key_matches = public_key == sample_encoded
print_info(f"\nABI encoding equals public_key_from_address: {public_key_matches}")
# Step 7: Encoding bytes directly
print_step(7, "Encode Raw Bytes Directly")
# AddressType can accept raw bytes (32 bytes)
address_from_bytes = address_type.encode(raw_public_key)
print_info(f"Raw public key: {format_hex(raw_public_key)}")
print_info(f"Encoded from bytes: {format_hex(address_from_bytes)}")
bytes_match = address_from_bytes == raw_public_key
print_info(f"Encoding matches raw public key: {bytes_match}")
# Step 8: Summary - all encoding methods produce 32 bytes
print_step(8, "Summary - All Encoding Methods")
print_info("AddressType accepts:")
print_info(" 1. Address string (base32 format, 58 chars) -> extracts public key")
print_info(" 2. bytes (32 bytes) -> uses directly")
print_info("\nAll methods produce exactly 32 bytes (no length prefix):")
print_info(f" From string: {len(address_type.encode(sample_address_string))} bytes")
print_info(f" From bytes: {len(address_type.encode(raw_public_key))} bytes")
print_info("\nDecode always returns base32 address string (58 chars)")
print_success("ABI Address Type example completed successfully!")
if __name__ == "__main__":
main()