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

@lnbot/sdk

v1.0.0

Published

Official TypeScript SDK for LnBot — Bitcoin for AI Agents. Send and receive sats over Lightning with a few lines of code. Zero dependencies.

Readme

@lnbot/sdk

npm version npm downloads bundle size TypeScript License: MIT

The official TypeScript SDK for ln.bot — Bitcoin for AI Agents.

Give your AI agents, apps, and services access to Bitcoin over the Lightning Network. Create wallets, send and receive sats, and get real-time payment notifications — all in a few lines of code.

import { LnBot } from "@lnbot/sdk";

const client = new LnBot({ apiKey: "uk_..." });
const wallet = client.wallet("wal_...");

await wallet.payments.create({ target: "[email protected]", amount: 1000 });

ln.bot also ships a Python SDK, Go SDK, Rust SDK, CLI, and MCP server.


Why ln.bot?

  • Built for agents — programmatic wallets, API keys, and idempotent payments designed for autonomous software
  • Instant settlement — payments arrive in seconds, not days
  • Lightning addresses — human-readable addresses like [email protected]
  • Real-time events — SSE streams and webhooks for payment notifications
  • Recovery built in — 12-word BIP-39 passphrase and passkey backup
  • Simple pricing — no monthly fees, pay only when you move sats off-network

Why this SDK?

  • Zero dependencies — native fetch (Node 18+, Bun, Deno, browsers)
  • Fully typed — every request, response, and error has TypeScript types
  • Tiny — under 10 KB minified + gzipped
  • Dual format — ESM + CJS with source maps and .d.ts declarations
  • Wallet-scopedclient.wallet("wal_...").invoices.create() — clean, explicit, no ambiguity

Install

npm install @lnbot/sdk
pnpm add @lnbot/sdk
yarn add @lnbot/sdk

Quick start

1. Register and create a wallet

import { LnBot } from "@lnbot/sdk";

// Register a new account (no auth needed)
const client = new LnBot();
const account = await client.register();

console.log(account.primaryKey);         // user key (uk_...)
console.log(account.recoveryPassphrase); // back this up!

// Create a wallet using your user key
const authed = new LnBot({ apiKey: account.primaryKey });
const wallet = await authed.wallets.create();

console.log(wallet.walletId); // wal_...
console.log(wallet.address);  // your Lightning address

2. Receive sats

const client = new LnBot({ apiKey: "uk_..." });
const w = client.wallet("wal_...");

const invoice = await w.invoices.create({
  amount: 1000,
  memo: "Payment for task #42",
});

console.log(invoice.bolt11); // share with the payer

3. Wait for payment (SSE)

// SSE requires a wallet key (wk_...)
const wkClient = new LnBot({ apiKey: "wk_..." });
const w = wkClient.wallet("wal_...");

for await (const event of w.invoices.watch(invoice.number)) {
  if (event.event === "settled") {
    console.log("Paid!", event.data.preimage);
    break;
  }
}

4. Send sats

const w = client.wallet("wal_...");

// To a Lightning address
await w.payments.create({ target: "[email protected]", amount: 500 });

// To a BOLT11 invoice
await w.payments.create({ target: "lnbc10u1p..." });

5. Check balance

const info = await client.wallet("wal_...").get();
console.log(`${info.available} sats available`);

Authentication

ln.bot uses two key types:

  • User key (uk_...) — manages all wallets under your account. Use for creating wallets, listing wallets, rotating user keys.
  • Wallet key (wk_...) — scoped to a single wallet. Use for SSE streams, or to give a service access to one wallet only.
// User key — full account access
const client = new LnBot({ apiKey: "uk_..." });
const w1 = client.wallet("wal_abc");
const w2 = client.wallet("wal_xyz");

// Wallet key — single wallet
const wkClient = new LnBot({ apiKey: "wk_..." });
const w = wkClient.wallet("current"); // "current" resolves to the key's wallet

Wallet keys

const w = client.wallet("wal_...");

// Create (one key per wallet)
const key = await w.key.create();
console.log(key.key); // wk_... — shown once

// Get metadata
const info = await w.key.get();

// Rotate (old key invalidated immediately)
const rotated = await w.key.rotate();

// Delete
await w.key.delete();

Addresses

Every wallet gets a Lightning address on creation. Create more or claim vanity addresses:

const w = client.wallet("wal_...");

const random = await w.addresses.create();
const vanity = await w.addresses.create({ address: "myagent" });
const all    = await w.addresses.list();

await w.addresses.delete("[email protected]");

// Transfer a vanity address to another wallet
await w.addresses.transfer("[email protected]", {
  targetWalletKey: "wk_other_wallet_key",
});

Transactions

Full history of credits and debits:

const txs = await client.wallet("wal_...").transactions.list({ limit: 20 });

for (const tx of txs) {
  console.log(`${tx.type} ${tx.amount} sats — balance: ${tx.balanceAfter}`);
}

Webhooks

Get notified when invoices are paid:

const w = client.wallet("wal_...");

const hook = await w.webhooks.create({
  url: "https://example.com/webhooks/lnbot",
});
// hook.secret — save this for signature verification. Only returned once.

const hooks = await w.webhooks.list();
await w.webhooks.delete(hook.id);

Public invoices (no auth)

Create invoices for any wallet or address without authentication:

const client = new LnBot(); // no API key needed

const inv = await client.invoices.createForWallet({
  walletId: "wal_...",
  amount: 100,
});

const inv2 = await client.invoices.createForAddress({
  address: "[email protected]",
  amount: 100,
});

User keys

const rotated = await client.keys.rotate(0); // 0 = primary, 1 = secondary
// rotated.key — new plaintext key, shown once

Backup & restore

Recovery passphrase

const backup = await client.backup.recovery();
// backup.passphrase — 12-word BIP-39, shown once

const restored = await client.restore.recovery({
  passphrase: "word1 word2 ... word12",
});
// restored.primaryKey, restored.secondaryKey — fresh keys

Passkey (WebAuthn)

const begin = await client.backup.passkeyBegin();
// pass begin.options to navigator.credentials.create()

await client.backup.passkeyComplete({
  sessionId: begin.sessionId,
  attestation: credential,
});

L402 paywalls

Monetize APIs with Lightning-native authentication:

const w = client.wallet("wal_...");

// Create a challenge (server side)
const challenge = await w.l402.createChallenge({
  amount: 100,
  description: "API access",
  expirySeconds: 3600,
});

// Pay the challenge (client side)
const other = otherClient.wallet("wal_...");
const result = await other.l402.pay({
  wwwAuthenticate: challenge.wwwAuthenticate,
});

// Verify a token (server side, stateless)
const { valid } = await w.l402.verify({
  authorization: result.authorization!,
});

SSE event streams

Watch a single invoice

for await (const event of w.invoices.watch(invoiceNumber, 120)) {
  // event.event: "pending" | "settled" | "expired"
  // event.data: InvoiceResponse
}

Watch a single payment

for await (const event of w.payments.watch(paymentNumber, 60)) {
  // event.event: "processing" | "settled" | "failed"
  // event.data: PaymentResponse
}

Stream all wallet events

const controller = new AbortController();

for await (const event of w.events.stream(controller.signal)) {
  // event.event: "invoice.created" | "invoice.settled" | "payment.created" | ...
  console.log(event.event, event.data);
}

SSE streams require wallet key (wk_...) authentication.

Pagination

All list endpoints support cursor-based pagination:

const page1 = await w.invoices.list({ limit: 10 });

const page2 = await w.invoices.list({
  limit: 10,
  after: page1[page1.length - 1].number,
});

Works the same for w.payments.list() and w.transactions.list().

Error handling

All API errors throw typed exceptions:

import {
  LnBotError,
  BadRequestError,
  UnauthorizedError,
  ForbiddenError,
  NotFoundError,
  ConflictError,
} from "@lnbot/sdk";

try {
  await w.payments.create({ target: "invalid", amount: 100 });
} catch (err) {
  if (err instanceof BadRequestError) {
    // 400 — validation failed
  } else if (err instanceof UnauthorizedError) {
    // 401 — invalid or missing API key
  } else if (err instanceof ForbiddenError) {
    // 403 — key doesn't have access
  } else if (err instanceof NotFoundError) {
    // 404 — resource not found
  } else if (err instanceof ConflictError) {
    // 409 — duplicate or conflict
  } else if (err instanceof LnBotError) {
    // Other API error
    console.error(err.status, err.body);
  }
}

Configuration

import { LnBot } from "@lnbot/sdk";

const client = new LnBot({
  apiKey: "uk_...",                  // optional — not needed for register or public invoices
  baseUrl: "https://api.ln.bot",     // optional — this is the default
  fetch: customFetch,                // optional — bring your own fetch for testing or proxies
});

API reference

Top-level

| Method | Description | | --- | --- | | client.register() | Create a new account (no auth) | | client.me() | Get current identity | | client.wallet(id) | Get a wallet handle for scoped operations | | client.wallets.create() | Create a new wallet (user key) | | client.wallets.list() | List all wallets (user key) | | client.keys.rotate(slot) | Rotate user key (0 = primary, 1 = secondary) | | client.invoices.createForWallet(req) | Create invoice by wallet ID (no auth) | | client.invoices.createForAddress(req) | Create invoice by Lightning address (no auth) | | client.backup.recovery() | Generate 12-word recovery passphrase | | client.restore.recovery(req) | Restore with recovery passphrase |

Wallet-scoped (client.wallet("wal_..."))

| Method | Description | | --- | --- | | w.get() | Get wallet info and balance | | w.update(req) | Update wallet name |

Wallet key (w.key)

| Method | Description | | --- | --- | | w.key.create() | Create wallet key (max 1 per wallet) | | w.key.get() | Get key metadata | | w.key.rotate() | Rotate key (old key invalidated) | | w.key.delete() | Delete/revoke key |

Invoices (w.invoices)

| Method | Description | | --- | --- | | w.invoices.create(req) | Create a BOLT11 invoice | | w.invoices.list(params?) | List invoices | | w.invoices.get(numberOrHash) | Get invoice by number or payment hash | | w.invoices.watch(numberOrHash, timeout?) | SSE stream for invoice status |

Payments (w.payments)

| Method | Description | | --- | --- | | w.payments.create(req) | Send sats to address or invoice | | w.payments.list(params?) | List payments | | w.payments.get(numberOrHash) | Get payment by number or hash | | w.payments.resolve(params) | Inspect a target without sending | | w.payments.watch(numberOrHash, timeout?) | SSE stream for payment status |

Addresses (w.addresses)

| Method | Description | | --- | --- | | w.addresses.create(req?) | Create random or vanity address | | w.addresses.list() | List all addresses | | w.addresses.delete(address) | Delete an address | | w.addresses.transfer(address, req) | Transfer vanity address to another wallet |

Transactions (w.transactions)

| Method | Description | | --- | --- | | w.transactions.list(params?) | List credit and debit transactions |

Webhooks (w.webhooks)

| Method | Description | | --- | --- | | w.webhooks.create(req) | Register a webhook endpoint (max 10) | | w.webhooks.list() | List all webhooks | | w.webhooks.delete(id) | Delete a webhook |

L402 (w.l402)

| Method | Description | | --- | --- | | w.l402.createChallenge(req) | Create L402 challenge (invoice + macaroon) | | w.l402.verify(req) | Verify L402 authorization token | | w.l402.pay(req) | Pay L402 challenge, get authorization header |

Events (w.events)

| Method | Description | | --- | --- | | w.events.stream(signal?) | SSE stream of all wallet events |


Requirements

  • Node.js 18+, Bun, Deno, or any environment with a global fetch
  • Get your API key at ln.bot

Other interfaces

ln.bot isn't just an SDK — pick the interface that fits your stack:

  • CLIlnbot pay lnbc1...f3q --amount 1000
  • MCP Server — Model Context Protocol for AI agents
  • REST API — direct HTTP calls

Links

Other SDKs

License

MIT