- {t('The amount to to bid for this parachain period range.')}
+ {t('The amount to to bid for this parachain lease period range.')}
{t('The bid should be more than the current range winner to be accepted and influence the auction outcome.')}
>
}>
diff --git a/packages/page-parachains/src/Crowdloan/Refund.tsx b/packages/page-parachains/src/Crowdloan/Refund.tsx
index 8d723bf5c1..12769d5be1 100644
--- a/packages/page-parachains/src/Crowdloan/Refund.tsx
+++ b/packages/page-parachains/src/Crowdloan/Refund.tsx
@@ -107,7 +107,7 @@ function Refund ({ allAccounts, className, myAccounts, paraId }: Props): React.R
('Withdraw')}
+ label={t('Refund')}
onClick={toggleOpen}
/>
{isOpen && (
diff --git a/packages/page-parachains/src/Overview/Lifecycle.tsx b/packages/page-parachains/src/Overview/Lifecycle.tsx
index 50710f3121..cb62ae8eed 100644
--- a/packages/page-parachains/src/Overview/Lifecycle.tsx
+++ b/packages/page-parachains/src/Overview/Lifecycle.tsx
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type { ParaLifecycle } from '@polkadot/types/interfaces';
-import type { QueuedAction } from './types';
+import type { QueuedAction } from '../types';
import React from 'react';
diff --git a/packages/page-parachains/src/Overview/Parachain.tsx b/packages/page-parachains/src/Overview/Parachain.tsx
index 6de5e66b24..7a89a613bc 100644
--- a/packages/page-parachains/src/Overview/Parachain.tsx
+++ b/packages/page-parachains/src/Overview/Parachain.tsx
@@ -4,8 +4,8 @@
import type { Option, Vec } from '@polkadot/types';
import type { AccountId, BalanceOf, BlockNumber, CandidatePendingAvailability, HeadData, Header, HrmpChannel, HrmpChannelId, ParaId, ParaInfo, ParaLifecycle } from '@polkadot/types/interfaces';
import type { Codec, ITuple } from '@polkadot/types/types';
-import type { LeasePeriod } from '../types';
-import type { EventMapInfo, QueuedAction, ValidatorInfo } from './types';
+import type { LeasePeriod, QueuedAction } from '../types';
+import type { EventMapInfo, ValidatorInfo } from './types';
import BN from 'bn.js';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
diff --git a/packages/page-parachains/src/Overview/Parachains.tsx b/packages/page-parachains/src/Overview/Parachains.tsx
index 01ec24ebe1..46a1b8124f 100644
--- a/packages/page-parachains/src/Overview/Parachains.tsx
+++ b/packages/page-parachains/src/Overview/Parachains.tsx
@@ -5,8 +5,8 @@ import type { ApiPromise } from '@polkadot/api';
import type { SignedBlockExtended } from '@polkadot/api-derive/types';
import type { AccountId, CandidateReceipt, Event, ParaId, ParaValidatorIndex } from '@polkadot/types/interfaces';
import type { IEvent } from '@polkadot/types/types';
-import type { LeasePeriod, ScheduledProposals } from '../types';
-import type { EventMapInfo, QueuedAction, ValidatorInfo } from './types';
+import type { LeasePeriod, QueuedAction, ScheduledProposals } from '../types';
+import type { EventMapInfo, ValidatorInfo } from './types';
import BN from 'bn.js';
import React, { useEffect, useMemo, useRef, useState } from 'react';
@@ -15,8 +15,8 @@ import { Table } from '@polkadot/react-components';
import { useApi, useBestNumber, useCall, useCallMulti } from '@polkadot/react-hooks';
import { useTranslation } from '../translate';
+import useHrmp from '../useHrmp';
import Parachain from './Parachain';
-import useHrmp from './useHrmp';
interface Props {
actionsQueue: QueuedAction[];
diff --git a/packages/page-parachains/src/Overview/Upcomings.tsx b/packages/page-parachains/src/Overview/Upcomings.tsx
deleted file mode 100644
index e68ec3ba2d..0000000000
--- a/packages/page-parachains/src/Overview/Upcomings.tsx
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
-// SPDX-License-Identifier: Apache-2.0
-
-import type { ParaId } from '@polkadot/types/interfaces';
-import type { LeasePeriod } from '../types';
-import type { QueuedAction } from './types';
-
-import React, { useRef } from 'react';
-
-import { Table } from '@polkadot/react-components';
-
-import { useTranslation } from '../translate';
-import Upcoming from './Upcoming';
-
-interface Props {
- actionsQueue: QueuedAction[];
- ids?: ParaId[];
- leasePeriod?: LeasePeriod;
-}
-
-function Upcomings ({ actionsQueue, ids, leasePeriod }: Props): React.ReactElement {
- const { t } = useTranslation();
-
- const headerRef = useRef([
- [t('parathreads'), 'start', 3],
- [t('head'), 'start'],
- [t('lifecycle'), 'start'],
- [t('leases')]
- ]);
-
- return (
- ('There are no upcoming parachains')}
- header={headerRef.current}
- >
- {leasePeriod && ids?.map((id): React.ReactNode => (
-
- paraIds.some((p) => p.eq(id))
- )}
- />
- ))}
-
- );
-}
-
-export default React.memo(Upcomings);
diff --git a/packages/page-parachains/src/Overview/index.tsx b/packages/page-parachains/src/Overview/index.tsx
index 981da820a8..bb40a60484 100644
--- a/packages/page-parachains/src/Overview/index.tsx
+++ b/packages/page-parachains/src/Overview/index.tsx
@@ -2,55 +2,38 @@
// SPDX-License-Identifier: Apache-2.0
import type { ParaId } from '@polkadot/types/interfaces';
-import type { LeasePeriod, Proposals } from '../types';
+import type { LeasePeriod, Proposals, QueuedAction } from '../types';
import React from 'react';
-import { useApi, useCall } from '@polkadot/react-hooks';
-
-import Actions from './Actions';
import Parachains from './Parachains';
import Summary from './Summary';
-import Upcomings from './Upcomings';
-import useActionsQueue from './useActionsQueue';
-import useUpcomingIds from './useUpcomingIds';
interface Props {
+ actionsQueue: QueuedAction[];
className?: string;
leasePeriod?: LeasePeriod;
+ paraIds?: ParaId[];
proposals?: Proposals;
+ threadIds?: ParaId[];
+ upcomingIds?: ParaId[];
}
-function Overview ({ className, leasePeriod, proposals }: Props): React.ReactElement {
- const { api } = useApi();
- const paraIds = useCall(api.query.paras?.parachains);
- const actionsQueue = useActionsQueue();
- const upcomingIds = useUpcomingIds();
-
+function Overview ({ actionsQueue, className, leasePeriod, paraIds, proposals, threadIds }: Props): React.ReactElement {
return (
+
-
- {api.query.paras && (
- <>
-
-
- >
- )}
);
}
diff --git a/packages/page-parachains/src/Overview/types.ts b/packages/page-parachains/src/Overview/types.ts
index e1cc55a783..0802eac142 100644
--- a/packages/page-parachains/src/Overview/types.ts
+++ b/packages/page-parachains/src/Overview/types.ts
@@ -2,20 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import type BN from 'bn.js';
-import type { AccountId, BalanceOf, HrmpChannel, HrmpChannelId, ParaId, ParaValidatorIndex } from '@polkadot/types/interfaces';
-
-export type ChannelMap = Record;
-
-export interface LeaseInfo {
- accountId: AccountId;
- balance: BalanceOf;
- period: number;
-}
-
-export interface QueuedAction {
- paraIds: ParaId[];
- sessionIndex: BN;
-}
+import type { AccountId, ParaValidatorIndex } from '@polkadot/types/interfaces';
export interface EventMapInfo {
blockHash: string;
diff --git a/packages/page-parachains/src/Overview/Actions.tsx b/packages/page-parachains/src/Parathreads/Actions.tsx
similarity index 100%
rename from packages/page-parachains/src/Overview/Actions.tsx
rename to packages/page-parachains/src/Parathreads/Actions.tsx
diff --git a/packages/page-parachains/src/Overview/Upcoming.tsx b/packages/page-parachains/src/Parathreads/Parathread.tsx
similarity index 58%
rename from packages/page-parachains/src/Overview/Upcoming.tsx
rename to packages/page-parachains/src/Parathreads/Parathread.tsx
index 0097ed06e8..3a6f44beae 100644
--- a/packages/page-parachains/src/Overview/Upcoming.tsx
+++ b/packages/page-parachains/src/Parathreads/Parathread.tsx
@@ -1,32 +1,30 @@
// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
// SPDX-License-Identifier: Apache-2.0
-import type { Option, Vec } from '@polkadot/types';
-import type { AccountId, BalanceOf, HeadData, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle } from '@polkadot/types/interfaces';
-import type { ITuple } from '@polkadot/types/types';
-import type { LeasePeriod } from '../types';
-import type { LeaseInfo, QueuedAction } from './types';
+import type { Option } from '@polkadot/types';
+import type { AccountId, HeadData, ParaGenesisArgs, ParaId, ParaInfo, ParaLifecycle } from '@polkadot/types/interfaces';
+import type { LeaseInfo, LeasePeriod, QueuedAction } from '../types';
import React, { useMemo } from 'react';
-import { AddressSmall, ParaLink } from '@polkadot/react-components';
-import { useApi, useCallMulti } from '@polkadot/react-hooks';
+import { AddressSmall, ParaLink, TxButton } from '@polkadot/react-components';
+import { useAccounts, useApi, useCallMulti } from '@polkadot/react-hooks';
import { formatNumber } from '@polkadot/util';
+import Lifecycle from '../Overview/Lifecycle';
+import Periods from '../Overview/Periods';
import { useTranslation } from '../translate';
import { sliceHex } from '../util';
-import Lifecycle from './Lifecycle';
-import Periods from './Periods';
interface Props {
id: ParaId;
leasePeriod: LeasePeriod;
+ leases: LeaseInfo[];
nextAction?: QueuedAction;
}
interface MultiState {
headHex: string | null;
- leases: LeaseInfo[] | null;
lifecycle: ParaLifecycle | null;
manager: AccountId | null;
}
@@ -34,33 +32,15 @@ interface MultiState {
const optMulti = {
defaultValue: {
headHex: null,
- leases: null,
lifecycle: null,
manager: null
},
- transform: ([optHead, optGenesis, optLifecycle, optInfo, leases]: [Option, Option, Option, Option, Vec>>]): MultiState => ({
+ transform: ([optHead, optGenesis, optLifecycle, optInfo]: [Option, Option, Option, Option]): MultiState => ({
headHex: optHead.isSome
? sliceHex(optHead.unwrap())
: optGenesis.isSome
? sliceHex(optGenesis.unwrap().genesisHead)
: null,
- leases: leases
- ? leases
- .map((optLease, period): LeaseInfo | null => {
- if (optLease.isNone) {
- return null;
- }
-
- const [accountId, balance] = optLease.unwrap();
-
- return {
- accountId,
- balance,
- period
- };
- })
- .filter((item): item is LeaseInfo => !!item)
- : [],
lifecycle: optLifecycle.unwrapOr(null),
manager: optInfo.isSome
? optInfo.unwrap().manager
@@ -68,15 +48,15 @@ const optMulti = {
})
};
-function Upcoming ({ id, leasePeriod, nextAction }: Props): React.ReactElement {
+function Upcoming ({ id, leasePeriod, leases, nextAction }: Props): React.ReactElement {
const { t } = useTranslation();
const { api } = useApi();
- const { headHex, leases, lifecycle, manager } = useCallMulti([
+ const { isAccount } = useAccounts();
+ const { headHex, lifecycle, manager } = useCallMulti([
[api.query.paras.heads, id],
[api.query.paras.upcomingParasGenesis, id],
[api.query.paras.paraLifecycles, id],
- [api.query.registrar?.paras, id],
- [api.query.slots?.leases, id]
+ [api.query.registrar?.paras, id]
], optMulti);
const periods = useMemo(
@@ -85,6 +65,8 @@ function Upcoming ({ id, leasePeriod, nextAction }: Props): React.ReactElement
{formatNumber(id)}
@@ -110,6 +92,16 @@ function Upcoming ({ id, leasePeriod, nextAction }: Props): React.ReactElement
+
+ ('Deregister')}
+ params={[id]}
+ tx={api.tx.registrar.deregister}
+ />
+
);
}
diff --git a/packages/page-parachains/src/Overview/RegisterThread.tsx b/packages/page-parachains/src/Parathreads/RegisterThread.tsx
similarity index 100%
rename from packages/page-parachains/src/Overview/RegisterThread.tsx
rename to packages/page-parachains/src/Parathreads/RegisterThread.tsx
diff --git a/packages/page-parachains/src/Parathreads/index.tsx b/packages/page-parachains/src/Parathreads/index.tsx
new file mode 100644
index 0000000000..67692f8e87
--- /dev/null
+++ b/packages/page-parachains/src/Parathreads/index.tsx
@@ -0,0 +1,100 @@
+// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+import type { Option } from '@polkadot/types';
+import type { AccountId, BalanceOf, ParaId } from '@polkadot/types/interfaces';
+import type { ITuple } from '@polkadot/types/types';
+import type { LeaseInfo, LeasePeriod, QueuedAction } from '../types';
+
+import React, { useRef } from 'react';
+
+import { Table } from '@polkadot/react-components';
+import { useApi, useCall } from '@polkadot/react-hooks';
+
+import { useTranslation } from '../translate';
+import Actions from './Actions';
+import Parathread from './Parathread';
+
+interface Props {
+ actionsQueue: QueuedAction[];
+ className?: string;
+ ids?: ParaId[];
+ leasePeriod?: LeasePeriod;
+}
+
+type ParaMap = [ParaId, LeaseInfo[]][];
+
+const optLeases = {
+ transform: ([[paraIds], leases]: [[ParaId[]], Option>[][]]): ParaMap =>
+ paraIds
+ .reduce((all: ParaMap, id, index): ParaMap => {
+ all.push([
+ id,
+ leases[index]
+ .map((optLease, period): LeaseInfo | null => {
+ if (optLease.isNone) {
+ return null;
+ }
+
+ const [accountId, balance] = optLease.unwrap();
+
+ return {
+ accountId,
+ balance,
+ period
+ };
+ })
+ .filter((item): item is LeaseInfo => !!item)
+ ]);
+
+ return all;
+ }, [])
+ .sort(([aId, aLeases], [bId, bLeases]) =>
+ aLeases.length && bLeases.length
+ ? (aLeases[0].period - bLeases[0].period) || aId.cmp(bId)
+ : aLeases.length
+ ? -1
+ : bLeases.length
+ ? 1
+ : aId.cmp(bId)
+ ),
+ withParamsTransform: true
+};
+
+function Parathreads ({ actionsQueue, className, ids, leasePeriod }: Props): React.ReactElement {
+ const { t } = useTranslation();
+ const { api } = useApi();
+ const leaseMap = useCall(ids && api.query.slots.leases.multi, [ids], optLeases);
+
+ const headerRef = useRef([
+ [t('parathreads'), 'start', 3],
+ [t('head'), 'start'],
+ [t('lifecycle'), 'start'],
+ [t('leases')],
+ []
+ ]);
+
+ return (
+
+
+
('There are no available parathreads')}
+ header={headerRef.current}
+ >
+ {leasePeriod && leaseMap?.map(([id, leases]): React.ReactNode => (
+
+ paraIds.some((p) => p.eq(id))
+ )}
+ />
+ ))}
+
+
+ );
+}
+
+export default React.memo(Parathreads);
diff --git a/packages/page-parachains/src/index.tsx b/packages/page-parachains/src/index.tsx
index 2ad834f7df..2d1b195ee7 100644
--- a/packages/page-parachains/src/index.tsx
+++ b/packages/page-parachains/src/index.tsx
@@ -1,24 +1,29 @@
// Copyright 2017-2021 @polkadot/app-parachains authors & contributors
// SPDX-License-Identifier: Apache-2.0
+import type { ParaId } from '@polkadot/types/interfaces';
+
import React, { useRef } from 'react';
import { Route, Switch } from 'react-router';
import { useLocation } from 'react-router-dom';
import styled from 'styled-components';
import { Tabs } from '@polkadot/react-components';
-import { useApi } from '@polkadot/react-hooks';
+import { useApi, useCall } from '@polkadot/react-hooks';
import Auctions from './Auctions';
import Crowdloan from './Crowdloan';
import Overview from './Overview';
+import Parathreads from './Parathreads';
import Proposals from './Proposals';
import { useTranslation } from './translate';
+import useActionsQueue from './useActionsQueue';
import useAuctionInfo from './useAuctionInfo';
import useFunds from './useFunds';
import useLeasePeriod from './useLeasePeriod';
import useOwnedIds from './useOwnedIds';
import useProposals from './useProposals';
+import useUpcomingIds from './useUpcomingIds';
import useWinningData from './useWinningData';
interface Props {
@@ -36,6 +41,9 @@ function ParachainsApp ({ basePath, className }: Props): React.ReactElement(api.query.paras?.parachains);
+ const actionsQueue = useActionsQueue();
+ const upcomingIds = useUpcomingIds();
const items = useRef([
{
@@ -43,6 +51,10 @@ function ParachainsApp ({ basePath, className }: Props): React.ReactElement('Overview')
},
+ {
+ name: 'parathreads',
+ text: t('Parathreads')
+ },
api.query.proposeParachain && {
name: 'proposals',
text: t('Proposals')
@@ -85,9 +97,18 @@ function ParachainsApp ({ basePath, className }: Props): React.ReactElement
+
);
diff --git a/packages/page-parachains/src/types.ts b/packages/page-parachains/src/types.ts
index 5ab6b3f9dd..f902368911 100644
--- a/packages/page-parachains/src/types.ts
+++ b/packages/page-parachains/src/types.ts
@@ -2,7 +2,25 @@
// SPDX-License-Identifier: Apache-2.0
import type BN from 'bn.js';
-import type { AuctionIndex, BlockNumber, FundInfo, LeasePeriodOf, ParachainProposal, ParaId, ParaInfo, SessionIndex } from '@polkadot/types/interfaces';
+import type { AccountId, AuctionIndex, BalanceOf, BlockNumber, FundInfo, HrmpChannel, HrmpChannelId, LeasePeriodOf, ParachainProposal, ParaId, ParaInfo, SessionIndex } from '@polkadot/types/interfaces';
+
+export type ChannelMap = Record;
+
+export interface AllChannels {
+ dst: ChannelMap;
+ src: ChannelMap;
+}
+
+export interface LeaseInfo {
+ accountId: AccountId;
+ balance: BalanceOf;
+ period: number;
+}
+
+export interface QueuedAction {
+ paraIds: ParaId[];
+ sessionIndex: BN;
+}
export interface AuctionInfo {
endBlock: BlockNumber | null;
diff --git a/packages/page-parachains/src/Overview/useActionsQueue.ts b/packages/page-parachains/src/useActionsQueue.ts
similarity index 100%
rename from packages/page-parachains/src/Overview/useActionsQueue.ts
rename to packages/page-parachains/src/useActionsQueue.ts
diff --git a/packages/page-parachains/src/useFunds.ts b/packages/page-parachains/src/useFunds.ts
index 0bb3230035..f5c9bf202e 100644
--- a/packages/page-parachains/src/useFunds.ts
+++ b/packages/page-parachains/src/useFunds.ts
@@ -169,7 +169,7 @@ export default function useFunds (): Campaigns {
const [paraIds, setParaIds] = useState([]);
const trigger = useEventTrigger([api.events.crowdloan?.Created]);
const campaigns = useCall(api.query.crowdloan?.funds.multi, [paraIds], optFundMulti);
- const leases = useCall(api.query.slots?.leases.multi, [paraIds], optLeaseMulti);
+ const leases = useCall(api.query.slots.leases.multi, [paraIds], optLeaseMulti);
const [result, setResult] = useState(EMPTY);
// on event triggers, update the available paraIds
diff --git a/packages/page-parachains/src/Overview/useHrmp.ts b/packages/page-parachains/src/useHrmp.ts
similarity index 79%
rename from packages/page-parachains/src/Overview/useHrmp.ts
rename to packages/page-parachains/src/useHrmp.ts
index f3fb72f8af..06071f8d9f 100644
--- a/packages/page-parachains/src/Overview/useHrmp.ts
+++ b/packages/page-parachains/src/useHrmp.ts
@@ -3,24 +3,19 @@
import type { Option } from '@polkadot/types';
import type { HrmpChannel, HrmpChannelId } from '@polkadot/types/interfaces';
-import type { ChannelMap } from './types';
+import type { AllChannels } from './types';
import { useEffect, useState } from 'react';
import { useApi, useCall, useEventTrigger } from '@polkadot/react-hooks';
-interface Result {
- dst: ChannelMap;
- src: ChannelMap;
-}
-
const optChannels = {
- transform: ([[channelIds], channels]: [[HrmpChannelId[]], Option[]]): Result =>
+ transform: ([[channelIds], channels]: [[HrmpChannelId[]], Option[]]): AllChannels =>
channelIds
.map((id, index): [HrmpChannelId, Option] => [id, channels[index]])
.filter(([, opt]) => opt.isSome)
.map(([id, opt]): [HrmpChannelId, HrmpChannel] => [id, opt.unwrap()])
- .reduce((all: Result, [id, channel]): Result => {
+ .reduce((all: AllChannels, [id, channel]): AllChannels => {
all.dst[id.receiver.toString()] ||= [];
all.src[id.sender.toString()] ||= [];
@@ -32,11 +27,11 @@ const optChannels = {
withParamsTransform: true
};
-export default function useHrmp (): Result | undefined {
+export default function useHrmp (): AllChannels | undefined {
const { api } = useApi();
const [channelIds, setChannelIds] = useState(null);
const trigger = useEventTrigger([api.events.hrmp?.OpenChannelAccepted, api.events.hrmp?.ChannelClosed]);
- const allChannels = useCall(channelIds && api.query.hrmp?.hrmpChannels.multi, [channelIds], optChannels);
+ const allChannels = useCall(channelIds && api.query.hrmp?.hrmpChannels.multi, [channelIds], optChannels);
useEffect((): void => {
trigger &&
diff --git a/packages/page-parachains/src/useLeasePeriod.ts b/packages/page-parachains/src/useLeasePeriod.ts
index b660dbe118..0f151abd42 100644
--- a/packages/page-parachains/src/useLeasePeriod.ts
+++ b/packages/page-parachains/src/useLeasePeriod.ts
@@ -13,7 +13,7 @@ export default function useLeasePeriod (): LeasePeriod | undefined {
const bestNumber = useBestNumber();
return useMemo((): LeasePeriod | undefined => {
- if (!api.consts.slots?.leasePeriod || !bestNumber) {
+ if (!api.consts.slots.leasePeriod || !bestNumber) {
return;
}
diff --git a/packages/page-parachains/src/Overview/useUpcomingIds.ts b/packages/page-parachains/src/useUpcomingIds.ts
similarity index 100%
rename from packages/page-parachains/src/Overview/useUpcomingIds.ts
rename to packages/page-parachains/src/useUpcomingIds.ts
diff --git a/packages/react-hooks/src/useAccounts.ts b/packages/react-hooks/src/useAccounts.ts
index 2eac30f6a0..6ed319193a 100644
--- a/packages/react-hooks/src/useAccounts.ts
+++ b/packages/react-hooks/src/useAccounts.ts
@@ -10,7 +10,7 @@ import { useIsMountedRef } from './useIsMountedRef';
interface UseAccounts {
allAccounts: string[];
hasAccounts: boolean;
- isAccount: (address: string) => boolean;
+ isAccount: (address?: string | null) => boolean;
}
const EMPTY: UseAccounts = { allAccounts: [], hasAccounts: false, isAccount: () => false };
@@ -24,7 +24,7 @@ export function useAccounts (): UseAccounts {
if (mountedRef.current) {
const allAccounts = accounts ? Object.keys(accounts) : [];
const hasAccounts = allAccounts.length !== 0;
- const isAccount = (address: string) => allAccounts.includes(address);
+ const isAccount = (address?: string | null) => !!address && allAccounts.includes(address);
setState({ allAccounts, hasAccounts, isAccount });
}