Files
archy/neode-ui/src/composables/useLightningRequired.ts
T

59 lines
2.2 KiB
TypeScript
Raw Normal View History

// Shared "this action needs a Lightning node" gate (2026-08-02).
//
// Creating a Lightning invoice with no Lightning node installed used to fail
// at the RPC layer — `lnd.createinvoice` returns a connection-refused error
// and the Receive screen showed it as a red failure string. That reads as the
// wallet being broken, when in fact the node simply has no Lightning
// implementation installed yet.
//
// Callers ask `requireLightningNode()` BEFORE attempting the call. When no
// node is installed it opens the global LightningRequiredModal (which offers
// to install one) and returns false, so the caller bails without surfacing an
// error at all.
//
// Detection is install-state, not reachability, on purpose: an installed node
// that is merely stopped or still starting is a different situation (wait or
// start it) and must NOT be answered with "install a Lightning node".
import { ref } from 'vue'
import { useAppStore } from '@/stores/app'
/** Package ids that provide a Lightning node.
*
* `lnd` ships today. Core Lightning is the next implementation the modal
* offers — when its app id lands in the catalog, add it here and flip its
* `available` flag in LightningRequiredModal so the same gate recognises it
* with no other change. */
export const LIGHTNING_NODE_APP_IDS = ['lnd'] as const
// Module-scope: one source of truth shared by every caller and the single
// global modal mounted in App.vue.
const show = ref(false)
export function useLightningRequired() {
const appStore = useAppStore()
/** True when some Lightning implementation is installed on this node. */
function hasLightningNode(): boolean {
const installed = Object.keys(appStore.packages ?? {})
return installed.some((pkgId) =>
(LIGHTNING_NODE_APP_IDS as readonly string[]).includes(pkgId),
)
}
/**
* Gate a Lightning-only action. Returns true to proceed; returns false and
* opens the install modal when this node has no Lightning implementation.
*/
function requireLightningNode(): boolean {
if (hasLightningNode()) return true
show.value = true
return false
}
function close() {
show.value = false
}
return { show, hasLightningNode, requireLightningNode, close }
}