diff --git a/packages/page-treasury/src/Tips/Tip.tsx b/packages/page-treasury/src/Tips/Tip.tsx
index dbeb84e34e..1139803dd4 100644
--- a/packages/page-treasury/src/Tips/Tip.tsx
+++ b/packages/page-treasury/src/Tips/Tip.tsx
@@ -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 (
@@ -166,6 +168,7 @@ function Tip ({ bestNumber, className = '', defaultId, hash, isMember, members,
isTipped={isTipped}
median={median}
members={members}
+ recipient={recipient}
/>
)
: (
diff --git a/packages/page-treasury/src/Tips/TipEndorse.tsx b/packages/page-treasury/src/Tips/TipEndorse.tsx
index 5645777a54..375426b532 100644
--- a/packages/page-treasury/src/Tips/TipEndorse.tsx
+++ b/packages/page-treasury/src/Tips/TipEndorse.tsx
@@ -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 {
+const transformBalance = {
+ transform: ({ freeBalance, reservedBalance }: DeriveBalancesAll): BN =>
+ freeBalance.add(reservedBalance)
+};
+
+function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members, recipient }: Props): React.ReactElement {
const { t } = useTranslation();
const { api } = useApi();
const [isOpen, toggleOpen] = useToggle();
const [accountId, setAccountId] = useState(defaultId);
const [value, setValue] = useState();
+ const totalBalance = useCall(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('value')}
onChange={setValue}
/>
+ {totalBalance && totalBalance.isZero() && (
+ ('The recipient account has no balance, ensure the tip is more than the existential deposit to create the account.')} />
+ )}
@@ -80,7 +93,7 @@ function TipEndorse ({ defaultId, hash, isMember, isTipped, median, members }: P
label={t('Submit tip')}
onStart={toggleOpen}
params={[hash, value]}
- tx={(api.tx.tips || api.tx.treasury).tip}
+ tx={tipTx}
/>
diff --git a/packages/page-treasury/src/Tips/Tips.tsx b/packages/page-treasury/src/Tips/Tips.tsx
index adb4c1dee1..fb01493df3 100644
--- a/packages/page-treasury/src/Tips/Tips.tsx
+++ b/packages/page-treasury/src/Tips/Tips.tsx
@@ -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[]], inHashes?: string[] | null): Tip[] | undefined {
+function extractTips (tipsWithHashes?: [[string[]], Option[]], inHashes?: string[] | null): Tip[] | undefined {
if (!tipsWithHashes || !inHashes) {
return undefined;
}
@@ -35,8 +36,8 @@ function extractTips (tipsWithHashes?: [[string[]], Option[]], 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[]]>(hashes && (api.query.tips || api.query.treasury).tips.multi, [hashes], TIP_OPTS);
+ const tipsWithHashes = useCall<[[string[]], Option[]]>(hashes && (api.query.tips || api.query.treasury).tips.multi, [hashes], TIP_OPTS);
const tips = useMemo(
() => extractTips(tipsWithHashes, hashes),