From bcca7242db7ae1d0a651dfdff9525a31fea8b165 Mon Sep 17 00:00:00 2001 From: cuteolaf Date: Wed, 24 Apr 2024 20:04:09 -0700 Subject: [PATCH] renew parachains --- src/components/Elements/Balance/index.tsx | 10 +- src/components/Elements/index.ts | 1 + src/hooks/useRenewableParas.ts | 76 +++++++++++ src/pages/renewal.tsx | 157 ++++++++++++++++++++++ 4 files changed, 242 insertions(+), 2 deletions(-) create mode 100644 src/hooks/useRenewableParas.ts create mode 100644 src/pages/renewal.tsx diff --git a/src/components/Elements/Balance/index.tsx b/src/components/Elements/Balance/index.tsx index 49b80f03..4ad9c017 100644 --- a/src/components/Elements/Balance/index.tsx +++ b/src/components/Elements/Balance/index.tsx @@ -14,10 +14,16 @@ const Balance = ({ relayBalance, coretimeBalance, symbol }: BalanceProps) => { return (
- {`Relay chain: ${formatBalance(relayBalance.toString(), false)} ${symbol}`} + {`Relay chain: ${formatBalance( + relayBalance.toString(), + false + )} ${symbol}`} - {`Coretime chain: ${formatBalance(coretimeBalance.toString(), false)} ${symbol}`} + {`Coretime chain: ${formatBalance( + coretimeBalance.toString(), + false + )} ${symbol}`}
); diff --git a/src/components/Elements/index.ts b/src/components/Elements/index.ts index 0456f2fd..47ea6d01 100644 --- a/src/components/Elements/index.ts +++ b/src/components/Elements/index.ts @@ -1,4 +1,5 @@ export * from './AmountInput'; +export * from './Balance'; export * from './Banner'; export * from './Buttons'; export * from './CoreDetailsPanel'; diff --git a/src/hooks/useRenewableParas.ts b/src/hooks/useRenewableParas.ts new file mode 100644 index 00000000..3db16f6c --- /dev/null +++ b/src/hooks/useRenewableParas.ts @@ -0,0 +1,76 @@ +import { CoreMask } from 'coretime-utils'; +import { useEffect, useState } from 'react'; + +import { parseHNString } from '@/utils/functions'; + +import { useCoretimeApi } from '@/contexts/apis'; +import { ApiState } from '@/contexts/apis/types'; + +type RenewableParachain = { + core: number; + paraID: number; + price: number; + mask: CoreMask; + when: number; +}; + +export const useRenewableParachains = () => { + const { + state: { api, apiState }, + } = useCoretimeApi(); + + const [loading, setLoading] = useState(false); + const [parachains, setParachains] = useState([]); + + useEffect(() => { + if (apiState !== ApiState.READY) { + setLoading(false); + setParachains([]); + } + + const asyncFetchParaIds = async () => { + if (!api) return; + + setLoading(true); + + const renewals = await api.query.broker.allowedRenewals.entries(); + for (const [key, value] of renewals) { + const data: any = key.toHuman(); + const core = parseHNString(data[0].core); + const when = parseHNString(data[0].when); + + const record: any = value.toHuman(); + const price = parseHNString(record.price); + const { + completion: { Complete }, + } = record; + if (Complete === undefined) continue; + if (Complete.length !== 1) continue; + const [ + { + mask, + assignment: { Task }, + }, + ] = Complete; + + if (Task === undefined) continue; + + parachains.push({ + core, + price, + mask: new CoreMask(mask), + paraID: parseHNString(Task), + when, + }); + } + + setParachains(parachains); + + setLoading(false); + }; + + asyncFetchParaIds(); + }, [api, apiState]); + + return { loading, parachains }; +}; diff --git a/src/pages/renewal.tsx b/src/pages/renewal.tsx new file mode 100644 index 00000000..453f03cb --- /dev/null +++ b/src/pages/renewal.tsx @@ -0,0 +1,157 @@ +import { + Backdrop, + Box, + Button, + CircularProgress, + FormControl, + InputLabel, + MenuItem, + Select, + Stack, + Typography, + useTheme, +} from '@mui/material'; +import Link from 'next/link'; +import { useState } from 'react'; + +import useBalance from '@/hooks/balance'; +import { useRenewableParachains } from '@/hooks/useRenewableParas'; +import { formatBalance, sendTx } from '@/utils/functions'; + +import { ProgressButton } from '@/components'; +import Balance from '@/components/Elements/Balance'; + +import { useAccounts } from '@/contexts/account'; +import { useCoretimeApi } from '@/contexts/apis'; +import { useToast } from '@/contexts/toast'; + +const Renewal = () => { + const theme = useTheme(); + + const { + state: { activeAccount, activeSigner }, + } = useAccounts(); + const { coretimeBalance, relayBalance } = useBalance(); + const { loading, parachains } = useRenewableParachains(); + const { + state: { api, symbol }, + } = useCoretimeApi(); + const { toastError, toastInfo, toastSuccess } = useToast(); + + const [paraId, setParaId] = useState(0); + const [working, setWorking] = useState(false); + + const defaultHandler = { + ready: () => toastInfo('Transaction was initiated.'), + inBlock: () => toastInfo(`In Block`), + finalized: () => setWorking(false), + success: () => { + toastSuccess('Successfully renewed the selected parachain.'); + }, + error: () => { + toastError(`Failed to renew the selected parachain.`); + setWorking(false); + }, + }; + + const handleRenew = () => { + if (!activeAccount || !api || !activeSigner) return; + + const { core } = parachains[paraId]; + + const txRenewal = api.tx.broker.renew(core); + + sendTx(txRenewal, activeAccount.address, activeSigner, defaultHandler); + }; + + return loading ? ( + + + + ) : parachains.length === 0 ? ( + There are no renewable parachains. + ) : ( + <> + + + + Renew a parachain + + + Renew a parachain + + + + + + + + Select a parachain to renew. + + + Parachain + + + + {`Core number: ${parachains[paraId].core}`} + {`Renewal price: ${formatBalance( + parachains[paraId].price.toString(), + false + )} ${symbol}`} + + + + + + + + + + ); +}; +export default Renewal;