fix(lightning): channel open raced async peer connect, errors were swallowed

- Connect to peer synchronously (perm=false, 30s timeout) and check the
  result before opening the channel; previously the connect was fired
  with perm=true (queued in background, returns immediately) and its
  result ignored, so the open failed with 'peer is not online'
- Let LND channel/peer errors through the error sanitizer so the UI
  shows the real cause instead of 'Check server logs'
- Add private (unannounced) channel option to backend and UI — some
  peers (e.g. Olympus/ZEUS LSP) reject public channel opens

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-07-10 15:04:13 +01:00
co-authored by Claude Fable 5
parent e56c5af3ba
commit c141a733b4
3 changed files with 51 additions and 9 deletions
+12 -4
View File
@@ -155,6 +155,13 @@
/>
<p class="text-white/40 text-xs mt-1">Minimum 20,000 sats</p>
</div>
<div>
<label class="flex items-center gap-2 cursor-pointer">
<input v-model="openForm.private" type="checkbox" class="accent-blue-500" />
<span class="text-white/60 text-sm">Private channel (unannounced)</span>
</label>
<p class="text-white/40 text-xs mt-1">Some nodes (e.g. LSPs like Olympus) only accept unannounced channels</p>
</div>
</div>
<div v-if="openError" class="mt-3 alert-error">
@@ -221,7 +228,7 @@ const channels = ref<Channel[]>([])
const summary = ref({ total_inbound: 0, total_outbound: 0 })
const showOpenModal = ref(false)
const openForm = ref({ peerUri: '', amount: 100000 })
const openForm = ref({ peerUri: '', amount: 100000, private: false })
const openingChannel = ref(false)
const openError = ref<string | null>(null)
@@ -279,11 +286,12 @@ async function openChannel() {
try {
await rpcClient.call({
method: 'lnd.openchannel',
params: { pubkey, address, amount: openForm.value.amount },
timeout: 30000,
params: { pubkey, address, amount: openForm.value.amount, private: openForm.value.private },
// Server may wait up to 35s for a synchronous peer connect before opening
timeout: 60000,
})
showOpenModal.value = false
openForm.value = { peerUri: '', amount: 100000 }
openForm.value = { peerUri: '', amount: 100000, private: false }
await loadChannels()
} catch (err: unknown) {
openError.value = err instanceof Error ? err.message : 'Failed to open channel'