Skip to content

Commit

Permalink
[Update] Refactor priority logic v2
Browse files Browse the repository at this point in the history
  • Loading branch information
tunghp2002 committed Dec 23, 2024
1 parent ccb80e4 commit 24788a4
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 120 deletions.
3 changes: 3 additions & 0 deletions packages/extension-base/src/background/KoniTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,9 @@ export interface MetadataItem {
types: Record<string, Record<string, string> | string>;
userExtensions?: ExtDef;
hexV15?: HexString;
ss58Format?: number;
tokenDecimals?: number;
tokenSymbol?: string;
}

export interface CrowdloanItem {
Expand Down
28 changes: 16 additions & 12 deletions packages/extension-base/src/koni/background/handlers/Extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ import { AnyJson, Registry, SignerPayloadJSON, SignerPayloadRaw } from '@polkado
import { assert, hexStripPrefix, hexToU8a, isAscii, isHex, u8aToHex } from '@polkadot/util';
import { decodeAddress, isEthereumAddress } from '@polkadot/util-crypto';

import { getSuitableRegistry, MetadataSource, MetadataWithSource } from '../utils';
import { getSuitableRegistry, RegistrySource, setupApiRegistry, setupDappRegistry, setupDatabaseRegistry } from '../utils';

export function isJsonPayload (value: SignerPayloadJSON | SignerPayloadRaw): value is SignerPayloadJSON {
return (value as SignerPayloadJSON).genesisHash !== undefined;
Expand Down Expand Up @@ -2546,20 +2546,24 @@ export default class KoniExtension {

if (isJsonPayload(payload)) {
const [, chainInfo] = this.#koniState.findNetworkKeyByGenesisHash(payload.genesisHash);
const [dbMetadata, dappMetadata] = await Promise.all([
{ metadata: await this.#koniState.chainService.getMetadataByHash(payload.genesisHash), source: MetadataSource.DB },
{ metadata: this.#koniState.knownMetadata.find((meta: MetadataDef) => meta.genesisHash === payload.genesisHash), source: MetadataSource.DAPP }
]);

const allMetadata: MetadataWithSource[] = [
{ metadata: dbMetadata.metadata, source: dbMetadata.source },
{ metadata: dappMetadata.metadata, source: dappMetadata.source }
].filter((item) => item.metadata);

if (allMetadata.length === 0) {
const allRegistry: RegistrySource[] = [
setupApiRegistry(chainInfo, this.#koniState),
setupDatabaseRegistry(
await this.#koniState.chainService.getMetadataByHash(payload.genesisHash) as MetadataItem,
chainInfo,
payload
),
setupDappRegistry(
this.#koniState.knownMetadata.find((meta: MetadataDef) => meta.genesisHash === payload.genesisHash) as MetadataDef,
payload
)
].filter((item): item is RegistrySource => item !== null && item.registry !== undefined);

if (allRegistry.length === 0) {
registry.setSignedExtensions(payload.signedExtensions);
} else {
registry = getSuitableRegistry(allMetadata, payload, chainInfo, this.#koniState);
registry = getSuitableRegistry(allRegistry, payload).metadata;
}
}

Expand Down
133 changes: 58 additions & 75 deletions packages/extension-base/src/koni/background/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,107 +12,90 @@ import { Registry, SignerPayloadJSON } from '@polkadot/types/types';

import KoniState from './handlers/State';

export enum MetadataSource {
API = 'api',
DB = 'db',
DAPP = 'dapp'
export interface RegistrySource{
registry: Registry,
specVersion: string | number,
}

export interface MetadataWithSource{
metadata: MetadataDef | MetadataItem | undefined;
source: MetadataSource;
}

export interface CachedChainProperties {
ss58Format: number;
tokenDecimals: number | undefined;
tokenSymbol: string | undefined;
}

const cachedChainProperties: Map<string, Promise<CachedChainProperties | null>> = new Map();

function getChainProperties (chainInfo: _ChainInfo, genesisHash: string): Promise<CachedChainProperties | null> {
const cachedPromise = cachedChainProperties.get(genesisHash);

if (cachedPromise) {
return cachedPromise;
}

const chainPropertiesPromise = new Promise<CachedChainProperties | null>((resolve) => {
const chainProperties: CachedChainProperties = {
ss58Format: chainInfo?.substrateInfo?.addressPrefix ?? 42,
tokenDecimals: chainInfo?.substrateInfo?.decimals,
tokenSymbol: chainInfo?.substrateInfo?.symbol
};

cachedChainProperties.set(genesisHash, Promise.resolve(chainProperties));
resolve(chainProperties);
});

cachedChainProperties.set(genesisHash, chainPropertiesPromise);

return chainPropertiesPromise;
}

export function getSuitableRegistry (metadatas: MetadataWithSource[], payload: SignerPayloadJSON, chainInfo: _ChainInfo | undefined, koniState: KoniState) {
const api = chainInfo ? koniState.getSubstrateApi(chainInfo.slug).api : undefined;
const apiSpecVersion = api?.runtimeVersion.specVersion.toString();
export function getSuitableRegistry (registries: RegistrySource[], payload: SignerPayloadJSON) {
const payloadSpecVersion = parseInt(payload.specVersion);
const extendedMetadatas = [{
metadata: { specVersion: apiSpecVersion },
source: MetadataSource.API
},
...metadatas
];

const sortedMetadatas = extendedMetadatas
.filter((meta): meta is MetadataWithSource => meta.metadata !== undefined)
.map((meta) => ({
meta: meta.metadata,
source: meta.source,
distance: Math.abs(Number(meta.metadata?.specVersion) - payloadSpecVersion),
isHigher: Number(meta.metadata?.specVersion) >= payloadSpecVersion
}))
const sortedRegistries = registries
.filter((registrySource): registrySource is RegistrySource => registrySource.registry !== undefined)
.map((registrySource) => {
const specVersion = Number(registrySource.specVersion);
const distance = Math.abs(specVersion - payloadSpecVersion);
const isHigher = specVersion >= payloadSpecVersion;

return {
registry: registrySource.registry,
specVersion,
distance,
isHigher
};
})
.sort((a, b) => {
if (a.distance !== b.distance) {
return a.distance - b.distance;
}

return Number(b.meta?.specVersion) - Number(a.meta?.specVersion);
return a.specVersion - b.specVersion;
});

const closestMetadata = sortedMetadatas[0];
let registry: Registry;
return {
metadata: sortedRegistries[0].registry
};
}

if (closestMetadata.source === MetadataSource.API) {
registry = api?.registry as unknown as TypeRegistry;
} else if (closestMetadata.source === MetadataSource.DB && chainInfo) {
registry = setupDatabaseRegistry(closestMetadata.meta as MetadataItem, chainInfo, payload);
} else {
registry = setupDappRegistry(closestMetadata.meta as MetadataDef, payload);
export function setupApiRegistry (chainInfo: _ChainInfo | undefined, koniState: KoniState): RegistrySource | null {
if (!chainInfo) {
return null;
}

return registry;
const api = koniState.getSubstrateApi(chainInfo.slug).api;
const apiSpecVersion = api?.runtimeVersion.specVersion.toString();
const registry = api?.registry as unknown as TypeRegistry;

return {
registry,
specVersion: apiSpecVersion
};
}

export function setupDatabaseRegistry (metadata: MetadataItem, chainInfo: _ChainInfo, payload: SignerPayloadJSON) {
export function setupDatabaseRegistry (metadata: MetadataItem, chainInfo: _ChainInfo | undefined, payload: SignerPayloadJSON): RegistrySource | null {
if (!metadata || !metadata.genesisHash || !chainInfo) {
return null;
}

console.log('Checking', metadata);
const registry = new TypeRegistry();
const _metadata = new Metadata(registry, metadata.hexValue);

const chainProperties = getChainProperties(chainInfo, payload.genesisHash);

registry.register(metadata.types);
registry.setChainProperties(registry.createType('ChainProperties', chainProperties) as unknown as ChainProperties);
registry.setChainProperties(registry.createType('ChainProperties', {
ss58Format: metadata.ss58Format,
tokenDecimals: metadata.tokenDecimals,
tokenSymbol: metadata.tokenSymbol
}) as unknown as ChainProperties);
registry.setMetadata(_metadata, payload.signedExtensions, metadata.userExtensions);

return registry;
return {
registry,
specVersion: metadata.specVersion
};
}

export function setupDappRegistry (metadata: MetadataDef, payload: SignerPayloadJSON) {
export function setupDappRegistry (metadata: MetadataDef, payload: SignerPayloadJSON): RegistrySource | null {
if (!metadata || !metadata.genesisHash) {
return null;
}

const expanded = metadataExpand(metadata, false);
const registry = expanded.registry;

registry.setSignedExtensions(payload.signedExtensions, expanded.definition.userExtensions);

return registry;
return {
registry,
specVersion: metadata.specVersion
};
}
74 changes: 41 additions & 33 deletions packages/extension-base/src/utils/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,51 @@ export const getShortMetadata = (blob: HexString, extraInfo: ExtraInfo, metadata
return u8aToHex(_merkleizeMetadata.getProofForExtrinsicPayload(blob));
};

const storeMetadataV15: Map<string, HexString | undefined> = new Map();
const getMetadataV15 = async (chain: string, api: ApiPromise, chainService?: ChainService): Promise<void> => {
try {
if (api.call.metadata.metadataAtVersion) {
const metadataV15 = await api.call.metadata.metadataAtVersion(15);

const getMetadataV15 = (api: ApiPromise) => {
const genesisHash = api.genesisHash.toHex();

api.call.metadata.metadataAtVersion(15)
.then((metadataV15) => {
if (!metadataV15.isEmpty) {
const hexValue = metadataV15.unwrap().toHex();

storeMetadataV15.set(genesisHash, hexValue);
} else {
storeMetadataV15.set(genesisHash, undefined);
if (chainService) {
const metadata = await chainService.getMetadata(chain);

if (metadata) {
await chainService.upsertMetadata(chain, { ...metadata, hexV15: hexValue });
}
}
}
})
.catch((err) => {
console.error('Error:', err);
storeMetadataV15.set(genesisHash, undefined);
});
}
} catch (err) {
console.error('Error:', err);
}
};

return storeMetadataV15.get(genesisHash);
const getMetadata = (chain: string, api: ApiPromise, currentSpecVersion: string, genesisHash: HexString, chainService?: ChainService) => {
const specName = api.runtimeVersion.specName.toString();

const systemChain = api.runtimeChain;
// const _metadata: Option<OpaqueMetadata> = await api.call.metadata.metadataAtVersion(15);
// const metadataHex = _metadata.isSome ? _metadata.unwrap().toHex().slice(2) : ''; // Need unwrap to create metadata object
const metadataHex = api.runtimeMetadata.toHex();
const registry = api.registry;

const updateMetadata = {
chain: chain,
genesisHash: genesisHash,
specName: specName,
specVersion: currentSpecVersion,
hexValue: metadataHex,
types: getSpecTypes(api.registry, systemChain, api.runtimeVersion.specName, api.runtimeVersion.specVersion) as unknown as Record<string, string>,
userExtensions: getSpecExtensions(api.registry, systemChain, api.runtimeVersion.specName),
ss58Format: registry.chainSS58,
tokenDecimals: registry.chainDecimals[0],
tokenSymbol: registry.chainTokens[0]
};

chainService?.upsertMetadata(chain, { ...updateMetadata }).catch(console.error);
};

export const cacheMetadata = (
Expand All @@ -57,7 +81,6 @@ export const cacheMetadata = (
// Update metadata to database with async methods
substrateApi.api.isReady.then(async (api) => {
const currentSpecVersion = api.runtimeVersion.specVersion.toString();
const specName = api.runtimeVersion.specName.toString();
const genesisHash = api.genesisHash.toHex();
const metadata = await chainService?.getMetadata(chain);

Expand All @@ -66,22 +89,7 @@ export const cacheMetadata = (
return;
}

const systemChain = api.runtimeChain;
// const _metadata: Option<OpaqueMetadata> = await api.call.metadata.metadataAtVersion(15);
// const metadataHex = _metadata.isSome ? _metadata.unwrap().toHex().slice(2) : ''; // Need unwrap to create metadata object
const metadataHex = api.runtimeMetadata.toHex();
const metadataV15 = getMetadataV15(api);

const updateMetadata = {
chain: chain,
genesisHash: genesisHash,
specName: specName,
specVersion: currentSpecVersion,
hexValue: metadataHex,
types: getSpecTypes(api.registry, systemChain, api.runtimeVersion.specName, api.runtimeVersion.specVersion) as unknown as Record<string, string>,
userExtensions: getSpecExtensions(api.registry, systemChain, api.runtimeVersion.specName)
};

chainService?.upsertMetadata(chain, { ...updateMetadata, hexV15: metadataV15 }).catch(console.error);
getMetadata(chain, api, currentSpecVersion, genesisHash, chainService);
await getMetadataV15(chain, api, chainService);
}).catch(console.error);
};

0 comments on commit 24788a4

Please sign in to comment.