@@ -4,7 +4,6 @@ import android.content.Context
44import androidx.lifecycle.ViewModel
55import androidx.lifecycle.viewModelScope
66import com.synonym.bitkitcore.BtOrderState2
7- import com.synonym.bitkitcore.IBtInfo
87import com.synonym.bitkitcore.IBtOrder
98import dagger.hilt.android.lifecycle.HiltViewModel
109import dagger.hilt.android.qualifiers.ApplicationContext
@@ -32,20 +31,16 @@ import to.bitkit.data.CacheStore
3231import to.bitkit.data.SettingsStore
3332import to.bitkit.env.Env
3433import to.bitkit.ext.amountOnClose
35- import to.bitkit.models.EUR_CURRENCY
3634import to.bitkit.models.Toast
3735import to.bitkit.models.TransactionSpeed
3836import to.bitkit.models.TransferType
3937import to.bitkit.models.safe
4038import to.bitkit.repositories.BlocktankRepo
41- import to.bitkit.repositories.CurrencyRepo
4239import to.bitkit.repositories.LightningRepo
4340import to.bitkit.repositories.TransferRepo
4441import to.bitkit.repositories.WalletRepo
4542import to.bitkit.ui.shared.toast.ToastEventBus
4643import to.bitkit.utils.Logger
47- import to.bitkit.utils.ServiceError
48- import java.math.BigDecimal
4944import javax.inject.Inject
5045import kotlin.math.max
5146import kotlin.math.min
@@ -63,7 +58,6 @@ class TransferViewModel @Inject constructor(
6358 private val lightningRepo : LightningRepo ,
6459 private val blocktankRepo : BlocktankRepo ,
6560 private val walletRepo : WalletRepo ,
66- private val currencyRepo : CurrencyRepo ,
6761 private val settingsStore : SettingsStore ,
6862 private val cacheStore : CacheStore ,
6963 private val transferRepo : TransferRepo ,
@@ -361,120 +355,17 @@ class TransferViewModel @Inject constructor(
361355 // region Balance Calc
362356
363357 fun updateTransferValues (clientBalanceSat : ULong ) {
364- viewModelScope.launch {
365- _transferValues .value = calculateTransferValues(clientBalanceSat)
366- }
367- }
368-
369- fun calculateTransferValues (clientBalanceSat : ULong ): TransferValues {
370- val blocktankInfo = blocktankRepo.blocktankState.value.info
371- if (blocktankInfo == null ) return TransferValues ()
372-
373- // Calculate the total value of existing Blocktank channels
374- val channelsSize = totalBtChannelsValueSats(blocktankInfo)
375-
376- val minChannelSizeSat = blocktankInfo.options.minChannelSizeSat
377- val maxChannelSizeSat = blocktankInfo.options.maxChannelSizeSat
378-
379- // Because LSP limits constantly change depending on network fees
380- // Add a 2% buffer to avoid fluctuations while making the order
381- val maxChannelSize1 = (maxChannelSizeSat.toDouble() * 0.98 ).roundToLong().toULong()
382-
383- // The maximum channel size the user can open including existing channels
384- val maxChannelSize2 = maxChannelSize1.safe() - channelsSize.safe()
385- val maxChannelSizeAvailableToIncrease = min(maxChannelSize1, maxChannelSize2)
386-
387- val minLspBalance = getMinLspBalance(clientBalanceSat, minChannelSizeSat)
388- val maxLspBalance = maxChannelSizeAvailableToIncrease.safe() - clientBalanceSat.safe()
389- val defaultLspBalance = getDefaultLspBalance(clientBalanceSat, maxLspBalance)
390- val maxClientBalance = getMaxClientBalance(maxChannelSizeAvailableToIncrease)
391-
392- if (maxChannelSizeAvailableToIncrease < clientBalanceSat) {
393- Logger .warn(
394- " Amount clientBalanceSat:$clientBalanceSat too large, max possible: $maxChannelSizeAvailableToIncrease " ,
395- context = TAG
358+ val options = blocktankRepo.calculateLiquidityOptions(clientBalanceSat)
359+ _transferValues .value = if (options != null ) {
360+ TransferValues (
361+ defaultLspBalance = options.defaultLspBalanceSat,
362+ minLspBalance = options.minLspBalanceSat,
363+ maxLspBalance = options.maxLspBalanceSat,
364+ maxClientBalance = options.maxClientBalanceSat,
396365 )
397- }
398-
399- if (defaultLspBalance !in minLspBalance.. maxLspBalance) {
400- Logger .warn(
401- " Invalid defaultLspBalance:$defaultLspBalance " +
402- " min possible:$maxLspBalance , " +
403- " max possible: $minLspBalance " ,
404- context = TAG
405- )
406- }
407-
408- if (maxChannelSizeAvailableToIncrease <= 0u ) {
409- Logger .warn(" Max channel size reached. current size: $channelsSize sats" , context = TAG )
410- }
411-
412- if (maxClientBalance <= 0u ) {
413- Logger .warn(" No liquidity available to purchase $maxClientBalance " , context = TAG )
414- }
415-
416- return TransferValues (
417- defaultLspBalance = defaultLspBalance,
418- minLspBalance = minLspBalance,
419- maxLspBalance = maxLspBalance,
420- maxClientBalance = maxClientBalance,
421- )
422- }
423-
424- private fun getDefaultLspBalance (clientBalanceSat : ULong , maxLspBalance : ULong ): ULong {
425- // Calculate thresholds in sats
426- val threshold1 = currencyRepo.convertFiatToSats(BigDecimal (225 ), EUR_CURRENCY ).getOrNull()
427- val threshold2 = currencyRepo.convertFiatToSats(BigDecimal (495 ), EUR_CURRENCY ).getOrNull()
428- val defaultLspBalanceSats = currencyRepo.convertFiatToSats(BigDecimal (450 ), EUR_CURRENCY ).getOrNull()
429-
430- Logger .debug(" getDefaultLspBalance - clientBalanceSat: $clientBalanceSat " )
431- Logger .debug(" getDefaultLspBalance - maxLspBalance: $maxLspBalance " )
432- Logger .debug(" getDefaultLspBalance - defaultLspBalanceSats: $defaultLspBalanceSats " )
433-
434- if (threshold1 == null || threshold2 == null || defaultLspBalanceSats == null ) {
435- Logger .error(" Failed to get rates for lspBalance calculation" , context = TAG )
436- throw ServiceError .CurrencyRateUnavailable
437- }
438-
439- val lspBalance = if (clientBalanceSat < threshold1) { // 0-225€: LSP balance = 450€ - client balance
440- defaultLspBalanceSats.safe() - clientBalanceSat.safe()
441- } else if (clientBalanceSat < threshold2) { // 225-495€: LSP balance = client balance
442- clientBalanceSat
443- } else if (clientBalanceSat < maxLspBalance) { // 495-950€: LSP balance = max - client balance
444- maxLspBalance.safe() - clientBalanceSat.safe()
445366 } else {
446- maxLspBalance
367+ TransferValues ()
447368 }
448-
449- return min(lspBalance, maxLspBalance)
450- }
451-
452- private fun getMinLspBalance (clientBalance : ULong , minChannelSize : ULong ): ULong {
453- // LSP balance must be at least 2.5% of the channel size for LDK to accept (reserve balance)
454- val ldkMinimum = (clientBalance.toDouble() * 0.025 ).toULong()
455- // Channel size must be at least minChannelSize
456- val lspMinimum = minChannelSize.safe() - clientBalance.safe()
457-
458- return max(ldkMinimum, lspMinimum)
459- }
460-
461- private fun getMaxClientBalance (maxChannelSize : ULong ): ULong {
462- // Remote balance must be at least 2.5% of the channel size for LDK to accept (reserve balance)
463- val minRemoteBalance = (maxChannelSize.toDouble() * 0.025 ).toULong()
464-
465- return maxChannelSize.safe() - minRemoteBalance.safe()
466- }
467-
468- /* * Calculates the total value of channels connected to Blocktank nodes */
469- private fun totalBtChannelsValueSats (info : IBtInfo ? ): ULong {
470- val channels = lightningRepo.getChannels() ? : return 0u
471- val btNodeIds = info?.nodes?.map { it.pubkey } ? : return 0u
472-
473- val btChannels = channels.filter { btNodeIds.contains(it.counterpartyNodeId) }
474-
475- val totalValue = btChannels.sumOf { it.channelValueSats }
476-
477- return totalValue
478369 }
479370
480371 // endregion
0 commit comments