diff --git a/src/components/Send/SendForm.tsx b/src/components/Send/SendForm.tsx
index 51c93738..9f387fbe 100644
--- a/src/components/Send/SendForm.tsx
+++ b/src/components/Send/SendForm.tsx
@@ -228,8 +228,6 @@ interface InnerSendFormProps {
feeConfigValues?: FeeValues
reloadFeeConfigValues: () => void
disabled?: boolean
- isDisplayReloadInShowUtxos: boolean
- setIsDisplayReloadInShowUtxos: (arg: boolean) => void
}
const InnerSendForm = ({
@@ -243,8 +241,6 @@ const InnerSendForm = ({
feeConfigValues,
reloadFeeConfigValues,
disabled = false,
- isDisplayReloadInShowUtxos,
- setIsDisplayReloadInShowUtxos,
}: InnerSendFormProps) => {
const { t } = useTranslation()
const serviceInfo = useServiceInfo()
@@ -283,8 +279,6 @@ const InnerSendForm = ({
isLoading={isLoading}
disabled={disabled}
variant={showCoinjoinPreconditionViolationAlert ? 'warning' : 'default'}
- isDisplayReloadInShowUtxos={isDisplayReloadInShowUtxos}
- setIsDisplayReloadInShowUtxos={setIsDisplayReloadInShowUtxos}
/>
{showCoinjoinPreconditionViolationAlert && (
@@ -386,8 +380,6 @@ type SendFormProps = Omit
& {
formRef?: React.Ref>
blurred?: boolean
wallet: CurrentWallet
- isDisplayReloadInShowUtxos: boolean
- setIsDisplayReloadInShowUtxos: (arg: boolean) => void
}
export const SendForm = ({
diff --git a/src/components/Send/ShowUtxos.tsx b/src/components/Send/ShowUtxos.tsx
old mode 100644
new mode 100755
index 4d480a15..03eacd75
--- a/src/components/Send/ShowUtxos.tsx
+++ b/src/components/Send/ShowUtxos.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect, useCallback, memo, useRef, useMemo } from 'react'
+import { useState, useEffect, useCallback, memo, useMemo } from 'react'
import * as rb from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import type { TFunction } from 'i18next'
@@ -6,14 +6,7 @@ import classNames from 'classnames'
import { Table, Body, Row, Cell } from '@table-library/react-table-library/table'
import { useTheme } from '@table-library/react-table-library/theme'
import * as TableTypes from '@table-library/react-table-library/types/table'
-import * as Api from '../../libs/JmWalletApi'
-import {
- WalletInfo,
- CurrentWallet,
- useReloadCurrentWalletInfo,
- Utxo,
- useCurrentWalletInfo,
-} from '../../context/WalletContext'
+import { WalletInfo, Utxo, useCurrentWalletInfo } from '../../context/WalletContext'
import { useSettings, Settings } from '../../context/SettingsContext'
import Alert from '../Alert'
import Balance from '../Balance'
@@ -22,17 +15,18 @@ import Sprite from '../Sprite'
import { utxoTags } from '../jar_details/UtxoList'
import mainStyles from '../MainWalletView.module.css'
import styles from './ShowUtxos.module.css'
-
-type UtxoList = Array
+import { UtxoList } from './SourceJarSelector'
interface ShowUtxosProps {
- walletInfo: WalletInfo
- wallet: CurrentWallet
isOpen: boolean
onCancel: () => void
- jarIndex: String
- isDisplayReloadInShowUtxos: boolean
- setIsDisplayReloadInShowUtxos: (arg: boolean) => void
+ onConfirm: () => void
+ alert: SimpleAlert | undefined
+ isLoading: boolean
+ frozenUtxos: UtxoList
+ unFrozenUtxos: UtxoList
+ setFrozenUtxos: (arg: UtxoList) => void
+ setUnFrozenUtxos: (arg: UtxoList) => void
}
interface UtxoRowProps {
@@ -286,135 +280,49 @@ const Divider = ({ isState, setIsState, className }: DividerProps) => {
}
const ShowUtxos = ({
- walletInfo,
- wallet,
isOpen,
onCancel,
- jarIndex,
- isDisplayReloadInShowUtxos,
- setIsDisplayReloadInShowUtxos,
+ onConfirm,
+ alert,
+ isLoading,
+ frozenUtxos,
+ unFrozenUtxos,
+ setFrozenUtxos,
+ setUnFrozenUtxos,
}: ShowUtxosProps) => {
- const [alert, setAlert] = useState(undefined)
- const [showFrozenUtxos, setShowFrozenUtxos] = useState(false)
- const [unFrozenUtxos, setUnFrozenUtxos] = useState([])
- const [frozenUtxos, setFrozenUtxos] = useState([])
- const [isLoading, setIsLoading] = useState(true)
const { t } = useTranslation()
- const reloadCurrentWalletInfo = useReloadCurrentWalletInfo()
const settings = useSettings()
+ const [showFrozenUtxos, setShowFrozenUtxos] = useState(false)
- const isHandleReloadExecuted = useRef(false)
-
- // Load data from wallet info
- const loadData = useCallback(
- (walletInfo: WalletInfo) => {
- const data = Object.entries(walletInfo.utxosByJar).find(([key]) => key === jarIndex)
- const utxos: any = data ? data[1] : []
-
- const frozenUtxoList = utxos
- .filter((utxo: any) => utxo.frozen)
- .map((utxo: any) => ({ ...utxo, id: utxo.utxo, checked: false }))
- const unFrozenUtxosList = utxos
- .filter((utxo: any) => !utxo.frozen)
- .map((utxo: any) => ({ ...utxo, id: utxo.utxo, checked: true }))
-
- setFrozenUtxos(frozenUtxoList)
- setUnFrozenUtxos(unFrozenUtxosList)
-
- if (unFrozenUtxosList.length === 0) {
- setShowFrozenUtxos(true)
- setAlert({ variant: 'warning', message: t('show_utxos.alert_for_unfreeze_utxos'), dismissible: true })
+ // Handler to toggle UTXO selection
+ const handleUtxoCheckedState = useCallback(
+ (utxoIndex: number, isFrozen: boolean) => {
+ if (!isFrozen) {
+ const utxos = unFrozenUtxos.map((utxo: Utxo, i: number) =>
+ i === utxoIndex ? { ...utxo, checked: !utxo.checked } : utxo,
+ )
+ setUnFrozenUtxos(utxos)
} else {
- setAlert(undefined)
+ const utxos = frozenUtxos.map((utxo: Utxo, i: number) =>
+ i === utxoIndex ? { ...utxo, checked: !utxo.checked } : utxo,
+ )
+ setFrozenUtxos(utxos)
}
},
- [jarIndex, t],
+ [frozenUtxos, unFrozenUtxos, setUnFrozenUtxos, setFrozenUtxos],
)
- // Reload wallet info
- const handleReload = useCallback(async () => {
- const abortCtrl = new AbortController()
- try {
- setIsLoading(true)
- await reloadCurrentWalletInfo.reloadUtxos({ signal: abortCtrl.signal })
- if (isDisplayReloadInShowUtxos) {
- await reloadCurrentWalletInfo.reloadDisplay({ signal: abortCtrl.signal })
- setIsDisplayReloadInShowUtxos(false)
- }
- loadData(walletInfo)
- setIsLoading(false)
- } catch (err: any) {
- if (!abortCtrl.signal.aborted) {
- setAlert({ variant: 'danger', message: err.message, dismissible: true })
- }
- }
- }, [isDisplayReloadInShowUtxos, setIsDisplayReloadInShowUtxos, reloadCurrentWalletInfo, loadData, walletInfo])
-
- //Effect to Reload walletInfo only once
- useEffect(() => {
- if (!isHandleReloadExecuted.current) {
- handleReload()
- isHandleReloadExecuted.current = true
- }
- }, [handleReload])
-
- //Effect to set Alert according to the walletInfo
+ //Effect to hide the Divider line when there is no unFrozen-UTXOs present
useEffect(() => {
- const frozenUtxosToUpdate = frozenUtxos.filter((utxo: Utxo) => utxo.checked && !utxo.locktime)
- const timeLockedUtxo = frozenUtxos.find((utxo: Utxo) => utxo.checked && utxo.locktime)
- const allUnFrozenUnchecked = unFrozenUtxos.every((utxo: Utxo) => !utxo.checked)
-
- if (timeLockedUtxo) {
- setAlert({ variant: 'danger', message: `${t('show_utxos.alert_for_time_locked')} ${timeLockedUtxo.locktime}` })
- } else if (allUnFrozenUnchecked && frozenUtxosToUpdate.length === 0) {
- setAlert({ variant: 'warning', message: t('show_utxos.alert_for_unfreeze_utxos'), dismissible: true })
- } else if (unFrozenUtxos.length !== 0 || frozenUtxosToUpdate.length !== 0) {
- setAlert(undefined)
- }
- }, [frozenUtxos, unFrozenUtxos, t])
-
- // Handler to toggle UTXO selection
- const handleToggle = useCallback((utxoIndex: number, isFrozen: boolean) => {
- if (!isFrozen) {
- setUnFrozenUtxos((prevUtxos) =>
- prevUtxos.map((utxo, i) => (i === utxoIndex ? { ...utxo, checked: !utxo.checked } : utxo)),
- )
- } else {
- setFrozenUtxos((prevUtxos) =>
- prevUtxos.map((utxo, i) => (i === utxoIndex ? { ...utxo, checked: !utxo.checked } : utxo)),
- )
+ if (unFrozenUtxos.length === 0 && frozenUtxos.length > 0) {
+ setShowFrozenUtxos(true)
}
- }, [])
-
- // Handler for the "confirm" button click
- const handleConfirm = async () => {
- const abortCtrl = new AbortController()
-
- const frozenUtxosToUpdate = frozenUtxos
- .filter((utxo) => utxo.checked && !utxo.locktime)
- .map((utxo) => ({ utxo: utxo.utxo, freeze: false }))
- const unFrozenUtxosToUpdate = unFrozenUtxos
- .filter((utxo) => !utxo.checked)
- .map((utxo) => ({ utxo: utxo.utxo, freeze: true }))
-
- try {
- await Promise.all([
- ...frozenUtxosToUpdate.map((utxo) => Api.postFreeze({ ...wallet, signal: abortCtrl.signal }, utxo)),
- ...unFrozenUtxosToUpdate.map((utxo) => Api.postFreeze({ ...wallet, signal: abortCtrl.signal }, utxo)),
- ])
- await handleReload()
- onCancel()
- } catch (err: any) {
- if (!abortCtrl.signal.aborted) {
- setAlert({ variant: 'danger', message: err.message, dismissible: true })
- }
- }
- }
+ }, [unFrozenUtxos.length, frozenUtxos.length])
return (
{alert && (
- setAlert(undefined)}
- />
+
)}
void
}
interface ShowUtxosProps {
@@ -26,6 +25,8 @@ interface ShowUtxosProps {
isOpen: boolean
}
+export type UtxoList = Utxo[]
+
export const SourceJarSelector = ({
name,
label,
@@ -34,17 +35,20 @@ export const SourceJarSelector = ({
variant,
isLoading,
disabled = false,
- isDisplayReloadInShowUtxos,
- setIsDisplayReloadInShowUtxos,
}: SourceJarSelectorProps) => {
const { t } = useTranslation()
-
const [field] = useField(name)
const form = useFormikContext()
+ const reloadCurrentWalletInfo = useReloadCurrentWalletInfo()
+
const [showUtxos, setShowUtxos] = useState({
jarIndex: '',
isOpen: false,
})
+ const [alert, setAlert] = useState(undefined)
+ const [isUtxosLoading, setIsUtxosLoading] = useState(false)
+ const [unFrozenUtxos, setUnFrozenUtxos] = useState([])
+ const [frozenUtxos, setFrozenUtxos] = useState([])
const jarBalances = useMemo(() => {
if (!walletInfo) return []
@@ -53,6 +57,76 @@ export const SourceJarSelector = ({
)
}, [walletInfo])
+ useEffect(() => {
+ if (showUtxos.jarIndex && walletInfo?.utxosByJar) {
+ const data = Object.entries(walletInfo.utxosByJar).find(([key]) => key === showUtxos.jarIndex)
+ const utxos: any = data ? data[1] : []
+
+ const frozenUtxoList = utxos
+ .filter((utxo: any) => utxo.frozen)
+ .map((utxo: any) => ({ ...utxo, id: utxo.utxo, checked: false }))
+ const unFrozenUtxosList = utxos
+ .filter((utxo: any) => !utxo.frozen)
+ .map((utxo: any) => ({ ...utxo, id: utxo.utxo, checked: true }))
+
+ setFrozenUtxos(frozenUtxoList)
+ setUnFrozenUtxos(unFrozenUtxosList)
+ }
+ }, [walletInfo, showUtxos.jarIndex, t])
+
+ useEffect(() => {
+ if (frozenUtxos.length === 0 && unFrozenUtxos.length === 0) {
+ return
+ }
+ const frozenUtxosToUpdate = frozenUtxos.filter((utxo: Utxo) => utxo.checked && !utxo.locktime)
+ const timeLockedUtxo = frozenUtxos.find((utxo: Utxo) => utxo.checked && utxo.locktime)
+ const allUnFrozenUnchecked = unFrozenUtxos.every((utxo: Utxo) => !utxo.checked)
+
+ if (frozenUtxos.length > 0 && timeLockedUtxo) {
+ setAlert({ variant: 'danger', message: `${t('show_utxos.alert_for_time_locked')} ${timeLockedUtxo.locktime}` })
+ } else if (
+ (frozenUtxos.length > 0 || unFrozenUtxos.length > 0) &&
+ allUnFrozenUnchecked &&
+ frozenUtxosToUpdate.length === 0
+ ) {
+ setAlert({ variant: 'warning', message: t('show_utxos.alert_for_unfreeze_utxos'), dismissible: true })
+ } else {
+ setAlert(undefined)
+ }
+ }, [frozenUtxos, unFrozenUtxos, t, setAlert])
+
+ const handleUtxosFrozenState = useCallback(async () => {
+ const abortCtrl = new AbortController()
+ const frozenUtxosToUpdate = frozenUtxos
+ .filter((utxo) => utxo.checked && !utxo.locktime)
+ .map((utxo) => ({ utxo: utxo.utxo, freeze: false }))
+ const unFrozenUtxosToUpdate = unFrozenUtxos
+ .filter((utxo) => !utxo.checked)
+ .map((utxo) => ({ utxo: utxo.utxo, freeze: true }))
+
+ try {
+ const res = await Promise.all([
+ ...frozenUtxosToUpdate.map((utxo) => Api.postFreeze({ ...wallet, signal: abortCtrl.signal }, utxo)),
+ ...unFrozenUtxosToUpdate.map((utxo) => Api.postFreeze({ ...wallet, signal: abortCtrl.signal }, utxo)),
+ ])
+
+ if (res.length !== 0) {
+ setIsUtxosLoading(true)
+ await reloadCurrentWalletInfo.reloadUtxos({ signal: abortCtrl.signal })
+ setIsUtxosLoading(false)
+ }
+
+ setShowUtxos({
+ jarIndex: '',
+ isOpen: false,
+ })
+ } catch (err: any) {
+ if (!abortCtrl.signal.aborted) {
+ setAlert({ variant: 'danger', message: err.message, dismissible: true })
+ }
+ }
+ }, [frozenUtxos, unFrozenUtxos, wallet, reloadCurrentWalletInfo])
+
return (
<>
@@ -65,18 +139,20 @@ export const SourceJarSelector = ({
{showUtxos.isOpen && (
{
setShowUtxos({
jarIndex: '',
isOpen: false,
})
}}
- jarIndex={showUtxos.jarIndex}
- isDisplayReloadInShowUtxos={isDisplayReloadInShowUtxos}
- setIsDisplayReloadInShowUtxos={setIsDisplayReloadInShowUtxos}
+ alert={alert}
+ isLoading={isUtxosLoading}
+ frozenUtxos={frozenUtxos}
+ unFrozenUtxos={unFrozenUtxos}
+ setFrozenUtxos={setFrozenUtxos}
+ setUnFrozenUtxos={setUnFrozenUtxos}
/>
)}
{jarBalances.map((it) => {
diff --git a/src/components/Send/index.tsx b/src/components/Send/index.tsx
index 52850be6..fefbdc5b 100644
--- a/src/components/Send/index.tsx
+++ b/src/components/Send/index.tsx
@@ -91,8 +91,6 @@ export default function Send({ wallet }: SendProps) {
const reloadServiceInfo = useReloadServiceInfo()
const loadConfigValue = useLoadConfigValue()
- const [isDisplayReloadInShowUtxos, setIsDisplayReloadInShowUtxos] = useState(true)
-
const isCoinjoinInProgress = useMemo(() => serviceInfo?.coinjoinInProgress === true, [serviceInfo])
const isMakerRunning = useMemo(() => serviceInfo?.makerRunning === true, [serviceInfo])
const isRescanningInProgress = useMemo(() => serviceInfo?.rescanning === true, [serviceInfo])
@@ -204,7 +202,7 @@ export default function Send({ wallet }: SendProps) {
})
const loadingWalletInfoAndUtxos = reloadCurrentWalletInfo
- .reloadUtxos({ signal: abortCtrl.signal })
+ .reloadDisplay({ signal: abortCtrl.signal })
.catch((err) => {
if (abortCtrl.signal.aborted) return
const message = t('global.errors.error_loading_wallet_failed', {
@@ -268,7 +266,6 @@ export default function Send({ wallet }: SendProps) {
txid,
}),
})
- setIsDisplayReloadInShowUtxos(true)
setWaitForUtxosToBeSpent(inputs.map((it: any) => it.outpoint))
success = true
} else {
@@ -493,8 +490,6 @@ export default function Send({ wallet }: SendProps) {
loadNewWalletAddress={loadNewWalletAddress}
feeConfigValues={feeConfigValues}
reloadFeeConfigValues={reloadFeeConfigValues}
- isDisplayReloadInShowUtxos={isDisplayReloadInShowUtxos}
- setIsDisplayReloadInShowUtxos={setIsDisplayReloadInShowUtxos}
/>
{showConfirmAbortModal && (