A powerful Bitcoin Lightning terminal for Blink power users. Execute advanced operations, manage vouchers, process batch payments, accept payments with automatic forwarding, and leverage the full capabilities of your Blink account.
- Real-time Payment Detection: WebSocket connections for instant payment notifications
- Dynamic Currency Support: All 71+ fiat currencies from Blink with automatic formatting
- NFC Payments: Web NFC integration for contactless payments (NTAG424DNA compatible)
- Item Cart Mode: Optional cart for multi-item transactions
- Payment Animations: Full-screen celebratory animations for incoming payments
- Single Vouchers: Create individual LNURL-withdraw vouchers with QR codes
- Multi-Voucher Batches: Generate multiple vouchers at once (up to 24) for events or distributions
- Configurable Expiry: Set voucher expiration (1 hour to never expires)
- Commission Support: Optional commission percentage for resellers/distributors
- PDF Generation: Print-ready PDFs in multiple formats:
- A4 and Letter paper sizes
- Thermal printer formats (58mm and 80mm)
- Grid layouts (2x2, 2x3, 3x3, 3x4 vouchers per page)
- Voucher Manager: Comprehensive dashboard to track all vouchers
- Filter by status: Active, Claimed, Expired, Cancelled
- Sort by recent activity or soonest expiry
- Real-time status updates
- Cancel unclaimed vouchers
- View redemption details and timestamps
- PostgreSQL Persistence: Vouchers persist across deployments
- CSV Import: Upload recipient lists for bulk payments
- Validation: Automatic validation of Lightning addresses and amounts
- Progress Tracking: Real-time status updates during batch execution
- Split Payments: Automatically split payments between merchant and tip recipient
- Zero-Fee Forwarding: Uses Blink intraledger transactions for instant, free forwarding
- Flexible Destinations: Forward to Blink usernames or Lightning Addresses
- Configurable Presets: Set custom tip percentages (e.g., 10%, 15%, 20%)
- Blink Integration: Direct connection to Blink API for zero-fee intraledger transactions
- NWC Support: Connect external wallets via Nostr Wallet Connect
- Blink-based NWC benefits from zero-fee instant payments
- External NWC wallets fully supported for invoice creation and payments
- Multi-Wallet Management: Link and manage multiple Blink accounts
- Nostr Authentication: NIP-07 (browser extensions), NIP-55 (external signers like Amber) and NIP-46 (Nostr Connect / remote signers)
- Server-held NIP-46 sessions: the relay subscription for a Nostr Connect sign-in lives on the server, so opening the signer app (which backgrounds the browser tab) cannot lose the signer's one-shot response
- Cross-Device Sync: Profile settings and credentials sync across devices when authenticated via Nostr
- Encrypted Storage: Client-side encryption for sensitive credentials (API keys, NWC URIs)
- Transaction History: Comprehensive logs with status tracking and memo support
- CSV Export: Export transaction data for accounting
- Network Analytics: Transaction heatmaps and statistics
Frontend (Next.js) → Direct Blink WebSocket → Instant Payment Detection
→ API Routes → Hybrid Storage (Redis + PostgreSQL)
→ Blink GraphQL API
- Frontend: Next.js with React hooks and Tailwind CSS
- Authentication: Nostr-based auth with JWT sessions
- Real-time: Direct WebSocket connection to Blink API (wss://ws.blink.sv/graphql)
- Storage: Hybrid architecture with Redis (hot data) and PostgreSQL (cold data)
- PDF Generation: React-PDF for vouchers and transaction receipts
- Redis: Sub-millisecond access to active payments and hot data (24h TTL)
- PostgreSQL: Permanent storage for transaction history, vouchers, and analytics
- Automatic Migration: Data flows from Redis to PostgreSQL after completion
All Redis keys are prefixed with blink-terminal: to prevent collisions when sharing a Redis instance with other services:
| Key Pattern | Purpose | TTL |
|---|---|---|
blink-terminal:rate:{provider}:{CURRENCY} |
Exchange rate cache | 45s |
blink-terminal:payment:{paymentHash} |
Active payment data (hot cache) | 15-30min |
- Node.js 14+
- Docker and Docker Compose (for Redis and PostgreSQL)
- A Blink API key from Blink Dashboard
-
Clone the repository:
git clone https://github.com/blinkbitcoin/blink-terminal.git cd blink-terminal -
Install dependencies:
npm install
-
Start database services:
docker-compose up -d
-
Configure environment variables: Create
.env.localwith:JWT_SECRET=your-strong-jwt-secret-key ENCRYPTION_KEY=your-strong-encryption-key NODE_ENV=development # Database REDIS_URL=redis://localhost:6379 DATABASE_URL=postgresql://user:password@localhost:5432/blinkpos -
Start the development server:
npm run dev
-
Access the application: Open http://localhost:3000
- Authenticate: Sign in with Nostr (NIP-07 extension or NIP-55 signer) or enter Blink credentials directly
- Configure: Set up your Blink account, NWC connections, and preferences in Settings
- Operate: Use the terminal for payments, vouchers, batch operations, and more
- Monitor: Track transactions, balances, and statistics in the Dashboard
blink-terminal/
├── components/
│ ├── Dashboard.js # Main dashboard interface
│ ├── POS.js # Point of Sale interface
│ ├── ItemCart.js # Cart mode for multi-item transactions
│ ├── Voucher.js # Single voucher creation
│ ├── MultiVoucher.js # Batch voucher generation
│ ├── VoucherManager.js # Voucher tracking and management
│ ├── BatchPayments.js # Bulk payment processing
│ ├── Network.js # Network analytics and heatmaps
│ ├── TransactionDetail.js # Transaction detail view
│ ├── PaymentAnimation.js # Payment celebration overlay
│ ├── NFCPayment.js # NFC payment handling
│ ├── ExpirySelector.js # Voucher expiry configuration
│ ├── auth/ # Authentication components
│ ├── wallet/ # Wallet setup components
│ └── Settings/ # Settings page sections
├── lib/
│ ├── blink-api.js # Blink GraphQL API integration
│ ├── voucher-store.js # Voucher PostgreSQL storage
│ ├── voucher-expiry.js # Voucher expiration utilities
│ ├── storage/ # Hybrid storage implementation
│ ├── nostr/ # Nostr authentication services
│ ├── network/ # Network analytics
│ ├── batch-payments/ # Batch payment processing
│ ├── pdf/ # PDF generation (vouchers, receipts)
│ ├── nwc/ # Nostr Wallet Connect
│ └── migration/ # Data migration utilities
├── pages/
│ ├── api/
│ │ ├── blink/ # Blink API proxy endpoints
│ │ ├── voucher/ # Voucher management endpoints
│ │ ├── batch-payments/ # Batch payment endpoints
│ │ ├── network/ # Network analytics endpoints
│ │ └── user/ # User management endpoints
│ ├── _app.js # App wrapper
│ └── index.js # Main page
├── database/ # Database schemas and migrations
├── public/ # Static assets
├── scripts/ # Utility scripts
└── types/ # TypeScript type definitions
| Variable | Description | Required |
|---|---|---|
JWT_SECRET |
Secret for JWT token signing (64+ chars recommended) | Yes |
ENCRYPTION_KEY |
Key for API key encryption (32+ chars recommended) | Yes |
NODE_ENV |
Environment (development/production) | Yes |
REDIS_URL |
Redis connection URL | Yes |
DATABASE_URL |
PostgreSQL connection URL | Yes |
WEBHOOK_SECRET |
Secret for Blink webhook verification | Optional |
JWT_SECRET=your-super-strong-jwt-secret-key-here
ENCRYPTION_KEY=your-super-strong-encryption-key-here
NODE_ENV=development
REDIS_URL=redis://localhost:6379
DATABASE_URL=postgresql://blinkpos:password@localhost:5432/blinkpos| Endpoint | Method | Description |
|---|---|---|
POST /api/auth/login |
POST | Authenticate with Blink API key |
POST /api/auth/logout |
POST | Clear user session |
GET /api/auth/verify |
GET | Verify current session |
POST /api/auth/nostr-login |
POST | NIP-98 login (extension / generated keys) |
POST /api/nostr-connect/sessions |
POST | Start a NIP-46 sign-in; returns a ready URI |
GET /api/nostr-connect/sessions/:id |
GET | Poll session status (never mints a cookie) |
POST /api/nostr-connect/sessions/:id/consume |
POST | Consume the approval and set the session cookie |
DELETE /api/nostr-connect/sessions/:id |
DELETE | Cancel a session and release its relay sockets |
The NIP-46 endpoints are bound to the browser that created the session by an
HttpOnly SameSite=Strict cookie; the session id alone is not a login
capability. See lib/nip46-server/ for the transport and session model.
| Endpoint | Method | Description |
|---|---|---|
GET /api/blink/balance |
GET | Get wallet balances |
GET /api/blink/transactions |
GET | Get transaction history |
POST /api/blink/create-invoice |
POST | Create Lightning invoice |
GET /api/blink/check-payment |
GET | Check payment status |
GET /api/blink/exchange-rate |
GET | Get current exchange rates |
GET /api/blink/csv-export |
GET | Export transactions as CSV |
POST /api/blink/webhook |
POST | Receive Blink webhooks |
| Endpoint | Method | Description |
|---|---|---|
POST /api/voucher/create |
POST | Create a voucher. Body apiKey must currently own walletId and match walletCurrency |
GET /api/voucher/list |
GET | List the caller's vouchers. Requires x-voucher-api-key; ?environment=, ?status= |
GET /api/voucher/status/:chargeId |
GET | Check voucher status (capability URL: the chargeId is the secret) |
POST /api/voucher/cancel |
POST | Cancel an unclaimed voucher. Requires x-voucher-api-key |
POST /api/voucher/pdf |
POST | Disabled (returns 503) |
GET /api/voucher/lnurl/:chargeId/:amount |
GET | LNURL-withdraw endpoint (LUD-03) |
GET /api/voucher/callback |
GET | LNURL-withdraw callback; pays only an invoice for exactly the face value |
Voucher management (list, cancel, create) is authorized by current wallet
ownership: the presented Blink API key is checked live against Blink and must own
the voucher's wallet in the voucher's environment. A revoked key stops working
immediately; a replacement key for the same wallet can manage older vouchers.
list and cancel are same-origin only (no CORS). Voucher ids are LNURL k1
redemption secrets and are only returned to the current owner. If Blink can't be
reached to check ownership, these routes answer 503 (retry) rather than an auth error.
list returns at most 500 vouchers (newest first, truncated: true when capped);
stats always cover all of the owner's vouchers.
Rotated / revoked funding key: a voucher pays out with the API key it was created with. If that key is revoked, redemption fails with "This voucher's wallet is no longer available" and the voucher stays active; the owner can cancel it with the replacement key and reissue.
| Endpoint | Method | Description |
|---|---|---|
POST /api/batch-payments/validate |
POST | Validate recipient list |
POST /api/batch-payments/execute |
POST | Execute batch payments |
- Invoice Created: Backend generates Lightning invoice via Blink API
- WebSocket Connection: Frontend establishes direct connection to
wss://ws.blink.sv/graphql - Subscription: Subscribes to
myUpdatesGraphQL subscription - Payment Received: Blink sends real-time transaction data
- Animation Triggered: Full-screen celebration animation displays
- Forwarding: If configured, payment is automatically split and forwarded
- Storage Updated: Transaction recorded in Redis and archived to PostgreSQL
npm run devnpm run build
npm startdocker-compose -f docker-compose.prod.yml up -d- Vercel (recommended for Next.js)
- Docker with Nginx reverse proxy
- Any Node.js hosting with Redis and PostgreSQL
| Feature | Status |
|---|---|
| Hybrid Storage (Redis + PostgreSQL) | Completed |
| Payment Forwarding & Tipping | Completed |
| Dynamic Currencies (71+) | Completed |
| WebSocket Payment Detection | Completed |
| Transaction History & CSV Export | Completed |
| NWC Integration | Completed |
| Lightning Address Forwarding | Completed |
| npub.cash Integration | Removed |
| Cross-Device Sync | Completed |
| NFC Payments | Completed |
| Nostr Authentication (NIP-07, NIP-55) | Completed |
| Single Voucher Creation | Completed |
| Multi-Voucher Batch Generation | Completed |
| Voucher Manager Dashboard | Completed |
| Voucher PostgreSQL Persistence | Completed |
| Batch Payments | Completed |
| In-App Key Generation | In Progress |
| WebAuthn/Passkeys | Planned |
- Blink API Documentation - Official Blink API docs
- Blink Dashboard - Get your API key
- Nostr Wallet Connect (NIP-47) - NWC specification
Contributions are welcome! This project is licensed under the MIT License:
- Free to use for any purpose, including commercial
- Modify and distribute your changes freely
- Help make Bitcoin tools accessible to everyone
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License.
See the LICENSE file for details.
- Blink for the Lightning payment infrastructure
- Bitcoin Lightning Network for instant, low-fee payments
- Nostr Protocol for decentralized authentication
- Next.js & React for the development framework
- The open source community for inspiration and tools
- Issues: GitHub Issues
- Blink Support: Blink Developer Docs
Built for the Bitcoin Lightning Network