Sort parachain lists with known first (#5011)
* Sort parachain lists with known first * leases re-sort * Adjust sorting
This commit is contained in:
parent
e1d3919d65
commit
498a4818ff
@ -99,7 +99,7 @@ function Auction ({ auctionInfo, campaigns, className, winningData }: Props): Re
|
||||
blockNumber={blockNumber}
|
||||
isFirst={index === 0}
|
||||
isLatest={round === 0}
|
||||
key={`${blockNumber.toString()}:${index}`}
|
||||
key={`${blockNumber.toString()}:${value.key}`}
|
||||
value={value}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -2,11 +2,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { ParaId } from '@polkadot/types/interfaces';
|
||||
import type { Campaign, LeasePeriod } from '../types';
|
||||
|
||||
import React, { useMemo, useRef } from 'react';
|
||||
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useIsParasLinked } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Fund from './Fund';
|
||||
@ -18,19 +20,45 @@ interface Props {
|
||||
value: Campaign[] | null;
|
||||
}
|
||||
|
||||
function extractLists (value: Campaign[] | null, leasePeriod?: LeasePeriod): [Campaign[] | null, Campaign[] | null] {
|
||||
function extractLists (value: Campaign[] | null, leasePeriod?: LeasePeriod): [Campaign[] | null, Campaign[] | null, ParaId[] | null] {
|
||||
const currentPeriod = leasePeriod?.currentPeriod;
|
||||
let active: Campaign[] | null = null;
|
||||
let ended: Campaign[] | null = null;
|
||||
let allIds: ParaId[] | null = null;
|
||||
|
||||
return value && currentPeriod
|
||||
? [
|
||||
value.filter(({ firstSlot, isCapped, isEnded, isWinner }) => !(isCapped || isEnded || isWinner) && currentPeriod.lte(firstSlot)),
|
||||
value.filter(({ firstSlot, isCapped, isEnded, isWinner }) => (isCapped || isEnded || isWinner) || currentPeriod.gt(firstSlot))
|
||||
]
|
||||
: [null, null];
|
||||
if (value && currentPeriod) {
|
||||
active = value.filter(({ firstSlot, isCapped, isEnded, isWinner }) => !(isCapped || isEnded || isWinner) && currentPeriod.lte(firstSlot));
|
||||
ended = value.filter(({ firstSlot, isCapped, isEnded, isWinner }) => (isCapped || isEnded || isWinner) || currentPeriod.gt(firstSlot));
|
||||
allIds = value.map(({ paraId }) => paraId);
|
||||
}
|
||||
|
||||
return [active, ended, allIds];
|
||||
}
|
||||
|
||||
function sortList (hasLinksMap: Record<string, boolean>, list?: Campaign[] | null): Campaign[] | null | undefined {
|
||||
return list?.sort(({ key: a }, { key: b }): number => {
|
||||
const aKnown = hasLinksMap[a] || false;
|
||||
const bKnown = hasLinksMap[b] || false;
|
||||
|
||||
return aKnown === bKnown
|
||||
? 0
|
||||
: aKnown
|
||||
? -1
|
||||
: 1;
|
||||
});
|
||||
}
|
||||
|
||||
function Funds ({ bestNumber, className, leasePeriod, value }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const [active, ended, allIds] = useMemo(
|
||||
() => extractLists(value, leasePeriod),
|
||||
[leasePeriod, value]
|
||||
);
|
||||
const hasLinksMap = useIsParasLinked(allIds);
|
||||
const [activeSorted, endedSorted] = useMemo(
|
||||
() => [sortList(hasLinksMap, active), sortList(hasLinksMap, ended)],
|
||||
[active, ended, hasLinksMap]
|
||||
);
|
||||
|
||||
const headerActiveRef = useRef([
|
||||
[t('ongoing'), 'start', 2],
|
||||
@ -57,19 +85,14 @@ function Funds ({ bestNumber, className, leasePeriod, value }: Props): React.Rea
|
||||
[]
|
||||
]);
|
||||
|
||||
const [active, ended] = useMemo(
|
||||
() => extractLists(value, leasePeriod),
|
||||
[leasePeriod, value]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
className={className}
|
||||
empty={value && active && t<string>('No active campaigns found')}
|
||||
empty={value && activeSorted && t<string>('No active campaigns found')}
|
||||
header={headerActiveRef.current}
|
||||
>
|
||||
{active?.map((fund) => (
|
||||
{activeSorted?.map((fund) => (
|
||||
<Fund
|
||||
bestNumber={bestNumber}
|
||||
isOngoing
|
||||
@ -80,10 +103,10 @@ function Funds ({ bestNumber, className, leasePeriod, value }: Props): React.Rea
|
||||
</Table>
|
||||
<Table
|
||||
className={className}
|
||||
empty={value && ended && t<string>('No completed campaigns found')}
|
||||
empty={value && endedSorted && t<string>('No completed campaigns found')}
|
||||
header={headedEndedRef.current}
|
||||
>
|
||||
{ended?.map((fund) => (
|
||||
{endedSorted?.map((fund) => (
|
||||
<Fund
|
||||
bestNumber={bestNumber}
|
||||
key={fund.accountId}
|
||||
|
||||
@ -12,7 +12,7 @@ import BN from 'bn.js';
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useBestNumber, useCall, useCallMulti } from '@polkadot/react-hooks';
|
||||
import { useApi, useBestNumber, useCall, useCallMulti, useIsParasLinked } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import useHrmp from '../useHrmp';
|
||||
@ -61,10 +61,11 @@ function extractScheduledIds (scheduled: ScheduledProposals[] = []): Record<stri
|
||||
}), all), {});
|
||||
}
|
||||
|
||||
function mapValidators (ids: ParaId[] | undefined, validators: AccountId[] | null, validatorGroups: ParaValidatorIndex[][] | null, activeIndices: ParaValidatorIndex[] | null): ValidatorInfo[][] {
|
||||
function mapValidators (ids: ParaId[] | undefined, validators: AccountId[] | null, validatorGroups: ParaValidatorIndex[][] | null, activeIndices: ParaValidatorIndex[] | null): Record<string, ValidatorInfo[]> {
|
||||
return activeIndices && validators && validatorGroups && ids && ids.length === validatorGroups.length
|
||||
? validatorGroups.map((indices) =>
|
||||
indices
|
||||
? validatorGroups.reduce((all: Record<string, ValidatorInfo[]>, indices, index) => ({
|
||||
...all,
|
||||
[ids[index].toString()]: indices
|
||||
.map((indexActive) => [indexActive, activeIndices[indexActive.toNumber()]])
|
||||
.filter(([, a]) => a)
|
||||
.map(([indexActive, indexValidator]) => ({
|
||||
@ -72,8 +73,8 @@ function mapValidators (ids: ParaId[] | undefined, validators: AccountId[] | nul
|
||||
indexValidator,
|
||||
validatorId: validators[indexValidator.toNumber()]
|
||||
}))
|
||||
)
|
||||
: [];
|
||||
}), {})
|
||||
: {};
|
||||
}
|
||||
|
||||
function extractEvents (api: ApiPromise, lastBlock: SignedBlockExtended, prev: LastEvents): LastEvents {
|
||||
@ -125,6 +126,21 @@ function extractActions (actionsQueue: QueuedAction[], knownIds?: [ParaId, strin
|
||||
: {};
|
||||
}
|
||||
|
||||
function extractIds (hasLinksMap: Record<string, boolean>, ids?: ParaId[]): [ParaId, string][] | undefined {
|
||||
return ids
|
||||
?.map((id): [ParaId, string] => [id, id.toString()])
|
||||
.sort(([aId, aIds], [bId, bIds]): number => {
|
||||
const aKnown = hasLinksMap[aIds] || false;
|
||||
const bKnown = hasLinksMap[bIds] || false;
|
||||
|
||||
return aKnown === bKnown
|
||||
? aId.cmp(bId)
|
||||
: aKnown
|
||||
? -1
|
||||
: 1;
|
||||
});
|
||||
}
|
||||
|
||||
function Parachains ({ actionsQueue, ids, leasePeriod, scheduled }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
@ -137,6 +153,7 @@ function Parachains ({ actionsQueue, ids, leasePeriod, scheduled }: Props): Reac
|
||||
api.query.shared?.activeValidatorIndices
|
||||
], optionsMulti);
|
||||
const hrmp = useHrmp();
|
||||
const hasLinksMap = useIsParasLinked(ids);
|
||||
|
||||
const headerRef = useRef([
|
||||
[t('parachains'), 'start', 2],
|
||||
@ -163,8 +180,8 @@ function Parachains ({ actionsQueue, ids, leasePeriod, scheduled }: Props): Reac
|
||||
);
|
||||
|
||||
const knownIds = useMemo(
|
||||
() => ids?.map((id): [ParaId, string] => [id, id.toString()]),
|
||||
[ids]
|
||||
() => extractIds(hasLinksMap, ids),
|
||||
[ids, hasLinksMap]
|
||||
);
|
||||
|
||||
const nextActions = useMemo(
|
||||
@ -183,7 +200,7 @@ function Parachains ({ actionsQueue, ids, leasePeriod, scheduled }: Props): Reac
|
||||
empty={knownIds && t<string>('There are no registered parachains')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
{knownIds?.map(([id, key], index): React.ReactNode => (
|
||||
{knownIds?.map(([id, key]): React.ReactNode => (
|
||||
<Parachain
|
||||
bestNumber={bestNumber}
|
||||
channelDst={hrmp?.dst[id.toString()]}
|
||||
@ -197,7 +214,7 @@ function Parachains ({ actionsQueue, ids, leasePeriod, scheduled }: Props): Reac
|
||||
leasePeriod={leasePeriod}
|
||||
nextAction={nextActions[key]}
|
||||
sessionValidators={validators}
|
||||
validators={validatorMap[index]}
|
||||
validators={validatorMap[key]}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
|
||||
@ -6,10 +6,10 @@ 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 React, { useCallback, useRef } from 'react';
|
||||
|
||||
import { Table } from '@polkadot/react-components';
|
||||
import { useApi, useCall } from '@polkadot/react-hooks';
|
||||
import { useApi, useCall, useIsParasLinked } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
import Actions from './Actions';
|
||||
@ -24,47 +24,60 @@ interface Props {
|
||||
|
||||
type ParaMap = [ParaId, LeaseInfo[]][];
|
||||
|
||||
const optLeases = {
|
||||
transform: ([[paraIds], leases]: [[ParaId[]], Option<ITuple<[AccountId, BalanceOf]>>[][]]): ParaMap =>
|
||||
paraIds
|
||||
.reduce((all: ParaMap, id, index): ParaMap => {
|
||||
all.push([
|
||||
id,
|
||||
leases[index]
|
||||
.map((optLease, period): LeaseInfo | null => {
|
||||
if (optLease.isNone) {
|
||||
return null;
|
||||
}
|
||||
function extractParaMap (hasLinksMap: Record<string, boolean>, paraIds: ParaId[], leases: Option<ITuple<[AccountId, BalanceOf]>>[][]): ParaMap {
|
||||
return 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();
|
||||
const [accountId, balance] = optLease.unwrap();
|
||||
|
||||
return {
|
||||
accountId,
|
||||
balance,
|
||||
period
|
||||
};
|
||||
})
|
||||
.filter((item): item is LeaseInfo => !!item)
|
||||
]);
|
||||
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
|
||||
};
|
||||
return all;
|
||||
}, [])
|
||||
.sort(([aId, aLeases], [bId, bLeases]): number => {
|
||||
const aKnown = hasLinksMap[aId.toString()] || false;
|
||||
const bKnown = hasLinksMap[bId.toString()] || false;
|
||||
|
||||
return aLeases.length && bLeases.length
|
||||
? (aLeases[0].period - bLeases[0].period) || aId.cmp(bId)
|
||||
: aLeases.length
|
||||
? -1
|
||||
: bLeases.length
|
||||
? 1
|
||||
: aKnown === bKnown
|
||||
? aId.cmp(bId)
|
||||
: aKnown
|
||||
? -1
|
||||
: 1;
|
||||
});
|
||||
}
|
||||
|
||||
function Parathreads ({ actionsQueue, className, ids, leasePeriod }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const leaseMap = useCall<ParaMap>(ids && api.query.slots.leases.multi, [ids], optLeases);
|
||||
const hasLinksMap = useIsParasLinked(ids);
|
||||
const leaseMap = useCall<ParaMap>(ids && api.query.slots.leases.multi, [ids], {
|
||||
transform: useCallback(
|
||||
([[paraIds], leases]: [[ParaId[]], Option<ITuple<[AccountId, BalanceOf]>>[][]]): ParaMap =>
|
||||
extractParaMap(hasLinksMap, paraIds, leases),
|
||||
[hasLinksMap]
|
||||
),
|
||||
withParamsTransform: true
|
||||
});
|
||||
|
||||
const headerRef = useRef([
|
||||
[t('parathreads'), 'start', 3],
|
||||
|
||||
@ -86,6 +86,7 @@ export interface WinnerData {
|
||||
accountId: string;
|
||||
firstSlot: BN;
|
||||
isCrowdloan: boolean;
|
||||
key: string;
|
||||
lastSlot: BN;
|
||||
paraId: ParaId;
|
||||
value: BN;
|
||||
|
||||
@ -138,6 +138,7 @@ const optFundMulti = {
|
||||
firstSlot: info.firstSlot,
|
||||
info,
|
||||
isCrowdloan: true,
|
||||
key: paraId.toString(),
|
||||
lastSlot: info.lastSlot,
|
||||
paraId,
|
||||
value: info.raised
|
||||
|
||||
@ -41,6 +41,7 @@ function extractWinners (auctionInfo: AuctionInfo, optData: Option<WinningData>)
|
||||
accountId: accountId.toString(),
|
||||
firstSlot: period.addn(first),
|
||||
isCrowdloan: u8aEq(CROWD_PREFIX, accountId.subarray(0, CROWD_PREFIX.length)),
|
||||
key: paraId.toString(),
|
||||
lastSlot: period.addn(last),
|
||||
paraId,
|
||||
value
|
||||
|
||||
@ -33,7 +33,7 @@ export { useOwnEraRewards } from './useOwnEraRewards';
|
||||
export { useOwnStashes, useOwnStashIds } from './useOwnStashes';
|
||||
export { useOwnStashInfos } from './useOwnStashInfos';
|
||||
export { useParaApi } from './useParaApi';
|
||||
export { useParaEndpoints } from './useParaEndpoints';
|
||||
export { useIsParasLinked, useParaEndpoints } from './useParaEndpoints';
|
||||
export { usePassword } from './usePassword';
|
||||
export { useRegistrars } from './useRegistrars';
|
||||
export { useSavedFlags } from './useSavedFlags';
|
||||
|
||||
@ -11,19 +11,43 @@ import { bnToBn } from '@polkadot/util';
|
||||
|
||||
import { useApi } from './useApi';
|
||||
|
||||
function extractResults (genesisHash: string, paraId: BN | number): LinkOption[] {
|
||||
function extractRelayEndpoints (genesisHash: string): LinkOption[] {
|
||||
return createWsEndpoints((key: string, value: string | undefined) => value || key).filter(({ genesisHashRelay }) =>
|
||||
genesisHash === genesisHashRelay
|
||||
);
|
||||
}
|
||||
|
||||
function extractParaEndpoints (allEndpoints: LinkOption[], paraId: BN | number): LinkOption[] {
|
||||
const numId = bnToBn(paraId).toNumber();
|
||||
|
||||
return createWsEndpoints((key: string, value: string | undefined) => value || key).filter(({ genesisHashRelay, paraId }) =>
|
||||
paraId === numId && genesisHashRelay === genesisHash
|
||||
return allEndpoints.filter(({ paraId }) => paraId === numId);
|
||||
}
|
||||
|
||||
function useRelayEndpoints (): LinkOption[] {
|
||||
const { api } = useApi();
|
||||
|
||||
return useMemo(
|
||||
() => extractRelayEndpoints(api.genesisHash.toHex()),
|
||||
[api]
|
||||
);
|
||||
}
|
||||
|
||||
export function useParaEndpoints (paraId: BN | number): LinkOption[] {
|
||||
const { api } = useApi();
|
||||
const endpoints = useRelayEndpoints();
|
||||
|
||||
return useMemo(
|
||||
() => extractResults(api.genesisHash.toHex(), paraId),
|
||||
[api, paraId]
|
||||
() => extractParaEndpoints(endpoints, paraId),
|
||||
[endpoints, paraId]
|
||||
);
|
||||
}
|
||||
|
||||
export function useIsParasLinked (ids?: (BN | number)[] | null): Record<string, boolean> {
|
||||
const endpoints = useRelayEndpoints();
|
||||
|
||||
return useMemo(
|
||||
() => ids
|
||||
? ids.reduce((all: Record<string, boolean>, id) => ({ ...all, [id.toString()]: extractParaEndpoints(endpoints, id).length !== 0 }), {})
|
||||
: {},
|
||||
[endpoints, ids]
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user