Rebag on upper limit breached (#7269)

* Mrege prev/curr loadable bags

* Rebag on upper limit breached
This commit is contained in:
Jaco 2022-03-30 09:34:04 +02:00 committed by GitHub
parent 2a8ceb76d5
commit 9187f68bd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 67 additions and 36 deletions

View File

@ -1,9 +1,9 @@
// Copyright 2017-2022 @polkadot/app-staking authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { u64 } from '@polkadot/types';
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 React, { useEffect, useState } from 'react';
@ -17,12 +17,12 @@ import useBagEntries from './useBagEntries';
import useBonded from './useBonded';
interface Props {
id: u64;
info: PalletBagsListListBag;
stashNodes?: StashNode[];
upper: BN;
}
function Bag ({ id, info, stashNodes }: Props): React.ReactElement<Props> {
function Bag ({ info, stashNodes, upper }: Props): React.ReactElement<Props> {
const [[headId, trigger], setHeadId] = useState<[AccountId32 | null, number]>([null, 0]);
const [isLoading, setLoading] = useState(true);
const [isCompleted, list] = useBagEntries(headId, trigger);
@ -43,7 +43,7 @@ function Bag ({ id, info, stashNodes }: Props): React.ReactElement<Props> {
return (
<tr>
<td className='number'><FormatBalance value={id} /></td>
<td className='number'><FormatBalance value={upper} /></td>
<td className='address'>{info.head.isSome && <AddressMini value={info.head} />}</td>
<td className='address'>{info.tail.isSome && <AddressMini value={info.tail} />}</td>
<td className='address'>
@ -53,6 +53,7 @@ function Bag ({ id, info, stashNodes }: Props): React.ReactElement<Props> {
key={stashId}
list={bonded}
stashId={stashId}
upper={upper}
/>
))}
</td>

View File

@ -1,6 +1,7 @@
// Copyright 2017-2022 @polkadot/app-staking authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { BN } from '@polkadot/util';
import type { ListNode } from './types';
import React, { useMemo } from 'react';
@ -16,21 +17,36 @@ interface Props {
isLoading: boolean;
list?: ListNode[];
stashId: string;
upper: BN;
}
function findEntry (stashId: string, list: ListNode[] = []): [ListNode | null, boolean, number] {
const entry = list.find((o) => o.stashId === stashId) || null;
const other = (entry && entry.jump && list.find((o) => o.stashId === entry.jump)) || null;
return [entry, !!other, entry && other ? entry.index - other.index : 0];
interface Entry {
canJump: boolean;
canRebag: boolean;
jumpCount: number;
stashInfo: ListNode | null;
}
function Stash ({ className, isLoading, list, stashId }: Props): React.ReactElement<Props> {
function findEntry (upper: BN, stashId: string, list: ListNode[] = []): Entry {
const stashInfo = list.find((o) => o.stashId === stashId) || null;
const other = (stashInfo && stashInfo.jump && list.find((o) => o.stashId === stashInfo.jump)) || null;
return {
canJump: !!other,
canRebag: !!stashInfo && stashInfo.bonded.gt(upper),
jumpCount: stashInfo && other
? (stashInfo.index - other.index)
: 0,
stashInfo
};
}
function Stash ({ className, isLoading, list, stashId, upper }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const [stashInfo, canJump, jumpCount] = useMemo(
() => findEntry(stashId, list),
[list, stashId]
const { canJump, canRebag, jumpCount, stashInfo } = useMemo(
() => findEntry(upper, stashId, list),
[list, stashId, upper]
);
return (
@ -39,14 +55,31 @@ function Stash ({ className, isLoading, list, stashId }: Props): React.ReactElem
value={stashId}
withBonded
/>
<TxButton
accountId={stashInfo?.stashId}
icon='caret-up'
isDisabled={!canJump || isLoading}
label={t<string>('Move up {{jumpCount}}', { replace: { jumpCount } })}
params={[stashInfo?.jump]}
tx={api.tx.bagsList.putInFrontOf}
/>
{stashInfo && (
canRebag
? (
<TxButton
accountId={stashInfo.stashId}
icon='refresh'
isDisabled={isLoading}
label={t<string>('Rebag')}
params={[stashInfo.stashId]}
tx={api.tx.bagsList.rebag}
/>
)
: canJump
? (
<TxButton
accountId={stashInfo.stashId}
icon='caret-up'
isDisabled={isLoading}
label={t<string>('Move up {{jumpCount}}', { replace: { jumpCount } })}
params={[stashInfo.jump]}
tx={api.tx.bagsList.putInFrontOf}
/>
)
: null
)}
</div>
);
}
@ -55,9 +88,4 @@ export default React.memo(styled(Stash)`
.ui--AddressMini {
vertical-align: middle;
}
.ui--Button.isDisabled {
cursor: default;
opacity: 0;
}
`);

View File

@ -1,7 +1,7 @@
// Copyright 2017-2022 @polkadot/app-staking authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { u64 } from '@polkadot/types';
import type { BN } from '@polkadot/util';
import React from 'react';
@ -12,7 +12,7 @@ import { useTranslation } from '../translate';
interface Props {
className?: string;
ids?: u64[];
ids?: BN[];
}
function Summary ({ className = '', ids }: Props): React.ReactElement<Props> {

View File

@ -63,10 +63,10 @@ function Bags ({ ownStashes }: Props): React.ReactElement<Props> {
>
{sorted && sorted.map(({ id, info, key }) => (
<Bag
id={id}
info={info}
key={key}
stashNodes={nodes[key]}
upper={id}
/>
))}
</Table>

View File

@ -2,15 +2,16 @@
// SPDX-License-Identifier: Apache-2.0
import type { StorageKey, u64 } from '@polkadot/types';
import type { BN } from '@polkadot/util';
import { createNamedHook, useApi, useMapKeys } from '@polkadot/react-hooks';
const keyOptions = {
transform: (keys: StorageKey<[u64]>[]): u64[] =>
transform: (keys: StorageKey<[u64]>[]): BN[] =>
keys.map(({ args: [id] }) => id)
};
function useBagsIdsImpl (): u64[] | undefined {
function useBagsIdsImpl (): BN[] | undefined {
const { api } = useApi();
return useMapKeys(api.query.bagsList.listBags, keyOptions);

View File

@ -1,23 +1,24 @@
// Copyright 2017-2022 @polkadot/app-staking authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { Option, u64 } from '@polkadot/types';
import type { Option } from '@polkadot/types';
import type { PalletBagsListListBag } from '@polkadot/types/lookup';
import type { BN } from '@polkadot/util';
import { useEffect, useState } from 'react';
import { createNamedHook, useApi, useCall } from '@polkadot/react-hooks';
interface Result {
id: u64;
id: BN;
info: PalletBagsListListBag;
key: string;
}
const multiOptions = {
transform: ([[ids], opts]: [[u64[]], Option<PalletBagsListListBag>[]]): Result[] =>
transform: ([[ids], opts]: [[BN[]], Option<PalletBagsListListBag>[]]): Result[] =>
ids
.map((id, index): [u64, Option<PalletBagsListListBag>] => [id, opts[index]])
.map((id, index): [BN, Option<PalletBagsListListBag>] => [id, opts[index]])
.filter(([, o]) => o.isSome)
.map(([id, o]): Result => ({ id, info: o.unwrap(), key: id.toString() })),
withParamsTransform: true
@ -33,7 +34,7 @@ function merge (prev: Result[] | undefined, curr: Result[]): Result[] {
);
}
function useBagsListImpl (ids?: u64[]): Result[] | undefined {
function useBagsListImpl (ids?: BN[]): Result[] | undefined {
const { api } = useApi();
const [result, setResult] = useState<Result[] | undefined>();
const query = useCall(ids && ids.length !== 0 && api.query.bagsList.listBags.multi, [ids], multiOptions);