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.
Understanding Storage Encoding
Section titled “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
Section titled “Querying and Decoding Storage”Complete Example
Section titled “Complete Example”Create a new file bin/demo.dart
with the following code:
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(''); }}
Running the Example
Section titled “Running the Example”dart run bin/demo.dart
Understanding the Output
Section titled “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 accountfree
: Available balancereserved
: Balance locked for specific purposesfrozen
: Balance that cannot be transferred
Key Concepts
Section titled “Key Concepts”Storage Keys
Section titled “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
Section titled “SCALE Codec”The SCALE codec is used throughout Polkadot for efficient data encoding:
// Decode any SCALE-encoded datafinal decoded = SomeTypeCodec().decode(ByteInput(encodedData));
// Encode data to SCALE formatfinal encoded = SomeTypeCodec().encode(myData);
Type Safety
Section titled “Type Safety”Generated types ensure you’re working with the correct data structures:
// Type-safe query with auto-completionfinal balance = await polkadot.query.system.account(accountId);// balance is strongly typed as AccountInfo
🎉 Congratulations! You’ve successfully queried and decoded blockchain data!