Event lazy create classes (#3685)
* Event lazy create classes * head fallback
This commit is contained in:
@@ -286,7 +286,7 @@ export abstract class Init<ApiType extends ApiTypes> extends Decorate<ApiType> {
|
||||
}
|
||||
|
||||
// get unique types & validate
|
||||
metadata.getUniqTypes(false);
|
||||
metadata.getUniqTypes(this._options.throwOnUnknown || false);
|
||||
|
||||
return [genesisHash, metadata];
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ export interface ApiOptions extends RegisteredTypes {
|
||||
* @description Throws an error when the initial connection fails (same as isReadyOrError)
|
||||
*/
|
||||
throwOnConnect?: boolean;
|
||||
/**
|
||||
* @description Throws an error when some types are unknown (useful with throwOnConnect)
|
||||
*/
|
||||
throwOnUnknown?: boolean;
|
||||
}
|
||||
|
||||
// A smaller interface of ApiRx, used in derive and in SubmittableExtrinsic
|
||||
|
||||
@@ -89,7 +89,7 @@ function extendHeadMeta (registry: Registry, { meta: { documentation, name, type
|
||||
// meta fallback only applies to actual entry values, create one for head
|
||||
(iterFn as IterFn).meta = registry.createType('StorageEntryMetadataLatest', {
|
||||
documentation,
|
||||
fallback: registry.createType('Bytes', registry.createType(outputType.toString() as 'Raw').toHex()),
|
||||
fallback: registry.createType('Bytes'),
|
||||
modifier: registry.createType('StorageEntryModifierLatest', 1), // required
|
||||
name,
|
||||
type: registry.createType('StorageEntryTypeLatest', registry.createType('Type', outputType), 0)
|
||||
|
||||
@@ -51,31 +51,32 @@ function injectErrors (_: Registry, metadata: Metadata, metadataErrors: Record<s
|
||||
|
||||
// create event classes from metadata
|
||||
function injectEvents (registry: Registry, metadata: Metadata, metadataEvents: Record<string, Constructor<GenericEventData>>): void {
|
||||
const modules = metadata.asLatest.modules;
|
||||
|
||||
// decorate the events
|
||||
modules
|
||||
metadata.asLatest.modules
|
||||
.filter(({ events }) => events.isSome)
|
||||
.forEach((section, _sectionIndex): void => {
|
||||
const sectionIndex = metadata.version >= 12 ? section.index.toNumber() : _sectionIndex;
|
||||
const sectionIndex = metadata.version >= 12
|
||||
? section.index.toNumber()
|
||||
: _sectionIndex;
|
||||
const sectionName = stringCamelCase(section.name);
|
||||
|
||||
section.events.unwrap().forEach((meta, methodIndex): void => {
|
||||
const methodName = meta.name.toString();
|
||||
const eventIndex = new Uint8Array([sectionIndex, methodIndex]);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-member-access
|
||||
const typeDef = meta.args.map((arg) => getTypeDef(arg));
|
||||
let Types: Constructor<Codec>[] = [];
|
||||
let Types: Constructor<Codec>[] | null = null;
|
||||
|
||||
try {
|
||||
Types = typeDef.map((typeDef) => getTypeClass(registry, typeDef));
|
||||
} catch (error) {
|
||||
l.error(error);
|
||||
}
|
||||
// Lazy create the actual type classes right at the point of use
|
||||
const getTypes = (): Constructor<Codec>[] => {
|
||||
if (!Types) {
|
||||
Types = typeDef.map((typeDef) => getTypeClass(registry, typeDef));
|
||||
}
|
||||
|
||||
metadataEvents[u8aToHex(eventIndex)] = class extends GenericEventData {
|
||||
return Types;
|
||||
};
|
||||
|
||||
metadataEvents[u8aToHex(new Uint8Array([sectionIndex, methodIndex]))] = class extends GenericEventData {
|
||||
constructor (registry: Registry, value: Uint8Array) {
|
||||
super(registry, value, Types, typeDef, meta, sectionName, methodName);
|
||||
super(registry, value, getTypes(), typeDef, meta, sectionName, methodName);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -10,6 +10,31 @@ import { Struct } from '../codec/Struct';
|
||||
import { Tuple } from '../codec/Tuple';
|
||||
import { Null } from '../primitive/Null';
|
||||
|
||||
interface Decoded {
|
||||
DataType: Constructor<Null> | Constructor<GenericEventData>;
|
||||
value?: {
|
||||
index: Uint8Array;
|
||||
data: Uint8Array;
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
function decodeEvent (registry: Registry, value?: Uint8Array): Decoded {
|
||||
if (!value || !value.length) {
|
||||
return { DataType: Null };
|
||||
}
|
||||
|
||||
const index = value.subarray(0, 2);
|
||||
|
||||
return {
|
||||
DataType: registry.findMetaEvent(index),
|
||||
value: {
|
||||
data: value.subarray(2),
|
||||
index
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @name GenericEventData
|
||||
* @description
|
||||
@@ -72,7 +97,7 @@ export class GenericEvent extends Struct implements IEvent<Codec[]> {
|
||||
// Currently we _only_ decode from Uint8Array, since we expect it to
|
||||
// be used via EventRecord
|
||||
constructor (registry: Registry, _value?: Uint8Array) {
|
||||
const { DataType, value } = GenericEvent.decodeEvent(registry, _value);
|
||||
const { DataType, value } = decodeEvent(registry, _value);
|
||||
|
||||
super(registry, {
|
||||
index: 'EventId',
|
||||
@@ -81,23 +106,6 @@ export class GenericEvent extends Struct implements IEvent<Codec[]> {
|
||||
}, value);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
public static decodeEvent (registry: Registry, value: Uint8Array = new Uint8Array()): { DataType: Constructor<Null> | Constructor<GenericEventData>; value?: { index: Uint8Array; data: Uint8Array } } {
|
||||
if (!value.length) {
|
||||
return { DataType: Null };
|
||||
}
|
||||
|
||||
const index = value.subarray(0, 2);
|
||||
|
||||
return {
|
||||
DataType: registry.findMetaEvent(index),
|
||||
value: {
|
||||
data: value.subarray(2),
|
||||
index
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @description The wrapped [[EventData]]
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user