diff --git a/package-lock.json b/package-lock.json index afb67f82..e6bebe45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "simple-staking", - "version": "0.3.4", + "version": "0.3.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "simple-staking", - "version": "0.3.4", + "version": "0.3.5", "dependencies": { "@babylonlabs-io/btc-staking-ts": "0.3.0", "@bitcoin-js/tiny-secp256k1-asmjs": "2.2.3", diff --git a/package.json b/package.json index f744a64e..c78586e2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "simple-staking", - "version": "0.3.4", + "version": "0.3.5", "private": true, "scripts": { "dev": "next dev", diff --git a/src/app/components/Delegations/Delegations.tsx b/src/app/components/Delegations/Delegations.tsx index 066cf4c7..97d5e6db 100644 --- a/src/app/components/Delegations/Delegations.tsx +++ b/src/app/components/Delegations/Delegations.tsx @@ -1,5 +1,5 @@ import type { networks } from "bitcoinjs-lib"; -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import InfiniteScroll from "react-infinite-scroll-component"; import { useLocalStorage } from "usehooks-ts"; @@ -111,9 +111,12 @@ const DelegationsContent: React.FC = ({ const { showError } = useError(); const { isApiNormal, isGeoBlocked } = useHealthCheck(); const [awaitingWalletResponse, setAwaitingWalletResponse] = useState(false); - const [selectedDelegationHeight, setSelectedDelegationHeight] = useState< - number | undefined - >(); + + const delegation = useMemo( + () => + delegationsAPI.find((delegation) => delegation.stakingTxHashHex === txID), + [delegationsAPI, txID], + ); const shouldShowPoints = isApiNormal && !isGeoBlocked && shouldDisplayPoints(); @@ -185,15 +188,13 @@ const DelegationsContent: React.FC = ({ message: error.message, errorState: ErrorState.UNBONDING, }, - retryAction: () => - handleModal(id, MODE_UNBOND, selectedDelegationHeight!), + retryAction: () => handleModal(id, MODE_UNBOND), }); } finally { setModalOpen(false); setTxID(""); setModalMode(undefined); setAwaitingWalletResponse(false); - setSelectedDelegationHeight(undefined); } }; @@ -222,23 +223,20 @@ const DelegationsContent: React.FC = ({ message: error.message, errorState: ErrorState.WITHDRAW, }, - retryAction: () => - handleModal(id, MODE_WITHDRAW, selectedDelegationHeight!), + retryAction: () => handleModal(id, MODE_WITHDRAW), }); } finally { setModalOpen(false); setTxID(""); setModalMode(undefined); setAwaitingWalletResponse(false); - setSelectedDelegationHeight(undefined); } }; - const handleModal = (txID: string, mode: MODE, delegationHeight: number) => { + const handleModal = (txID: string, mode: MODE) => { setModalOpen(true); setTxID(txID); setModalMode(mode); - setSelectedDelegationHeight(delegationHeight); }; useEffect(() => { @@ -286,6 +284,21 @@ const DelegationsContent: React.FC = ({ }); }, [delegationsAPI, setIntermediateDelegationsLocalStorage]); + useEffect(() => { + if (modalOpen && !delegation) { + showError({ + error: { + message: "Delegation not found", + errorState: ErrorState.SERVER_ERROR, + }, + noCancel: false, + }); + setModalOpen(false); + setTxID(""); + setModalMode(undefined); + } + }, [modalOpen, delegation, showError]); + // combine delegations from the API and local storage, prioritizing API data const combinedDelegationsData = delegationsAPI ? [...delegationsLocalStorage, ...delegationsAPI] @@ -344,19 +357,9 @@ const DelegationsContent: React.FC = ({ stakingValueSat={stakingValueSat} stakingTxHash={stakingTxHashHex} state={state} - onUnbond={() => - handleModal( - stakingTxHashHex, - MODE_UNBOND, - stakingTx.startHeight, - ) - } + onUnbond={() => handleModal(stakingTxHashHex, MODE_UNBOND)} onWithdraw={() => - handleModal( - stakingTxHashHex, - MODE_WITHDRAW, - stakingTx.startHeight, - ) + handleModal(stakingTxHashHex, MODE_WITHDRAW) } intermediateState={intermediateDelegation?.state} isOverflow={isOverflow} @@ -368,9 +371,8 @@ const DelegationsContent: React.FC = ({ )} - {modalMode && txID && selectedDelegationHeight !== undefined && ( + {modalMode && txID && delegation && ( setModalOpen(false)} onProceed={() => { @@ -380,6 +382,7 @@ const DelegationsContent: React.FC = ({ }} mode={modalMode} awaitingWalletResponse={awaitingWalletResponse} + delegation={delegation} /> )} diff --git a/src/app/components/Modals/UnbondWithdrawModal.tsx b/src/app/components/Modals/UnbondWithdrawModal.tsx index 63aeb715..d953e761 100644 --- a/src/app/components/Modals/UnbondWithdrawModal.tsx +++ b/src/app/components/Modals/UnbondWithdrawModal.tsx @@ -1,6 +1,7 @@ import { IoMdClose } from "react-icons/io"; -import { useVersionInfo } from "@/app/context/api/VersionInfo"; +import { useVersionByHeight } from "@/app/context/api/VersionInfo"; +import { Delegation as DelegationInterface } from "@/app/types/delegations"; import { getNetworkConfig } from "@/config/network.config"; import { blocksToDisplayTime } from "@/utils/blocksToDisplayTime"; import { satoshiToBtc } from "@/utils/btcConversions"; @@ -15,28 +16,30 @@ export const MODE_WITHDRAW = "withdraw"; export type MODE = typeof MODE_UNBOND | typeof MODE_WITHDRAW; interface PreviewModalProps { - delegationHeight: number; open: boolean; onClose: (value: boolean) => void; onProceed: () => void; mode: MODE; awaitingWalletResponse: boolean; + delegation: DelegationInterface; } export const UnbondWithdrawModal: React.FC = ({ - delegationHeight, open, onClose, onProceed, mode, awaitingWalletResponse, + delegation, }) => { const { coinName, networkName } = getNetworkConfig(); - const versionInfo = useVersionInfo(); - const globalParams = versionInfo?.currentVersion; - const unbondingFeeSat = globalParams?.unbondingFeeSat || 0; - const unbondingTimeBlocks = globalParams?.unbondingTime || 0; + const { currentVersion: delegationGlobalParams } = useVersionByHeight( + delegation.stakingTx.startHeight ?? 0, + ); + + const unbondingFeeSat = delegationGlobalParams?.unbondingFeeSat ?? 0; + const unbondingTimeBlocks = delegationGlobalParams?.unbondingTime ?? 0; const unbondTitle = "Unbond"; diff --git a/src/app/context/api/VersionInfo.tsx b/src/app/context/api/VersionInfo.tsx index 75a5d1cd..5f0d75d3 100644 --- a/src/app/context/api/VersionInfo.tsx +++ b/src/app/context/api/VersionInfo.tsx @@ -24,6 +24,14 @@ export function useVersionInfo() { return useContext(VersionInfoContext); } +export function useVersionByHeight(height: number) { + const { data: versions } = useVersions(); + return useMemo( + () => getCurrentGlobalParamsVersion(height, versions ?? []), + [versions, height], + ); +} + export function VersionInfoProvider({ children }: PropsWithChildren) { const { data: versions, @@ -45,11 +53,16 @@ export function VersionInfoProvider({ children }: PropsWithChildren) { isLoading: isVersionLoading || isHeightLoading, }; + const currentVersionInfo = getCurrentGlobalParamsVersion( + height + 1, + versions, + ); + return { currentHeight: height, isError: isHeightError || isVersionError, isLoading: isVersionLoading || isHeightLoading, - ...getCurrentGlobalParamsVersion(height + 1, versions), + ...currentVersionInfo, }; }, [ versions,