diff --git a/src/components/Earn.jsx b/src/components/Earn.jsx index fd1cc926..ffe0fa58 100644 --- a/src/components/Earn.jsx +++ b/src/components/Earn.jsx @@ -189,7 +189,9 @@ export default function Earn({ currentWallet, coinjoinInProcess, makerRunning }) }) // show the loader a little longer to avoid flickering .then((_) => new Promise((r) => setTimeout(r, 200))) - .finally(() => setIsReportLoading(false)) + .finally(() => { + !abortCtrl.signal.aborted && setIsReportLoading(false) + }) return () => abortCtrl.abort() }, [makerRunning, isShowReport]) diff --git a/src/components/Send.jsx b/src/components/Send.jsx index eba4d3e6..bf0802f1 100644 --- a/src/components/Send.jsx +++ b/src/components/Send.jsx @@ -113,6 +113,30 @@ const CollaboratorsSelector = ({ numCollaborators, setNumCollaborators, minNumCo ) } +const enhanceTakerErrorMessageIfNecessary = async (requestContext, httpStatus, errorMessage) => { + const configExists = (section, field) => Api.postConfigGet(requestContext, { section, field }).then((res) => res.ok) + + const tryEnhanceMessage = httpStatus === 409 + if (tryEnhanceMessage) { + const maxFeeSettingsPresent = await Promise.all([ + configExists('POLICY', 'max_cj_fee_rel'), + configExists('POLICY', 'max_cj_fee_abs'), + ]) + .then((arr) => arr.every((e) => e)) + .catch(() => false) + + if (!maxFeeSettingsPresent) { + const maxFeeSettingsMissingMessage = ` + Config variables 'max_cj_fee_rel' and 'max_cj_fee_abs' must be set in your joinmarket.cfg in order to send collaborative transactions. + Consider adding them to your config manually. + ` + return `${errorMessage} ${maxFeeSettingsMissingMessage}` + } + } + + return errorMessage +} + export default function Send({ makerRunning, coinjoinInProcess }) { const wallet = useCurrentWallet() const walletInfo = useCurrentWalletInfo() @@ -182,7 +206,9 @@ export default function Send({ makerRunning, coinjoinInProcess }) { }) const loadingMinimumMakerConfig = Api.postConfigGet(requestContext, { section: 'POLICY', field: 'minimum_makers' }) - .then((res) => (res.ok ? res.json() : Promise.reject(new Error(res.message || 'Loading config value failed.')))) + .then((res) => + res.ok ? res.json() : Promise.reject(new Error(res.message || 'Loading config value "minimum_makers" failed.')) + ) .then((data) => { const minimumMakers = parseInt(data.configvalue, 10) setMinNumCollaborators(minimumMakers) @@ -195,7 +221,7 @@ export default function Send({ makerRunning, coinjoinInProcess }) { Promise.all([loadingWalletInfo, loadingMinimumMakerConfig]).finally(() => setIsLoading(false)) return () => abortCtrl.abort() - }, [wallet, setWalletInfo, walletInfo]) + }, [wallet, walletInfo, setWalletInfo]) const sendPayment = async (account, destination, amount_sats) => { const { name: walletName, token } = wallet @@ -229,13 +255,13 @@ export default function Send({ makerRunning, coinjoinInProcess }) { } const startCoinjoin = async (account, destination, amount_sats, counterparties) => { - const { name: walletName, token } = wallet + const requestContext = { walletName: wallet.name, token: wallet.token } setAlert(null) setIsSending(true) let success = false try { - const res = await Api.postCoinjoin({ walletName, token }, { account, destination, amount_sats, counterparties }) + const res = await Api.postCoinjoin(requestContext, { account, destination, amount_sats, counterparties }) if (res.ok) { const data = await res.json() console.log(data) @@ -243,7 +269,9 @@ export default function Send({ makerRunning, coinjoinInProcess }) { success = true } else { const { message } = await res.json() - setAlert({ variant: 'danger', message }) + const displayMessage = await enhanceTakerErrorMessageIfNecessary(requestContext, res.status, message) + + setAlert({ variant: 'danger', message: displayMessage }) } } catch (e) { setAlert({ variant: 'danger', message: e.message })