Display tip warning on no recipient balance (#6393)
This commit is contained in:
parent
720f13844c
commit
8770390a58
@ -2,7 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { AccountId, Balance, BlockNumber, OpenTip, OpenTipTo225 } from '@polkadot/types/interfaces';
|
||||
import type { AccountId, Balance, BlockNumber, OpenTipTo225 } from '@polkadot/types/interfaces';
|
||||
import type { PalletTipsOpenTip } from '@polkadot/types/lookup';
|
||||
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
@ -25,7 +26,7 @@ interface Props {
|
||||
members: string[];
|
||||
onSelect: (hash: string, isSelected: boolean, value: BN) => void;
|
||||
onlyUntipped: boolean;
|
||||
tip: OpenTip | OpenTipTo225;
|
||||
tip: PalletTipsOpenTip | OpenTipTo225;
|
||||
}
|
||||
|
||||
interface TipState {
|
||||
@ -38,11 +39,11 @@ interface TipState {
|
||||
median: BN;
|
||||
}
|
||||
|
||||
function isCurrentTip (tip: OpenTip | OpenTipTo225): tip is OpenTip {
|
||||
return !!(tip as OpenTip)?.findersFee;
|
||||
function isCurrentTip (tip: PalletTipsOpenTip | OpenTipTo225): tip is PalletTipsOpenTip {
|
||||
return !!(tip as PalletTipsOpenTip)?.findersFee;
|
||||
}
|
||||
|
||||
function extractTipState (tip: OpenTip | OpenTipTo225, allAccounts: string[]): TipState {
|
||||
function extractTipState (tip: PalletTipsOpenTip | OpenTipTo225, allAccounts: string[]): TipState {
|
||||
const closesAt = tip.closes.unwrapOr(null);
|
||||
let finder: AccountId | null = null;
|
||||
let deposit: Balance | null = null;
|
||||
@ -106,6 +107,7 @@ function Tip ({ bestNumber, className = '', defaultId, hash, isMember, members,
|
||||
}
|
||||
|
||||
const { reason, tips, who } = tip;
|
||||
const recipient = who.toString();
|
||||
|
||||
return (
|
||||
<tr className={className}>
|
||||
@ -166,6 +168,7 @@ function Tip ({ bestNumber, className = '', defaultId, hash, isMember, members,
|
||||
isTipped={isTipped}
|
||||
median={median}
|
||||
members={members}
|
||||
recipient={recipient}
|
||||
/>
|
||||
)
|
||||
: (
|
||||
|
||||
@ -2,11 +2,12 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { DeriveBalancesAll } from '@polkadot/api-derive/types';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Button, InputAddress, InputBalance, Modal, TxButton } from '@polkadot/react-components';
|
||||
import { useApi, useToggle } from '@polkadot/react-hooks';
|
||||
import { Button, InputAddress, InputBalance, MarkWarning, Modal, TxButton } from '@polkadot/react-components';
|
||||
import { useApi, useCall, useToggle } from '@polkadot/react-hooks';
|
||||
|
||||
import { useTranslation } from '../translate';
|
||||
|
||||
@ -17,14 +18,23 @@ interface Props {
|
||||
isTipped: boolean;
|
||||
median: BN;
|
||||
members: string[];
|
||||
recipient: string;
|
||||
}
|
||||
|
||||
function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members }: Props): React.ReactElement<Props> {
|
||||
const transformBalance = {
|
||||
transform: ({ freeBalance, reservedBalance }: DeriveBalancesAll): BN =>
|
||||
freeBalance.add(reservedBalance)
|
||||
};
|
||||
|
||||
function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members, recipient }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const [isOpen, toggleOpen] = useToggle();
|
||||
const [accountId, setAccountId] = useState<string | null>(defaultId);
|
||||
const [value, setValue] = useState<BN | undefined>();
|
||||
const totalBalance = useCall<BN>(api.derive.balances?.all, [recipient], transformBalance);
|
||||
|
||||
const tipTx = (api.tx.tips || api.tx.treasury).tip;
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -41,7 +51,7 @@ function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members }: P
|
||||
isDisabled={!isMember || !isTipped}
|
||||
isIcon
|
||||
params={[hash, median]}
|
||||
tx={(api.tx.tips || api.tx.treasury).tip}
|
||||
tx={tipTx}
|
||||
withoutLink
|
||||
/>
|
||||
{isOpen && (
|
||||
@ -70,6 +80,9 @@ function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members }: P
|
||||
label={t<string>('value')}
|
||||
onChange={setValue}
|
||||
/>
|
||||
{totalBalance && totalBalance.isZero() && (
|
||||
<MarkWarning content={t<string>('The recipient account has no balance, ensure the tip is more than the existential deposit to create the account.')} />
|
||||
)}
|
||||
</Modal.Columns>
|
||||
</Modal.Content>
|
||||
<Modal.Actions>
|
||||
@ -80,7 +93,7 @@ function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members }: P
|
||||
label={t<string>('Submit tip')}
|
||||
onStart={toggleOpen}
|
||||
params={[hash, value]}
|
||||
tx={(api.tx.tips || api.tx.treasury).tip}
|
||||
tx={tipTx}
|
||||
/>
|
||||
</Modal.Actions>
|
||||
</Modal>
|
||||
|
||||
@ -3,7 +3,8 @@
|
||||
|
||||
import type BN from 'bn.js';
|
||||
import type { Option } from '@polkadot/types';
|
||||
import type { OpenTip, OpenTipTo225 } from '@polkadot/types/interfaces';
|
||||
import type { OpenTipTo225 } from '@polkadot/types/interfaces';
|
||||
import type { PalletTipsOpenTip } from '@polkadot/types/lookup';
|
||||
|
||||
import React, { useMemo, useRef, useState } from 'react';
|
||||
import styled from 'styled-components';
|
||||
@ -23,11 +24,11 @@ interface Props {
|
||||
onSelectTip: (hash: string, isSelected: boolean, value: BN) => void,
|
||||
}
|
||||
|
||||
type Tip = [string, OpenTip | OpenTipTo225];
|
||||
type Tip = [string, PalletTipsOpenTip | OpenTipTo225];
|
||||
|
||||
const TIP_OPTS = { withParams: true };
|
||||
|
||||
function extractTips (tipsWithHashes?: [[string[]], Option<OpenTip>[]], inHashes?: string[] | null): Tip[] | undefined {
|
||||
function extractTips (tipsWithHashes?: [[string[]], Option<PalletTipsOpenTip>[]], inHashes?: string[] | null): Tip[] | undefined {
|
||||
if (!tipsWithHashes || !inHashes) {
|
||||
return undefined;
|
||||
}
|
||||
@ -35,8 +36,8 @@ function extractTips (tipsWithHashes?: [[string[]], Option<OpenTip>[]], inHashes
|
||||
const [[hashes], optTips] = tipsWithHashes;
|
||||
|
||||
return optTips
|
||||
.map((opt, index): [string, OpenTip | null] => [hashes[index], opt.unwrapOr(null)])
|
||||
.filter((val): val is [string, OpenTip] => inHashes.includes(val[0]) && !!val[1])
|
||||
.map((opt, index): [string, PalletTipsOpenTip | null] => [hashes[index], opt.unwrapOr(null)])
|
||||
.filter((val): val is [string, PalletTipsOpenTip] => inHashes.includes(val[0]) && !!val[1])
|
||||
.sort((a, b) =>
|
||||
a[1].closes.isNone
|
||||
? b[1].closes.isNone
|
||||
@ -53,7 +54,7 @@ function Tips ({ className = '', defaultId, hashes, isMember, members, onSelectT
|
||||
const { api } = useApi();
|
||||
const [onlyUntipped, setOnlyUntipped] = useState(false);
|
||||
const bestNumber = useBestNumber();
|
||||
const tipsWithHashes = useCall<[[string[]], Option<OpenTip>[]]>(hashes && (api.query.tips || api.query.treasury).tips.multi, [hashes], TIP_OPTS);
|
||||
const tipsWithHashes = useCall<[[string[]], Option<PalletTipsOpenTip>[]]>(hashes && (api.query.tips || api.query.treasury).tips.multi, [hashes], TIP_OPTS);
|
||||
|
||||
const tips = useMemo(
|
||||
() => extractTips(tipsWithHashes, hashes),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user