Skip to main content

Special Types

Special types handle domain-specific MultiversX data like addresses, tokens, and hashes.

Address

32-byte MultiversX addresses:

// From bech32 string directly
final address = AddressType.create(
'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu'
);

// nativeValue returns the bech32 string
final bech32 = address.nativeValue; // String: 'erd1qqq...'
print(bech32);

// For bytes or hex representation, use the AddressValue methods
final addressValue = address as AddressValue;
print(addressValue.toBech32()); // erd1qqq...
print(addressValue.toHex()); // 0000...

Creating Address Values

// Method 1: Static factory - AddressType.create()
final addr1 = AddressType.create(
'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu'
);

// Method 2: Direct constructor - AddressValue.fromBech32()
final addr2 = AddressValue.fromBech32(
'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th'
);

// Method 3: Via type singleton
final addr3 = AddressType.type.createValue(
'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu'
);

// From hex string
final fromHex = AddressType.create(
'0000000000000000000000000000000000000000000000000000000000000000'
);

// From bytes
final fromBytes = AddressType.create(List<int>.filled(32, 0));

// Zero address (system address)
final zeroAddr = AddressType.createZero();

TokenIdentifier

ESDT token identifiers:

// Standard ESDT
final token = TokenIdentifierType.create('USDC-123456');
print(token.nativeValue); // 'USDC-123456'

// NFT collection
final nft = TokenIdentifierType.create('MYNFT-abc123');

Token Identifier Format

TICKER-randomhex
└─────┘ └───────┘
3-10 6 hex
chars chars

Examples:

  • WEGLD-bd4d79 - Wrapped EGLD
  • USDC-c76f1f - USD Coin
  • MEX-455c57 - MEX token

EgldOrEsdtTokenIdentifier

Either EGLD or an ESDT token:

// EGLD
final egld = EgldOrEsdtTokenIdentifierType.create('EGLD');
print(egld.nativeValue); // 'EGLD'

// ESDT
final esdt = EgldOrEsdtTokenIdentifierType.create('USDC-123456');
print(esdt.nativeValue); // 'USDC-123456'

This is commonly used in payable endpoints that accept either EGLD or tokens.

EsdtTokenPayment

Complete token payment information:

// Define EsdtTokenPayment type
final paymentType = StructBuilder('EsdtTokenPayment')
.field('token_identifier', TokenIdentifierType.type)
.field('token_nonce', U64Type.type)
.field('amount', BigUIntType.type)
.build();

// Create payment value
final payment = paymentType.createValue({
'token_identifier': 'USDC-123456',
'token_nonce': BigInt.zero, // 0 for fungible
'amount': BigInt.from(1000000),
});

NFT Payment

// Define EsdtTokenPayment type
final paymentType = StructBuilder('EsdtTokenPayment')
.field('token_identifier', TokenIdentifierType.type)
.field('token_nonce', U64Type.type)
.field('amount', BigUIntType.type)
.build();

// NFT with nonce
final nftPayment = paymentType.createValue({
'token_identifier': 'MYNFT-abc123',
'token_nonce': BigInt.from(42), // NFT nonce
'amount': BigInt.one,
});

H256

32-byte hash values (256 bits):

import 'dart:typed_data';

// From bytes (must be exactly 32 bytes)
final hash = H256Type.create(List<int>.filled(32, 0));
print(hash.nativeValue); // Uint8List of 32 bytes

// From hex string (64 characters)
final hashHex = H256Type.create(
'0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20'
);

// Common use: transaction hashes, merkle roots

CodeMetadata

Smart contract deployment metadata stored as 16-bit integer (2 bytes, big-endian):

// From integer flags
final metadata = CodeMetadataType.create(0x0506); // upgradeable + readable + payable + payableBySc

// Check individual flags on the value
print(metadata.isUpgradeable); // true
print(metadata.isReadable); // true
print(metadata.isPayable); // true
print(metadata.isPayableBySc); // true

// From byte array (2 bytes, big-endian)
final fromBytes = CodeMetadataType.create([0x05, 0x06]); // All flags set

Metadata Flags (Big-Endian Layout)

CodeMetadata uses a 2-byte big-endian format where flags are split across both bytes:

FlagHex ValueByteBitDescription
upgradeable0x010000Contract can be upgraded
readable0x040002Other contracts can read storage
payable0x000211Can receive EGLD
payableBySc0x000412Can receive from smart contracts

Common Flag Combinations

// Upgradeable only
final upgradeOnly = CodeMetadataType.create(0x0100);

// Upgradeable + readable
final upgradeRead = CodeMetadataType.create(0x0500);

// Upgradeable + payable
final upgradePay = CodeMetadataType.create(0x0102);

// Upgradeable + readable + payable
final standard = CodeMetadataType.create(0x0502);

// All flags (upgradeable + readable + payable + payableBySc)
final allFlags = CodeMetadataType.create(0x0506);

ManagedDecimal

Fixed-point decimal numbers:

// Decimal with 18 places (like EGLD)
final decimal = ManagedDecimalType.create(
BigInt.parse('1500000000000000000'), // 1.5 * 10^18
18, // scale
);

// The value represents 1.5

Nothing

The unit/void type:

final nothing = NothingType.create();
print(nothing.nativeValue); // null

Used for endpoints that don't return a value.

Complete Example

import 'package:abidock_mvx/abidock_mvx.dart';
import 'dart:typed_data';

void main() {
print('=== Special Types Demo ===\n');

// === Address ===
print('Address:');
final address = AddressType.create(
'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu'
);
final bech32 = address.nativeValue; // String
final addressValue = address as AddressValue;
print(' Bech32: $bech32');
print(' Hex: ${addressValue.toHex().substring(0, 16)}...');

// === TokenIdentifier ===
final token = TokenIdentifierType.create('WEGLD-bd4d79');
print(' Token: ${token.nativeValue}');

// === EgldOrEsdtTokenIdentifier ===
final egld = EgldOrEsdtTokenIdentifierType.create('EGLD');
final esdt = EgldOrEsdtTokenIdentifierType.create('MEX-455c57');
print(' EGLD: ${egld.nativeValue}');
print(' ESDT: ${esdt.nativeValue}');

// === EsdtTokenPayment ===

// Define the type
final paymentType = StructBuilder('EsdtTokenPayment')
.field('token_identifier', TokenIdentifierType.type)
.field('token_nonce', U64Type.type)
.field('amount', BigUIntType.type)
.build();

// Create the value
final payment = paymentType.createValue({
'token_identifier': 'USDC-c76f1f',
'token_nonce': BigInt.zero,
'amount': BigInt.from(1000000),
});
print(' Payment: ${payment.nativeValue}');

// === H256 ===
final hash = H256Type.create(
Uint8List.fromList(List.generate(32, (i) => i * 8))
);
final hashBytes = hash.nativeValue as Uint8List;
print(' First 8 bytes: ${hashBytes.take(8).toList()}');
print(' Length: ${hashBytes.length} bytes');

// === CodeMetadata ===
final metadata = CodeMetadataType.create(0x0502); // upgradeable + readable + payable
final metaVal = metadata as CodeMetadataValue;
print(' Upgradeable: ${metaVal.isUpgradeable}');
print(' Payable: ${metaVal.isPayable}');
print(' Metadata: ${metadata.nativeValue}');

// === Nothing ===
final nothing = NothingType.create();
print(' Value: ${nothing.nativeValue}'); // null
}

Common Patterns

Token Amount Formatting

// Format token amount with decimals
String formatAmount(BigInt amount, int decimals) {
final divisor = BigInt.from(10).pow(decimals);
final whole = amount ~/ divisor;
final fraction = (amount % divisor).toString().padLeft(decimals, '0');
return '$whole.$fraction';
}

// Usage
final amount = BigInt.parse('1500000000000000000'); // 1.5 EGLD
print(formatAmount(amount, 18)); // '1.500000000000000000'

Working with Token Payments

// Parse EsdtTokenPayment from query result
void parsePayment(StructValue payment) {
final tokenId = payment.getFieldValue('token_identifier')?.nativeValue;
final nonce = payment.getFieldValue('token_nonce')?.nativeValue as BigInt;
final amount = payment.getFieldValue('amount')?.nativeValue as BigInt;

if (nonce == BigInt.zero) {
print('Fungible: $tokenId, Amount: $amount');
} else {
print('NFT: $tokenId-${nonce.toRadixString(16)}, Amount: $amount');
}
}

Next Steps