diff --git a/frontend/mobile-app/lib/core/services/wallet_service.dart b/frontend/mobile-app/lib/core/services/wallet_service.dart index 8eed7c7e..ba174147 100644 --- a/frontend/mobile-app/lib/core/services/wallet_service.dart +++ b/frontend/mobile-app/lib/core/services/wallet_service.dart @@ -181,6 +181,36 @@ class FeeConfig { } } + /// 计算给定余额下的最大可转金额 + /// 因为手续费由发送方承担,所以 总花费 = 转账金额 + 手续费 + /// 返回能够使 转账金额 + 手续费 <= balance 的最大转账金额 + double calculateMaxAmount(double balance) { + if (balance <= 0) return 0; + + if (feeType == FeeType.fixed) { + // 固定费率: maxAmount = balance - fixedFee + final maxAmount = balance - feeValue; + return maxAmount > 0 ? maxAmount : 0; + } else { + // 百分比费率: 总花费 = amount * (1 + rate) + // 所以 maxAmount = balance / (1 + rate) + final maxAmount = balance / (1 + feeValue); + + // 检查最小/最大手续费限制 + final fee = calculateFee(maxAmount); + final actualTotal = maxAmount + fee; + + // 如果由于 minFee 导致超出余额,需要重新计算 + if (actualTotal > balance && minFee > 0) { + // 使用 minFee 计算: maxAmount = balance - minFee + final adjustedMax = balance - minFee; + return adjustedMax > 0 ? adjustedMax : 0; + } + + return maxAmount > 0 ? maxAmount : 0; + } + } + /// 获取费率描述 String get description { if (feeType == FeeType.fixed) { diff --git a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart index ba080c4b..7e32d49a 100644 --- a/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart +++ b/frontend/mobile-app/lib/features/withdraw/presentation/pages/withdraw_usdt_page.dart @@ -167,9 +167,18 @@ class _WithdrawUsdtPageState extends ConsumerState { }); } - /// 设置全部金额 + /// 设置全部金额(扣除手续费后的最大可转金额) void _setMaxAmount() { - _amountController.text = _usdtBalance.toStringAsFixed(2); + double maxAmount; + if (_feeConfig != null) { + maxAmount = _feeConfig!.calculateMaxAmount(_usdtBalance); + } else { + // 默认固定 2 绿积分手续费 + maxAmount = _usdtBalance - 2; + } + // 确保金额不为负 + if (maxAmount < 0) maxAmount = 0; + _amountController.text = maxAmount.toStringAsFixed(2); setState(() {}); }