Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions app/src/main/java/to/bitkit/repositories/WalletRepo.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package to.bitkit.repositories

import com.google.firebase.messaging.FirebaseMessaging
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.tasks.await
import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock
import org.lightningdevkit.ldknode.BalanceDetails
Expand All @@ -26,14 +24,12 @@ import to.bitkit.env.Env
import to.bitkit.ext.toHex
import to.bitkit.models.BalanceState
import to.bitkit.models.NodeLifecycleState
import to.bitkit.services.BlocktankNotificationsService
import to.bitkit.services.CoreService
import to.bitkit.utils.AddressChecker
import to.bitkit.utils.Bip21Utils
import to.bitkit.utils.Logger
import uniffi.bitkitcore.Activity
import uniffi.bitkitcore.ActivityFilter
import uniffi.bitkitcore.IBtInfo
import uniffi.bitkitcore.PaymentType
import uniffi.bitkitcore.Scanner
import uniffi.bitkitcore.decode
Expand Down Expand Up @@ -345,6 +341,22 @@ class WalletRepo @Inject constructor(
}
}

suspend fun shouldRequestAdditionalLiquidity() : Result<Boolean> = withContext(bgDispatcher) {
return@withContext try {
if (_walletState.value.receiveOnSpendingBalance == false) return@withContext Result.success(false)

if (coreService.checkGeoStatus() == true) return@withContext Result.success(false)

val channels = lightningRepo.lightningState.value.channels
val inboundBalanceSats = channels.sumOf { it.inboundCapacityMsat / 1000u }.toULong()

Result.success((_walletState.value.bip21AmountSats ?: 0uL) >= inboundBalanceSats)
} catch (e: Exception) {
Logger.error("shouldRequestAdditionalLiquidity error", e, context = TAG)
Result.failure(e)
}
}

// Debug methods
suspend fun debugKeychain(key: String, value: String): Result<String?> = withContext(bgDispatcher) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand All @@ -39,11 +40,13 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import to.bitkit.R
import to.bitkit.models.BitcoinDisplayUnit
import to.bitkit.models.PrimaryDisplay
import to.bitkit.repositories.WalletState
import to.bitkit.ui.LocalCurrencies
import to.bitkit.ui.blocktankViewModel
import to.bitkit.ui.components.AmountInputHandler
import to.bitkit.ui.components.BodySSB
import to.bitkit.ui.components.ButtonSize
Expand All @@ -61,24 +64,67 @@ import to.bitkit.ui.theme.AppTextFieldDefaults
import to.bitkit.ui.theme.AppThemeSurface
import to.bitkit.ui.theme.Colors
import to.bitkit.ui.utils.keyboardAsState
import to.bitkit.utils.Logger
import to.bitkit.viewmodels.CurrencyUiState

@Composable
fun EditInvoiceScreen(
currencyUiState: CurrencyUiState = LocalCurrencies.current,
editInvoiceVM: EditInvoiceVM = hiltViewModel(),
walletUiState: WalletState,
updateInvoice: (ULong?) -> Unit,
onClickAddTag: () -> Unit,
onClickTag: (String) -> Unit,
onInputUpdated: (String) -> Unit,
onDescriptionUpdate: (String) -> Unit,
onBack: () -> Unit,
navigateReceiveConfirm: (CjitEntryDetails) -> Unit,
) {
val currencyVM = currencyViewModel ?: return
val blocktankVM = blocktankViewModel ?: return
var satsString by rememberSaveable { mutableStateOf("") }
var keyboardVisible by remember { mutableStateOf(false) }
var isSoftKeyboardVisible by keyboardAsState()

LaunchedEffect(Unit) {
editInvoiceVM.editInvoiceEffect.collect { effect ->
when(effect) {
is EditInvoiceVM.EditInvoiceScreenEffects.NavigateAddLiquidity -> {
val receiveSats = satsString.toULongOrNull()
updateInvoice(receiveSats)


if (receiveSats == null) {
onBack()
return@collect
}

satsString.toULongOrNull()?.let { sats ->
runCatching { blocktankVM.createCjit(sats) }.onSuccess { entry ->
navigateReceiveConfirm(
CjitEntryDetails(
networkFeeSat = entry.networkFeeSat.toLong(),
serviceFeeSat = entry.serviceFeeSat.toLong(),
channelSizeSat = entry.channelSizeSat.toLong(),
feeSat = entry.feeSat.toLong(),
receiveAmountSats = receiveSats.toLong(),
invoice = entry.invoice.request,
)
)
}.onFailure { e ->
Logger.error(e = e, msg = "error creating cjit invoice" ,context = "EditInvoiceScreen")
onBack()
}
}
}
EditInvoiceVM.EditInvoiceScreenEffects.UpdateInvoice -> {
updateInvoice(satsString.toULongOrNull())
onBack()
}
}
}
}

AmountInputHandler(
input = walletUiState.balanceInput,
primaryDisplay = currencyUiState.primaryDisplay,
Expand All @@ -100,7 +146,10 @@ fun EditInvoiceScreen(
onClickBalance = { keyboardVisible = true },
onInputChanged = onInputUpdated,
onContinueKeyboard = { keyboardVisible = false },
onContinueGeneral = { updateInvoice(satsString.toULongOrNull()) },
onContinueGeneral = {
updateInvoice(satsString.toULongOrNull())
editInvoiceVM.onClickContinue()
},
onClickAddTag = onClickAddTag,
onClickTag = onClickTag,
isSoftKeyboardVisible = isSoftKeyboardVisible
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package to.bitkit.ui.screens.wallets.receive

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import to.bitkit.repositories.WalletRepo
import to.bitkit.utils.Logger
import javax.inject.Inject

@HiltViewModel
class EditInvoiceVM @Inject constructor(
val walletRepo: WalletRepo
): ViewModel() {

private val _editInvoiceEffect = MutableSharedFlow<EditInvoiceScreenEffects>(extraBufferCapacity = 1)
val editInvoiceEffect = _editInvoiceEffect.asSharedFlow()
private fun editInvoiceEffect(effect: EditInvoiceScreenEffects) = viewModelScope.launch { _editInvoiceEffect.emit(effect) }

fun onClickContinue() {
viewModelScope.launch {
walletRepo.shouldRequestAdditionalLiquidity().onSuccess { shouldRequest ->
if (shouldRequest) {
editInvoiceEffect(EditInvoiceScreenEffects.NavigateAddLiquidity)
} else {
editInvoiceEffect(EditInvoiceScreenEffects.UpdateInvoice)
}
}.onFailure {
Logger.warn("Error checking for liquidity, navigating back to QR Screen", context = TAG)
editInvoiceEffect(EditInvoiceScreenEffects.UpdateInvoice)
}
}
}

sealed interface EditInvoiceScreenEffects {
data object UpdateInvoice : EditInvoiceScreenEffects
data object NavigateAddLiquidity : EditInvoiceScreenEffects
}

companion object {
const val TAG = "EditInvoiceVM"
}
}
Loading