Skip to content

Commit 4d95348

Browse files
committed
fix: accept cln-form order scid for closed channels
1 parent 37ee77d commit 4d95348

2 files changed

Lines changed: 25 additions & 12 deletions

File tree

app/src/main/java/to/bitkit/ext/ShortChannelId.kt

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,18 @@ fun ULong.formattedAsShortChannelId(): String {
1212
return "${blockHeight}x${txIndex}x$outputIndex"
1313
}
1414

15+
private val CLN_SHORT_CHANNEL_ID = Regex("""\d+x\d+x\d+""")
16+
1517
/**
16-
* Short channel id for display. Uses the channel's own scid (open channels) and, for closed
17-
* channels which carry none, the scid from the confidently-linked order. Null when unavailable.
18+
* Short channel id for display. Uses the channel's own scid (open channels, a numeric BOLT scid)
19+
* and, for closed channels which carry none, the scid from the confidently-linked Blocktank order.
20+
* Blocktank delivers it already in `block x tx x output` form, so an `x`-formatted value is kept
21+
* as-is and only a numeric value is decoded. Null when unavailable.
1822
*/
19-
internal fun resolveDisplayShortChannelId(channelScid: ULong?, linkedOrderScid: String?): String? =
20-
channelScid?.formattedAsShortChannelId()
21-
?: linkedOrderScid?.toULongOrNull()?.formattedAsShortChannelId()
23+
internal fun resolveDisplayShortChannelId(channelScid: ULong?, linkedOrderScid: String?): String? {
24+
channelScid?.let { return it.formattedAsShortChannelId() }
25+
26+
val orderScid = linkedOrderScid?.takeIf { it.isNotBlank() } ?: return null
27+
orderScid.toULongOrNull()?.let { return it.formattedAsShortChannelId() }
28+
return orderScid.takeIf { CLN_SHORT_CHANNEL_ID.matches(it) }
29+
}

app/src/test/java/to/bitkit/ext/ShortChannelIdTest.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,26 @@ class ShortChannelIdTest : BaseUnitTest() {
4141
}
4242

4343
@Test
44-
fun `resolveDisplayShortChannelId falls back to linked order scid for closed channel`() {
45-
val result = resolveDisplayShortChannelId(
46-
channelScid = null,
47-
linkedOrderScid = "854845001888432128",
48-
)
44+
fun `resolveDisplayShortChannelId keeps cln-form linked order scid for closed channel`() {
45+
// Blocktank delivers the order scid already in `block x tx x output` form.
46+
val result = resolveDisplayShortChannelId(channelScid = null, linkedOrderScid = "792906x599x1")
47+
assertEquals("792906x599x1", result)
48+
}
49+
50+
@Test
51+
fun `resolveDisplayShortChannelId decodes numeric linked order scid`() {
52+
val result = resolveDisplayShortChannelId(channelScid = null, linkedOrderScid = "854845001888432128")
4953
assertEquals("777477x916x0", result)
5054
}
5155

5256
@Test
5357
fun `resolveDisplayShortChannelId returns null when both unavailable`() {
5458
assertNull(resolveDisplayShortChannelId(channelScid = null, linkedOrderScid = null))
59+
assertNull(resolveDisplayShortChannelId(channelScid = null, linkedOrderScid = ""))
5560
}
5661

5762
@Test
58-
fun `resolveDisplayShortChannelId returns null for non-numeric order scid`() {
59-
assertNull(resolveDisplayShortChannelId(channelScid = null, linkedOrderScid = "not-a-number"))
63+
fun `resolveDisplayShortChannelId returns null for malformed order scid`() {
64+
assertNull(resolveDisplayShortChannelId(channelScid = null, linkedOrderScid = "not-a-scid"))
6065
}
6166
}

0 commit comments

Comments
 (0)