Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
9604817
feat: ConnectionIssuesView
jvsena42 Mar 31, 2026
b93d729
feat: display connection issues view
jvsena42 Mar 31, 2026
1671051
fix: circle alignment
jvsena42 Mar 31, 2026
61e0371
fix: circle color and fading
jvsena42 Mar 31, 2026
e60c9fb
chore: lint
jvsena42 Mar 31, 2026
aaa3d8d
fix: gradient color
jvsena42 Mar 31, 2026
9f3c1f9
feat: display connection issues screen in transfer flows
jvsena42 Apr 1, 2026
46f955f
refactor: remove unnecessary parameter
jvsena42 Apr 1, 2026
e81a4ff
Merge branch 'feat/send-v60' into feat/connection-issues-view
jvsena42 Apr 1, 2026
a5fde6d
fix: re-trigger updateLimits when switch to online
jvsena42 Apr 1, 2026
4f9c6df
Merge branch 'feat/send-v60' into feat/connection-issues-view
jvsena42 Apr 2, 2026
70f1112
fix: not populated LN balance on canSend fallback
jvsena42 Apr 2, 2026
db7d466
fix: add spacer
jvsena42 Apr 2, 2026
8b11ea7
fix: fallback to cached balance for validation when channels are loading
jvsena42 Apr 2, 2026
5f3da5c
fix: isFirstEmission check
jvsena42 Apr 2, 2026
eec1e8e
fix: await for peer connection before try to close
jvsena42 Apr 2, 2026
49167e1
Merge branch 'feat/send-v60' into feat/connection-issues-view
jvsena42 Apr 2, 2026
20154dc
doc: changelog entry
jvsena42 Apr 2, 2026
4e7e2a2
chore: lint
jvsena42 Apr 2, 2026
0136e97
merge: feat/send-v60 into feat/connection-issues-view
jvsena42 Apr 2, 2026
5caf2b3
doc: consolidate changelog entries
jvsena42 Apr 2, 2026
ef540ab
Merge branch 'feat/send-v60' into feat/connection-issues-view
jvsena42 Apr 2, 2026
e3d6b4f
Update app/src/main/java/to/bitkit/ui/components/ConnectionIssuesView.kt
jvsena42 Apr 2, 2026
2c417d5
Merge branch 'feat/send-v60' into feat/connection-issues-view
jvsena42 Apr 2, 2026
1b796a1
feat: add transfer from savings button on empty spending screen
jvsena42 Apr 2, 2026
3f35635
doc: add changelog entry
jvsena42 Apr 2, 2026
7942b52
chore: backfill changelog pr number
jvsena42 Apr 2, 2026
28da848
Merge branch 'feat/connection-issues-view' into feat/transfer-from-sa…
jvsena42 Apr 2, 2026
99cf123
Update app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletS…
jvsena42 Apr 2, 2026
e0b12fd
Update app/src/main/java/to/bitkit/ui/screens/wallets/SpendingWalletS…
jvsena42 Apr 2, 2026
ecdb66b
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 2, 2026
9805964
Merge branch 'feat/connection-issues-view' into feat/transfer-from-sa…
jvsena42 Apr 2, 2026
984f20c
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 6, 2026
2445a59
Merge branch 'feat/connection-issues-view' into feat/transfer-from-sa…
jvsena42 Apr 6, 2026
c032a4d
fix: import
jvsena42 Apr 6, 2026
5392a89
chore: lint
jvsena42 Apr 6, 2026
dc6a27a
chore: lint
jvsena42 Apr 6, 2026
7ec57f9
refactor: replace cache strategy with flow collecting + timeout
jvsena42 Apr 6, 2026
055a783
fix: display SyncNodeView on SendSheet start when node is not running…
jvsena42 Apr 6, 2026
385b655
fix: display sync view early when handling deeplinks
jvsena42 Apr 6, 2026
00a8108
refactor: extract waitForUsableChannels logic from canSend
jvsena42 Apr 6, 2026
3da8e8d
Merge branch 'feat/connection-issues-view' into feat/transfer-from-sa…
ovitrif Apr 6, 2026
fbe31db
fix: don't block navigation by ln fee estimation
jvsena42 Apr 6, 2026
18b4a23
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 6, 2026
730a4ae
Merge branch 'master' into feat/transfer-from-savings-button-on-empty…
ovitrif Apr 6, 2026
2d9d0d3
chore: rm unused import
ovitrif Apr 6, 2026
fd8f672
fix: add bg blur to transfer from savings button
ovitrif Apr 6, 2026
2780cc5
fix: secondary button weight layout regression
ovitrif Apr 6, 2026
cb49884
Merge branch 'feat/connection-issues-view' into feat/transfer-from-sa…
ovitrif Apr 6, 2026
ced3109
chore: rm modifier arg trailing comma
ovitrif Apr 6, 2026
34daff4
Merge pull request #882 from synonymdev/feat/transfer-from-savings-bu…
ovitrif Apr 6, 2026
d934929
Merge branch 'master' into feat/connection-issues-view
ovitrif Apr 6, 2026
5225b07
fix: set loading state for confirm button
jvsena42 Apr 7, 2026
b3b57b0
fix: check for usable channels directly from service instead of waiti…
jvsena42 Apr 7, 2026
3948fe6
fix: reduce restrictions for display sync overlay
jvsena42 Apr 7, 2026
52adf83
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 7, 2026
7aa3f2a
chore: topbar gradient constant
jvsena42 Apr 7, 2026
08115f4
fix: scroll screens behind top bar and implement gradient effect
jvsena42 Apr 7, 2026
8aade71
fix: set bgDispatcher context
jvsena42 Apr 7, 2026
052883d
fix: hide sheet on lightning only decode error
jvsena42 Apr 7, 2026
1e42566
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 7, 2026
29e9fe6
refactor: implement VerticalSpacer
jvsena42 Apr 7, 2026
15db679
refactor: implement VerticalSpacer
jvsena42 Apr 7, 2026
03ba518
chore: lint
jvsena42 Apr 7, 2026
828e048
chore: lint
jvsena42 Apr 7, 2026
1dd5737
chore: lint
jvsena42 Apr 7, 2026
ec1bee9
doc: changelog entry
jvsena42 Apr 7, 2026
d075af2
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 7, 2026
9050881
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 7, 2026
39af4b3
fix: lint
jvsena42 Apr 8, 2026
b5dc130
fix: hide sheet on invalid address and network mismatch
jvsena42 Apr 8, 2026
03698fb
fix: open scanner sheet inside send sheet to fix navigation
jvsena42 Apr 8, 2026
f533734
fix: hide sheet in more error cases
jvsena42 Apr 8, 2026
fabb81a
Update app/src/main/java/to/bitkit/repositories/LightningRepo.kt
jvsena42 Apr 8, 2026
479ff9b
Update app/src/main/java/to/bitkit/ui/screens/wallets/receive/EditInv…
jvsena42 Apr 8, 2026
268ff81
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 8, 2026
5365361
fix: shouldShowSyncOverlay causing too much recompositions
jvsena42 Apr 8, 2026
f7e6f53
Merge remote-tracking branch 'origin/feat/connection-issues-view' int…
jvsena42 Apr 8, 2026
0a02b89
chore: lint
jvsena42 Apr 8, 2026
dada317
chore: lint
jvsena42 Apr 8, 2026
0cfc2af
fix: sync state before check if can send lighting to don't use stale …
jvsena42 Apr 8, 2026
7e1118f
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 8, 2026
588d2e5
fix: sync state after channel ready
jvsena42 Apr 9, 2026
fbe494c
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 9, 2026
5ff4110
fix: reconnect peers immediately after connection recovery to restore…
jvsena42 Apr 9, 2026
9f1a66a
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 9, 2026
a87185f
doc: update changelog
jvsena42 Apr 9, 2026
60c57b4
Merge remote-tracking branch 'origin/fix/spending-and-savings-scroll'…
jvsena42 Apr 9, 2026
50d9472
doc: update changelog
jvsena42 Apr 9, 2026
c53d402
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 9, 2026
5aed3e8
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 11, 2026
4e812bf
Merge branch 'feat/connection-issues-view' into fix/spending-and-savi…
jvsena42 Apr 11, 2026
5df68a9
Merge pull request #892 from synonymdev/fix/spending-and-savings-scroll
jvsena42 Apr 17, 2026
77e31a1
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 20, 2026
e723f8e
Merge branch 'master' into feat/connection-issues-view
ovitrif Apr 21, 2026
d22844e
Merge remote-tracking branch 'origin/master' into feat/connection-iss…
jvsena42 Apr 22, 2026
c38fdcf
Merge remote-tracking branch 'origin/feat/connection-issues-view' int…
jvsena42 Apr 22, 2026
17e9f00
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 27, 2026
e5e0f68
Merge branch 'master' into feat/connection-issues-view
ovitrif Apr 28, 2026
af971ee
Merge branch 'master' into feat/connection-issues-view
ovitrif Apr 30, 2026
708a8b7
Merge branch 'master' into feat/connection-issues-view
jvsena42 Apr 30, 2026
96f8799
doc: migrate changelog entry to fragment changelog pattern
jvsena42 Apr 30, 2026
e72c985
Merge branch 'master' into feat/connection-issues-view
jvsena42 May 4, 2026
e6c4fff
chore: lint
ovitrif May 1, 2026
3851847
fix: stabilize send scan routing
ovitrif May 1, 2026
d90ee6d
Merge branch 'master' into feat/connection-issues-view
ovitrif May 7, 2026
8b15897
chore: fix manual merge issues
ovitrif May 7, 2026
bfa54b9
Merge branch 'feat/connection-issues-view' into fix/connection-issues…
ovitrif May 7, 2026
9bcb59b
fix: use const for bolt11 expiry default
ovitrif May 7, 2026
aeee301
chore: restore comment
ovitrif May 7, 2026
c39ceb5
fix: preserve main scanner routing
ovitrif May 7, 2026
10cbfdf
fix: magic number use in constant
ovitrif May 7, 2026
bdc6d95
test: cover scanner routing
ovitrif May 8, 2026
bf5e8f0
fix: wait for channel state
ovitrif May 8, 2026
25e5abb
chore: clean lnurl expiry naming
ovitrif May 10, 2026
cd22987
fix: soften channel unavailable feedback
ovitrif May 11, 2026
321cc3d
chore: use duration for channel timeout
ovitrif May 11, 2026
55341fd
Merge pull request #925 from synonymdev/fix/connection-issues-view
ovitrif May 12, 2026
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
- Fix Spending and Savings screens scrolling behind top bar and add gradient fade effect #892

### Changed
- Improve Pubky profile restore, contact editing, and contact routing flows #905
Expand All @@ -25,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Show loading state on Spending tab when node is not running #875

### Added
- Transfer from Savings button on empty Spending screen when savings balance exists #882
Comment thread
jvsena42 marked this conversation as resolved.
- Pubky profile onboarding with contact sync, import, and editing #824
- Lightning Connections empty state with onboarding screen #857
- Unified PIN management screen (enable/disable/change in one place) #857
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/to/bitkit/env/Env.kt
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ internal object Env {
@Suppress("ConstPropertyName")
object Defaults {
/** Default Bolt11 invoice expiry in seconds. */
const val bolt11InvoiceExpirySeconds = 3_600u
const val bolt11ExpirySec = 86_400u

/** Recommended transaction base fee in sats */
const val recommendedBaseFee = 256u
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/to/bitkit/repositories/BlocktankRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ import org.lightningdevkit.ldknode.ChannelDetails
import to.bitkit.async.ServiceQueue
import to.bitkit.data.CacheStore
import to.bitkit.di.BgDispatcher
import to.bitkit.env.Defaults
import to.bitkit.env.Env
import to.bitkit.ext.calculateRemoteBalance
import to.bitkit.ext.nowTimestamp
Expand All @@ -57,6 +56,7 @@ import javax.inject.Named
import javax.inject.Singleton
import kotlin.math.ceil
import kotlin.time.Duration
import kotlin.time.Duration.Companion.hours
import kotlin.time.Duration.Companion.seconds

@Singleton
Expand Down Expand Up @@ -463,7 +463,7 @@ class BlocktankRepo @Inject constructor(
val invoice = lightningRepo.createInvoice(
amountSats = null,
description = "blocktank-gift-code:$code",
expirySeconds = Defaults.bolt11InvoiceExpirySeconds,
expirySeconds = 1.hours.inWholeSeconds.toUInt(),
).getOrThrow()

Logger.debug("Created invoice for gift code, requesting payment from LSP", context = TAG)
Expand Down
110 changes: 88 additions & 22 deletions app/src/main/java/to/bitkit/repositories/LightningRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ import to.bitkit.data.SettingsStore
import to.bitkit.data.backup.VssBackupClientLdk
import to.bitkit.data.keychain.Keychain
import to.bitkit.di.BgDispatcher
import to.bitkit.env.Defaults
import to.bitkit.env.Env
import to.bitkit.ext.getSatsPerVByteFor
import to.bitkit.ext.nowTimestamp
import to.bitkit.ext.toPeerDetailsList
import to.bitkit.ext.totalNextOutboundHtlcLimitSats
import to.bitkit.models.ALL_ADDRESS_TYPE_STRINGS
import to.bitkit.models.CoinSelectionPreference
import to.bitkit.models.NATIVE_WITNESS_TYPES
Expand Down Expand Up @@ -93,6 +95,7 @@ import javax.inject.Inject
import javax.inject.Singleton
import kotlin.coroutines.cancellation.CancellationException
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds

Expand Down Expand Up @@ -151,6 +154,10 @@ class LightningRepo @Inject constructor(
return@collect
}

if (_lightningState.value.nodeLifecycleState.isRunning()) {
connectToTrustedPeers()
}

// Start retry loop if sync is failing
startSyncRetryLoopIfNeeded()
}
Expand Down Expand Up @@ -533,7 +540,11 @@ class LightningRepo @Inject constructor(

private fun handleLdkEvent(event: Event) {
when (event) {
is Event.ChannelPending, is Event.ChannelReady -> scope.launch { refreshChannelCache() }
is Event.ChannelPending, is Event.ChannelReady -> scope.launch {
refreshChannelCache()
syncState()
}

is Event.ChannelClosed -> scope.launch { registerClosedChannel(event.channelId, event.reason) }
else -> Unit
}
Expand Down Expand Up @@ -917,7 +928,7 @@ class LightningRepo @Inject constructor(
suspend fun createInvoice(
amountSats: ULong? = null,
description: String,
expirySeconds: UInt = 86_400u,
expirySeconds: UInt = Defaults.bolt11ExpirySec,
): Result<String> = executeWhenNodeRunning("createInvoice") {
updateGeoBlockState()
runCatching { lightningService.receive(amountSats, description, expirySeconds) }
Expand All @@ -926,7 +937,7 @@ class LightningRepo @Inject constructor(
suspend fun createInvoiceMsats(
amountMsats: ULong,
description: String,
expirySeconds: UInt = 86_400u,
expirySeconds: UInt = Defaults.bolt11ExpirySec,
): Result<String> = executeWhenNodeRunning("createInvoiceMsats") {
updateGeoBlockState()
runCatching { lightningService.receiveMsats(amountMsats, description, expirySeconds) }
Expand Down Expand Up @@ -1009,15 +1020,69 @@ class LightningRepo @Inject constructor(
}
}

private suspend fun waitForUsableChannels() {
if (lightningService.channels?.any { it.isUsable } == true) return
suspend fun waitForUsableChannels() = withContext(bgDispatcher) {
var state = _lightningState.value
if (!state.nodeLifecycleState.canRun()) {
delayNoUsableChannelsFeedback()
return@withContext
}
if (state.hasUsableChannels()) return@withContext

state = waitForChannelsToLoadIfNeeded(state) ?: return@withContext
if (!state.nodeLifecycleState.canRun()) {
delayNoUsableChannelsFeedback()
return@withContext
}

if (state.channels.isEmpty()) {
if (state.nodeLifecycleState.isRunning()) {
syncState()
state = _lightningState.value
}

if (state.channels.isEmpty()) {
delayNoUsableChannelsFeedback()
return@withContext
}
if (state.hasUsableChannels()) return@withContext
}

Logger.info("Waiting for usable channels before sending payment", context = TAG)
syncState()

withTimeoutOrNull(CHANNELS_USABLE_TIMEOUT_MS) {
_lightningState.first { state -> state.channels.any { it.isUsable } }
} ?: Logger.warn("Timeout waiting for usable channels", context = TAG)
val finalState = withTimeoutOrNull(CHANNELS_USABLE_TIMEOUT) {
_lightningState.first { it.shouldStopWaitingForUsableChannels() }
} ?: run {
Logger.warn("Timed out waiting for usable channels", context = TAG)
return@withContext
}

if (!finalState.nodeLifecycleState.canRun() || finalState.channels.isEmpty()) {
delayNoUsableChannelsFeedback()
}
}

private suspend fun waitForChannelsToLoadIfNeeded(state: LightningState): LightningState? {
if (state.channels.isNotEmpty() || state.nodeLifecycleState.isRunning()) return state

Logger.info("Waiting for node to load channels before sending payment", context = TAG)
return withTimeoutOrNull(CHANNELS_USABLE_TIMEOUT) {
_lightningState.first { it.shouldStopWaitingForLoadedChannels() }
} ?: run {
Logger.warn("Timed out waiting for node to load channels", context = TAG)
null
}
}

private fun LightningState.hasUsableChannels() = channels.any { it.isUsable }

private fun LightningState.shouldStopWaitingForLoadedChannels() =
!nodeLifecycleState.canRun() || nodeLifecycleState.isRunning() || channels.isNotEmpty()

private fun LightningState.shouldStopWaitingForUsableChannels() =
!nodeLifecycleState.canRun() || channels.isEmpty() || hasUsableChannels()

private suspend fun delayNoUsableChannelsFeedback() {
delay(NO_USABLE_CHANNELS_FEEDBACK_DELAY)
}

@Suppress("LongParameterList")
Expand Down Expand Up @@ -1229,19 +1294,20 @@ class LightningRepo @Inject constructor(
}
}

suspend fun canSend(amountSats: ULong, fallbackToCachedBalance: Boolean = true) = withContext(bgDispatcher) {
if (!_lightningState.value.nodeLifecycleState.canRun()) {
return@withContext false
}
if (_lightningState.value.nodeLifecycleState.isStarting() && fallbackToCachedBalance) {
return@withContext amountSats <= (cacheStore.data.first().balance?.maxSendLightningSats ?: 0u)
}
if (lightningService.channels == null) {
withTimeoutOrNull(CHANNELS_READY_TIMEOUT_MS) {
_lightningState.first { lightningService.channels != null }
suspend fun awaitPeerConnected(timeout: Duration = 30.seconds) = withContext(bgDispatcher) {
Comment thread
jvsena42 marked this conversation as resolved.
if (lightningService.peers?.any { it.isConnected } == true) return@withContext
Logger.debug("Waiting for peer to reconnect (timeout='$timeout')...", context = TAG)
withTimeoutOrNull(timeout) {
while (lightningService.peers?.any { it.isConnected } != true) {
delay(1.seconds)
}
}
return@withContext lightningService.canSend(amountSats)
}

fun canSend(amountSats: ULong): Boolean {
val state = _lightningState.value
if (!state.nodeLifecycleState.canRun()) return false
return state.channels.totalNextOutboundHtlcLimitSats() >= amountSats
}

fun getNodeId(): String? =
Expand Down Expand Up @@ -1478,8 +1544,8 @@ class LightningRepo @Inject constructor(
private const val LENGTH_CHANNEL_ID_PREVIEW = 10
private const val MS_SYNC_LOOP_DEBOUNCE = 500L
private const val SYNC_RETRY_DELAY_MS = 15_000L
private const val CHANNELS_READY_TIMEOUT_MS = 15_000L
private const val CHANNELS_USABLE_TIMEOUT_MS = 15_000L
private val CHANNELS_USABLE_TIMEOUT = 15.seconds
private val NO_USABLE_CHANNELS_FEEDBACK_DELAY = 2_500.milliseconds
val SEND_LN_TIMEOUT = 10.seconds
private val PROBE_TIMEOUT = 60.seconds
}
Expand Down
9 changes: 7 additions & 2 deletions app/src/main/java/to/bitkit/services/CoreService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import org.lightningdevkit.ldknode.TransactionDetails
import to.bitkit.async.ServiceQueue
import to.bitkit.data.CacheStore
import to.bitkit.data.SettingsStore
import to.bitkit.env.Defaults
import to.bitkit.env.Env
import to.bitkit.ext.amountSats
import to.bitkit.ext.channelId
Expand Down Expand Up @@ -1523,11 +1524,15 @@ class BlocktankService(
)
}

suspend fun regtestCloseChannel(fundingTxId: String, vout: UInt, forceCloseAfterS: ULong = 86_400uL): String {
suspend fun regtestCloseChannel(
fundingTxId: String,
vout: UInt,
forceCloseAfterS: UInt = Defaults.bolt11ExpirySec,
): String {
return com.synonym.bitkitcore.regtestCloseChannel(
fundingTxId = fundingTxId,
vout = vout,
forceCloseAfterS = forceCloseAfterS,
forceCloseAfterS = forceCloseAfterS.toULong(),
)
}
}
Expand Down
22 changes: 2 additions & 20 deletions app/src/main/java/to/bitkit/services/LightningService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import to.bitkit.data.keychain.Keychain
import to.bitkit.di.BgDispatcher
import to.bitkit.env.Defaults
import to.bitkit.env.Env
import to.bitkit.ext.totalNextOutboundHtlcLimitSats
import to.bitkit.ext.uByteList
import to.bitkit.ext.uri
import to.bitkit.models.OpenChannelResult
Expand Down Expand Up @@ -596,15 +595,15 @@ class LightningService @Inject constructor(
suspend fun receive(
sat: ULong? = null,
description: String,
expirySecs: UInt = Defaults.bolt11InvoiceExpirySeconds,
expirySecs: UInt = Defaults.bolt11ExpirySec,
): String {
return receiveMsats(amountMsat = sat?.let { it * 1000u }, description = description, expirySecs = expirySecs)
}

suspend fun receiveMsats(
amountMsat: ULong? = null,
description: String,
expirySecs: UInt = Defaults.bolt11InvoiceExpirySeconds,
expirySecs: UInt = Defaults.bolt11ExpirySec,
): String {
val node = this.node ?: throw ServiceError.NodeNotSetup()

Expand All @@ -630,23 +629,6 @@ class LightningService @Inject constructor(
}
}

fun canSend(amountSats: ULong): Boolean {
val channels = this.channels
if (channels == null) {
Logger.warn("Channels not available", context = TAG)
return false
}

val totalNextOutboundHtlcLimitSats = channels.totalNextOutboundHtlcLimitSats()

if (totalNextOutboundHtlcLimitSats < amountSats) {
Logger.warn("Insufficient outbound capacity: $totalNextOutboundHtlcLimitSats < $amountSats", context = TAG)
return false
}

return true
}

suspend fun send(
address: Address,
sats: ULong,
Expand Down
Loading
Loading