Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
15 changes: 15 additions & 0 deletions app/src/main/java/to/bitkit/repositories/LightningRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import org.lightningdevkit.ldknode.ChannelConfig
import org.lightningdevkit.ldknode.ChannelDataMigration
import org.lightningdevkit.ldknode.ChannelDetails
import org.lightningdevkit.ldknode.ClosureReason
import org.lightningdevkit.ldknode.CoinSelectionAlgorithm
import org.lightningdevkit.ldknode.Event
import org.lightningdevkit.ldknode.NodeStatus
import org.lightningdevkit.ldknode.PaymentDetails
Expand Down Expand Up @@ -1262,6 +1263,20 @@ class LightningRepo @Inject constructor(
lightningService.listSpendableOutputs()
}

suspend fun selectUtxosWithAlgorithm(
targetAmountSats: ULong,
satsPerVByte: ULong,
algorithm: CoinSelectionAlgorithm = CoinSelectionAlgorithm.LARGEST_FIRST,
utxos: List<SpendableUtxo>? = null,
): Result<List<SpendableUtxo>> = executeWhenNodeRunning("selectUtxosWithAlgorithm") {
lightningService.selectUtxosWithAlgorithm(
targetAmountSats = targetAmountSats,
satsPerVByte = satsPerVByte,
algorithm = algorithm,
utxos = utxos,
)
}

suspend fun calculateTotalFee(
amountSats: ULong,
address: Address? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
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 Down Expand Up @@ -44,9 +45,9 @@ import com.synonym.bitkitcore.IBtOnchainTransactions
import com.synonym.bitkitcore.IBtOrder
import com.synonym.bitkitcore.IBtPayment
import com.synonym.bitkitcore.ILspNode
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import to.bitkit.R
import to.bitkit.models.safe
import to.bitkit.ui.components.ButtonSize
import to.bitkit.ui.components.ChannelStatusUi
import to.bitkit.ui.components.ConnectionIssuesView
Expand Down Expand Up @@ -91,6 +92,12 @@ fun SpendingConfirmScreen(
return
}
val isAdvanced = state.isAdvanced
val miningFeeSats = state.miningFeeSats
val isConfirmFeeReady = state.isConfirmFeeReady

LaunchedEffect(order.id, order.feeSat) {
viewModel.prepareSpendingConfirmFunding(order)
}

val notificationsGranted by settingsViewModel.notificationsGranted.collectAsStateWithLifecycle()

Expand All @@ -116,6 +123,8 @@ fun SpendingConfirmScreen(
onUseDefaultLspBalanceClick = viewModel::onUseDefaultLspBalanceClick,
onTransferToSpendingConfirm = viewModel::onTransferToSpendingConfirm,
order = order,
miningFeeSats = miningFeeSats,
isConfirmFeeReady = isConfirmFeeReady,
hasNotificationPermission = notificationsGranted,
onSwitchClick = onNotificationSwitchClick,
isAdvanced = isAdvanced,
Expand All @@ -133,7 +142,7 @@ fun SpendingConfirmScreen(
}
}

@Suppress("MagicNumber")
@Suppress("MagicNumber", "LongMethod")
@Composable
private fun Content(
onBackClick: () -> Unit,
Expand All @@ -143,8 +152,10 @@ private fun Content(
onUseDefaultLspBalanceClick: () -> Unit,
onSwitchClick: () -> Unit,
hasNotificationPermission: Boolean,
onTransferToSpendingConfirm: (IBtOrder) -> Unit,
onTransferToSpendingConfirm: suspend (IBtOrder) -> Boolean,
order: IBtOrder,
miningFeeSats: ULong,
isConfirmFeeReady: Boolean,
isAdvanced: Boolean,
) {
val scope = rememberCoroutineScope()
Expand Down Expand Up @@ -175,10 +186,10 @@ private fun Content(
.fillMaxSize()
.verticalScroll(rememberScrollState())
) {
// Match iOS SpendingConfirm: network fee = mining fee, lsp fee = order fee - client.
val clientBalance = order.clientBalanceSat
val networkFee = order.networkFeeSat
val serviceFee = order.serviceFeeSat
val totalFee = order.feeSat
val lspFee = order.feeSat.safe() - clientBalance.safe()
val total = order.feeSat.safe() + miningFeeSats.safe()
val lspBalance = order.lspBalanceSat

VerticalSpacer(32.dp)
Expand All @@ -191,11 +202,11 @@ private fun Content(
) {
FeeInfo(
label = stringResource(R.string.lightning__spending_confirm__network_fee),
amount = networkFee.toLong(),
amount = miningFeeSats.toLong(),
)
FeeInfo(
label = stringResource(R.string.lightning__spending_confirm__lsp_fee),
amount = serviceFee.toLong(),
amount = lspFee.toLong(),
)
}
Row(
Expand All @@ -208,7 +219,7 @@ private fun Content(
)
FeeInfo(
label = stringResource(R.string.lightning__spending_confirm__total),
amount = totalFee.toLong(),
amount = total.toLong(),
)
}

Expand Down Expand Up @@ -268,16 +279,22 @@ private fun Content(
FillHeight()

var isLoading by remember { mutableStateOf(false) }
// Match iOS: keep swipe in loading state until mining fee is ready.
val canConfirm = isConfirmFeeReady && miningFeeSats > 0uL && !isLoading
SwipeToConfirm(
text = stringResource(R.string.lightning__transfer__swipe),
loading = isLoading,
loading = isLoading || !isConfirmFeeReady,
color = Colors.Purple,
onConfirm = {
if (!canConfirm) return@SwipeToConfirm
scope.launch {
isLoading = true
delay(300)
onTransferToSpendingConfirm(order)
onConfirm()
val paid = onTransferToSpendingConfirm(order)
if (paid) {
onConfirm()
} else {
isLoading = false
}
}
},
)
Expand All @@ -297,7 +314,7 @@ private fun Preview() {
onAdvancedClick = {},
onConfirm = {},
onUseDefaultLspBalanceClick = {},
onTransferToSpendingConfirm = {},
onTransferToSpendingConfirm = { true },
order = IBtOrder(
id = "order_7e6f3b7c-486a-4f5a-8b1e-2c9d7f0a8b9d",
state = BtOrderState.CREATED,
Expand Down Expand Up @@ -359,6 +376,8 @@ private fun Preview() {
),
onSwitchClick = {},
hasNotificationPermission = true,
miningFeeSats = 250uL,
isConfirmFeeReady = true,
isAdvanced = false
)
}
Expand All @@ -374,7 +393,7 @@ private fun Preview2() {
onAdvancedClick = {},
onConfirm = {},
onUseDefaultLspBalanceClick = {},
onTransferToSpendingConfirm = {},
onTransferToSpendingConfirm = { true },
order = IBtOrder(
id = "order_7e6f3b7c-486a-4f5a-8b1e-2c9d7f0a8b9d",
state = BtOrderState.CREATED,
Expand Down Expand Up @@ -436,6 +455,8 @@ private fun Preview2() {
),
onSwitchClick = {},
hasNotificationPermission = true,
miningFeeSats = 250uL,
isConfirmFeeReady = true,
isAdvanced = true
)
}
Expand All @@ -451,7 +472,7 @@ private fun Preview3() {
onAdvancedClick = {},
onConfirm = {},
onUseDefaultLspBalanceClick = {},
onTransferToSpendingConfirm = {},
onTransferToSpendingConfirm = { true },
order = IBtOrder(
id = "order_7e6f3b7c-486a-4f5a-8b1e-2c9d7f0a8b9d",
state = BtOrderState.CREATED,
Expand Down Expand Up @@ -513,6 +534,8 @@ private fun Preview3() {
),
onSwitchClick = {},
hasNotificationPermission = false,
miningFeeSats = 250uL,
isConfirmFeeReady = true,
isAdvanced = false
)
}
Expand All @@ -528,7 +551,7 @@ private fun Preview4() {
onAdvancedClick = {},
onConfirm = {},
onUseDefaultLspBalanceClick = {},
onTransferToSpendingConfirm = {},
onTransferToSpendingConfirm = { true },
order = IBtOrder(
id = "order_7e6f3b7c-486a-4f5a-8b1e-2c9d7f0a8b9d",
state = BtOrderState.CREATED,
Expand Down Expand Up @@ -590,6 +613,8 @@ private fun Preview4() {
),
onSwitchClick = {},
hasNotificationPermission = true,
miningFeeSats = 250uL,
isConfirmFeeReady = true,
isAdvanced = true
)
}
Expand Down
Loading
Loading