Skip to content

Commit ebff98e

Browse files
committed
refactor: Move transfer limits calculation to viewModel
1 parent aa79ac1 commit ebff98e

File tree

5 files changed

+174
-128
lines changed

5 files changed

+174
-128
lines changed

app/src/main/java/to/bitkit/services/CurrencyService.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import kotlin.math.pow
1919
class CurrencyService @Inject constructor(
2020
private val blocktankHttpClient: BlocktankHttpClient,
2121
) {
22+
private var cachedRates: List<FxRate>? = null
23+
2224
private val maxRetries = 3
2325

2426
suspend fun fetchLatestRates(): List<FxRate> {
@@ -27,7 +29,12 @@ class CurrencyService @Inject constructor(
2729
for (attempt in 0 until maxRetries) {
2830
try {
2931
val response = ServiceQueue.FOREX.background { blocktankHttpClient.fetchLatestRates() }
30-
return response.tickers
32+
val rates = response.tickers
33+
34+
// TODO Cache to disk
35+
cachedRates = rates
36+
37+
return rates
3138
} catch (e: Exception) {
3239
lastError = e
3340
if (attempt < maxRetries - 1) {
@@ -41,6 +48,11 @@ class CurrencyService @Inject constructor(
4148
throw lastError ?: CurrencyError.Unknown
4249
}
4350

51+
fun loadCachedRates(): List<FxRate>? {
52+
// TODO load from disk
53+
return cachedRates
54+
}
55+
4456
fun convert(sats: Long, rate: FxRate): ConvertedAmount? {
4557
val btcAmount = BigDecimal(sats).divide(BigDecimal(100_000_000))
4658
val value: BigDecimal = btcAmount.multiply(BigDecimal.valueOf(rate.rate))

app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAdvancedScreen.kt

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import androidx.compose.material3.Icon
1818
import androidx.compose.material3.IconButton
1919
import androidx.compose.runtime.Composable
2020
import androidx.compose.runtime.LaunchedEffect
21+
import androidx.compose.runtime.collectAsState
2122
import androidx.compose.runtime.getValue
2223
import androidx.compose.runtime.mutableLongStateOf
2324
import androidx.compose.runtime.mutableStateOf
@@ -44,7 +45,6 @@ import to.bitkit.ui.components.TransferAmount
4445
import to.bitkit.ui.scaffold.AppTopBar
4546
import to.bitkit.ui.scaffold.ScreenColumn
4647
import to.bitkit.ui.theme.Colors
47-
import to.bitkit.ui.utils.useTransfer
4848
import to.bitkit.ui.utils.withAccent
4949
import to.bitkit.viewmodels.TransferViewModel
5050

@@ -81,28 +81,33 @@ fun SpendingAdvancedScreen(
8181
.fillMaxSize()
8282
.imePadding()
8383
) {
84-
var lspBalance by rememberSaveable { mutableLongStateOf(0) }
84+
var receivingSatsAmount by rememberSaveable { mutableLongStateOf(0) }
8585
var overrideSats: Long? by remember { mutableStateOf(null) }
8686

8787
val clientBalance = order.clientBalanceSat
8888
var feeEstimate: Long? by remember { mutableStateOf(null) }
8989
var isLoading by remember { mutableStateOf(false) }
9090

91-
val transferValues = useTransfer(clientBalance.toLong())
91+
val transferValues by viewModel.transferValues.collectAsState()
9292

93-
val isValid = lspBalance >= transferValues.minLspBalance &&
94-
lspBalance <= transferValues.maxLspBalance
93+
LaunchedEffect(order.clientBalanceSat) {
94+
viewModel.updateTransferValues(clientBalance, blocktank.info)
95+
}
96+
97+
val isValid = transferValues.let {
98+
val isAboveMin = receivingSatsAmount.toULong() >= it.minLspBalance
99+
val isBelowMax = receivingSatsAmount.toULong() <= it.maxLspBalance
100+
isAboveMin && isBelowMax
101+
}
95102

96-
// Update LSP Fee estimate
97-
LaunchedEffect(lspBalance) {
103+
// Update feeEstimate
104+
LaunchedEffect(receivingSatsAmount) {
98105
feeEstimate = null
99-
if (lspBalance < transferValues.minLspBalance) {
100-
return@LaunchedEffect
101-
}
106+
if (receivingSatsAmount.toULong() < transferValues.minLspBalance) return@LaunchedEffect
102107
runCatching {
103108
val estimate = blocktank.estimateOrderFee(
104109
spendingBalanceSats = clientBalance,
105-
receivingBalanceSats = lspBalance.toULong(),
110+
receivingBalanceSats = receivingSatsAmount.toULong(),
106111
)
107112
feeEstimate = estimate.feeSat.toLong()
108113
}
@@ -119,7 +124,7 @@ fun SpendingAdvancedScreen(
119124
primaryDisplay = currencies.primaryDisplay,
120125
overrideSats = overrideSats,
121126
onSatsChange = { sats ->
122-
lspBalance = sats
127+
receivingSatsAmount = sats
123128
overrideSats = null
124129
},
125130
)
@@ -156,23 +161,23 @@ fun SpendingAdvancedScreen(
156161
text = stringResource(R.string.common__min),
157162
color = Colors.Purple,
158163
onClick = {
159-
overrideSats = transferValues.minLspBalance
164+
overrideSats = transferValues.minLspBalance.toLong()
160165
},
161166
)
162167
// Default Button
163168
NumberPadActionButton(
164169
text = stringResource(R.string.common__default),
165170
color = Colors.Purple,
166171
onClick = {
167-
overrideSats = transferValues.defaultLspBalance
172+
overrideSats = transferValues.defaultLspBalance.toLong()
168173
},
169174
)
170175
// Max Button
171176
NumberPadActionButton(
172177
text = stringResource(R.string.common__max),
173178
color = Colors.Purple,
174179
onClick = {
175-
overrideSats = transferValues.maxLspBalance
180+
overrideSats = transferValues.maxLspBalance.toLong()
176181
},
177182
)
178183
}
@@ -187,7 +192,7 @@ fun SpendingAdvancedScreen(
187192
try {
188193
val newOrder = blocktank.createOrder(
189194
spendingBalanceSats = clientBalance,
190-
receivingBalanceSats = lspBalance.toULong(),
195+
receivingBalanceSats = receivingSatsAmount.toULong(),
191196
)
192197
viewModel.onAdvancedOrderCreated(newOrder)
193198
onOrderCreated()

app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ import to.bitkit.ui.components.UnitButton
4444
import to.bitkit.ui.scaffold.AppTopBar
4545
import to.bitkit.ui.scaffold.ScreenColumn
4646
import to.bitkit.ui.theme.Colors
47-
import to.bitkit.ui.utils.useTransfer
4847
import to.bitkit.ui.utils.withAccent
48+
import to.bitkit.utils.Logger
4949
import to.bitkit.viewmodels.TransferViewModel
5050
import kotlin.math.max
5151
import kotlin.math.min
@@ -83,27 +83,39 @@ fun SpendingAmountScreen(
8383
.fillMaxSize()
8484
.imePadding()
8585
) {
86-
var spendingBalanceSats by rememberSaveable { mutableLongStateOf(0) }
86+
var satsAmount by rememberSaveable { mutableLongStateOf(0) }
8787
var overrideSats: Long? by remember { mutableStateOf(null) }
8888
var isLoading by remember { mutableStateOf(false) }
8989

90-
val balances = LocalBalances.current
90+
val availableAmount = LocalBalances.current.totalOnchainSats - 512u // default tx fee
9191

92-
val availableAmount = balances.totalOnchainSats - 512u // default tx fee
92+
var maxClientBalance by remember { mutableStateOf(0uL) }
93+
var maxLspBalance by remember { mutableStateOf(0uL) }
94+
var maxLspFee by remember { mutableStateOf(0uL) }
9395

94-
val maxClientBalance = useTransfer(spendingBalanceSats).maxClientBalance
95-
val maxLspBalance = useTransfer(availableAmount.toLong()).defaultLspBalance
96+
val feeMaximum = max(0, availableAmount.toLong() - maxLspFee.toLong())
97+
val maximum = min(maxClientBalance.toLong(), feeMaximum)
9698

97-
var maxLspFee by remember { mutableStateOf(0uL) }
99+
// Update maxClientBalance Effect
100+
LaunchedEffect(satsAmount) {
101+
val transferValues = viewModel.calculateTransferValues(satsAmount.toULong(), blocktank.info)
102+
maxClientBalance = transferValues.maxClientBalance
103+
Logger.debug("maxClientBalance: $maxClientBalance", context = "SpendingAmountScreen")
104+
}
98105

99-
val feeMaximum = max(0, (availableAmount - maxLspFee).toLong())
100-
val maximum = min(maxClientBalance, feeMaximum)
106+
// Update maxLspBalance Effect
107+
LaunchedEffect(availableAmount) {
108+
val transferValues = viewModel.calculateTransferValues(availableAmount, blocktank.info)
109+
maxLspBalance = transferValues.defaultLspBalance
110+
Logger.debug("maxLspBalance: $maxLspBalance", context = "SpendingAmountScreen")
111+
}
101112

113+
// Update maxLspFee Effect
102114
LaunchedEffect(availableAmount, maxLspBalance) {
103115
runCatching {
104116
val estimate = blocktank.estimateOrderFee(
105117
spendingBalanceSats = availableAmount,
106-
receivingBalanceSats = maxLspBalance.toULong(),
118+
receivingBalanceSats = maxLspBalance,
107119
)
108120
maxLspFee = estimate.feeSat
109121
}
@@ -117,7 +129,7 @@ fun SpendingAmountScreen(
117129
primaryDisplay = currencies.primaryDisplay,
118130
overrideSats = overrideSats,
119131
onSatsChange = { sats ->
120-
spendingBalanceSats = sats
132+
satsAmount = sats
121133
overrideSats = null
122134
},
123135
)
@@ -165,7 +177,7 @@ fun SpendingAmountScreen(
165177
PrimaryButton(
166178
text = stringResource(R.string.common__continue),
167179
onClick = {
168-
if (maxLspBalance == 0L) {
180+
if (maxLspBalance == 0uL) {
169181
app.toast(
170182
type = Toast.ToastType.ERROR,
171183
title = resources.getString(R.string.lightning__spending_amount__error_max__title),
@@ -177,7 +189,7 @@ fun SpendingAmountScreen(
177189
isLoading = true
178190
scope.launch {
179191
try {
180-
val order = blocktank.createOrder(spendingBalanceSats.toULong())
192+
val order = blocktank.createOrder(satsAmount.toULong())
181193
viewModel.onOrderCreated(order)
182194
onOrderCreated()
183195
} catch (e: Throwable) {
@@ -187,7 +199,7 @@ fun SpendingAmountScreen(
187199
}
188200
}
189201
},
190-
enabled = !isLoading && spendingBalanceSats != 0L,
202+
enabled = !isLoading && satsAmount != 0L,
191203
isLoading = isLoading,
192204
)
193205

app/src/main/java/to/bitkit/ui/utils/Transfer.kt

Lines changed: 0 additions & 87 deletions
This file was deleted.

0 commit comments

Comments
 (0)