Skip to main content

Code Generation

abidock_mvx includes a CLI to generate type-safe Dart code from ABI files.

Why Generate Code?

Manual ApproachGenerated Code
Type casting requiredType-safe methods
Error-prone string literalsCompile-time checks
Runtime errorsIDE autocomplete
Repetitive boilerplateClean, minimal code

Before (Manual)

// Manual: error-prone, requires type knowledge
final tokenIdValue = TokenIdentifierType.type.createValue(tokenId);
final result = await controller.query(
endpointName: 'getReserve',
arguments: [tokenIdValue],
);
final reserve = infer<BigInt>(result[0]);

After (Generated)

// Generated: type-safe, IDE-supported
final reserve = await pair.getReserve(tokenId);

Quick Start

First, install the CLI globally:

dart pub global activate abidock_mvx

Then generate code from your ABI:

# Generate from ABI (positional arguments)
abidock assets/pair.abi.json lib/generated/pair Pair

# With all features enabled
abidock assets/pair.abi.json lib/generated/pair Pair --full

# Interactive mode
abidock --interactive

Generated Structure

For an ABI file, the generator creates a modular directory structure:

lib/generated/pair/
├── pair.dart # Barrel export (import this)
├── abi.dart # ABI constant
├── controller.dart # Main controller class
├── models/ # Custom types (structs, enums)
│ ├── state.dart
│ └── esdt_token_payment.dart
├── queries/ # View endpoints (one file per endpoint)
│ ├── get_reserve.dart
│ └── get_reserves_and_total_supply.dart
├── calls/ # Mutable endpoints (one file per endpoint)
│ ├── add_liquidity.dart
│ └── swap_tokens_fixed_input.dart
├── events/ # Event streaming
│ ├── polling_events/
│ └── websocket_events/
└── transfers/ # Transfer helpers (with --transfers flag)

Example Usage

import 'package:abidock_mvx/abidock_mvx.dart';
import 'generated/pair/pair.dart';

void main() async {
final provider = GatewayNetworkProvider.devnet();
final account = await Account.fromMnemonic('...');
final accountInfo = await provider.getAccount(account.address);

// Create controller with contract address
final pair = PairController(
contractAddress: 'erd1qqq...pairaddress...',
networkProvider: provider,
);

// Type-safe queries - returns native Dart types
final reserve = await pair.getReserve('WEGLD-abcdef');
print('Reserve: $reserve');

// Multiple return values use Dart records
final (reserveA, reserveB, totalSupply) = await pair.getReservesAndTotalSupply();
print('Reserves: $reserveA / $reserveB, Total: $totalSupply');

// Type-safe transaction builders
final tx = await pair.addLiquidity(
account,
accountInfo.nonce,
BigInt.from(1000), // firstTokenAmountMin
BigInt.from(1000), // secondTokenAmountMin
tokenTransfers: [
TokenTransferValue.fromPrimitives(
tokenIdentifier: 'WEGLD-abcdef',
amount: BigInt.from(1000000),
),
TokenTransferValue.fromPrimitives(
tokenIdentifier: 'USDC-123456',
amount: BigInt.from(1000000),
),
],
);

final hash = await provider.sendTransaction(tx);
print('Transaction: $hash');
}

CLI Flags

FlagDescription
--loggerInclude ConsoleLogger in generated controller
--autogasGenerate automatic gas estimation via simulateGas
--transfersGenerate transfer service for EGLD/ESDT/NFT
--fullEnable ALL features (logger + autogas + transfers)

Features

  • All ABI types supported (primitives, structs, enums, options, lists)
  • Custom struct and enum generation with Dart classes
  • Query methods with proper return types
  • Transaction builders with auto gas estimation
  • ESDT/NFT token payment support
  • Multi-value returns using Dart records (BigInt, BigInt)
  • Optional/variadic argument handling
  • Event streaming (polling and WebSocket)
  • Unsigned transaction builders for batch signing
  • Relayer and guardian support built-in

Next Steps