From bb10d2813f3f6e8e83063f5d046d1ea61b183bdc Mon Sep 17 00:00:00 2001 From: Jaco Date: Wed, 17 Nov 2021 09:18:55 +0100 Subject: [PATCH] Expand runtime Call/Event matching (#4220) * Expand runtime Call/Event matching * Adjust * matching * CHANGELOG --- CHANGELOG.md | 2 + packages/api-derive/src/bundle.ts | 90 +++++++++++++++---- .../PortableRegistry/PortableRegistry.ts | 28 ++++-- 3 files changed, 96 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2972d0ef8..5358a43809 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ Contributed: Changes: +- Adjust runtime `*::{Call, Event}` matching for metadata v14 +- Adjust derive decoration with (optional) known methods - Align Option `.toJSON` output with Substrate input - Prepare pre-v13 types for optional injection diff --git a/packages/api-derive/src/bundle.ts b/packages/api-derive/src/bundle.ts index 1b0497dcce..9975e90960 100644 --- a/packages/api-derive/src/bundle.ts +++ b/packages/api-derive/src/bundle.ts @@ -30,6 +30,7 @@ export * from './type'; interface Avail { instances: string[]; + methods: string[]; withDetect?: boolean; } @@ -54,19 +55,61 @@ export type ExactDerive = DeriveAllSections; // Enable derive only if some of these modules are available const checks: Record = { - contracts: { instances: ['contracts'] }, - council: { instances: ['council'], withDetect: true }, - crowdloan: { instances: ['crowdloan'] }, - democracy: { instances: ['democracy'] }, - elections: { instances: ['phragmenElection', 'electionsPhragmen', 'elections', 'council'], withDetect: true }, - imOnline: { instances: ['imOnline'] }, - membership: { instances: ['membership'] }, - parachains: { instances: ['parachains', 'registrar'] }, - session: { instances: ['session'] }, - society: { instances: ['society'] }, - staking: { instances: ['staking'] }, - technicalCommittee: { instances: ['technicalCommittee'], withDetect: true }, - treasury: { instances: ['treasury'] } + contracts: { + instances: ['contracts'], + methods: [] + }, + council: { + instances: ['council'], + methods: [], + withDetect: true + }, + crowdloan: { + instances: ['crowdloan'], + methods: [] + }, + democracy: { + instances: ['democracy'], + methods: [] + }, + elections: { + instances: ['phragmenElection', 'electionsPhragmen', 'elections', 'council'], + methods: [], + withDetect: true + }, + imOnline: { + instances: ['imOnline'], + methods: [] + }, + membership: { + instances: ['membership'], + methods: [] + }, + parachains: { + instances: ['parachains', 'registrar'], + methods: [] + }, + session: { + instances: ['session'], + methods: [] + }, + society: { + instances: ['society'], + methods: [] + }, + staking: { + instances: ['staking'], + methods: ['erasRewardPoints'] + }, + technicalCommittee: { + instances: ['technicalCommittee'], + methods: [], + withDetect: true + }, + treasury: { + instances: ['treasury'], + methods: [] + } }; function getModuleInstances (api: ApiInterfaceRx, specName: string, moduleName: string): string[] { @@ -88,12 +131,27 @@ function injectFunctions (instanceId: string, api: ApiInterfaceRx, derives: Deri const filterInstances = (q: string) => getModuleInstances(api, specName, q).some(filterQueryKeys); + const filterMethods = (instances: string[]) => + (m: string) => + instances.some((q) => + queryKeys.includes(q) && + !!api.query[q][m] + ); + const isIncluded = (s: string) => ( !checks[s] || - checks[s].instances.some(filterQueryKeys) || ( - checks[s].withDetect && - checks[s].instances.some(filterInstances) + ( + checks[s].instances.some(filterQueryKeys) && + ( + !checks[s].methods.length || + checks[s].methods.every(filterMethods(checks[s].instances)) + ) + ) || + ( + checks[s].withDetect && + checks[s].instances.some(filterInstances) + ) ) ); diff --git a/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts b/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts index 2272ed2829..f1ad8f3acb 100644 --- a/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts +++ b/packages/types/src/metadata/PortableRegistry/PortableRegistry.ts @@ -26,9 +26,13 @@ const PRIMITIVE_ALIAS: Record = { // These are types where we have a specific decoding/encoding override + helpers const PATHS_ALIAS = splitNamespace([ - // match {node, polkadot, ...}_runtime - '*_runtime::Call', - '*_runtime::Event', + // These come in different forms + // - node_runtime::Call + // - polkadot_runtime::Call + // - node_template_runtime::Call + // - interbtc_runtime_parachain::Call + '*_runtime_*::Call', + '*_runtime_*::Event', // these have a specific encoding or logic (for pallets) 'pallet_democracy::vote::Vote', 'pallet_identity::types::Data', @@ -81,16 +85,24 @@ function matchParts (first: string[], second: (string | Text)[]): boolean { } if (a.includes('*') && a.includes('_') && b.includes('_')) { - const suba = a.split('_'); - const subb = b.split('_'); + let suba = a.split('_'); + let subb = b.split('_'); + // match initial *'s to multiples if we have a match for the other if (suba[0] === '*') { - // the first parts where the length is greater is always a match - while (suba.length < subb.length) { - subb.shift(); + const indexOf = subb.indexOf(suba[1]); + + if (indexOf !== -1) { + suba = suba.slice(1); + subb = subb.slice(indexOf); } } + // check for * matches at the end, adjust accordingly + if ((suba.length === 2) && (suba[1] === '*') && (suba[0] === subb[0])) { + return true; + } + return matchParts(suba, subb); }