diff --git a/src/components/send/SendForm.tsx b/src/components/send/SendForm.tsx
index e8e7125f..d102b020 100644
--- a/src/components/send/SendForm.tsx
+++ b/src/components/send/SendForm.tsx
@@ -186,7 +186,12 @@ export function SendForm({
const {
hasOrders,
- queryResult: { isLoading: orderbookCheckIsLoading, isError: orderbookCheckIsError },
+ queryResult: {
+ isLoading: orderbookCheckIsLoading,
+ isFetching: orderbookCheckIsFetching,
+ isError: orderbookCheckIsError,
+ refetch: orderbookRefetch,
+ },
} = useQueryOrderbook()
const destinationAddressInfo = useMemo(() => {
@@ -369,7 +374,9 @@ export function SendForm({
{hasCoinjoinPreconditionWarning && coinjoinPreconditionSummary && (
)}
- {isCoinJoin && !orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && }
+ {isCoinJoin && !orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && (
+
+ )}
diff --git a/src/components/sweep/SweepPage.tsx b/src/components/sweep/SweepPage.tsx
index 2a62bd60..bbc95e4c 100644
--- a/src/components/sweep/SweepPage.tsx
+++ b/src/components/sweep/SweepPage.tsx
@@ -76,7 +76,12 @@ export const SweepPage = ({ walletFileName }: SweepPageProps) => {
const [alertMessage, setAlertMessage] = useState
()
const {
hasOrders,
- queryResult: { isLoading: orderbookCheckIsLoading, isError: orderbookCheckIsError },
+ queryResult: {
+ isLoading: orderbookCheckIsLoading,
+ isError: orderbookCheckIsError,
+ isFetching: orderbookCheckIsFetching,
+ refetch: orderbookRefetch,
+ },
} = useQueryOrderbook()
const feeConfigValidation = useFeeConfigValidation({ walletFileName })
@@ -290,7 +295,9 @@ export const SweepPage = ({ walletFileName }: SweepPageProps) => {
setShowFeeConfigDialog(true)} className="mb-4" />
)}
- {!orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && }
+ {!orderbookCheckIsLoading && !orderbookCheckIsError && !hasOrders && (
+
+ )}
{alertMessage && (
diff --git a/src/components/ui/jam/OrderbookEmptyAlert.test.tsx b/src/components/ui/jam/OrderbookEmptyAlert.test.tsx
index 3eebb623..aae12d42 100644
--- a/src/components/ui/jam/OrderbookEmptyAlert.test.tsx
+++ b/src/components/ui/jam/OrderbookEmptyAlert.test.tsx
@@ -20,11 +20,27 @@ vi.mock('react-router-dom', () => ({
}))
describe('OrderbookEmptyAlert', () => {
- it('renders title, description and link to orderbook page', () => {
- render()
+ it('renders title, description, button and link to orderbook page', () => {
+ render( {}} />)
expect(screen.getByText('orderbook.alert_precheck_empty_title')).toBeInTheDocument()
expect(screen.getByText(/orderbook.alert_precheck_empty_description/u)).toBeInTheDocument()
expect(screen.getByRole('link')).toHaveAttribute('href', '/orderbook')
+
+ const actionCheck = screen.getByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_check' })
+ expect(actionCheck).toBeEnabled()
+
+ const actionChecking = screen.queryByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_checking' })
+ expect(actionChecking).not.toBeInTheDocument()
+ })
+
+ it('disables button while checking', () => {
+ render( {}} />)
+
+ const actionChecking = screen.getByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_checking' })
+ expect(actionChecking).toBeDisabled()
+
+ const actionCheck = screen.queryByRole('button', { name: 'orderbook.alert_precheck_empty_text_button_check' })
+ expect(actionCheck).not.toBeInTheDocument()
})
})
diff --git a/src/components/ui/jam/OrderbookEmptyAlert.tsx b/src/components/ui/jam/OrderbookEmptyAlert.tsx
index 01aa6f13..9b602fc7 100644
--- a/src/components/ui/jam/OrderbookEmptyAlert.tsx
+++ b/src/components/ui/jam/OrderbookEmptyAlert.tsx
@@ -1,14 +1,17 @@
-import { AlertTriangleIcon } from 'lucide-react'
+import { AlertTriangleIcon, RefreshCwIcon } from 'lucide-react'
import { Trans, useTranslation } from 'react-i18next'
import { Link } from 'react-router-dom'
-import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
+import { Alert, AlertAction, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { routes } from '@/constants/routes'
+import { Button } from '../button'
interface OrderbookEmptyAlertProps {
className?: string
+ isChecking?: boolean
+ onCheckClick?: () => Promise
}
-export const OrderbookEmptyAlert = ({ className }: OrderbookEmptyAlertProps) => {
+export const OrderbookEmptyAlert = ({ className, isChecking, onCheckClick }: OrderbookEmptyAlertProps) => {
const { t } = useTranslation()
return (
@@ -23,6 +26,16 @@ export const OrderbookEmptyAlert = ({ className }: OrderbookEmptyAlertProps) =>
}}
/>
+ {onCheckClick && (
+
+
+
+ )}
)
}
diff --git a/src/hooks/useQueryOrderbook.ts b/src/hooks/useQueryOrderbook.ts
index 5a248535..bcef2c88 100644
--- a/src/hooks/useQueryOrderbook.ts
+++ b/src/hooks/useQueryOrderbook.ts
@@ -1,5 +1,6 @@
import { useQuery, type UseQueryResult } from '@tanstack/react-query'
import { fetchOrderbook, type OrderbookResponse } from '@/lib/api/orderbook'
+import { withQueryDelay } from '@/lib/queryClient'
export type UseQueryOrderbookResult = {
hasOrders: boolean
@@ -9,7 +10,11 @@ export type UseQueryOrderbookResult = {
export function useQueryOrderbook(): UseQueryOrderbookResult {
const queryResult = useQuery({
queryKey: ['orderbook-precheck'],
- queryFn: fetchOrderbook,
+ queryFn: withQueryDelay(fetchOrderbook, {
+ // avoid flickering and let user briefly know that something is happening in the background
+ delayBefore: 1_000,
+ }),
+ staleTime: 30 * 1_000,
retry: false,
})
diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json
index 67830fec..5357883a 100644
--- a/src/i18n/locales/en/translation.json
+++ b/src/i18n/locales/en/translation.json
@@ -755,6 +755,8 @@
"alert_empty_orderbook": "Orderbook is empty",
"alert_precheck_empty_title": "No active makers found",
"alert_precheck_empty_description": "Your local Orderbook appears to be empty right now. Collaborative transactions might fail. Please check <1>your local Orderbook1>.",
+ "alert_precheck_empty_text_button_check": "Check again",
+ "alert_precheck_empty_text_button_checking": "Checking...",
"error_loading_orderbook_failed": "Error while loading the orderbook. Your current local setup might not support fetching the orderbook. Reason: {{ reason }}",
"text_offer_type_absolute": "absolute",
"text_offer_type_relative": "relative",