npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@coinexams/lightning

v1.1.4

Published

Self-custodial Bitcoin Lightning Network client for Node.js — invoices, payments, balances, LNURL-pay addresses and Nostr Zap receipts via a local Phoenixd node.

Readme

@coinexams/lightning

A self-custodial Bitcoin Lightning Network client for Node.js that wraps a local Phoenixd node REST API — create invoices, send Lightning and on-chain payments, query balances and history, resolve LNURL-pay requests, and publish Nostr Zap receipts.

npm version npm downloads license node

Table of Contents

Why @coinexams/lightning

  • Self-custodial — talks only to your own local Phoenixd node over localhost; no third-party custodian.
  • Zero protocol plumbing — invoices, payments, LNURL-pay, and Nostr kind-9735 Zap receipts behind one small client.
  • TypeScript first — every request, response, and enum is typed and shipped as dist/index.d.ts.
  • Nostr native — sign Zap receipts, resolve sender relays, and publish to a preset relay list out of the box.
  • Resilient — invoice creation auto-recovers a stalled node, request timeouts are capped, and concurrent restarts are coordinated.
  • Tiny surface — a single startLightning() factory plus a handful of helpers, with no runtime framework lock-in.

Install

npm install @coinexams/lightning
yarn add @coinexams/lightning
pnpm add @coinexams/lightning

Node.js >=18. This is a Node-only package (it uses node:child_process and Buffer); there is no browser bundle or CDN build.

Quick Start

1. Setup Phoenixd

Install, configure, and start a local Phoenixd node as a systemd service (requires Linux with systemd and sudo):

npx @coinexams/lightning setup
# Optional: --seed "<12-or-24-word phrase>" --port 9740

On success the CLI prints the ready port and persists the credentials Phoenixd generated.

2. Connect and pay

import { startLightning, nsecToBytes, npubToHex } from "@coinexams/lightning";

const client = startLightning({
  serverPrvKeyBytes: nsecToBytes("nsec1..."),
  serverPubKeyHex: npubToHex("npub1..."),
});

// Full zap workflow: build an invoice, poll until paid, publish a kind-9735 receipt
const zap = client.zapProcess({
  lnAddress: `[email protected]`,
  amountMsat: 100_000,
  nostrEvent: `<zap-request-json>`,
});
// → { invoice: { pr: "lnbc...", routes: [] }, invoiceId: "..." }

Configuration

startLightning(options) returns a LightningClient, or undefined when the Phoenixd credentials cannot be loaded.

| Option | Type | Default | Description | | ------------------- | ------------ | ------------- | ------------------------------------------------------------------ | | serverPrvKeyBytes | Uint8Array | — | Server Nostr private key used to sign Zap receipts (kind 9735). | | serverPubKeyHex | string | — | Server Nostr public key in hex, set as the receipt pubkey. | | defaultRelays | string[] | RELAYS_LIST | Extra relays used when a Zap request carries no relays tag. | | cacheDurationMs | number | 500 | Cache window for read-only fundsData responses, in milliseconds. |

Reads http-password and http-bind-port from the Phoenixd config on disk, so the node must be installed and running before calling startLightning.

Exports

Functions and values

| Export | Signature | Returns | Description | | -------------------------------------- | ---------------------------------------- | -------------------------- | ---------------------------------------------------------------------------- | | startLightning | (options) => LightningClient | LightningClient \| undefined | Create a client bound to the local Phoenixd node. | | msatToSat | (msat) => number | number | Convert millisatoshis to satoshis; 0 on invalid input. | | isLightningAddress | RegExp | — | Matches user@domain Lightning addresses. | | RELAYS_LIST | string[] | — | Preset list of Nostr relay URLs used as the default for defaultRelays. | | npubToHex | (npub) => string | string | Convert an npub/nprofile bech32 key to hex; empty string on failure. | | nsecToHex | (nsec) => string | string | Convert an nsec bech32 key to a hex private key; empty string on failure. | | hexToBytes | (hex) => Uint8Array | Uint8Array \| undefined | Convert a hex string to bytes; undefined on failure. | | nsecToBytes | (nsec) => Uint8Array | Uint8Array \| undefined | Convert an nsec bech32 key directly to bytes; undefined on failure. |

Enums

| Export | Members | Description | | ------------------ | ------------------------------------------------------------ | ----------------------------------------------------------------- | | PaymentDirection | Incoming ("incoming"), Outgoing ("outgoing") | Selects the payment direction for invoiceStatus. | | LNDataType | GetBalance, GetInfo, PaymentsIncoming, PaymentsOutgoing | Common Phoenixd endpoints for fundsData type values. |

Types

IncomingPayment, OutgoingPayment, SentPayment, LNBalance, PaymentInvoiceDetails, PaymentMakeRequest, PaymentNewRequest, LNDataParams, ZapRequest, ZapRequestResponse, ZapSignRequest, ZapSignResponse, ZapPublishRequest, UserStoredPayment, UserSeverData.

Client methods

All methods return undefined on failure and log via console.error with an ISO timestamp prefix. Optional maxTime (seconds) caps the underlying curl request; it defaults to 1 second.

| Method | Signature | Returns | Description | | --------------- | ------------------------------------------------------------------ | ---------------------------------------- | ----------------------------------------------------------------- | | invoiceNew | ({ amountSat, description?, maxTime? }) | PaymentInvoiceDetails \| undefined | Create an invoice to receive funds. | | invoiceStatus | ({ invoiceId, type }) | IncomingPayment \| OutgoingPayment \| undefined | Look up a payment by hash. | | fundsWithdraw | ({ amountSat, address, feeRateSatByte?, maxTime? }) | SentPayment \| undefined | Send to a Lightning address or on-chain address (auto-detected). | | fundsData | <T>({ type, params?, maxTime? }) | T \| undefined | Query any Phoenixd REST endpoint and cache the result. | | fundsBalance | () | LNBalance \| undefined | On-chain and Lightning balance summary. | | fundsIncoming | (count?) | IncomingPayment[] \| undefined | Recent incoming payments (default 30). | | fundsOutgoing | (count?) | OutgoingPayment[] \| undefined | Recent outgoing payments (default 30). | | zapProcess | ({ lnAddress, amountMsat, nostrEvent }) | ZapRequestResponse \| undefined | Create a Zap invoice and publish its receipt once paid. |

invoiceNew validates amountSat, and if Phoenixd fails to issue the invoice it restarts the node and retries once.

Invoices

// Create an invoice to receive funds
const invoice = client.invoiceNew({ amountSat: 1000, description: "test" });
// → { invoiceString: "lnbc1...", invoiceId: "abc..." }

// Check if it has been paid
import { PaymentDirection } from "@coinexams/lightning";

const payment = client.invoiceStatus({
  invoiceId: "abc...",
  type: PaymentDirection.Incoming,
});
// → IncomingPayment | OutgoingPayment | undefined

Payments

// Lightning address (auto-detected by address format)
const sent = client.fundsWithdraw({
  amountSat: 500,
  address: "[email protected]",
});
// → { recipientAmountSat: 500, paymentHash: "...", ... }

// On-chain address (auto-detected by address format)
const onchain = client.fundsWithdraw({
  amountSat: 10000,
  address: "bc1...",
});

// Full balance details
const balance = client.fundsBalance();
// → { balanceSat: 50000, feeCreditSat: 100 }

// Recent incoming and outgoing payments
const incoming = client.fundsIncoming(10);
const outgoing = client.fundsOutgoing(10);

// Custom data query
const data = client.fundsData({
  type: "payments/incoming",
  params: { limit: 10 },
});

Nostr Zaps

zapProcess ties the whole flow together: it requests an invoice for the given amountMsat, signs a Zap request with the configured server key, and polls until the invoice is paid before publishing a kind-9735 receipt to the sender's relays plus defaultRelays.

const result = client.zapProcess({
  lnAddress: `[email protected]`,
  amountMsat: 100_000,
  nostrEvent: `<zap-request-json>`,
});

if (!result) throw new Error("zap failed");
// result.invoice.pr → "lnbc..."
// result.invoiceId   → "..." use with invoiceStatus to confirm settlement

Error handling

  • Every method returns undefined on failure instead of throwing.
  • Failures are logged as console.error(<ISO timestamp>, "<method> failed", <error>).
  • Check the return value at the call site to detect a failure.

CLI setup

The package ships a celightning binary that installs, configures, and starts Phoenixd as a systemd service:

npx @coinexams/lightning setup
npx @coinexams/lightning setup --seed "<12-or-24-word phrase>" --port 9740
npx @coinexams/lightning --version
npx @coinexams/lightning --help

Requires Linux with systemd, sudo, and the ability to install wget, unzip, curl, and jq.

FAQ

What is @coinexams/lightning? A Node.js SDK that wraps a local Phoenixd node, exposing invoices, payments, balances, LNURL-pay, and Nostr Zap receipts through one typed client.

Is it free? Yes. It is open source under the Apache-2.0 license. You pay only Bitcoin network/Lightning routing fees to your own node.

Does it work in the browser? No. It is a Node-only package: it shells out via node:child_process and uses Buffer, and it needs a local Phoenixd node on localhost.

What are the dependencies? bech32 for Nostr key encoding and nostr-tools for event signing, verification, and relay publishing.

Is it TypeScript? Yes. It is written in TypeScript and ships complete declarations at dist/index.d.ts.

Which frameworks does it support? Any Node.js >=18 runtime — Express, Fastify, NestJS, serverless handlers, or plain scripts.

Do I need to run Phoenixd separately? Yes. npx @coinexams/lightning setup installs and starts it for you, or you can point the SDK at an existing local Phoenixd instance.

Keywords

Bitcoin, Lightning Network, Phoenixd, self-custodial, Lightning invoice, LNURL-pay, Nostr, Nostr Zap, kind-9735, zap receipt, bech32, npub, nsec, Node.js SDK, TypeScript SDK, on-chain payment, payment SDK.

License

Apache-2.0 © CoinExams