From f6800a4bd5ea20766d3474e18a53e4c254e41331 Mon Sep 17 00:00:00 2001 From: Thibaut Sardan Date: Thu, 10 Oct 2024 12:28:18 +0100 Subject: [PATCH] delegation card logic isolated --- src/components/DelegationCard.tsx | 103 +++++++++++++++++++++++++++++ src/components/MyDelegations.tsx | 106 +++--------------------------- src/pages/Delegate/index.tsx | 1 + 3 files changed, 114 insertions(+), 96 deletions(-) create mode 100644 src/components/DelegationCard.tsx diff --git a/src/components/DelegationCard.tsx b/src/components/DelegationCard.tsx new file mode 100644 index 0000000..86ca99e --- /dev/null +++ b/src/components/DelegationCard.tsx @@ -0,0 +1,103 @@ +import { useDelegates } from '@/contexts/DelegatesContext' +import { CurrentDelegation, useLocks } from '@/contexts/LocksContext' +import { Card } from '@polkadot-ui/react' +import { useCallback, useMemo, useState } from 'react' +import { DelegationByAmountConviction } from './DelegationByAmountConviction' +import { AddressDisplay } from './ui/address-display' +import { Button } from './ui/button' +import { useGetSigningCallback } from '@/hooks/useGetSigningCallback' +import { useNetwork } from '@/contexts/NetworkContext' +import { useAccounts } from '@/contexts/AccountsContext' +import { Transaction } from 'polkadot-api' + +interface Props { + delegateAddress: string + amountConvictionMap: Record +} + +export const DelegationCard = ({ + delegateAddress, + amountConvictionMap, +}: Props) => { + const { getDelegateByAddress } = useDelegates() + const knownDelegate = getDelegateByAddress(delegateAddress) + const [isUndelegating, setIsUndelegating] = useState(false) + const { api } = useNetwork() + const { delegations, refreshLocks } = useLocks() + const { selectedAccount } = useAccounts() + const tx = useMemo(() => { + if (!api || !delegations) { + return + } + + const tracks = delegations[delegateAddress].map((d) => d.trackId) + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let tx: Transaction + + if (tracks.length === 1) { + tx = api.tx.ConvictionVoting.undelegate({ class: tracks[0] }) + } else { + const batchTx = tracks.map( + (t) => api.tx.ConvictionVoting.undelegate({ class: t }).decodedCall, + ) + tx = api.tx.Utility.batch({ calls: batchTx }) + } + + return tx + }, [api, delegateAddress, delegations]) + + const getSubscriptionCallback = useGetSigningCallback() + const subscriptionCallback = useMemo( + () => + getSubscriptionCallback({ + onError: () => { + setIsUndelegating(false) + }, + onInBlock: () => { + setIsUndelegating(false) + refreshLocks() + }, + }), + [getSubscriptionCallback, refreshLocks], + ) + + const onUndelegate = useCallback(() => { + if (!tx || !selectedAccount) return + + setIsUndelegating(true) + + tx.signSubmitAndWatch(selectedAccount.polkadotSigner, { + at: 'best', + }).subscribe(subscriptionCallback) + }, [selectedAccount, subscriptionCallback, tx]) + + return ( + +
+ {knownDelegate?.name ? ( +
+ +
+ {knownDelegate.name} +
+
+ ) : ( + + )} + +
+ +
+ ) +} diff --git a/src/components/MyDelegations.tsx b/src/components/MyDelegations.tsx index 97e118d..d12020b 100644 --- a/src/components/MyDelegations.tsx +++ b/src/components/MyDelegations.tsx @@ -2,27 +2,16 @@ import { Card } from '@polkadot-ui/react' import { Title } from './ui/title' import { TreePalm } from 'lucide-react' import { CurrentDelegation, useLocks } from '@/contexts/LocksContext' -import { useCallback, useMemo, useState } from 'react' +import { useMemo } from 'react' import { Skeleton } from './ui/skeleton' -import { useDelegates } from '@/contexts/DelegatesContext' -import { useNetwork } from '@/contexts/NetworkContext' -import { AddressDisplay } from './ui/address-display' -import { Button } from './ui/button' -import { useAccounts } from '@/contexts/AccountsContext' -import { Transaction } from 'polkadot-api' -import { DelegationByAmountConviction } from './DelegationByAmountConviction' -import { useGetSigningCallback } from '@/hooks/useGetSigningCallback' +import { DelegationCard } from './DelegationCard' export const MyDelegations = () => { - const { api } = useNetwork() - const { delegations, refreshLocks } = useLocks() - const [delegateLoading, setDelegatesLoading] = useState([]) + const { delegations } = useLocks() const noDelegations = useMemo( () => !!delegations && Object.entries(delegations).length === 0, [delegations], ) - const { getDelegateByAddress } = useDelegates() - const { selectedAccount } = useAccounts() const delegationsByDelegateConvictionAmount = useMemo(() => { if (!delegations) return @@ -42,44 +31,6 @@ export const MyDelegations = () => { return result }, [delegations]) - const getSubscriptionCallback = useGetSigningCallback() - const onUndelegate = useCallback( - (delegate: string) => { - if (!api || !selectedAccount || !delegations) return - - setDelegatesLoading((prev) => [...prev, delegate]) - - const tracks = delegations[delegate].map((d) => d.trackId) - - // @ts-expect-error we can't strongly type this - let tx: Transaction - - if (tracks.length === 1) { - tx = api.tx.ConvictionVoting.undelegate({ class: tracks[0] }) - } else { - const batchTx = tracks.map( - (t) => api.tx.ConvictionVoting.undelegate({ class: t }).decodedCall, - ) - tx = api.tx.Utility.batch({ calls: batchTx }) - } - - const subscriptionCallback = getSubscriptionCallback({ - onError: () => { - setDelegatesLoading((prev) => prev.filter((id) => id !== delegate)) - }, - onInBlock: () => { - setDelegatesLoading((prev) => prev.filter((id) => id !== delegate)) - refreshLocks() - }, - }) - - tx.signSubmitAndWatch(selectedAccount.polkadotSigner, { - at: 'best', - }).subscribe(subscriptionCallback) - }, - [api, delegations, getSubscriptionCallback, refreshLocks, selectedAccount], - ) - return ( <> My Delegations @@ -99,50 +50,13 @@ export const MyDelegations = () => { ) : ( Object.entries(delegationsByDelegateConvictionAmount).map( - ([delegateAddress, amountConvictionMap]) => { - const knownDelegate = getDelegateByAddress(delegateAddress) - const isUndelegating = delegateLoading.includes(delegateAddress) - - return ( - - <> -
- {knownDelegate?.name ? ( -
- -
- {knownDelegate.name} -
-
- ) : ( - - )} - -
- - -
- ) - }, + ([delegateAddress, amountConvictionMap]) => ( + + ), ) )} diff --git a/src/pages/Delegate/index.tsx b/src/pages/Delegate/index.tsx index a692e46..4dc5717 100644 --- a/src/pages/Delegate/index.tsx +++ b/src/pages/Delegate/index.tsx @@ -209,6 +209,7 @@ export const Delegate = () => { setIsTxInitiated(false) return } + if (isExhaustsResourcesError) { setIsMultiTxDialogOpen(true) return