Skip to content

Decoding Chain Data

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.

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

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

demo.dart
import 'package:convert/convert.dart';
import 'package:demo/generated/polkadot/polkadot.dart';
import 'package:polkadart/scale_codec.dart';
import 'package:demo/generated/polkadot/types/sp_core/crypto/account_id32.dart';
import 'package:polkadart/polkadart.dart' show Provider;
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('');
}
}
Terminal window
dart run bin/demo.dart

The output shows:

  1. Storage Keys: Long hexadecimal strings that identify storage locations
  2. Account IDs: 32-byte public keys extracted from the storage keys
  3. 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

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

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);

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!