Package Exports
- lightning-auth-and-payment
- lightning-auth-and-payment/dev
Readme
โก Lightning Auth & Payment
The complete Lightning Network authentication and payment solution for modern web applications
Build Lightning Network-powered applications with ease. From simple single-page shops to complex eCommerce platforms, Lightning Auth & Payment provides everything you need for Lightning Network integration.
๐ Quick Start
npm install lightning-auth-and-paymentEnvironment Setup
Create .env.local:
# Session Configuration
SESSION_SECRET=your-super-secret-session-key-here
SESSION_COOKIE_DOMAIN=localhost
# BTCPay Server Configuration
BTCPAY_HOST=https://your-btcpay-server.com
BTCPAY_STORE_ID=your-store-id
BTCPAY_API_KEY=your-api-key
BTCPAY_WEBHOOK_SECRET=your-webhook-secret
# Application Configuration
NEXT_PUBLIC_APP_URL=https://your-app.com
NODE_ENV=developmentBasic Usage
import {
LightningAuth,
createBTCPayClientFromEnv,
useLightningAuth,
useLightningPayment,
} from "lightning-auth-and-payment";
// Lightning authentication
const auth = new LightningAuth({
sessionSecret: process.env.SESSION_SECRET!,
sessionCookieDomain: process.env.SESSION_COOKIE_DOMAIN,
});
// BTCPay Server integration
const btcpay = createBTCPayClientFromEnv();
// React hooks
function App() {
const { isAuthenticated, login, logout, user } = useLightningAuth();
const { createInvoice, paymentState, timeLeft } = useLightningPayment();
return (
<div>
{isAuthenticated ? (
<button onClick={logout}>Logout {user?.userId}</button>
) : (
<button onClick={login}>Login with Lightning</button>
)}
</div>
);
}โก Lightning-fast setup. Lightning Network payments. Lightning authentication.
๐ Prerequisites
Required
- BTCPay Server - For payment processing
- Node.js 18+ - Runtime environment
- Lightning Network wallet - For authentication and payments
Recommended for Development
- ngrok - For LN-auth in development (Lightning wallets require HTTPS)
- Lightning wallet (Phoenix, Breez, Zeus, etc.)
BTCPay Server Setup
Install BTCPay Server:
- Use BTCPay Server Docker for easy setup
- Or use BTCPay Server VPS for production
Configure Lightning Network (Recommended Easy Setup):
- Easiest Method: Install the Boltz plugin together with the SamRock protocol plugin and Aqua Wallet
- This setup provides a complete Lightning payment solution with minimal configuration
- Perfect for VPS deployments and development environments
- Alternative: Connect to a Lightning node (LND, c-lightning, or Eclair) manually
Get API Credentials:
- Create a new API key in BTCPay Server
- Note your Store ID and Webhook Secret
Development with ngrok
For Lightning authentication in development:
# Install ngrok
npm install -g ngrok
# Start your app
npm run dev
# In another terminal, expose your local server
ngrok http 3000Use the HTTPS URL from ngrok for your NEXT_PUBLIC_APP_URL.
โ๏ธ React/Next.js Integration
Provider Setup
// app/layout.tsx or pages/_app.tsx
import { LightningProvider } from "lightning-auth-and-payment";
export default function RootLayout({ children }) {
return (
<LightningProvider
sessionSecret={process.env.SESSION_SECRET!}
cookieName="lightning-auth-session"
cookieDomain={process.env.SESSION_COOKIE_DOMAIN}
>
{children}
</LightningProvider>
);
}Authentication Hook
// components/LoginButton.tsx
import { useLightningAuth } from "lightning-auth-and-payment";
export function LoginButton() {
const { isAuthenticated, login, logout, user } = useLightningAuth();
if (isAuthenticated) {
return (
<div>
<p>Welcome, {user?.userId}!</p>
<button onClick={logout}>Logout</button>
</div>
);
}
return <button onClick={login}>Login with Lightning</button>;
}Payment Hook
// components/PaymentButton.tsx
import { useLightningPayment } from "lightning-auth-and-payment";
export function PaymentButton({ amount, description }) {
const { createInvoice, paymentState, timeLeft, copyBolt11, copied } =
useLightningPayment();
const handlePayment = () => {
createInvoice(amount, description);
};
return (
<div>
<button onClick={handlePayment}>Pay {amount} sats</button>
{paymentState === "waiting" && (
<div>
<p>Time Left: {timeLeft}s</p>
<button onClick={copyBolt11}>
{copied ? "Copied!" : "Copy BOLT11"}
</button>
</div>
)}
</div>
);
}Next.js Middleware
// middleware.ts
import { defaultLightningMiddleware } from "lightning-auth-and-payment";
export default defaultLightningMiddleware;
export const config = {
matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"],
};โจ Features
๐ Authentication
|
๐ฐ Payments
|
๐ eCommerce
|
๐๏ธ Database
|
โ๏ธ React Components
|
๐ ๏ธ Developer Experience
|
๐๏ธ Architecture
graph TB
A[User] --> B[Lightning Wallet]
B --> C[LNURL Auth]
C --> D[Lightning Auth & Payment Package]
D --> E[BTCPay Server]
D --> F[Database]
D --> G[React Components]
H[Admin] --> I[Admin Panel]
I --> D
J[Webhook] --> E
E --> D
K[Payment] --> L[Lightning Network]
L --> E
style D fill:#f9f,stroke:#333,stroke-width:4px
style E fill:#bbf,stroke:#333,stroke-width:2px
style F fill:#bfb,stroke:#333,stroke-width:2px๐ฏ Use Cases
| ๐๏ธ eCommerce | ๐ Education | ๐ฎ Gaming | ๐ฐ Donations |
|---|---|---|---|
| Digital products | Online courses | In-game purchases | Tipping platform |
| PDF stores | Content access | NFT marketplaces | Fundraising |
| SaaS subscriptions | Premium content | Virtual items | Charity donations |
| ๐ซ Events | ๐ APIs | ๐ฆ Marketplace | ๐ฑ Mobile |
|---|---|---|---|
| Event tickets | API access control | Multi-vendor | Mobile payments |
| Conference passes | Rate limiting | Vendor payouts | Cross-platform |
| Workshop access | Usage billing | Commission handling | Offline support |
๐ฆ Installation
# npm
npm install lightning-auth-and-payment
# yarn
yarn add lightning-auth-and-payment
# pnpm
pnpm add lightning-auth-and-payment๐ Examples
๐ Lightning Auth & Paymententication
import { LightningAuth, MemoryLnurlStore } from "lightning-auth-and-payment";
const auth = new LightningAuth({
sessionSecret: process.env.SESSION_SECRET!,
baseUrl: process.env.NEXT_PUBLIC_APP_URL!,
});
const store = new MemoryLnurlStore();
// Generate login challenge
const challenge = await auth.generateK1Challenge();
await store.addChallenge(challenge.k1);
const lnurl = await auth.generateLnurl(challenge.k1);
// Display QR code: <LnurlAuthQRCode lnurl={lnurl} size={200} />๐ฐ Lightning Payments
import { createBTCPayClientFromEnv, LightningQRCode } from 'lightning-auth-and-payment'
const btcpay = createBTCPayClientFromEnv()
// Create Lightning invoice
const invoice = await btcpay.createInvoice({
amount: '0.00001', // 1000 sats
currency: 'BTC',
metadata: { productId: 'bitcoin-whitepaper' }
})
// Display payment QR code
<LightningQRCode bolt11={invoice.bolt11} size={200} />๐ Complete eCommerce Store
import {
ECommerceManager,
createBTCPayClientFromEnv,
db,
} from "lightning-auth-and-payment";
const btcpay = createBTCPayClientFromEnv();
const store = new ECommerceManager(db, btcpay);
// Create digital product
const product = await store.products.createProduct({
name: "Bitcoin Whitepaper",
slug: "bitcoin-whitepaper",
priceSats: 1000,
isDigital: true,
filePath: "/downloads/bitcoin-whitepaper.pdf",
});
// Process order with Lightning payment
const order = await store.createOrderWithPayment({
userId: user.id,
items: [{ productId: product.id, quantity: 1, priceSats: 1000 }],
});
// Redirect to payment
return Response.redirect(order.paymentUrl);๐ง Configuration
Environment Variables
# Database
DATABASE_URL="file:./dev.db" # SQLite (dev)
# DATABASE_URL="postgresql://user:pass@localhost:5432/lightning_auth" # PostgreSQL (prod)
# Lightning Auth & Payment
SESSION_SECRET="your-32-character-secret-key"
NEXT_PUBLIC_APP_URL="http://localhost:3000"
# BTCPay Server
BTCPAY_HOST="https://your-btcpay-server.com"
BTCPAY_STORE_ID="your-store-id"
BTCPAY_API_KEY="your-api-key"
BTCPAY_WEBHOOK_SECRET="your-webhook-secret"
# Admin (optional)
ADMIN_SECRET="your-admin-secret"Database Setup
# Copy schema
cp node_modules/@lightning-auth-and-payment/src/database/schema.prisma prisma/schema.prisma
# Install Prisma
npm install prisma @prisma/client
# Generate client and migrate
npx prisma generate
npx prisma migrate dev --name initQuick Start
Basic Setup
import {
LightningAuth,
MemoryLnurlStore,
createBTCPayClientFromEnv,
} from "lightning-auth-and-payment";
// Initialize authentication
const auth = new LightningAuth({
sessionSecret: process.env.SESSION_SECRET!,
baseUrl: process.env.NEXT_PUBLIC_APP_URL,
isProduction: process.env.NODE_ENV === "production",
});
// Initialize storage
const store = new MemoryLnurlStore();
// Initialize BTCPay client
const btcpay = createBTCPayClientFromEnv();Next.js Integration
// app/api/auth/lnurl/route.ts
import {
createNextJSLightningAuth,
MemoryLnurlStore,
} from "lightning-auth-and-payment";
const auth = createNextJSLightningAuth(
{
sessionSecret: process.env.SESSION_SECRET!,
baseUrl: process.env.NEXT_PUBLIC_APP_URL,
isProduction: process.env.NODE_ENV === "production",
},
new MemoryLnurlStore()
);
export async function GET(request: NextRequest) {
return auth.handleLnurlRequest(request);
}Environment Variables
Required
SESSION_SECRET: Secret key for JWT session tokensBTCPAY_HOST: BTCPay Server URLBTCPAY_STORE_ID: BTCPay Store IDBTCPAY_API_KEY: BTCPay API KeyBTCPAY_WEBHOOK_SECRET: BTCPay Webhook Secret
Optional
NEXT_PUBLIC_APP_URL: Your application URL (for production)SESSION_COOKIE_DOMAIN: Cookie domain (for multi-domain setups)LNURL_FORCE_MEMORY: Force memory storage (set to '1' to disable database)
Storage Options
Memory Storage (Development)
import { MemoryLnurlStore } from "lightning-auth-and-payment";
const store = new MemoryLnurlStore();Database Storage (Production)
import { DatabaseLnurlStore } from "lightning-auth-and-payment";
const store = new DatabaseLnurlStore(yourDatabaseAdapter);Hybrid Storage (Recommended)
import { HybridLnurlStore } from "lightning-auth-and-payment";
const store = new HybridLnurlStore(yourDatabaseAdapter);BTCPay Server Integration
Creating Invoices
import {
createBTCPayClientFromEnv,
BTCPayClient,
} from "lightning-auth-and-payment";
const btcpay = createBTCPayClientFromEnv();
const invoice = await btcpay.createInvoice({
amount: "0.00001", // BTC amount
currency: "BTC",
orderId: "unique-order-id",
notificationURL: "https://yourdomain.com/api/webhooks/btcpay",
metadata: { userId: "user123" },
});
// Get Lightning Network BOLT11 invoice
const bolt11 = await btcpay.getLightningBOLT11(invoice.id);Webhook Handling
import { BTCPayClient } from "lightning-auth-and-payment";
export async function POST(request: NextRequest) {
const body = await request.text();
const signature = request.headers.get("btcpay-sig") || "";
const webhookSecret = process.env.BTCPAY_WEBHOOK_SECRET!;
// Verify webhook signature
if (!BTCPayClient.verifyWebhookSignature(body, signature, webhookSecret)) {
return NextResponse.json({ error: "Invalid signature" }, { status: 401 });
}
const payload = JSON.parse(body);
if (payload.type === "InvoiceSettled") {
// Handle settled invoice
console.log("Invoice settled:", payload.invoiceId);
}
return NextResponse.json({ received: true });
}Development with ngrok
For development, the package automatically detects the environment and uses appropriate URLs:
- Development: Uses request headers to determine the current host
- Production: Uses
NEXT_PUBLIC_APP_URLenvironment variable
ngrok Setup
# Install ngrok
npm install -g ngrok
# Start your app
npm run dev
# In another terminal, expose with ngrok
ngrok http 3000The package will automatically use the ngrok URL for LNURL generation.
API Reference
LightningAuth Class
createSession(userId: string): Promise<string>- Create a JWT sessionverifySession(token: string): Promise<SessionData | null>- Verify session tokengenerateK1Challenge(): string- Generate LNURL challengegenerateLnurl(k1: string, baseUrl?: string): string- Generate LNURLverifyLnurlSignature(k1: string, sig: string, key: string): boolean- Verify signature
BTCPayClient Class
createInvoice(request: CreateInvoiceRequest): Promise<BTCPayInvoice>- Create invoicegetInvoice(invoiceId: string): Promise<BTCPayInvoice>- Get invoice detailsgetLightningBOLT11(invoiceId: string): Promise<string | null>- Get Lightning invoicestatic verifyWebhookSignature(payload: string, signature: string, secret: string): boolean- Verify webhook
Storage Classes
All storage classes implement the LnurlStore interface:
addChallenge(k1: string): Promise<void>- Add challengehasChallenge(k1: string): Promise<boolean>- Check if challenge existscompleteLogin(k1: string, userId: string, token: string): Promise<void>- Complete loginconsumeLogin(k1: string): Promise<LoginInfo | null>- Consume completed login
React Components
PaymentModal
A complete Lightning payment modal with QR code display and payment status tracking:
import { PaymentModal } from "lightning-auth-and-payment";
function MyComponent() {
const [isOpen, setIsOpen] = useState(false);
const createInvoice = async () => {
// Your invoice creation logic
const response = await fetch("/api/invoice", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ amountSats: 1000 }),
});
return await response.json();
};
const checkPaymentStatus = async (invoiceId: string) => {
const response = await fetch(`/api/invoices/status?id=${invoiceId}`);
return await response.json();
};
return (
<PaymentModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
onCreateInvoice={createInvoice}
onCheckPaymentStatus={checkPaymentStatus}
amountSats={1000}
description="Pay 1,000 sats for your purchase"
onPaymentSuccess={(data) => console.log("Payment successful:", data)}
/>
);
}QR Code Components
import { LightningQRCode, LnurlAuthQRCode } from "lightning-auth-and-payment";
// Lightning payment QR code
<LightningQRCode
bolt11="lnbc1000n1..."
size={200}
/>
// LNURL authentication QR code
<LnurlAuthQRCode
lnurl="lnurl1dp68gurn8ghj7um5..."
size={200}
/>UI Components
import { Button, Badge, Card, Dialog } from "lightning-auth-and-payment";
// Button with variants
<Button variant="default">Default</Button>
<Button variant="bitcoin">Bitcoin</Button>
// Badge with rarity variants
<Badge variant="common">Common</Badge>
<Badge variant="rare">Rare</Badge>
<Badge variant="legendary">Legendary</Badge>
// Card components
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Content</CardContent>
</Card>
// Dialog modal
<Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Modal Title</DialogTitle>
<DialogDescription>Modal description</DialogDescription>
</DialogHeader>
{/* Your content */}
</DialogContent>
</Dialog>Utility Functions
Rate Limiting
import {
rateLimit,
getClientIP,
createRateLimitResponse,
} from "lightning-auth-and-payment";
export async function GET(request: NextRequest) {
const clientIP = getClientIP(request);
const result = rateLimit(clientIP, 10, 60000); // 10 requests per minute
if (!result.success) {
return createRateLimitResponse(result.resetTime);
}
// Your API logic here
return NextResponse.json({ data: "success" });
}Invoice Events (Server-Sent Events)
import {
registerInvoiceConnection,
emitInvoiceEvent,
} from "lightning-auth-and-payment";
// In your API route
export async function GET(request: NextRequest) {
const invoiceId = request.nextUrl.searchParams.get("id");
return new Response(
new ReadableStream({
start(controller) {
registerInvoiceConnection(invoiceId, controller);
},
cancel() {
unregisterInvoiceConnection(invoiceId);
},
}),
{
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
}
);
}
// In your webhook handler
import { emitInvoiceEvent } from "lightning-auth-and-payment";
if (payload.type === "InvoiceSettled") {
emitInvoiceEvent(payload.invoiceId, {
type: "settled",
sticker: {
/* your data */
},
});
}Formatting Utilities
import {
formatSats,
formatBTC,
satsToBTC,
btcToSats,
formatNumber,
formatDate,
cn,
} from "lightning-auth-and-payment";
// Bitcoin formatting
formatSats(1000); // "1,000 sats"
formatBTC(0.001); // "0.001 BTC"
satsToBTC(100000000); // 1
btcToSats(0.5); // 50000000
// General formatting
formatNumber(1234567); // "1,234,567"
formatDate(new Date()); // "October 27, 2023, 10:30 AM"
// CSS class merging (Tailwind)
cn("px-2 py-1", "p-3"); // "p-3" (conflicting classes merged)Constants
import {
DEFAULT_RATE_LIMIT,
RATE_LIMIT_WINDOW_MS,
DEFAULT_INVOICE_EXPIRY_MINUTES,
LNURL_TIMEOUT_MS,
BTCPAY_INVOICE_STATUS,
} from "lightning-auth-and-payment";
// Use in your application
const rateLimit = rateLimit(clientIP, DEFAULT_RATE_LIMIT, RATE_LIMIT_WINDOW_MS);
if (invoice.status === BTCPAY_INVOICE_STATUS.SETTLED) {
// Handle settled invoice
}eCommerce Integration
The package includes complete eCommerce functionality for digital products:
import {
ECommerceManager,
createBTCPayClientFromEnv,
db,
} from "lightning-auth-and-payment";
// Initialize eCommerce manager
const btcpay = createBTCPayClientFromEnv();
const ecommerce = new ECommerceManager(db, btcpay);
// Create a digital product
const product = await ecommerce.products.createProduct({
name: "Bitcoin Whitepaper",
slug: "bitcoin-whitepaper",
priceSats: 1000,
isDigital: true,
filePath: "/downloads/bitcoin-whitepaper.pdf",
});
// Create an order with Lightning payment
const order = await ecommerce.createOrderWithPayment({
userId: user.id,
items: [{ productId: product.id, quantity: 1, priceSats: 1000 }],
});๐ Documentation
- Complete Documentation - See
DOCUMENTATION.mdin the package for comprehensive guide - AI Integration Guide - See
AI_INTEGRATION.mdin the package for step-by-step AI agent integration - npm Package - View on npm for installation and basic usage
โก Performance
Benchmarks
| Operation | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| User Auth | ~5ms | ~3ms | ~4ms |
| Invoice Creation | ~10ms | ~8ms | ~9ms |
| Order Processing | ~15ms | ~12ms | ~13ms |
| Database Queries | ~2ms | ~1ms | ~1.5ms |
Optimization Tips
// Database indexing
model User {
lnPubkey String? @unique
@@index([createdAt])
@@index([lnPubkey])
}
// Connection pooling
const db = new PrismaClient({
datasources: { db: { url: process.env.DATABASE_URL } }
})
// Caching
const auth = new LightningAuth({
sessionSecret: process.env.SESSION_SECRET!,
cache: true // Enable caching
})๐ก๏ธ Security
Best Practices
- โ Environment Variables - Never commit secrets
- โ HTTPS Only - Always use secure connections
- โ Session Management - Secure JWT tokens
- โ Rate Limiting - Prevent abuse
- โ Input Validation - Sanitize all inputs
- โ Webhook Verification - Verify BTCPay signatures
Security Features
// Secure session management
const auth = new LightningAuth({
sessionSecret: process.env.SESSION_SECRET!, // 32+ characters
baseUrl: process.env.NEXT_PUBLIC_APP_URL!,
secure: process.env.NODE_ENV === "production",
});
// Rate limiting
const rateLimitResult = rateLimit(userIP, 10, 60000); // 10 requests per minute
if (!rateLimitResult.success) {
return createRateLimitResponse(rateLimitResult.resetTime);
}
// Webhook verification
const isValid = BTCPayClient.verifyWebhookSignature(payload, signature, secret);
if (!isValid) {
throw new Error("Invalid webhook signature");
}๐งช Testing
import { describe, it, expect } from "vitest";
import { LightningAuth } from "lightning-auth-and-payment";
describe("LightningAuth", () => {
it("should generate valid challenges", async () => {
const auth = new LightningAuth({
sessionSecret: "test-secret",
baseUrl: "http://localhost:3000",
});
const challenge = await auth.generateK1Challenge();
expect(challenge.k1).toBeDefined();
expect(challenge.k1.length).toBeGreaterThan(0);
});
});๐ Deployment
Vercel (Recommended)
# Install dependencies
npm install lightning-auth-and-payment
# Set environment variables
vercel env add DATABASE_URL
vercel env add SESSION_SECRET
vercel env add BTCPAY_HOST
# Deploy
vercel --prodDocker
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3000
CMD ["npm", "start"]Railway
# Connect to Railway
railway login
railway init
# Set environment variables
railway variables set DATABASE_URL="postgresql://..."
railway variables set SESSION_SECRET="your-secret"
# Deploy
railway up๐ค Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
# Clone the repository
git clone https://github.com/erich-mueller/lightning-auth.git
cd lightning-auth
# Install dependencies
npm install
# Run tests
npm test
# Build the package
npm run buildCode of Conduct
This project follows the Contributor Covenant code of conduct.
๐ Support
Community
- ๐ฌ GitHub Discussions - Ask questions and share ideas
- ๐ GitHub Issues - Report bugs and request features
- ๐ Documentation - Comprehensive guides and examples
- ๐ค AI Agent Integration Guide - Complete guide for AI agents
- โก AI Quick Reference - Quick patterns for AI agents
- ๐ AI Prompt Template - Template for AI requests
Professional Support
Need help with your Lightning Network application? We offer:
- ๐ Implementation Support - Get your app up and running quickly
- ๐ง Custom Development - Tailored solutions for your needs
- ๐ก๏ธ Security Audits - Ensure your app is secure
- ๐ Performance Optimization - Scale your application
Contact us for professional support.
๐ Showcase
Built something amazing with Lightning Auth & Payment? We'd love to see it!
- ๐ Featured Projects - Showcase your Lightning Network apps
- ๐ธ Screenshots - Share your UI/UX
- ๐ฅ Demo Videos - Show your app in action
- ๐ Case Studies - Share your success story
๐ Stats
๐ License
MIT License - see LICENSE for details.
๐ Acknowledgments
- BTCPay Server - Amazing Bitcoin payment processor
- Lightning Network - The future of Bitcoin payments
- Prisma - Next-generation ORM
- Next.js - The React framework for production
- Tailwind CSS - Utility-first CSS framework
Built with โก by the Lightning Network community
โญ Star us on GitHub โข ๐ Read the docs โข ๐ฌ Join the discussion