Skip to content

Repository files navigation

⚑ LnwPoS - Bitcoin Lightning Point of Sale

A Point of Sale system built with SvelteKit, Svelte 5, and LocalStorage. Suitable for small businesses accepting both Fiat and Bitcoin payments via Lightning Network with OpenPleb integration. Enables merchants to receive fiat payments for Bitcoin transactions via peer-to-peer matching offers.

License TypeScript Svelte

Features

OpenPleb Integration

  • Bitcoin Payments for Fiat - Customers can pay with Bitcoin, and the merchant receives fiat when a taker who want to earn Bitcoin accepts the offer
  • Fiat on-chain Transfer - Merchant receives fiat directly when taker accepts the offer
  • Cashu Bond Time-Lock Protection - Merchant protected with NUT-11 time-locked bonds
  • Automatic Bitcoin Conversion - Convert bonds back to BTC if no taker arrives

πŸ” Authentication

  • Secure client-side authentication with LocalStorage
  • Cookie-based token storage (24-hour expiry)
  • SSR-compatible route protection
  • Session management and auto-expiry
  • Default credentials: user / password

πŸ“Š Dashboard

  • Today's sales overview with totals
  • Transaction statistics and charts
  • Recent transaction history feed
  • Bitcoin exchange rate display (configurable)
  • Pending transaction tracking
  • Sales by payment method breakdown

πŸ›’ Point of Sale

  • Add products to cart with one click
  • Multiple payment methods (Cash, PromptPay, Lightning, LNURL, Cashu)
  • Real-time cart total calculation
  • Quick checkout with invoice generation
  • Multi-line items support for complex orders

πŸ“¦ Product Management

  • Create, edit, and delete products
  • Stock management (on/off toggle)
  • Sequential product IDs (00001, 00002, ...)
  • Product categories with emoji icons
  • Custom product images
  • Category-based product organization

πŸ“‹ Transaction History

  • View all transactions with full details
  • Filter by payment method (Cash, PromptPay, Lightning, LNURL, Cashu)
  • Filter by status (Success, Pending, Failed)
  • Transaction details with timestamps
  • Invoice and memo details for Lightning payments
  • Search and filter functionality

🎨 User Interface

  • Fully responsive design (mobile + desktop)
  • Dark/Light theme toggle
  • English localization
  • Modern, clean UI with Tailwind CSS
  • Smooth animations and transitions
  • Intuitive navigation

Tech Stack

Technology Version
SvelteKit 2.x
Svelte 5.x
TypeScript 5.x
Tailwind CSS 3.x
Vite 7.x
LocalStorage API Native

Architecture

Storage Layer

All data is persisted in the browser's LocalStorage, making the application:

  • Offline-capable - Works without internet once loaded
  • Privacy-focused - No backend database required
  • Fast - Instant load and data access
  • No server maintenance - No database to manage

Data Types

Products

{
  id: string        // Sequential: 00001, 00002, ...
  name: string
  price: number
  category: string
  image?: string
  stock: number     // 1 = in stock, 0 = out of stock
  createdAt: string
}

Transactions

{
  id: string
  items: TransactionItem[]
  total: number
  paymentMethod: 'cash' | 'promptpay' | 'lnurl' | 'cashu' | 'lightning'
  status: 'paid' | 'pending' | 'failed'
  invoice?: string  // Lightning invoice
  memo?: string     // Payment memo
  paidAt?: string
  createdAt: string
}

Settings

{
  lightningAddress?: string  // Your lightning@address
  openPlebApiKey?: string    // For Bitcoin price updates
  cashuMint?: string         // Cashu mint URL
  currency?: 'sat' | 'btc'   // Price display currency
  taxRate?: number           // Tax percentage (optional)
}

Authentication

// Cookie: lnwpos_user
{
  id: string
  email: string
  passwordHash: string
  createdAt: string
}

// Cookie: lnwpos_token
value: "username.timestamp"  // 24-hour expiry

Installation

  1. Clone the repository

    git clone https://github.com/pruks-dev/lnwPOS.git
    cd lnwPOS
  2. Install dependencies

    npm install
  3. Run development server

    npm run dev
  4. Open in browser

    http://localhost:5173
    

Usage

First-Time Setup

  1. Login with default credentials

    • Email: user
    • Password: password
  2. (Optional) Add products via Products page

    • Click "Add Product" to create new products
    • Configure categories and pricing
    • Set stock availability

Making a Sale

  1. Navigate to POS page
  2. Click products to add to cart (supports multiple quantities)
  3. Select payment method (Cash/PromptPay/Lightning/LNURL/Cashu)
  4. Click "Checkout" button
  5. Confirm payment
  6. Transaction is saved to LocalStorage immediately

Managing Products

  1. Navigate to Products page
  2. Click "Add Product" to create new product
  3. Click product to toggle stock status (on/off)
  4. Click edit icon to modify product details
  5. Click delete icon to remove product
  6. Product ID auto-generates sequentially

Viewing Transactions

  1. Navigate to Transactions page
  2. Filter by payment method (Cash, PromptPay, Lightning, LNURL, Cashu)
  3. Filter by status (Paid, Pending, Failed)
  4. View transaction details with items, totals, and timestamps

Configuring Settings

  1. Navigate to Settings page
  2. Configure Lightning address for price updates
  3. Set Cashu mint URL for Cashu payments
  4. Choose currency (satoshi or BTC)
  5. Optionally configure tax rate

Authentication System

The application uses a secure client-side authentication system with SSR protection:

How It Works

  • Login: POST to /api/auth/login
  • Logout: POST to /api/auth/logout
  • Token Storage: Cookies (not LocalStorage) - SSR-safe
  • Token Format: username.timestamp
  • Expiration: 24 hours (configurable)
  • Password Hashing: Simple hash function (TODO: upgrade to bcrypt/argon2)

Session Management

  • Token automatically expires after 24 hours
  • User is logged out after token expiration
  • Session persists across page refreshes within token validity
  • SSR-safe route protection prevents unauthorized access

Payment Methods

πŸ’³ Lightning + OpenPleb (Main Feature)

  • LNURL Support - Lightning Network URL for payments
  • Cashu Integration - Decentralized micro-credentials (unspent tokens)
  • Accept Bitcoin for Fiat - Customer pays with Bitcoin, merchant receives fiat when taker accepts the offer
  • Cashu Bond Protection - NUT-11 time-locked bonds protect merchants
  • Real-Time Pricing - Automatic Bitcoin price updates via OpenPleb API
  • Status Tracking - Support for paid, pending, failed states

Cash

  • Accept cash payments directly
  • No verification needed
  • Status: paid
  • Simple and instant

PromptPay

  • QR code for customer payment
  • Shop PromptPay ID configured in Settings
  • Status: paid

Data Persistence

LocalStorage Keys

  • lnwpos_products - All products data
  • lnwpos_transactions - All transactions data
  • lnwpos_settings - Application settings
  • lnwpos_user - Current user session
  • lnwpos_token - Authentication token
  • lnwpos_next_id - Next sequential product ID

Browser Compatibility

  • βœ… Chrome/Edge (latest)
  • βœ… Firefox (latest)
  • βœ… Safari (latest)
  • βœ… Mobile browsers (iOS Safari, Chrome Mobile)
  • βœ… Desktop browsers (Chrome, Firefox, Safari, Edge)

Note: LocalStorage-based storage requires JavaScript to be enabled.

Development

Build for Production

npm run build
npm run preview

TypeScript Compilation

npm run build  # Validates TypeScript types

Development Tips

  • Use npm run dev for hot reload development
  • npm run check validates Svelte components
  • Data persists in browser during development

Security Considerations

⚠️ Important Notes:

Current Limitations

  • Client-side only - No server-side validation
  • LocalStorage - Susceptible to browser extensions attacks
  • Password hashing - Simple hash
  • No CSRF protection - CSRF tokens not implemented
  • No rate limiting - No API rate limiting

Suitable For

  • βœ… Small businesses and sole proprietorships
  • βœ… Testing and prototyping
  • βœ… Teaching and learning

Roadmap

βœ… Complete (Phase 1)

  • LocalStorage layer (products, transactions, users, settings)
  • Client-side authentication with cookie tokens
  • POS with cart and multi-item support
  • Product management (CRUD operations)
  • Transaction history with filters
  • Dashboard with analytics
  • Dark/Light theme toggle
  • Responsive design (mobile + desktop)

πŸš€ Future (Phase 2) - Enhanced Features

  • Lightning integration (LNURL + OpenPleb API)
  • Receipt generation (print/export)
  • Inventory alerts (low stock notifications)
  • Data backup and export features
  • Multiple currency support

πŸš€ Future (Phase 3) - Advanced Features

  • Advanced cart management (quantities, modifiers, discounts)
  • Receipt generation (print/export PDF/QR)
  • Inventory alerts (low stock notifications)
  • Data backup and export (JSON/CSV)
  • Multi-device sync
  • User management system
  • POS hardware support (thermal printer)

Contributing

OpenPleb Integration

LnwPoS integrates with OpenPleb to facilitate instant fiat-on-ramp transactions via Lightning Network. This allows customers to pay with Bitcoin while the merchant receives fiat directly.

How It Works

The integration follows a peer-to-peer matching offer flow:

1. Order & Request Offer
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ POS requests    β”‚  β†’ OpenPleb: Create offer (bitcoin + fiat price)
   β”‚ offer with      β”‚
   β”‚ bitcoin amount  β”‚  β†’ Return LN invoice for payment
   β”‚ + fiat price    β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
2. Display QR Code
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ Show LN invoice β”‚  β†’ Customer scans & pays with Lightning
   β”‚ QR code         β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
3. Payment Confirmed + Bond Assigned
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ OpenPleb        β”‚  β†’ Offer confirmed, bond assigned
   β”‚ creates offer   β”‚
   β”‚ + sends bond    β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚
            β–Ό
4. Two Possible Outcomes
            β”‚
            β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
            β–Ό                β–Ό            
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” 
   β”‚ Case A: No     β”‚ β”‚ Case B:     β”‚ 
   β”‚ Taker          β”‚ β”‚ Taker       β”‚ 
   β”‚                β”‚ β”‚ Arrives     β”‚ 
   β”‚ Timeout        β”‚ β”‚             β”‚ 
   β”‚ 7 days         β”‚ β”‚ Taker       β”‚ 
   β”‚                β”‚ β”‚ pays fiat   β”‚ 
   β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜ 
          β”‚                  β”‚
          β–Ό                  β–Ό
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ POS redeems    β”‚ β”‚ Bond        β”‚
   β”‚ bond token     β”‚ β”‚ rejected    β”‚
   β”‚ to get BTC     β”‚ β”‚ in list     β”‚
   β”‚ (time locked   β”‚ β”‚ (cannot     β”‚
   β”‚ NUT-11)        β”‚ β”‚ redeem)     β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Flow Details

Step 1: Request Offer

  • POS generates order with bitcoin_amount and fiat_price
  • OpenPleb creates a sell order (maker) and returns:
    • Lightning Network invoice for the bitcoin amount
    • Cashu bond token (p2pk time-locked, NUT-11)

Step 2: Payment

  • Customer scans QR code and pays via Lightning Network
  • Payment is confirmed on the Lightning Network

Step 3: Offer Confirmed

  • OpenPleb confirms the offer and declares it as "completed"
  • POS status updates to pending (waiting for taker)
  • OpenPleb assigns a Cashu bond token to the POS

Step 4a: No Taker (Timeout)

  • If no taker arrives within the time lock period:
    • User (merchant) can redeem the bond token themselves
    • Bond has a default time lock of 7 days (configurable)
    • Token can be redeemed with the configured cashu mint
    • Redeeming converts the bond back to Bitcoin

Step 4b: Taker Arrives

  • If a taker accepts the offer:
    • The bond is immediately rejected/removed from the list
    • Taker transfers fiat directly to the merchant
    • Merchant receives fiat without needing the bond

Time Lock & Redemption

  • Default Time Lock: 7 days (configurable in settings)
  • Bond Type: Cashu token with p2pk time lock (NUT-11 specification)
  • Redemption: User/POS redeems token with configured cashu mint
  • Fiat Transfer: Happens directly between merchant and taker (off-chain)

Use Cases

  • Instant Fiat: Customer pays with Bitcoin, merchant gets fiat via peer payment
  • Peer-to-peer: No need for centralized fiat on-ramp services
  • Time-Lock Protection: Merchant is protected if taker doesn't arrive
  • Auto-Convert: If no taker, bond automatically converts to BTC

Configuration

Required settings in Settings page:

  • Lightning Address: Your lightning@address (for OpenPleb)
  • OpenPleb API Key: For connecting to OpenPleb API
  • Cashu Mint URL: Your configured cashu mint for redemption
  • Time Lock: Bond expiration time (default: 7 days)

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - Feel free to use this project for personal or commercial purposes.

Credits

Built with ❀️ using:


Made with Bitcoin ⚑

About

A Point of Sale system for small businesses accepting both Fiat and Bitcoin payments via Lightning Network with OpenPleb integration.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages