Skip to content

Commit

Permalink
RuntimeV14 parser and adds V15 support (#487)
Browse files Browse the repository at this point in the history
* Implement Runtime V14 scale codec parser

* Fix generator

* dart format

* dart format && dart analyze

* Add metadata v15

* Some improvements

* Finishes

* Lint

* Changes

* fix

---------

Co-authored-by: Leonardo Custodio <[email protected]>
  • Loading branch information
Lohann and leonardocustodio authored Jan 18, 2025
1 parent f087b3a commit 46932af
Show file tree
Hide file tree
Showing 28 changed files with 3,363 additions and 1,080 deletions.
15 changes: 8 additions & 7 deletions examples/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,25 @@ environment:
# Add regular dependencies here.
dependencies:
convert: ^3.1.1
polkadart: ^0.4.6
polkadart_cli: ^0.4.2
polkadart_keyring: ^0.4.3
polkadart_scale_codec: ^1.2.0
ss58: ^1.1.2
substrate_bip39: ^0.4.0
substrate_metadata: ^1.2.0
polkadart: ^0.4.7
polkadart_keyring: ^0.4.4
polkadart_scale_codec: ^1.2.1
ss58: ^1.1.3
substrate_bip39: ^0.4.1
substrate_metadata: ^1.2.2

# Generated files depend on quiver
quiver: ^3.2.1

dev_dependencies:
polkadart_cli: ^0.4.3
lints: ^2.0.0
test: ^1.21.0

polkadart:
output_dir: lib/generated
chains:
kusama: wss://kusama-rpc.publicnode.com
polkadot: wss://rpc.ibp.network/polkadot
astar: wss://rpc.astar.network
westend: wss://westend-rpc.polkadot.io
Expand Down
22 changes: 18 additions & 4 deletions packages/polkadart/lib/apis/apis.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,24 @@ library apis;
import 'dart:typed_data' show Uint8List;
import 'dart:async' show Future, StreamSubscription;
import 'package:convert/convert.dart' show hex;
import 'package:polkadart/polkadart.dart';
import 'dart:typed_data';

import 'package:convert/convert.dart';
import 'package:polkadart/polkadart.dart'
show
Provider,
ExtrinsicStatus,
BlockHash,
KeyValue,
StorageKey,
StorageData,
StorageChangeSet,
ReadProof,
RuntimeVersion,
Events,
ChainType,
Health,
SyncState,
PeerInfo;
import 'package:substrate_metadata/substrate_metadata.dart'
show RuntimeMetadataPrefixed;

part './author.dart';
part './chain.dart';
Expand Down
34 changes: 20 additions & 14 deletions packages/polkadart/lib/apis/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ part of apis;
class StateApi<P extends Provider> {
final P _provider;

/// Metadata used to decode events.
RuntimeMetadataPrefixed? runtimeMetadata;

StateApi(this._provider);

late RuntimeMetadata latestRuntimeMetadata;
late RuntimeMetadataPrefixed latestRuntimeMetadata;

/// Call a contract at a block's state.
Future<Uint8List> call(String method, Uint8List bytes,
Expand Down Expand Up @@ -146,10 +149,12 @@ class StateApi<P extends Provider> {
}

/// Returns the runtime metadata
Future<RuntimeMetadata> getMetadata({BlockHash? at}) async {
Future<RuntimeMetadataPrefixed> getMetadata({BlockHash? at}) async {
final List<String> params = at != null ? ['0x${hex.encode(at)}'] : const [];
final response = await _provider.send('state_getMetadata', params);
return RuntimeMetadata.fromHex(response.result);
final metadataPrefixed = RuntimeMetadataPrefixed.fromHex(response.result);
runtimeMetadata ??= metadataPrefixed;
return metadataPrefixed;
}

/// Get the runtime version.
Expand All @@ -175,17 +180,18 @@ class StateApi<P extends Provider> {

Future<StreamSubscription<Events>> subscribeEvents(
BlockHash at, Function(Events) onData) async {
latestRuntimeMetadata = await getMetadata();

final subscription = await _provider.subscribe('state_subscribeStorage', [
['0x${hex.encode(at)}']
], onCancel: (subscription) async {
await _provider.send('state_unsubscribeStorage', [subscription]);
});

return subscription.stream.map((response) {
return Events.fromJson(response.result, latestRuntimeMetadata.chainInfo);
}).listen(onData);
throw UnimplementedError();
// latestRuntimeMetadata = await getMetadata();

// final subscription = await _provider.subscribe('state_subscribeStorage', [
// ['0x${hex.encode(at)}']
// ], onCancel: (subscription) async {
// await _provider.send('state_unsubscribeStorage', [subscription]);
// });

// return subscription.stream.map((response) {
// return Events.fromJson(response.result, runtimeMetadata.metadata);
// }).listen(onData);
}

/// Subscribes to storage changes for the provided keys
Expand Down
5 changes: 3 additions & 2 deletions packages/polkadart/lib/multisig/multisig_meta.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class MultiSigMeta {
final Uint8List genesisHash;
final int specVersion;
final int transactionVersion;
final RuntimeMetadata runtimeMetadata;
final RuntimeMetadataPrefixed runtimeMetadata;

const MultiSigMeta({
required this.blockNumber,
Expand All @@ -31,7 +31,8 @@ class MultiSigMeta {
final Uint8List genesisHash = await chainApi.getBlockHash(blockNumber: 0);

final StateApi stateApi = StateApi(provider);
final RuntimeMetadata runtimeMetadata = await stateApi.getMetadata();
final RuntimeMetadataPrefixed runtimeMetadata =
await stateApi.getMetadata();
final RuntimeVersion stateRuntimeVersion =
await stateApi.getRuntimeVersion();

Expand Down
2 changes: 2 additions & 0 deletions packages/polkadart_cli/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ build/
# Omit committing pubspec.lock for library packages; see
# https://dart.dev/guides/libraries/private-files#pubspeclock.
pubspec.lock

lib/generated
37 changes: 12 additions & 25 deletions packages/polkadart_cli/bin/generate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import 'package:path/path.dart' as path;
import 'package:recase/recase.dart' show ReCase;
import 'package:polkadart_cli/polkadart_cli.dart'
show ChainGenerator, PubspecConfig;
import 'package:polkadart_cli/src/typegen/runtime_metadata_v14.dart'
show RuntimeMetadataV14;
import 'package:substrate_metadata/substrate_metadata.dart'
show RuntimeMetadata;

class ChainProperties {
final RuntimeMetadataV14 metadata;
final RuntimeMetadata metadata;
final RuntimeVersion version;

ChainProperties(this.metadata, this.version);
Expand All @@ -19,35 +19,21 @@ class ChainProperties {
final provider = Provider.fromUri(uri);
final api = StateApi(provider);
final decodedMetadata = await api.getMetadata();
if (decodedMetadata.version != 14) {
await provider.disconnect();
throw Exception('Only metadata version 14 is supported');
}
final version = await api.getRuntimeVersion();

await provider.disconnect();

if (![14, 15].contains(decodedMetadata.metadata.runtimeMetadataVersion())) {
throw Exception('Only metadata versions 14 and 15 are supported');
}

return ChainProperties(
RuntimeMetadataV14.fromJson(decodedMetadata.toJson()['metadata']),
decodedMetadata.metadata as RuntimeMetadata,
version,
);
}
}

Future<ChainProperties> chainProperties(Uri url) async {
final provider = Provider.fromUri(url);
final api = StateApi(provider);
final decodedMetadata = await api.getMetadata();
if (decodedMetadata.version != 14) {
await provider.disconnect();
throw Exception('Only metadata version 14 is supported');
}
final version = await api.getRuntimeVersion();
await provider.disconnect();
return ChainProperties(
RuntimeMetadataV14.fromJson(decodedMetadata.toJson()['metadata']),
version,
);
}

void main(List<String> args) async {
final config = PubspecConfig.fromPubspecFile();
final parser = ArgParser();
Expand All @@ -70,7 +56,8 @@ void main(List<String> args) async {
final chain = entry.value;

// Get chain properties
final ChainProperties properties = await chainProperties(chain.metadataUri);
final ChainProperties properties =
await ChainProperties.fromURL(chain.metadataUri);

// Create chain directory
final chainDirectory =
Expand Down
9 changes: 5 additions & 4 deletions packages/polkadart_cli/lib/src/generator/chain.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import '../typegen/typegen.dart'
TypeDescriptor,
TypeBuilder,
GeneratedOutput;
import '../typegen/runtime_metadata_v14.dart' show RuntimeMetadataV14;
import 'package:substrate_metadata/substrate_metadata.dart'
show RuntimeMetadata;
import './pallet.dart' show PalletGenerator;
import './polkadart.dart' show PolkadartGenerator;

Expand All @@ -27,20 +28,20 @@ class ChainGenerator {
factory ChainGenerator.fromMetadata(
{required Directory basePath,
required chainName,
required RuntimeMetadataV14 metadata}) {
required RuntimeMetadata metadata}) {
final typesPath = path.join(basePath.path, 'types');
final palletsPath = path.join(basePath.path, 'pallets');

// Get type generators
final Map<int, TypeDescriptor> typeGenerators =
TypeDescriptor.fromTypes(metadata.registry, typesPath);
TypeDescriptor.fromTypes(metadata.types, typesPath);

// Get pallet generators
final List<PalletGenerator> palletGenerators = metadata.pallets
// Remove Empty Pallets
// TODO: remove this field once we support extrinsics
.where((pallet) =>
pallet.call != null ||
pallet.calls != null ||
pallet.storage != null ||
pallet.constants.isNotEmpty)
.map((pallet) => PalletGenerator.fromMetadata(
Expand Down
Loading

0 comments on commit 46932af

Please sign in to comment.