mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-13 12:33:26 +02:00
fix: correct rescan progress on Rescan page (#1313)
* dev(regtest): remove unnecessary env vars
* fix: correct rescan progress on Rescan page
* Revert "dev(regtest): remove unnecessary env vars"
This reverts commit f6ca1cbd4c.
* chore: progress in percentage as string
This commit is contained in:
parent
1b5d1cf6e6
commit
147d815f3b
6 changed files with 29 additions and 27 deletions
|
|
@ -60,11 +60,11 @@ const WalletPreview = ({
|
|||
<div className="flex min-h-5 min-w-0 items-center sm:min-w-[150px]">
|
||||
{rescanInfo?.rescanning === true ? (
|
||||
<div className="cursor-wait motion-safe:animate-pulse">
|
||||
{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,
|
||||
})}
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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) => {
|
|||
<div className="flex min-w-0 items-start gap-2">
|
||||
<RefreshCwIcon className="mt-0.5 h-4 w-4 shrink-0 animate-spin motion-reduce:hidden" />
|
||||
<span className="min-w-0 text-sm break-words">
|
||||
{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,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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' }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue