Skip to content
Algorand Developer Portal

ABI Type Parsing

← Back to ABI Encoding

This example demonstrates how to parse ABI type strings into type objects using ABIType.from(). It shows parsing of:

  • Primitive types: uint8, uint64, uint256, bool, byte, address, string
  • Array types: uint64[], byte[32], address[5]
  • Tuple types: (uint64,address), (bool,string,uint256) And demonstrates type properties and instanceof checks for type category detection.
  • No LocalNet required

From the repository root:

Terminal window
cd examples
npm run example abi/01-type-parsing.ts

View source on GitHub

01-type-parsing.ts
/**
* Example: ABI Type Parsing
*
* This example demonstrates how to parse ABI type strings into type objects using ABIType.from().
* It shows parsing of:
* - Primitive types: uint8, uint64, uint256, bool, byte, address, string
* - Array types: uint64[], byte[32], address[5]
* - Tuple types: (uint64,address), (bool,string,uint256)
*
* And demonstrates type properties and instanceof checks for type category detection.
*
* Prerequisites:
* - No LocalNet required
*/
import {
ABIAddressType,
ABIArrayDynamicType,
ABIArrayStaticType,
ABIBoolType,
ABIByteType,
ABIStringType,
ABITupleType,
ABIType,
ABIUintType,
} from '@algorandfoundation/algokit-utils/abi';
import { printHeader, printInfo, printStep, printSuccess } from '../shared/utils.js';
function main() {
printHeader('ABI Type Parsing Example');
// Step 1: Parse primitive unsigned integer types
printStep(1, 'Parse Unsigned Integer Types');
const uint8Type = ABIType.from('uint8');
const uint64Type = ABIType.from('uint64');
const uint256Type = ABIType.from('uint256');
printInfo(`Parsed 'uint8': ${uint8Type.toString()}`);
printInfo(`Parsed 'uint64': ${uint64Type.toString()}`);
printInfo(`Parsed 'uint256': ${uint256Type.toString()}`);
// Show uint-specific properties
if (uint8Type instanceof ABIUintType) {
printInfo(` uint8 bitSize: ${uint8Type.bitSize}`);
printInfo(` uint8 byteLen: ${uint8Type.byteLen()}`);
printInfo(` uint8 isDynamic: ${uint8Type.isDynamic()}`);
}
if (uint64Type instanceof ABIUintType) {
printInfo(` uint64 bitSize: ${uint64Type.bitSize}`);
printInfo(` uint64 byteLen: ${uint64Type.byteLen()}`);
}
if (uint256Type instanceof ABIUintType) {
printInfo(` uint256 bitSize: ${uint256Type.bitSize}`);
printInfo(` uint256 byteLen: ${uint256Type.byteLen()}`);
}
// Step 2: Parse other primitive types
printStep(2, 'Parse Other Primitive Types');
const boolType = ABIType.from('bool');
const byteType = ABIType.from('byte');
const addressType = ABIType.from('address');
const stringType = ABIType.from('string');
printInfo(`Parsed 'bool': ${boolType.toString()}`);
printInfo(` bool byteLen: ${boolType.byteLen()}`);
printInfo(` bool isDynamic: ${boolType.isDynamic()}`);
printInfo(`Parsed 'byte': ${byteType.toString()}`);
printInfo(` byte byteLen: ${byteType.byteLen()}`);
printInfo(` byte isDynamic: ${byteType.isDynamic()}`);
printInfo(`Parsed 'address': ${addressType.toString()}`);
printInfo(` address byteLen: ${addressType.byteLen()}`);
printInfo(` address isDynamic: ${addressType.isDynamic()}`);
printInfo(`Parsed 'string': ${stringType.toString()}`);
printInfo(` string isDynamic: ${stringType.isDynamic()}`);
// Step 3: Parse dynamic array types
printStep(3, 'Parse Dynamic Array Types');
const uint64ArrayType = ABIType.from('uint64[]');
const addressArrayType = ABIType.from('address[]');
printInfo(`Parsed 'uint64[]': ${uint64ArrayType.toString()}`);
if (uint64ArrayType instanceof ABIArrayDynamicType) {
printInfo(` childType: ${uint64ArrayType.childType.toString()}`);
printInfo(` isDynamic: ${uint64ArrayType.isDynamic()}`);
}
printInfo(`Parsed 'address[]': ${addressArrayType.toString()}`);
if (addressArrayType instanceof ABIArrayDynamicType) {
printInfo(` childType: ${addressArrayType.childType.toString()}`);
}
// Step 4: Parse static array types
printStep(4, 'Parse Static Array Types');
const byte32Type = ABIType.from('byte[32]');
const address5Type = ABIType.from('address[5]');
printInfo(`Parsed 'byte[32]': ${byte32Type.toString()}`);
if (byte32Type instanceof ABIArrayStaticType) {
printInfo(` childType: ${byte32Type.childType.toString()}`);
printInfo(` length: ${byte32Type.length}`);
printInfo(` byteLen: ${byte32Type.byteLen()}`);
printInfo(` isDynamic: ${byte32Type.isDynamic()}`);
}
printInfo(`Parsed 'address[5]': ${address5Type.toString()}`);
if (address5Type instanceof ABIArrayStaticType) {
printInfo(` childType: ${address5Type.childType.toString()}`);
printInfo(` length: ${address5Type.length}`);
printInfo(` byteLen: ${address5Type.byteLen()}`);
}
// Step 5: Parse tuple types
printStep(5, 'Parse Tuple Types');
const simpleTupleType = ABIType.from('(uint64,address)');
const complexTupleType = ABIType.from('(bool,string,uint256)');
printInfo(`Parsed '(uint64,address)': ${simpleTupleType.toString()}`);
if (simpleTupleType instanceof ABITupleType) {
printInfo(` childTypes count: ${simpleTupleType.childTypes.length}`);
simpleTupleType.childTypes.forEach((childType, index) => {
printInfo(` [${index}]: ${childType.toString()}`);
});
printInfo(` isDynamic: ${simpleTupleType.isDynamic()}`);
printInfo(` byteLen: ${simpleTupleType.byteLen()}`);
}
printInfo(`Parsed '(bool,string,uint256)': ${complexTupleType.toString()}`);
if (complexTupleType instanceof ABITupleType) {
printInfo(` childTypes count: ${complexTupleType.childTypes.length}`);
complexTupleType.childTypes.forEach((childType, index) => {
printInfo(` [${index}]: ${childType.toString()}`);
});
printInfo(` isDynamic: ${complexTupleType.isDynamic()} (contains 'string' which is dynamic)`);
}
// Step 6: Parse nested tuple types
printStep(6, 'Parse Nested Tuple Types');
const nestedTupleType = ABIType.from('((uint64,bool),address[])');
printInfo(`Parsed '((uint64,bool),address[])': ${nestedTupleType.toString()}`);
if (nestedTupleType instanceof ABITupleType) {
printInfo(` childTypes count: ${nestedTupleType.childTypes.length}`);
nestedTupleType.childTypes.forEach((childType, index) => {
printInfo(` [${index}]: ${childType.toString()}`);
if (childType instanceof ABITupleType) {
childType.childTypes.forEach((nestedChild, nestedIndex) => {
printInfo(` [${nestedIndex}]: ${nestedChild.toString()}`);
});
}
});
printInfo(` isDynamic: ${nestedTupleType.isDynamic()}`);
}
// Step 7: Type category detection using instanceof
printStep(7, 'Type Category Detection with instanceof');
const testTypes = [
'uint64',
'bool',
'byte',
'address',
'string',
'uint64[]',
'byte[32]',
'(uint64,address)',
];
for (const typeStr of testTypes) {
const parsedType = ABIType.from(typeStr);
let category = 'Unknown';
if (parsedType instanceof ABIUintType) {
category = 'UintType';
} else if (parsedType instanceof ABIBoolType) {
category = 'BoolType';
} else if (parsedType instanceof ABIByteType) {
category = 'ByteType';
} else if (parsedType instanceof ABIAddressType) {
category = 'AddressType';
} else if (parsedType instanceof ABIStringType) {
category = 'StringType';
} else if (parsedType instanceof ABIArrayDynamicType) {
category = 'ArrayDynamicType';
} else if (parsedType instanceof ABIArrayStaticType) {
category = 'ArrayStaticType';
} else if (parsedType instanceof ABITupleType) {
category = 'TupleType';
}
printInfo(`'${typeStr}' -> ${category}`);
}
// Step 8: Demonstrate type equality
printStep(8, 'Type Equality Comparison');
const type1 = ABIType.from('uint64');
const type2 = ABIType.from('uint64');
const type3 = ABIType.from('uint32');
printInfo(`ABIType.from('uint64').equals(ABIType.from('uint64')): ${type1.equals(type2)}`);
printInfo(`ABIType.from('uint64').equals(ABIType.from('uint32')): ${type1.equals(type3)}`);
const tuple1 = ABIType.from('(uint64,address)');
const tuple2 = ABIType.from('(uint64,address)');
const tuple3 = ABIType.from('(uint64,bool)');
printInfo(
`ABIType.from('(uint64,address)').equals(ABIType.from('(uint64,address)')): ${tuple1.equals(tuple2)}`,
);
printInfo(
`ABIType.from('(uint64,address)').equals(ABIType.from('(uint64,bool)')): ${tuple1.equals(tuple3)}`,
);
printSuccess('ABI Type Parsing example completed successfully!');
}
main();