diff --git a/renderer/components/NoteRow/NoteRow.tsx b/renderer/components/NoteRow/NoteRow.tsx index 1a4e17a3..33789411 100644 --- a/renderer/components/NoteRow/NoteRow.tsx +++ b/renderer/components/NoteRow/NoteRow.tsx @@ -5,15 +5,19 @@ import type { TransactionStatus, TransactionType, } from "@ironfish/sdk"; -import { ReactNode, useMemo } from "react"; +import { ReactNode, useMemo, useState } from "react"; import { MessageDescriptor, useIntl } from "react-intl"; -import { TRPCRouterOutputs } from "@/providers/TRPCProvider"; +import { trpcReact, TRPCRouterOutputs } from "@/providers/TRPCProvider"; import { MaybeLink } from "@/ui/ChakraLink/ChakraLink"; import { COLORS } from "@/ui/colors"; import { ShadowCard } from "@/ui/ShadowCard/ShadowCard"; import { CurrencyUtils } from "@/utils/currency"; import { formatDate } from "@/utils/formatDate"; +import { + refetchTransactionUntilTerminal, + isTransactionStatusTerminal, +} from "@/utils/transactionUtils"; import { BridgeIcon } from "./icons/BridgeIcon"; import { ChangeIcon } from "./icons/ChangeIcon"; @@ -110,7 +114,7 @@ export function NoteRow({ from, to, type, - status, + status: initialStatus, memo, transactionHash, asTransaction = false, @@ -137,6 +141,21 @@ export function NoteRow({ isBridge?: boolean; }) { const { formatMessage } = useIntl(); + const [status, setStatus] = useState(initialStatus); + + // Poll Transaction if it is a non-terminal status + trpcReact.getTransaction.useQuery( + { accountName, transactionHash }, + { + enabled: asTransaction && !isTransactionStatusTerminal(status), + refetchInterval: refetchTransactionUntilTerminal, + onSuccess: (data) => { + if (data.transaction.status !== status) { + setStatus(data.transaction.status); + } + }, + }, + ); const statusDisplay = getNoteStatusDisplay( type, diff --git a/renderer/intl/locales/en-US.json b/renderer/intl/locales/en-US.json index a27c698f..51083612 100644 --- a/renderer/intl/locales/en-US.json +++ b/renderer/intl/locales/en-US.json @@ -544,6 +544,9 @@ "TzwzhT": { "message": "You can remove and reimport your accounts whenever you like, provided that you possess the account keys. It is highly recommended to maintain a backup of your account keys in a secure location." }, + "U78NhE": { + "message": "Complete" + }, "ULXFfP": { "message": "Receive" }, @@ -730,6 +733,9 @@ "hR0flV": { "message": "All your transactions, whether in $IRON or other custom assets, will be displayed in this section. To start a transaction, simply click on the 'Send' or 'Receive' tabs." }, + "iFsDVR": { + "message": "Loading" + }, "iWiHY7": { "message": "The blockchain is syncing. Your balance may be inaccurate and sending transactions will be disabled until the sync is complete." }, @@ -769,6 +775,9 @@ "kTt/ND": { "message": "Russian" }, + "kbpDqo": { + "message": "Preparing destination txn" + }, "krty63": { "message": "Need help?" }, @@ -856,6 +865,9 @@ "rGIQdX": { "message": "Back to Account Overview" }, + "raexxM": { + "message": "Submitted" + }, "rbrahO": { "message": "Close" }, @@ -865,6 +877,9 @@ "rqrhXg": { "message": "Confirm Your Recovery Phrase" }, + "rrBTkh": { + "message": "Submitted destination txn" + }, "sXlL42": { "message": "Encrypted Wallets Unsupported" }, @@ -907,6 +922,9 @@ "vV69eP": { "message": "Downloading a snapshot is the fastest way to sync with the network." }, + "vXCeIi": { + "message": "Failed" + }, "vaP4MI": { "message": "It currently holds:" }, diff --git a/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx b/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx index 9910bd65..36d2024e 100644 --- a/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx +++ b/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx @@ -10,6 +10,7 @@ import { TransactionInformation } from "@/components/TransactionInformation/Tran import MainLayout from "@/layouts/MainLayout"; import { trpcReact } from "@/providers/TRPCProvider"; import { asQueryString } from "@/utils/parseRouteQuery"; +import { refetchTransactionUntilTerminal } from "@/utils/transactionUtils"; const messages = defineMessages({ backToAccountOverview: { @@ -38,10 +39,15 @@ function SingleTransactionContent({ name: accountName, }); - const { data: transactionData } = trpcReact.getTransaction.useQuery({ - accountName, - transactionHash, - }); + const { data: transactionData } = trpcReact.getTransaction.useQuery( + { + accountName, + transactionHash, + }, + { + refetchInterval: refetchTransactionUntilTerminal, + }, + ); if (!accountData) { return null; diff --git a/renderer/utils/transactionUtils.ts b/renderer/utils/transactionUtils.ts new file mode 100644 index 00000000..d26ead04 --- /dev/null +++ b/renderer/utils/transactionUtils.ts @@ -0,0 +1,19 @@ +import type { TransactionStatus } from "@ironfish/sdk"; + +import { TRPCRouterOutputs } from "@/providers/TRPCProvider"; + +export const isTransactionStatusTerminal = (status: TransactionStatus) => { + return status === "confirmed" || status === "expired"; +}; + +export const refetchTransactionUntilTerminal = ( + query: TRPCRouterOutputs["getTransaction"] | undefined, +) => { + if (!query) { + return 5000; + } + const txStatus = query.transaction.status; + const isTerminalStatus = isTransactionStatusTerminal(txStatus); + + return !isTerminalStatus ? 5000 : false; +};