From edc5a31aa3edda9489f9989eb5ee4f86dc1e4dc8 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Tue, 3 Dec 2024 15:52:39 +0100 Subject: [PATCH 1/9] Use tanstack query to fetch activities --- dapp/src/constants/queryKeysFactory.ts | 1 + dapp/src/hooks/sdk/useActivitiesQuery.ts | 47 +++++++++++++++++++ dapp/src/hooks/sdk/useInitDataFromSdk.ts | 22 +++------ dapp/src/hooks/store/index.ts | 1 - .../hooks/store/useHasFetchedActivities.ts | 8 ---- dapp/src/hooks/useIsFetchedWalletData.ts | 8 +--- dapp/src/store/tests/walletSlice.test.ts | 6 --- dapp/src/store/wallet/walletSelector.ts | 3 -- dapp/src/store/wallet/walletSlice.ts | 3 -- 9 files changed, 57 insertions(+), 42 deletions(-) create mode 100644 dapp/src/hooks/sdk/useActivitiesQuery.ts delete mode 100644 dapp/src/hooks/store/useHasFetchedActivities.ts diff --git a/dapp/src/constants/queryKeysFactory.ts b/dapp/src/constants/queryKeysFactory.ts index f7a543e0c..95a82ff5c 100644 --- a/dapp/src/constants/queryKeysFactory.ts +++ b/dapp/src/constants/queryKeysFactory.ts @@ -2,6 +2,7 @@ const userKeys = { all: ["user"] as const, balance: () => [...userKeys.all, "balance"] as const, position: () => [...userKeys.all, "position"] as const, + activities: () => [...userKeys.all, "activities"] as const, pointsData: () => [...userKeys.all, "points-data"] as const, } diff --git a/dapp/src/hooks/sdk/useActivitiesQuery.ts b/dapp/src/hooks/sdk/useActivitiesQuery.ts new file mode 100644 index 000000000..f13f52466 --- /dev/null +++ b/dapp/src/hooks/sdk/useActivitiesQuery.ts @@ -0,0 +1,47 @@ +import { queryKeysFactory, REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants" +import { useQuery } from "@tanstack/react-query" +import { Activity } from "#/types" +import { DepositStatus } from "@acre-btc/sdk" +import { useAcreContext } from "#/acre-react/hooks" +import { useWallet } from "../useWallet" + +const { userKeys } = queryKeysFactory + +export default function useActivitiesQuery() { + const { address } = useWallet() + const { acre, isConnected } = useAcreContext() + + return useQuery({ + queryKey: [...userKeys.activities(), { acre, isConnected, address }], + enabled: isConnected && !!acre && !!address, + queryFn: async () => { + if (!acre) return undefined + + const deposits: Activity[] = (await acre.account.getDeposits()).map( + (deposit) => ({ + ...deposit, + status: + deposit.status === DepositStatus.Finalized + ? "completed" + : "pending", + type: "deposit", + }), + ) + + const withdrawals: Activity[] = (await acre.account.getWithdrawals()).map( + (withdraw) => { + const { bitcoinTransactionId, status, ...rest } = withdraw + + return { + ...rest, + txHash: bitcoinTransactionId, + status: status === "finalized" ? "completed" : "pending", + type: "withdraw", + } + }, + ) + return [...deposits, ...withdrawals] + }, + refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, + }) +} diff --git a/dapp/src/hooks/sdk/useInitDataFromSdk.ts b/dapp/src/hooks/sdk/useInitDataFromSdk.ts index fdc19e82f..3e5e618be 100644 --- a/dapp/src/hooks/sdk/useInitDataFromSdk.ts +++ b/dapp/src/hooks/sdk/useInitDataFromSdk.ts @@ -1,24 +1,16 @@ import { useEffect } from "react" -import { useInterval } from "@chakra-ui/react" -import { logPromiseFailure } from "#/utils" -import { REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants" +import { setActivities } from "#/store/wallet" import { useFetchMinDepositAmount } from "./useFetchMinDepositAmount" -import { useFetchActivities } from "./useFetchActivities" -import { useWallet } from "../useWallet" +import useActivitiesQuery from "./useActivitiesQuery" +import { useAppDispatch } from "../store/useAppDispatch" export function useInitDataFromSdk() { - const { address } = useWallet() - const fetchActivities = useFetchActivities() + const { data } = useActivitiesQuery() + const dispatch = useAppDispatch() useEffect(() => { - if (address) { - logPromiseFailure(fetchActivities()) - } - }, [address, fetchActivities]) + dispatch(setActivities(data ?? [])) + }, [data, dispatch]) useFetchMinDepositAmount() - useInterval( - () => logPromiseFailure(fetchActivities()), - REFETCH_INTERVAL_IN_MILLISECONDS, - ) } diff --git a/dapp/src/hooks/store/index.ts b/dapp/src/hooks/store/index.ts index 07b9a19c0..e07660cc5 100644 --- a/dapp/src/hooks/store/index.ts +++ b/dapp/src/hooks/store/index.ts @@ -9,5 +9,4 @@ export * from "./useActionFlowTxHash" export * from "./useAllActivitiesCount" export * from "./useActionFlowPause" export * from "./useIsSignedMessage" -export { default as useHasFetchedActivities } from "./useHasFetchedActivities" export { default as useActivities } from "./useActivities" diff --git a/dapp/src/hooks/store/useHasFetchedActivities.ts b/dapp/src/hooks/store/useHasFetchedActivities.ts deleted file mode 100644 index 569978be9..000000000 --- a/dapp/src/hooks/store/useHasFetchedActivities.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { selectHasFetchedActivities } from "#/store/wallet" -import { useAppSelector } from "./useAppSelector" - -function useHasFetchedActivities() { - return useAppSelector(selectHasFetchedActivities) -} - -export default useHasFetchedActivities diff --git a/dapp/src/hooks/useIsFetchedWalletData.ts b/dapp/src/hooks/useIsFetchedWalletData.ts index 1d69280d4..f5382935d 100644 --- a/dapp/src/hooks/useIsFetchedWalletData.ts +++ b/dapp/src/hooks/useIsFetchedWalletData.ts @@ -1,19 +1,15 @@ import { queryKeysFactory } from "#/constants" import { useIsFetching } from "@tanstack/react-query" -import { useHasFetchedActivities, useIsSignedMessage } from "./store" +import { useIsSignedMessage } from "./store" const { userKeys } = queryKeysFactory export default function useIsFetchedWalletData() { const isSignedMessage = useIsSignedMessage() - const hasFetchedActivities = useHasFetchedActivities() const fetchingQueries = useIsFetching({ queryKey: userKeys.all, predicate: (query) => query.state.data === undefined, }) - return ( - (isSignedMessage && fetchingQueries === 0 && hasFetchedActivities) || - !isSignedMessage - ) + return (isSignedMessage && fetchingQueries === 0) || !isSignedMessage } diff --git a/dapp/src/store/tests/walletSlice.test.ts b/dapp/src/store/tests/walletSlice.test.ts index b29009f60..664ea714d 100644 --- a/dapp/src/store/tests/walletSlice.test.ts +++ b/dapp/src/store/tests/walletSlice.test.ts @@ -5,7 +5,6 @@ import { WalletState } from "../wallet" import reducer, { initialState, setActivities } from "../wallet/walletSlice" const isSignedMessage = false -const hasFetchedActivities = true const pendingActivityId = "0" const pendingActivity = createActivity({ id: pendingActivityId, @@ -27,7 +26,6 @@ describe("Wallet redux slice", () => { ...initialState, activities, isSignedMessage, - hasFetchedActivities, } }) @@ -46,7 +44,6 @@ describe("Wallet redux slice", () => { ...initialState, activities: newActivities, isSignedMessage, - hasFetchedActivities, }) }) }) @@ -98,7 +95,6 @@ describe("Wallet redux slice", () => { ...initialState, activities: currentActivities, isSignedMessage, - hasFetchedActivities, } }) @@ -107,7 +103,6 @@ describe("Wallet redux slice", () => { ...initialState, activities: newActivities, isSignedMessage, - hasFetchedActivities, }) }) }) @@ -138,7 +133,6 @@ describe("Wallet redux slice", () => { ...initialState, activities: newActivities, isSignedMessage, - hasFetchedActivities, }) }) }) diff --git a/dapp/src/store/wallet/walletSelector.ts b/dapp/src/store/wallet/walletSelector.ts index db8194cd6..8a1cba315 100644 --- a/dapp/src/store/wallet/walletSelector.ts +++ b/dapp/src/store/wallet/walletSelector.ts @@ -21,8 +21,5 @@ export const selectAllActivitiesCount = createSelector( export const selectIsSignedMessage = (state: RootState): boolean => state.wallet.isSignedMessage -export const selectHasFetchedActivities = (state: RootState): boolean => - state.wallet.hasFetchedActivities - export const selectWalletAddress = (state: RootState): string | undefined => state.wallet.address diff --git a/dapp/src/store/wallet/walletSlice.ts b/dapp/src/store/wallet/walletSlice.ts index fb0296445..4da460562 100644 --- a/dapp/src/store/wallet/walletSlice.ts +++ b/dapp/src/store/wallet/walletSlice.ts @@ -6,7 +6,6 @@ export type WalletState = { sharesBalance: bigint isSignedMessage: boolean activities: Activity[] - hasFetchedActivities: boolean address: string | undefined } @@ -15,7 +14,6 @@ export const initialState: WalletState = { sharesBalance: 0n, isSignedMessage: false, activities: [], - hasFetchedActivities: false, address: undefined, } @@ -34,7 +32,6 @@ export const walletSlice = createSlice({ }, setActivities(state, action: PayloadAction) { state.activities = action.payload - state.hasFetchedActivities = true }, resetState: (state) => ({ ...initialState, address: state.address }), activityInitialized(state, action: PayloadAction) { From 780d6eb5a9ea0a6c0e47268a1d0a2bb6f3c809c1 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 4 Dec 2024 10:18:52 +0100 Subject: [PATCH 2/9] Refactor tanstack queries for dApp Let's create a dedicated folder for tanstack queries make each query a separate hook. This approach will allow us to use queries whenever we want.Additionally, the code becomes more clear. --- dapp/src/components/MezoBeehiveModal.tsx | 4 +- .../TransactionModal/ActionFormModal.tsx | 4 +- .../ActiveStakingStep/DepositBTCModal.tsx | 14 +++---- .../ActiveUnstakingStep/SignMessageModal.tsx | 17 ++++---- .../UnstakeFormModal/index.tsx | 4 +- .../src/components/TransactionModal/index.tsx | 8 ++-- dapp/src/hooks/index.ts | 4 +- dapp/src/hooks/orangeKit/index.ts | 1 - dapp/src/hooks/sdk/index.ts | 2 - dapp/src/hooks/sdk/useFetchActivities.ts | 41 ------------------- dapp/src/hooks/sdk/useInitDataFromSdk.ts | 11 ----- dapp/src/hooks/store/index.ts | 1 + dapp/src/hooks/store/useWalletAddress.ts | 6 +++ dapp/src/hooks/tanstack-query/index.ts | 7 ++++ .../tanstack-query/useAcrePointsDataQuery.ts | 13 ++++++ .../useActivitiesQuery.ts | 0 .../useBitcoinBalanceQuery.ts} | 6 ++- .../useBitcoinPositionQuery.ts} | 2 +- .../useMatsQuery.ts} | 2 +- .../tanstack-query/useStatisticsQuery.ts | 13 ++++++ .../tanstack-query/useUserPointsDataQuery.ts | 16 ++++++++ dapp/src/hooks/useAcrePoints.ts | 22 ++++------ dapp/src/hooks/useInitApp.ts | 2 + dapp/src/hooks/useInvalidateQueries.ts | 16 -------- dapp/src/hooks/useStatistics.ts | 12 +----- dapp/src/hooks/useTrackActivities.ts | 13 ++++++ dapp/src/hooks/useWallet.ts | 11 ++--- dapp/src/pages/DashboardPage/BeehiveCard.tsx | 4 +- .../pages/DashboardPage/PositionDetails.tsx | 4 +- 29 files changed, 120 insertions(+), 140 deletions(-) delete mode 100644 dapp/src/hooks/sdk/useFetchActivities.ts create mode 100644 dapp/src/hooks/store/useWalletAddress.ts create mode 100644 dapp/src/hooks/tanstack-query/index.ts create mode 100644 dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts rename dapp/src/hooks/{sdk => tanstack-query}/useActivitiesQuery.ts (100%) rename dapp/src/hooks/{orangeKit/useBitcoinBalance.ts => tanstack-query/useBitcoinBalanceQuery.ts} (73%) rename dapp/src/hooks/{sdk/useBitcoinPosition.ts => tanstack-query/useBitcoinPositionQuery.ts} (94%) rename dapp/src/hooks/{useMats.ts => tanstack-query/useMatsQuery.ts} (89%) create mode 100644 dapp/src/hooks/tanstack-query/useStatisticsQuery.ts create mode 100644 dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts delete mode 100644 dapp/src/hooks/useInvalidateQueries.ts create mode 100644 dapp/src/hooks/useTrackActivities.ts diff --git a/dapp/src/components/MezoBeehiveModal.tsx b/dapp/src/components/MezoBeehiveModal.tsx index 18ca145d8..d33328608 100644 --- a/dapp/src/components/MezoBeehiveModal.tsx +++ b/dapp/src/components/MezoBeehiveModal.tsx @@ -18,11 +18,11 @@ import { AcreSignIcon, MatsIcon, MezoSignIcon } from "#/assets/icons" import { IconArrowUpRight, IconChartPieFilled } from "@tabler/icons-react" import { EXTERNAL_HREF } from "#/constants" import { numberToLocaleString } from "#/utils" -import { useMats } from "#/hooks" +import { useMatsQuery } from "#/hooks" import withBaseModal from "./ModalRoot/withBaseModal" function MezoBeehiveModalBase() { - const { data } = useMats() + const { data } = useMatsQuery() return ( <> diff --git a/dapp/src/components/TransactionModal/ActionFormModal.tsx b/dapp/src/components/TransactionModal/ActionFormModal.tsx index 8c50be64e..52647f56e 100644 --- a/dapp/src/components/TransactionModal/ActionFormModal.tsx +++ b/dapp/src/components/TransactionModal/ActionFormModal.tsx @@ -3,7 +3,7 @@ import { Box, ModalBody, ModalCloseButton, ModalHeader } from "@chakra-ui/react" import { useActionFlowStatus, useAppDispatch, - useBitcoinPosition, + useBitcoinPositionQuery, useMinWithdrawAmount, useStakeFlowContext, } from "#/hooks" @@ -40,7 +40,7 @@ function ActionFormModal({ type }: { type: ActionFlowType }) { const { initStake } = useStakeFlowContext() const dispatch = useAppDispatch() const minWithdrawAmount = useMinWithdrawAmount() - const { data } = useBitcoinPosition() + const { data } = useBitcoinPositionQuery() const depositedAmount = data?.estimatedBitcoinBalance ?? 0n const status = useActionFlowStatus() diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx index 08926094e..0d140d5fe 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx @@ -3,35 +3,31 @@ import { useActionFlowPause, useActionFlowTokenAmount, useAppDispatch, + useBitcoinBalanceQuery, useDepositBTCTransaction, - useInvalidateQueries, useStakeFlowContext, useVerifyDepositAddress, } from "#/hooks" import { eip1193, logPromiseFailure } from "#/utils" import { PROCESS_STATUSES } from "#/types" import { setStatus, setTxHash } from "#/store/action-flow" -import { ONE_SEC_IN_MILLISECONDS, queryKeysFactory } from "#/constants" +import { ONE_SEC_IN_MILLISECONDS } from "#/constants" import { useTimeout } from "@chakra-ui/react" import { useMutation } from "@tanstack/react-query" import WalletInteractionModal from "../WalletInteractionModal" -const { userKeys } = queryKeysFactory - export default function DepositBTCModal() { const tokenAmount = useActionFlowTokenAmount() const { btcAddress, depositReceipt, stake } = useStakeFlowContext() const verifyDepositAddress = useVerifyDepositAddress() const dispatch = useAppDispatch() const { handlePause } = useActionFlowPause() - const handleBitcoinBalanceInvalidation = useInvalidateQueries({ - queryKey: userKeys.balance(), - }) + const { refetch: refetchBitcoinBalance } = useBitcoinBalanceQuery() const onStakeBTCSuccess = useCallback(() => { - handleBitcoinBalanceInvalidation() + logPromiseFailure(refetchBitcoinBalance()) dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED)) - }, [dispatch, handleBitcoinBalanceInvalidation]) + }, [dispatch, refetchBitcoinBalance]) const onError = useCallback( (error: unknown) => { diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx index 915a9436a..243f5f742 100644 --- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx @@ -3,23 +3,21 @@ import { useActionFlowPause, useActionFlowTokenAmount, useAppDispatch, - useInvalidateQueries, + useBitcoinPositionQuery, useModal, useTimeout, useTransactionDetails, } from "#/hooks" import { ACTION_FLOW_TYPES, PROCESS_STATUSES } from "#/types" -import { dateToUnixTimestamp, eip1193 } from "#/utils" +import { dateToUnixTimestamp, eip1193, logPromiseFailure } from "#/utils" import { setStatus } from "#/store/action-flow" import { useInitializeWithdraw } from "#/acre-react/hooks" -import { ONE_SEC_IN_MILLISECONDS, queryKeysFactory } from "#/constants" +import { ONE_SEC_IN_MILLISECONDS } from "#/constants" import { activityInitialized } from "#/store/wallet" import { useMutation } from "@tanstack/react-query" import BuildTransactionModal from "./BuildTransactionModal" import WalletInteractionModal from "../WalletInteractionModal" -const { userKeys } = queryKeysFactory - type WithdrawalStatus = "building-data" | "built-data" | "signature" const sessionIdToPromise: Record< @@ -40,9 +38,8 @@ export default function SignMessageModal() { const { closeModal } = useModal() const { handlePause } = useActionFlowPause() const initializeWithdraw = useInitializeWithdraw() - const handleBitcoinPositionInvalidation = useInvalidateQueries({ - queryKey: userKeys.position(), - }) + const { refetch: refetchBitcoinPosition } = useBitcoinPositionQuery() + const sessionId = useRef(Math.random()) const { transactionFee } = useTransactionDetails( amount, @@ -76,9 +73,9 @@ export default function SignMessageModal() { }, []) const onSignMessageSuccess = useCallback(() => { - handleBitcoinPositionInvalidation() + logPromiseFailure(refetchBitcoinPosition()) dispatch(setStatus(PROCESS_STATUSES.SUCCEEDED)) - }, [dispatch, handleBitcoinPositionInvalidation]) + }, [dispatch, refetchBitcoinPosition]) const onSignMessageError = useCallback( (error: unknown) => { diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx index afab79189..5b095b5dd 100644 --- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx +++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx @@ -5,7 +5,7 @@ import { FormSubmitButton } from "#/components/shared/Form" import { ACTION_FLOW_TYPES, BaseFormProps, PROCESS_STATUSES } from "#/types" import { useActionFlowStatus, - useBitcoinPosition, + useBitcoinPositionQuery, useMinWithdrawAmount, } from "#/hooks" import { fixedPointNumberToString, getCurrencyByType } from "#/utils" @@ -15,7 +15,7 @@ import ActionDurationEstimation from "../../ActionDurationEstimation" function UnstakeFormModal({ onSubmitForm, }: BaseFormProps) { - const { data } = useBitcoinPosition() + const { data } = useBitcoinPositionQuery() const balance = data?.estimatedBitcoinBalance ?? 0n const minTokenAmount = useMinWithdrawAmount() const status = useActionFlowStatus() diff --git a/dapp/src/components/TransactionModal/index.tsx b/dapp/src/components/TransactionModal/index.tsx index dd30a73ad..51fd2da29 100644 --- a/dapp/src/components/TransactionModal/index.tsx +++ b/dapp/src/components/TransactionModal/index.tsx @@ -1,8 +1,8 @@ import React, { useEffect } from "react" import { StakeFlowProvider } from "#/contexts" import { + useActivitiesQuery, useAppDispatch, - useFetchActivities, useIsSignedMessage, useTransactionModal, } from "#/hooks" @@ -18,7 +18,7 @@ type TransactionModalProps = { type: ActionFlowType } & BaseModalProps function TransactionModalBase({ type, closeModal }: TransactionModalProps) { const dispatch = useAppDispatch() - const fetchActivities = useFetchActivities() + const { refetch: refetchActivities } = useActivitiesQuery() useEffect(() => { dispatch(setType(type)) @@ -28,9 +28,9 @@ function TransactionModalBase({ type, closeModal }: TransactionModalProps) { useEffect(() => { return () => { dispatch(resetState()) - logPromiseFailure(fetchActivities()) + logPromiseFailure(refetchActivities()) } - }, [dispatch, fetchActivities]) + }, [dispatch, refetchActivities]) return ( diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 28bc42703..a4f35511f 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -1,6 +1,7 @@ export * from "./store" export * from "./sdk" export * from "./orangeKit" +export * from "./tanstack-query" export * from "./useDetectThemeMode" export * from "./useSidebar" export * from "./useDocsDrawer" @@ -21,14 +22,12 @@ export * from "./useVerifyDepositAddress" export { default as useStatistics } from "./useStatistics" export * from "./useDisconnectWallet" export * from "./useWalletConnectionError" -export { default as useInvalidateQueries } from "./useInvalidateQueries" export { default as useResetWalletState } from "./useResetWalletState" export { default as useMobileMode } from "./useMobileMode" export { default as useBitcoinRecoveryAddress } from "./useBitcoinRecoveryAddress" export { default as useIsFetchedWalletData } from "./useIsFetchedWalletData" export { default as useLocalStorage } from "./useLocalStorage" export { default as useReferral } from "./useReferral" -export { default as useMats } from "./useMats" export { default as useIsEmbed } from "./useIsEmbed" export { default as useTriggerConnectWalletModal } from "./useTriggerConnectWalletModal" export { default as useLastUsedBtcAddress } from "./useLastUsedBtcAddress" @@ -38,3 +37,4 @@ export { default as useScrollbarVisibility } from "./useScrollbarVisibility" export { default as useAccessCode } from "./useAccessCode" export { default as useFormField } from "./useFormField" export { default as useDepositBTCTransaction } from "./useDepositBTCTransaction" +export { default as useTrackActivities } from "./useTrackActivities" diff --git a/dapp/src/hooks/orangeKit/index.ts b/dapp/src/hooks/orangeKit/index.ts index 96fd2cb7a..dcc5160a5 100644 --- a/dapp/src/hooks/orangeKit/index.ts +++ b/dapp/src/hooks/orangeKit/index.ts @@ -4,4 +4,3 @@ export * from "./useConnectors" export * from "./useAccountsChangedUnisat" export * from "./useAccountsChangedOKX" export * from "./useAccountChangedOKX" -export { default as useBitcoinBalance } from "./useBitcoinBalance" diff --git a/dapp/src/hooks/sdk/index.ts b/dapp/src/hooks/sdk/index.ts index 0759a84ea..dca3d2ffa 100644 --- a/dapp/src/hooks/sdk/index.ts +++ b/dapp/src/hooks/sdk/index.ts @@ -1,6 +1,4 @@ export * from "./useInitializeAcreSdk" export * from "./useFetchMinDepositAmount" export * from "./useInitDataFromSdk" -export * from "./useFetchActivities" export * from "./useMinWithdrawAmount" -export { default as useBitcoinPosition } from "./useBitcoinPosition" diff --git a/dapp/src/hooks/sdk/useFetchActivities.ts b/dapp/src/hooks/sdk/useFetchActivities.ts deleted file mode 100644 index 0d35bcbcc..000000000 --- a/dapp/src/hooks/sdk/useFetchActivities.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { useCallback } from "react" -import { setActivities } from "#/store/wallet" -import { useAcreContext } from "#/acre-react/hooks" -import { Activity } from "#/types" -import { DepositStatus } from "@acre-btc/sdk" -import { useAppDispatch } from "../store/useAppDispatch" -import { useWallet } from "../useWallet" - -export function useFetchActivities() { - const dispatch = useAppDispatch() - const { address } = useWallet() - const { acre, isConnected } = useAcreContext() - - return useCallback(async () => { - if (!acre || !isConnected || !address) return - - const deposits: Activity[] = (await acre.account.getDeposits()).map( - (deposit) => ({ - ...deposit, - status: - deposit.status === DepositStatus.Finalized ? "completed" : "pending", - type: "deposit", - }), - ) - - const withdrawals: Activity[] = (await acre.account.getWithdrawals()).map( - (withdraw) => { - const { bitcoinTransactionId, status, ...rest } = withdraw - - return { - ...rest, - txHash: bitcoinTransactionId, - status: status === "finalized" ? "completed" : "pending", - type: "withdraw", - } - }, - ) - - dispatch(setActivities([...deposits, ...withdrawals])) - }, [acre, dispatch, isConnected, address]) -} diff --git a/dapp/src/hooks/sdk/useInitDataFromSdk.ts b/dapp/src/hooks/sdk/useInitDataFromSdk.ts index 3e5e618be..f912be723 100644 --- a/dapp/src/hooks/sdk/useInitDataFromSdk.ts +++ b/dapp/src/hooks/sdk/useInitDataFromSdk.ts @@ -1,16 +1,5 @@ -import { useEffect } from "react" -import { setActivities } from "#/store/wallet" import { useFetchMinDepositAmount } from "./useFetchMinDepositAmount" -import useActivitiesQuery from "./useActivitiesQuery" -import { useAppDispatch } from "../store/useAppDispatch" export function useInitDataFromSdk() { - const { data } = useActivitiesQuery() - const dispatch = useAppDispatch() - - useEffect(() => { - dispatch(setActivities(data ?? [])) - }, [data, dispatch]) - useFetchMinDepositAmount() } diff --git a/dapp/src/hooks/store/index.ts b/dapp/src/hooks/store/index.ts index e07660cc5..12063841d 100644 --- a/dapp/src/hooks/store/index.ts +++ b/dapp/src/hooks/store/index.ts @@ -10,3 +10,4 @@ export * from "./useAllActivitiesCount" export * from "./useActionFlowPause" export * from "./useIsSignedMessage" export { default as useActivities } from "./useActivities" +export { default as useWalletAddress } from "./useWalletAddress" diff --git a/dapp/src/hooks/store/useWalletAddress.ts b/dapp/src/hooks/store/useWalletAddress.ts new file mode 100644 index 000000000..424d4cd8f --- /dev/null +++ b/dapp/src/hooks/store/useWalletAddress.ts @@ -0,0 +1,6 @@ +import { selectWalletAddress } from "#/store/wallet" +import { useAppSelector } from "./useAppSelector" + +export default function useWalletAddress() { + return useAppSelector(selectWalletAddress) +} diff --git a/dapp/src/hooks/tanstack-query/index.ts b/dapp/src/hooks/tanstack-query/index.ts new file mode 100644 index 000000000..f0857ebfd --- /dev/null +++ b/dapp/src/hooks/tanstack-query/index.ts @@ -0,0 +1,7 @@ +export { default as useAcrePointsDataQuery } from "./useAcrePointsDataQuery" +export { default as useActivitiesQuery } from "./useActivitiesQuery" +export { default as useBitcoinBalanceQuery } from "./useBitcoinBalanceQuery" +export { default as useBitcoinPositionQuery } from "./useBitcoinPositionQuery" +export { default as useUserPointsDataQuery } from "./useUserPointsDataQuery" +export { default as useMatsQuery } from "./useMatsQuery" +export { default as useStatisticsQuery } from "./useStatisticsQuery" diff --git a/dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts b/dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts new file mode 100644 index 000000000..50fcdb823 --- /dev/null +++ b/dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts @@ -0,0 +1,13 @@ +import { queryKeysFactory, REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants" +import { useQuery } from "@tanstack/react-query" +import { acreApi } from "#/utils" + +const { acreKeys } = queryKeysFactory + +export default function useAcrePointsDataQuery() { + return useQuery({ + queryKey: [...acreKeys.pointsData()], + queryFn: async () => acreApi.getPointsData(), + refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, + }) +} diff --git a/dapp/src/hooks/sdk/useActivitiesQuery.ts b/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts similarity index 100% rename from dapp/src/hooks/sdk/useActivitiesQuery.ts rename to dapp/src/hooks/tanstack-query/useActivitiesQuery.ts diff --git a/dapp/src/hooks/orangeKit/useBitcoinBalance.ts b/dapp/src/hooks/tanstack-query/useBitcoinBalanceQuery.ts similarity index 73% rename from dapp/src/hooks/orangeKit/useBitcoinBalance.ts rename to dapp/src/hooks/tanstack-query/useBitcoinBalanceQuery.ts index b7ed40eb8..e0932682f 100644 --- a/dapp/src/hooks/orangeKit/useBitcoinBalance.ts +++ b/dapp/src/hooks/tanstack-query/useBitcoinBalanceQuery.ts @@ -1,10 +1,12 @@ import { useQuery } from "@tanstack/react-query" import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" -import { useBitcoinProvider } from "./useBitcoinProvider" +import { useWalletAddress } from "../store" +import { useBitcoinProvider } from "../orangeKit/useBitcoinProvider" const { userKeys } = queryKeysFactory -export default function useBitcoinBalance(address: string | undefined) { +export default function useBitcoinBalanceQuery() { + const address = useWalletAddress() const provider = useBitcoinProvider() return useQuery({ diff --git a/dapp/src/hooks/sdk/useBitcoinPosition.ts b/dapp/src/hooks/tanstack-query/useBitcoinPositionQuery.ts similarity index 94% rename from dapp/src/hooks/sdk/useBitcoinPosition.ts rename to dapp/src/hooks/tanstack-query/useBitcoinPositionQuery.ts index f1036ef1a..b9fdc3732 100644 --- a/dapp/src/hooks/sdk/useBitcoinPosition.ts +++ b/dapp/src/hooks/tanstack-query/useBitcoinPositionQuery.ts @@ -5,7 +5,7 @@ import { useWallet } from "../useWallet" const { userKeys } = queryKeysFactory -export default function useBitcoinPosition() { +export default function useBitcoinPositionQuery() { const { address } = useWallet() const { acre, isConnected } = useAcreContext() diff --git a/dapp/src/hooks/useMats.ts b/dapp/src/hooks/tanstack-query/useMatsQuery.ts similarity index 89% rename from dapp/src/hooks/useMats.ts rename to dapp/src/hooks/tanstack-query/useMatsQuery.ts index fe62d63f2..b861e9469 100644 --- a/dapp/src/hooks/useMats.ts +++ b/dapp/src/hooks/tanstack-query/useMatsQuery.ts @@ -4,7 +4,7 @@ import { acreApi } from "#/utils" const { acreKeys } = queryKeysFactory -export default function useMats() { +export default function useMatsQuery() { return useQuery({ queryKey: [...acreKeys.mats()], queryFn: async () => acreApi.getMats(), diff --git a/dapp/src/hooks/tanstack-query/useStatisticsQuery.ts b/dapp/src/hooks/tanstack-query/useStatisticsQuery.ts new file mode 100644 index 000000000..a7661a7ea --- /dev/null +++ b/dapp/src/hooks/tanstack-query/useStatisticsQuery.ts @@ -0,0 +1,13 @@ +import { useQuery } from "@tanstack/react-query" +import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" +import { acreApi } from "#/utils" + +const { acreKeys } = queryKeysFactory + +export default function useStatisticsQuery() { + return useQuery({ + queryKey: [...acreKeys.statistics()], + queryFn: acreApi.getStatistics, + refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, + }) +} diff --git a/dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts b/dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts new file mode 100644 index 000000000..a18d37976 --- /dev/null +++ b/dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts @@ -0,0 +1,16 @@ +import { queryKeysFactory } from "#/constants" +import { useQuery } from "@tanstack/react-query" +import { acreApi } from "#/utils" +import { useWallet } from "../useWallet" + +const { userKeys } = queryKeysFactory + +export default function useUserPointsDataQuery() { + const { ethAddress = "" } = useWallet() + + return useQuery({ + queryKey: [...userKeys.pointsData(), ethAddress], + enabled: !!ethAddress, + queryFn: async () => acreApi.getPointsDataByUser(ethAddress), + }) +} diff --git a/dapp/src/hooks/useAcrePoints.ts b/dapp/src/hooks/useAcrePoints.ts index 81c329c14..52a092441 100644 --- a/dapp/src/hooks/useAcrePoints.ts +++ b/dapp/src/hooks/useAcrePoints.ts @@ -1,11 +1,12 @@ -import { useMutation, useQuery } from "@tanstack/react-query" +import { useMutation } from "@tanstack/react-query" import { acreApi } from "#/utils" -import { queryKeysFactory, REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants" import { MODAL_TYPES } from "#/types" import { useWallet } from "./useWallet" import { useModal } from "./useModal" - -const { userKeys, acreKeys } = queryKeysFactory +import { + useAcrePointsDataQuery, + useUserPointsDataQuery, +} from "./tanstack-query" type UseAcrePointsReturnType = { totalBalance: number @@ -22,17 +23,8 @@ export default function useAcrePoints(): UseAcrePointsReturnType { const { ethAddress = "" } = useWallet() const { openModal } = useModal() - const userPointsDataQuery = useQuery({ - queryKey: [...userKeys.pointsData(), ethAddress], - enabled: !!ethAddress, - queryFn: async () => acreApi.getPointsDataByUser(ethAddress), - }) - - const pointsDataQuery = useQuery({ - queryKey: [...acreKeys.pointsData()], - queryFn: async () => acreApi.getPointsData(), - refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, - }) + const userPointsDataQuery = useUserPointsDataQuery() + const pointsDataQuery = useAcrePointsDataQuery() const { mutate: claimPoints } = useMutation({ mutationFn: async () => acreApi.claimPoints(ethAddress), diff --git a/dapp/src/hooks/useInitApp.ts b/dapp/src/hooks/useInitApp.ts index caf792595..79af43506 100644 --- a/dapp/src/hooks/useInitApp.ts +++ b/dapp/src/hooks/useInitApp.ts @@ -6,6 +6,7 @@ import { useSentry } from "./sentry" import useDetectEmbed from "./useDetectEmbed" import { useDisconnectWallet } from "./useDisconnectWallet" import { useFetchBTCPriceUSD } from "./useFetchBTCPriceUSD" +import useTrackActivities from "./useTrackActivities" export function useInitApp() { // TODO: Let's uncomment when dark mode is ready @@ -19,4 +20,5 @@ export function useInitApp() { useAccountChangedOKX() useAccountsChangedOKX() useAccountsChangedUnisat() + useTrackActivities() } diff --git a/dapp/src/hooks/useInvalidateQueries.ts b/dapp/src/hooks/useInvalidateQueries.ts deleted file mode 100644 index 2f64ae0f1..000000000 --- a/dapp/src/hooks/useInvalidateQueries.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { logPromiseFailure } from "#/utils" -import { QueryClient, useQueryClient } from "@tanstack/react-query" -import { useCallback } from "react" - -type InvalidateQueriesParams = Parameters - -export default function useInvalidateQueries( - ...params: InvalidateQueriesParams -) { - const queryClient = useQueryClient() - - return useCallback( - () => logPromiseFailure(queryClient.invalidateQueries(...params)), - [params, queryClient], - ) -} diff --git a/dapp/src/hooks/useStatistics.ts b/dapp/src/hooks/useStatistics.ts index 22dc77acd..5d8583efc 100644 --- a/dapp/src/hooks/useStatistics.ts +++ b/dapp/src/hooks/useStatistics.ts @@ -1,15 +1,7 @@ -import { queryKeysFactory, REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants" -import { acreApi } from "#/utils" -import { useQuery } from "@tanstack/react-query" - -const { acreKeys } = queryKeysFactory +import { useStatisticsQuery } from "./tanstack-query" const useStatistics = () => { - const { data } = useQuery({ - queryKey: [...acreKeys.statistics()], - queryFn: acreApi.getStatistics, - refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, - }) + const { data } = useStatisticsQuery() const bitcoinTvl = data?.btc ?? 0 const usdTvl = data?.usd ?? 0 diff --git a/dapp/src/hooks/useTrackActivities.ts b/dapp/src/hooks/useTrackActivities.ts new file mode 100644 index 000000000..231f0a477 --- /dev/null +++ b/dapp/src/hooks/useTrackActivities.ts @@ -0,0 +1,13 @@ +import { useEffect } from "react" +import { setActivities } from "#/store/wallet" +import { useActivitiesQuery } from "./tanstack-query" +import { useAppDispatch } from "./store" + +export default function useTrackActivities() { + const { data } = useActivitiesQuery() + const dispatch = useAppDispatch() + + useEffect(() => { + dispatch(setActivities(data ?? [])) + }, [data, dispatch]) +} diff --git a/dapp/src/hooks/useWallet.ts b/dapp/src/hooks/useWallet.ts index 504b0a453..fd5451c83 100644 --- a/dapp/src/hooks/useWallet.ts +++ b/dapp/src/hooks/useWallet.ts @@ -16,11 +16,12 @@ import { Status, } from "#/types" import { useMutation, useQueryClient } from "@tanstack/react-query" -import { useDispatch, useSelector } from "react-redux" -import { selectWalletAddress, setAddress } from "#/store/wallet" -import useBitcoinBalance from "./orangeKit/useBitcoinBalance" +import { useDispatch } from "react-redux" +import { setAddress } from "#/store/wallet" import useResetWalletState from "./useResetWalletState" import useLastUsedBtcAddress from "./useLastUsedBtcAddress" +import useBitcoinBalanceQuery from "./tanstack-query/useBitcoinBalanceQuery" +import { useWalletAddress } from "./store" const { typeConversionToConnector, typeConversionToOrangeKitConnector } = orangeKit @@ -45,12 +46,12 @@ type UseWalletReturn = { export function useWallet(): UseWalletReturn { const queryClient = useQueryClient() const dispatch = useDispatch() - const btcAddress = useSelector(selectWalletAddress) + const btcAddress = useWalletAddress() const resetWalletState = useResetWalletState() const { setAddressInLocalStorage, removeAddressFromLocalStorage } = useLastUsedBtcAddress() - const { data: balance } = useBitcoinBalance(btcAddress) + const { data: balance } = useBitcoinBalanceQuery() const chainId = useChainId() const config = useConfig() diff --git a/dapp/src/pages/DashboardPage/BeehiveCard.tsx b/dapp/src/pages/DashboardPage/BeehiveCard.tsx index 9168d0b5b..2c63cceaf 100644 --- a/dapp/src/pages/DashboardPage/BeehiveCard.tsx +++ b/dapp/src/pages/DashboardPage/BeehiveCard.tsx @@ -13,7 +13,7 @@ import { VStack, } from "@chakra-ui/react" import { MezoSignIcon } from "#/assets/icons" -import { useMats, useModal } from "#/hooks" +import { useMatsQuery, useModal } from "#/hooks" import { MODAL_TYPES } from "#/types" import beehiveIllustrationSrc from "#/assets/images/beehive-illustration.svg" import UserDataSkeleton from "#/components/shared/UserDataSkeleton" @@ -22,7 +22,7 @@ import InfoTooltip from "#/components/shared/InfoTooltip" export default function BeehiveCard(props: CardProps) { const { openModal } = useModal() - const { data } = useMats() + const { data } = useMatsQuery() const handleOpenBeehiveModal = () => { openModal(MODAL_TYPES.MEZO_BEEHIVE) diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index db3dbdb06..40d095ad8 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -2,7 +2,7 @@ import React from "react" import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion" import { useAllActivitiesCount, - useBitcoinPosition, + useBitcoinPositionQuery, useTransactionModal, useStatistics, useWallet, @@ -36,7 +36,7 @@ const buttonStyles: ButtonProps = { } export default function PositionDetails() { - const { data } = useBitcoinPosition() + const { data } = useBitcoinPositionQuery() const bitcoinAmount = data?.estimatedBitcoinBalance ?? 0n const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE) From 1d4f0224762ae1ce8593c26cd1f32ebb3dc5af1c Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 4 Dec 2024 10:30:31 +0100 Subject: [PATCH 3/9] Fix for checking the status of fetched data The previous solution was wrong because `useIsFetching` returns the number of the queries that your application is loading or fetching in the background. We should check the fetch status for all the data we are interested in. --- dapp/src/hooks/useIsFetchedWalletData.ts | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/dapp/src/hooks/useIsFetchedWalletData.ts b/dapp/src/hooks/useIsFetchedWalletData.ts index f5382935d..8cde4000c 100644 --- a/dapp/src/hooks/useIsFetchedWalletData.ts +++ b/dapp/src/hooks/useIsFetchedWalletData.ts @@ -1,15 +1,23 @@ -import { queryKeysFactory } from "#/constants" -import { useIsFetching } from "@tanstack/react-query" import { useIsSignedMessage } from "./store" - -const { userKeys } = queryKeysFactory +import { + useActivitiesQuery, + useBitcoinBalanceQuery, + useBitcoinPositionQuery, + useUserPointsDataQuery, +} from "./tanstack-query" export default function useIsFetchedWalletData() { const isSignedMessage = useIsSignedMessage() - const fetchingQueries = useIsFetching({ - queryKey: userKeys.all, - predicate: (query) => query.state.data === undefined, - }) + const { isFetched: isBitcoinBalanceFetched } = useBitcoinBalanceQuery() + const { isFetched: isBitcoinPositionFetched } = useBitcoinPositionQuery() + const { isFetched: isActivitiesFetched } = useActivitiesQuery() + const { isFetched: isPointsDataFetched } = useUserPointsDataQuery() + + const isFetchedData = + isBitcoinBalanceFetched && + isActivitiesFetched && + isBitcoinPositionFetched && + isPointsDataFetched - return (isSignedMessage && fetchingQueries === 0) || !isSignedMessage + return (isSignedMessage && isFetchedData) || !isSignedMessage } From 9ae921864435b149714a8c5f68c85ef86c2adf53 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 4 Dec 2024 12:11:37 +0100 Subject: [PATCH 4/9] Add comment: why activities are stored in redux --- dapp/src/store/wallet/walletSlice.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dapp/src/store/wallet/walletSlice.ts b/dapp/src/store/wallet/walletSlice.ts index 4da460562..ff480fae3 100644 --- a/dapp/src/store/wallet/walletSlice.ts +++ b/dapp/src/store/wallet/walletSlice.ts @@ -5,6 +5,12 @@ export type WalletState = { estimatedBtcBalance: bigint sharesBalance: bigint isSignedMessage: boolean + // Activities are saved in redux because the Acre subgraph may or may not be + // up to date with the chain. As a result, if we fetch data from Acre SDK + // after the withdrawal is initiated, we may not yet see this activity. + // Storing activities in redux gives us the option to add activities manually + // by `activityInitialized`. However, fetching the activity from the Acre SDK + // again later should already return us the updated data. activities: Activity[] address: string | undefined } From c2ccf9b59584a5edb6caabc29297739c33fa6be7 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Fri, 6 Dec 2024 13:02:08 +0100 Subject: [PATCH 5/9] Use `queryClient.setQueriesData` to update activities `setQueriesData` is a synchronous function that can be used to immediately update cached data of multiple queries by using matching the query key. With the new approach, we can remove activities from redux. --- .../ActiveUnstakingStep/SignMessageModal.tsx | 78 +++++----- dapp/src/hooks/index.ts | 2 +- dapp/src/hooks/store/index.ts | 2 - dapp/src/hooks/store/useActivities.ts | 6 - dapp/src/hooks/store/useAllActivitiesCount.ts | 6 - .../tanstack-query/useActivitiesQuery.ts | 3 +- dapp/src/hooks/useActivitiesCount.ts | 6 + dapp/src/hooks/useInitApp.ts | 2 - dapp/src/hooks/useTrackActivities.ts | 13 -- .../pages/DashboardPage/AcreTVLMessage.tsx | 4 +- .../pages/DashboardPage/PositionDetails.tsx | 4 +- .../TransactionHistory/TransactionTable.tsx | 6 +- .../TransactionHistory/index.tsx | 4 +- dapp/src/store/tests/walletSlice.test.ts | 140 ------------------ dapp/src/store/wallet/walletSelector.ts | 12 -- dapp/src/store/wallet/walletSlice.ts | 18 --- 16 files changed, 60 insertions(+), 246 deletions(-) delete mode 100644 dapp/src/hooks/store/useActivities.ts delete mode 100644 dapp/src/hooks/store/useAllActivitiesCount.ts create mode 100644 dapp/src/hooks/useActivitiesCount.ts delete mode 100644 dapp/src/hooks/useTrackActivities.ts delete mode 100644 dapp/src/store/tests/walletSlice.test.ts diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx index b97abf714..f9662f219 100644 --- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx @@ -9,13 +9,12 @@ import { useTimeout, useTransactionDetails, } from "#/hooks" -import { ACTION_FLOW_TYPES, PROCESS_STATUSES } from "#/types" +import { ACTION_FLOW_TYPES, Activity, PROCESS_STATUSES } from "#/types" import { dateToUnixTimestamp, eip1193, logPromiseFailure } from "#/utils" import { setStatus } from "#/store/action-flow" import { useInitializeWithdraw } from "#/acre-react/hooks" -import { ONE_SEC_IN_MILLISECONDS } from "#/constants" -import { activityInitialized } from "#/store/wallet" -import { useMutation } from "@tanstack/react-query" +import { ONE_SEC_IN_MILLISECONDS, queryKeysFactory } from "#/constants" +import { useMutation, useQueryClient } from "@tanstack/react-query" import { PostHogEvent } from "#/posthog/events" import { usePostHogCapture } from "#/hooks/posthog/usePostHogCapture" import BuildTransactionModal from "./BuildTransactionModal" @@ -27,6 +26,7 @@ export default function SignMessageModal() { const [status, setWaitingStatus] = useState("building-data") const dispatch = useAppDispatch() + const queryClient = useQueryClient() const tokenAmount = useActionFlowTokenAmount() const amount = tokenAmount?.amount const { closeModal } = useModal() @@ -100,38 +100,44 @@ export default function SignMessageModal() { onSignMessageCallback, ) - dispatch( - activityInitialized({ - // Note that the withdraw id returned from the Acre SDK while fetching - // the withdrawals has the following pattern: - // `-`. The redemption key returned during the - // withdrawal initialization does not contain the `-` suffix - // because there may be delay between indexing the Acre subgraph and - // the time when a transaction was actually made and it's hard to get - // the exact number of the redemptions with the same key. Eg: - // - a user initialized a withdraw, - // - the Acre SDK is asking the subgraph for the number of withdrawals - // with the same redemption key, - // - the Acre subgraph may or may not be up to date with the chain and - // we are not sure if we should add +1 to the counter or the - // returned value already includes the requested withdraw from the - // first step. So we can't create the correct withdraw id. - // So here we set the id as a redemption key. Only one pending - // withdrawal can exist with the same redemption key, so when the user - // can initialize the next withdrawal with the same redemption key, we - // assume the dapp should already re-fetch all withdrawals with the - // correct IDs and move the `pending` redemption to `completed` - // section with the proper id. - id: redemptionKey, - type: "withdraw", - status: "pending", - // This is a requested amount. The amount of BTC received will be - // around: `amount - transactionFee.total`. - amount: amount - transactionFee.acre, - initializedAt: dateToUnixTimestamp(), - // The message is signed immediately after the initialization. - finalizedAt: dateToUnixTimestamp(), - }), + queryClient.setQueriesData( + { queryKey: queryKeysFactory.userKeys.activities() }, + (oldData: Activity[] | undefined) => { + const newActivity: Activity = { + // Note that the withdraw id returned from the Acre SDK while fetching + // the withdrawals has the following pattern: + // `-`. The redemption key returned during the + // withdrawal initialization does not contain the `-` suffix + // because there may be delay between indexing the Acre subgraph and + // the time when a transaction was actually made and it's hard to get + // the exact number of the redemptions with the same key. Eg: + // - a user initialized a withdraw, + // - the Acre SDK is asking the subgraph for the number of withdrawals + // with the same redemption key, + // - the Acre subgraph may or may not be up to date with the chain and + // we are not sure if we should add +1 to the counter or the + // returned value already includes the requested withdraw from the + // first step. So we can't create the correct withdraw id. + // So here we set the id as a redemption key. Only one pending + // withdrawal can exist with the same redemption key, so when the user + // can initialize the next withdrawal with the same redemption key, we + // assume the dapp should already re-fetch all withdrawals with the + // correct IDs and move the `pending` redemption to `completed` + // section with the proper id. + id: redemptionKey, + type: "withdraw", + status: "pending", + // This is a requested amount. The amount of BTC received will be + // around: `amount - transactionFee.total`. + amount: amount - transactionFee.acre, + initializedAt: dateToUnixTimestamp(), + // The message is signed immediately after the initialization. + finalizedAt: dateToUnixTimestamp(), + } + + if (oldData) return [newActivity, ...oldData] + return [newActivity] + }, ) }, onSuccess: onSignMessageSuccess, diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index f0a885c2d..79d7e2983 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -37,5 +37,5 @@ export { default as useScrollbarVisibility } from "./useScrollbarVisibility" export { default as useAccessCode } from "./useAccessCode" export { default as useFormField } from "./useFormField" export { default as useDepositBTCTransaction } from "./useDepositBTCTransaction" -export { default as useTrackActivities } from "./useTrackActivities" export { default as useCancelPromise } from "./useCancelPromise" +export { default as useActivitiesCount } from "./useActivitiesCount" diff --git a/dapp/src/hooks/store/index.ts b/dapp/src/hooks/store/index.ts index 12063841d..b88527385 100644 --- a/dapp/src/hooks/store/index.ts +++ b/dapp/src/hooks/store/index.ts @@ -6,8 +6,6 @@ export * from "./useActionFlowStatus" export * from "./useActionFlowActiveStep" export * from "./useActionFlowTokenAmount" export * from "./useActionFlowTxHash" -export * from "./useAllActivitiesCount" export * from "./useActionFlowPause" export * from "./useIsSignedMessage" -export { default as useActivities } from "./useActivities" export { default as useWalletAddress } from "./useWalletAddress" diff --git a/dapp/src/hooks/store/useActivities.ts b/dapp/src/hooks/store/useActivities.ts deleted file mode 100644 index b9f022b29..000000000 --- a/dapp/src/hooks/store/useActivities.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { selectActivities } from "#/store/wallet" -import { useAppSelector } from "./useAppSelector" - -export default function useActivities() { - return useAppSelector(selectActivities) -} diff --git a/dapp/src/hooks/store/useAllActivitiesCount.ts b/dapp/src/hooks/store/useAllActivitiesCount.ts deleted file mode 100644 index cbf4e711f..000000000 --- a/dapp/src/hooks/store/useAllActivitiesCount.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { selectAllActivitiesCount } from "#/store/wallet" -import { useAppSelector } from "./useAppSelector" - -export function useAllActivitiesCount() { - return useAppSelector(selectAllActivitiesCount) -} diff --git a/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts b/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts index f13f52466..9e03bc0c0 100644 --- a/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts +++ b/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts @@ -3,6 +3,7 @@ import { useQuery } from "@tanstack/react-query" import { Activity } from "#/types" import { DepositStatus } from "@acre-btc/sdk" import { useAcreContext } from "#/acre-react/hooks" +import { sortActivitiesByTimestamp } from "#/utils" import { useWallet } from "../useWallet" const { userKeys } = queryKeysFactory @@ -40,7 +41,7 @@ export default function useActivitiesQuery() { } }, ) - return [...deposits, ...withdrawals] + return sortActivitiesByTimestamp([...deposits, ...withdrawals]) }, refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, }) diff --git a/dapp/src/hooks/useActivitiesCount.ts b/dapp/src/hooks/useActivitiesCount.ts new file mode 100644 index 000000000..279fe6539 --- /dev/null +++ b/dapp/src/hooks/useActivitiesCount.ts @@ -0,0 +1,6 @@ +import { useActivitiesQuery } from "./tanstack-query" + +export default function useActivitiesCount() { + const { data } = useActivitiesQuery() + return data ? data.length : 0 +} diff --git a/dapp/src/hooks/useInitApp.ts b/dapp/src/hooks/useInitApp.ts index 79af43506..caf792595 100644 --- a/dapp/src/hooks/useInitApp.ts +++ b/dapp/src/hooks/useInitApp.ts @@ -6,7 +6,6 @@ import { useSentry } from "./sentry" import useDetectEmbed from "./useDetectEmbed" import { useDisconnectWallet } from "./useDisconnectWallet" import { useFetchBTCPriceUSD } from "./useFetchBTCPriceUSD" -import useTrackActivities from "./useTrackActivities" export function useInitApp() { // TODO: Let's uncomment when dark mode is ready @@ -20,5 +19,4 @@ export function useInitApp() { useAccountChangedOKX() useAccountsChangedOKX() useAccountsChangedUnisat() - useTrackActivities() } diff --git a/dapp/src/hooks/useTrackActivities.ts b/dapp/src/hooks/useTrackActivities.ts deleted file mode 100644 index 231f0a477..000000000 --- a/dapp/src/hooks/useTrackActivities.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useEffect } from "react" -import { setActivities } from "#/store/wallet" -import { useActivitiesQuery } from "./tanstack-query" -import { useAppDispatch } from "./store" - -export default function useTrackActivities() { - const { data } = useActivitiesQuery() - const dispatch = useAppDispatch() - - useEffect(() => { - dispatch(setActivities(data ?? [])) - }, [data, dispatch]) -} diff --git a/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx b/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx index 0960e95af..97619481d 100644 --- a/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx +++ b/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx @@ -1,6 +1,6 @@ import React from "react" import { Box, HStack, StackProps, VStack } from "@chakra-ui/react" -import { useAllActivitiesCount, useStatistics, useWallet } from "#/hooks" +import { useActivitiesCount, useStatistics, useWallet } from "#/hooks" import { BoltFilled } from "#/assets/icons" import { TextMd } from "#/components/shared/Typography" import { CurrencyBalance } from "#/components/shared/CurrencyBalance" @@ -10,7 +10,7 @@ type AcreTVLMessageProps = Omit export default function AcreTVLMessage(props: AcreTVLMessageProps) { const { tvl } = useStatistics() const { isConnected } = useWallet() - const activitiesCount = useAllActivitiesCount() + const activitiesCount = useActivitiesCount() const isFirstTimeUser = activitiesCount === 0 diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index 40d095ad8..54d0b4ca1 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -1,7 +1,7 @@ import React from "react" import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion" import { - useAllActivitiesCount, + useActivitiesCount, useBitcoinPositionQuery, useTransactionModal, useStatistics, @@ -41,7 +41,7 @@ export default function PositionDetails() { const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE) const openWithdrawModal = useTransactionModal(ACTION_FLOW_TYPES.UNSTAKE) - const activitiesCount = useAllActivitiesCount() + const activitiesCount = useActivitiesCount() const isMobileMode = useMobileMode() const { tvl } = useStatistics() diff --git a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx index b6ed02c49..6aa0c37af 100644 --- a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx +++ b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx @@ -13,18 +13,18 @@ import { displayBlockTimestamp, getActivityTimestamp } from "#/utils" import { Activity } from "#/types" import BlockExplorerLink from "#/components/shared/BlockExplorerLink" import { IconArrowUpRight } from "@tabler/icons-react" -import { useActivities, useMobileMode } from "#/hooks" +import { useActivitiesQuery, useMobileMode } from "#/hooks" import { semanticTokens } from "#/theme/utils" import EstimatedDuration from "./EstimatedDuration" const BLOCK_EXPLORER_CELL_MIN_WIDTH = 16 export default function TransactionTable() { - const activities = useActivities() + const { data } = useActivitiesQuery() const isMobileMode = useMobileMode() return ( - + {(pageData: Activity[]) => pageData.map((activity) => ( diff --git a/dapp/src/pages/DashboardPage/TransactionHistory/index.tsx b/dapp/src/pages/DashboardPage/TransactionHistory/index.tsx index 960d7f363..539dffdf3 100644 --- a/dapp/src/pages/DashboardPage/TransactionHistory/index.tsx +++ b/dapp/src/pages/DashboardPage/TransactionHistory/index.tsx @@ -1,13 +1,13 @@ import React from "react" import { StackProps, VStack, Image } from "@chakra-ui/react" import { TextMd } from "#/components/shared/Typography" -import { useAllActivitiesCount, useIsFetchedWalletData } from "#/hooks" +import { useActivitiesCount, useIsFetchedWalletData } from "#/hooks" import UserDataSkeleton from "#/components/shared/UserDataSkeleton" import emptyStateIllustration from "#/assets/images/empty-state.svg" import TransactionTable from "./TransactionTable" function TransactionHistoryContent() { - const activitiesCount = useAllActivitiesCount() + const activitiesCount = useActivitiesCount() const isFetchedWalletData = useIsFetchedWalletData() if (!isFetchedWalletData) diff --git a/dapp/src/store/tests/walletSlice.test.ts b/dapp/src/store/tests/walletSlice.test.ts deleted file mode 100644 index 664ea714d..000000000 --- a/dapp/src/store/tests/walletSlice.test.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { beforeEach, describe, expect, it } from "vitest" -import { createActivity } from "#/tests/factories" -import { Activity } from "#/types" -import { WalletState } from "../wallet" -import reducer, { initialState, setActivities } from "../wallet/walletSlice" - -const isSignedMessage = false -const pendingActivityId = "0" -const pendingActivity = createActivity({ - id: pendingActivityId, - status: "pending", -}) - -const activities = [ - pendingActivity, - createActivity({ id: "1" }), - createActivity({ id: "2" }), -] - -describe("Wallet redux slice", () => { - describe("deposits", () => { - let state: WalletState - - beforeEach(() => { - state = { - ...initialState, - activities, - isSignedMessage, - } - }) - - it("should update activities when the status of item changes", () => { - const newActivities = [...activities] - const completedActivity: Activity = { - ...pendingActivity, - status: "completed", - } - const foundIndex = newActivities.findIndex( - ({ id }) => id === pendingActivityId, - ) - newActivities[foundIndex] = completedActivity - - expect(reducer(state, setActivities(newActivities))).toEqual({ - ...initialState, - activities: newActivities, - isSignedMessage, - }) - }) - }) - - describe("withdrawals", () => { - let state: WalletState - const pendingWithdrawRedemptionKey = - "0x047078deab9f2325ce5adc483d6b28dfb32547017ffb73f857482b51b622d5eb" - const pendingWithdrawActivity = createActivity({ - // After the successful withdrawal flow we set the id to redemption key - // w/o the `-` suffix because it's hard to get the exact number of - // withdrawals with the same redemption key. There can only be one pending - // withdrawal with the same redemption key at a time. - id: pendingWithdrawRedemptionKey, - status: "pending", - type: "withdraw", - }) - - // Let's assume the user has already made 2 withdrawals and these 2 - // withdrawals have the same redemption key as the newly created. Both are - // completed. - const currentActivities = [ - createActivity({ - type: "withdraw", - id: `${pendingWithdrawRedemptionKey}-1`, - }), - createActivity({ - type: "withdraw", - id: `${pendingWithdrawRedemptionKey}-2`, - }), - ] - - describe("when withdrawal is still pending", () => { - // This is our pending withdrawal but with the full id with the `-` - // suffix returned by backend. - const pendingWithdrawActivityWithFullId = { - ...pendingWithdrawActivity, - id: `${pendingWithdrawRedemptionKey}-3`, - } - // The new data returned from the backend and they includes our pending - // withdrawal. - const newActivities = [ - ...currentActivities, - pendingWithdrawActivityWithFullId, - ] - - beforeEach(() => { - state = { - ...initialState, - activities: currentActivities, - isSignedMessage, - } - }) - - it("should not update pending withdraw state and should set correct id", () => { - expect(reducer(state, setActivities(newActivities))).toEqual({ - ...initialState, - activities: newActivities, - isSignedMessage, - }) - }) - }) - - describe("when withdrawal is already complete", () => { - const withdrawActivityCompleted: Activity = { - ...pendingWithdrawActivity, - status: "completed", - id: `${pendingWithdrawRedemptionKey}-3`, - } - - // Let's assume the pending withdrawal is already completed and the - // backend returns it but with the full id. Note that the pending activity - // is still in the `latestActivities` map but w/o the full id (id is - // redemption key). - const newActivities = [...currentActivities, withdrawActivityCompleted] - - beforeEach(() => { - state = { - ...initialState, - activities: currentActivities, - isSignedMessage, - } - }) - - it("should mark the latest pending withdraw activity as completed", () => { - expect(reducer(state, setActivities(newActivities))).toEqual({ - ...initialState, - activities: newActivities, - isSignedMessage, - }) - }) - }) - }) -}) diff --git a/dapp/src/store/wallet/walletSelector.ts b/dapp/src/store/wallet/walletSelector.ts index 8a1cba315..9df077205 100644 --- a/dapp/src/store/wallet/walletSelector.ts +++ b/dapp/src/store/wallet/walletSelector.ts @@ -1,5 +1,3 @@ -import { createSelector } from "@reduxjs/toolkit" -import { sortActivitiesByTimestamp } from "#/utils" import { RootState } from ".." export const selectEstimatedBtcBalance = (state: RootState): bigint => @@ -8,16 +6,6 @@ export const selectEstimatedBtcBalance = (state: RootState): bigint => export const selectSharesBalance = (state: RootState): bigint => state.wallet.sharesBalance -export const selectActivities = createSelector( - (state: RootState) => state.wallet.activities, - (activities) => sortActivitiesByTimestamp(activities), -) - -export const selectAllActivitiesCount = createSelector( - (state: RootState) => state.wallet.activities, - (activities) => activities.length, -) - export const selectIsSignedMessage = (state: RootState): boolean => state.wallet.isSignedMessage diff --git a/dapp/src/store/wallet/walletSlice.ts b/dapp/src/store/wallet/walletSlice.ts index ff480fae3..a067fbcca 100644 --- a/dapp/src/store/wallet/walletSlice.ts +++ b/dapp/src/store/wallet/walletSlice.ts @@ -1,17 +1,9 @@ -import { Activity } from "#/types" import { PayloadAction, createSlice } from "@reduxjs/toolkit" export type WalletState = { estimatedBtcBalance: bigint sharesBalance: bigint isSignedMessage: boolean - // Activities are saved in redux because the Acre subgraph may or may not be - // up to date with the chain. As a result, if we fetch data from Acre SDK - // after the withdrawal is initiated, we may not yet see this activity. - // Storing activities in redux gives us the option to add activities manually - // by `activityInitialized`. However, fetching the activity from the Acre SDK - // again later should already return us the updated data. - activities: Activity[] address: string | undefined } @@ -19,7 +11,6 @@ export const initialState: WalletState = { estimatedBtcBalance: 0n, sharesBalance: 0n, isSignedMessage: false, - activities: [], address: undefined, } @@ -36,14 +27,7 @@ export const walletSlice = createSlice({ setIsSignedMessage(state, action: PayloadAction) { state.isSignedMessage = action.payload }, - setActivities(state, action: PayloadAction) { - state.activities = action.payload - }, resetState: (state) => ({ ...initialState, address: state.address }), - activityInitialized(state, action: PayloadAction) { - const activity = action.payload - state.activities = [...state.activities, activity] - }, setAddress(state, action: PayloadAction) { state.address = action.payload }, @@ -54,9 +38,7 @@ export const { setSharesBalance, setEstimatedBtcBalance, setIsSignedMessage, - setActivities, resetState, - activityInitialized, setAddress, } = walletSlice.actions export default walletSlice.reducer From bf3b3ab9daf16a5bff2431bb31c15f2c8d36c4db Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Fri, 6 Dec 2024 14:33:49 +0100 Subject: [PATCH 6/9] Remove query suffix from hooks The name should not suggest which lib is used for fetching data.The current solution is more abstract. --- dapp/src/components/MezoBeehiveModal.tsx | 4 +- .../TransactionModal/ActionFormModal.tsx | 4 +- .../ActiveStakingStep/DepositBTCModal.tsx | 4 +- .../ActiveUnstakingStep/SignMessageModal.tsx | 4 +- .../UnstakeFormModal/index.tsx | 4 +- .../src/components/TransactionModal/index.tsx | 4 +- dapp/src/hooks/index.ts | 9 +++-- dapp/src/hooks/tanstack-query/index.ts | 7 ---- .../tanstack-query/useStatisticsQuery.ts | 13 ------- ...ointsDataQuery.ts => useAcrePointsData.ts} | 2 +- ...useActivitiesQuery.ts => useActivities.ts} | 4 +- dapp/src/hooks/useActivitiesCount.ts | 4 +- ...ints.ts => useAggregatedAcrePointsData.ts} | 14 +++---- ...inBalanceQuery.ts => useBitcoinBalance.ts} | 6 +-- ...PositionQuery.ts => useBitcoinPosition.ts} | 4 +- dapp/src/hooks/useEnhancedStatistics.ts | 28 +++++++++++++ dapp/src/hooks/useIsFetchedWalletData.ts | 18 ++++----- .../useMatsQuery.ts => useMats.ts} | 2 +- dapp/src/hooks/useStatistics.ts | 39 ++++++------------- ...ointsDataQuery.ts => useUserPointsData.ts} | 4 +- dapp/src/hooks/useWallet.ts | 4 +- .../pages/DashboardPage/AcrePointsCard.tsx | 4 +- .../pages/DashboardPage/AcreTVLMessage.tsx | 4 +- .../pages/DashboardPage/AcreTVLProgress.tsx | 4 +- dapp/src/pages/DashboardPage/BeehiveCard.tsx | 4 +- .../pages/DashboardPage/PositionDetails.tsx | 8 ++-- .../TransactionHistory/TransactionTable.tsx | 4 +- 27 files changed, 101 insertions(+), 109 deletions(-) delete mode 100644 dapp/src/hooks/tanstack-query/index.ts delete mode 100644 dapp/src/hooks/tanstack-query/useStatisticsQuery.ts rename dapp/src/hooks/{tanstack-query/useAcrePointsDataQuery.ts => useAcrePointsData.ts} (88%) rename dapp/src/hooks/{tanstack-query/useActivitiesQuery.ts => useActivities.ts} (94%) rename dapp/src/hooks/{useAcrePoints.ts => useAggregatedAcrePointsData.ts} (84%) rename dapp/src/hooks/{tanstack-query/useBitcoinBalanceQuery.ts => useBitcoinBalance.ts} (77%) rename dapp/src/hooks/{tanstack-query/useBitcoinPositionQuery.ts => useBitcoinPosition.ts} (90%) create mode 100644 dapp/src/hooks/useEnhancedStatistics.ts rename dapp/src/hooks/{tanstack-query/useMatsQuery.ts => useMats.ts} (89%) rename dapp/src/hooks/{tanstack-query/useUserPointsDataQuery.ts => useUserPointsData.ts} (80%) diff --git a/dapp/src/components/MezoBeehiveModal.tsx b/dapp/src/components/MezoBeehiveModal.tsx index d33328608..18ca145d8 100644 --- a/dapp/src/components/MezoBeehiveModal.tsx +++ b/dapp/src/components/MezoBeehiveModal.tsx @@ -18,11 +18,11 @@ import { AcreSignIcon, MatsIcon, MezoSignIcon } from "#/assets/icons" import { IconArrowUpRight, IconChartPieFilled } from "@tabler/icons-react" import { EXTERNAL_HREF } from "#/constants" import { numberToLocaleString } from "#/utils" -import { useMatsQuery } from "#/hooks" +import { useMats } from "#/hooks" import withBaseModal from "./ModalRoot/withBaseModal" function MezoBeehiveModalBase() { - const { data } = useMatsQuery() + const { data } = useMats() return ( <> diff --git a/dapp/src/components/TransactionModal/ActionFormModal.tsx b/dapp/src/components/TransactionModal/ActionFormModal.tsx index 52647f56e..8c50be64e 100644 --- a/dapp/src/components/TransactionModal/ActionFormModal.tsx +++ b/dapp/src/components/TransactionModal/ActionFormModal.tsx @@ -3,7 +3,7 @@ import { Box, ModalBody, ModalCloseButton, ModalHeader } from "@chakra-ui/react" import { useActionFlowStatus, useAppDispatch, - useBitcoinPositionQuery, + useBitcoinPosition, useMinWithdrawAmount, useStakeFlowContext, } from "#/hooks" @@ -40,7 +40,7 @@ function ActionFormModal({ type }: { type: ActionFlowType }) { const { initStake } = useStakeFlowContext() const dispatch = useAppDispatch() const minWithdrawAmount = useMinWithdrawAmount() - const { data } = useBitcoinPositionQuery() + const { data } = useBitcoinPosition() const depositedAmount = data?.estimatedBitcoinBalance ?? 0n const status = useActionFlowStatus() diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx index 0a0fe86f2..c6eaae8a2 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx @@ -3,7 +3,7 @@ import { useActionFlowPause, useActionFlowTokenAmount, useAppDispatch, - useBitcoinBalanceQuery, + useBitcoinBalance, useCancelPromise, useDepositBTCTransaction, useStakeFlowContext, @@ -25,7 +25,7 @@ export default function DepositBTCModal() { const verifyDepositAddress = useVerifyDepositAddress() const dispatch = useAppDispatch() const { handlePause } = useActionFlowPause() - const { refetch: refetchBitcoinBalance } = useBitcoinBalanceQuery() + const { refetch: refetchBitcoinBalance } = useBitcoinBalance() const { handleCapture, handleCaptureWithCause } = usePostHogCapture() const sessionId = useRef(Math.random()) diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx index f9662f219..53784597f 100644 --- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/SignMessageModal.tsx @@ -3,7 +3,7 @@ import { useActionFlowPause, useActionFlowTokenAmount, useAppDispatch, - useBitcoinPositionQuery, + useBitcoinPosition, useCancelPromise, useModal, useTimeout, @@ -32,7 +32,7 @@ export default function SignMessageModal() { const { closeModal } = useModal() const { handlePause } = useActionFlowPause() const initializeWithdraw = useInitializeWithdraw() - const { refetch: refetchBitcoinPosition } = useBitcoinPositionQuery() + const { refetch: refetchBitcoinPosition } = useBitcoinPosition() const sessionId = useRef(Math.random()) const { cancel, resolve, sessionIdToPromise } = useCancelPromise( diff --git a/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx b/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx index 22a78885a..a27f677d1 100644 --- a/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx +++ b/dapp/src/components/TransactionModal/ActiveUnstakingStep/UnstakeFormModal/index.tsx @@ -5,7 +5,7 @@ import { FormSubmitButton } from "#/components/shared/Form" import { ACTION_FLOW_TYPES, BaseFormProps, PROCESS_STATUSES } from "#/types" import { useActionFlowStatus, - useBitcoinPositionQuery, + useBitcoinPosition, useMinWithdrawAmount, } from "#/hooks" import { fixedPointNumberToString, getCurrencyByType } from "#/utils" @@ -15,7 +15,7 @@ import ActionDurationEstimation from "../../ActionDurationEstimation" function UnstakeFormModal({ onSubmitForm, }: BaseFormProps) { - const { data } = useBitcoinPositionQuery() + const { data } = useBitcoinPosition() const balance = data?.estimatedBitcoinBalance ?? 0n const minTokenAmount = useMinWithdrawAmount() const status = useActionFlowStatus() diff --git a/dapp/src/components/TransactionModal/index.tsx b/dapp/src/components/TransactionModal/index.tsx index 51fd2da29..92d805380 100644 --- a/dapp/src/components/TransactionModal/index.tsx +++ b/dapp/src/components/TransactionModal/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect } from "react" import { StakeFlowProvider } from "#/contexts" import { - useActivitiesQuery, + useActivities, useAppDispatch, useIsSignedMessage, useTransactionModal, @@ -18,7 +18,7 @@ type TransactionModalProps = { type: ActionFlowType } & BaseModalProps function TransactionModalBase({ type, closeModal }: TransactionModalProps) { const dispatch = useAppDispatch() - const { refetch: refetchActivities } = useActivitiesQuery() + const { refetch: refetchActivities } = useActivities() useEffect(() => { dispatch(setType(type)) diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 79d7e2983..e10ad6b25 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -1,7 +1,6 @@ export * from "./store" export * from "./sdk" export * from "./orangeKit" -export * from "./tanstack-query" export * from "./useDetectThemeMode" export * from "./useSidebar" export * from "./useDocsDrawer" @@ -19,7 +18,7 @@ export * from "./usePagination" export * from "./useModal" export * from "./useTransactionModal" export * from "./useVerifyDepositAddress" -export { default as useStatistics } from "./useStatistics" +export { default as useEnhancedStatistics } from "./useEnhancedStatistics" export * from "./useDisconnectWallet" export { default as useWalletConnectionAlert } from "./useWalletConnectionAlert" export { default as useResetWalletState } from "./useResetWalletState" @@ -31,7 +30,7 @@ export { default as useReferral } from "./useReferral" export { default as useIsEmbed } from "./useIsEmbed" export { default as useTriggerConnectWalletModal } from "./useTriggerConnectWalletModal" export { default as useLastUsedBtcAddress } from "./useLastUsedBtcAddress" -export { default as useAcrePoints } from "./useAcrePoints" +export { default as useAggregatedAcrePointsData } from "./useAggregatedAcrePointsData" export { default as useSignMessageAndCreateSession } from "./useSignMessageAndCreateSession" export { default as useScrollbarVisibility } from "./useScrollbarVisibility" export { default as useAccessCode } from "./useAccessCode" @@ -39,3 +38,7 @@ export { default as useFormField } from "./useFormField" export { default as useDepositBTCTransaction } from "./useDepositBTCTransaction" export { default as useCancelPromise } from "./useCancelPromise" export { default as useActivitiesCount } from "./useActivitiesCount" +export { default as useActivities } from "./useActivities" +export { default as useBitcoinBalance } from "./useBitcoinBalance" +export { default as useBitcoinPosition } from "./useBitcoinPosition" +export { default as useMats } from "./useMats" diff --git a/dapp/src/hooks/tanstack-query/index.ts b/dapp/src/hooks/tanstack-query/index.ts deleted file mode 100644 index f0857ebfd..000000000 --- a/dapp/src/hooks/tanstack-query/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { default as useAcrePointsDataQuery } from "./useAcrePointsDataQuery" -export { default as useActivitiesQuery } from "./useActivitiesQuery" -export { default as useBitcoinBalanceQuery } from "./useBitcoinBalanceQuery" -export { default as useBitcoinPositionQuery } from "./useBitcoinPositionQuery" -export { default as useUserPointsDataQuery } from "./useUserPointsDataQuery" -export { default as useMatsQuery } from "./useMatsQuery" -export { default as useStatisticsQuery } from "./useStatisticsQuery" diff --git a/dapp/src/hooks/tanstack-query/useStatisticsQuery.ts b/dapp/src/hooks/tanstack-query/useStatisticsQuery.ts deleted file mode 100644 index a7661a7ea..000000000 --- a/dapp/src/hooks/tanstack-query/useStatisticsQuery.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { useQuery } from "@tanstack/react-query" -import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" -import { acreApi } from "#/utils" - -const { acreKeys } = queryKeysFactory - -export default function useStatisticsQuery() { - return useQuery({ - queryKey: [...acreKeys.statistics()], - queryFn: acreApi.getStatistics, - refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, - }) -} diff --git a/dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts b/dapp/src/hooks/useAcrePointsData.ts similarity index 88% rename from dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts rename to dapp/src/hooks/useAcrePointsData.ts index 50fcdb823..f46474a27 100644 --- a/dapp/src/hooks/tanstack-query/useAcrePointsDataQuery.ts +++ b/dapp/src/hooks/useAcrePointsData.ts @@ -4,7 +4,7 @@ import { acreApi } from "#/utils" const { acreKeys } = queryKeysFactory -export default function useAcrePointsDataQuery() { +export default function useAcrePointsData() { return useQuery({ queryKey: [...acreKeys.pointsData()], queryFn: async () => acreApi.getPointsData(), diff --git a/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts b/dapp/src/hooks/useActivities.ts similarity index 94% rename from dapp/src/hooks/tanstack-query/useActivitiesQuery.ts rename to dapp/src/hooks/useActivities.ts index 9e03bc0c0..adeb004fe 100644 --- a/dapp/src/hooks/tanstack-query/useActivitiesQuery.ts +++ b/dapp/src/hooks/useActivities.ts @@ -4,11 +4,11 @@ import { Activity } from "#/types" import { DepositStatus } from "@acre-btc/sdk" import { useAcreContext } from "#/acre-react/hooks" import { sortActivitiesByTimestamp } from "#/utils" -import { useWallet } from "../useWallet" +import { useWallet } from "./useWallet" const { userKeys } = queryKeysFactory -export default function useActivitiesQuery() { +export default function useActivities() { const { address } = useWallet() const { acre, isConnected } = useAcreContext() diff --git a/dapp/src/hooks/useActivitiesCount.ts b/dapp/src/hooks/useActivitiesCount.ts index 279fe6539..a1ef7dba8 100644 --- a/dapp/src/hooks/useActivitiesCount.ts +++ b/dapp/src/hooks/useActivitiesCount.ts @@ -1,6 +1,6 @@ -import { useActivitiesQuery } from "./tanstack-query" +import useActivities from "./useActivities" export default function useActivitiesCount() { - const { data } = useActivitiesQuery() + const { data } = useActivities() return data ? data.length : 0 } diff --git a/dapp/src/hooks/useAcrePoints.ts b/dapp/src/hooks/useAggregatedAcrePointsData.ts similarity index 84% rename from dapp/src/hooks/useAcrePoints.ts rename to dapp/src/hooks/useAggregatedAcrePointsData.ts index a26ea5661..3e7309a31 100644 --- a/dapp/src/hooks/useAcrePoints.ts +++ b/dapp/src/hooks/useAggregatedAcrePointsData.ts @@ -4,13 +4,11 @@ import { MODAL_TYPES } from "#/types" import { PostHogEvent } from "#/posthog/events" import { useWallet } from "./useWallet" import { useModal } from "./useModal" -import { - useAcrePointsDataQuery, - useUserPointsDataQuery, -} from "./tanstack-query" import { usePostHogCapture } from "./posthog/usePostHogCapture" +import useUserPointsData from "./useUserPointsData" +import useAcrePointsData from "./useAcrePointsData" -type UseAcrePointsReturnType = { +type UseAggregatedAcrePointsDataReturnType = { totalBalance: number claimableBalance: number nextDropTimestamp?: number @@ -21,13 +19,13 @@ type UseAcrePointsReturnType = { totalPoolBalance: number } -export default function useAcrePoints(): UseAcrePointsReturnType { +export default function useAggregatedAcrePointsData(): UseAggregatedAcrePointsDataReturnType { const { ethAddress = "" } = useWallet() const { openModal } = useModal() const { handleCapture, handleCaptureWithCause } = usePostHogCapture() - const userPointsDataQuery = useUserPointsDataQuery() - const pointsDataQuery = useAcrePointsDataQuery() + const userPointsDataQuery = useUserPointsData() + const pointsDataQuery = useAcrePointsData() const { mutate: claimPoints } = useMutation({ mutationFn: async () => acreApi.claimPoints(ethAddress), diff --git a/dapp/src/hooks/tanstack-query/useBitcoinBalanceQuery.ts b/dapp/src/hooks/useBitcoinBalance.ts similarity index 77% rename from dapp/src/hooks/tanstack-query/useBitcoinBalanceQuery.ts rename to dapp/src/hooks/useBitcoinBalance.ts index e0932682f..d3f17aee6 100644 --- a/dapp/src/hooks/tanstack-query/useBitcoinBalanceQuery.ts +++ b/dapp/src/hooks/useBitcoinBalance.ts @@ -1,11 +1,11 @@ import { useQuery } from "@tanstack/react-query" import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" -import { useWalletAddress } from "../store" -import { useBitcoinProvider } from "../orangeKit/useBitcoinProvider" +import useWalletAddress from "./store/useWalletAddress" +import { useBitcoinProvider } from "./orangeKit/useBitcoinProvider" const { userKeys } = queryKeysFactory -export default function useBitcoinBalanceQuery() { +export default function useBitcoinBalance() { const address = useWalletAddress() const provider = useBitcoinProvider() diff --git a/dapp/src/hooks/tanstack-query/useBitcoinPositionQuery.ts b/dapp/src/hooks/useBitcoinPosition.ts similarity index 90% rename from dapp/src/hooks/tanstack-query/useBitcoinPositionQuery.ts rename to dapp/src/hooks/useBitcoinPosition.ts index b9fdc3732..8f208b958 100644 --- a/dapp/src/hooks/tanstack-query/useBitcoinPositionQuery.ts +++ b/dapp/src/hooks/useBitcoinPosition.ts @@ -1,11 +1,11 @@ import { useAcreContext } from "#/acre-react/hooks" import { useQuery } from "@tanstack/react-query" import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" -import { useWallet } from "../useWallet" +import { useWallet } from "./useWallet" const { userKeys } = queryKeysFactory -export default function useBitcoinPositionQuery() { +export default function useBitcoinPosition() { const { address } = useWallet() const { acre, isConnected } = useAcreContext() diff --git a/dapp/src/hooks/useEnhancedStatistics.ts b/dapp/src/hooks/useEnhancedStatistics.ts new file mode 100644 index 000000000..d7852dba5 --- /dev/null +++ b/dapp/src/hooks/useEnhancedStatistics.ts @@ -0,0 +1,28 @@ +import useStatistics from "./useStatistics" + +const useEnhancedStatistics = () => { + const { data } = useStatistics() + + const bitcoinTvl = data?.btc ?? 0 + const usdTvl = data?.usd ?? 0 + const tvlCap = data?.cap ?? 0 + + const isCapExceeded = bitcoinTvl > tvlCap + + const progress = isCapExceeded ? 100 : Math.floor((bitcoinTvl / tvlCap) * 100) + + const remaining = isCapExceeded ? 0 : tvlCap - bitcoinTvl + + return { + tvl: { + progress, + value: bitcoinTvl, + usdValue: usdTvl, + isCapExceeded, + remaining, + cap: tvlCap, + }, + } +} + +export default useEnhancedStatistics diff --git a/dapp/src/hooks/useIsFetchedWalletData.ts b/dapp/src/hooks/useIsFetchedWalletData.ts index 8cde4000c..0f2a99868 100644 --- a/dapp/src/hooks/useIsFetchedWalletData.ts +++ b/dapp/src/hooks/useIsFetchedWalletData.ts @@ -1,17 +1,15 @@ import { useIsSignedMessage } from "./store" -import { - useActivitiesQuery, - useBitcoinBalanceQuery, - useBitcoinPositionQuery, - useUserPointsDataQuery, -} from "./tanstack-query" +import useActivities from "./useActivities" +import useBitcoinBalance from "./useBitcoinBalance" +import useBitcoinPosition from "./useBitcoinPosition" +import useUserPointsData from "./useUserPointsData" export default function useIsFetchedWalletData() { const isSignedMessage = useIsSignedMessage() - const { isFetched: isBitcoinBalanceFetched } = useBitcoinBalanceQuery() - const { isFetched: isBitcoinPositionFetched } = useBitcoinPositionQuery() - const { isFetched: isActivitiesFetched } = useActivitiesQuery() - const { isFetched: isPointsDataFetched } = useUserPointsDataQuery() + const { isFetched: isBitcoinBalanceFetched } = useBitcoinBalance() + const { isFetched: isBitcoinPositionFetched } = useBitcoinPosition() + const { isFetched: isActivitiesFetched } = useActivities() + const { isFetched: isPointsDataFetched } = useUserPointsData() const isFetchedData = isBitcoinBalanceFetched && diff --git a/dapp/src/hooks/tanstack-query/useMatsQuery.ts b/dapp/src/hooks/useMats.ts similarity index 89% rename from dapp/src/hooks/tanstack-query/useMatsQuery.ts rename to dapp/src/hooks/useMats.ts index b861e9469..fe62d63f2 100644 --- a/dapp/src/hooks/tanstack-query/useMatsQuery.ts +++ b/dapp/src/hooks/useMats.ts @@ -4,7 +4,7 @@ import { acreApi } from "#/utils" const { acreKeys } = queryKeysFactory -export default function useMatsQuery() { +export default function useMats() { return useQuery({ queryKey: [...acreKeys.mats()], queryFn: async () => acreApi.getMats(), diff --git a/dapp/src/hooks/useStatistics.ts b/dapp/src/hooks/useStatistics.ts index 5d8583efc..20cddddb0 100644 --- a/dapp/src/hooks/useStatistics.ts +++ b/dapp/src/hooks/useStatistics.ts @@ -1,28 +1,13 @@ -import { useStatisticsQuery } from "./tanstack-query" - -const useStatistics = () => { - const { data } = useStatisticsQuery() - - const bitcoinTvl = data?.btc ?? 0 - const usdTvl = data?.usd ?? 0 - const tvlCap = data?.cap ?? 0 - - const isCapExceeded = bitcoinTvl > tvlCap - - const progress = isCapExceeded ? 100 : Math.floor((bitcoinTvl / tvlCap) * 100) - - const remaining = isCapExceeded ? 0 : tvlCap - bitcoinTvl - - return { - tvl: { - progress, - value: bitcoinTvl, - usdValue: usdTvl, - isCapExceeded, - remaining, - cap: tvlCap, - }, - } +import { useQuery } from "@tanstack/react-query" +import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" +import { acreApi } from "#/utils" + +const { acreKeys } = queryKeysFactory + +export default function useStatistics() { + return useQuery({ + queryKey: [...acreKeys.statistics()], + queryFn: acreApi.getStatistics, + refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, + }) } - -export default useStatistics diff --git a/dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts b/dapp/src/hooks/useUserPointsData.ts similarity index 80% rename from dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts rename to dapp/src/hooks/useUserPointsData.ts index a18d37976..9e6e2cad2 100644 --- a/dapp/src/hooks/tanstack-query/useUserPointsDataQuery.ts +++ b/dapp/src/hooks/useUserPointsData.ts @@ -1,11 +1,11 @@ import { queryKeysFactory } from "#/constants" import { useQuery } from "@tanstack/react-query" import { acreApi } from "#/utils" -import { useWallet } from "../useWallet" +import { useWallet } from "./useWallet" const { userKeys } = queryKeysFactory -export default function useUserPointsDataQuery() { +export default function useUserPointsData() { const { ethAddress = "" } = useWallet() return useQuery({ diff --git a/dapp/src/hooks/useWallet.ts b/dapp/src/hooks/useWallet.ts index fd5451c83..8125fd51a 100644 --- a/dapp/src/hooks/useWallet.ts +++ b/dapp/src/hooks/useWallet.ts @@ -20,7 +20,7 @@ import { useDispatch } from "react-redux" import { setAddress } from "#/store/wallet" import useResetWalletState from "./useResetWalletState" import useLastUsedBtcAddress from "./useLastUsedBtcAddress" -import useBitcoinBalanceQuery from "./tanstack-query/useBitcoinBalanceQuery" +import useBitcoinBalance from "./useBitcoinBalance" import { useWalletAddress } from "./store" const { typeConversionToConnector, typeConversionToOrangeKitConnector } = @@ -51,7 +51,7 @@ export function useWallet(): UseWalletReturn { const { setAddressInLocalStorage, removeAddressFromLocalStorage } = useLastUsedBtcAddress() - const { data: balance } = useBitcoinBalanceQuery() + const { data: balance } = useBitcoinBalance() const chainId = useChainId() const config = useConfig() diff --git a/dapp/src/pages/DashboardPage/AcrePointsCard.tsx b/dapp/src/pages/DashboardPage/AcrePointsCard.tsx index 193c6c5d1..34cc0d16c 100644 --- a/dapp/src/pages/DashboardPage/AcrePointsCard.tsx +++ b/dapp/src/pages/DashboardPage/AcrePointsCard.tsx @@ -12,7 +12,7 @@ import { } from "@chakra-ui/react" import Countdown from "#/components/shared/Countdown" import { logPromiseFailure, numberToLocaleString } from "#/utils" -import { useAcrePoints, useWallet } from "#/hooks" +import { useAggregatedAcrePointsData, useWallet } from "#/hooks" import Spinner from "#/components/shared/Spinner" import UserDataSkeleton from "#/components/shared/UserDataSkeleton" import InfoTooltip from "#/components/shared/InfoTooltip" @@ -37,7 +37,7 @@ export default function AcrePointsCard(props: CardProps) { updatePointsData, isCalculationInProgress, totalPoolBalance, - } = useAcrePoints() + } = useAggregatedAcrePointsData() const { isConnected } = useWallet() const debouncedClaimPoints = useDebounce(claimPoints, ONE_SEC_IN_MILLISECONDS) diff --git a/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx b/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx index 97619481d..dadfa67b5 100644 --- a/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx +++ b/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx @@ -1,6 +1,6 @@ import React from "react" import { Box, HStack, StackProps, VStack } from "@chakra-ui/react" -import { useActivitiesCount, useStatistics, useWallet } from "#/hooks" +import { useActivitiesCount, useEnhancedStatistics, useWallet } from "#/hooks" import { BoltFilled } from "#/assets/icons" import { TextMd } from "#/components/shared/Typography" import { CurrencyBalance } from "#/components/shared/CurrencyBalance" @@ -8,7 +8,7 @@ import { CurrencyBalance } from "#/components/shared/CurrencyBalance" type AcreTVLMessageProps = Omit export default function AcreTVLMessage(props: AcreTVLMessageProps) { - const { tvl } = useStatistics() + const { tvl } = useEnhancedStatistics() const { isConnected } = useWallet() const activitiesCount = useActivitiesCount() diff --git a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx index 51c645153..228fd4546 100644 --- a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx +++ b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx @@ -7,7 +7,7 @@ import { Grid, Box, } from "@chakra-ui/react" -import { useStatistics } from "#/hooks" +import { useEnhancedStatistics } from "#/hooks" import { BitcoinIcon } from "#/assets/icons" import { CurrencyBalance } from "#/components/shared/CurrencyBalance" import ProgressBar from "#/components/shared/ProgressBar" @@ -19,7 +19,7 @@ const STEP_COUNT = 5 export function AcreTVLProgress(props: AcreTVLProgressProps) { const styles = useMultiStyleConfig("AcreTVLProgress") - const { tvl } = useStatistics() + const { tvl } = useEnhancedStatistics() const steps = useMemo( () => diff --git a/dapp/src/pages/DashboardPage/BeehiveCard.tsx b/dapp/src/pages/DashboardPage/BeehiveCard.tsx index 2c63cceaf..9168d0b5b 100644 --- a/dapp/src/pages/DashboardPage/BeehiveCard.tsx +++ b/dapp/src/pages/DashboardPage/BeehiveCard.tsx @@ -13,7 +13,7 @@ import { VStack, } from "@chakra-ui/react" import { MezoSignIcon } from "#/assets/icons" -import { useMatsQuery, useModal } from "#/hooks" +import { useMats, useModal } from "#/hooks" import { MODAL_TYPES } from "#/types" import beehiveIllustrationSrc from "#/assets/images/beehive-illustration.svg" import UserDataSkeleton from "#/components/shared/UserDataSkeleton" @@ -22,7 +22,7 @@ import InfoTooltip from "#/components/shared/InfoTooltip" export default function BeehiveCard(props: CardProps) { const { openModal } = useModal() - const { data } = useMatsQuery() + const { data } = useMats() const handleOpenBeehiveModal = () => { openModal(MODAL_TYPES.MEZO_BEEHIVE) diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index 54d0b4ca1..725dc9ac7 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -2,9 +2,9 @@ import React from "react" import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion" import { useActivitiesCount, - useBitcoinPositionQuery, + useBitcoinPosition, useTransactionModal, - useStatistics, + useEnhancedStatistics, useWallet, useMobileMode, } from "#/hooks" @@ -36,7 +36,7 @@ const buttonStyles: ButtonProps = { } export default function PositionDetails() { - const { data } = useBitcoinPositionQuery() + const { data } = useBitcoinPosition() const bitcoinAmount = data?.estimatedBitcoinBalance ?? 0n const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE) @@ -44,7 +44,7 @@ export default function PositionDetails() { const activitiesCount = useActivitiesCount() const isMobileMode = useMobileMode() - const { tvl } = useStatistics() + const { tvl } = useEnhancedStatistics() const { isConnected } = useWallet() diff --git a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx index 6aa0c37af..baba6aa83 100644 --- a/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx +++ b/dapp/src/pages/DashboardPage/TransactionHistory/TransactionTable.tsx @@ -13,14 +13,14 @@ import { displayBlockTimestamp, getActivityTimestamp } from "#/utils" import { Activity } from "#/types" import BlockExplorerLink from "#/components/shared/BlockExplorerLink" import { IconArrowUpRight } from "@tabler/icons-react" -import { useActivitiesQuery, useMobileMode } from "#/hooks" +import { useActivities, useMobileMode } from "#/hooks" import { semanticTokens } from "#/theme/utils" import EstimatedDuration from "./EstimatedDuration" const BLOCK_EXPLORER_CELL_MIN_WIDTH = 16 export default function TransactionTable() { - const { data } = useActivitiesQuery() + const { data } = useActivities() const isMobileMode = useMobileMode() return ( From d2128ca4191076188a6ba122cb64ad5face71e61 Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Mon, 9 Dec 2024 14:41:31 +0100 Subject: [PATCH 7/9] Move logic from wallet selectors to utils for activities --- dapp/src/pages/DashboardPage/PositionDetails.tsx | 10 +++++----- dapp/src/utils/activities.ts | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index 98f820356..9faebe703 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -24,6 +24,7 @@ import { featureFlags } from "#/constants" import { TextMd } from "#/components/shared/Typography" import { IconClockHour5Filled } from "@tabler/icons-react" import TooltipIcon from "#/components/shared/TooltipIcon" +import { hasPendingDeposits } from "#/utils" import AcreTVLMessage from "./AcreTVLMessage" const isWithdrawalFlowEnabled = featureFlags.WITHDRAWALS_ENABLED @@ -39,12 +40,13 @@ const buttonStyles: ButtonProps = { } export default function PositionDetails() { - const { data } = useBitcoinPosition() - const bitcoinAmount = data?.estimatedBitcoinBalance ?? 0n + const { data: bitcoinPosition } = useBitcoinPosition() + const bitcoinAmount = bitcoinPosition?.estimatedBitcoinBalance ?? 0n const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE) const openWithdrawModal = useTransactionModal(ACTION_FLOW_TYPES.UNSTAKE) const activitiesCount = useActivitiesCount() + const { data: activities } = useActivities() const isMobileMode = useMobileMode() const { tvl } = useEnhancedStatistics() @@ -54,15 +56,13 @@ export default function PositionDetails() { const isDisabledForMobileMode = isMobileMode && !featureFlags.MOBILE_MODE_ENABLED - const { hasPendingActivities } = useActivities() - return ( {/* TODO: Component should be moved to `CardHeader` */} Your Acre balance - {hasPendingActivities && ( + {hasPendingDeposits(activities ?? []) && ( export const getActivityTimestamp = (activity: Activity): number => activity?.finalizedAt ?? activity.initializedAt +export const hasPendingDeposits = (activities: Activity[]): boolean => + activities.some( + (activity) => activity.status === "pending" && activity.type === "deposit", + ) + export const sortActivitiesByTimestamp = (activities: Activity[]): Activity[] => [...activities].sort( (activity1, activity2) => From 0d5d3e8c6f578fd7fbc47974c2db78111853763b Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 11 Dec 2024 09:38:45 +0100 Subject: [PATCH 8/9] Create one hook for statistics --- dapp/src/hooks/index.ts | 2 +- dapp/src/hooks/useEnhancedStatistics.ts | 28 ----------------- dapp/src/hooks/useStatistics.ts | 31 ++++++++++++++++--- .../pages/DashboardPage/AcreTVLMessage.tsx | 4 +-- .../pages/DashboardPage/AcreTVLProgress.tsx | 4 +-- .../pages/DashboardPage/PositionDetails.tsx | 2 +- 6 files changed, 33 insertions(+), 38 deletions(-) delete mode 100644 dapp/src/hooks/useEnhancedStatistics.ts diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 07e87118c..1945ee45e 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -17,7 +17,7 @@ export * from "./usePagination" export * from "./useModal" export * from "./useTransactionModal" export * from "./useVerifyDepositAddress" -export { default as useEnhancedStatistics } from "./useEnhancedStatistics" +export { default as useStatistics } from "./useStatistics" export * from "./useDisconnectWallet" export { default as useWalletConnectionAlert } from "./useWalletConnectionAlert" export { default as useResetWalletState } from "./useResetWalletState" diff --git a/dapp/src/hooks/useEnhancedStatistics.ts b/dapp/src/hooks/useEnhancedStatistics.ts deleted file mode 100644 index d7852dba5..000000000 --- a/dapp/src/hooks/useEnhancedStatistics.ts +++ /dev/null @@ -1,28 +0,0 @@ -import useStatistics from "./useStatistics" - -const useEnhancedStatistics = () => { - const { data } = useStatistics() - - const bitcoinTvl = data?.btc ?? 0 - const usdTvl = data?.usd ?? 0 - const tvlCap = data?.cap ?? 0 - - const isCapExceeded = bitcoinTvl > tvlCap - - const progress = isCapExceeded ? 100 : Math.floor((bitcoinTvl / tvlCap) * 100) - - const remaining = isCapExceeded ? 0 : tvlCap - bitcoinTvl - - return { - tvl: { - progress, - value: bitcoinTvl, - usdValue: usdTvl, - isCapExceeded, - remaining, - cap: tvlCap, - }, - } -} - -export default useEnhancedStatistics diff --git a/dapp/src/hooks/useStatistics.ts b/dapp/src/hooks/useStatistics.ts index 20cddddb0..22dc77acd 100644 --- a/dapp/src/hooks/useStatistics.ts +++ b/dapp/src/hooks/useStatistics.ts @@ -1,13 +1,36 @@ -import { useQuery } from "@tanstack/react-query" -import { REFETCH_INTERVAL_IN_MILLISECONDS, queryKeysFactory } from "#/constants" +import { queryKeysFactory, REFETCH_INTERVAL_IN_MILLISECONDS } from "#/constants" import { acreApi } from "#/utils" +import { useQuery } from "@tanstack/react-query" const { acreKeys } = queryKeysFactory -export default function useStatistics() { - return useQuery({ +const useStatistics = () => { + const { data } = useQuery({ queryKey: [...acreKeys.statistics()], queryFn: acreApi.getStatistics, refetchInterval: REFETCH_INTERVAL_IN_MILLISECONDS, }) + + const bitcoinTvl = data?.btc ?? 0 + const usdTvl = data?.usd ?? 0 + const tvlCap = data?.cap ?? 0 + + const isCapExceeded = bitcoinTvl > tvlCap + + const progress = isCapExceeded ? 100 : Math.floor((bitcoinTvl / tvlCap) * 100) + + const remaining = isCapExceeded ? 0 : tvlCap - bitcoinTvl + + return { + tvl: { + progress, + value: bitcoinTvl, + usdValue: usdTvl, + isCapExceeded, + remaining, + cap: tvlCap, + }, + } } + +export default useStatistics diff --git a/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx b/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx index dadfa67b5..97619481d 100644 --- a/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx +++ b/dapp/src/pages/DashboardPage/AcreTVLMessage.tsx @@ -1,6 +1,6 @@ import React from "react" import { Box, HStack, StackProps, VStack } from "@chakra-ui/react" -import { useActivitiesCount, useEnhancedStatistics, useWallet } from "#/hooks" +import { useActivitiesCount, useStatistics, useWallet } from "#/hooks" import { BoltFilled } from "#/assets/icons" import { TextMd } from "#/components/shared/Typography" import { CurrencyBalance } from "#/components/shared/CurrencyBalance" @@ -8,7 +8,7 @@ import { CurrencyBalance } from "#/components/shared/CurrencyBalance" type AcreTVLMessageProps = Omit export default function AcreTVLMessage(props: AcreTVLMessageProps) { - const { tvl } = useEnhancedStatistics() + const { tvl } = useStatistics() const { isConnected } = useWallet() const activitiesCount = useActivitiesCount() diff --git a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx index 228fd4546..51c645153 100644 --- a/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx +++ b/dapp/src/pages/DashboardPage/AcreTVLProgress.tsx @@ -7,7 +7,7 @@ import { Grid, Box, } from "@chakra-ui/react" -import { useEnhancedStatistics } from "#/hooks" +import { useStatistics } from "#/hooks" import { BitcoinIcon } from "#/assets/icons" import { CurrencyBalance } from "#/components/shared/CurrencyBalance" import ProgressBar from "#/components/shared/ProgressBar" @@ -19,7 +19,7 @@ const STEP_COUNT = 5 export function AcreTVLProgress(props: AcreTVLProgressProps) { const styles = useMultiStyleConfig("AcreTVLProgress") - const { tvl } = useEnhancedStatistics() + const { tvl } = useStatistics() const steps = useMemo( () => diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index 9faebe703..ac295c967 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -49,7 +49,7 @@ export default function PositionDetails() { const { data: activities } = useActivities() const isMobileMode = useMobileMode() - const { tvl } = useEnhancedStatistics() + const { tvl } = useStatistics() const { isConnected } = useWallet() From a24af4ec9f016e071c6292e45b32c4bd746df45b Mon Sep 17 00:00:00 2001 From: Karolina Kosiorowska Date: Wed, 11 Dec 2024 09:44:12 +0100 Subject: [PATCH 9/9] Fix failed build --- dapp/src/pages/DashboardPage/PositionDetails.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dapp/src/pages/DashboardPage/PositionDetails.tsx b/dapp/src/pages/DashboardPage/PositionDetails.tsx index ac295c967..d403519f6 100644 --- a/dapp/src/pages/DashboardPage/PositionDetails.tsx +++ b/dapp/src/pages/DashboardPage/PositionDetails.tsx @@ -4,7 +4,7 @@ import { useActivitiesCount, useBitcoinPosition, useTransactionModal, - useEnhancedStatistics, + useStatistics, useWallet, useMobileMode, useActivities,