Skip to content

Commit b176b92

Browse files
authored
Merge pull request #940 from synonymdev/feat/mainnet-probe-devtools
test: add mainnet probe devtools
2 parents 6fddaf5 + 93fd5ab commit b176b92

2 files changed

Lines changed: 97 additions & 1 deletion

File tree

app/src/debug/java/to/bitkit/dev/DevToolsProvider.kt

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@ import dagger.hilt.components.SingletonComponent
1414
import kotlinx.serialization.Serializable
1515
import kotlinx.serialization.json.Json
1616
import to.bitkit.async.ServiceQueue
17+
import to.bitkit.models.msatCeilOf
1718
import to.bitkit.repositories.LightningRepo
19+
import to.bitkit.repositories.ProbeOutcome
1820
import to.bitkit.utils.Logger
21+
import kotlin.time.Duration.Companion.seconds
1922

2023
private const val TAG = "DevToolsProvider"
24+
private val DEV_JSON = Json { encodeDefaults = true }
2125

2226
class DevToolsProvider : ContentProvider() {
2327

@@ -56,6 +60,7 @@ private sealed interface DevCommand {
5660
companion object {
5761
fun parse(method: String, arg: String?): DevCommand? = when (method) {
5862
CreateInvoice.METHOD -> CreateInvoice.parse(arg)
63+
ProbeInvoice.METHOD -> ProbeInvoice.parse(arg)
5964
else -> null
6065
}
6166
}
@@ -80,6 +85,44 @@ private sealed interface DevCommand {
8085
},
8186
)
8287
}
88+
89+
data class ProbeInvoice(val args: Args) : DevCommand {
90+
companion object {
91+
const val METHOD = "probeInvoice"
92+
fun parse(arg: String?) = ProbeInvoice(arg.deserialize<Args>())
93+
}
94+
95+
@Serializable
96+
data class Args(
97+
val targetName: String? = null,
98+
val bolt11: String,
99+
val amountMsat: ULong? = null,
100+
val amountSats: ULong? = null,
101+
val timeoutSeconds: Long = 90,
102+
)
103+
104+
override suspend fun execute(deps: DevToolsProvider.Dependencies): DevResult {
105+
val amountSats = args.amountSats ?: args.amountMsat?.let { msatCeilOf(it) }
106+
val timeout = args.timeoutSeconds.coerceAtLeast(1).seconds
107+
108+
Logger.info(
109+
"Sending probe for target '${args.targetName ?: "unknown"}' amountSats='${amountSats ?: "invoice"}'",
110+
context = TAG,
111+
)
112+
113+
return deps.lightningRepo().sendProbeForInvoice(args.bolt11, amountSats)
114+
.fold(
115+
onSuccess = {
116+
deps.lightningRepo().waitForProbeOutcome(it.paymentIds, timeout)
117+
.fold(
118+
onSuccess = { outcome -> outcome.toDevResult(it.paymentIds) },
119+
onFailure = { error -> DevResult.ProbeFailure.from(error, it.paymentIds) },
120+
)
121+
},
122+
onFailure = { DevResult.ProbeFailure.from(it) },
123+
)
124+
}
125+
}
83126
}
84127

85128
@Serializable
@@ -91,9 +134,49 @@ private sealed interface DevResult {
91134

92135
@Serializable data class Invoice(val bolt11: String) : DevResult
93136

137+
@Serializable
138+
data class ProbeSuccess(
139+
val success: Boolean = true,
140+
val paymentId: String,
141+
val paymentHash: String,
142+
val paymentIds: List<String>,
143+
) : DevResult
144+
145+
@Serializable
146+
data class ProbeFailure(
147+
val success: Boolean = false,
148+
val message: String? = null,
149+
val paymentId: String? = null,
150+
val paymentHash: String? = null,
151+
val shortChannelId: ULong? = null,
152+
val paymentIds: List<String> = emptyList(),
153+
) : DevResult {
154+
companion object {
155+
fun from(error: Throwable, paymentIds: Set<String> = emptySet()) = ProbeFailure(
156+
message = error.message,
157+
paymentIds = paymentIds.toList(),
158+
)
159+
}
160+
}
161+
94162
@Serializable data class Error(val message: String? = null) : DevResult
95163

96-
fun toBundle() = bundleOf(KEY_RESULT to Json.encodeToString(this))
164+
fun toBundle() = bundleOf(KEY_RESULT to DEV_JSON.encodeToString(this))
165+
}
166+
167+
private fun ProbeOutcome.toDevResult(paymentIds: Set<String>): DevResult = when (this) {
168+
is ProbeOutcome.Success -> DevResult.ProbeSuccess(
169+
paymentId = paymentId,
170+
paymentHash = paymentHash,
171+
paymentIds = paymentIds.toList(),
172+
)
173+
is ProbeOutcome.Failure -> DevResult.ProbeFailure(
174+
message = "Probe failed",
175+
paymentId = paymentId,
176+
paymentHash = paymentHash,
177+
shortChannelId = shortChannelId,
178+
paymentIds = paymentIds.toList(),
179+
)
97180
}
98181

99182
private inline fun <reified T> String?.deserialize(): T =

app/src/test/java/to/bitkit/repositories/LightningRepoTest.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,19 @@ class LightningRepoTest : BaseUnitTest() {
13461346
assertEquals(setOf(probePaymentA, probePaymentB), result.getOrThrow().paymentIds)
13471347
}
13481348

1349+
@Test
1350+
fun `sendProbeForInvoice delegates amount probes when sats are provided`() = test {
1351+
startNodeForTesting()
1352+
whenever(lightningService.sendProbesUsingAmount("lnbc1", 42_000uL))
1353+
.thenReturn(Result.success(setOf(probePaymentA)))
1354+
1355+
val result = sut.sendProbeForInvoice("lnbc1", amountSats = 42uL)
1356+
1357+
assertTrue(result.isSuccess)
1358+
assertEquals(setOf(probePaymentA), result.getOrThrow().paymentIds)
1359+
verify(lightningService).sendProbesUsingAmount("lnbc1", 42_000uL)
1360+
}
1361+
13491362
@Test
13501363
fun `sendProbeForNode delegates to keysend probe and returns payment IDs`() = test {
13511364
startNodeForTesting()

0 commit comments

Comments
 (0)