mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-04-22 13:37:58 +00:00
feat: initial Pezkuwi Apps rebrand from polkadot-apps
Rebranded terminology: - Polkadot → Pezkuwi - Kusama → Dicle - Westend → Zagros - Rococo → PezkuwiChain - Substrate → Bizinikiwi - parachain → teyrchain Custom logos with Kurdistan brand colors (#e6007a → #86e62a): - bizinikiwi-hexagon.svg - sora-bizinikiwi.svg - hezscanner.svg - heztreasury.svg - pezkuwiscan.svg - pezkuwistats.svg - pezkuwiassembly.svg - pezkuwiholic.svg
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-settings authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@pezkuwi/api';
|
||||
import type { InjectedExtension, InjectedMetadataKnown, MetadataDef } from '@pezkuwi/extension-inject/types';
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import store from 'store';
|
||||
|
||||
import { createNamedHook, useApi } from '@pezkuwi/react-hooks';
|
||||
|
||||
interface ExtensionKnown {
|
||||
extension: InjectedExtension;
|
||||
known: InjectedMetadataKnown[];
|
||||
update: (def: MetadataDef) => Promise<boolean>;
|
||||
}
|
||||
|
||||
interface ExtensionInfo extends ExtensionKnown {
|
||||
current: InjectedMetadataKnown | null;
|
||||
}
|
||||
|
||||
interface Extensions {
|
||||
count: number;
|
||||
extensions: ExtensionInfo[];
|
||||
}
|
||||
|
||||
interface ExtensionProperties {
|
||||
extensionVersion: string;
|
||||
tokenDecimals: number;
|
||||
tokenSymbol: string;
|
||||
ss58Format?: number;
|
||||
}
|
||||
|
||||
type SavedProperties = Record<string, ExtensionProperties>;
|
||||
|
||||
type TriggerFn = (counter: number) => void;
|
||||
|
||||
let triggerCount = 0;
|
||||
const triggers = new Map<string, TriggerFn>();
|
||||
|
||||
function triggerAll (): void {
|
||||
[...triggers.values()].forEach((trigger) => trigger(Date.now()));
|
||||
}
|
||||
|
||||
// save the properties for a specific extension
|
||||
function saveProperties (api: ApiPromise, { name, version }: InjectedExtension): void {
|
||||
const storeKey = `properties:${api.genesisHash.toHex()}`;
|
||||
const allProperties = store.get(storeKey, {}) as SavedProperties;
|
||||
|
||||
allProperties[name] = {
|
||||
extensionVersion: version,
|
||||
ss58Format: api.registry.chainSS58,
|
||||
tokenDecimals: api.registry.chainDecimals[0],
|
||||
tokenSymbol: api.registry.chainTokens[0]
|
||||
};
|
||||
|
||||
store.set(storeKey, allProperties);
|
||||
}
|
||||
|
||||
// determines if the extension has current properties
|
||||
function hasCurrentProperties (api: ApiPromise, { extension }: ExtensionKnown): boolean {
|
||||
const allProperties = store.get(`properties:${api.genesisHash.toHex()}`, {}) as SavedProperties;
|
||||
|
||||
// when we don't have properties yet, assume nothing has changed and store
|
||||
if (!allProperties[extension.name]) {
|
||||
saveProperties(api, extension);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const { ss58Format, tokenDecimals, tokenSymbol } = allProperties[extension.name];
|
||||
|
||||
return ss58Format === api.registry.chainSS58 &&
|
||||
tokenDecimals === api.registry.chainDecimals[0] &&
|
||||
tokenSymbol === api.registry.chainTokens[0];
|
||||
}
|
||||
|
||||
// filter extensions based on the properties we have available
|
||||
function filterAll (api: ApiPromise, all: ExtensionKnown[]): Extensions {
|
||||
const extensions = all
|
||||
.map((info): ExtensionInfo | null => {
|
||||
const current = info.known.find(({ genesisHash }) => api.genesisHash.eq(genesisHash)) || null;
|
||||
|
||||
// if we cannot find it as known, or either the specVersion or properties mismatches, mark it as upgradable
|
||||
return !current || api.runtimeVersion.specVersion.gtn(current.specVersion) || !hasCurrentProperties(api, info)
|
||||
? { ...info, current }
|
||||
: null;
|
||||
})
|
||||
.filter((info): info is ExtensionInfo => !!info);
|
||||
|
||||
return {
|
||||
count: extensions.length,
|
||||
extensions
|
||||
};
|
||||
}
|
||||
|
||||
async function getExtensionInfo (api: ApiPromise, extension: InjectedExtension): Promise<ExtensionKnown | null> {
|
||||
if (!extension.metadata) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const metadata = extension.metadata;
|
||||
const known = await metadata.get();
|
||||
|
||||
return {
|
||||
extension,
|
||||
known,
|
||||
update: async (def: MetadataDef): Promise<boolean> => {
|
||||
let isOk = false;
|
||||
|
||||
try {
|
||||
isOk = await metadata.provide(def);
|
||||
|
||||
if (isOk) {
|
||||
saveProperties(api, extension);
|
||||
triggerAll();
|
||||
}
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return isOk;
|
||||
}
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getKnown (api: ApiPromise, extensions: InjectedExtension[], _: number): Promise<ExtensionKnown[]> {
|
||||
const all = await Promise.all(
|
||||
extensions.map((extension) => getExtensionInfo(api, extension))
|
||||
);
|
||||
|
||||
return all.filter((info): info is ExtensionKnown => !!info);
|
||||
}
|
||||
|
||||
const EMPTY_STATE = { count: 0, extensions: [] };
|
||||
|
||||
function useExtensionsImpl (): Extensions {
|
||||
const { api, extensions, isApiReady, isDevelopment } = useApi();
|
||||
const [all, setAll] = useState<ExtensionKnown[] | undefined>();
|
||||
const [trigger, setTrigger] = useState(0);
|
||||
|
||||
useEffect((): () => void => {
|
||||
const myId = `${++triggerCount}-${Date.now()}`;
|
||||
|
||||
triggers.set(myId, setTrigger);
|
||||
|
||||
return (): void => {
|
||||
triggers.delete(myId);
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect((): void => {
|
||||
extensions && getKnown(api, extensions, trigger)
|
||||
.then(setAll)
|
||||
.catch(console.error);
|
||||
}, [api, extensions, trigger]);
|
||||
|
||||
return useMemo(
|
||||
() => isDevelopment || !isApiReady || !all
|
||||
? EMPTY_STATE
|
||||
: filterAll(api, all),
|
||||
[all, api, isApiReady, isDevelopment]
|
||||
);
|
||||
}
|
||||
|
||||
export default createNamedHook('useExtensions', useExtensionsImpl);
|
||||
Reference in New Issue
Block a user