mirror of
https://github.com/joinmarket-webui/jam.git
synced 2026-08-13 12:33:26 +02:00
chore: enable eslint recommendedTypeChecked
This commit is contained in:
parent
93f7cb10bb
commit
6f1a1f7ed1
29 changed files with 125 additions and 184 deletions
|
|
@ -1,7 +1,6 @@
|
|||
// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
|
||||
import js from '@eslint/js'
|
||||
import compat from 'eslint-plugin-compat'
|
||||
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import storybook from 'eslint-plugin-storybook'
|
||||
|
|
@ -13,7 +12,7 @@ import tseslint from 'typescript-eslint'
|
|||
export default defineConfig(
|
||||
{ ignores: ['dist', './.storybook/**', './storybook-static/**'] },
|
||||
{
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended, eslintPluginPrettierRecommended],
|
||||
extends: [js.configs.recommended, ...tseslint.configs.recommended],
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2023,
|
||||
|
|
@ -38,11 +37,27 @@ export default defineConfig(
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
ignores: [
|
||||
'./src/components/ui/*.tsx', // shadcn components
|
||||
'./src/**/*.stories.tsx',
|
||||
'./src/components/settings/CollaboratorFeesForm.tsx', // TODO: remove
|
||||
],
|
||||
files: ['./src/**/*.{ts,tsx}'],
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
projectService: true,
|
||||
},
|
||||
},
|
||||
extends: [...tseslint.configs.recommendedTypeChecked],
|
||||
rules: {
|
||||
'@typescript-eslint/no-redundant-type-constituents': ['off'], // shows intent
|
||||
},
|
||||
},
|
||||
{
|
||||
extends: [eslintPluginUnicorn.configs.recommended],
|
||||
ignores: [
|
||||
'./src/components/ui/*.tsx', // shadcn components
|
||||
'./src/components/earn/CreateFidelityBondDialog.tsx', // TODO: remove
|
||||
'./src/components/settings/CollaboratorFeesForm.tsx', // TODO: remove
|
||||
],
|
||||
rules: {
|
||||
|
|
@ -60,11 +75,7 @@ export default defineConfig(
|
|||
'unicorn/catch-error-name': [
|
||||
'error',
|
||||
{
|
||||
ignore: [
|
||||
String.raw`^error\d*$`,
|
||||
'_ignoredOnPurpose',
|
||||
'e', // TODO: remove
|
||||
],
|
||||
ignore: ['_ignoredOnPurpose'],
|
||||
},
|
||||
],
|
||||
'unicorn/numeric-separators-style': [
|
||||
|
|
|
|||
99
package-lock.json
generated
99
package-lock.json
generated
|
|
@ -72,9 +72,7 @@
|
|||
"@vitest/coverage-v8": "4.0.9",
|
||||
"conventional-changelog": "7.1.1",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-compat": "6.1.0",
|
||||
"eslint-plugin-prettier": "5.5.5",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
"eslint-plugin-react-refresh": "0.5.0",
|
||||
"eslint-plugin-storybook": "10.2.5",
|
||||
|
|
@ -1353,19 +1351,6 @@
|
|||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/core": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
|
||||
"integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.58.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.1.tgz",
|
||||
|
|
@ -6289,23 +6274,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-config-prettier": {
|
||||
"version": "10.1.8",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz",
|
||||
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint-config-prettier"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-compat": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-6.1.0.tgz",
|
||||
|
|
@ -6355,37 +6323,6 @@
|
|||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.5.5",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz",
|
||||
"integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prettier-linter-helpers": "^1.0.1",
|
||||
"synckit": "^0.11.12"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint-plugin-prettier"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/eslint": ">=8.0.0",
|
||||
"eslint": ">=8.0.0",
|
||||
"eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
|
||||
"prettier": ">=3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/eslint": {
|
||||
"optional": true
|
||||
},
|
||||
"eslint-config-prettier": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-hooks": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz",
|
||||
|
|
@ -6644,13 +6581,6 @@
|
|||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-diff": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
|
||||
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/fast-json-stable-stringify": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||
|
|
@ -8540,19 +8470,6 @@
|
|||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-linter-helpers": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz",
|
||||
"integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-diff": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-tailwindcss": {
|
||||
"version": "0.7.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.7.2.tgz",
|
||||
|
|
@ -9724,22 +9641,6 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.11.12",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",
|
||||
"integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/synckit"
|
||||
}
|
||||
},
|
||||
"node_modules/tailwind-merge": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz",
|
||||
|
|
|
|||
|
|
@ -115,9 +115,7 @@
|
|||
"@vitest/coverage-v8": "4.0.9",
|
||||
"conventional-changelog": "7.1.1",
|
||||
"eslint": "9.39.2",
|
||||
"eslint-config-prettier": "10.1.8",
|
||||
"eslint-plugin-compat": "6.1.0",
|
||||
"eslint-plugin-prettier": "5.5.5",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
"eslint-plugin-react-refresh": "0.5.0",
|
||||
"eslint-plugin-storybook": "10.2.5",
|
||||
|
|
|
|||
|
|
@ -91,7 +91,12 @@ function LogViewer({ value, refresh }: LogViewerProps) {
|
|||
<DownloadIcon className="group/download" />
|
||||
{t('global.download')}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleRefresh} disabled={isLoadingRefresh} title={t('global.refresh')}>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => void handleRefresh()}
|
||||
disabled={isLoadingRefresh}
|
||||
title={t('global.refresh')}
|
||||
>
|
||||
<RefreshCwIcon
|
||||
className={cn({
|
||||
'animate-spin': isLoadingRefresh,
|
||||
|
|
@ -161,11 +166,13 @@ export const LogsContent = ({ enabled, className }: LogsContentProps) => {
|
|||
setAlert(undefined)
|
||||
setLogFileContent(data)
|
||||
})
|
||||
.catch((error) => {
|
||||
.catch((error: unknown) => {
|
||||
if (signal.aborted) return
|
||||
|
||||
const reason = (error instanceof Error ? error.message : undefined) || t('global.errors.reason_unknown')
|
||||
const errorMessage = t('logs.error_loading_logs_failed', {
|
||||
reason: error.message || t('global.errors.reason_unknown'),
|
||||
/* TODO: add reason to i18n string */
|
||||
reason,
|
||||
})
|
||||
|
||||
if (isDevMode()) {
|
||||
|
|
@ -183,7 +190,7 @@ export const LogsContent = ({ enabled, className }: LogsContentProps) => {
|
|||
|
||||
if (enabled && !isInitialized) {
|
||||
const abortCtrl = new AbortController()
|
||||
refresh(abortCtrl.signal).finally(() => {
|
||||
void refresh(abortCtrl.signal).finally(() => {
|
||||
if (abortCtrl.signal.aborted) return
|
||||
setIsInitialized(true)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -95,7 +95,12 @@ function LogContent({ value, refresh }: LogContentProps) {
|
|||
<DownloadIcon className="group/download" />
|
||||
{t('global.download')}
|
||||
</Button>
|
||||
<Button variant="outline" onClick={handleRefresh} disabled={isLoadingRefresh} title={t('global.refresh')}>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => void handleRefresh()}
|
||||
disabled={isLoadingRefresh}
|
||||
title={t('global.refresh')}
|
||||
>
|
||||
<RefreshCwIcon className={cn({ 'animate-spin': isLoadingRefresh })} />
|
||||
{t('global.refresh')}
|
||||
</Button>
|
||||
|
|
@ -159,9 +164,10 @@ export const LogsPage = () => {
|
|||
.catch((error) => {
|
||||
if (signal.aborted) return
|
||||
|
||||
const reason = (error instanceof Error ? error.message : undefined) || t('global.errors.reason_unknown')
|
||||
const errorMessage = t('logs.error_loading_logs_failed', {
|
||||
/* TODO: add reason to i18n string */
|
||||
reason: error.message || t('global.errors.reason_unknown'),
|
||||
reason,
|
||||
})
|
||||
|
||||
if (isDevMode()) {
|
||||
|
|
@ -181,7 +187,7 @@ export const LogsPage = () => {
|
|||
|
||||
if (!isInitialized) {
|
||||
const abortCtrl = new AbortController()
|
||||
refresh(abortCtrl.signal).finally(() => {
|
||||
void refresh(abortCtrl.signal).finally(() => {
|
||||
if (abortCtrl.signal.aborted) return
|
||||
setIsInitialized(true)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ export default function MainWalletPage({ walletFileName }: MainWalletPageProps)
|
|||
{t('global.errors.error_loading_wallet_failed', {
|
||||
reason: error.message || t('global.errors.reason_unknown'),
|
||||
})}
|
||||
<Button variant="outline" size="sm" onClick={() => refetchWalletData()}>
|
||||
<Button variant="outline" size="sm" onClick={() => void refetchWalletData()}>
|
||||
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
|
||||
{t('global.retry')}
|
||||
</Button>
|
||||
|
|
@ -145,7 +145,7 @@ export default function MainWalletPage({ walletFileName }: MainWalletPageProps)
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex w-full max-w-xl justify-end">
|
||||
<Button variant="ghost" size="xs" onClick={() => refetchWalletData()}>
|
||||
<Button variant="ghost" size="xs" onClick={() => void refetchWalletData()}>
|
||||
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
|
||||
{t('global.refresh')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ const SwitchWalletPage = ({ walletFileName }: SwitchWalletPageProps) => {
|
|||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onClick={handleLockCurrentWallet}
|
||||
onClick={() => void handleLockCurrentWallet()}
|
||||
disabled={lockCurrentWallet.isFetching || currentWalletLocked}
|
||||
className="flex-1"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -81,19 +81,16 @@ const CreateWalletPage = () => {
|
|||
}
|
||||
|
||||
const walletFileName = walletDisplayNameToFileName(walletName)
|
||||
const { data: createData, error: createError } = await createwallet({
|
||||
const { data: createData } = await createwallet({
|
||||
client,
|
||||
body: {
|
||||
walletname: walletFileName,
|
||||
password,
|
||||
wallettype: 'sw-fb',
|
||||
},
|
||||
throwOnError: true,
|
||||
})
|
||||
|
||||
if (createError) {
|
||||
throw createError
|
||||
}
|
||||
|
||||
let hashedPassword: string | undefined = undefined
|
||||
try {
|
||||
hashedPassword = await hashPassword(password, createData.walletname)
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ function DevConfigTabContent({ walletFileName }: DevConfigTabContentProps) {
|
|||
<code className="light:text-red-700 text-red-800">feeConfig.maxFeesConfigMissing:</code>
|
||||
<pre className="text-xs">{JSON.stringify(feeConfig.maxFeesConfigMissing, null, 2)}</pre>
|
||||
</div>
|
||||
<Button onClick={() => feeConfig.refetchAll()}>feeConfig.refetchAll()</Button>
|
||||
<Button onClick={() => void feeConfig.refetchAll()}>feeConfig.refetchAll()</Button>
|
||||
|
||||
<FeeConfigTestComponent walletFileName={walletFileName} />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export function CreateFidelityBondDialog({ open, onOpenChange, walletFileName }:
|
|||
<Button
|
||||
variant="outline"
|
||||
className="min-w-32"
|
||||
onClick={handleUnfreezeUtxos}
|
||||
onClick={() => void handleUnfreezeUtxos()}
|
||||
disabled={unfreezeUtxo.isPending}
|
||||
>
|
||||
{unfreezeUtxo.isPending ? (
|
||||
|
|
@ -78,7 +78,7 @@ export function CreateFidelityBondDialog({ open, onOpenChange, walletFileName }:
|
|||
<Button variant="outline" className="min-w-24" onClick={() => handleOpenChange(false)} disabled={isLoading}>
|
||||
{t('earn.fidelity_bond.select_date.text_secondary_button')}
|
||||
</Button>
|
||||
<Button className="min-w-32" onClick={handleNext} disabled={!canProceed() || isLoading}>
|
||||
<Button className="min-w-32" onClick={() => void handleNext()} disabled={!canProceed() || isLoading}>
|
||||
{isLoading && <Spinner className="mr-2 h-4 w-4" />}
|
||||
{step === 'freeze_utxos'
|
||||
? utxosToFreeze.length > 0
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ export function CreateFidelityBondDialogSteps({ wizard }: CreateFidelityBondDial
|
|||
<Select
|
||||
value={selectedMonth}
|
||||
onValueChange={(month) => {
|
||||
const year = selectedYear || String(parseInt(month, 10) >= minMonth ? minYear : minYear + 1)
|
||||
const year = selectedYear || String(Number.parseInt(month, 10) >= minMonth ? minYear : minYear + 1)
|
||||
const newLockdate = clampLockdate(`${year}-${month}`)
|
||||
setSelectedLockdate(newLockdate)
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ export function generateLockdateOptions(isDeveloperMode: boolean): { value: fb.L
|
|||
|
||||
export function getYearOptions(lockdateOptions: { value: fb.Lockdate }[]) {
|
||||
if (lockdateOptions.length === 0) return []
|
||||
const minYear = parseInt(lockdateOptions[0].value.slice(0, 4), 10)
|
||||
const maxYear = parseInt(lockdateOptions[lockdateOptions.length - 1].value.slice(0, 4), 10)
|
||||
const minYear = Number.parseInt(lockdateOptions[0].value.slice(0, 4), 10)
|
||||
const maxYear = Number.parseInt(lockdateOptions.at(-1)!.value.slice(0, 4), 10)
|
||||
return Array.from({ length: maxYear - minYear + 1 }, (_, i) => ({
|
||||
value: String(minYear + i),
|
||||
label: String(minYear + i),
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ export function useCreateFidelityBondWizard(
|
|||
const yearOptions = useMemo(() => getYearOptions(lockdateOptions), [lockdateOptions])
|
||||
const monthOptions = useMemo(() => getMonthOptions(), [])
|
||||
|
||||
const minLockdate = lockdateOptions[0]?.value ?? ''
|
||||
const maxLockdate = lockdateOptions[lockdateOptions.length - 1]?.value ?? ''
|
||||
const minLockdate = lockdateOptions.at(0)?.value ?? ''
|
||||
const maxLockdate = lockdateOptions.at(-1)?.value ?? ''
|
||||
const clampLockdate = (lockdate: string): fb.Lockdate | '' => {
|
||||
if (!lockdate || lockdate < minLockdate) return minLockdate || ''
|
||||
if (lockdate > maxLockdate) return maxLockdate || ''
|
||||
|
|
@ -51,8 +51,8 @@ export function useCreateFidelityBondWizard(
|
|||
}
|
||||
const selectedYear = selectedLockdate ? selectedLockdate.slice(0, 4) : ''
|
||||
const selectedMonth = selectedLockdate ? selectedLockdate.slice(5, 7) : ''
|
||||
const minYear = minLockdate ? parseInt(minLockdate.slice(0, 4), 10) : 0
|
||||
const minMonth = minLockdate ? parseInt(minLockdate.slice(5, 7), 10) : 1
|
||||
const minYear = minLockdate ? Number.parseInt(minLockdate.slice(0, 4), 10) : 0
|
||||
const minMonth = minLockdate ? Number.parseInt(minLockdate.slice(5, 7), 10) : 1
|
||||
|
||||
const existingFbLockdates = useMemo(() => {
|
||||
return walletInfo.fidelityBondSummary.fbOutputs
|
||||
|
|
@ -75,17 +75,17 @@ export function useCreateFidelityBondWizard(
|
|||
|
||||
const availableUtxos = useMemo(() => {
|
||||
if (selectedJarIndex === undefined) return []
|
||||
const jar = walletInfo.jars.find((j) => j.jarIndex === selectedJarIndex)
|
||||
const jar = walletInfo.jars.find((it) => it.jarIndex === selectedJarIndex)
|
||||
if (!jar) return []
|
||||
return jar.utxos.filter((utxo) => !utxo.frozen && !fb.utxo.isFidelityBond(utxo))
|
||||
}, [walletInfo.jars, selectedJarIndex])
|
||||
|
||||
const utxosToFreeze = useMemo(() => {
|
||||
if (selectedJarIndex === undefined) return []
|
||||
const jar = walletInfo.jars.find((j) => j.jarIndex === selectedJarIndex)
|
||||
const jar = walletInfo.jars.find((it) => it.jarIndex === selectedJarIndex)
|
||||
if (!jar) return []
|
||||
return jar.utxos.filter(
|
||||
(utxo) => !utxo.frozen && !fb.utxo.isFidelityBond(utxo) && !selectedUtxos.some((s) => s.utxo === utxo.utxo),
|
||||
(utxo) => !utxo.frozen && !fb.utxo.isFidelityBond(utxo) && !selectedUtxos.some((it) => it.utxo === utxo.utxo),
|
||||
)
|
||||
}, [walletInfo.jars, selectedJarIndex, selectedUtxos])
|
||||
|
||||
|
|
@ -115,27 +115,24 @@ export function useCreateFidelityBondWizard(
|
|||
|
||||
const freezeUtxo = useMutation({
|
||||
...freezeMutation({ client }),
|
||||
onError: (err: ErrorMessage) => {
|
||||
console.error('Freeze error:', err)
|
||||
const reason = err.message || err.error_description || t('global.errors.reason_unknown')
|
||||
onError: (error: ErrorMessage) => {
|
||||
const reason = error.message || error.error_description || t('global.errors.reason_unknown')
|
||||
setError(`${t('earn.fidelity_bond.error_freezing_utxos')} ${reason}`)
|
||||
},
|
||||
})
|
||||
|
||||
const unfreezeUtxo = useMutation({
|
||||
...freezeMutation({ client }),
|
||||
onError: (err: ErrorMessage) => {
|
||||
console.error('Unfreeze error:', err)
|
||||
const reason = err.message || err.error_description || t('global.errors.reason_unknown')
|
||||
onError: (error: ErrorMessage) => {
|
||||
const reason = error.message || error.error_description || t('global.errors.reason_unknown')
|
||||
setError(`${t('earn.fidelity_bond.error_unfreezing_utxos')} ${reason}`)
|
||||
},
|
||||
})
|
||||
|
||||
const directSend = useMutation({
|
||||
...directsendMutation({ client }),
|
||||
onError: (err: ErrorMessage) => {
|
||||
console.error('DirectSend error:', err)
|
||||
const reason = err.message || err.error_description || t('global.errors.reason_unknown')
|
||||
onError: (error: ErrorMessage) => {
|
||||
const reason = error.message || error.error_description || t('global.errors.reason_unknown')
|
||||
setError(`${t('earn.fidelity_bond.error_creating_fidelity_bond')} ${reason}`)
|
||||
},
|
||||
})
|
||||
|
|
@ -243,7 +240,7 @@ export function useCreateFidelityBondWizard(
|
|||
setTxResult(result)
|
||||
setStep('success')
|
||||
toast.success(t('earn.fidelity_bond.create_fidelity_bond.success_text'))
|
||||
walletInfo.refetch()
|
||||
await walletInfo.refetch()
|
||||
} catch {
|
||||
setStep('review')
|
||||
}
|
||||
|
|
@ -259,19 +256,19 @@ export function useCreateFidelityBondWizard(
|
|||
}
|
||||
setFrozenUtxos([])
|
||||
toast.success(t('earn.fidelity_bond.unfreeze_utxos.done'))
|
||||
walletInfo.refetch()
|
||||
await walletInfo.refetch()
|
||||
} catch {
|
||||
// Error handled in onError
|
||||
}
|
||||
}
|
||||
|
||||
const toggleUtxoSelection = (utxo: Utxo) => {
|
||||
setSelectedUtxos((prev) => {
|
||||
const isSelected = prev.some((u) => u.utxo === utxo.utxo)
|
||||
setSelectedUtxos((current) => {
|
||||
const isSelected = current.some((u) => u.utxo === utxo.utxo)
|
||||
if (isSelected) {
|
||||
return prev.filter((u) => u.utxo !== utxo.utxo)
|
||||
return current.filter((u) => u.utxo !== utxo.utxo)
|
||||
}
|
||||
return [...prev, utxo]
|
||||
return [...current, utxo]
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ const baseSchema = yup
|
|||
then: (schema) => schema.min(JAM.OFFER_FEE_ABS_MIN).required(),
|
||||
otherwise: (schema) =>
|
||||
schema
|
||||
.transform((value) => (Number.isNaN(value) ? null : value))
|
||||
.transform((value) => (Number.isSafeInteger(value) ? Number(value) : null))
|
||||
.nullable()
|
||||
.optional(),
|
||||
}),
|
||||
|
|
@ -68,7 +68,7 @@ const baseSchema = yup
|
|||
schema.min(factorToPercentage(JAM.OFFER_FEE_REL_MIN)).max(factorToPercentage(JAM.OFFER_FEE_REL_MAX)).required(),
|
||||
otherwise: (schema) =>
|
||||
schema
|
||||
.transform((value) => (Number.isNaN(value) ? null : value))
|
||||
.transform((value) => (Number.isFinite(value) ? Number(value) : null))
|
||||
.nullable()
|
||||
.optional(),
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ export const EarnPage = ({ walletFileName }: EarnPageProps) => {
|
|||
value={jmSession.offer_list[0]}
|
||||
nickname={jmSession.nickname}
|
||||
>
|
||||
<Button type="button" onClick={() => onStop()} className="w-full" size="lg">
|
||||
<Button type="button" onClick={() => void onStop()} className="w-full" size="lg">
|
||||
{isWaitingMakerStop ? (
|
||||
<>
|
||||
<Spinner className="motion-reduce:hidden" />
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ function UnknownError({ error }: { error: unknown }) {
|
|||
return <ErrorView title={title} subtitle={subtitle} reason={t('global.errors.reason_unknown')} />
|
||||
}
|
||||
|
||||
const reason = 'message' in error && error.message ? String(error.message) : undefined
|
||||
const stacktrace = 'stack' in error && error.stack ? String(error.stack) : undefined
|
||||
const reason = 'message' in error && typeof error.message === 'string' ? error.message : undefined
|
||||
const stacktrace = 'stack' in error && typeof error.stack === 'string' ? error.stack : undefined
|
||||
return (
|
||||
<ErrorView
|
||||
title={title}
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ export const OrderbookContent = ({ enabled, className }: OrderbookContentProps)
|
|||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<Button variant="ghost" onClick={() => refetchOrderbookData()} disabled={isFetching}>
|
||||
<Button variant="ghost" onClick={() => void refetchOrderbookData()} disabled={isFetching}>
|
||||
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
|
||||
{t('global.retry')}
|
||||
</Button>
|
||||
|
|
@ -246,7 +246,13 @@ export const OrderbookContent = ({ enabled, className }: OrderbookContentProps)
|
|||
)}
|
||||
|
||||
<ButtonGroup>
|
||||
<Button variant="outline" className="rounded-r-none" size="sm" onClick={handleReload} disabled={isFetching}>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="rounded-r-none"
|
||||
size="sm"
|
||||
onClick={() => void handleReload()}
|
||||
disabled={isFetching}
|
||||
>
|
||||
<RefreshCwIcon className={cn({ 'motion-safe:animate-spin': isFetching })} />
|
||||
{t('orderbook.button_reload_title')}
|
||||
</Button>
|
||||
|
|
@ -259,7 +265,7 @@ export const OrderbookContent = ({ enabled, className }: OrderbookContentProps)
|
|||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-52">
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onClick={handleClearAndReload} disabled={isFetching}>
|
||||
<DropdownMenuItem onClick={() => void handleClearAndReload()} disabled={isFetching}>
|
||||
{t('orderbook.button_refresh_text')}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ type OrderTableColumnMeta =
|
|||
| undefined
|
||||
|
||||
const fuzzyFilter: FilterFn<OrderTableEntry> = (row, columnId, value, addMeta) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- tanstack/table api
|
||||
const itemRank = rankItem(row.getValue(columnId), value)
|
||||
addMeta({ itemRank })
|
||||
return itemRank.passed
|
||||
|
|
@ -121,7 +122,7 @@ export const OrderbookTable = ({
|
|||
numeric: true,
|
||||
} as OrderTableColumnMeta,
|
||||
}),
|
||||
columnHelper.accessor('type', {
|
||||
columnHelper.accessor<'type', OrderTableEntry['type']>('type', {
|
||||
header: () => <div className="flex items-center">{t('orderbook.table.heading_type')}</div>,
|
||||
sortingFn: (a, b) => a.original.type.displayValue.localeCompare(b.original.type.displayValue),
|
||||
cell: (info) => (
|
||||
|
|
@ -161,7 +162,7 @@ export const OrderbookTable = ({
|
|||
numeric: true,
|
||||
} as OrderTableColumnMeta,
|
||||
}),
|
||||
columnHelper.accessor('minimumSize', {
|
||||
columnHelper.accessor<'minimumSize', OrderTableEntry['minimumSize']>('minimumSize', {
|
||||
header: () => <div className="flex items-center">{t('orderbook.table.heading_minimum_size')}</div>,
|
||||
sortingFn: (a, b) => Number(a.original.minimumSize) - Number(b.original.minimumSize),
|
||||
cell: (info) => <Balance colored={false} valueString={info.getValue()} />,
|
||||
|
|
@ -170,7 +171,7 @@ export const OrderbookTable = ({
|
|||
numeric: true,
|
||||
} as OrderTableColumnMeta,
|
||||
}),
|
||||
columnHelper.accessor('maximumSize', {
|
||||
columnHelper.accessor<'maximumSize', OrderTableEntry['maximumSize']>('maximumSize', {
|
||||
header: () => <div className="flex items-center">{t('orderbook.table.heading_maximum_size')}</div>,
|
||||
sortingFn: (a, b) => Number(a.original.maximumSize) - Number(b.original.maximumSize),
|
||||
cell: (info) => <Balance colored={false} valueString={info.getValue()} />,
|
||||
|
|
@ -179,7 +180,7 @@ export const OrderbookTable = ({
|
|||
numeric: true,
|
||||
} as OrderTableColumnMeta,
|
||||
}),
|
||||
columnHelper.accessor('minerFeeContribution', {
|
||||
columnHelper.accessor<'minerFeeContribution', OrderTableEntry['minerFeeContribution']>('minerFeeContribution', {
|
||||
header: () => <div className="flex items-center">{t('orderbook.table.heading_miner_fee_contribution')}</div>,
|
||||
sortingFn: (a, b) => Number(a.original.minerFeeContribution) - Number(b.original.minerFeeContribution),
|
||||
cell: (info) => <Balance colored={false} valueString={info.getValue()} />,
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ const receiveFormSchema = (jars: Jar[]) => {
|
|||
.integer()
|
||||
.min(1)
|
||||
.max(21_000_000 * 100_000_000)
|
||||
.transform((value) => (Number.isNaN(value) ? undefined : value))
|
||||
.transform((value) => (Number.isSafeInteger(value) ? Number(value) : null))
|
||||
.nullable()
|
||||
.optional(),
|
||||
})
|
||||
|
|
@ -83,8 +83,10 @@ export const ReceiveForm = ({ className, defaultValues, onSubmit, jars, disabled
|
|||
|
||||
const values = useWatch({ control })
|
||||
|
||||
const doOnChange = handleSubmit(onSubmit)
|
||||
|
||||
return (
|
||||
<form onChange={handleSubmit(onSubmit)} className={cn('flex flex-col gap-4', className)} noValidate>
|
||||
<form onChange={(event) => void doOnChange(event)} className={cn('flex flex-col gap-4', className)} noValidate>
|
||||
<div className="space-y-2">
|
||||
<Field className="space-y-4" data-invalid={errors.source !== undefined}>
|
||||
<FieldLabel>{t('receive.label_source_jar')}</FieldLabel>
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export const ReceivePage = ({ walletFileName }: ReceivePageProps) => {
|
|||
const getAddressQueryOptions = getaddressOptions({
|
||||
client,
|
||||
path: {
|
||||
walletname: encodeURIComponent(walletFileName!),
|
||||
walletname: encodeURIComponent(walletFileName),
|
||||
mixdepth: String(sourceJar?.jarIndex),
|
||||
},
|
||||
})
|
||||
|
|
@ -147,7 +147,12 @@ export const ReceivePage = ({ walletFileName }: ReceivePageProps) => {
|
|||
)}
|
||||
|
||||
<div className="mt-4 flex items-center gap-2">
|
||||
<Button variant="outline" size="sm" onClick={getNewAddress} disabled={getAddressQuery.isFetching}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => void getNewAddress()}
|
||||
disabled={getAddressQuery.isFetching}
|
||||
>
|
||||
{getAddressQuery.isFetching ? (
|
||||
<>
|
||||
<RefreshCwIcon className="animate-spin motion-reduce:hidden" />
|
||||
|
|
|
|||
|
|
@ -41,13 +41,16 @@ export default function JarSelectorDialog({
|
|||
onOpenChange(false)
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
const confirm = async () => {
|
||||
if (selectedJar === undefined) return
|
||||
|
||||
setIsConfirming(true)
|
||||
onConfirm(selectedJar.jarIndex)
|
||||
.then(() => setSelectedJar(undefined))
|
||||
.finally(() => setIsConfirming(false))
|
||||
try {
|
||||
await onConfirm(selectedJar.jarIndex)
|
||||
setSelectedJar(undefined)
|
||||
} finally {
|
||||
setIsConfirming(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -79,7 +82,7 @@ export default function JarSelectorDialog({
|
|||
<Button className="flex-1" variant="outline" onClick={handleClose}>
|
||||
{t('modal.confirm_button_reject')}
|
||||
</Button>
|
||||
<Button className="flex-1" onClick={confirm} disabled={!selectedJar || isConfirming}>
|
||||
<Button className="flex-1" onClick={() => void confirm()} disabled={!selectedJar || isConfirming}>
|
||||
{isConfirming ? (
|
||||
<>
|
||||
<Spinner className="motion-reduce:hidden" />
|
||||
|
|
|
|||
|
|
@ -98,9 +98,13 @@ export default function PaymentConfirmDialog({
|
|||
onOpenChange(false)
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
const confirm = async () => {
|
||||
setIsConfirming(true)
|
||||
onConfirm(values).finally(() => setIsConfirming(false))
|
||||
try {
|
||||
await onConfirm(values)
|
||||
} finally {
|
||||
setIsConfirming(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -213,7 +217,7 @@ export default function PaymentConfirmDialog({
|
|||
<Button className="flex-1" variant="outline" onClick={handleClose}>
|
||||
{t('modal.confirm_button_reject')}
|
||||
</Button>
|
||||
<Button className="flex-1" onClick={confirm} disabled={isConfirming}>
|
||||
<Button className="flex-1" onClick={() => void confirm()} disabled={isConfirming}>
|
||||
{isConfirming ? (
|
||||
<>
|
||||
<Spinner className="motion-reduce:hidden" />
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ export const AccountXpubsDialog = ({
|
|||
|
||||
useEffect(() => {
|
||||
if (open && isPasswordVerified && seedQuery.data === undefined) {
|
||||
seedQuery.refetch()
|
||||
void seedQuery.refetch()
|
||||
}
|
||||
}, [open, isPasswordVerified, seedQuery])
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ const fillLevelToPercent = (fillLevel: JarFillLevel): number => {
|
|||
}
|
||||
|
||||
interface JarIconProps {
|
||||
color?: string
|
||||
amount?: AmountSats
|
||||
totalBalance?: number
|
||||
color: string
|
||||
amount: AmountSats
|
||||
totalBalance: AmountSats
|
||||
width?: number
|
||||
height?: number
|
||||
isSelected?: boolean
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ type BranchEntryTableColumnMeta =
|
|||
| undefined
|
||||
|
||||
const fuzzyFilter: FilterFn<BranchEntryTableRow> = (row, columnId, value, addMeta) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- tanstack/table api
|
||||
const itemRank = rankItem(row.getValue(columnId), value)
|
||||
addMeta({ itemRank })
|
||||
return itemRank.passed
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ type UtxoTableColumnMeta =
|
|||
| undefined
|
||||
|
||||
const fuzzyFilter: FilterFn<UtxoTableEntry> = (row, columnId, value, addMeta) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- tanstack/table api
|
||||
const itemRank = rankItem(row.getValue(columnId), value)
|
||||
addMeta({ itemRank })
|
||||
return itemRank.passed
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ describe('setIntervalDebounced', () => {
|
|||
const callback = vi.fn().mockRejectedValueOnce(error).mockResolvedValueOnce(undefined)
|
||||
const onTimerIdChanged = vi.fn()
|
||||
const onError = vi.fn((_, loop) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call -- okay when using vi mocks
|
||||
loop()
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
||||
"target": "es2023",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["es2023", "DOM", "DOM.Iterable"],
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2023", "DOM", "DOM.Iterable"],
|
||||
"module": "esnext",
|
||||
"skipLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
||||
"target": "ES2022",
|
||||
"target": "es2023",
|
||||
"lib": ["ES2023"],
|
||||
"module": "ESNext",
|
||||
"module": "esnext",
|
||||
"skipLibCheck": true,
|
||||
|
||||
/* Bundler mode */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue