ABI Type Parsing
Description
Section titled “Description”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
Section titled “Prerequisites”- No LocalNet required
Run This Example
Section titled “Run This Example”From the repository root:
cd examplesnpm run example abi/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();