Skip to content
109 changes: 51 additions & 58 deletions app/src/main/java/to/bitkit/ext/ChannelDetails.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,76 +15,69 @@ import org.lightningdevkit.ldknode.MaxDustHtlcExposure
* - our_reserve: Our reserve that we get back on close
*/
val ChannelDetails.amountOnClose: ULong
@Suppress("ForbiddenComment")
get() {
// TODO: use channelDetails.claimableOnCloseSats
val outboundCapacitySat = this.outboundCapacityMsat / 1000u
val ourReserve = this.unspendablePunishmentReserve ?: 0u

return outboundCapacitySat + ourReserve
}

/** Returns only `open` channels, filtering out pending ones. */
fun List<ChannelDetails>.filterOpen(): List<ChannelDetails> {
return this.filter { it.isChannelReady }
}
fun List<ChannelDetails>.filterOpen(): List<ChannelDetails> = this.filter { it.isChannelReady }

/** Returns only `pending` channels. */
fun List<ChannelDetails>.filterPending(): List<ChannelDetails> {
return this.filterNot { it.isChannelReady }
}
fun List<ChannelDetails>.filterPending(): List<ChannelDetails> = this.filterNot { it.isChannelReady }

/** Returns a limit in sats as close as possible to the HTLC limit we can currently send. */
fun List<ChannelDetails>?.totalNextOutboundHtlcLimitSats(): ULong {
return this?.filter { it.isUsable }
?.sumOf { it.nextOutboundHtlcLimitMsat / 1000u }
?: 0u
}
fun List<ChannelDetails>?.totalNextOutboundHtlcLimitSats(): ULong = this?.filter { it.isUsable }
?.sumOf { it.nextOutboundHtlcLimitMsat / 1000u }
?: 0u

/** Calculates the total remote balance (inbound capacity) from open channels. */
fun List<ChannelDetails>.calculateRemoteBalance(): ULong {
return this
.filterOpen()
.sumOf { it.inboundCapacityMsat / 1000u }
}
fun List<ChannelDetails>.calculateRemoteBalance(): ULong = this
.filterOpen()
.sumOf { it.inboundCapacityMsat / 1000u }

fun createChannelDetails(): ChannelDetails {
return ChannelDetails(
channelId = "channelId",
counterpartyNodeId = "counterpartyNodeId",
fundingTxo = null,
shortChannelId = null,
outboundScidAlias = null,
inboundScidAlias = null,
channelValueSats = 0u,
unspendablePunishmentReserve = null,
userChannelId = "0",
feerateSatPer1000Weight = 0u,
outboundCapacityMsat = 0u,
inboundCapacityMsat = 0u,
confirmationsRequired = null,
confirmations = null,
isOutbound = false,
isChannelReady = false,
isUsable = false,
isAnnounced = false,
cltvExpiryDelta = null,
counterpartyUnspendablePunishmentReserve = 0u,
counterpartyOutboundHtlcMinimumMsat = null,
counterpartyOutboundHtlcMaximumMsat = null,
counterpartyForwardingInfoFeeBaseMsat = null,
counterpartyForwardingInfoFeeProportionalMillionths = null,
counterpartyForwardingInfoCltvExpiryDelta = null,
nextOutboundHtlcLimitMsat = 0u,
nextOutboundHtlcMinimumMsat = 0u,
forceCloseSpendDelay = null,
inboundHtlcMinimumMsat = 0u,
inboundHtlcMaximumMsat = null,
config = ChannelConfig(
forwardingFeeProportionalMillionths = 0u,
forwardingFeeBaseMsat = 0u,
cltvExpiryDelta = 0u,
maxDustHtlcExposure = MaxDustHtlcExposure.FixedLimit(limitMsat = 0u),
forceCloseAvoidanceMaxFeeSatoshis = 0u,
acceptUnderpayingHtlcs = false,
),
)
}
fun createChannelDetails(): ChannelDetails = ChannelDetails(
channelId = "channelId",
counterpartyNodeId = "counterpartyNodeId",
fundingTxo = null,
shortChannelId = null,
outboundScidAlias = null,
inboundScidAlias = null,
channelValueSats = 0u,
unspendablePunishmentReserve = null,
userChannelId = "0",
feerateSatPer1000Weight = 0u,
outboundCapacityMsat = 0u,
inboundCapacityMsat = 0u,
confirmationsRequired = null,
confirmations = null,
isOutbound = false,
isChannelReady = false,
isUsable = false,
isAnnounced = false,
cltvExpiryDelta = null,
counterpartyUnspendablePunishmentReserve = 0u,
counterpartyOutboundHtlcMinimumMsat = null,
counterpartyOutboundHtlcMaximumMsat = null,
counterpartyForwardingInfoFeeBaseMsat = null,
counterpartyForwardingInfoFeeProportionalMillionths = null,
counterpartyForwardingInfoCltvExpiryDelta = null,
nextOutboundHtlcLimitMsat = 0u,
nextOutboundHtlcMinimumMsat = 0u,
forceCloseSpendDelay = null,
inboundHtlcMinimumMsat = 0u,
inboundHtlcMaximumMsat = null,
claimableOnCloseSats = 0u,
config = ChannelConfig(
forwardingFeeProportionalMillionths = 0u,
forwardingFeeBaseMsat = 0u,
cltvExpiryDelta = 0u,
maxDustHtlcExposure = MaxDustHtlcExposure.FixedLimit(limitMsat = 0u),
forceCloseAvoidanceMaxFeeSatoshis = 0u,
acceptUnderpayingHtlcs = false,
),
)
2 changes: 0 additions & 2 deletions app/src/main/java/to/bitkit/repositories/LightningRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -659,8 +659,6 @@ class LightningRepo @Inject constructor(
lnurlService.requestLnurlWithdraw(callbackUrl)
}

suspend fun fetchLnurlChannelInfo(url: String) = lnurlService.fetchLnurlChannelInfo(url)

suspend fun requestLnurlChannel(
k1: String,
callback: String,
Expand Down
4 changes: 1 addition & 3 deletions app/src/main/java/to/bitkit/services/CoreService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,8 @@ class CoreService @Inject constructor(
com.synonym.bitkitcore.isAddressUsed(address = address)
}

@Suppress("ForbiddenComment")
suspend fun decode(input: String): Scanner = ServiceQueue.CORE.background {
// TODO: Remove lowercase workaround when https://github.com/synonymdev/bitkit-core/issues/66 is fixed
com.synonym.bitkitcore.decode(input.lowercase())
com.synonym.bitkitcore.decode(input)
}

companion object {
Expand Down
23 changes: 0 additions & 23 deletions app/src/main/java/to/bitkit/services/LnurlService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,21 +63,6 @@ class LnurlService @Inject constructor(
return@runCatching response.body<LnurlPayResponse>()
}

suspend fun fetchLnurlChannelInfo(url: String): Result<LnurlChannelInfoResponse> = runCatching {
Logger.debug("Fetching LNURL channel info from: $url", context = TAG)

val response: HttpResponse = client.get(url)
Logger.debug("Http call: $response", context = TAG)

if (!response.status.isSuccess()) {
throw HttpError("fetchLnurlChannelInfo error: '${response.status.description}'", response.status.value)
}

return@runCatching response.body<LnurlChannelInfoResponse>()
}.onFailure {
Logger.warn("Failed to fetch channel info", it, context = TAG)
}

suspend fun requestLnurlChannel(url: String): Result<LnurlChannelResponse> = runCatching {
Logger.debug("Requesting LNURL channel request via: '$url'", context = TAG)

Expand Down Expand Up @@ -127,11 +112,3 @@ data class LnurlChannelResponse(
val status: String? = null,
val reason: String? = null,
)

@Serializable
data class LnurlChannelInfoResponse(
val uri: String,
val tag: String,
val callback: String,
val k1: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,11 @@ class LnurlChannelViewModel @Inject constructor(

private fun fetchChannelInfo() {
viewModelScope.launch {
lightningRepo.fetchLnurlChannelInfo(params.uri)
.onSuccess { channelInfo ->
val peer = runCatching { PeerDetails.of(channelInfo.uri) }.getOrElse {
errorToast(it)
return@onSuccess
}
_uiState.update { it.copy(peer = peer) }
}
.onFailure { error ->
val message = context.getString(R.string.other__lnurl_channel_error_raw)
.replace("{raw}", error.message.orEmpty())
errorToast(Exception(message))
}
val peer = runCatching { PeerDetails.of(params.uri) }.getOrElse {
errorToast(it)
return@launch
}
_uiState.update { it.copy(peer = peer) }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,7 @@ private fun PreviewAutoMode() {
forceCloseSpendDelay = null,
inboundHtlcMinimumMsat = 0uL,
inboundHtlcMaximumMsat = null,
claimableOnCloseSats = 0uL,
config = org.lightningdevkit.ldknode.ChannelConfig(
forwardingFeeProportionalMillionths = 0u,
forwardingFeeBaseMsat = 0u,
Expand Down Expand Up @@ -764,6 +765,7 @@ private fun PreviewSpendingMode() {
forceCloseSpendDelay = null,
inboundHtlcMinimumMsat = 0uL,
inboundHtlcMaximumMsat = null,
claimableOnCloseSats = 0uL,
config = org.lightningdevkit.ldknode.ChannelConfig(
forwardingFeeProportionalMillionths = 0u,
forwardingFeeBaseMsat = 0u,
Expand Down
16 changes: 10 additions & 6 deletions app/src/main/java/to/bitkit/utils/Logger.kt
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,18 @@ class LogSaverImpl(
}
}

private fun log(message: String, level: LogLevel = LogLevel.INFO) {
private fun log(
message: String,
level: LogLevel = LogLevel.INFO,
androidLog: (String, String) -> Unit = { tag, msg -> Log.i(tag, msg) },
) {
val formatted = formatLog(level, message, TAG, getCallerPath(), getCallerLine())
Log.i(APP, formatted)
androidLog(APP, formatted)
save(formatted)
}

private fun cleanupOldLogFiles(maxTotalSizeMB: Int = 20) {
log("Deleting old log files…", LogLevel.VERBOSE)
log("Deleting old log files…", LogLevel.VERBOSE, Log::v)
val logDir = runCatching { Env.logDir }.getOrNull() ?: return

val logFiles = logDir
Expand All @@ -263,15 +267,15 @@ class LogSaverImpl(
if (totalSize <= maxSizeBytes) return

runCatching {
Log.d(APP, "Deleting old log file: '${file.name}'")
log("Deleting old log file: '${file.name}'", LogLevel.DEBUG, Log::d)
if (file.delete()) {
totalSize -= file.length()
}
}.onFailure {
Log.w(APP, "Failed to delete old log file: '${file.name}'", it)
log("Failed to delete old log file: '${file.name}'", LogLevel.WARN, Log::w)
}
}
Log.v(APP, "Deleted all old log files.")
log("Deleted all old log files.", LogLevel.VERBOSE, Log::v)
}

companion object {
Expand Down
Loading
Loading