getChainInfo method
Implementation
ChainInfo getChainInfo() {
final rawMetadata = decodedMetadata.metadataJson;
//
// copy of the siTypes map
final siTypes = Map<int, String>.from(_metadataExpander.registeredSiType);
final callsCodec = <int, MapEntry<String, Codec>>{};
final eventsCodec = <int, MapEntry<String, Codec>>{};
//
// Temporariy referencing it to GenericCall until the real GenericCall is created below
// and
// then add it to the _resultingRegistry
{
final proxyCodec = ProxyCodec();
_resultingRegistry.addCodec('Call', proxyCodec);
_resultingRegistry.addCodec('RuntimeCall', proxyCodec);
// TODO: Check https://github.com/leonardocustodio/polkadart/pull/487
_resultingRegistry.addCodec('MinInflation', proxyCodec);
_resultingRegistry.addCodec('MaxInflation', proxyCodec);
_resultingRegistry.addCodec('Falloff', proxyCodec);
_resultingRegistry.addCodec('IdealStake', proxyCodec);
_resultingRegistry.addCodec('UseAuctionSlots', proxyCodec);
}
// Iterate over the pallets
//
// Set the types names for the storage, calls, events, constants
for (final pallet in rawMetadata['pallets']) {
// pallet name
final palletName = pallet['name'];
// pallet index
final palletIndex = pallet['index'];
//
// calls
final calls = <int, MapEntry<String, Map<String, dynamic>>>{};
if (pallet['calls'] != null) {
final variants =
rawMetadata['lookup']['types'][pallet['calls']['type']];
for (final variant in variants['type']['def']['Variant']['variants']) {
// fill args
final args = <Map<String, dynamic>>[];
// iterate over fields of each variant
for (final v in variant['fields']) {
args.add({
'name': v['name'],
'type': siTypes[v['type']],
});
}
calls[variant['index']] = MapEntry(variant['name'], {
'name': variant['name'],
'args': args,
'docs': variant['docs'],
});
}
}
//
// events
final events = <Map<String, dynamic>>[];
if (pallet['events'] != null) {
final variants =
rawMetadata['lookup']['types'][pallet['events']['type']];
for (final variant in variants['type']['def']['Variant']['variants']) {
// fill args
final args = <Map<String, dynamic>>[];
// iterate over fields of each variant
for (final v in variant['fields']) {
args.add({
'name': v['typeName'],
'type': siTypes[v['type']],
});
}
events.add({
'name': variant['name'],
'args': args,
'docs': variant['docs'],
});
}
}
{
//
// call lookup filling
final callEnumCodec = <int, MapEntry<String, Codec>>{};
for (final callEntry in calls.entries) {
final int callIndex = callEntry.key;
final MapEntry<String, Map<String, dynamic>> callValue =
callEntry.value;
final List<Map<String, dynamic>> callArgs =
(callValue.value['args'] as List<dynamic>)
.cast<Map<String, dynamic>>();
final Map<String, Codec> codecs = <String, Codec>{};
final List<Codec> codecList = <Codec>[];
late Codec argsCodec;
for (final arg in callArgs) {
final argName = arg['name'];
final typeName = arg['type'];
final codec = _resultingRegistry.parseSpecificCodec(
_metadataExpander.customCodecRegister, typeName);
codecList.add(codec);
codecs[argName] = codec;
}
if (codecs.length != callArgs.length) {
argsCodec = TupleCodec(codecList);
} else {
argsCodec = CompositeCodec(codecs);
}
callEnumCodec[callIndex] = MapEntry(callValue.key, argsCodec);
}
callsCodec[palletIndex] =
MapEntry(palletName, ComplexEnumCodec.sparse(callEnumCodec));
}
{
//
// event lookup filling
final eventEnumCodec = <int, MapEntry<String, Codec>>{};
for (var eventIndex = 0; eventIndex < events.length; eventIndex++) {
final event = events[eventIndex];
final List<Map<String, dynamic>> eventArgs =
(event['args'] as List<dynamic>).cast<Map<String, dynamic>>();
final Map<String, Codec> codecs = <String, Codec>{};
final List<Codec> codecsList = <Codec>[];
late Codec argsCodec;
for (final arg in eventArgs) {
final argName = arg['name'];
final typeName = arg['type'];
final codec = _resultingRegistry.parseSpecificCodec(
_metadataExpander.customCodecRegister, typeName);
codecsList.add(codec);
codecs[argName] = codec;
}
if (eventArgs.length != codecs.length) {
argsCodec = TupleCodec(codecsList);
} else {
argsCodec = CompositeCodec(codecs);
}
eventEnumCodec[eventIndex] = MapEntry(event['name'], argsCodec);
}
eventsCodec[palletIndex] =
MapEntry(palletName, ComplexEnumCodec.sparse(eventEnumCodec));
}
}
//
// Register the Generic Call
{
// replace the proxy of GenericCall with the real GenericCall
final proxyCodec = _resultingRegistry.getCodec('Call')! as ProxyCodec;
proxyCodec.codec = ComplexEnumCodec.sparse(callsCodec);
}
//
// Register the Generic Event
_resultingRegistry.addCodec(
'GenericEvent', ComplexEnumCodec.sparse(eventsCodec));
{
//
// Create the Event Codecs
// Sample Registry Map for the Event Definitions
final eventType = <String, dynamic>{
'Phase': {
'_enum': {
'ApplyExtrinsic': 'u32',
'Finalization': 'Null',
'Initialization': 'Null',
}
},
'EventRecord': {
'phase': 'Phase',
'event':
'GenericEvent', // GenericEvent is already registered in line: 244
'topics': 'Vec<Str>'
},
'EventCodec': 'Vec<EventRecord>',
};
// Parses the EventCodec from the above eventTye
_resultingRegistry.parseSpecificCodec(eventType, 'EventCodec');
}
{
//
// Configure the Extrinsics Signature Codec.
_resultingRegistry.addCodec('Era', EraExtrinsic.codec);
// integrating Code for ExtrinsicSignature
final extrinsicTypeId = rawMetadata['extrinsic']['type'];
final extrinsicDef = rawMetadata['lookup']['types'][extrinsicTypeId];
final extrinsicSignature = <String, Codec>{};
for (final params in extrinsicDef['type']['params']) {
final name = params['name'].toString().toLowerCase();
switch (name) {
case 'extra':
case 'call':
break;
default:
final siTypeName = siTypes[params['type']]!;
final codec = _resultingRegistry.parseSpecificCodec(
_metadataExpander.customCodecRegister, siTypeName);
extrinsicSignature[name] = codec;
}
}
// SignedExtensions Parsing
{
final signedExtensionsCompositeCodec = <String, Codec>{};
// Set the extrinsic version which would be helpful further in extrinsic and signing payload.
_resultingRegistry.extrinsicVersion =
rawMetadata['extrinsic']['version']!;
// clear the signedExtensions in the registry
_resultingRegistry.signedExtensions.clear();
for (final signedExtensions in rawMetadata['extrinsic']
['signedExtensions']) {
final type = siTypes[signedExtensions['type']];
final additionalSignedType =
siTypes[signedExtensions['additionalSigned']];
final identifier = signedExtensions['identifier'].toString();
// put a NullCodec which does nothing
_resultingRegistry.signedExtensions[identifier] = NullCodec.codec;
// put a NullCodec which does nothing
_resultingRegistry.additionalSignedExtensions[identifier] =
NullCodec.codec;
if (type == null || type.toLowerCase() == 'null') {
continue;
}
final typeCodec = _resultingRegistry.parseSpecificCodec(
_metadataExpander.customCodecRegister, type);
// overwrite the codec here.
_resultingRegistry.signedExtensions[identifier] = typeCodec;
if (additionalSignedType != null ||
additionalSignedType?.toLowerCase() != 'null') {
final additionalSignedTypeCodec =
_resultingRegistry.parseSpecificCodec(
_metadataExpander.customCodecRegister,
additionalSignedType!);
// overwrite the additional signed codec here.
_resultingRegistry.additionalSignedExtensions[identifier] =
additionalSignedTypeCodec;
}
String newIdentifier = identifier.replaceAll('Check', '');
switch (newIdentifier) {
case 'Mortality':
signedExtensionsCompositeCodec['era'] =
_resultingRegistry.parseSpecificCodec(
_metadataExpander.customCodecRegister, 'Era');
continue;
case 'ChargeTransactionPayment':
newIdentifier = 'tip';
break;
default:
}
signedExtensionsCompositeCodec[newIdentifier.snakeCase()] = typeCodec;
}
final extrinsicCodec = CompositeCodec(
{
...extrinsicSignature,
'signedExtensions': CompositeCodec(signedExtensionsCompositeCodec),
},
);
_resultingRegistry.addCodec('ExtrinsicSignatureCodec', extrinsicCodec);
}
}
return ChainInfo(
scaleCodec: ScaleCodec(_resultingRegistry),
version: decodedMetadata.version,
constants: _constants(),
);
}