diff --git a/CHANGELOG.md b/CHANGELOG.md index f42d038c0b..b74d4de935 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Upgrade priority: High. Metadata v12 is the next major version containing struct Changes: +- Ensure that upgrades override old registry types (non-specified in current) - Support for Metadata v12 with fixed indices - Cleanups for WebSocket class detection and creation - Ensure that ignored map params yield an error on `iterKey` diff --git a/packages/api/src/base/Init.ts b/packages/api/src/base/Init.ts index 3e7b3287a8..28ecaf57b0 100644 --- a/packages/api/src/base/Init.ts +++ b/packages/api/src/base/Init.ts @@ -2,11 +2,12 @@ // This software may be modified and distributed under the terms // of the Apache-2.0 license. See the LICENSE file for details. -import { SignedBlock, RuntimeVersion } from '@polkadot/types/interfaces'; +import { ChainProperties, SignedBlock, RuntimeVersion } from '@polkadot/types/interfaces'; import { Registry } from '@polkadot/types/types'; import { ApiBase, ApiOptions, ApiTypes, DecorateMethod } from '../types'; import { VersionedRegistry } from './types'; +import BN from 'bn.js'; import { Observable, Subscription, of } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; import { Metadata, Text, TypeRegistry } from '@polkadot/types'; @@ -68,6 +69,22 @@ export default abstract class Init extends Decorate extends Decorate extends Decorate extends Decorate { - // if (this._rpc) { - // if (!this._rpc[section as 'author']) { - // this._rpc[section as 'author'] = {} as DecoratedRpcSection; - // } - - // Object.entries(value).forEach(([name, method]): void => { - // if (this._rpc && !this._rpc[section as 'author'][name as 'hasKey']) { - // // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - // this._rpc[section as 'author'][name as 'hasKey'] = method; - // } - // }); - // } - // }); - } - private async _metaFromChain (optMetadata: Record): Promise { const [runtimeVersion, chain, chainProps] = await Promise.all([ this._rpcCore.state.getRuntimeVersion().toPromise(), @@ -256,14 +239,8 @@ export default abstract class Init extends Decorate(); + #classes = new Map(); - readonly #definitions = new Map(); + #definitions = new Map(); readonly #metadataCalls: Record = {}; @@ -103,32 +103,49 @@ export class TypeRegistry implements Registry { readonly #metadataEvents: Record> = {}; - readonly #unknownTypes = new Map(); + #unknownTypes = new Map(); #chainProperties?: ChainProperties; #hasher: (data: Uint8Array) => Uint8Array = blake2AsU8a; + readonly #knownDefaults: RegistryTypes; + + readonly #knownDefinitions: Record; + #knownTypes: RegisteredTypes = {}; #signedExtensions: string[] = defaultExtensions; constructor () { - // we only want to import these on creation, i.e. we want to avoid types - // weird side-effects from circular references. (Since registry is injected - // into types, this can be a real concern now) + // we only want to import these on creation, i.e. we want to avoid weird + // side-effects from circular references. (Since registry is injected + // into types, this can be a real concern now) // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const baseTypes: RegistryTypes = require('../index.types'); // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment const definitions: Record = require('../interfaces/definitions'); - // since these are classes, they are injected first - this.register({ Raw, ...baseTypes }); + this.#knownDefaults = { Raw, ...baseTypes }; + this.#knownDefinitions = definitions; - // since these are definitions, they would only get created when needed - Object.values(definitions).forEach(({ types }): void => + this.init(); + } + + public init (): this { + // start clean + this.#classes = new Map(); + this.#definitions = new Map(); + this.#unknownTypes = new Map(); + this.#knownTypes = {}; + + // register know, first classes then on-demand-created definitions + this.register(this.#knownDefaults); + Object.values(this.#knownDefinitions).forEach(({ types }): void => this.register(types) ); + + return this; } public get chainDecimals (): number { diff --git a/packages/types/src/types/registry.ts b/packages/types/src/types/registry.ts index 1cec5d3a24..637f11d5df 100644 --- a/packages/types/src/types/registry.ts +++ b/packages/types/src/types/registry.ts @@ -163,6 +163,7 @@ export interface Registry { hasDef (name: string): boolean; hasType (name: string): boolean; hash (data: Uint8Array): Uint8Array; + init (): Registry; register (type: Constructor | RegistryTypes): void; register (name: string, type: Constructor): void; register (arg1: string | Constructor | RegistryTypes, arg2?: Constructor): void;