diff --git a/src/components/Jam.jsx b/src/components/Jam.jsx index 5cd7b9186..1f815e957 100644 --- a/src/components/Jam.jsx +++ b/src/components/Jam.jsx @@ -350,25 +350,34 @@ export default function Jam() { const isValidAddress = (candidate) => { return typeof candidate !== 'undefined' && candidate !== '' } + const isAddressReused = (destination, inputAddresses) => { + if (!destination) return false - if (!isValidAddress(values.dest1)) { - errors.dest1 = t('scheduler.error_invalid_destionation_address') - } - if (!isValidAddress(values.dest2)) { - errors.dest2 = t('scheduler.error_invalid_destionation_address') - } - if (!isValidAddress(values.dest3)) { - errors.dest3 = t('scheduler.error_invalid_destionation_address') + const knownAddress = walletInfo?.addressSummary[destination] || false + const alreadyUsed = knownAddress && walletInfo?.addressSummary[destination]?.status !== 'new' + const duplicateEntry = inputAddresses.filter((it) => it === destination).length > 1 + + return alreadyUsed || duplicateEntry } - const validAddresses = Array(3) + const addressDict = Array(3) .fill('') - .map((_, index) => values[`dest${index + 1}`]) - .filter((it) => isValidAddress(it)) - const uniqueValidAddresses = [...new Set(validAddresses)] - if (validAddresses.length !== uniqueValidAddresses.length) { - errors.addressReuse = t('scheduler.error_address_reuse') - } + .map((_, index) => { + const key = `dest${index + 1}` + return { + key, + address: values[key], + } + }) + const addresses = addressDict.map((it) => it.address) + + addressDict.forEach((addressEntry) => { + if (!isValidAddress(addressEntry.address)) { + errors[addressEntry.key] = t('scheduler.feedback_invalid_destination_address') + } else if (isAddressReused(addressEntry.address, addresses)) { + errors[addressEntry.key] = t('scheduler.feedback_reused_destination_address') + } + }) return errors }} @@ -457,10 +466,10 @@ export default function Jam() { isInvalid={touched[`dest${i}`] && !!errors[`dest${i}`]} className={`${styles.input} slashed-zeroes`} /> + {errors[`dest${i}`]} ) })} - {errors && errors.addressReuse && {errors.addressReuse}} {!collaborativeOperationRunning && (

{t('scheduler.description_fees')}

)} diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index 3ee7bef49..02cee55a3 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -389,7 +389,8 @@ "complete_wallet_title": "Complete Wallet", "complete_wallet_subtitle": "This will use all of your non-frozen funds.", "description_destination_addresses": "You can choose to send your funds to an external wallet after completion automatically. However, this feature requires you to provide multiple destination addresses to preserve your privacy.", - "error_invalid_destionation_address": "Please enter valid a destination address.", + "feedback_invalid_destination_address": "Please enter valid a destination address.", + "feedback_reused_destination_address": "This address is already used. To preserve your privacy please choose another one.", "toggle_internal_destination_title": "Send to external wallet", "toggle_internal_destination_subtitle": "Specify destination addresses to send funds to an external wallet.", "label_destination_input": "Destination {{ destination }}", @@ -403,7 +404,6 @@ "progress_current_state": "Waiting for transaction <1>{{ current }} of <3>{{ total }} to process...", "progress_done": "All transactions completed successfully. The scheduler will stop soon.", "error_loading_schedule_failed": "Loading schedule progress failed.", - "error_address_reuse": "Reusing addresses is prohibited. Make sure to use unique and unused addresses.", "precondition": { "hint_missing_utxos": "To run the scheduler you need at least one UTXO with <2>{{ minConfirmations }} confirmations in Jar #0. Fund your wallet and wait for <6>{{ minConfirmations }} blocks.", "hint_missing_confirmations": "The scheduler requires one of your UTXOs in Jar #0 to have <2>{{ minConfirmations }} or more confirmations. Wait for <6>{{ amountOfMissingConfirmations }} more block(s).",