From b1979f4b76319216db0114a3fc1bbce07ee0c07d Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed Date: Wed, 22 May 2024 04:07:15 +0200 Subject: [PATCH 1/9] added new para id --- .../(App)/bulkcore1/CoreUtilisation.tsx | 2 +- .../[network]/(App)/bulkcore1/TimeSection.tsx | 2 +- src/app/[network]/(App)/paraId/page.tsx | 29 +++- .../registrar/RegisterParaIDModal.tsx | 78 ++++++++++ src/config/network.ts | 10 +- src/hooks/parachainUtils.ts | 146 ++++++++++++++++++ src/hooks/useParachainInfo.tsx | 77 +++++++++ src/utils/helperFunc.ts | 9 ++ 8 files changed, 342 insertions(+), 11 deletions(-) create mode 100644 src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx create mode 100644 src/hooks/parachainUtils.ts create mode 100644 src/hooks/useParachainInfo.tsx diff --git a/src/app/[network]/(App)/bulkcore1/CoreUtilisation.tsx b/src/app/[network]/(App)/bulkcore1/CoreUtilisation.tsx index 6645b53d..2c998c6b 100644 --- a/src/app/[network]/(App)/bulkcore1/CoreUtilisation.tsx +++ b/src/app/[network]/(App)/bulkcore1/CoreUtilisation.tsx @@ -17,7 +17,7 @@ type DataSetKey = 'priceOnePeriod' | 'price' | 'cores' | 'pastAuctions' // Add m const CoreUtilisation: React.FC = () => { const pathname = usePathname() const network = getChainFromPath(pathname) - const decimalPoints = network_list[network].decimalPoints + const decimalPoints = network_list[network].tokenDecimals const [activeDataSet, setActiveDataSet] = useState('priceOnePeriod') // Change to string to accommodate multiple datasets const client = useMemo(() => getClient(), []) diff --git a/src/app/[network]/(App)/bulkcore1/TimeSection.tsx b/src/app/[network]/(App)/bulkcore1/TimeSection.tsx index 0fb5831c..886ff551 100644 --- a/src/app/[network]/(App)/bulkcore1/TimeSection.tsx +++ b/src/app/[network]/(App)/bulkcore1/TimeSection.tsx @@ -32,7 +32,7 @@ export default function BrokerSaleInfo() { const configuration = network_list[network].configuration const brokerConstants = network_list[network].constants const tokenSymbol = network_list[network].tokenSymbol - const decimalPoints = network_list[network].decimalPoints + const decimalPoints = network_list[network].tokenDecimals const currentSaleRegion = useSaleRegion(network, client) diff --git a/src/app/[network]/(App)/paraId/page.tsx b/src/app/[network]/(App)/paraId/page.tsx index 847b11d7..0d279086 100644 --- a/src/app/[network]/(App)/paraId/page.tsx +++ b/src/app/[network]/(App)/paraId/page.tsx @@ -1,17 +1,32 @@ 'use client' -import { useInkathon } from '@poppyseed/lastic-sdk' -import SubTitle from '../samesections/SubTitle' +import RegisterParaIDModal from '@/components/broker/extrinsics/registrar/RegisterParaIDModal' +import PrimaryButton from '@/components/button/PrimaryButton' +import { useParachainInfo } from '@/hooks/useParachainInfo' +import { getChainFromPath } from '@/utils/common/chainPath' +import { usePathname } from 'next/navigation' +import { useState } from 'react' import ParaIdFetch from './ParaIdFetch' import ParaIdRelay from './ParaIdRelay' import ParachainsSubscanInfo from './ParachainsSubscanInfo' const InstaCore = () => { - const { activeRelayChain } = useInkathon() + const pathname = usePathname() + const network = getChainFromPath(pathname) + const [isParaRegisterOpen, setIsParaRegisterOpen] = useState(false) + + const { nextParaId, reservationCost } = useParachainInfo() return ( <> - {' '} +
+
+

+ Para Id Execution on {network} +

+ setIsParaRegisterOpen(true)} /> +
+
@@ -19,6 +34,12 @@ const InstaCore = () => {
+ setIsParaRegisterOpen(false)} + /> ) } diff --git a/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx b/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx new file mode 100644 index 00000000..1b02d7aa --- /dev/null +++ b/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx @@ -0,0 +1,78 @@ +import PrimaryButton from '@/components/button/PrimaryButton' +import Modal from '@/components/modal/Modal' +import { formatPrice } from '@/utils' +import { getChainFromPath } from '@/utils/common/chainPath' +import { truncateHash } from '@/utils/truncateHash' +import { encodeAddress } from '@polkadot/util-crypto' +import { TxButtonProps, useInkathon, useTxButton } from '@poppyseed/lastic-sdk' +import { usePathname } from 'next/navigation' +import { FC } from 'react' + +interface TransferModalProps { + isOpen: boolean + nextParaId: number + reservationCost: string + onClose: () => void +} + +const TransferModal: FC = ({ + isOpen, + nextParaId, + reservationCost, + onClose, +}) => { + const { relayApi, activeSigner, activeAccount, activeChain } = useInkathon() + const pathname = usePathname() + const network = getChainFromPath(pathname) + + const txButtonProps: TxButtonProps = { + api: relayApi, // api is guaranteed to be defined here + setStatus: (status: string | null) => console.log('tx status:', status), + attrs: { + palletRpc: 'registrar', + callable: 'reserve', + inputParams: [], + paramFields: [], + }, + type: 'SIGNED-TX', + activeAccount, + activeSigner, + } + + const { transaction, status, allParamsFilled } = useTxButton(txButtonProps) + + if (!isOpen) return null + + return ( + +
+
+

+ Reserved Deposit: {formatPrice(reservationCost, network)} +

+

Next ParaID: {nextParaId}

+ +

+ Reserve with account:{' '} + {activeAccount + ? truncateHash( + encodeAddress(activeAccount.address, activeChain?.ss58Prefix || 42), + 10, + ) + : 'error'} +

+
+
+ +
+
{status}
+
+
+ ) +} + +export default TransferModal diff --git a/src/config/network.ts b/src/config/network.ts index 2074641a..3d51f36f 100644 --- a/src/config/network.ts +++ b/src/config/network.ts @@ -6,7 +6,7 @@ export type NetworkInfo = { [key: string]: { name: string tokenSymbol: string - decimalPoints: number + tokenDecimals: number apiUrl: string paraId: { [key: string]: string // This tells TypeScript any string key returns a string value @@ -21,7 +21,7 @@ export const network_list: NetworkInfo = { polkadot: { name: 'Polkadot', tokenSymbol: 'DOT', - decimalPoints: 10, + tokenDecimals: 10, apiUrl: 'https://polkadot.api.subscan.io/api', paraId: { '1000': 'AssetHub', @@ -92,7 +92,7 @@ export const network_list: NetworkInfo = { kusama: { name: 'Kusama', tokenSymbol: 'KSM', - decimalPoints: 12, + tokenDecimals: 12, apiUrl: 'https://kusama.api.subscan.io/api', paraId: { '1000': 'AssetHub', @@ -180,7 +180,7 @@ export const network_list: NetworkInfo = { westend: { name: 'Westend', tokenSymbol: 'WST', - decimalPoints: 12, + tokenDecimals: 12, apiUrl: 'https://westend.api.subscan.io/api', paraId: { '1000': 'assethub-westend', @@ -219,7 +219,7 @@ export const network_list: NetworkInfo = { rococo: { name: 'Rococo', tokenSymbol: 'ROC', - decimalPoints: 12, + tokenDecimals: 12, apiUrl: 'https://rococo.api.subscan.io/api', paraId: { '1000': 'AssetHub', diff --git a/src/hooks/parachainUtils.ts b/src/hooks/parachainUtils.ts new file mode 100644 index 00000000..d72458f2 --- /dev/null +++ b/src/hooks/parachainUtils.ts @@ -0,0 +1,146 @@ +import { network_list } from '@/config/network' +import { parseHNStringToString } from '@/utils/broker/blockTime' +import { ApiPromise } from '@polkadot/api' +import { ParachainInfo, ParachainState } from './useParachainInfo' + +// Fetches the list of currently active parachains. +export const getActiveParachains = async ( + api?: ApiPromise, + relayApi?: ApiPromise, +): Promise => { + if (!api || !relayApi) return [] + + const workloadEntries = await api.query.broker.workload.entries() + return workloadEntries + .map(([, value]) => (value.toJSON() as any)[0].assignment.task) + .filter((task) => task !== undefined) +} + +// Fetches the list of parachains that are in the workplan. +export const getWorkplanParachains = async ( + api?: ApiPromise, + relayApi?: ApiPromise, +): Promise => { + if (!api || !relayApi) return [] + + const workplanEntries = await api.query.broker.workplan.entries() + return workplanEntries + .map(([, value]) => (value.toJSON() as any)[0].assignment.task) + .filter((task) => task !== undefined) +} + +// Fetches the list of parachains that are currently lease holding. +export const getLeaseHoldingParachains = async ( + api: ApiPromise, + relayApi?: ApiPromise, +): Promise => { + if (!api || !relayApi) return [] + + const leases = await api.query.broker.leases() + return (leases.toJSON() as Array<{ until: number; task: number }>).map((lease) => lease.task) +} + +// Fetches the list of system parachains. +export const getSystemParachains = async ( + api?: ApiPromise, + relayApi?: ApiPromise, +): Promise => { + if (!api || !relayApi) return [] + + const reservations = await api.query.broker.reservations() + return (reservations.toJSON() as Array) + .map((entry) => entry[0]) + .filter((lease) => lease.assignment.task) + .map((lease) => lease.assignment.task) +} + +// Fetches the list of all parachains and their states. +export const fetchAllParachains = async ( + network: string, + api?: ApiPromise, + relayApi?: ApiPromise, +): Promise => { + if (!api || !relayApi) return [] + + const parachainLifecycles = await relayApi.query.paras.paraLifecycles.entries() + const activeParas = await getActiveParachains(api, relayApi) + const workplanParas = await getWorkplanParachains(api, relayApi) + const leaseHoldingParas = await getLeaseHoldingParachains(api, relayApi) + const systemParas = await getSystemParachains(api, relayApi) + + return parachainLifecycles.map(([key, value]) => { + const [strId] = key.toHuman() as [string] + const id = parseInt(strId.replace(/,/g, '')) + const strState = value.toString() + const name = network_list[network].name ?? '' + const state = systemParas.includes(id) + ? ParachainState.SYSTEM + : leaseHoldingParas.includes(id) + ? ParachainState.LEASE_HOLDING + : strState === 'Onboarding' + ? ParachainState.ONBOARDING + : activeParas.includes(id) + ? ParachainState.ACTIVE_PARA + : workplanParas.includes(id) + ? ParachainState.IN_WORKPLAN + : strState === 'Parathread' + ? ParachainState.ONDEMAND_PARACHAIN + : ParachainState.IDLE_PARA + + return { id, state, name } + }) +} + +// Fetches the list of reserved parachains. +export const getReservedParachains = async ( + activeAccount: any, + api?: ApiPromise, + relayApi?: ApiPromise, +): Promise => { + if (!relayApi) return [] + + const records = await relayApi.query.registrar.paras.entries() + return records + .map(([key, value]) => { + const id = parseInt(parseHNStringToString((key.toHuman() as any)[0])) + const { manager } = value.toJSON() as any + return manager === activeAccount?.address + ? { id, state: ParachainState.RESERVED, name: '' } + : null + }) + .filter((parachain) => parachain !== null) as ParachainInfo[] +} + +// Fetches the next available parachain ID on the relay chain. +export const fetchNextParachainId = async ( + setNextParaId: (id: number) => void, + api?: ApiPromise, + relayApi?: ApiPromise, +) => { + if (!relayApi) return + const idRaw = await relayApi.query.registrar.nextFreeParaId() + setNextParaId(idRaw.toPrimitive() as number) +} + +// Fetches the reservation cost for parachains. +export const fetchReservationCost = async ( + setReservationCost: (cost: string) => void, + api?: ApiPromise, + relayApi?: ApiPromise, +) => { + if (!relayApi) return + setReservationCost(relayApi.consts.registrar.paraDeposit.toString()) +} + +// Fetches registration constants such as data deposit per byte and maximum code size. +export const fetchRegistrationConstants = async ( + setDataDepositPerByte: (value: bigint) => void, + setMaxCodeSize: (value: bigint) => void, + api?: ApiPromise, + relayApi?: ApiPromise, +) => { + if (!relayApi) return + setDataDepositPerByte(BigInt(relayApi.consts.registrar.dataDepositPerByte.toString())) + const { maxCodeSize } = (await relayApi.query.configuration.activeConfig()).toJSON() as any + setMaxCodeSize(BigInt(maxCodeSize)) +} diff --git a/src/hooks/useParachainInfo.tsx b/src/hooks/useParachainInfo.tsx new file mode 100644 index 00000000..6ae05d27 --- /dev/null +++ b/src/hooks/useParachainInfo.tsx @@ -0,0 +1,77 @@ +import { getChainFromPath } from '@/utils/common/chainPath' +import { useInkathon } from '@poppyseed/lastic-sdk' +import { usePathname } from 'next/navigation' +import { useCallback, useEffect, useState } from 'react' +import { + fetchAllParachains, + fetchNextParachainId, + fetchRegistrationConstants, + fetchReservationCost, + getReservedParachains, +} from './parachainUtils' + +export type ParachainInfo = { + id: number + state: ParachainState + name: string +} + +export enum ParachainState { + SYSTEM = 'System', + ACTIVE_PARA = 'Currently Active', + IDLE_PARA = 'Idle Chain', + RESERVED = 'Reserved', + ONBOARDING = 'Onboarding', + ONDEMAND_PARACHAIN = 'On-Demand Parachain', + IN_WORKPLAN = 'Idle(In workplan)', + LEASE_HOLDING = 'Lease Holding', +} + +export const useParachainInfo = () => { + const [loading, setLoading] = useState(false) + const [parachains, setParachains] = useState([]) + const [nextParaId, setNextParaId] = useState(0) + const [reservationCost, setReservationCost] = useState('0') + const [dataDepositPerByte, setDataDepositPerByte] = useState(BigInt(0)) + const [maxCodeSize, setMaxCodeSize] = useState(BigInt(0)) + + const { api, relayApi, activeAccount } = useInkathon() + const pathname = usePathname() + const network = getChainFromPath(pathname) + + const fetchParachainStates = useCallback(async () => { + setLoading(true) + await Promise.all([ + fetchNextParachainId(setNextParaId, api, relayApi), + fetchReservationCost(setReservationCost, api, relayApi), + fetchRegistrationConstants(setDataDepositPerByte, setMaxCodeSize, api, relayApi), + ]) + + const allParachains = await fetchAllParachains(network, api, relayApi) + const reservedParachains = await getReservedParachains(activeAccount, api, relayApi) + + const uniqueParachains = [ + ...allParachains, + ...reservedParachains.filter( + (reserved) => !allParachains.some((para) => para.id === reserved.id), + ), + ].sort((a, b) => a.id - b.id) + + setParachains(uniqueParachains) + setLoading(false) + }, [api, relayApi, activeAccount, network]) + + useEffect(() => { + fetchParachainStates() + }, [fetchParachainStates]) + + return { + loading, + parachains, + nextParaId, + reservationCost, + dataDepositPerByte, + maxCodeSize, + fetchParachainStates, + } +} diff --git a/src/utils/helperFunc.ts b/src/utils/helperFunc.ts index 383d07fb..1ef6a37d 100644 --- a/src/utils/helperFunc.ts +++ b/src/utils/helperFunc.ts @@ -1,3 +1,5 @@ +import { network_list } from '@/config/network' + export function joinClassNames(...classes: (string | undefined | null | false)[]): string { return classes.filter(Boolean).join(' ') } @@ -7,3 +9,10 @@ export const parseFormattedNumber = (str?: string | number): number => { if (!str) return 0 return typeof str === 'number' ? str : parseInt(str.replace(/,/g, ''), 10) } + +export const formatPrice = (price: string | number, network: string): string => { + price = typeof price === 'number' ? price : +price + const { tokenDecimals, tokenSymbol } = network_list[network] + + return `${Number(price) / 10 ** tokenDecimals} ${tokenSymbol}` +} From 86ed4bcc0eafc56eb125ebc3d85e698b05ecac95 Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed Date: Wed, 22 May 2024 04:08:27 +0200 Subject: [PATCH 2/9] added parachain utils --- src/hooks/useParachainInfo.tsx | 8 ++++---- src/{hooks => utils/parachain}/parachainUtils.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename src/{hooks => utils/parachain}/parachainUtils.ts (98%) diff --git a/src/hooks/useParachainInfo.tsx b/src/hooks/useParachainInfo.tsx index 6ae05d27..2dbddbcc 100644 --- a/src/hooks/useParachainInfo.tsx +++ b/src/hooks/useParachainInfo.tsx @@ -1,14 +1,14 @@ import { getChainFromPath } from '@/utils/common/chainPath' -import { useInkathon } from '@poppyseed/lastic-sdk' -import { usePathname } from 'next/navigation' -import { useCallback, useEffect, useState } from 'react' import { fetchAllParachains, fetchNextParachainId, fetchRegistrationConstants, fetchReservationCost, getReservedParachains, -} from './parachainUtils' +} from '@/utils/parachain/parachainUtils' +import { useInkathon } from '@poppyseed/lastic-sdk' +import { usePathname } from 'next/navigation' +import { useCallback, useEffect, useState } from 'react' export type ParachainInfo = { id: number diff --git a/src/hooks/parachainUtils.ts b/src/utils/parachain/parachainUtils.ts similarity index 98% rename from src/hooks/parachainUtils.ts rename to src/utils/parachain/parachainUtils.ts index d72458f2..80d7e844 100644 --- a/src/hooks/parachainUtils.ts +++ b/src/utils/parachain/parachainUtils.ts @@ -1,7 +1,7 @@ import { network_list } from '@/config/network' import { parseHNStringToString } from '@/utils/broker/blockTime' import { ApiPromise } from '@polkadot/api' -import { ParachainInfo, ParachainState } from './useParachainInfo' +import { ParachainInfo, ParachainState } from '../../hooks/useParachainInfo' // Fetches the list of currently active parachains. export const getActiveParachains = async ( From 7aab1ecdd7865d46141698a782514210ff6c2bf4 Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed Date: Wed, 22 May 2024 05:23:24 +0200 Subject: [PATCH 3/9] able to register your parachain - untested --- src/app/[network]/(App)/paraId/page.tsx | 22 ++++-- .../registrar/RegisterParaIDModal.tsx | 70 +++++++++++------ .../registrar/ReserveParaIDModal.tsx | 78 +++++++++++++++++++ src/components/inputFile/InputFile.tsx | 44 +++++++++++ src/components/modal/Modal.tsx | 2 +- 5 files changed, 188 insertions(+), 28 deletions(-) create mode 100644 src/components/broker/extrinsics/registrar/ReserveParaIDModal.tsx create mode 100644 src/components/inputFile/InputFile.tsx diff --git a/src/app/[network]/(App)/paraId/page.tsx b/src/app/[network]/(App)/paraId/page.tsx index 0d279086..c8e247f8 100644 --- a/src/app/[network]/(App)/paraId/page.tsx +++ b/src/app/[network]/(App)/paraId/page.tsx @@ -1,7 +1,9 @@ 'use client' import RegisterParaIDModal from '@/components/broker/extrinsics/registrar/RegisterParaIDModal' +import ReserveParaIDModal from '@/components/broker/extrinsics/registrar/ReserveParaIDModal' import PrimaryButton from '@/components/button/PrimaryButton' +import SecondaryButton from '@/components/button/SecondaryButton' import { useParachainInfo } from '@/hooks/useParachainInfo' import { getChainFromPath } from '@/utils/common/chainPath' import { usePathname } from 'next/navigation' @@ -13,18 +15,22 @@ import ParachainsSubscanInfo from './ParachainsSubscanInfo' const InstaCore = () => { const pathname = usePathname() const network = getChainFromPath(pathname) + const [isParaReserveOpen, setIsParaReserveOpen] = useState(false) const [isParaRegisterOpen, setIsParaRegisterOpen] = useState(false) - const { nextParaId, reservationCost } = useParachainInfo() + const { nextParaId, reservationCost, dataDepositPerByte, maxCodeSize } = useParachainInfo() return ( <>

- Para Id Execution on {network} + Execution on {network}

- setIsParaRegisterOpen(true)} /> +
+ setIsParaReserveOpen(true)} /> + setIsParaRegisterOpen(true)} /> +
@@ -34,10 +40,16 @@ const InstaCore = () => {
- setIsParaReserveOpen(false)} + /> + setIsParaRegisterOpen(false)} /> diff --git a/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx b/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx index 1b02d7aa..01ddaaf5 100644 --- a/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx +++ b/src/components/broker/extrinsics/registrar/RegisterParaIDModal.tsx @@ -1,38 +1,51 @@ import PrimaryButton from '@/components/button/PrimaryButton' +import InputFile from '@/components/inputFile/InputFile' import Modal from '@/components/modal/Modal' import { formatPrice } from '@/utils' import { getChainFromPath } from '@/utils/common/chainPath' import { truncateHash } from '@/utils/truncateHash' +import { ArrowUpOnSquareIcon, CodeBracketIcon } from '@heroicons/react/24/solid' +import { compactAddLength } from '@polkadot/util' import { encodeAddress } from '@polkadot/util-crypto' import { TxButtonProps, useInkathon, useTxButton } from '@poppyseed/lastic-sdk' import { usePathname } from 'next/navigation' -import { FC } from 'react' +import { FC, useState } from 'react' interface TransferModalProps { isOpen: boolean - nextParaId: number - reservationCost: string + dataDepositPerByte: bigint + maxCodeSize: bigint onClose: () => void } -const TransferModal: FC = ({ +const ReserveParaIDModal: FC = ({ isOpen, - nextParaId, - reservationCost, + dataDepositPerByte, + maxCodeSize, onClose, }) => { const { relayApi, activeSigner, activeAccount, activeChain } = useInkathon() const pathname = usePathname() const network = getChainFromPath(pathname) + const [genesisHead, setGenesisHead] = useState() + const [wasmCode, setWasmCode] = useState() + + const regCost = dataDepositPerByte * (BigInt(genesisHead?.length ?? 0) + maxCodeSize) const txButtonProps: TxButtonProps = { - api: relayApi, // api is guaranteed to be defined here + api: relayApi, setStatus: (status: string | null) => console.log('tx status:', status), attrs: { palletRpc: 'registrar', - callable: 'reserve', - inputParams: [], - paramFields: [], + callable: 'register', + inputParams: [ + genesisHead ? compactAddLength(genesisHead) : undefined, + wasmCode ? compactAddLength(wasmCode) : undefined, + ], + paramFields: [ + { name: 'genesisHead', type: 'Bytes', optional: false }, + { name: 'wasmCode', type: 'Bytes', optional: false }, + ], }, type: 'SIGNED-TX', activeAccount, @@ -41,17 +54,17 @@ const TransferModal: FC = ({ const { transaction, status, allParamsFilled } = useTxButton(txButtonProps) + // Check if genesisHead and wasmCode are defined and non-empty + const canSubmitTransaction = () => { + return genesisHead && genesisHead.length > 0 && wasmCode && wasmCode.length > 0 + } + if (!isOpen) return null return ( - -
-
-

- Reserved Deposit: {formatPrice(reservationCost, network)} -

-

Next ParaID: {nextParaId}

- + +
+

Reserve with account:{' '} {activeAccount @@ -62,17 +75,30 @@ const TransferModal: FC = ({ : 'error'}

+
Registration Cost: {formatPrice(regCost.toString(), network)}
+ } + onChange={(data) => setWasmCode(data)} + onCancel={() => setWasmCode(new Uint8Array())} + /> + } + onChange={(data) => setGenesisHead(data)} + onCancel={() => setGenesisHead(new Uint8Array())} + />
-
{status}
+
{status}
) } -export default TransferModal +export default ReserveParaIDModal diff --git a/src/components/broker/extrinsics/registrar/ReserveParaIDModal.tsx b/src/components/broker/extrinsics/registrar/ReserveParaIDModal.tsx new file mode 100644 index 00000000..c3deaf6f --- /dev/null +++ b/src/components/broker/extrinsics/registrar/ReserveParaIDModal.tsx @@ -0,0 +1,78 @@ +import PrimaryButton from '@/components/button/PrimaryButton' +import Modal from '@/components/modal/Modal' +import { formatPrice } from '@/utils' +import { getChainFromPath } from '@/utils/common/chainPath' +import { truncateHash } from '@/utils/truncateHash' +import { encodeAddress } from '@polkadot/util-crypto' +import { TxButtonProps, useInkathon, useTxButton } from '@poppyseed/lastic-sdk' +import { usePathname } from 'next/navigation' +import { FC } from 'react' + +interface TransferModalProps { + isOpen: boolean + nextParaId: number + reservationCost: string + onClose: () => void +} + +const ReserveParaIDModal: FC = ({ + isOpen, + nextParaId, + reservationCost, + onClose, +}) => { + const { relayApi, activeSigner, activeAccount, activeChain } = useInkathon() + const pathname = usePathname() + const network = getChainFromPath(pathname) + + const txButtonProps: TxButtonProps = { + api: relayApi, // api is guaranteed to be defined here + setStatus: (status: string | null) => console.log('tx status:', status), + attrs: { + palletRpc: 'registrar', + callable: 'reserve', + inputParams: [], + paramFields: [], + }, + type: 'SIGNED-TX', + activeAccount, + activeSigner, + } + + const { transaction, status, allParamsFilled } = useTxButton(txButtonProps) + + if (!isOpen) return null + + return ( + +
+
+

+ Reserved Deposit: {formatPrice(reservationCost, network)} +

+

Next ParaID: {nextParaId}

+ +

+ Reserve with account:{' '} + {activeAccount + ? truncateHash( + encodeAddress(activeAccount.address, activeChain?.ss58Prefix || 42), + 10, + ) + : 'error'} +

+
+
+ +
+
{status}
+
+
+ ) +} + +export default ReserveParaIDModal diff --git a/src/components/inputFile/InputFile.tsx b/src/components/inputFile/InputFile.tsx new file mode 100644 index 00000000..c1957dca --- /dev/null +++ b/src/components/inputFile/InputFile.tsx @@ -0,0 +1,44 @@ +import React, { FC, useState } from 'react' + +interface InputFileProps { + label: string + icon: React.ReactNode + onChange: (data: Uint8Array) => void + onCancel: () => void +} + +const InputFile: FC = ({ label, icon, onChange, onCancel }) => { + const [fileName, setFileName] = useState(null) + + const handleFileChange = async (event: React.ChangeEvent) => { + if (event.target.files && event.target.files[0]) { + const file = event.target.files[0] + const arrayBuffer = await file.arrayBuffer() + onChange(new Uint8Array(arrayBuffer)) + setFileName(file.name) + } + } + + const handleCancel = () => { + onCancel() + setFileName(null) + } + + return ( +
+ + {fileName && ( + {fileName} + )} + +
+ ) +} + +export default InputFile diff --git a/src/components/modal/Modal.tsx b/src/components/modal/Modal.tsx index 178edf54..d35cece8 100644 --- a/src/components/modal/Modal.tsx +++ b/src/components/modal/Modal.tsx @@ -19,7 +19,7 @@ const Modal: FC = ({ isOpen, onClose, title, children }) => { ​ -
+
Registration Cost: {formatPrice(regCost.toString(), network)}
+
+ + setParaId(parseFloat(e.target.value) || null)} + /> +
} diff --git a/src/components/inputField/NumberField.tsx b/src/components/inputField/NumberField.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/components/inputField/TextField.tsx b/src/components/inputField/TextField.tsx new file mode 100644 index 00000000..bb29f811 --- /dev/null +++ b/src/components/inputField/TextField.tsx @@ -0,0 +1,25 @@ +import React, { FC } from 'react' + +interface TextFieldProps { + label: string + value: string + onChange: (e: React.ChangeEvent) => void + className?: string + inputClassName?: string +} + +const TextField: FC = ({ label, value, onChange, className, inputClassName }) => { + return ( +
+ + +
+ ) +} + +export default TextField diff --git a/src/components/inputFile/InputFile.tsx b/src/components/inputFile/InputFile.tsx index c1957dca..b9ff11e2 100644 --- a/src/components/inputFile/InputFile.tsx +++ b/src/components/inputFile/InputFile.tsx @@ -25,8 +25,8 @@ const InputFile: FC = ({ label, icon, onChange, onCancel }) => { } return ( -
-
-
Registration Cost: {formatPrice(regCost.toString(), network)}
-
- - setParaId(parseFloat(e.target.value) || null)} - /> +
+ Registration Cost: {formatPrice(registrationCost.toString(), network)}
+ setParaId(parseFloat(e.target.value) || null)} + /> } diff --git a/src/components/broker/extrinsics/registrar/ReserveParaIDModal.tsx b/src/components/extrinsics/registrar/ReserveParaIDModal.tsx similarity index 100% rename from src/components/broker/extrinsics/registrar/ReserveParaIDModal.tsx rename to src/components/extrinsics/registrar/ReserveParaIDModal.tsx diff --git a/src/components/walletStatus/BuyWalletStatus.tsx b/src/components/walletStatus/BuyWalletStatus.tsx index 1c2c61dc..ce853b7c 100644 --- a/src/components/walletStatus/BuyWalletStatus.tsx +++ b/src/components/walletStatus/BuyWalletStatus.tsx @@ -1,5 +1,5 @@ -import PurchaseInteractor from '@/components/broker/extrinsics/PurchaseInteractor' import SecondaryButton from '@/components/button/SecondaryButton' +import PurchaseInteractor from '@/components/extrinsics/broker/PurchaseInteractor' import CuteInfo from '@/components/info/CuteInfo' import { ConnectButton } from '@/components/web3/ConnectButton' import { parseNativeTokenToHuman } from '@/utils/account/token' From e1e5fd499c4b7a014a520465c176deba4f11a74a Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed Date: Wed, 22 May 2024 07:22:27 +0200 Subject: [PATCH 7/9] adding descriptions --- .../[network]/(App)/paraId/ParaIdFetch2.tsx | 110 ++++ .../[network]/(App)/paraId/ParaIdRelay.tsx | 1 + .../(App)/paraId/ParachainsSubscanInfo.tsx | 2 +- src/app/[network]/(App)/paraId/page.tsx | 7 +- .../[network]/(App)/renewal/RenewFetch.tsx | 2 +- .../table/GeneralTableWithButtons.tsx | 75 +++ src/config/network.ts | 619 ++++++++++++------ src/hooks/useParachainInfo.tsx | 14 +- src/utils/parachain/parachainUtils.ts | 18 +- 9 files changed, 631 insertions(+), 217 deletions(-) create mode 100644 src/app/[network]/(App)/paraId/ParaIdFetch2.tsx create mode 100644 src/components/table/GeneralTableWithButtons.tsx diff --git a/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx b/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx new file mode 100644 index 00000000..b59df321 --- /dev/null +++ b/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx @@ -0,0 +1,110 @@ +import Border from '@/components/border/Border' +import GeneralTable from '@/components/table/GeneralTable' +import WalletStatus from '@/components/walletStatus/WalletStatus' +import { network_list } from '@/config/network' +import { ParachainInfo } from '@/hooks/useParachainInfo' +import { useInkathon } from '@poppyseed/lastic-sdk' +import { useState } from 'react' + +const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { + const { activeAccount, activeChain } = useInkathon() + const [filter, setFilter] = useState('all') + const [task, setTask] = useState(null) + const [core, setCore] = useState(null) + const [begin, setBegin] = useState(null) + + // Pagination state + const [currentPage, setCurrentPage] = useState(1) + const itemsPerPage = 8 + // Pagination functions + const handleNextPage = () => setCurrentPage(currentPage + 1) + const handlePrevPage = () => setCurrentPage(currentPage - 1) + + if (!activeChain) { + return ( + + + + ) + } + + return ( + +
+

Cores set for execution - Workload

+
+ + {filter === 'tasks' && ( + <> + + setTask(parseFloat(e.target.value) || null)} + className="ml-2 p-2 border rounded" + /> + + )} + + setBegin(parseFloat(e.target.value) || null)} + className="p-2 border rounded" + /> + + setCore(parseFloat(e.target.value) || null)} + className="p-2 border rounded" + /> +
+ {parachains ? ( + <> +
+ ({ + data: [ + paraId.toString(), + network_list[network]?.paraId[paraId.toString()]?.name, + network_list[network]?.paraId[paraId.toString()]?.description, + state, + network_list[network]?.paraId[paraId.toString()]?.lease, + , + ], + }))} + tableHeader={[ + { title: 'ParaId' }, + { title: 'Name' }, + { title: 'Description' }, + { title: 'Status' }, + { title: 'Lease Period' }, + ]} + colClass="grid-cols-5" + /> +
+ + ) : ( +

No data available.

+ )} +
+
+ ) +} + +export default ParaIdFetch diff --git a/src/app/[network]/(App)/paraId/ParaIdRelay.tsx b/src/app/[network]/(App)/paraId/ParaIdRelay.tsx index caa63c17..fa54f08d 100644 --- a/src/app/[network]/(App)/paraId/ParaIdRelay.tsx +++ b/src/app/[network]/(App)/paraId/ParaIdRelay.tsx @@ -146,6 +146,7 @@ const ParaIdRelay = () => { data.parachain.toString(), ) ? network_list[network as PossibleNetworks].paraId[data.parachain.toString()] + .name : null, data.head.toString(), data.para.toString(), diff --git a/src/app/[network]/(App)/paraId/ParachainsSubscanInfo.tsx b/src/app/[network]/(App)/paraId/ParachainsSubscanInfo.tsx index 18f69701..08b0e939 100644 --- a/src/app/[network]/(App)/paraId/ParachainsSubscanInfo.tsx +++ b/src/app/[network]/(App)/paraId/ParachainsSubscanInfo.tsx @@ -70,7 +70,7 @@ const ParachainInfo: React.FC = () => { network_list[network as PossibleNetworks].paraId.hasOwnProperty( paraInfo.para_id.toString(), ) - ? network_list[network as PossibleNetworks].paraId[paraInfo.para_id.toString()] + ? network_list[network as PossibleNetworks].paraId[paraInfo.para_id.toString()]?.name : null, paraInfo.status, toShortAddress(paraInfo.manager_display?.address), diff --git a/src/app/[network]/(App)/paraId/page.tsx b/src/app/[network]/(App)/paraId/page.tsx index 2215ed75..6cb5938f 100644 --- a/src/app/[network]/(App)/paraId/page.tsx +++ b/src/app/[network]/(App)/paraId/page.tsx @@ -9,6 +9,7 @@ import { getChainFromPath } from '@/utils/common/chainPath' import { usePathname } from 'next/navigation' import { useState } from 'react' import ParaIdFetch from './ParaIdFetch' +import ParaIdFetch2 from './ParaIdFetch2' import ParaIdRelay from './ParaIdRelay' import ParachainsSubscanInfo from './ParachainsSubscanInfo' @@ -18,7 +19,8 @@ const InstaCore = () => { const [isParaReserveOpen, setIsParaReserveOpen] = useState(false) const [isParaRegisterOpen, setIsParaRegisterOpen] = useState(false) - const { nextParaId, reservationCost, dataDepositPerByte, maxCodeSize } = useParachainInfo() + const { parachains, nextParaId, reservationCost, dataDepositPerByte, maxCodeSize } = + useParachainInfo() return ( <> @@ -33,6 +35,9 @@ const InstaCore = () => {
+
+ +
diff --git a/src/app/[network]/(App)/renewal/RenewFetch.tsx b/src/app/[network]/(App)/renewal/RenewFetch.tsx index e842027f..8d3ba05c 100644 --- a/src/app/[network]/(App)/renewal/RenewFetch.tsx +++ b/src/app/[network]/(App)/renewal/RenewFetch.tsx @@ -146,7 +146,7 @@ const RenewalsData = () => { network_list[network as PossibleNetworks].paraId.hasOwnProperty( task ? task : '', ) - ? network_list[network as PossibleNetworks].paraId[task] + ? network_list[network as PossibleNetworks].paraId[task].name : null, coreInfo[0].when, coreInfo[0].core, diff --git a/src/components/table/GeneralTableWithButtons.tsx b/src/components/table/GeneralTableWithButtons.tsx new file mode 100644 index 00000000..2741fbe3 --- /dev/null +++ b/src/components/table/GeneralTableWithButtons.tsx @@ -0,0 +1,75 @@ +import { joinClassNames } from '@/utils/helperFunc' // This is a custom function to join class names +import Link from 'next/link' +import { FC } from 'react' + +type GeneralTableProps = { + tableData: Array<{ href?: string; data: Array }> + tableHeader: Array<{ title: string }> + colClass?: string +} + +const GeneralTableWithButtions: FC = ({ + tableData, + tableHeader, + colClass = 'grid-cols-4', +}) => { + return ( +
+
+
+
+
+ {tableHeader.map((item, index) => ( +
+ {item.title} +
+ ))} +
+ + {tableData.map((item, index) => ( +
+ {item.href && ( + +
+ {item.data?.map((item2, innerIndex) => ( +
+ {item2} +
+ ))} +
+ + )} + {!item.href && ( +
+
+ {item.data.map((item2, innerIndex) => ( +
+ {item2} +
+ ))} +
+
+ )} +
+ ))} +
+
+
+
+ ) +} + +export default GeneralTableWithButtions diff --git a/src/config/network.ts b/src/config/network.ts index 3d51f36f..b97bc4c8 100644 --- a/src/config/network.ts +++ b/src/config/network.ts @@ -9,7 +9,11 @@ export type NetworkInfo = { tokenDecimals: number apiUrl: string paraId: { - [key: string]: string // This tells TypeScript any string key returns a string value + [key: string]: { + name: string + description: string + lease: number | null + } // This tells TypeScript any string key returns a string value } constants: BrokerConstantsType | null // This values changes so little, that we can just store it here rather than having to read it from the state configuration: ConfigurationType | null @@ -24,66 +28,66 @@ export const network_list: NetworkInfo = { tokenDecimals: 10, apiUrl: 'https://polkadot.api.subscan.io/api', paraId: { - '1000': 'AssetHub', - '1001': 'Collectives', - '1002': 'BridgeHub', - '1005': 'Coretime', - '2000': 'Acala', - '2002': 'Clover', - '2004': 'Moonbeam', - '2006': 'Astar', - '2007': 'Kapex', - '2008': 'Crust', - '2012': 'Parallel', - '2013': 'Litentry', - '2019': 'Composable Finance', - '2025': 'SORA', - '2026': 'Nodle', - '2027': 'Coinversation', - '2030': 'Bifrost', - '2031': 'Centrifuge', - '2032': 'Interlay', - '2034': 'HydraDX', - '2035': 'Phala Network', - '2037': 'Unique Network', - '2039': 'Integritee Network', - '2040': 'Polkadex', - '2043': 'NeuroWeb', - '2046': 'Darwinia', - '2048': 'Bitgreen', - '2051': 'Ajuna Network', - '2053': 'OmniBTC', - '2056': 'Aventus', - '2058': 'Watr Network', - '2086': 'KILT Spiritnet', - '2090': 'OAK Network', - '2091': 'Frequency', - '2092': 'Zeitgeist', - '2093': 'Hashed Network', - '2094': 'Pendulum', - '2101': 'Subsocial', - '2104': 'Manta', - '3333': 't3rn', - '3338': 'peaq', - '3340': 'InvArch', - '3344': 'Polimec', - '3345': 'Energy Web X', - '3346': 'Continuum', - '3354': 'Logion', - '3369': 'Mythos', - '3360': 'NeuroWeb', - '3366': 'Unknown', - '3367': 'Hyperbridge (Nexus)', - '2011': 'Equilibrium', - '2017': 'SubGame Gamma', - '2018': 'SubDAO', - '2021': 'Efinity', - '2028': 'Ares Odyssey', - '2038': 'Geminis', - '2052': 'Kylin', - '3334': 'Moonsama', - '3359': 'Integritee Network', - '3363': 'Polkadex', + '1000': { name: 'AssetHub', description: 'A hub for tokenized assets', lease: null }, + '1001': { name: 'Collectives', description: '', lease: null }, + '1002': { name: 'BridgeHub', description: '', lease: null }, + '1005': { name: 'Coretime', description: '', lease: null }, + '2000': { name: 'Acala', description: '', lease: null }, + '2002': { name: 'Clover', description: '', lease: null }, + '2004': { name: 'Moonbeam', description: '', lease: null }, + '2006': { name: 'Astar', description: '', lease: null }, + '2007': { name: 'Kapex', description: '', lease: null }, + '2008': { name: 'Crust', description: '', lease: null }, + '2012': { name: 'Parallel', description: '', lease: null }, + '2013': { name: 'Litentry', description: '', lease: null }, + '2019': { name: 'Composable Finance', description: '', lease: null }, + '2025': { name: 'SORA', description: '', lease: null }, + '2026': { name: 'Nodle', description: '', lease: null }, + '2027': { name: 'Coinversation', description: '', lease: null }, + '2030': { name: 'Bifrost', description: '', lease: null }, + '2031': { name: 'Centrifuge', description: '', lease: null }, + '2032': { name: 'Interlay', description: '', lease: null }, + '2034': { name: 'HydraDX', description: '', lease: null }, + '2035': { name: 'Phala Network', description: '', lease: null }, + '2037': { name: 'Unique Network', description: '', lease: null }, + '2039': { name: 'Integritee Network', description: '', lease: null }, + '2040': { name: 'Polkadex', description: '', lease: null }, + '2043': { name: 'NeuroWeb', description: '', lease: null }, + '2046': { name: 'Darwinia', description: '', lease: null }, + '2048': { name: 'Bitgreen', description: '', lease: null }, + '2051': { name: 'Ajuna Network', description: '', lease: null }, + '2053': { name: 'OmniBTC', description: '', lease: null }, + '2056': { name: 'Aventus', description: '', lease: null }, + '2058': { name: 'Watr Network', description: '', lease: null }, + '2086': { name: 'KILT Spiritnet', description: '', lease: null }, + '2090': { name: 'OAK Network', description: '', lease: null }, + '2091': { name: 'Frequency', description: '', lease: null }, + '2092': { name: 'Zeitgeist', description: '', lease: null }, + '2093': { name: 'Hashed Network', description: '', lease: null }, + '2094': { name: 'Pendulum', description: '', lease: null }, + '2101': { name: 'Subsocial', description: '', lease: null }, + '2104': { name: 'Manta', description: '', lease: null }, + '3333': { name: 't3rn', description: '', lease: null }, + '3338': { name: 'peaq', description: '', lease: null }, + '3340': { name: 'InvArch', description: '', lease: null }, + '3344': { name: 'Polimec', description: '', lease: null }, + '3345': { name: 'Energy Web X', description: '', lease: null }, + '3346': { name: 'Continuum', description: '', lease: null }, + '3354': { name: 'Logion', description: '', lease: null }, + '3369': { name: 'Mythos', description: '', lease: null }, + '3360': { name: 'NeuroWeb', description: '', lease: null }, + '3366': { name: 'Unknown', description: '', lease: null }, + '3367': { name: 'Hyperbridge (Nexus)', description: '', lease: null }, + '2011': { name: 'Equilibrium', description: '', lease: null }, + '2017': { name: 'SubGame Gamma', description: '', lease: null }, + '2018': { name: 'SubDAO', description: '', lease: null }, + '2021': { name: 'Efinity', description: '', lease: null }, + '2028': { name: 'Ares Odyssey', description: '', lease: null }, + '2038': { name: 'Geminis', description: '', lease: null }, + '2052': { name: 'Kylin', description: '', lease: null }, + '3334': { name: 'Moonsama', description: '', lease: null }, + '3359': { name: 'Integritee Network', description: '', lease: null }, + '3363': { name: 'Polkadex', description: '', lease: null }, }, constants: null, configuration: null, @@ -95,67 +99,288 @@ export const network_list: NetworkInfo = { tokenDecimals: 12, apiUrl: 'https://kusama.api.subscan.io/api', paraId: { - '1000': 'AssetHub', - '1001': 'Encointer Network', - '1002': 'BridgeHub', - '1005': 'Coretime', - '2000': 'Karura', - '2001': 'Bifrost', - '2004': 'Khala Network', - '2007': 'Shiden', - '2011': 'SORA', - '2012': 'Crust Shadow', - '2015': 'Integritee Network', - '2023': 'Moonriver', - '2024': 'Genshiro', - '2048': 'Robonomics', - '2084': 'Calamari', - '2085': 'Parallel Heiko', - '2087': 'Picasso', - '2088': 'Altair', - '2090': 'Basilisk', - '2092': 'Kintsugi BTC', - '2095': 'QUARTZ by UNIQUE', - '2096': 'Pioneer', - '2105': 'Crab', - '2106': 'Litmus', - '2110': 'Mangata', - '2113': 'Kabocha', - '2114': 'Turing Network', - '2119': 'Bajun Network', - '2121': 'Imbue Network', - '2123': 'GM', - '2124': 'Amplitude', - '2125': 'InvArch Tinkernet', - '2222': 'DAO IPCI', - '2236': 'subzero', - '2239': 'Acurast Canary', - '2241': 'Krest', - '2274': 'Quantum Portal Network', - '2281': 'Kreivo - By Virto', - '3334': 't1rn', - '3336': 'K-Laos', - '3339': 'Curio', - '3340': 'Hyperbridge (Messier)', - '3345': 'Yerba Network', - '2008': 'Mars', - '2016': 'Sakura', - '2018': 'SubGame Gamma', - '2019': 'Kpron', - '2078': 'TrustBase', - '2080': 'Loom Network', - '2094': 'Unorthodox', - '2100': 'SubsocialX', - '2102': 'Pichiu', - '2107': 'KICO', - '2115': 'Dora Factory', - '2116': 'Tanganika', - '2126': 'Parallel Heiko 2', - '2129': 'SNOW Network', - '2225': 'Crust Shadow 2', - '2226': 'Genshiro crowdloan 2', - '2240': 'Robonomics 2', - '3344': 'Xode', + '1000': { + name: 'AssetHub', + description: 'A hub for managing and trading digital assets.', + lease: 24507199, + }, + '1001': { + name: 'Encointer Network', + description: 'A network focused on local community currencies and social recognition.', + lease: 25716799, + }, + '1002': { + name: 'BridgeHub', + description: 'A bridging solution for connecting different blockchain networks.', + lease: 25716799, + }, + '1005': { + name: 'Coretime', + description: 'A decentralized time-stamping and verification network.', + lease: 27329599, + }, + '2000': { + name: 'Karura', + description: 'A DeFi hub and stablecoin platform on Kusama.', + lease: 27329599, + }, + '2001': { + name: 'Bifrost', + description: 'A staking liquidity and derivatives platform.', + lease: 24507199, + }, + '2004': { + name: 'Khala Network', + description: 'A privacy-focused cloud computing network.', + lease: 26926399, + }, + '2007': { + name: 'Shiden', + description: 'A smart contract platform supporting multiple blockchains.', + lease: 25716799, + }, + '2011': { + name: 'SORA', + description: 'A decentralized economic system for managing digital assets and DeFi.', + lease: 26119999, + }, + '2012': { + name: 'Crust Shadow', + description: 'A decentralized storage network providing cloud services.', + lease: 24910399, + }, + '2023': { + name: 'Moonriver', + description: 'A smart contract platform compatible with Ethereum, running on Kusama.', + lease: 24910399, + }, + '2024': { + name: 'Genshiro', + description: 'A DeFi platform offering various financial instruments.', + lease: 24910399, + }, + '2048': { + name: 'Robonomics', + description: 'An IoT and robotics integration platform.', + lease: 24507199, + }, + '2084': { name: 'Calamari', description: 'A privacy-focused DeFi network.', lease: 27329599 }, + '2085': { + name: 'Parallel Heiko', + description: 'A DeFi platform offering money markets and staking derivatives.', + lease: 23700799, + }, + '2087': { + name: 'Picasso', + description: 'A parachain focused on providing DeFi infrastructure and tools.', + lease: 27329599, + }, + '2090': { + name: 'Basilisk', + description: 'A liquidity bootstrapping platform for new crypto assets.', + lease: 27329599, + }, + '2095': { + name: 'QUARTZ by UNIQUE', + description: 'An NFT platform providing customization and marketplace functionalities.', + lease: 26926399, + }, + '2096': { + name: 'Pioneer', + description: 'A testing ground for new blockchain technologies.', + lease: 26926399, + }, + '2105': { + name: 'Crab', + description: 'A canary network for the Darwinia blockchain.', + lease: 26119999, + }, + '2106': { + name: 'Litmus', + description: 'A test network for the Litentry identity aggregation protocol.', + lease: 26119999, + }, + '2110': { + name: 'Mangata', + description: 'A decentralized exchange offering frictionless trading.', + lease: 25716799, + }, + '2113': { + name: 'Kabocha', + description: 'A project incubator and community-driven network.', + lease: 26926399, + }, + '2114': { + name: 'Turing Network', + description: 'A smart contract platform for automated business logic.', + lease: 25716799, + }, + '2119': { + name: 'Bajun Network', + description: 'A blockchain designed for gaming and digital collectibles.', + lease: 27329599, + }, + '2121': { + name: 'Imbue Network', + description: 'A crowdfunding platform for decentralized projects.', + lease: 26926399, + }, + '2123': { + name: 'GM', + description: 'A platform for governance and community engagement.', + lease: 23700799, + }, + '2125': { + name: 'InvArch Tinkernet', + description: 'A decentralized innovation network for collaborative projects.', + lease: 23700799, + }, + '2222': { + name: 'DAO IPCI', + description: 'A decentralized autonomous organization for environmental projects.', + lease: 24507199, + }, + '2236': { + name: 'subzero', + description: 'A network focused on secure and scalable cold storage solutions.', + lease: 25716799, + }, + '2239': { + name: 'Acurast Canary', + description: 'A test network for decentralized oracle services.', + lease: 26926399, + }, + '2241': { + name: 'Krest', + description: 'A blockchain platform for decentralized finance and applications.', + lease: 26119999, + }, + '2274': { + name: 'Quantum Portal Network', + description: 'A platform for cross-chain quantum computing solutions.', + lease: 23700799, + }, + '2281': { + name: 'Kreivo - By Virto', + description: 'A network for decentralized e-commerce solutions.', + lease: 24507199, + }, + '3334': { + name: 't1rn', + description: 'A blockchain network providing privacy and security features.', + lease: 24910399, + }, + '3336': { + name: 'K-Laos', + description: 'A decentralized network focused on supply chain transparency.', + lease: 25716799, + }, + '3339': { + name: 'Curio', + description: 'A platform for creating and managing digital art and collectibles.', + lease: 26119999, + }, + '3340': { + name: 'Hyperbridge (Messier)', + description: 'A cross-chain bridge facilitating interoperability between blockchains.', + lease: 26119999, + }, + '3344': { + name: 'Xode', + description: 'A decentralized autonomous organization for software development.', + lease: 27329599, + }, + '3345': { + name: 'Yerba Network', + description: 'A platform for sustainable agriculture and environmental projects.', + lease: 26119999, + }, + '2008': { + name: 'Mars', + description: 'A DeFi platform focused on yield farming and liquidity provision.', + lease: null, + }, + '2016': { + name: 'Sakura', + description: 'A testing and development network for the Clover finance ecosystem.', + lease: null, + }, + '2018': { + name: 'SubGame Gamma', + description: 'A blockchain gaming platform offering various play-to-earn opportunities.', + lease: null, + }, + '2019': { + name: 'Kpron', + description: 'A platform for decentralized finance and asset management.', + lease: null, + }, + '2078': { + name: 'TrustBase', + description: 'A protocol for decentralized identity and trust management.', + lease: null, + }, + '2080': { + name: 'Loom Network', + description: 'A layer 2 scaling solution for Ethereum and other blockchains.', + lease: null, + }, + '2094': { + name: 'Unorthodox', + description: 'A network for unconventional blockchain applications and experiments.', + lease: null, + }, + '2100': { + name: 'SubsocialX', + description: 'A decentralized social media platform.', + lease: null, + }, + '2102': { + name: 'Pichiu', + description: 'A blockchain network for small and medium enterprises.', + lease: null, + }, + '2107': { + name: 'KICO', + description: 'A decentralized finance platform for cross-chain transactions.', + lease: null, + }, + '2115': { + name: 'Dora Factory', + description: 'A decentralized governance and development platform.', + lease: null, + }, + '2116': { + name: 'Tanganika', + description: 'A blockchain platform for supply chain and logistics management.', + lease: null, + }, + '2126': { + name: 'Parallel Heiko 2', + description: 'An extension of the Parallel Heiko network for further DeFi applications.', + lease: null, + }, + '2129': { + name: 'SNOW Network', + description: 'A blockchain platform for decentralized finance and asset tokenization.', + lease: null, + }, + '2225': { + name: 'Crust Shadow 2', + description: 'An additional network for the Crust decentralized storage ecosystem.', + lease: null, + }, + '2226': { + name: 'Genshiro crowdloan 2', + description: 'A secondary crowdloan network for the Genshiro DeFi platform.', + lease: null, + }, + '2240': { + name: 'Robonomics 2', + description: + 'An additional network for the Robonomics IoT and robotics integration platform.', + lease: null, + }, }, constants: { maxLeasedCores: 50, @@ -183,18 +408,18 @@ export const network_list: NetworkInfo = { tokenDecimals: 12, apiUrl: 'https://westend.api.subscan.io/api', paraId: { - '1000': 'assethub-westend', - '1001': 'collectives', - '1002': 'bridgehub-westend', - '1004': 'people', - '1005': 'coretime-westend', - '2002': 'Moonshadow', - '2005': 'Wendala', - '2013': 'Whala', - '2081': 'Integritee Network', - '2086': 'Charcoal', - '2094': 'Interlay', - '2112': 'Pichiu', + '1000': { name: 'assethub-westend', description: '', lease: null }, + '1001': { name: 'collectives', description: '', lease: null }, + '1002': { name: 'bridgehub-westend', description: '', lease: null }, + '1004': { name: 'people', description: '', lease: null }, + '1005': { name: 'coretime-westend', description: '', lease: null }, + '2002': { name: 'Moonshadow', description: '', lease: null }, + '2005': { name: 'Wendala', description: '', lease: null }, + '2013': { name: 'Whala', description: '', lease: null }, + '2081': { name: 'Integritee Network', description: '', lease: null }, + '2086': { name: 'Charcoal', description: '', lease: null }, + '2094': { name: 'Interlay', description: '', lease: null }, + '2112': { name: 'Pichiu', description: '', lease: null }, }, constants: { maxLeasedCores: 10, @@ -222,69 +447,69 @@ export const network_list: NetworkInfo = { tokenDecimals: 12, apiUrl: 'https://rococo.api.subscan.io/api', paraId: { - '1000': 'AssetHub', - '1003': 'Encointer Lietaer', - '1004': 'People', - '1005': 'Coretime', - '1013': 'Bridgehub', - '1836': 'Trappist', - '2004': 'Rhala Testnet', - '2007': 'Stagex', - '2026': 'Nodle', - '2030': 'Bifrost', - '2031': 'Catalyst', - '2034': 'HydraDX', - '2040': 'Kaizen', - '2043': 'NeuroWeb Testnet', - '2056': 'Aventus', - '2058': 'Watr Network', - '2090': 'Basilisk', - '2093': 'MD5 Network', - '2100': 'SoonsocialX', - '2101': 'Zeitgeist Battery Station', - '2105': 'Pangolin2', - '2106': 'Litentry', - '2110': 'Mangata', - '2114': 'Turing Network (Staging)', - '2119': 'Bajun Network', - '2124': 'Amplitude testnet (Foucoco)', - '2125': 'Tinkernet', - '2239': 'Acurast Testnet', - '3016': 'Snowbridge Bridge Hub', - '3333': 't0rn', - '3339': 'Curio Testnet', - '3345': 'REX', - '3369': 'Muse network', - '3416': 'Snowbridge Asset Hub', - '4044': 'Frequency', - '4292': 'Yerba Network', - '4343': 'Giedi', - '4374': 'Hyperbridge (Gargantua)', - '1002': 'Contracts', - '2011': 'SORA', - '2012': 'Crust Testnet', - '2021': 'Rocfinity', - '2024': 'Genshiro Testnet', - '2048': 'Robonomics', - '2084': 'Dolphin', - '2086': 'RILT', - '2087': 'Picasso Testnet', - '2095': 'Ethos', - '2113': 'Kabocha (kabsoup)', - '2116': 'Spreehafen', - '2121': 'Imbue Network', - '3003': 'Virto', - '3015': 'Arctic', - '3025': 'Helixstreet', - '4023': 'OLI', - '4040': 'Subzero', - '4094': 'Confti', - '4168': 'Unit Network', - '4222': 'Idiyanale Network', - '4227': 'GIANT Protocol', - '4253': 'Societal', - '4354': 'OpenZeppelin Runtime Template', - '20048': 'Bitgreen', + '1000': { name: 'AssetHub', description: '', lease: 14587200 }, + '1003': { name: 'Encointer Lietaer', description: '', lease: 10555200 }, + '1004': { name: 'People', description: '', lease: 14025600 }, + '1005': { name: 'Coretime', description: '', lease: 13363200 }, + '1013': { name: 'Bridgehub', description: '', lease: 14529600 }, + '1836': { name: 'Trappist', description: '', lease: 11145600 }, + '2004': { name: 'Rhala Testnet', description: '', lease: 10972800 }, + '2007': { name: 'Stagex', description: '', lease: 11188800 }, + '2026': { name: 'Nodle', description: '', lease: 10569600 }, + '2030': { name: 'Bifrost', description: '', lease: null }, + '2031': { name: 'Catalyst', description: '', lease: 10886400 }, + '2034': { name: 'HydraDX', description: '', lease: 13161600 }, + '2040': { name: 'Kaizen', description: '', lease: 11433600 }, + '2043': { name: 'NeuroWeb Testnet', description: '', lease: 10900800 }, + '2056': { name: 'Aventus', description: '', lease: 12960000 }, + '2058': { name: 'Watr Network', description: '', lease: 14385600 }, + '2090': { name: 'Basilisk', description: '', lease: 14400000 }, + '2093': { name: 'MD5 Network', description: '', lease: 10569600 }, + '2100': { name: 'SoonsocialX', description: '', lease: 10512000 }, + '2101': { name: 'Zeitgeist Battery Station', description: '', lease: 13348800 }, + '2105': { name: 'Pangolin2', description: '', lease: 14400000 }, + '2106': { name: 'Litentry', description: '', lease: 14400000 }, + '2110': { name: 'Mangata', description: '', lease: 10742400 }, + '2114': { name: 'Turing Network (Staging)', description: '', lease: 10800000 }, + '2119': { name: 'Bajun Network', description: '', lease: 13248000 }, + '2124': { name: 'Amplitude testnet (Foucoco)', description: '', lease: 11577600 }, + '2125': { name: 'Tinkernet', description: '', lease: 10886400 }, + '2239': { name: 'Acurast Testnet', description: '', lease: 10915200 }, + '3016': { name: 'Snowbridge Bridge Hub', description: '', lease: 11520000 }, + '3333': { name: 't0rn', description: '', lease: 13248000 }, + '3339': { name: 'Curio Testnet', description: '', lease: 13737600 }, + '3345': { name: 'REX', description: '', lease: 11908800 }, + '3369': { name: 'Muse network', description: '', lease: 14932800 }, + '3416': { name: 'Snowbridge Asset Hub', description: '', lease: 11289600 }, + '4044': { name: 'Frequency', description: '', lease: 13521600 }, + '4292': { name: 'Yerba Network', description: '', lease: 12585600 }, + '4343': { name: 'Giedi', description: '', lease: 14140800 }, + '4374': { name: 'Hyperbridge (Gargantua)', description: '', lease: 12470400 }, + '1002': { name: 'Contracts', description: '', lease: null }, + '2011': { name: 'SORA', description: '', lease: null }, + '2012': { name: 'Crust Testnet', description: '', lease: null }, + '2021': { name: 'Rocfinity', description: '', lease: null }, + '2024': { name: 'Genshiro Testnet', description: '', lease: null }, + '2048': { name: 'Robonomics', description: '', lease: null }, + '2084': { name: 'Dolphin', description: '', lease: null }, + '2086': { name: 'RILT', description: '', lease: null }, + '2087': { name: 'Picasso Testnet', description: '', lease: null }, + '2095': { name: 'Ethos', description: '', lease: null }, + '2113': { name: 'Kabocha (kabsoup)', description: '', lease: null }, + '2116': { name: 'Spreehafen', description: '', lease: null }, + '2121': { name: 'Imbue Network', description: '', lease: null }, + '3003': { name: 'Virto', description: '', lease: null }, + '3015': { name: 'Arctic', description: '', lease: null }, + '3025': { name: 'Helixstreet', description: '', lease: null }, + '4023': { name: 'OLI', description: '', lease: null }, + '4040': { name: 'Subzero', description: '', lease: null }, + '4094': { name: 'Confti', description: '', lease: null }, + '4168': { name: 'Unit Network', description: '', lease: null }, + '4222': { name: 'Idiyanale Network', description: '', lease: null }, + '4227': { name: 'GIANT Protocol', description: '', lease: null }, + '4253': { name: 'Societal', description: '', lease: null }, + '4354': { name: 'OpenZeppelin Runtime Template', description: '', lease: null }, + '20048': { name: 'Bitgreen', description: '', lease: null }, }, constants: { maxLeasedCores: 50, diff --git a/src/hooks/useParachainInfo.tsx b/src/hooks/useParachainInfo.tsx index 2dbddbcc..2febedd7 100644 --- a/src/hooks/useParachainInfo.tsx +++ b/src/hooks/useParachainInfo.tsx @@ -11,20 +11,20 @@ import { usePathname } from 'next/navigation' import { useCallback, useEffect, useState } from 'react' export type ParachainInfo = { - id: number + paraId: number state: ParachainState - name: string + network: string } export enum ParachainState { - SYSTEM = 'System', + SYSTEM = 'System Chain', ACTIVE_PARA = 'Currently Active', IDLE_PARA = 'Idle Chain', RESERVED = 'Reserved', ONBOARDING = 'Onboarding', - ONDEMAND_PARACHAIN = 'On-Demand Parachain', + ONDEMAND_PARACHAIN = 'Parathread', IN_WORKPLAN = 'Idle(In workplan)', - LEASE_HOLDING = 'Lease Holding', + LEASE_HOLDING = 'Holding Slot', } export const useParachainInfo = () => { @@ -53,9 +53,9 @@ export const useParachainInfo = () => { const uniqueParachains = [ ...allParachains, ...reservedParachains.filter( - (reserved) => !allParachains.some((para) => para.id === reserved.id), + (reserved) => !allParachains.some((para) => para.paraId === reserved.paraId), ), - ].sort((a, b) => a.id - b.id) + ].sort((a, b) => a.paraId - b.paraId) setParachains(uniqueParachains) setLoading(false) diff --git a/src/utils/parachain/parachainUtils.ts b/src/utils/parachain/parachainUtils.ts index 80d7e844..159aee97 100644 --- a/src/utils/parachain/parachainUtils.ts +++ b/src/utils/parachain/parachainUtils.ts @@ -1,4 +1,3 @@ -import { network_list } from '@/config/network' import { parseHNStringToString } from '@/utils/broker/blockTime' import { ApiPromise } from '@polkadot/api' import { ParachainInfo, ParachainState } from '../../hooks/useParachainInfo' @@ -70,24 +69,23 @@ export const fetchAllParachains = async ( return parachainLifecycles.map(([key, value]) => { const [strId] = key.toHuman() as [string] - const id = parseInt(strId.replace(/,/g, '')) + const paraId = parseInt(strId.replace(/,/g, '')) const strState = value.toString() - const name = network_list[network].name ?? '' - const state = systemParas.includes(id) + const state = systemParas.includes(paraId) ? ParachainState.SYSTEM - : leaseHoldingParas.includes(id) + : leaseHoldingParas.includes(paraId) ? ParachainState.LEASE_HOLDING : strState === 'Onboarding' ? ParachainState.ONBOARDING - : activeParas.includes(id) + : activeParas.includes(paraId) ? ParachainState.ACTIVE_PARA - : workplanParas.includes(id) + : workplanParas.includes(paraId) ? ParachainState.IN_WORKPLAN : strState === 'Parathread' ? ParachainState.ONDEMAND_PARACHAIN : ParachainState.IDLE_PARA - return { id, state, name } + return { paraId, state, network } }) } @@ -102,10 +100,10 @@ export const getReservedParachains = async ( const records = await relayApi.query.registrar.paras.entries() return records .map(([key, value]) => { - const id = parseInt(parseHNStringToString((key.toHuman() as any)[0])) + const paraId = parseInt(parseHNStringToString((key.toHuman() as any)[0])) const { manager } = value.toJSON() as any return manager === activeAccount?.address - ? { id, state: ParachainState.RESERVED, name: '' } + ? { paraId, state: ParachainState.RESERVED, network: '' } : null }) .filter((parachain) => parachain !== null) as ParachainInfo[] From b00a33090b36e3b374d045a6595ca0f4f2eaf7fb Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed Date: Wed, 22 May 2024 08:36:39 +0200 Subject: [PATCH 8/9] looks cuutte --- .../[network]/(App)/paraId/ParaIdFetch2.tsx | 158 +++++++++--------- src/app/[network]/(App)/paraId/page.tsx | 8 +- src/components/inputField/NumberField.tsx | 2 +- .../table/GeneralTableWithButtons.tsx | 53 ++++-- 4 files changed, 123 insertions(+), 98 deletions(-) diff --git a/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx b/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx index b59df321..8ad50983 100644 --- a/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx +++ b/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx @@ -1,24 +1,27 @@ import Border from '@/components/border/Border' -import GeneralTable from '@/components/table/GeneralTable' +import NumberField from '@/components/inputField/NumberField' +import GeneralTableWithButtons from '@/components/table/GeneralTableWithButtons' import WalletStatus from '@/components/walletStatus/WalletStatus' import { network_list } from '@/config/network' -import { ParachainInfo } from '@/hooks/useParachainInfo' +import { ParachainInfo, ParachainState } from '@/hooks/useParachainInfo' import { useInkathon } from '@poppyseed/lastic-sdk' -import { useState } from 'react' +import { ChangeEvent, useState } from 'react' -const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { - const { activeAccount, activeChain } = useInkathon() - const [filter, setFilter] = useState('all') - const [task, setTask] = useState(null) - const [core, setCore] = useState(null) - const [begin, setBegin] = useState(null) +const statusColors = { + 'System Chain': 'bg-blue-200', + 'Currently Active': 'bg-green-200', + 'Idle Chain': 'bg-yellow-200', + Reserved: 'bg-red-200', + Onboarding: 'bg-purple-200', + Parathread: 'bg-indigo-200', + 'Idle(In workplan)': 'bg-pink-200', + 'Holding Slot': 'bg-orange-200', +} - // Pagination state - const [currentPage, setCurrentPage] = useState(1) - const itemsPerPage = 8 - // Pagination functions - const handleNextPage = () => setCurrentPage(currentPage + 1) - const handlePrevPage = () => setCurrentPage(currentPage - 1) +const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { + const { activeChain } = useInkathon() + const [filter, setFilter] = useState('all') + const [paraIdSET, setParaId] = useState(null) if (!activeChain) { return ( @@ -28,77 +31,70 @@ const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { ) } + const handleParaIdChange = (e: ChangeEvent) => { + const value = e.target.value + setParaId(value ? parseFloat(value) : null) + } + + const filteredParachains = parachains.filter((parachain) => { + const matchesFilter = filter === 'all' || parachain.state === filter + const matchesParaId = paraIdSET === null || parachain.paraId === paraIdSET + return matchesFilter && matchesParaId + }) + return (
-

Cores set for execution - Workload

-
- - {filter === 'tasks' && ( - <> - - setTask(parseFloat(e.target.value) || null)} - className="ml-2 p-2 border rounded" - /> - - )} - - setBegin(parseFloat(e.target.value) || null)} - className="p-2 border rounded" - /> - - setCore(parseFloat(e.target.value) || null)} - className="p-2 border rounded" +

Status of {filter} cores

+
+ +
+ + {Object.entries(ParachainState).map(([stateKey, stateValue]) => ( + + ))} +
- {parachains ? ( - <> -
- ({ - data: [ - paraId.toString(), - network_list[network]?.paraId[paraId.toString()]?.name, - network_list[network]?.paraId[paraId.toString()]?.description, - state, - network_list[network]?.paraId[paraId.toString()]?.lease, - , - ], - }))} - tableHeader={[ - { title: 'ParaId' }, - { title: 'Name' }, - { title: 'Description' }, - { title: 'Status' }, - { title: 'Lease Period' }, - ]} - colClass="grid-cols-5" - /> -
- + {filteredParachains.length > 0 ? ( +
+ ({ + data: [ + paraId.toString(), + network_list[network]?.paraId[paraId.toString()]?.name, + network_list[network]?.paraId[paraId.toString()]?.description, + + {state} + , + network_list[network]?.paraId[paraId.toString()]?.lease?.toString(), + ], + }))} + tableHeader={[ + { title: 'ParaId' }, + { title: 'Name' }, + { title: 'Description' }, + { title: 'Status' }, + { title: 'Lease Period' }, + ]} + colClass="grid-cols-5" + /> +
) : (

No data available.

)} diff --git a/src/app/[network]/(App)/paraId/page.tsx b/src/app/[network]/(App)/paraId/page.tsx index 6cb5938f..47d5c6a6 100644 --- a/src/app/[network]/(App)/paraId/page.tsx +++ b/src/app/[network]/(App)/paraId/page.tsx @@ -8,10 +8,7 @@ import { useParachainInfo } from '@/hooks/useParachainInfo' import { getChainFromPath } from '@/utils/common/chainPath' import { usePathname } from 'next/navigation' import { useState } from 'react' -import ParaIdFetch from './ParaIdFetch' import ParaIdFetch2 from './ParaIdFetch2' -import ParaIdRelay from './ParaIdRelay' -import ParachainsSubscanInfo from './ParachainsSubscanInfo' const InstaCore = () => { const pathname = usePathname() @@ -38,13 +35,12 @@ const InstaCore = () => {
-
+ {/*
-
-
+
*/} = ({
}> @@ -8,16 +8,29 @@ type GeneralTableProps = { colClass?: string } -const GeneralTableWithButtions: FC = ({ +const GeneralTableWithButtons: FC = ({ tableData, tableHeader, colClass = 'grid-cols-4', }) => { + // Pagination state + const [currentPage, setCurrentPage] = useState(1) + const itemsPerPage = 8 + + // Pagination functions + const handleNextPage = () => setCurrentPage(currentPage + 1) + const handlePrevPage = () => setCurrentPage(currentPage - 1) + + const currentTableData = tableData.slice( + (currentPage - 1) * itemsPerPage, + currentPage * itemsPerPage, + ) + return (
-
-
+
+
= ({ ))}
- {tableData.map((item, index) => ( -
- {item.href && ( + {currentTableData.map((item, index) => ( +
+ {item.href ? ( = ({ ))}
- )} - {!item.href && ( + ) : (
= ({
))}
+ {/* Pagination buttons */} +
+ +

{currentPage}

+ +
) } -export default GeneralTableWithButtions +export default GeneralTableWithButtons From 94060db2c761fc4eca8a30d5e1a3a3d1e5fa3834 Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed Date: Wed, 22 May 2024 09:38:46 +0200 Subject: [PATCH 9/9] adding --- .../[network]/(App)/paraId/ParaIdFetch2.tsx | 53 ++++++++++++++----- src/hooks/useParachainInfo.tsx | 2 +- src/utils/broker/blockTime.ts | 20 +++++-- 3 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx b/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx index 8ad50983..f71be51e 100644 --- a/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx +++ b/src/app/[network]/(App)/paraId/ParaIdFetch2.tsx @@ -4,6 +4,8 @@ import GeneralTableWithButtons from '@/components/table/GeneralTableWithButtons' import WalletStatus from '@/components/walletStatus/WalletStatus' import { network_list } from '@/config/network' import { ParachainInfo, ParachainState } from '@/hooks/useParachainInfo' +import { useCurrentRelayBlockNumber } from '@/hooks/useSubstrateQuery' +import { blocksToTimeFormat } from '@/utils/broker/blockTime' import { useInkathon } from '@poppyseed/lastic-sdk' import { ChangeEvent, useState } from 'react' @@ -14,14 +16,30 @@ const statusColors = { Reserved: 'bg-red-200', Onboarding: 'bg-purple-200', Parathread: 'bg-indigo-200', - 'Idle(In workplan)': 'bg-pink-200', + 'Idle - In workplan': 'bg-pink-200', 'Holding Slot': 'bg-orange-200', } +const statusDescriptions = { + 'System Chain': + 'A system chain is the main chain of a blockchain network, responsible for its core functionality.', + 'Currently Active': + 'An active parachain is currently producing blocks and participating in the relay chain.', + 'Idle Chain': 'An idle chain is not currently active or producing blocks.', + Reserved: 'Reserved parachains have slots that are reserved but not yet active.', + Onboarding: 'Parachains that are currently in the process of onboarding to the network.', + Parathread: + 'Parathreads are parachains that are not continuously active but can participate in the network on demand.', + 'Idle - In workplan': + 'Idle parachains that are included in a work plan but are not currently active.', + 'Holding Slot': 'Parachains that hold a slot but are not actively producing blocks.', +} + const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { - const { activeChain } = useInkathon() + const { activeChain, relayApi } = useInkathon() const [filter, setFilter] = useState('all') const [paraIdSET, setParaId] = useState(null) + const currentBlockNumber = useCurrentRelayBlockNumber(relayApi) if (!activeChain) { return ( @@ -57,6 +75,7 @@ const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { @@ -65,6 +84,7 @@ const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { key={stateKey} onClick={() => setFilter(stateValue)} className={`px-4 py-2 rounded-full text-black ${statusColors[stateValue]} ${filter === stateValue ? 'font-bold' : ''}`} + title={statusDescriptions[stateValue]} > {stateValue} @@ -74,17 +94,24 @@ const ParaIdFetch = ({ parachains }: { parachains: ParachainInfo[] }) => { {filteredParachains.length > 0 ? (
({ - data: [ - paraId.toString(), - network_list[network]?.paraId[paraId.toString()]?.name, - network_list[network]?.paraId[paraId.toString()]?.description, - - {state} - , - network_list[network]?.paraId[paraId.toString()]?.lease?.toString(), - ], - }))} + tableData={filteredParachains.map(({ paraId, state, network }, idx) => { + const leaseEndBlock = network_list[network]?.paraId[paraId.toString()]?.lease + const remainingBlocks = + leaseEndBlock !== null && currentBlockNumber !== null + ? leaseEndBlock - currentBlockNumber + : null + return { + data: [ + paraId.toString(), + network_list[network]?.paraId[paraId.toString()]?.name, + network_list[network]?.paraId[paraId.toString()]?.description, + + {state} + , + blocksToTimeFormat(remainingBlocks, 'RELAY'), + ], + } + })} tableHeader={[ { title: 'ParaId' }, { title: 'Name' }, diff --git a/src/hooks/useParachainInfo.tsx b/src/hooks/useParachainInfo.tsx index 2febedd7..4876612a 100644 --- a/src/hooks/useParachainInfo.tsx +++ b/src/hooks/useParachainInfo.tsx @@ -23,7 +23,7 @@ export enum ParachainState { RESERVED = 'Reserved', ONBOARDING = 'Onboarding', ONDEMAND_PARACHAIN = 'Parathread', - IN_WORKPLAN = 'Idle(In workplan)', + IN_WORKPLAN = 'Idle - In workplan', LEASE_HOLDING = 'Holding Slot', } diff --git a/src/utils/broker/blockTime.ts b/src/utils/broker/blockTime.ts index 2e7d0fd7..7779ac1e 100644 --- a/src/utils/broker/blockTime.ts +++ b/src/utils/broker/blockTime.ts @@ -40,9 +40,12 @@ export const getBlockTimestamp = async ( * Use for future blocks only and approximations only. */ export const blocksToTimeFormat = ( - nbOfBlocks: number, + nbOfBlocks: number | null, typeOfChain?: 'PARA' | 'RELAY' | 'LOCAL', ): string => { + if (!nbOfBlocks) { + return '-' + } let secondsPerBlock: number = 6 // Default value for relay chain if (typeOfChain === 'PARA') { secondsPerBlock = 12 // Parachain @@ -53,13 +56,20 @@ export const blocksToTimeFormat = ( } const totalSeconds = nbOfBlocks * secondsPerBlock - const days = Math.floor(totalSeconds / (24 * 3600)) - const hours = Math.floor((totalSeconds - days * 24 * 3600) / 3600) + + const months = Math.floor(totalSeconds / (30 * 24 * 3600)) + const weeks = Math.floor((totalSeconds % (30 * 24 * 3600)) / (7 * 24 * 3600)) + const days = Math.floor((totalSeconds % (7 * 24 * 3600)) / (24 * 3600)) + const hours = Math.floor((totalSeconds % (24 * 3600)) / 3600) const minutes = Math.floor((totalSeconds % 3600) / 60) const seconds = totalSeconds % 60 - if (days > 0) { - return `${days} days ${hours} hours ${minutes} min ${seconds} sec` + if (months > 0) { + return `${months} months ${weeks} weeks ${days} days` + } else if (weeks > 0) { + return `${weeks} weeks ${days} days ${hours} hours` + } else if (days > 0) { + return `${days} days ${hours} hours ${minutes} min` } else if (hours > 0) { return `${hours} hours ${minutes} min ${seconds} sec` } else if (minutes > 0) {