Skip to content

Commit d3ce231

Browse files
authored
Merge pull request #327 from synonymdev/fix/fee-over-10-usd-warning
fix: Fee above 10 USD sanity check and don't skip checks
2 parents 5b466e2 + 3bd315e commit d3ce231

File tree

2 files changed

+45
-27
lines changed

2 files changed

+45
-27
lines changed

app/src/main/java/to/bitkit/ui/screens/wallets/send/SendConfirmScreen.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ import to.bitkit.ui.theme.AppThemeSurface
7474
import to.bitkit.ui.theme.Colors
7575
import to.bitkit.ui.utils.rememberBiometricAuthSupported
7676
import to.bitkit.ui.utils.withAccent
77-
import to.bitkit.viewmodels.AmountWarning
77+
import to.bitkit.viewmodels.SanityWarning
7878
import to.bitkit.viewmodels.LnurlParams
7979
import to.bitkit.viewmodels.SendEvent
8080
import to.bitkit.viewmodels.SendMethod
@@ -238,13 +238,13 @@ private fun Content(
238238
)
239239
}
240240

241-
uiState.showAmountWarningDialog?.let { dialog ->
241+
uiState.showSanityWarningDialog?.let { dialog ->
242242
AppAlertDialog(
243243
title = stringResource(R.string.common__are_you_sure),
244244
text = stringResource(dialog.message),
245245
confirmText = stringResource(R.string.wallet__send_yes),
246246
dismissText = stringResource(R.string.common__cancel),
247-
onConfirm = { onEvent(SendEvent.ConfirmAmountWarning) },
247+
onConfirm = { onEvent(SendEvent.ConfirmAmountWarning(dialog)) },
248248
onDismiss = {
249249
onEvent(SendEvent.DismissAmountWarning)
250250
onBack()
@@ -660,7 +660,7 @@ private fun PreviewDialog() {
660660
BottomSheetPreview {
661661
Content(
662662
uiState = sendUiState().copy(
663-
showAmountWarningDialog = AmountWarning.VALUE_OVER_100_USD,
663+
showSanityWarningDialog = SanityWarning.VALUE_OVER_100_USD,
664664
),
665665
isLoading = false,
666666
showBiometrics = true,

app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ class AppViewModel @Inject constructor(
303303

304304
SendEvent.SpeedAndFee -> setSendEffect(SendEffect.NavigateToFee)
305305
SendEvent.SwipeToPay -> onSwipeToPay()
306-
SendEvent.ConfirmAmountWarning -> onConfirmAmountWarning()
306+
is SendEvent.ConfirmAmountWarning -> onConfirmAmountWarning(it.warning)
307307
SendEvent.DismissAmountWarning -> onDismissAmountWarning()
308308
SendEvent.PayConfirmed -> onConfirmPay()
309309
SendEvent.BackToAmount -> setSendEffect(SendEffect.PopBack(SendRoute.Amount))
@@ -828,29 +828,36 @@ class AppViewModel @Inject constructor(
828828
val amount = _sendUiState.value.amount
829829

830830
handleSanityChecks(amount)
831-
if (_sendUiState.value.showAmountWarningDialog != null) return@launch // await for dialog UI interaction
831+
if (_sendUiState.value.showSanityWarningDialog != null) return@launch // await for dialog UI interaction
832832

833833
_sendUiState.update { it.copy(shouldConfirmPay = true) }
834834
}
835835
}
836836

837837
private suspend fun handleSanityChecks(amountSats: ULong) {
838-
if (_sendUiState.value.showAmountWarningDialog != null) return
838+
if (_sendUiState.value.showSanityWarningDialog != null) return
839839

840840
val settings = settingsStore.data.first()
841-
val amountInUsd = currencyRepo.convertSatsToFiat(amountSats.toLong(), "USD").getOrNull() ?: return
842-
if (amountInUsd.value > BigDecimal(SEND_AMOUNT_WARNING_THRESHOLD) && settings.enableSendAmountWarning) {
841+
842+
if (
843+
amountSats > BigDecimal.valueOf(walletRepo.balanceState.value.totalSats.toLong())
844+
.times(BigDecimal(MAX_BALANCE_FRACTION)).toLong().toUInt() &&
845+
SanityWarning.OVER_HALF_BALANCE !in _sendUiState.value.confirmedWarnings
846+
) {
843847
_sendUiState.update {
844-
it.copy(showAmountWarningDialog = AmountWarning.VALUE_OVER_100_USD)
848+
it.copy(showSanityWarningDialog = SanityWarning.OVER_HALF_BALANCE)
845849
}
846850
return
847851
}
848852

849-
if (amountSats > BigDecimal.valueOf(walletRepo.balanceState.value.totalSats.toLong())
850-
.times(BigDecimal(0.5)).toLong().toUInt()
853+
val amountInUsd = currencyRepo.convertSatsToFiat(amountSats.toLong(), "USD").getOrNull() ?: return
854+
if (
855+
amountInUsd.value > BigDecimal(SEND_AMOUNT_WARNING_THRESHOLD) &&
856+
settings.enableSendAmountWarning &&
857+
SanityWarning.VALUE_OVER_100_USD !in _sendUiState.value.confirmedWarnings
851858
) {
852859
_sendUiState.update {
853-
it.copy(showAmountWarningDialog = AmountWarning.OVER_HALF_BALANCE)
860+
it.copy(showSanityWarningDialog = SanityWarning.VALUE_OVER_100_USD)
854861
}
855862
return
856863
}
@@ -864,25 +871,31 @@ class AppViewModel @Inject constructor(
864871
utxosToSpend = _sendUiState.value.selectedUtxos,
865872
).getOrNull() ?: return
866873

867-
if (totalFee > BigDecimal.valueOf(amountSats.toLong())
868-
.times(BigDecimal(0.5)).toLong().toUInt()
874+
if (
875+
totalFee > BigDecimal.valueOf(
876+
amountSats.toLong()
877+
).times(BigDecimal(MAX_FEE_AMOUNT_RATIO)).toLong().toUInt() &&
878+
SanityWarning.FEE_OVER_HALF_VALUE !in _sendUiState.value.confirmedWarnings
869879
) {
870880
_sendUiState.update {
871-
it.copy(showAmountWarningDialog = AmountWarning.FEE_OVER_HALF_VALUE)
881+
it.copy(showSanityWarningDialog = SanityWarning.FEE_OVER_HALF_VALUE)
872882
}
873883
return
874884
}
875885

876-
val feeInUsd = currencyRepo.convertSatsToFiat(amountSats.toLong(), "USD").getOrNull() ?: return
877-
if (feeInUsd.value > BigDecimal(10)) {
886+
val feeInUsd = currencyRepo.convertSatsToFiat(totalFee.toLong(), "USD").getOrNull() ?: return
887+
if (
888+
feeInUsd.value > BigDecimal(TEN_USD) &&
889+
SanityWarning.FEE_OVER_10_USD !in _sendUiState.value.confirmedWarnings
890+
) {
878891
_sendUiState.update {
879-
it.copy(showAmountWarningDialog = AmountWarning.FEE_OVER_10_USD)
892+
it.copy(showSanityWarningDialog = SanityWarning.FEE_OVER_10_USD)
880893
}
881894
return
882895
}
883896

884897
_sendUiState.update {
885-
it.copy(showAmountWarningDialog = null)
898+
it.copy(showSanityWarningDialog = null)
886899
}
887900
}
888901

@@ -1364,20 +1377,21 @@ class AppViewModel @Inject constructor(
13641377
}
13651378
}
13661379

1367-
private fun onConfirmAmountWarning() {
1380+
private fun onConfirmAmountWarning(warning: SanityWarning) {
13681381
viewModelScope.launch {
13691382
_sendUiState.update {
13701383
it.copy(
1371-
showAmountWarningDialog = null,
1372-
shouldConfirmPay = true,
1384+
showSanityWarningDialog = null,
1385+
confirmedWarnings = it.confirmedWarnings + warning
13731386
)
13741387
}
13751388
}
1389+
onSwipeToPay()
13761390
}
13771391

13781392
private fun onDismissAmountWarning() {
13791393
_sendUiState.update {
1380-
it.copy(showAmountWarningDialog = null)
1394+
it.copy(showSanityWarningDialog = null)
13811395
}
13821396
}
13831397

@@ -1392,6 +1406,9 @@ class AppViewModel @Inject constructor(
13921406
companion object {
13931407
private const val TAG = "AppViewModel"
13941408
private const val SEND_AMOUNT_WARNING_THRESHOLD = 100.0
1409+
private const val TEN_USD = 10
1410+
private const val MAX_BALANCE_FRACTION = 0.5
1411+
private const val MAX_FEE_AMOUNT_RATIO = 0.5
13951412
}
13961413
}
13971414

@@ -1408,7 +1425,8 @@ data class SendUiState(
14081425
val payMethod: SendMethod = SendMethod.ONCHAIN,
14091426
val selectedTags: List<String> = listOf(),
14101427
val decodedInvoice: LightningInvoice? = null,
1411-
val showAmountWarningDialog: AmountWarning? = null,
1428+
val showSanityWarningDialog: SanityWarning? = null,
1429+
val confirmedWarnings: List<SanityWarning> = listOf(),
14121430
val shouldConfirmPay: Boolean = false,
14131431
val selectedUtxos: List<SpendableUtxo>? = null,
14141432
val lnurl: LnurlParams? = null,
@@ -1420,7 +1438,7 @@ data class SendUiState(
14201438
val fees: Map<FeeRate, Long> = emptyMap(),
14211439
)
14221440

1423-
enum class AmountWarning(@StringRes val message: Int, val testTag: String) {
1441+
enum class SanityWarning(@StringRes val message: Int, val testTag: String) {
14241442
VALUE_OVER_100_USD(R.string.wallet__send_dialog1, "SendDialog1"),
14251443
OVER_HALF_BALANCE(R.string.wallet__send_dialog2, "SendDialog2"),
14261444
FEE_OVER_HALF_VALUE(R.string.wallet__send_dialog3, "SendDialog3"),
@@ -1471,7 +1489,7 @@ sealed interface SendEvent {
14711489
data object SwipeToPay : SendEvent
14721490
data object SpeedAndFee : SendEvent
14731491
data object PaymentMethodSwitch : SendEvent
1474-
data object ConfirmAmountWarning : SendEvent
1492+
data class ConfirmAmountWarning(val warning: SanityWarning) : SendEvent
14751493
data object DismissAmountWarning : SendEvent
14761494
data object PayConfirmed : SendEvent
14771495
data object BackToAmount : SendEvent

0 commit comments

Comments
 (0)