From d58840ec5b649cb1fc388a5701182606ffcec455 Mon Sep 17 00:00:00 2001 From: Daniel Cortes Date: Mon, 24 Jun 2024 16:36:36 -0600 Subject: [PATCH 1/4] Add chainport information to account overview and tx details --- .../BridgeTransactionInformation.tsx | 91 ++++++++ .../BridgeTransactionInformationShell.tsx | 199 +++++++++++++++++ .../BridgeTransactionProgressIndicator.tsx | 206 ++++++++++++++++++ renderer/components/NoteRow/NoteRow.tsx | 16 +- .../components/NoteRow/icons/BridgeIcon.tsx | 14 ++ renderer/components/NoteRow/shared.ts | 6 + renderer/components/NotesList/NotesList.tsx | 2 + .../ConfirmTransactionModal.tsx | 3 +- .../SendAssetsForm/SendAssetsForm.tsx | 102 ++------- .../SendAssetsForm/transactionSchema.ts | 15 +- .../TransactionInformation.tsx | 5 +- renderer/intl/locales/en-US.json | 30 +++ .../pages/accounts/[account-name]/index.tsx | 2 +- .../transaction/[transaction-hash].tsx | 18 ++ renderer/utils/chainport/constants.ts | 1 + renderer/utils/chainport/isChainportTx.ts | 44 ++++ .../useChainportTransactionStatus.ts | 39 ++++ 17 files changed, 688 insertions(+), 105 deletions(-) create mode 100644 renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx create mode 100644 renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx create mode 100644 renderer/components/BridgeTransactionProgressIndicator/BridgeTransactionProgressIndicator.tsx create mode 100644 renderer/components/NoteRow/icons/BridgeIcon.tsx create mode 100644 renderer/utils/chainport/constants.ts create mode 100644 renderer/utils/chainport/isChainportTx.ts create mode 100644 renderer/utils/chainport/useChainportTransactionStatus.ts diff --git a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx new file mode 100644 index 00000000..1facecc8 --- /dev/null +++ b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx @@ -0,0 +1,91 @@ +import { BoxProps, Skeleton } from "@chakra-ui/react"; +import { useMemo } from "react"; + +import { trpcReact, TRPCRouterOutputs } from "@/providers/TRPCProvider"; +import { IRONFISH_NETWORK_ID } from "@/utils/chainport/constants"; + +import { BridgeTransactionInformationShell } from "./BridgeTransactionInformationShell"; + +type Transaction = TRPCRouterOutputs["getTransaction"]["transaction"]; + +type Props = BoxProps & { + transaction: Transaction; +}; + +export function BridgeTransactionInformation({ transaction, ...rest }: Props) { + const isSend = transaction.type === "send"; + + const encodedBridgeNoteMemo = useMemo(() => { + const match = transaction.notes?.find((note) => { + return note.memo && !note.memo.includes("fee_payment"); + }); + return match || null; + }, [transaction.notes]); + + const { data: chainportMeta } = trpcReact.getChainportMeta.useQuery(); + const { data: bridgeNoteMemo } = trpcReact.decodeMemo.useQuery( + { + memo: encodedBridgeNoteMemo?.memoHex ?? "", + }, + { + enabled: !!encodedBridgeNoteMemo, + }, + ); + + const baseNetworkId = isSend ? IRONFISH_NETWORK_ID : bridgeNoteMemo?.[0]; + + const { data: chainportStatus, isLoading: isChainportStatusLoading } = + trpcReact.getChainportTransactionStatus.useQuery( + { + transactionHash: transaction.hash, + baseNetworkId: baseNetworkId ?? 0, + }, + { + enabled: !!baseNetworkId, + }, + ); + + const targetNetwork = useMemo(() => { + if (!chainportStatus || !chainportMeta) return null; + + return chainportMeta.cp_network_ids[ + chainportStatus.target_network_id ?? "" + ]; + }, [chainportMeta, chainportStatus]); + + const destinationTxHashContent = useMemo(() => { + if (!chainportStatus || !chainportMeta) return null; + + const baseUrl = + chainportMeta.cp_network_ids[chainportStatus.target_network_id ?? ""] + ?.explorer_url; + + return { + href: baseUrl + "tx/" + chainportStatus.target_tx_hash, + txHash: chainportStatus.target_tx_hash, + }; + }, [chainportMeta, chainportStatus]); + + if (isChainportStatusLoading) { + return ( + placeholder} + type={pending} + address={0x12345678} + {...rest} + /> + ); + } + + return ( + + ); +} diff --git a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx new file mode 100644 index 00000000..83fc5b0c --- /dev/null +++ b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx @@ -0,0 +1,199 @@ +import { + Box, + BoxProps, + Grid, + GridItem, + Heading, + Text, + HStack, + VStack, + Image, +} from "@chakra-ui/react"; +import NextImage from "next/image"; +import { ReactNode } from "react"; +import { defineMessages, useIntl } from "react-intl"; + +import chainportIcon from "@/images/chainport/chainport-icon-lg.png"; +import { COLORS } from "@/ui/colors"; +import { ShadowCard } from "@/ui/ShadowCard/ShadowCard"; + +import { CopyAddress } from "../CopyAddress/CopyAddress"; + +const messages = defineMessages({ + heading: { + defaultMessage: "Bridge Information", + }, + status: { + defaultMessage: "Status", + }, + senderAddress: { + defaultMessage: "Sender Address", + }, + destinationAddress: { + defaultMessage: "Destination Address", + }, + destinationTxnHash: { + defaultMessage: "Destination Txn Hash", + }, + viewInBlockExplorer: { + defaultMessage: "View in Block Explorer", + }, +}); + +type Props = BoxProps & { + status: ReactNode; + type: ReactNode; + address: ReactNode; + networkIcon?: string; + targetTxHash?: string; + blockExplorerUrl?: string; +}; + +export function BridgeTransactionInformationShell({ + status, + type, + address, + networkIcon, + targetTxHash, + blockExplorerUrl, + ...rest +}: Props) { + const { formatMessage } = useIntl(); + const isSend = type === "send"; + return ( + + + {formatMessage(messages.heading)} + + + + + + + + {formatMessage(messages.status)} + + {status} + + + + + + + + + + + + {formatMessage( + isSend + ? messages.destinationAddress + : messages.senderAddress, + )} + + + {typeof address === "string" + ? `${address.slice(0, 6)}...${address.toString().slice(-4)}` + : address} + + + {networkIcon && ( + + )} + + + + + + + + + + {formatMessage(messages.destinationTxnHash)} + + + + {targetTxHash ? ( + + ) : ( + + )} + {blockExplorerUrl && ( + + + {formatMessage(messages.viewInBlockExplorer)} + + + )} + + + + {networkIcon && ( + + )} + + + + + + ); +} diff --git a/renderer/components/BridgeTransactionProgressIndicator/BridgeTransactionProgressIndicator.tsx b/renderer/components/BridgeTransactionProgressIndicator/BridgeTransactionProgressIndicator.tsx new file mode 100644 index 00000000..19e15bcb --- /dev/null +++ b/renderer/components/BridgeTransactionProgressIndicator/BridgeTransactionProgressIndicator.tsx @@ -0,0 +1,206 @@ +import { Box, Flex, HStack, Text, useColorMode } from "@chakra-ui/react"; +import { useMemo } from "react"; +import { IoMdCheckmark } from "react-icons/io"; +import { defineMessages, useIntl } from "react-intl"; + +import { TRPCRouterOutputs } from "@/providers/TRPCProvider"; +import { COLORS } from "@/ui/colors"; +import { useChainportTransactionStatus } from "@/utils/chainport/useChainportTransactionStatus"; + +const messages = defineMessages({ + submitted: { + defaultMessage: "Submitted", + }, + bridgePending: { + defaultMessage: "Preparing target txn", + }, + bridgeSubmitted: { + defaultMessage: "Submitted target txn", + }, + complete: { + defaultMessage: "Complete", + }, +}); + +const STEPS = [ + "iron_fish_submitted", + "bridge_pending", + "bridge_submitted", + "complete", +]; + +const BAR_BG_LIGHT = "#D9D9D9"; +const BAR_BG_DARK = COLORS.DARK_MODE.GRAY_MEDIUM; +const ICON_SIZE = "24px"; +const PENDING_SIZE = "16px"; + +type Props = { + transaction: TRPCRouterOutputs["getTransaction"]["transaction"]; +}; + +export function BridgeTransactionProgressIndicator({ transaction }: Props) { + const { formatMessage } = useIntl(); + + const status = useChainportTransactionStatus(transaction); + + const progressWidth = useMemo(() => { + if (status === "loading" || status === "failed") return 0; + + const sections = STEPS.length - 1; + const padding = 100 / sections / 2; + + return Math.min(STEPS.indexOf(status) * (100 / sections) + padding, 100); + }, [status]); + + if (status === "failed") { + return null; + } + + const currentStepIndex = STEPS.indexOf(status); + + return ( + + + = 0 ? "complete" : "pending"} + align="left" + label={formatMessage(messages.submitted)} + /> + = 1 ? "complete" : "pending"} + align="center" + label={formatMessage(messages.bridgePending)} + /> + = 2 ? "complete" : "pending"} + align="center" + label={formatMessage(messages.bridgeSubmitted)} + /> + = 3 ? "complete" : "pending"} + align="right" + label={formatMessage(messages.complete)} + /> + + + + + + ); +} + +function Step({ + label, + status, + align = "center", +}: { + label: string; + status: "pending" | "complete" | "failed"; + align?: "center" | "left" | "right"; +}) { + const { colorMode } = useColorMode(); + + const labelPositionStyles = useMemo(() => { + if (align === "center") { + return { + left: "50%", + transform: "translateX(-50%)", + }; + } + if (align === "left") { + return { + left: 0, + }; + } + if (align === "right") { + return { + right: 0, + }; + } + }, [align]); + + const indicator = useMemo(() => { + const borderColor = { + pending: "transparent", + complete: colorMode === "light" ? COLORS.GREEN_DARK : COLORS.PISTACHIO, + failed: COLORS.RED, + }[status] as string; + + const icon = { + pending: ( + + ), + complete: , + failed: , + }[status]; + + return ( + + {icon} + + ); + }, [status, colorMode]); + + return ( + + {indicator} + + {label} + + + ); +} diff --git a/renderer/components/NoteRow/NoteRow.tsx b/renderer/components/NoteRow/NoteRow.tsx index a4710084..d025b7e3 100644 --- a/renderer/components/NoteRow/NoteRow.tsx +++ b/renderer/components/NoteRow/NoteRow.tsx @@ -14,6 +14,7 @@ import { ShadowCard } from "@/ui/ShadowCard/ShadowCard"; import { CurrencyUtils } from "@/utils/currency"; import { formatDate } from "@/utils/formatDate"; +import { BridgeIcon } from "./icons/BridgeIcon"; import { ChangeIcon } from "./icons/ChangeIcon"; import { ExpiredIcon } from "./icons/ExpiredIcon"; import { PendingIcon } from "./icons/PendingIcon"; @@ -27,12 +28,21 @@ function getNoteStatusDisplay( status: TransactionStatus, asTransaction: boolean, isSelfSend: boolean, + isBridge: boolean, ): { icon: ReactNode; message: MessageDescriptor } { if (!asTransaction || status === "confirmed") { if (isSelfSend) { return { icon: , message: messages.change }; } + if (isBridge && type === "send") { + return { icon: , message: messages.bridgeSent }; + } + + if (isBridge && type === "receive") { + return { icon: , message: messages.bridgeReceived }; + } + if (type === "send") { return { icon: , message: messages.sent }; } @@ -100,6 +110,7 @@ export function NoteRow({ memo, transactionHash, asTransaction = false, + isBridge = false, }: { accountName: string; asset?: RpcAsset; @@ -117,6 +128,7 @@ export function NoteRow({ * show the status as the transaction's status) */ asTransaction?: boolean; + isBridge?: boolean; }) { const { formatMessage } = useIntl(); @@ -125,6 +137,7 @@ export function NoteRow({ status, asTransaction, from === to && type !== "miner", + isBridge, ); const headings = useHeadingsText(); @@ -153,7 +166,7 @@ export function NoteRow({ {formatDate(timestamp)} , - {!memo + {!memo || isBridge ? "—" : Array.isArray(memo) ? formatMessage(messages.multipleMemos) @@ -165,6 +178,7 @@ export function NoteRow({ assetId, formatMessage, from, + isBridge, memo, statusDisplay.icon, statusDisplay.message, diff --git a/renderer/components/NoteRow/icons/BridgeIcon.tsx b/renderer/components/NoteRow/icons/BridgeIcon.tsx new file mode 100644 index 00000000..8c5586de --- /dev/null +++ b/renderer/components/NoteRow/icons/BridgeIcon.tsx @@ -0,0 +1,14 @@ +import { chakra } from "@chakra-ui/react"; + +export function BridgeIcon() { + return ( + + + + + ); +} diff --git a/renderer/components/NoteRow/shared.ts b/renderer/components/NoteRow/shared.ts index f83d6b05..ddab20ae 100644 --- a/renderer/components/NoteRow/shared.ts +++ b/renderer/components/NoteRow/shared.ts @@ -41,6 +41,12 @@ export const messages = defineMessages({ description: "Change as in the money that is returned to the sender after a transaction", }, + bridgeSent: { + defaultMessage: "Bridge sent", + }, + bridgeReceived: { + defaultMessage: "Bridge received", + }, }); export function useHeadingsText() { diff --git a/renderer/components/NotesList/NotesList.tsx b/renderer/components/NotesList/NotesList.tsx index bc3d6fcb..3df2e91c 100644 --- a/renderer/components/NotesList/NotesList.tsx +++ b/renderer/components/NotesList/NotesList.tsx @@ -5,6 +5,7 @@ import { Virtuoso } from "react-virtuoso"; import { NoteHeadings } from "@/components/NoteRow/NoteHeadings"; import { NoteRow } from "@/components/NoteRow/NoteRow"; import { useScrollElementContext } from "@/layouts/MainLayout"; +import { isChainportNote } from "@/utils/chainport/isChainportTx"; import { TransactionNote } from "../../../shared/types"; import { EmptyStateMessage } from "../EmptyStateMessage/EmptyStateMessage"; @@ -94,6 +95,7 @@ export function NotesList({ status={note.status} memo={note.memo} asTransaction={asTransactions} + isBridge={asTransactions && isChainportNote(note)} /> ); }} diff --git a/renderer/components/SendAssetsForm/ConfirmTransactionModal/ConfirmTransactionModal.tsx b/renderer/components/SendAssetsForm/ConfirmTransactionModal/ConfirmTransactionModal.tsx index 8fc804c2..07ee6376 100644 --- a/renderer/components/SendAssetsForm/ConfirmTransactionModal/ConfirmTransactionModal.tsx +++ b/renderer/components/SendAssetsForm/ConfirmTransactionModal/ConfirmTransactionModal.tsx @@ -14,13 +14,14 @@ import { useRouter } from "next/router"; import { useCallback } from "react"; import { defineMessages, useIntl } from "react-intl"; +import { AssetOptionType } from "@/components/AssetAmountInput/utils"; import { trpcReact } from "@/providers/TRPCProvider"; import { COLORS } from "@/ui/colors"; import { PillButton } from "@/ui/PillButton/PillButton"; import { CurrencyUtils } from "@/utils/currency"; import { formatOre } from "@/utils/ironUtils"; -import { TransactionData, AssetOptionType } from "../transactionSchema"; +import { TransactionData } from "../transactionSchema"; const messages = defineMessages({ confirmTransactionDetails: { diff --git a/renderer/components/SendAssetsForm/SendAssetsForm.tsx b/renderer/components/SendAssetsForm/SendAssetsForm.tsx index 6c6a4d17..f6cef7f5 100644 --- a/renderer/components/SendAssetsForm/SendAssetsForm.tsx +++ b/renderer/components/SendAssetsForm/SendAssetsForm.tsx @@ -12,7 +12,6 @@ import { Select } from "@/ui/Forms/Select/Select"; import { TextInput } from "@/ui/Forms/TextInput/TextInput"; import { PillButton } from "@/ui/PillButton/PillButton"; import { CurrencyUtils } from "@/utils/currency"; -import { hexToUTF16String } from "@/utils/hexToUTF16String"; import { formatOre } from "@/utils/ironUtils"; import { asQueryString } from "@/utils/parseRouteQuery"; import { sliceToUtf8Bytes } from "@/utils/sliceToUtf8Bytes"; @@ -24,10 +23,11 @@ import { TransactionData, TransactionFormData, transactionSchema, - AccountType, - BalanceType, - AssetOptionType, } from "./transactionSchema"; +import { + normalizeAmountInputChange, + useAccountAssets, +} from "../AssetAmountInput/utils"; import { AccountSyncingMessage, ChainSyncingMessage, @@ -73,21 +73,6 @@ const messages = defineMessages({ }, }); -function getAccountBalances(account: AccountType): { - [key: string]: BalanceType; -} { - const customAssets = account.balances.custom?.reduce((acc, customAsset) => { - return { - ...acc, - [customAsset.asset.id]: customAsset, - }; - }, {}); - return { - [account.balances.iron.asset.id]: account.balances.iron, - ...customAssets, - }; -} - export function SendAssetsFormContent({ accountsData, defaultToAddress, @@ -131,6 +116,7 @@ export function SendAssetsFormContent({ setValue, } = useForm({ resolver: zodResolver(transactionSchema), + mode: "onBlur", defaultValues: { amount: "0", fromAccount: defaultAccount, @@ -155,46 +141,14 @@ export function SendAssetsFormContent({ }, [resetField, assetIdValue]); const selectedAccount = useMemo(() => { - const match = accountsData?.find( - (account) => account.name === fromAccountValue, + return ( + accountsData?.find((account) => account.name === fromAccountValue) ?? + accountsData[0] ); - if (!match) { - return accountsData[0]; - } - return match; }, [accountsData, fromAccountValue]); - const accountBalances = useMemo(() => { - return getAccountBalances(selectedAccount); - }, [selectedAccount]); - - const assetOptionsMap = useMemo(() => { - const entries: Array<[string, AssetOptionType]> = Object.values( - accountBalances, - ).map((balance) => { - const assetName = hexToUTF16String(balance.asset.name); - const confirmed = CurrencyUtils.render( - BigInt(balance.confirmed), - balance.asset.id, - balance.asset.verification, - ); - return [ - balance.asset.id, - { - assetName: assetName, - label: assetName + ` (${confirmed})`, - value: balance.asset.id, - asset: balance.asset, - }, - ]; - }); - return new Map(entries); - }, [accountBalances]); - - const assetOptions = useMemo( - () => Array.from(assetOptionsMap.values()), - [assetOptionsMap], - ); + const { accountBalances, assetOptionsMap, assetOptions } = + useAccountAssets(selectedAccount); const assetAmountToSend = useMemo(() => { const assetToSend = assetOptionsMap.get(assetIdValue); @@ -350,36 +304,12 @@ export function SendAssetsFormContent({ {...field} value={field.value ?? ""} onChange={(e) => { - clearErrors("root.serverError"); - - // remove any non-numeric characters except for periods - const azValue = e.target.value.replace(/[^\d.]/g, ""); - - // only allow one period - if (azValue.split(".").length > 2) { - e.preventDefault(); - return; - } - - const assetToSend = assetOptionsMap.get(assetIdValue); - const decimals = - assetToSend?.asset.verification?.decimals ?? 0; - - let finalValue = azValue; - - if (decimals === 0) { - // If decimals is 0, take the left side of the decimal. - // If no decimal is present, this will still work correctly. - finalValue = azValue.split(".")[0]; - } else { - // Otherwise, take the left side of the decimal and up to the correct number of decimal places. - const parts = azValue.split("."); - if (parts[1]?.length > decimals) { - finalValue = `${parts[0]}.${parts[1].slice(0, decimals)}`; - } - } - - field.onChange(finalValue); + normalizeAmountInputChange({ + changeEvent: e, + selectedAsset: assetOptionsMap.get(assetIdValue), + onStart: () => clearErrors("root.serverError"), + onChange: field.onChange, + }); }} onFocus={() => { if (field.value === "0") { diff --git a/renderer/components/SendAssetsForm/transactionSchema.ts b/renderer/components/SendAssetsForm/transactionSchema.ts index 3e2fbe5b..8f633222 100644 --- a/renderer/components/SendAssetsForm/transactionSchema.ts +++ b/renderer/components/SendAssetsForm/transactionSchema.ts @@ -1,9 +1,6 @@ import * as z from "zod"; -import { - TRPCRouterOutputs, - getTrpcVanillaClient, -} from "@/providers/TRPCProvider"; +import { getTrpcVanillaClient } from "@/providers/TRPCProvider"; import { sliceToUtf8Bytes } from "@/utils/sliceToUtf8Bytes"; export const MAX_MEMO_SIZE = 32; @@ -45,13 +42,3 @@ export type TransactionFormData = z.infer; export type TransactionData = Omit & { fee: number; }; - -export type AccountType = TRPCRouterOutputs["getAccounts"][number]; -export type BalanceType = AccountType["balances"]["iron"]; -export type AssetType = BalanceType["asset"]; -export type AssetOptionType = { - assetName: string; - label: string; - value: string; - asset: AssetType; -}; diff --git a/renderer/components/TransactionInformation/TransactionInformation.tsx b/renderer/components/TransactionInformation/TransactionInformation.tsx index 54e611f7..af702ed5 100644 --- a/renderer/components/TransactionInformation/TransactionInformation.tsx +++ b/renderer/components/TransactionInformation/TransactionInformation.tsx @@ -141,7 +141,8 @@ export function TransactionInformation({ transaction, ...rest }: Props) { {render(transaction)} - {icon} + {icon} diff --git a/renderer/intl/locales/en-US.json b/renderer/intl/locales/en-US.json index 9b3c77b9..be26740c 100644 --- a/renderer/intl/locales/en-US.json +++ b/renderer/intl/locales/en-US.json @@ -60,6 +60,9 @@ "3/a0Ho": { "message": "We're not able to download release notes right now." }, + "3KdqXd": { + "message": "Destination Txn Hash" + }, "3OLlCN": { "message": "From/To" }, @@ -406,6 +409,9 @@ "QXxopU": { "message": "Mnemonic phrase copied to clipboard!" }, + "QgKpaU": { + "message": "Bridge sent" + }, "QlsDcr": { "message": "Action" }, @@ -466,12 +472,18 @@ "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" }, "UTOugV": { "message": "Your Assets" }, + "Uh1bJh": { + "message": "Bridge Information" + }, "Uvwn4S": { "message": "Something went wrong while rendering this component. Please try again. If the issue persists, report the issue on Discord." }, @@ -577,6 +589,9 @@ "dTSUUK": { "message": "If you remove this account without exporting it first, YOU WILL LOSE ACCESS TO IT." }, + "e6HIlS": { + "message": "Destination Address" + }, "e6Ph5+": { "message": "Address" }, @@ -586,6 +601,9 @@ "eVlu1R": { "message": "Select language" }, + "eaEGGc": { + "message": "Preparing target txn" + }, "ecJcrS": { "message": "Syncing blocks" }, @@ -601,6 +619,9 @@ "fKN5VY": { "message": "Create Contact" }, + "fYjxPn": { + "message": "Submitted target txn" + }, "flxGnZ": { "message": "Telemetry enabled" }, @@ -616,6 +637,9 @@ "gjBiyj": { "message": "Loading..." }, + "gu1qWm": { + "message": "Bridge received" + }, "gu9i+5": { "message": "Version {currentVersion}" }, @@ -739,6 +763,9 @@ "rGIQdX": { "message": "Back to Account Overview" }, + "raexxM": { + "message": "Submitted" + }, "rbrahO": { "message": "Close" }, @@ -763,6 +790,9 @@ "tf1lIh": { "message": "Free" }, + "tjHKMS": { + "message": "Sender Address" + }, "tzMNF3": { "message": "Status" }, diff --git a/renderer/pages/accounts/[account-name]/index.tsx b/renderer/pages/accounts/[account-name]/index.tsx index a35c4d3b..d3c559a9 100644 --- a/renderer/pages/accounts/[account-name]/index.tsx +++ b/renderer/pages/accounts/[account-name]/index.tsx @@ -114,7 +114,7 @@ function AccountOverviewContent({ accountName }: { accountName: string }) { > - {accountData.name} + {accountData.name} {accountData.status.viewOnly && ( diff --git a/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx b/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx index 68bcc04a..fd9cac98 100644 --- a/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx +++ b/renderer/pages/accounts/[account-name]/transaction/[transaction-hash].tsx @@ -2,11 +2,14 @@ import { Box, HStack, Heading, Skeleton } from "@chakra-ui/react"; import { useRouter } from "next/router"; import { defineMessages, useIntl } from "react-intl"; +import { BridgeTransactionInformation } from "@/components/BridgeTransactionInformation/BridgeTransactionInformation"; +import { BridgeTransactionProgressIndicator } from "@/components/BridgeTransactionProgressIndicator/BridgeTransactionProgressIndicator"; import { CopyAddress } from "@/components/CopyAddress/CopyAddress"; import { NotesList } from "@/components/NotesList/NotesList"; import { TransactionInformation } from "@/components/TransactionInformation/TransactionInformation"; import MainLayout from "@/layouts/MainLayout"; import { trpcReact } from "@/providers/TRPCProvider"; +import { isChainportTx } from "@/utils/chainport/isChainportTx"; import { asQueryString } from "@/utils/parseRouteQuery"; const messages = defineMessages({ @@ -41,6 +44,9 @@ function SingleTransactionContent({ transactionHash, }); + const isChainportTransaction = + !!transactionData && isChainportTx(transactionData); + if (!accountData) { return null; } @@ -99,10 +105,22 @@ function SingleTransactionContent({ transform="translateY(0.4em)" /> + {isChainportTransaction && + transactionData.transaction.type === "send" && ( + + )} + {isChainportTransaction && ( + + )} { + return isChainportNote(note); + }); +} + +function toLower(content: string | string[]) { + return Array.isArray(content) + ? content.map((c) => c.toLowerCase()) + : content.toLowerCase(); +} + +function hasAddress(haystack: Set, needle: string | string[]) { + return Array.isArray(needle) + ? needle.some((n) => haystack.has(n)) + : haystack.has(needle); +} diff --git a/renderer/utils/chainport/useChainportTransactionStatus.ts b/renderer/utils/chainport/useChainportTransactionStatus.ts new file mode 100644 index 00000000..1aa4dca7 --- /dev/null +++ b/renderer/utils/chainport/useChainportTransactionStatus.ts @@ -0,0 +1,39 @@ +import { useMemo } from "react"; + +import { trpcReact, TRPCRouterOutputs } from "@/providers/TRPCProvider"; + +import { IRONFISH_NETWORK_ID } from "./constants"; + +type ChainportTransactionStatus = + | "loading" + | "iron_fish_submitted" + | "bridge_pending" + | "bridge_submitted" + | "complete" + | "failed"; + +export function useChainportTransactionStatus( + transaction: TRPCRouterOutputs["getTransaction"]["transaction"], +): ChainportTransactionStatus { + const { data, error, isLoading } = + trpcReact.getChainportTransactionStatus.useQuery({ + transactionHash: transaction.hash, + baseNetworkId: IRONFISH_NETWORK_ID, + }); + + return useMemo(() => { + if (!data || isLoading) return "loading"; + + if (error) return "failed"; + + if (Object.entries(data).length === 0) return "iron_fish_submitted"; + + if (data.base_tx_status === 1) return "bridge_pending"; + + if (data.target_tx_status === null) return "bridge_submitted"; + + if (data.target_tx_status === 1) return "complete"; + + return "iron_fish_submitted"; + }, [data, isLoading, error]); +} From 1efcef08274552711fa0924ad7a0362e56d3fed2 Mon Sep 17 00:00:00 2001 From: Daniel Cortes Date: Tue, 25 Jun 2024 09:57:19 -0600 Subject: [PATCH 2/4] Fix Bridge Information Chainport Status --- .../BridgeTransactionInformation.tsx | 10 ++++++- .../BridgeTransactionProgressIndicator.tsx | 30 ++++++------------- renderer/intl/locales/en-US.json | 6 ++++ .../useChainportTransactionStatus.ts | 26 ++++++++++++++++ 4 files changed, 50 insertions(+), 22 deletions(-) diff --git a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx index 1facecc8..7c11881f 100644 --- a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx +++ b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx @@ -1,8 +1,13 @@ import { BoxProps, Skeleton } from "@chakra-ui/react"; import { useMemo } from "react"; +import { useIntl } from "react-intl"; import { trpcReact, TRPCRouterOutputs } from "@/providers/TRPCProvider"; import { IRONFISH_NETWORK_ID } from "@/utils/chainport/constants"; +import { + getMessageForStatus, + useChainportTransactionStatus, +} from "@/utils/chainport/useChainportTransactionStatus"; import { BridgeTransactionInformationShell } from "./BridgeTransactionInformationShell"; @@ -13,6 +18,7 @@ type Props = BoxProps & { }; export function BridgeTransactionInformation({ transaction, ...rest }: Props) { + const { formatMessage } = useIntl(); const isSend = transaction.type === "send"; const encodedBridgeNoteMemo = useMemo(() => { @@ -66,6 +72,8 @@ export function BridgeTransactionInformation({ transaction, ...rest }: Props) { }; }, [chainportMeta, chainportStatus]); + const status = useChainportTransactionStatus(transaction); + if (isChainportStatusLoading) { return ( = 0 ? "complete" : "pending"} align="left" - label={formatMessage(messages.submitted)} + label={formatMessage(getMessageForStatus("iron_fish_submitted"))} /> = 1 ? "complete" : "pending"} align="center" - label={formatMessage(messages.bridgePending)} + label={formatMessage(getMessageForStatus("bridge_pending"))} /> = 2 ? "complete" : "pending"} align="center" - label={formatMessage(messages.bridgeSubmitted)} + label={formatMessage(getMessageForStatus("bridge_submitted"))} /> = 3 ? "complete" : "pending"} align="right" - label={formatMessage(messages.complete)} + label={formatMessage(getMessageForStatus("complete"))} /> Date: Tue, 25 Jun 2024 10:27:37 -0600 Subject: [PATCH 3/4] Address PR feedback --- .../BridgeTransactionInformation.tsx | 14 +- .../BridgeTransactionInformationShell.tsx | 156 +++++++++++------- renderer/intl/locales/en-US.json | 18 -- 3 files changed, 113 insertions(+), 75 deletions(-) diff --git a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx index 7c11881f..f043c35d 100644 --- a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx +++ b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformation.tsx @@ -74,6 +74,17 @@ export function BridgeTransactionInformation({ transaction, ...rest }: Props) { const status = useChainportTransactionStatus(transaction); + const sourceNetwork = useMemo(() => { + const result = chainportMeta?.cp_network_ids[baseNetworkId ?? ""]; + + if (!result) return; + + return { + name: result.label, + icon: result.network_icon, + }; + }, [baseNetworkId, chainportMeta?.cp_network_ids]); + if (isChainportStatusLoading) { return ( ); diff --git a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx index 83fc5b0c..af6a5d2d 100644 --- a/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx +++ b/renderer/components/BridgeTransactionInformation/BridgeTransactionInformationShell.tsx @@ -38,6 +38,9 @@ const messages = defineMessages({ viewInBlockExplorer: { defaultMessage: "View in Block Explorer", }, + sourceNetwork: { + defaultMessage: "Source Network", + }, }); type Props = BoxProps & { @@ -47,6 +50,10 @@ type Props = BoxProps & { networkIcon?: string; targetTxHash?: string; blockExplorerUrl?: string; + sourceNetwork?: { + name: string; + icon: string; + }; }; export function BridgeTransactionInformationShell({ @@ -56,6 +63,7 @@ export function BridgeTransactionInformationShell({ networkIcon, targetTxHash, blockExplorerUrl, + sourceNetwork, ...rest }: Props) { const { formatMessage } = useIntl(); @@ -137,62 +145,98 @@ export function BridgeTransactionInformationShell({ - - - - - - {formatMessage(messages.destinationTxnHash)} - - - - {targetTxHash ? ( - - ) : ( - - )} - {blockExplorerUrl && ( - - - {formatMessage(messages.viewInBlockExplorer)} - - - )} - - - - {networkIcon && ( - - )} - - - + {isSend && ( + + + + + + {formatMessage(messages.destinationTxnHash)} + + + + {targetTxHash ? ( + + ) : ( + + )} + {blockExplorerUrl && ( + + + {formatMessage(messages.viewInBlockExplorer)} + + + )} + + + + {networkIcon && ( + + )} + + + + )} + {!isSend && sourceNetwork && ( + + + + + + {formatMessage(messages.sourceNetwork)} + + {sourceNetwork?.name} + + + + + + )} ); diff --git a/renderer/intl/locales/en-US.json b/renderer/intl/locales/en-US.json index c8283a64..f1622cee 100644 --- a/renderer/intl/locales/en-US.json +++ b/renderer/intl/locales/en-US.json @@ -472,9 +472,6 @@ "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" }, @@ -601,9 +598,6 @@ "eVlu1R": { "message": "Select language" }, - "eaEGGc": { - "message": "Preparing target txn" - }, "ecJcrS": { "message": "Syncing blocks" }, @@ -619,9 +613,6 @@ "fKN5VY": { "message": "Create Contact" }, - "fYjxPn": { - "message": "Submitted target txn" - }, "flxGnZ": { "message": "Telemetry enabled" }, @@ -658,9 +649,6 @@ "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." }, @@ -766,9 +754,6 @@ "rGIQdX": { "message": "Back to Account Overview" }, - "raexxM": { - "message": "Submitted" - }, "rbrahO": { "message": "Close" }, @@ -817,9 +802,6 @@ "vV69eP": { "message": "Downloading a snapshot is the fastest way to sync with the network." }, - "vXCeIi": { - "message": "Failed" - }, "vaP4MI": { "message": "It currently holds:" }, From 24dbca75619ffaae035b49bb627476938d6ae8a3 Mon Sep 17 00:00:00 2001 From: Daniel Cortes Date: Tue, 25 Jun 2024 14:08:28 -0600 Subject: [PATCH 4/4] Fix bridge transaction status logic --- package-lock.json | 453 ++++++++++++++---- package.json | 2 +- renderer/intl/locales/en-US.json | 18 + .../useChainportTransactionStatus.ts | 7 +- 4 files changed, 394 insertions(+), 86 deletions(-) diff --git a/package-lock.json b/package-lock.json index a83c1379..aea3e3ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "hasInstallScript": true, "license": "MPL-2.0", "dependencies": { - "@ironfish/sdk": "2.2.0", + "@ironfish/sdk": "2.4.0", "electron-serve": "^1.1.0", "keccak": "^3.0.4" }, @@ -4519,26 +4519,26 @@ "dev": true }, "node_modules/@ironfish/rust-nodejs": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs/-/rust-nodejs-2.2.0.tgz", - "integrity": "sha512-xStPyoltT9lK3UKfju3lUnjgJHS+EYQO8Aapw/1NYSThdKNhFkUlY0tP2Gl2w5NYu7wRYjQUyg4RQPwFgiyVcQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs/-/rust-nodejs-2.4.0.tgz", + "integrity": "sha512-dul47EmZdsP4whs9Lc+idED080yYf/n5Eq1zd2/8xRCYwr4an74GqupcTKFpkHKkD/3Gf/eQjGZxrQqrXrCiZA==", "engines": { "node": ">=18" }, "optionalDependencies": { - "@ironfish/rust-nodejs-darwin-arm64": "2.2.0", - "@ironfish/rust-nodejs-darwin-x64": "2.2.0", - "@ironfish/rust-nodejs-linux-arm64-gnu": "2.2.0", - "@ironfish/rust-nodejs-linux-arm64-musl": "2.2.0", - "@ironfish/rust-nodejs-linux-x64-gnu": "2.2.0", - "@ironfish/rust-nodejs-linux-x64-musl": "2.2.0", - "@ironfish/rust-nodejs-win32-x64-msvc": "2.2.0" + "@ironfish/rust-nodejs-darwin-arm64": "2.4.0", + "@ironfish/rust-nodejs-darwin-x64": "2.4.0", + "@ironfish/rust-nodejs-linux-arm64-gnu": "2.4.0", + "@ironfish/rust-nodejs-linux-arm64-musl": "2.4.0", + "@ironfish/rust-nodejs-linux-x64-gnu": "2.4.0", + "@ironfish/rust-nodejs-linux-x64-musl": "2.4.0", + "@ironfish/rust-nodejs-win32-x64-msvc": "2.4.0" } }, "node_modules/@ironfish/rust-nodejs-darwin-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-darwin-arm64/-/rust-nodejs-darwin-arm64-2.2.0.tgz", - "integrity": "sha512-i/sDaHoNLEIYKZCXB8JRN0B+bSGl+BSXE5DFmuuFCmzf/c23ipPQ8hRW99wbIx2lzKYTzpmhVK0dQMcKJ/bzPQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-darwin-arm64/-/rust-nodejs-darwin-arm64-2.4.0.tgz", + "integrity": "sha512-Fj4U/fcP2j2R6qcUEgbXMz37IBC14tDGorg9f2LxU+lPeqHmsNApKrLrEXTkwW0Ec/pfxz09vkX99DaKIKTTIA==", "cpu": [ "arm64" ], @@ -4551,9 +4551,9 @@ } }, "node_modules/@ironfish/rust-nodejs-darwin-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-darwin-x64/-/rust-nodejs-darwin-x64-2.2.0.tgz", - "integrity": "sha512-iky97r0ChU/AOKK1ArCQhPkvFWbDiheVqD5w2LbDegM2RQGKlYHOGFFrKZ/sJT0/wTTPF7H7Ct+Z8JtuafPGMg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-darwin-x64/-/rust-nodejs-darwin-x64-2.4.0.tgz", + "integrity": "sha512-/jeUuirjCGG9g8BgYiIc9bWBhBuhjA3+F7v/qxT9If/Xe/DFF7GZwwiAGhLuG0kA483H2qB4EAa+PgUNjSazQQ==", "cpu": [ "x64" ], @@ -4566,9 +4566,9 @@ } }, "node_modules/@ironfish/rust-nodejs-linux-arm64-gnu": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-arm64-gnu/-/rust-nodejs-linux-arm64-gnu-2.2.0.tgz", - "integrity": "sha512-5fd9uJoNJdMlL/yEPx0HFvyRglqhMkEl536e5mJL3P+angjgx02FPIZ00VGK9Er5piXalvSDDKSSN9le4SUGeQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-arm64-gnu/-/rust-nodejs-linux-arm64-gnu-2.4.0.tgz", + "integrity": "sha512-QO71yoOUBq2giGSwqafshHd438cX8x6COVty769RdxC/TL7adJKJ8eMrk/DQ+ou5Y8vjlQxoA0hXUwV5rvIpyg==", "cpu": [ "arm64" ], @@ -4581,9 +4581,9 @@ } }, "node_modules/@ironfish/rust-nodejs-linux-arm64-musl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-arm64-musl/-/rust-nodejs-linux-arm64-musl-2.2.0.tgz", - "integrity": "sha512-X1IEjvC2Pgb86Sg78u18aNZZT1LxRX01FE8xPOEBPHgNQko8BqgzCggbnI1mFY4wRfcI+c6ILIvee/c6tZ/TTQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-arm64-musl/-/rust-nodejs-linux-arm64-musl-2.4.0.tgz", + "integrity": "sha512-31vtiBdJYE0vku3GMLBDFq6mGubqNahPT7r1Nu69+/r3RPyds657WZbzHvaqYYRzLLnAGyoPRVGIr07G+C+HXw==", "cpu": [ "arm64" ], @@ -4596,9 +4596,9 @@ } }, "node_modules/@ironfish/rust-nodejs-linux-x64-gnu": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-x64-gnu/-/rust-nodejs-linux-x64-gnu-2.2.0.tgz", - "integrity": "sha512-CmLaiRKGquc2HBBG7y+/qaoRkLimbkctgHmxvhyGCgI9Z4ii7G1emMpYzwIDKDqUithoM2MEtG+Zm6Ug/s5lQw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-x64-gnu/-/rust-nodejs-linux-x64-gnu-2.4.0.tgz", + "integrity": "sha512-s1S7wnyUZBV0ZoGZLfZfo4WRUvlabi9Az+MIRYYCeFKO/RoZF0+F2in7wgsGC3oIweSGRM84Mjps/TOzzzBmAQ==", "cpu": [ "x64" ], @@ -4611,9 +4611,9 @@ } }, "node_modules/@ironfish/rust-nodejs-linux-x64-musl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-x64-musl/-/rust-nodejs-linux-x64-musl-2.2.0.tgz", - "integrity": "sha512-h8ZDsjBJ1OnOmjrL/Ogc2tYp6z2FALfm2pdIjpsTa5ztsr5UrvKqj0SXKwr82p//7yQktroFFyxAXfJzyiGyKQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-linux-x64-musl/-/rust-nodejs-linux-x64-musl-2.4.0.tgz", + "integrity": "sha512-OEx2J0m9yBR9RAjRIp1395mspMuWCTtHDvR3bvMKDMAjg3kkb6MMN/ndhesO7FGarUSPMZrhZ9aOwIvRRrWwmA==", "cpu": [ "x64" ], @@ -4626,9 +4626,9 @@ } }, "node_modules/@ironfish/rust-nodejs-win32-x64-msvc": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-win32-x64-msvc/-/rust-nodejs-win32-x64-msvc-2.2.0.tgz", - "integrity": "sha512-jBkNdyfLsGlfET5OFWCy7BFjwDzw7RA4fLdrMv/egcVjEbYjx25PeBiSm+CV9KI4omUMXLRKFRhc+qcpyJmgTg==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/rust-nodejs-win32-x64-msvc/-/rust-nodejs-win32-x64-msvc-2.4.0.tgz", + "integrity": "sha512-nMW5rnnGzhbeeuhZOUBHYMz6QRWLtQl53dn7YBK+KMhIzZN51Yd3Oz0FdFXgJNzwVhaUSB7CK3PLsRMvfIO0jg==", "cpu": [ "x64" ], @@ -4641,15 +4641,15 @@ } }, "node_modules/@ironfish/sdk": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ironfish/sdk/-/sdk-2.2.0.tgz", - "integrity": "sha512-x4gaVRk2ZQyoPj9Ayi/N77qW8OpNRCXG0EEsUEI6drswgugYjqK86PRYsChanFMPdJpe0Gr1FNR3N/uagkYinw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@ironfish/sdk/-/sdk-2.4.0.tgz", + "integrity": "sha512-6ooh+czhZvzhH5VunEnaDkkek99nWmexBlVcey4K6htcxtj6BAnQu8uGzNmCT1NlPh4T7ELdo10XDEtujXPVSQ==", "dependencies": { "@ethersproject/bignumber": "5.7.0", "@fast-csv/format": "4.3.5", - "@ironfish/rust-nodejs": "2.2.0", + "@ironfish/rust-nodejs": "2.4.0", "@napi-rs/blake-hash": "1.3.3", - "axios": "0.21.4", + "axios": "1.7.2", "bech32": "2.0.0", "blru": "0.1.6", "buffer": "6.0.3", @@ -4663,10 +4663,10 @@ "fastpriorityqueue": "0.7.1", "imurmurhash": "0.1.4", "level-errors": "2.0.1", - "leveldown": "5.6.0", + "leveldown": "6.1.1", "levelup": "4.4.0", "lodash": "4.17.21", - "node-datachannel": "0.5.1", + "node-datachannel": "0.8.0", "node-forge": "1.3.1", "parse-json": "5.2.0", "sqlite": "4.0.23", @@ -4679,6 +4679,16 @@ "node": ">=18" } }, + "node_modules/@ironfish/sdk/node_modules/axios": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/@ironfish/sdk/node_modules/date-fns": { "version": "2.16.1", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz", @@ -5931,6 +5941,198 @@ "@babel/runtime": "^7.13.10" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rushstack/eslint-patch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.5.1.tgz", @@ -6150,8 +6352,7 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/fs-extra": { "version": "9.0.13", @@ -7330,8 +7531,7 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/at-least-node": { "version": "1.0.0", @@ -7376,6 +7576,7 @@ "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dev": true, "dependencies": { "follow-redirects": "^1.14.0" } @@ -7940,6 +8141,14 @@ } ] }, + "node_modules/catering": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", + "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", + "engines": { + "node": ">=6" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -8161,7 +8370,6 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -8609,7 +8817,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -10204,9 +10411,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "funding": [ { "type": "individual", @@ -10235,7 +10442,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -10398,7 +10604,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -11802,16 +12007,6 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, - "node_modules/keccak/node_modules/node-gyp-build": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", - "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -11898,17 +12093,74 @@ } }, "node_modules/leveldown": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-5.6.0.tgz", - "integrity": "sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/leveldown/-/leveldown-6.1.1.tgz", + "integrity": "sha512-88c+E+Eizn4CkQOBHwqlCJaTNEjGpaEIikn1S+cINc5E9HEvJ77bqY4JY/HxT5u0caWqsc3P3DcFIKBI1vHt+A==", "hasInstallScript": true, "dependencies": { - "abstract-leveldown": "~6.2.1", + "abstract-leveldown": "^7.2.0", "napi-macros": "~2.0.0", - "node-gyp-build": "~4.1.0" + "node-gyp-build": "^4.3.0" }, "engines": { - "node": ">=8.6.0" + "node": ">=10.12.0" + } + }, + "node_modules/leveldown/node_modules/abstract-leveldown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz", + "integrity": "sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ==", + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.0.0", + "is-buffer": "^2.0.5", + "level-concat-iterator": "^3.0.0", + "level-supports": "^2.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/leveldown/node_modules/is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "engines": { + "node": ">=4" + } + }, + "node_modules/leveldown/node_modules/level-concat-iterator": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz", + "integrity": "sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ==", + "dependencies": { + "catering": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/leveldown/node_modules/level-supports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-2.1.0.tgz", + "integrity": "sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA==", + "engines": { + "node": ">=10" } }, "node_modules/levelup": { @@ -13005,7 +13257,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -13014,7 +13265,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -13502,9 +13752,9 @@ } }, "node_modules/node-abi": { - "version": "3.51.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.51.0.tgz", - "integrity": "sha512-SQkEP4hmNWjlniS5zdnfIXTk1x7Ome85RDzHlTbBtzE97Gfwz/Ipw4v/Ryk20DWIy3yCNVLVlGKApCnmvYoJbA==", + "version": "3.65.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz", + "integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==", "dependencies": { "semver": "^7.3.5" }, @@ -13520,13 +13770,14 @@ "optional": true }, "node_modules/node-datachannel": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/node-datachannel/-/node-datachannel-0.5.1.tgz", - "integrity": "sha512-3hwCrBWJqYoozwVtJNzNtISLKwa3l/XTbrPFCyhC3KCgW1IvYMHhHm5FW37p0p2oth3J6MDwCw3T/0m7DTR7lw==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/node-datachannel/-/node-datachannel-0.8.0.tgz", + "integrity": "sha512-05vYthhjESfO5qumWRbqHI1PN71rc19DJjc14ofOLapJrTCnmhx0JYw0G5wcL56b57uHQP9WjEak3+XklrB+Og==", "hasInstallScript": true, "dependencies": { "node-domexception": "^2.0.1", - "prebuild-install": "^7.0.1" + "prebuild-install": "^7.0.1", + "rollup": "^4.14.1" }, "engines": { "node": ">=16.0.0" @@ -13602,9 +13853,9 @@ } }, "node_modules/node-gyp-build": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.1.1.tgz", - "integrity": "sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ==", + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.1.tgz", + "integrity": "sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -14292,9 +14543,9 @@ } }, "node_modules/prebuild-install": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", - "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", + "integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==", "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", @@ -14394,6 +14645,11 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, "node_modules/prr": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", @@ -14421,7 +14677,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -15042,6 +15297,40 @@ "node": ">=8.0" } }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", diff --git a/package.json b/package.json index a4624b19..ea6dc330 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ }, "license": "MPL-2.0", "dependencies": { - "@ironfish/sdk": "2.2.0", + "@ironfish/sdk": "2.4.0", "electron-serve": "^1.1.0", "keccak": "^3.0.4" }, diff --git a/renderer/intl/locales/en-US.json b/renderer/intl/locales/en-US.json index f1622cee..c8283a64 100644 --- a/renderer/intl/locales/en-US.json +++ b/renderer/intl/locales/en-US.json @@ -472,6 +472,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" }, @@ -598,6 +601,9 @@ "eVlu1R": { "message": "Select language" }, + "eaEGGc": { + "message": "Preparing target txn" + }, "ecJcrS": { "message": "Syncing blocks" }, @@ -613,6 +619,9 @@ "fKN5VY": { "message": "Create Contact" }, + "fYjxPn": { + "message": "Submitted target txn" + }, "flxGnZ": { "message": "Telemetry enabled" }, @@ -649,6 +658,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." }, @@ -754,6 +766,9 @@ "rGIQdX": { "message": "Back to Account Overview" }, + "raexxM": { + "message": "Submitted" + }, "rbrahO": { "message": "Close" }, @@ -802,6 +817,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/utils/chainport/useChainportTransactionStatus.ts b/renderer/utils/chainport/useChainportTransactionStatus.ts index 2279096f..35eb08d5 100644 --- a/renderer/utils/chainport/useChainportTransactionStatus.ts +++ b/renderer/utils/chainport/useChainportTransactionStatus.ts @@ -54,12 +54,13 @@ export function useChainportTransactionStatus( if (Object.entries(data).length === 0) return "iron_fish_submitted"; - if (data.base_tx_status === 1) return "bridge_pending"; - - if (data.target_tx_status === null) return "bridge_submitted"; + if (data.base_tx_status === 1 && data.target_tx_status === null) + return "bridge_pending"; if (data.target_tx_status === 1) return "complete"; + if (data.target_tx_hash) return "bridge_submitted"; + return "iron_fish_submitted"; }, [data, isLoading, error]); }