mirror of
https://github.com/pezkuwichain/pezkuwi-sdk-ui.git
synced 2026-07-12 22:45:45 +00:00
Initial commit: Pezkuwi SDK UI
Comprehensive web interface for interacting with Pezkuwi blockchain. Features: - Blockchain explorer - Wallet management - Staking interface - Governance participation - Developer tools Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
// Copyright 2017-2026 @pezkuwi/react-hooks authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@pezkuwi/api';
|
||||
import type { ChainInformation, CoretimeInformation, CoreWorkload, CoreWorkloadInfo, LegacyLease, PotentialRenewal, Reservation } from './types.js';
|
||||
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { createNamedHook, useApi, useBrokerConfig, useBrokerLeases, useBrokerReservations, useBrokerSalesInfo, useBrokerStatus, useCoreDescriptor, useRegions, useWorkloadInfos, useWorkplanInfos } from '@pezkuwi/react-hooks';
|
||||
import { BN, BN_ZERO } from '@pezkuwi/util';
|
||||
|
||||
import { ChainRenewalStatus, CoreTimeTypes } from './constants.js';
|
||||
import { useBrokerPotentialRenewals } from './useBrokerPotentialRenewals.js';
|
||||
import { useCoretimeConsts } from './useCoretimeConsts.js';
|
||||
|
||||
const getOccupancyType = (lease: LegacyLease | undefined, reservation: Reservation | undefined, isPool: boolean): CoreTimeTypes => {
|
||||
if (isPool) {
|
||||
return CoreTimeTypes['On Demand'];
|
||||
}
|
||||
|
||||
return reservation ? CoreTimeTypes.Reservation : lease ? CoreTimeTypes.Lease : CoreTimeTypes['Bulk Coretime'];
|
||||
};
|
||||
|
||||
function useCoretimeInformationImpl (api: ApiPromise, ready: boolean): CoretimeInformation | undefined {
|
||||
const { apiCoretime, isApiReady } = useApi();
|
||||
|
||||
const [workloadData, setWorkloadData] = useState<CoreWorkload[]>([]);
|
||||
const [taskIds, setTaskIds] = useState<number[]>([]);
|
||||
const [blocksPerTimesliceCoretimeChain, setBlocksPerTimesliceCoretimeChain] = useState<BN | undefined>();
|
||||
|
||||
/** coretime API calls */
|
||||
const status = useBrokerStatus(apiCoretime, isApiReady);
|
||||
const leases = useBrokerLeases(apiCoretime, isApiReady);
|
||||
const reservations = useBrokerReservations(apiCoretime, isApiReady);
|
||||
const salesInfo = useBrokerSalesInfo(apiCoretime, isApiReady);
|
||||
const workloads = useWorkloadInfos(apiCoretime, isApiReady);
|
||||
const workplans = useWorkplanInfos(apiCoretime, isApiReady);
|
||||
const config = useBrokerConfig(apiCoretime, isApiReady);
|
||||
const potentialRenewals = useBrokerPotentialRenewals(apiCoretime, isApiReady);
|
||||
const region = useRegions(apiCoretime);
|
||||
const coretimeConstants = useCoretimeConsts();
|
||||
|
||||
/** Coretime constants */
|
||||
useEffect(() => {
|
||||
if (!coretimeConstants?.coretime.blocksPerTimeslice) {
|
||||
return;
|
||||
}
|
||||
|
||||
setBlocksPerTimesliceCoretimeChain(new BN(coretimeConstants.coretime.blocksPerTimeslice));
|
||||
}, [coretimeConstants]);
|
||||
/** *******************/
|
||||
|
||||
const coreInfos = useCoreDescriptor(api, ready);
|
||||
const paraIds = useMemo(() => coreInfos && [...new Set(coreInfos?.map((a) => a.info.currentWork.assignments.map((ass) => ass.task)).flat().filter((id) => id !== 'Pool'))], [coreInfos]);
|
||||
|
||||
const isInterludePhase = useMemo(() => {
|
||||
if (!salesInfo || !config || !status || !blocksPerTimesliceCoretimeChain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const currentRegionStart = new BN(salesInfo?.regionBegin).sub(new BN(config.regionLength));
|
||||
const interludeLengthTs = blocksPerTimesliceCoretimeChain.gt(BN_ZERO) ? new BN(config?.interludeLength).div(blocksPerTimesliceCoretimeChain) : BN_ZERO;
|
||||
const interludeEndTs = currentRegionStart.add(interludeLengthTs);
|
||||
|
||||
return interludeEndTs.gte(new BN(status?.lastCommittedTimeslice));
|
||||
}, [status, salesInfo, config, blocksPerTimesliceCoretimeChain]);
|
||||
|
||||
const potentialRenewalsCurrentRegion = useMemo(() => {
|
||||
if (!isInterludePhase || !config || !salesInfo) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// when - The point in time that the renewable workload on core ends and a fresh renewal may begin.
|
||||
return potentialRenewals?.filter((renewal: PotentialRenewal) => renewal.when.toString() === salesInfo?.regionBegin.toString());
|
||||
}, [potentialRenewals, salesInfo, config, isInterludePhase]);
|
||||
|
||||
const [state, setState] = useState<CoretimeInformation | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
if (paraIds?.length && !taskIds.length) {
|
||||
const simpleIds = paraIds.map((p) => Number(p));
|
||||
const renewalIds = potentialRenewals?.map((r) => Number(r.task));
|
||||
|
||||
if (renewalIds) {
|
||||
const numbers = [...new Set(simpleIds.concat(renewalIds))];
|
||||
|
||||
if (numbers?.length > simpleIds.length) {
|
||||
setTaskIds(numbers.sort((a, b) => a - b));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setTaskIds(simpleIds);
|
||||
}
|
||||
}, [potentialRenewals, paraIds, taskIds]);
|
||||
|
||||
useEffect(() => {
|
||||
if (workloads?.length) {
|
||||
setWorkloadData(workloads);
|
||||
}
|
||||
|
||||
if (!!coreInfos?.length && !workloads?.length) {
|
||||
const parsedCoreInfos = coreInfos?.map((coreInfo) => ({
|
||||
core: -1,
|
||||
info: coreInfo.info.currentWork.assignments.map((assignment) => (
|
||||
{
|
||||
isPool: assignment.isPool,
|
||||
isTask: assignment.isTask,
|
||||
mask: [],
|
||||
maskBits: 0,
|
||||
task: assignment.task
|
||||
}
|
||||
) as CoreWorkloadInfo)
|
||||
}));
|
||||
|
||||
setWorkloadData(parsedCoreInfos as unknown as CoreWorkload[]);
|
||||
}
|
||||
}, [workloads, coreInfos]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (!workloadData?.length || !reservations?.length || !coretimeConstants) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chainInfo: Record<string, ChainInformation> = {};
|
||||
|
||||
taskIds?.forEach((id) => {
|
||||
const taskId = id.toString();
|
||||
const lease = leases?.length ? leases?.find((lease) => lease.task === taskId) : undefined;
|
||||
const reservation = reservations?.find((reservation) => reservation.task === taskId);
|
||||
const workloads = workloadData?.filter((one) => one.info.task === taskId);
|
||||
|
||||
const workTaskInfo = workloads.map((workload) => {
|
||||
// teyrchain can be renewed on a different core
|
||||
const workplan = workplans?.filter((workplan) => workplan.info.task.toString() === taskId);
|
||||
const type = getOccupancyType(lease, reservation, workload?.info.isPool ?? false);
|
||||
|
||||
const potentialRenewal = potentialRenewalsCurrentRegion?.find((renewal) => renewal.task.toString() === taskId);
|
||||
|
||||
const chainRenewedCore = type === CoreTimeTypes['Bulk Coretime'] && !!workplan?.length;
|
||||
|
||||
let renewalStatus = ChainRenewalStatus.None;
|
||||
let renewalStatusMessage = '';
|
||||
|
||||
if (potentialRenewal) {
|
||||
renewalStatus = ChainRenewalStatus.Eligible;
|
||||
}
|
||||
|
||||
if (chainRenewedCore) {
|
||||
renewalStatus = ChainRenewalStatus.Renewed;
|
||||
renewalStatusMessage = `Next cycle on core ${workplan[0].core}`;
|
||||
}
|
||||
|
||||
const chainRegionEnd = (renewalStatus === ChainRenewalStatus.Renewed ? salesInfo?.regionEnd : salesInfo?.regionBegin);
|
||||
const targetTimeslice = lease?.until || chainRegionEnd;
|
||||
|
||||
const lastBlock = targetTimeslice ? targetTimeslice * coretimeConstants?.relay.blocksPerTimeslice : 0;
|
||||
|
||||
return {
|
||||
lastBlock,
|
||||
renewal: potentialRenewal,
|
||||
renewalStatus,
|
||||
renewalStatusMessage,
|
||||
type,
|
||||
workload,
|
||||
workplan
|
||||
};
|
||||
});
|
||||
|
||||
chainInfo[id.toString()] = {
|
||||
id,
|
||||
lease,
|
||||
reservation,
|
||||
workTaskInfo
|
||||
};
|
||||
});
|
||||
|
||||
if (chainInfo && config && region && salesInfo && status && coretimeConstants) {
|
||||
setState({
|
||||
chainInfo,
|
||||
config,
|
||||
constants: coretimeConstants,
|
||||
region,
|
||||
salesInfo,
|
||||
status,
|
||||
taskIds
|
||||
});
|
||||
}
|
||||
}, [
|
||||
config,
|
||||
coretimeConstants,
|
||||
taskIds,
|
||||
workloadData,
|
||||
potentialRenewalsCurrentRegion,
|
||||
salesInfo,
|
||||
leases,
|
||||
reservations,
|
||||
region,
|
||||
status,
|
||||
workplans
|
||||
]);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
export const useCoretimeInformation = createNamedHook('useCoretimeInformation', useCoretimeInformationImpl);
|
||||
Reference in New Issue
Block a user