Polkadart Logo
Getting Started

Decoding Chain Data

Learn how to query and decode blockchain data from storage into human-readable format

When working with blockchain data, all information is stored in an encoded format for efficiency. Polkadart provides powerful tools to decode this data into human-readable formats that your Dart applications can easily work with.

Understanding Storage Encoding

Blockchain storage uses SCALE (Simple Concatenated Aggregate Little-Endian) encoding. This includes:

  • Storage keys: Hashed identifiers for storage locations
  • Storage values: The actual encoded data
  • Account IDs: 32-byte public keys

Querying and Decoding Storage

Complete Example

Create a new file bin/demo.dart with the following code:

demo.dart

Future<void> main(List<String> arguments) async {
  final provider = Provider.fromUri(Uri.parse('wss://rpc.polkadot.io'));
  final polkadot = Polkadot(provider);

  // Step 1: Get the storage key prefix for accounts
  final accountMapPrefix = polkadot.query.system.accountMapPrefix();
  
  // Step 2: Query the first 10 account storage keys
  final keys = await polkadot.rpc.state.getKeysPaged(
    key: accountMapPrefix, 
    count: 10
  );

  print("First 10 account storage keys:");
  print(keys.map((key) => '0x${hex.encode(key)}').join('\n')));

  // Step 3: Decode account IDs from storage keys
  // Storage keys are composed of: [pallet_hash(16 bytes) + storage_item_hash(16 bytes) + account_id(32 bytes)]
  final accountIds = keys.map((key) => 
    const AccountId32Codec().decode(ByteInput(key.sublist(32)))
  );
  
  print("\nFirst 10 account public keys:");
  print(accountIds.map((account) => '0x${hex.encode(account)}').join('\n')));

  // Step 4: Query account information for each account
  final accountInfos = await Future.wait(
    accountIds.map((account) => polkadot.query.system.account(account))
  );

  // Step 5: Display decoded account information
  print("\nAccount Information:");
  for (final (index, accountInfo) in accountInfos.indexed) {
    print('Account ${index + 1}:');
    print('  Nonce: ${accountInfo.nonce}');
    print('  Free Balance: ${accountInfo.data.free}');
    print('  Reserved: ${accountInfo.data.reserved}');
    print('  Frozen: ${accountInfo.data.frozen}');
    print('');
  }
}

Running the Example

dart run bin/demo.dart

Understanding the Output

The output shows:

Storage Keys: Long hexadecimal strings that identify storage locations

Account IDs: 32-byte public keys extracted from the storage keys

Account Information: Decoded data including:

  • nonce: Number of transactions sent from this account
  • free: Available balance
  • reserved: Balance locked for specific purposes
  • frozen: Balance that cannot be transferred
The storage key structure is:
  • First 16 bytes: Pallet identifier hash
  • Next 16 bytes: Storage item identifier hash
  • Remaining bytes: The actual key data (account ID in this case)

Key Concepts

Storage Keys

Every piece of data on the blockchain has a unique storage key. Polkadart helps you:

  • Generate the correct storage keys
  • Query data using these keys
  • Decode the returned values

SCALE Codec

The SCALE codec is used throughout Polkadot for efficient data encoding:

// Decode any SCALE-encoded data
final decoded = SomeTypeCodec().decode(ByteInput(encodedData));

// Encode data to SCALE format
final encoded = SomeTypeCodec().encode(myData);

Type Safety

Generated types ensure you're working with the correct data structures:

// Type-safe query with auto-completion
final balance = await polkadot.query.system.account(accountId);
// balance is strongly typed as AccountInfo

🎉 Congratulations! You've successfully queried and decoded blockchain data!

Next Steps