From 1a8bfaf17b4737318a927f42c3d9d12c612c1471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harrison=20Mendon=C3=A7a?= Date: Thu, 9 Jan 2025 13:40:17 -0300 Subject: [PATCH 1/5] feat: listen for the complete event --- apps/namadillo/src/App/Common/Timeline.tsx | 37 ++++------------- .../src/hooks/useTransactionCallbacks.tsx | 20 +++------ .../src/hooks/useTransactionNotifications.tsx | 15 +++---- apps/namadillo/src/types.ts | 5 ++- apps/namadillo/src/types/events.ts | 2 +- apps/namadillo/src/utils/index.ts | 41 +++++++++++++------ packages/config/eslint/react.js | 2 +- 7 files changed, 53 insertions(+), 69 deletions(-) diff --git a/apps/namadillo/src/App/Common/Timeline.tsx b/apps/namadillo/src/App/Common/Timeline.tsx index 4c616e3334..246153a2a0 100644 --- a/apps/namadillo/src/App/Common/Timeline.tsx +++ b/apps/namadillo/src/App/Common/Timeline.tsx @@ -15,42 +15,25 @@ type TransactionTimelineProps = { complete?: boolean; }; -type DisabledProps = { - disabled: boolean; -}; - -const StepConnector = ({ disabled }: DisabledProps): JSX.Element => ( - +const StepConnector = (): JSX.Element => ( + ); -const StepBullet = ({ disabled }: DisabledProps): JSX.Element => ( - +const StepBullet = (): JSX.Element => ( + ); const StepContent = ({ children, isCurrentStep, hasError, - disabled, }: React.PropsWithChildren & { isCurrentStep: boolean; hasError: boolean; - disabled: boolean; }): JSX.Element => (
{children} @@ -206,19 +189,15 @@ export const Timeline = ({ className={twMerge( clsx( "flex flex-col gap-1 items-center", - "text-center transition-all duration-150" + "text-center transition-all duration-150", + { "opacity-20": index > currentStepIndex } ) )} > - {index > 0 && ( - currentStepIndex} /> - )} - {step.bullet && ( - currentStepIndex} /> - )} + {index > 0 && } + {step.bullet && } currentStepIndex} hasError={!!hasError} > {step.children} diff --git a/apps/namadillo/src/hooks/useTransactionCallbacks.tsx b/apps/namadillo/src/hooks/useTransactionCallbacks.tsx index bb24b4f44f..5767562ad2 100644 --- a/apps/namadillo/src/hooks/useTransactionCallbacks.tsx +++ b/apps/namadillo/src/hooks/useTransactionCallbacks.tsx @@ -35,9 +35,7 @@ export const useTransactionCallback = (): void => { useTransactionEventListener("Unbond.Success", onBalanceUpdate); useTransactionEventListener("Withdraw.Success", onBalanceUpdate); useTransactionEventListener("Redelegate.Success", onBalanceUpdate); - useTransactionEventListener("ClaimRewards.Success", onBalanceUpdate, [ - account?.address, - ]); + useTransactionEventListener("ClaimRewards.Success", onBalanceUpdate); useTransactionEventListener("VoteProposal.Success", () => { shouldUpdateProposal(true); @@ -56,18 +54,10 @@ export const useTransactionCallback = (): void => { "UnshieldingTransfer.Success", ], (e) => { - e.detail.data.forEach((dataList) => { - dataList.data.forEach((props) => { - const sourceAddress = "source" in props ? props.source : ""; - sourceAddress && - changeTransaction( - e.detail.tx.hash, - { - status: "success", - currentStep: TransferStep.Complete, - }, - sourceAddress - ); + e.detail.tx.forEach(({ hash }) => { + changeTransaction(hash, { + status: "success", + currentStep: TransferStep.Complete, }); }); } diff --git a/apps/namadillo/src/hooks/useTransactionNotifications.tsx b/apps/namadillo/src/hooks/useTransactionNotifications.tsx index dc7b5f0a1b..17302a3283 100644 --- a/apps/namadillo/src/hooks/useTransactionNotifications.tsx +++ b/apps/namadillo/src/hooks/useTransactionNotifications.tsx @@ -28,7 +28,7 @@ const getTotalAmountFromTransactionList = (txs: TxWithAmount[]): BigNumber => }, new BigNumber(0)); const parseTxsData = ( - tx: TxProps, + tx: TxProps | TxProps[], data: T[] ): { id: string; total: BigNumber } => { const id = createNotificationId(tx); @@ -357,11 +357,9 @@ export const useTransactionNotifications = (): void => { "UnshieldingTransfer.Error", ], (e) => { - const tx = e.detail.tx; - const data: TxWithAmount[] = e.detail.data[0].data; - const { id } = parseTxsData(tx, data); + const id = createNotificationId(e.detail.tx); clearPendingNotifications(id); - const storedTx = searchAllStoredTxByHash(tx.hash); + const storedTx = searchAllStoredTxByHash(e.detail.tx[0].hash); dispatchNotification({ id, type: "error", @@ -391,11 +389,10 @@ export const useTransactionNotifications = (): void => { "UnshieldingTransfer.Success", ], (e) => { - const tx = e.detail.tx; - const data: TxWithAmount[] = e.detail.data[0].data; - const { id } = parseTxsData(tx, data); + const id = createNotificationId(e.detail.tx); clearPendingNotifications(id); - const storedTx = searchAllStoredTxByHash(tx.hash); + clearPendingNotifications(id); + const storedTx = searchAllStoredTxByHash(e.detail.tx[0].hash); dispatchNotification({ id, title: "Transfer transaction succeeded", diff --git a/apps/namadillo/src/types.ts b/apps/namadillo/src/types.ts index 49deac9efb..718f54383c 100644 --- a/apps/namadillo/src/types.ts +++ b/apps/namadillo/src/types.ts @@ -235,22 +235,25 @@ export enum TransferStep { // Defines the steps in the Namada <> Namada transfer progress for tracking transaction stages. export const namadaTransferStages = { TransparentToShielded: [ - TransferStep.Sign, TransferStep.ZkProof, + TransferStep.Sign, TransferStep.TransparentToShielded, TransferStep.Complete, ] as const, ShieldedToTransparent: [ + TransferStep.ZkProof, TransferStep.Sign, TransferStep.ShieldedToTransparent, TransferStep.Complete, ] as const, ShieldedToShielded: [ + TransferStep.ZkProof, TransferStep.Sign, TransferStep.ShieldedToShielded, TransferStep.Complete, ] as const, TransparentToTransparent: [ + TransferStep.ZkProof, TransferStep.Sign, TransferStep.TransparentToTransparent, TransferStep.Complete, diff --git a/apps/namadillo/src/types/events.ts b/apps/namadillo/src/types/events.ts index c5506c61b9..c0532e3f50 100644 --- a/apps/namadillo/src/types/events.ts +++ b/apps/namadillo/src/types/events.ts @@ -32,7 +32,7 @@ export type TransactionEventHandlers = { export interface EventData extends CustomEvent { detail: { - tx: TxProps; + tx: TxProps[]; data: T[]; // If event is for PartialSuccess, use the following: successData?: T[]; diff --git a/apps/namadillo/src/utils/index.ts b/apps/namadillo/src/utils/index.ts index 74e2529ca1..cbab9d2cb3 100644 --- a/apps/namadillo/src/utils/index.ts +++ b/apps/namadillo/src/utils/index.ts @@ -3,8 +3,9 @@ import { ProposalStatus, ProposalTypeString } from "@namada/types"; import { localnetConfigAtom } from "atoms/integrations/atoms"; import BigNumber from "bignumber.js"; import { getDefaultStore } from "jotai"; +import { isEqual } from "lodash"; import namadaAssets from "namada-chain-registry/namada/assetlist.json"; -import { useEffect } from "react"; +import { useEffect, useRef } from "react"; export const proposalStatusToString = (status: ProposalStatus): string => { const statusText: Record = { @@ -38,32 +39,46 @@ export const proposalIdToString = (proposalId: bigint): string => export const useTransactionEventListener = ( event: T, - handler: (this: Window, ev: WindowEventMap[T]) => void, - deps: React.DependencyList = [] + handler: (event: WindowEventMap[T]) => void ): void => { + // `handlerRef` is useful to avoid recreating the listener every time + const handlerRef = useRef(handler); + handlerRef.current = handler; + useEffect(() => { - window.addEventListener(event, handler); + const callback: typeof handler = (event) => handlerRef.current(event); + window.addEventListener(event, callback); return () => { - window.removeEventListener(event, handler); + window.removeEventListener(event, callback); }; - }, deps); + }, [event]); }; export const useTransactionEventListListener = ( events: T[], - handler: (this: Window, ev: WindowEventMap[T]) => void, - deps: React.DependencyList = [] + handler: (event: WindowEventMap[T]) => void ): void => { + // `eventsRef` and `handlerRef` are useful to avoid recreating the listener every time + const eventsRef = useRef(events); + if (!isEqual(events, eventsRef.current)) { + eventsRef.current = events; + } + const eventsValue = eventsRef.current; + + const handlerRef = useRef(handler); + handlerRef.current = handler; + useEffect(() => { - events.forEach((event) => { - window.addEventListener(event, handler); + const callback: typeof handler = (event) => handlerRef.current(event); + eventsValue.forEach((event) => { + window.addEventListener(event, callback); }); return () => { - events.forEach((event) => { - window.removeEventListener(event, handler); + eventsValue.forEach((event) => { + window.removeEventListener(event, callback); }); }; - }, deps); + }, [eventsValue]); }; export const sumBigNumberArray = (numbers: BigNumber[]): BigNumber => { diff --git a/packages/config/eslint/react.js b/packages/config/eslint/react.js index f198c9c658..28190cd5ba 100644 --- a/packages/config/eslint/react.js +++ b/packages/config/eslint/react.js @@ -48,7 +48,7 @@ module.exports = { }, ], "react-hooks/rules-of-hooks": "error", - "react-hooks/exhaustive-deps": "off", + "react-hooks/exhaustive-deps": "warn", "react/prop-types": "off", }, settings: { From 4e70f121082e9c4547294361105c5be96bc7d9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harrison=20Mendon=C3=A7a?= Date: Thu, 9 Jan 2025 15:36:57 -0300 Subject: [PATCH 2/5] feat: fix lint --- packages/config/eslint/react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/config/eslint/react.js b/packages/config/eslint/react.js index 28190cd5ba..f198c9c658 100644 --- a/packages/config/eslint/react.js +++ b/packages/config/eslint/react.js @@ -48,7 +48,7 @@ module.exports = { }, ], "react-hooks/rules-of-hooks": "error", - "react-hooks/exhaustive-deps": "warn", + "react-hooks/exhaustive-deps": "off", "react/prop-types": "off", }, settings: { From ddebbf69d9ead456133268f6ac6178615e1959e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harrison=20Mendon=C3=A7a?= Date: Thu, 9 Jan 2025 16:59:15 -0300 Subject: [PATCH 3/5] feat: remove opacity when has error --- apps/namadillo/src/App/Common/Timeline.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/namadillo/src/App/Common/Timeline.tsx b/apps/namadillo/src/App/Common/Timeline.tsx index 246153a2a0..029e618f70 100644 --- a/apps/namadillo/src/App/Common/Timeline.tsx +++ b/apps/namadillo/src/App/Common/Timeline.tsx @@ -190,7 +190,7 @@ export const Timeline = ({ clsx( "flex flex-col gap-1 items-center", "text-center transition-all duration-150", - { "opacity-20": index > currentStepIndex } + { "opacity-20": index > currentStepIndex && !hasError } ) )} > From 1fea628b30a5425cd63d873cbb83bf57184ab641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harrison=20Mendon=C3=A7a?= Date: Thu, 9 Jan 2025 16:51:11 -0300 Subject: [PATCH 4/5] feat: add transfer watcher --- apps/namadillo/src/App/App.tsx | 2 +- .../namadillo/src/atoms/transactions/atoms.ts | 7 ++++ .../src/atoms/transactions/services.ts | 9 +++++ .../src/hooks/useTransactionWatcher.tsx | 37 ++++++++++++++++++- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/apps/namadillo/src/App/App.tsx b/apps/namadillo/src/App/App.tsx index c64606d513..25099f0b65 100644 --- a/apps/namadillo/src/App/App.tsx +++ b/apps/namadillo/src/App/App.tsx @@ -16,8 +16,8 @@ export function App(): JSX.Element { useExtensionEvents(); useTransactionNotifications(); useTransactionCallback(); - useRegistryFeatures(); useTransactionWatcher(); + useRegistryFeatures(); useServerSideEvents(); return ( diff --git a/apps/namadillo/src/atoms/transactions/atoms.ts b/apps/namadillo/src/atoms/transactions/atoms.ts index 82fab52383..c5bcef3c56 100644 --- a/apps/namadillo/src/atoms/transactions/atoms.ts +++ b/apps/namadillo/src/atoms/transactions/atoms.ts @@ -1,4 +1,5 @@ import { defaultAccountAtom } from "atoms/accounts"; +import { indexerApiAtom } from "atoms/api"; import { atom } from "jotai"; import { atomWithStorage } from "jotai/utils"; import { Address, TransferTransactionData } from "types"; @@ -6,6 +7,7 @@ import { filterCompleteTransactions, filterPendingTransactions, } from "./functions"; +import { fetchTransaction } from "./services"; export const transactionStorageKey = "namadillo:transactions"; @@ -31,3 +33,8 @@ export const completeTransactionsHistoryAtom = atom((get) => { const myTransactions = get(myTransactionHistoryAtom); return myTransactions.filter(filterCompleteTransactions); }); + +export const fetchTransactionAtom = atom((get) => { + const api = get(indexerApiAtom); + return (hash: string) => fetchTransaction(api, hash); +}); diff --git a/apps/namadillo/src/atoms/transactions/services.ts b/apps/namadillo/src/atoms/transactions/services.ts index 4143415fd6..0a22224872 100644 --- a/apps/namadillo/src/atoms/transactions/services.ts +++ b/apps/namadillo/src/atoms/transactions/services.ts @@ -1,4 +1,5 @@ import { IndexedTx, StargateClient } from "@cosmjs/stargate"; +import { DefaultApi, WrapperTransaction } from "@namada/indexer-client"; import { IbcTransferTransactionData } from "types"; type SearchByTagsQuery = { @@ -57,3 +58,11 @@ export const queryForAck = async ( ): Promise => { return await client.searchTx(getAckPacketsParams(ibcTx)); }; + +export const fetchTransaction = async ( + api: DefaultApi, + hash: string +): Promise => { + // indexer only accepts the hash as lowercase + return (await api.apiV1ChainWrapperTxIdGet(hash.toLowerCase())).data; +}; diff --git a/apps/namadillo/src/hooks/useTransactionWatcher.tsx b/apps/namadillo/src/hooks/useTransactionWatcher.tsx index 754ac43054..fa9728a287 100644 --- a/apps/namadillo/src/hooks/useTransactionWatcher.tsx +++ b/apps/namadillo/src/hooks/useTransactionWatcher.tsx @@ -1,16 +1,21 @@ +import { WrapperTransactionExitCodeEnum } from "@namada/indexer-client"; import { useQuery } from "@tanstack/react-query"; import { updateIbcTransferStatus, updateIbcWithdrawalStatus, } from "atoms/integrations"; -import { pendingTransactionsHistoryAtom } from "atoms/transactions"; +import { + fetchTransactionAtom, + pendingTransactionsHistoryAtom, +} from "atoms/transactions"; import { useAtomValue } from "jotai"; -import { IbcTransferTransactionData } from "types"; +import { IbcTransferTransactionData, TransferStep } from "types"; import { useTransactionActions } from "./useTransactionActions"; export const useTransactionWatcher = (): void => { const { changeTransaction } = useTransactionActions(); const pendingTransactions = useAtomValue(pendingTransactionsHistoryAtom); + const fetchTransaction = useAtomValue(fetchTransactionAtom); useQuery({ queryKey: ["transaction-status", pendingTransactions], @@ -19,6 +24,33 @@ export const useTransactionWatcher = (): void => { return Promise.allSettled( pendingTransactions.map(async (tx) => { switch (tx.type) { + case "TransparentToTransparent": + case "TransparentToShielded": + case "ShieldedToTransparent": + case "ShieldedToShielded": + { + const hash = tx.hash ?? ""; + const response = await fetchTransaction(hash); + const hasRejectedTx = response.innerTransactions.find( + ({ exitCode }) => + // indexer api is returning as "Rejected", but sdk type is "rejected" + exitCode.toLowerCase() === + WrapperTransactionExitCodeEnum.Rejected.toLowerCase() + ); + if (hasRejectedTx) { + changeTransaction(hash, { + status: "error", + errorMessage: "Transaction rejected", + }); + } else { + changeTransaction(hash, { + status: "success", + currentStep: TransferStep.Complete, + }); + } + } + break; + case "IbcToTransparent": case "IbcToShielded": await updateIbcTransferStatus( @@ -27,6 +59,7 @@ export const useTransactionWatcher = (): void => { changeTransaction ); break; + case "TransparentToIbc": await updateIbcWithdrawalStatus( tx as IbcTransferTransactionData, From c047fda2dbfd8df17f38b195915f4d884f061dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harrison=20Mendon=C3=A7a?= Date: Tue, 14 Jan 2025 11:55:10 -0300 Subject: [PATCH 5/5] feat: review --- apps/namadillo/package.json | 2 +- .../src/App/Common/SelectOptionModal.tsx | 7 +- .../src/atoms/transactions/services.ts | 3 +- .../src/hooks/useTransactionCallbacks.tsx | 32 ++--- .../src/hooks/useTransactionNotifications.tsx | 120 ++++++++---------- apps/namadillo/src/utils/index.ts | 28 ---- 6 files changed, 74 insertions(+), 118 deletions(-) diff --git a/apps/namadillo/package.json b/apps/namadillo/package.json index 0b0b6e1f00..01d931d246 100644 --- a/apps/namadillo/package.json +++ b/apps/namadillo/package.json @@ -1,6 +1,6 @@ { "name": "@namada/namadillo", - "version": "1.1.12", + "version": "1.2.0", "description": "Namadillo", "repository": "https://github.com/anoma/namada-interface/", "author": "Heliax Dev ", diff --git a/apps/namadillo/src/App/Common/SelectOptionModal.tsx b/apps/namadillo/src/App/Common/SelectOptionModal.tsx index 98a5fa1868..1cfd69ef06 100644 --- a/apps/namadillo/src/App/Common/SelectOptionModal.tsx +++ b/apps/namadillo/src/App/Common/SelectOptionModal.tsx @@ -1,4 +1,5 @@ import { Modal } from "@namada/components"; +import { Fragment } from "react"; import { AssetsModalCard } from "./AssetsModalCard"; import { ModalContainer } from "./ModalContainer"; @@ -30,14 +31,14 @@ export const SelectOptionModal = ({ >
    {items.map((item, index) => ( - <> -
  • + +
  • {item.children}
  • {index + 1 < items.length && (
  • )} - + ))}
diff --git a/apps/namadillo/src/atoms/transactions/services.ts b/apps/namadillo/src/atoms/transactions/services.ts index 0a22224872..10d408fe98 100644 --- a/apps/namadillo/src/atoms/transactions/services.ts +++ b/apps/namadillo/src/atoms/transactions/services.ts @@ -1,6 +1,7 @@ import { IndexedTx, StargateClient } from "@cosmjs/stargate"; import { DefaultApi, WrapperTransaction } from "@namada/indexer-client"; import { IbcTransferTransactionData } from "types"; +import { sanitizeAddress } from "utils/address"; type SearchByTagsQuery = { key: string; @@ -64,5 +65,5 @@ export const fetchTransaction = async ( hash: string ): Promise => { // indexer only accepts the hash as lowercase - return (await api.apiV1ChainWrapperTxIdGet(hash.toLowerCase())).data; + return (await api.apiV1ChainWrapperTxIdGet(sanitizeAddress(hash))).data; }; diff --git a/apps/namadillo/src/hooks/useTransactionCallbacks.tsx b/apps/namadillo/src/hooks/useTransactionCallbacks.tsx index 5767562ad2..2acdd6e33e 100644 --- a/apps/namadillo/src/hooks/useTransactionCallbacks.tsx +++ b/apps/namadillo/src/hooks/useTransactionCallbacks.tsx @@ -3,10 +3,8 @@ import { shouldUpdateBalanceAtom, shouldUpdateProposalAtom } from "atoms/etc"; import { claimableRewardsAtom, clearClaimRewards } from "atoms/staking"; import { useAtomValue, useSetAtom } from "jotai"; import { TransferStep } from "types"; -import { - useTransactionEventListener, - useTransactionEventListListener, -} from "utils"; +import { EventData } from "types/events"; +import { useTransactionEventListener } from "utils"; import { useTransactionActions } from "./useTransactionActions"; export const useTransactionCallback = (): void => { @@ -46,20 +44,16 @@ export const useTransactionCallback = (): void => { setTimeout(() => shouldUpdateProposal(false), timePolling); }); - useTransactionEventListListener( - [ - "TransparentTransfer.Success", - "ShieldedTransfer.Success", - "ShieldingTransfer.Success", - "UnshieldingTransfer.Success", - ], - (e) => { - e.detail.tx.forEach(({ hash }) => { - changeTransaction(hash, { - status: "success", - currentStep: TransferStep.Complete, - }); + const onTransferSuccess = (e: EventData): void => { + e.detail.tx.forEach(({ hash }) => { + changeTransaction(hash, { + status: "success", + currentStep: TransferStep.Complete, }); - } - ); + }); + }; + useTransactionEventListener("TransparentTransfer.Success", onTransferSuccess); + useTransactionEventListener("ShieldedTransfer.Success", onTransferSuccess); + useTransactionEventListener("ShieldingTransfer.Success", onTransferSuccess); + useTransactionEventListener("UnshieldingTransfer.Success", onTransferSuccess); }; diff --git a/apps/namadillo/src/hooks/useTransactionNotifications.tsx b/apps/namadillo/src/hooks/useTransactionNotifications.tsx index 17302a3283..6b634ae249 100644 --- a/apps/namadillo/src/hooks/useTransactionNotifications.tsx +++ b/apps/namadillo/src/hooks/useTransactionNotifications.tsx @@ -13,10 +13,8 @@ import { searchAllStoredTxByHash } from "atoms/transactions"; import BigNumber from "bignumber.js"; import invariant from "invariant"; import { useSetAtom } from "jotai"; -import { - useTransactionEventListener, - useTransactionEventListListener, -} from "utils"; +import { EventData } from "types/events"; +import { useTransactionEventListener } from "utils"; type TxWithAmount = { amount: BigNumber }; @@ -349,69 +347,59 @@ export const useTransactionNotifications = (): void => { }); }); - useTransactionEventListListener( - [ - "TransparentTransfer.Error", - "ShieldedTransfer.Error", - "ShieldingTransfer.Error", - "UnshieldingTransfer.Error", - ], - (e) => { - const id = createNotificationId(e.detail.tx); - clearPendingNotifications(id); - const storedTx = searchAllStoredTxByHash(e.detail.tx[0].hash); - dispatchNotification({ - id, - type: "error", - title: "Transfer transaction failed", - description: - storedTx ? - <> - Your transfer transaction of{" "} - {" "} - to {shortenAddress(storedTx.destinationAddress, 8, 8)} has failed - - : "Your transfer transaction has failed", - details: - e.detail.error?.message && failureDetails(e.detail.error.message), - }); - } - ); + const onTransferError = (e: EventData): void => { + const id = createNotificationId(e.detail.tx); + clearPendingNotifications(id); + const storedTx = searchAllStoredTxByHash(e.detail.tx[0].hash); + dispatchNotification({ + id, + type: "error", + title: "Transfer transaction failed", + description: + storedTx ? + <> + Your transfer transaction of{" "} + {" "} + to {shortenAddress(storedTx.destinationAddress, 8, 8)} has failed + + : "Your transfer transaction has failed", + details: + e.detail.error?.message && failureDetails(e.detail.error.message), + }); + }; + useTransactionEventListener("TransparentTransfer.Error", onTransferError); + useTransactionEventListener("ShieldedTransfer.Error", onTransferError); + useTransactionEventListener("ShieldingTransfer.Error", onTransferError); + useTransactionEventListener("UnshieldingTransfer.Error", onTransferError); - useTransactionEventListListener( - [ - "TransparentTransfer.Success", - "ShieldedTransfer.Success", - "ShieldingTransfer.Success", - "UnshieldingTransfer.Success", - ], - (e) => { - const id = createNotificationId(e.detail.tx); - clearPendingNotifications(id); - clearPendingNotifications(id); - const storedTx = searchAllStoredTxByHash(e.detail.tx[0].hash); - dispatchNotification({ - id, - title: "Transfer transaction succeeded", - description: - storedTx ? - <> - Your transfer transaction of{" "} - {" "} - to {shortenAddress(storedTx.destinationAddress, 8, 8)} has - succeeded - - : "Your transfer transaction has succeeded", - type: "success", - }); - } - ); + const onTransferSuccess = (e: EventData): void => { + const id = createNotificationId(e.detail.tx); + clearPendingNotifications(id); + const storedTx = searchAllStoredTxByHash(e.detail.tx[0].hash); + dispatchNotification({ + id, + title: "Transfer transaction succeeded", + description: + storedTx ? + <> + Your transfer transaction of{" "} + {" "} + to {shortenAddress(storedTx.destinationAddress, 8, 8)} has succeeded + + : "Your transfer transaction has succeeded", + type: "success", + }); + }; + useTransactionEventListener("TransparentTransfer.Success", onTransferSuccess); + useTransactionEventListener("ShieldedTransfer.Success", onTransferSuccess); + useTransactionEventListener("ShieldingTransfer.Success", onTransferSuccess); + useTransactionEventListener("UnshieldingTransfer.Success", onTransferSuccess); useTransactionEventListener("IbcTransfer.Success", (e) => { invariant(e.detail.hash, "Notification error: Invalid Tx hash"); diff --git a/apps/namadillo/src/utils/index.ts b/apps/namadillo/src/utils/index.ts index cbab9d2cb3..bde30209b9 100644 --- a/apps/namadillo/src/utils/index.ts +++ b/apps/namadillo/src/utils/index.ts @@ -3,7 +3,6 @@ import { ProposalStatus, ProposalTypeString } from "@namada/types"; import { localnetConfigAtom } from "atoms/integrations/atoms"; import BigNumber from "bignumber.js"; import { getDefaultStore } from "jotai"; -import { isEqual } from "lodash"; import namadaAssets from "namada-chain-registry/namada/assetlist.json"; import { useEffect, useRef } from "react"; @@ -54,33 +53,6 @@ export const useTransactionEventListener = ( }, [event]); }; -export const useTransactionEventListListener = ( - events: T[], - handler: (event: WindowEventMap[T]) => void -): void => { - // `eventsRef` and `handlerRef` are useful to avoid recreating the listener every time - const eventsRef = useRef(events); - if (!isEqual(events, eventsRef.current)) { - eventsRef.current = events; - } - const eventsValue = eventsRef.current; - - const handlerRef = useRef(handler); - handlerRef.current = handler; - - useEffect(() => { - const callback: typeof handler = (event) => handlerRef.current(event); - eventsValue.forEach((event) => { - window.addEventListener(event, callback); - }); - return () => { - eventsValue.forEach((event) => { - window.removeEventListener(event, callback); - }); - }; - }, [eventsValue]); -}; - export const sumBigNumberArray = (numbers: BigNumber[]): BigNumber => { if (numbers.length === 0) return new BigNumber(0); return BigNumber.sum(...numbers);