diff --git a/CHANGELOG.md b/CHANGELOG.md index 68120eca1f7..88fc4cb718f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased (develop) +- fixed: Hide the send scene's MAX button once a send has more than one recipient, and hide "Add another address" once MAX has been applied, so the two can no longer combine into an insufficient-funds transaction. + ## 4.51.0 (staging) - added: Push info-server attestation tokens into edge-core-js via `setAttestationToken` so the login server can skip CAPTCHA for attested devices, and allow `LOGIN_SERVER` / `INFO_SERVER` env overrides for local E2E stacks. diff --git a/src/components/scenes/SendScene2.tsx b/src/components/scenes/SendScene2.tsx index 050a7e8ddf2..1232d6bed4d 100644 --- a/src/components/scenes/SendScene2.tsx +++ b/src/components/scenes/SendScene2.tsx @@ -620,6 +620,11 @@ const SendComponent: React.FC = props => { const handleFlipInputModal = (index: number, spendTarget: EdgeSpendTarget) => (): void => { const { noChangeMiningFee } = getSpecialCurrencyInfo(pluginId) + // A max spend only has a defined meaning for a single recipient: it + // consumes the entire spendable balance. Once the send has more than one + // target there is nothing left over for the others, so the button is + // hidden rather than allowed to produce an insufficient-funds spend. + const isMultipleTargets = spendInfo.spendTargets.length > 1 Airship.show(bridge => ( = props => { startNativeAmount={spendTarget.nativeAmount} feeTokenId={null} forceField={fieldChanged} + hideMaxButton={isMultipleTargets} onAmountsChanged={handleAmountsChanged(spendTarget)} onMaxSet={() => { setMaxSpendSetter(index) @@ -753,7 +759,11 @@ const SendComponent: React.FC = props => { hiddenFeaturesMap.address === true || hiddenFeaturesMap.amount === true || lockTilesMap.address === true || - lockTilesMap.amount === true + lockTilesMap.amount === true || + // The existing target already claims the whole spendable balance, so a + // second recipient could only ever be funded by shrinking it. Withhold + // the entry point instead of silently discarding the max amount. + maxSpendSetter >= 0 ) { return null }