diff --git a/src/components/layout/AppNavbar.tsx b/src/components/layout/AppNavbar.tsx
index 2d4b6df9..58088d36 100644
--- a/src/components/layout/AppNavbar.tsx
+++ b/src/components/layout/AppNavbar.tsx
@@ -60,11 +60,11 @@ const WalletPreview = ({
{rescanInfo?.rescanning === true ? (
- {rescanInfo.progress !== undefined
- ? t('navbar.text_rescan_in_progress_with_progress', {
- progress: Math.floor(rescanInfo.progress * 100),
- })
- : t('navbar.text_rescan_in_progress')}
+ {rescanInfo.progressInPercentage === undefined
+ ? t('navbar.text_rescan_in_progress')
+ : t('navbar.text_rescan_in_progress_with_progress', {
+ progress: rescanInfo.progressInPercentage,
+ })}
) : (
<>
diff --git a/src/components/settings/RescanChainPage.test.tsx b/src/components/settings/RescanChainPage.test.tsx
index a9f343bc..21324ed9 100644
--- a/src/components/settings/RescanChainPage.test.tsx
+++ b/src/components/settings/RescanChainPage.test.tsx
@@ -87,7 +87,7 @@ const renderPage = async () => {
describe('RescanChainPage', () => {
beforeEach(() => {
vi.clearAllMocks()
- rescanInfo = { updatedAt: 0, rescanning: false, progress: undefined }
+ rescanInfo = { updatedAt: 0, rescanning: false, progress: undefined, progressInPercentage: undefined }
})
it('renders the form and navigates back', async () => {
@@ -105,7 +105,7 @@ describe('RescanChainPage', () => {
})
it('shows the in-progress alert with progress', async () => {
- rescanInfo = { updatedAt: 0, rescanning: true, progress: 42 }
+ rescanInfo = { updatedAt: 0, rescanning: true, progress: 0.4221, progressInPercentage: '42.2' }
await renderPage()
expect(screen.getByText(/app.alert_rescan_in_progress_with_progress/)).toBeInTheDocument()
})
@@ -113,15 +113,15 @@ describe('RescanChainPage', () => {
it('submits a valid block height through the mutation', async () => {
await renderPage()
const input = screen.getByPlaceholderText('rescan_chain.placeholder_blockheight')
- fireEvent.change(input, { target: { value: '700000' } })
+ fireEvent.change(input, { target: { value: String(700_000) } })
fireEvent.submit(input.closest('form')!)
- await waitFor(() => expect(mutateAsync).toHaveBeenCalledWith(700000))
+ await waitFor(() => expect(mutateAsync).toHaveBeenCalledWith(700_000))
})
it('mutationFn calls the rescan API and returns data', async () => {
await renderPage()
- await expect(mutationConfig.mutationFn(700000)).resolves.toBe('ok')
+ await expect(mutationConfig.mutationFn(700_000)).resolves.toBe('ok')
expect(rescanblockchainMock).toHaveBeenCalled()
})
diff --git a/src/components/settings/RescanChainPage.tsx b/src/components/settings/RescanChainPage.tsx
index 45b7dc5c..2fc8426f 100644
--- a/src/components/settings/RescanChainPage.tsx
+++ b/src/components/settings/RescanChainPage.tsx
@@ -124,7 +124,6 @@ export const RescanChainPage = ({ walletFileName }: RescanChainProps) => {
setRescanInfo({
updatedAt: Date.now(),
rescanning: true,
- progress: undefined,
})
},
onError: (error: unknown) => {
@@ -133,7 +132,6 @@ export const RescanChainPage = ({ walletFileName }: RescanChainProps) => {
setRescanInfo({
updatedAt: Date.now(),
rescanning: false,
- progress: undefined,
})
const reason = getErrorReason(error, t('global.errors.reason_unknown'))
@@ -181,10 +179,10 @@ export const RescanChainPage = ({ walletFileName }: RescanChainProps) => {
- {rescanInfo?.progress === undefined
+ {rescanInfo?.progressInPercentage === undefined
? t('app.alert_rescan_in_progress')
: t('app.alert_rescan_in_progress_with_progress', {
- progress: rescanInfo.progress,
+ progress: rescanInfo.progressInPercentage,
})}
diff --git a/src/context/JamSessionInfoContext.ts b/src/context/JamSessionInfoContext.ts
index 70f7fae6..685efe3b 100644
--- a/src/context/JamSessionInfoContext.ts
+++ b/src/context/JamSessionInfoContext.ts
@@ -1,11 +1,13 @@
import { createContext, useContext, type Dispatch, type SetStateAction } from 'react'
import type { SendFormValues } from '@/components/send/types'
import type { WalletFileName } from '@/lib/utils'
+import type { Factor } from '@/types/global'
export interface RescanInfo {
updatedAt: number
rescanning: boolean
- progress?: number
+ progress?: Factor
+ progressInPercentage?: string
}
export interface PaymentAttempt {
diff --git a/src/context/JamSessionInfoContextProvider.tsx b/src/context/JamSessionInfoContextProvider.tsx
index 0f75861a..26eef026 100644
--- a/src/context/JamSessionInfoContextProvider.tsx
+++ b/src/context/JamSessionInfoContextProvider.tsx
@@ -7,7 +7,7 @@ import { createJSONStorage, persist } from 'zustand/middleware'
import { JAM_RESCAN_PROGRESS_INTERVAL } from '@/constants/jam'
import { useApiClient } from '@/hooks/useApiClient'
import { withQueryDelay } from '@/lib/queryClient'
-import type { WalletFileName } from '@/lib/utils'
+import { factorToPercentage, type WalletFileName } from '@/lib/utils'
import { jmSessionStore } from '@/store/jmSessionStore'
import { JamSessionInfoContext } from './JamSessionInfoContext'
import type { PaymentAttempt, RescanInfo, TakerInfo } from './JamSessionInfoContext'
@@ -92,10 +92,12 @@ export const JamSessionInfoContextProvider = ({
const isRescanning = getrescaninfoQuery.data.rescanning || state?.rescanning === true
const rescanningFinished = getrescaninfoQuery.data.rescanning === false && state?.rescanning === true
+ const progress = rescanningFinished ? 1 : getrescaninfoQuery.data.progress
setRescanInfo({
updatedAt: getrescaninfoQuery.dataUpdatedAt,
rescanning: isRescanning,
- progress: rescanningFinished ? 1 : getrescaninfoQuery.data.progress,
+ progress: progress,
+ progressInPercentage: progress === undefined ? undefined : factorToPercentage(progress).toFixed(1),
})
}
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 8ab64db5..e6f0ffd0 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -1,7 +1,7 @@
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
import { JM_WALLET_FILE_EXTENSION, type OfferType } from '@/constants/jm'
-import type { Milliseconds, MnemonicPhrase } from '@/types/global'
+import type { Factor, Milliseconds, MnemonicPhrase } from '@/types/global'
const HORIZONTAL_ELLIPSIS = '\u2026' // Horizontal Ellipsis `…`
@@ -145,14 +145,6 @@ export const BITCOIN_GENESIS_DATE = new Date('2009-01-03T18:15:05Z')
export const DUMMY_SEED_PHRASE: MnemonicPhrase =
'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'.split(' ')
-export const percentageToFactorString = (val: number, precision = 6) => {
- return (val / 100).toFixed(precision)
-}
-
-export const percentageToFactor = (val: number, precision = 6) => {
- return Number(percentageToFactorString(val, precision))
-}
-
export const isValidNumber = (val: unknown): val is number => {
return Number.isFinite(val)
}
@@ -215,13 +207,21 @@ export const formatSats = (value: number) => {
})
}
-export const factorToPercentage = (val: number, precision = 6) => {
+export const factorToPercentage = (val: Factor, precision = 6) => {
// Value cannot just be multiplied
// e.g. ✗ 0.000027 * 100 == 0.0026999999999999997
// but: ✓ Number((0.000027 * 100).toFixed(6)) = 0.0027
return Number((val * 100).toFixed(precision))
}
+export const percentageToFactorString = (val: number, precision = 6) => {
+ return (val / 100).toFixed(precision)
+}
+
+export const percentageToFactor = (val: number, precision = 6): Factor => {
+ return Number(percentageToFactorString(val, precision))
+}
+
export type SemanticVersion = { major: number; minor: number; patch: number; raw?: string }
export const UNKNOWN_VERSION: SemanticVersion = { major: 0, minor: 0, patch: 0, raw: 'unknown' }