Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,13 @@ class FundingScreenTest {
manualClicks = 0
}

private fun setContent(fundableBalance: ULong = 100_000uL, isGeoBlocked: Boolean = false) {
private fun setContent(fundableBalance: ULong = 100_000uL) {
composeTestRule.setContent {
CompositionLocalProvider(
LocalBalances provides BalanceState(channelFundableBalance = fundableBalance)
) {
AppThemeSurface {
FundingScreen(
isGeoBlocked = isGeoBlocked,
onTransfer = { transferClicks++ },
onFund = { fundClicks++ },
onManual = { manualClicks++ },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ class ReceiveAutoTabSelectionTest {
fun keepsTabPickedByTapWhenAutoBecomesAvailable() {
setContent()

composeTestRule.onNodeWithTag("Tab-spending").performClick()
composeTestRule.onNodeWithTag("Tab-savings").performClick()
composeTestRule.waitForIdle()

Expand All @@ -59,7 +58,6 @@ class ReceiveAutoTabSelectionTest {
walletState = WALLET_STATE,
lightningState = lightningState,
onClickEditInvoice = { editedTabs += it },
onClickReceiveCjit = {},
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ class ReceiveHardwareFlowTest {
walletState = WALLET_STATE,
lightningState = LightningState(),
onClickEditInvoice = {},
onClickReceiveCjit = {},
onClickHardwareEditInvoice = {
editState.beginHardwareEdit()
isEditing = true
Expand Down
5 changes: 1 addition & 4 deletions app/src/main/java/to/bitkit/env/Env.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ internal object Env {

val isDebug = BuildConfig.DEBUG
const val isE2eTest = BuildConfig.E2E
const val isGeoblockingEnabled = BuildConfig.GEO
val e2eBackend = BuildConfig.E2E_BACKEND.lowercase()
val isLocalE2eBackend = isE2eTest && e2eBackend == "local"
const val e2eLocalHost = BuildConfig.E2E_LOCAL_HOST
Expand Down Expand Up @@ -69,7 +68,6 @@ internal object Env {

const val fxRateRefreshInterval = 2 * 60 * 1000L // 2 minutes in millis
const val fxRateStaleThreshold = 10 * 60 * 1000L // 10 minutes in millis
const val lspOrdersRefreshInterval = 2 * 60 * 1000L // 2 minutes in millis

val pushNotificationFeatures = BlocktankNotificationType.entries
const val derivationName = "bitkit-notifications"
Expand Down Expand Up @@ -152,7 +150,6 @@ internal object Env {
else -> "https://bitkit.stag0.blocktank.to/fx/rates/btc"
}

const val geoCheckUrl = "https://api1.blocktank.to/api/geocheck"
const val chatwootUrl = "https://synonym.to/api/chatwoot"
const val newsBaseUrl = "https://feeds.synonym.to/news-feed/api"
const val mempoolBaseUrl = "https://mempool.space/api"
Expand Down Expand Up @@ -287,7 +284,7 @@ object Peers {
val stag = PeerDetails.of("028a8910b0048630d4eb17af25668cdd7ea6f2d8ae20956e7a06e2ae46ebcb69fc@34.65.86.104:9400")
val lnd1 = PeerDetails.of("039b8b4dd1d88c2c5db374290cda397a8f5d79f312d6ea5d5bfdfc7c6ff363eae3@34.65.111.104:9735")
val lnd3 = PeerDetails.of("03816141f1dce7782ec32b66a300783b1d436b19777e7c686ed00115bd4b88ff4b@34.65.191.64:9735")
val lnd4 = PeerDetails.of("02a371038863605300d0b3fc9de0cf5ccb57728b7f8906535709a831b16e311187@34.65.153.174:9735")
val lnd4 = PeerDetails.of("02a371038863605300d0b3fc9de0cf5ccb57728b7f8906535709a831b16e311187@34.65.147.55:9735")

object Known {
val stag = NodePeer(Peers.stag, name = "Synonym-Own-Regtest-0")
Expand Down
21 changes: 0 additions & 21 deletions app/src/main/java/to/bitkit/fcm/WakeNodeWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.withTimeout
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonObject
import org.lightningdevkit.ldknode.Event
import to.bitkit.App
Expand Down Expand Up @@ -86,25 +84,6 @@ class WakeNodeWorker @AssistedInject constructor(
timeout = timeout,
eventHandler = { event -> handleLdkEvent(event) }
)

// Once node is started, handle the manual channel opening if needed
if (notificationType == orderPaymentConfirmed) {
val orderId = (notificationPayload?.get("orderId") as? JsonPrimitive)?.contentOrNull

if (orderId == null) {
Logger.error("Missing orderId", context = TAG)
} else {
Logger.info("Open channel request for order $orderId", context = TAG)
blocktankRepo.openChannel(orderId).onFailure {
Logger.error("Failed to open channel", it, context = TAG)
bestAttemptContent = NotificationDetails(
title = appContext.getString(R.string.notification__channel_open_failed_title),
body = it.message ?: appContext.getString(R.string.common__error_body),
)
deliver()
}
}
}
}
// Stops node on timeout & avoids notification replay by OS
withTimeout(timeout) { deliverSignal.await() }
Expand Down
15 changes: 12 additions & 3 deletions app/src/main/java/to/bitkit/models/ActivityBannerType.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,26 @@ enum class ActivityBannerType(
@DrawableRes val icon: Int,
@StringRes val title: Int,
val color: Color,
val testTag: String,
) {
SPENDING(
color = Colors.Purple,
icon = R.drawable.ic_transfer,
title = R.string.lightning__transfer_in_progress
title = R.string.lightning__transfer_in_progress,
testTag = "TransferToSpendingBanner",
),
SAVINGS(
color = Colors.Brand,
icon = R.drawable.ic_transfer,
title = R.string.lightning__transfer_in_progress
)
title = R.string.lightning__transfer_in_progress,
testTag = "TransferToSavingsBanner",
),
CHANNELS_CLOSING(
color = Colors.Yellow,
icon = R.drawable.ic_warning,
title = R.string.lightning__channels_closing_banner,
testTag = "ChannelsClosingBanner",
),
}

data class BannerItem(
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/java/to/bitkit/models/ChannelsClosing.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package to.bitkit.models

import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.util.Locale

/** Date on which Blocktank closes the remaining Lightning channels; set before release. */
val CHANNELS_CLOSE_DATE: LocalDate = LocalDate.of(2026, 12, 15)

/** Third-party Lightning service providers whose sites sell a channel the user claims by scanning a QR. */
val THIRD_PARTY_LSPS: List<ThirdPartyLsp> = listOf(
ThirdPartyLsp(name = "LNBIG", url = "https://lnbig.com/#/open-channel"),
ThirdPartyLsp(name = "ZEUS Olympus", url = "https://channels.zeuslsp.com/"),
ThirdPartyLsp(name = "Megalithic", url = "https://megalithic.me/get_a_channel"),
ThirdPartyLsp(name = "Amboss Magma", url = "https://amboss.space/magma"),
)

data class ThirdPartyLsp(
val name: String,
val url: String,
)

fun formatChannelsCloseDate(locale: Locale = Locale.getDefault()): String =
CHANNELS_CLOSE_DATE.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(locale))
68 changes: 0 additions & 68 deletions app/src/main/java/to/bitkit/models/ReceiveLiquidityDecision.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,5 @@
package to.bitkit.models

enum class ReceiveLiquiditySource {
SAVINGS,
AUTO,
SPENDING,
}

sealed interface ReceiveAdditionalLiquidityAction {
data object None : ReceiveAdditionalLiquidityAction
data object ChooseAmount : ReceiveAdditionalLiquidityAction
data class CreateCjit(val amountSats: ULong) : ReceiveAdditionalLiquidityAction
data object GeoBlocked : ReceiveAdditionalLiquidityAction
}

data class ReceiveAdditionalLiquidityParams(
val source: ReceiveLiquiditySource,
val invoiceAmountSats: ULong,
val inboundCapacitySats: ULong?,
val minCjitSats: ULong?,
val maxCjitAmountSats: ULong?,
val isGeoBlocked: Boolean,
)

object ReceiveLiquidityDecision {
fun canCreateLightningInvoice(
hasReadyChannels: Boolean,
Expand All @@ -36,50 +14,4 @@ object ReceiveLiquidityDecision {

return invoiceAmountSats <= inboundCapacitySats
}

fun additionalLiquidityAction(params: ReceiveAdditionalLiquidityParams): ReceiveAdditionalLiquidityAction {
return when {
params.source != ReceiveLiquiditySource.SPENDING -> ReceiveAdditionalLiquidityAction.None
!needsInboundLiquidity(params.invoiceAmountSats, params.inboundCapacitySats) ->
ReceiveAdditionalLiquidityAction.None
(params.inboundCapacitySats ?: 0uL) == 0uL -> ReceiveAdditionalLiquidityAction.None
params.isGeoBlocked -> ReceiveAdditionalLiquidityAction.GeoBlocked
shouldChooseAmount(params) -> ReceiveAdditionalLiquidityAction.ChooseAmount
else -> ReceiveAdditionalLiquidityAction.CreateCjit(params.invoiceAmountSats)
}
}

fun needsCjitLimitsForAdditionalLiquidity(
source: ReceiveLiquiditySource,
invoiceAmountSats: ULong,
inboundCapacitySats: ULong?,
isGeoBlocked: Boolean,
): Boolean {
if (source != ReceiveLiquiditySource.SPENDING) return false
if (!needsInboundLiquidity(invoiceAmountSats, inboundCapacitySats)) return false
if ((inboundCapacitySats ?: 0uL) == 0uL) return false

return !isGeoBlocked
}

fun needsInboundLiquidity(
invoiceAmountSats: ULong,
inboundCapacitySats: ULong?,
): Boolean {
val inbound = inboundCapacitySats ?: 0uL

if (invoiceAmountSats == 0uL) {
return inbound == 0uL
}

return invoiceAmountSats > inbound
}

private fun shouldChooseAmount(params: ReceiveAdditionalLiquidityParams): Boolean {
val min = params.minCjitSats ?: 0uL
val max = params.maxCjitAmountSats?.takeIf { it > 0uL } ?: return true
if (params.invoiceAmountSats == 0uL || min == 0uL) return true

return params.invoiceAmountSats < min || params.invoiceAmountSats > max
}
}
6 changes: 0 additions & 6 deletions app/src/main/java/to/bitkit/models/Suggestion.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,6 @@ enum class Suggestion(
color = Colors.Blue24,
icon = R.drawable.trezor,
),
LIGHTNING(
title = R.string.cards__lightning__title,
description = R.string.cards__lightning__description,
color = Colors.Purple24,
icon = R.drawable.lightning,
),
BACK_UP(
title = R.string.cards__backupSeedPhrase__title,
description = R.string.cards__backupSeedPhrase__description,
Expand Down
Loading
Loading