Perform per-loaded bag rebag calculations (#7288)

This commit is contained in:
Jaco 2022-04-02 09:04:00 +02:00 committed by GitHub
parent 7502a148e4
commit 97b4217610
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 15 deletions

View File

@ -4,7 +4,7 @@
import type { AccountId32 } from '@polkadot/types/interfaces';
import type { PalletBagsListListBag } from '@polkadot/types/lookup';
import type { BN } from '@polkadot/util';
import type { StashNode } from './types';
import type { ListNode, StashNode } from './types';
import React, { useEffect, useState } from 'react';
@ -24,8 +24,21 @@ interface Props {
upper: BN;
}
function getRebags (bonded: ListNode[], stashNodes: StashNode[], lower: BN, upper: BN): string[] {
return bonded
.filter(({ bonded, stashId }) =>
(
bonded.gt(upper) ||
bonded.lt(lower)
) &&
stashNodes.every((n) => n.stashId !== stashId)
)
.map(({ stashId }) => stashId);
}
function Bag ({ info, lower, stashNodes, upper }: Props): React.ReactElement<Props> {
const [[headId, trigger], setHeadId] = useState<[AccountId32 | null, number]>([null, 0]);
const [, setRebags] = useState<string[]>([]);
const [isLoading, setLoading] = useState(true);
const [isCompleted, list] = useBagEntries(headId, trigger);
const bonded = useBonded(list);
@ -43,6 +56,16 @@ function Bag ({ info, lower, stashNodes, upper }: Props): React.ReactElement<Pro
);
}, [bonded, isCompleted, stashNodes]);
// TODO: Currently not used, but calculated. This is the list of stashes that
// should be rebagged (need to provide a rebag modal to move all these at once)
useEffect((): void => {
// NOTE: There may be some issues if these are indeed rebagged - we need
// the StashNode to see if this item is indeed still within this list
!isLoading && bonded && stashNodes && setRebags(
getRebags(bonded, stashNodes, lower, upper)
);
}, [bonded, isLoading, lower, stashNodes, upper]);
return (
<tr>
<td className='number' />

View File

@ -70,12 +70,10 @@ function Bags ({ ownStashes }: Props): React.ReactElement<Props> {
value={filterIndex}
/>
</Button.Group>
{(
<article className='warning centered'>
<p>{t('The All bags list is composed of bags that each describe a range of active bonded funds of the nominators. In each bag is a list of nodes that correspond to a nominator and their staked funds.')}</p>
<p>{t('Within the context of a single bag, nodes are not sorted by their stake, but instead placed in insertion order. In other words, the most recently inserted node will be the last node in the bag, regardless of stake. Events like staking rewards or slashes do not automatically put you in a different bag. The bags-list pallet comes with an important permissionless extrinsic: rebag. This allows anyone to specify another account that is in the wrong bag, and place it in the correct one.')}</p>
</article>
)}
<article className='warning centered'>
<p>{t('The All bags list is composed of bags that each describe a range of active bonded funds of the nominators. In each bag is a list of nodes that correspond to a nominator and their staked funds.')}</p>
<p>{t('Within the context of a single bag, nodes are not sorted by their stake, but instead placed in insertion order. In other words, the most recently inserted node will be the last node in the bag, regardless of stake. Events like staking rewards or slashes do not automatically put you in a different bag. The bags-list pallet comes with an important permissionless extrinsic: rebag. This allows anyone to specify another account that is in the wrong bag, and place it in the correct one.')}</p>
</article>
<Table
empty={filtered && t<string>('No available bags')}
emptySpinner={t<string>('Retrieving all available bags, this will take some time')}

View File

@ -6,7 +6,7 @@ import type { BN } from '@polkadot/util';
import { createNamedHook, useApi, useMapKeys } from '@polkadot/react-hooks';
const keyOptions = {
const KEY_OPTS = {
transform: (keys: StorageKey<[u64]>[]): BN[] =>
keys.map(({ args: [id] }) => id)
};
@ -14,7 +14,7 @@ const keyOptions = {
function useBagsIdsImpl (): BN[] | undefined {
const { api } = useApi();
return useMapKeys(api.query.bagsList.listBags, keyOptions);
return useMapKeys(api.query.bagsList.listBags, KEY_OPTS);
}
export default createNamedHook('useBagsIds', useBagsIdsImpl);

View File

@ -11,7 +11,7 @@ import { useEffect, useState } from 'react';
import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
import { BN_ZERO } from '@polkadot/util';
const multiOptions = {
const MULTI_OPTS = {
transform: ([[ids], opts]: [[BN[]], Option<PalletBagsListListBag>[]]): BagInfo[] => {
const sorted = ids
.map((id, index): [BN, Option<PalletBagsListListBag>] => [id, opts[index]])
@ -48,7 +48,7 @@ function merge (prev: BagInfo[] | undefined, curr: BagInfo[]): BagInfo[] {
function useBagsListImpl (ids?: BN[]): BagInfo[] | undefined {
const { api } = useApi();
const [result, setResult] = useState<BagInfo[] | undefined>();
const query = useCall(ids && ids.length !== 0 && api.query.bagsList.listBags.multi, [ids], multiOptions);
const query = useCall(ids && ids.length !== 0 && api.query.bagsList.listBags.multi, [ids], MULTI_OPTS);
useEffect((): void => {
query && setResult((prev) => merge(prev, query));

View File

@ -9,7 +9,7 @@ import { useEffect, useState } from 'react';
import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
const multiOptions = {
const MULTI_OPTS = {
transform: (opts: Option<PalletBagsListListNode>[]): BagMap =>
opts
.filter((o) => o.isSome)
@ -42,7 +42,7 @@ function merge (prev: BagMap | undefined, curr: BagMap): BagMap {
function useBagsNodesImpl (stashIds: string[]): BagMap | undefined {
const { api } = useApi();
const [result, setResult] = useState<BagMap | undefined>();
const query = useCall(api.query.bagsList.listNodes.multi, [stashIds], multiOptions);
const query = useCall(api.query.bagsList.listNodes.multi, [stashIds], MULTI_OPTS);
useEffect((): void => {
query && setResult((prev) => merge(prev, query));

View File

@ -7,7 +7,7 @@ import type { ListNode } from './types';
import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
const deriveOpts = {
const DERIVE_OPTS = {
transform: (all: DeriveStakingAccount[]): ListNode[] => {
const infos = all.map(({ stakingLedger, stashId }, index): ListNode => ({
bonded: stakingLedger.active.unwrap(),
@ -34,7 +34,7 @@ const deriveOpts = {
function useBondedImpl (ids?: false | AccountId32[]): ListNode[] | undefined {
const { api } = useApi();
return useCall(ids && ids.length !== 0 && api.derive.staking.accounts, [ids], deriveOpts);
return useCall(ids && ids.length !== 0 && api.derive.staking.accounts, [ids], DERIVE_OPTS);
}
export default createNamedHook('useBonded', useBondedImpl);