@nodeflow-network/nodeflow-node
v0.1.0
Published
Lightning Network Link - A comprehensive Lightning Network node management solution
Downloads
88
Maintainers
Readme
nodeflow-node
SDK library built on the Nostr Asset Protocol, integrating the Lightning Network Daemon (LND) and RGB nodes to expose Nostr-based functionality as a single coordinated Node.js class.
Install
npm install @nodeflow-network/nodeflow-node
# or
yarn add @nodeflow-network/nodeflow-nodeRequirements: Node.js ≥ 19. Runtime binaries (litd, rgb-lightning-node,
tor) ship inside the @nodeflow-network/nodeflow-bin transitive
dependency — no separate download step. Supported platforms:
darwin-arm64, linux-x64, win32-x64.
Quick start
const Nodeflow = require("@nodeflow-network/nodeflow-node")
const nodeflow = new Nodeflow({
name: "mynode",
owner: "npub1...",
network: "regtest",
dataPath: "/path/to/data",
})
await nodeflow.start()
// HTTP API now listening on nodeflow.getStatus().port (default 8090)
// ... on shutdown:
await nodeflow.stop()For Electron hosts (the main process owns signals / Cmd+Q):
const Nodeflow = require("@nodeflow-network/nodeflow-node")
const { app } = require("electron")
const nodeflow = new Nodeflow({
dataPath: app.getPath("userData"),
name: instanceName,
owner: userNpub,
network: "regtest",
httpPort: 8099,
})
// Skip installing OS signal handlers — let Electron own the lifecycle.
await nodeflow.start({ handleSignals: false })Env-var alternative — equivalent to the object form, using the NODEFLOW_*
convention:
const { Nodeflow, optionsFromEnv } = require("@nodeflow-network/nodeflow-node")
process.env.NODEFLOW_NAME = "mynode"
process.env.NODEFLOW_OWNER = "npub1..."
process.env.NODEFLOW_NETWORK = "regtest"
const nodeflow = new Nodeflow(optionsFromEnv())
await nodeflow.start()Configuration
All runtime configuration flows through camelCase constructor options.
Every option has a matching NODEFLOW_* environment variable.
Required
| Option | Env | Description |
|--------|-----|-------------|
| name | NODEFLOW_NAME | Logical node name (used for litd alias / TLS SAN / container name) |
| owner | NODEFLOW_OWNER | Owner Nostr public key, matches ^npub[a-z0-9]{59,}$ |
| network | NODEFLOW_NETWORK | regtest | testnet | mainnet |
Common options
| Option | Env | Default |
|--------|-----|---------|
| dataPath | NODEFLOW_DATA_PATH | ~/.nodeflow — root data dir; actual data lands under <dataPath>/<name>/<network>/ |
| httpPort | NODEFLOW_HTTP_PORT | 8090 |
| debug | NODEFLOW_DEBUG | false |
| enableTor | NODEFLOW_ENABLE_TOR | false |
| unlockPassword | NODEFLOW_UNLOCK_PASSWORD | (unset) — regtest/testnet only; forbidden on mainnet |
| databaseUrl | NODEFLOW_DATABASE_URL | derived — file:<dataPath>/<name>/<network>/.nodeflow/nodeflow.db |
| httpsProxy | NODEFLOW_HTTPS_PROXY | (unset) — HTTPS proxy forwarded to Tor for clearnet egress |
Service ports (rarely changed)
| Option | Env | Default |
|--------|-----|---------|
| lndRpcPort | NODEFLOW_LND_RPC_PORT | 10009 |
| lndPeerListenPort | NODEFLOW_LND_PEER_LISTEN_PORT | 9735 |
| rgbListeningPort | NODEFLOW_RGB_LISTENING_PORT | 3001 |
| rgbLdkPeerListeningPort | NODEFLOW_RGB_LDK_PEER_LISTENING_PORT | 9736 |
| rgbHost | NODEFLOW_RGB_HOST | (unset) — public announce host for RGB peers |
Port collisions are resolved by assignAvailablePorts(): default ports auto-
shift to the next free slot; explicitly-specified ports throw
ForeignProcessOnPortError when held by a foreign process.
Backend + network profile
Per-network defaults (Bitcoind RPC, RGB peers, Nostr relays, Taproot assets
oracle) load automatically from the built-in network profile. Override any
of them via the matching NODEFLOW_* env var or constructor option if needed.
See the full constructor vocabulary at the NODEFLOW_OPTION_KEYS export.
Behavior notes
Identity immutability
Once an instance completes first-run (DB row with owner_npub + node_npub),
its identity is immutable:
- Changing
owner/networkon restart → WARN + DB value wins - Changing
name/dataPath→RoutingMismatchError, process exits - Changing a mutable field (e.g.
httpPort,enableTor) → input wins, WARN logged, persisted
To truly change identity, stop the process and construct a fresh instance with
a new name or dataPath.
Database lifecycle
The package owns its schema. Embedding apps must not run their own Prisma
migrations — nodeflow.start() triggers _ensureDatabaseSetup():
- Creates
<dataPath>/<name>/<network>/.nodeflow/if missing - Applies any pending migrations programmatically (no
prismaCLI) - Fail-closes with
error.classification = "migration"on migration error
prisma generate runs once at install time via the postinstall hook.
Lockfile semantics
<instancePath>/.nodeflow/instance.lock prevents two Nodeflow instances
from sharing a data dir. start() acquires, stop() releases. Stale locks
(dead PID, or same-PID-but-older-than-this-process — the Docker pid=1
restart case) are recovered automatically.
Exports
const {
Nodeflow, // main class
optionsFromEnv, // read NODEFLOW_* env vars → camelCase options
NODEFLOW_OPTION_KEYS, // array of supported option keys
INFO_RESPONSE_KEYS, // subset exposed via /api/lnd/info
} = require("@nodeflow-network/nodeflow-node")License
MIT.
