From dbd64f7fafc29c847d9a315f4d2cf1e679e863de Mon Sep 17 00:00:00 2001 From: Ben Weeks Date: Tue, 23 Dec 2025 12:53:21 +0000 Subject: [PATCH] feat: improve shipping zone UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove asterisks from UK/US country names (#153) - Remove unclear "Flat rate" option (#153) - Alphabetize country list, move China to correct position (#153) - Rename "Unit" to "Currency" (#154) - Rename cost label to "Default shipping cost" (#154) - Add currency suffix to cost field (#154) - Add hint about per-product shipping costs (#154) - Add validation for whole number sats (#155) - Disable submit button when sats validation fails (#155) - Show error message for invalid sats values (#155) Closes #153, #154, #155 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- CLAUDE.md | 104 ++++++++++++++++++ static/components/shipping-zones.js | 11 +- .../components/shipping-zones.html | 10 +- 3 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..db2ef06 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,104 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Nostr Market is an LNbits extension implementing NIP-15 (decentralized marketplace protocol) on Nostr. It enables merchants to create webshops (stalls) and sell products with Lightning Network payments, featuring encrypted customer-merchant communication via NIP-04. + +**Prerequisites:** Requires the LNbits [nostrclient](https://github.com/lnbits/nostrclient) extension to be installed and configured. + +## Common Commands + +All commands are in the Makefile: + +```bash +make format # Run prettier, black, and ruff formatters +make check # Run mypy, pyright, black check, ruff check, prettier check +make test # Run pytest with debug mode +make all # Run format and check +``` + +Individual tools: + +```bash +make black # Format Python files +make ruff # Check and fix Python linting +make mypy # Static type checking +make pyright # Python static type checker +make prettier # Format JS/HTML/CSS files +``` + +## Local Development Setup + +To run checks locally, install dependencies: + +```bash +# Install Python autotools dependencies (needed for secp256k1) +sudo apt-get install -y automake autoconf libtool + +# Install Python dependencies +uv sync + +# Install Node dependencies (for prettier) +npm install + +# Run all checks +make check +``` + +## Architecture + +### Core Layers + +1. **API Layer** (`views_api.py`) - REST endpoints for merchants, stalls, products, zones, orders, direct messages +2. **Business Logic** (`services.py`) - Order processing, Nostr event signing/publishing, message routing, invoice handling +3. **Data Layer** (`crud.py`) - Async SQLite operations via LNbits db module +4. **Models** (`models.py`) - Pydantic models for all entities + +### Nostr Integration (`nostr/`) + +- `nostr_client.py` - WebSocket client connecting to nostrclient extension for relay communication +- `event.py` - Nostr event model, serialization, ID computation (SHA256), Schnorr signatures + +### Background Tasks (`__init__.py`, `tasks.py`) + +Three permanent async tasks: + +- `wait_for_paid_invoices()` - Lightning payment listener +- `wait_for_nostr_events()` - Incoming Nostr message processor +- `_subscribe_to_nostr_client()` - WebSocket connection manager + +### Frontend (`static/`, `templates/`) + +- Merchant dashboard: `templates/nostrmarket/index.html` +- Customer marketplace: `templates/nostrmarket/market.html` with Vue.js/Quasar in `static/market/` +- Use Quasar UI components when possible: https://quasar.dev/components + +### Key Data Models + +- **Merchant** - Shop owner with Nostr keypair, handles event signing and DM encryption +- **Stall** - Individual shop with products and shipping zones (kind 30017) +- **Product** - Items for sale with categories, images, quantity (kind 30018) +- **Zone** - Shipping configuration by region +- **Order** - Customer purchases with Lightning invoice tracking +- **DirectMessage** - Encrypted chat (NIP-04) +- **Customer** - Buyer profile with Nostr pubkey + +### Key Patterns + +- **Nostrable Interface** - Base class for models convertible to Nostr events (`to_nostr_event()`, `to_nostr_delete_event()`) +- **Parameterized Replaceable Events** - Stalls (kind 30017) and Products (kind 30018) per NIP-33 +- **AES-256 Encryption** - Customer-merchant DMs use shared secret from ECDH +- **JSON Meta Fields** - Complex data (zones, items, config) stored as JSON in database + +### Cryptography (`helpers.py`) + +- Schnorr signatures for Nostr events +- NIP-04 encryption/decryption +- Key derivation and bech32 encoding (npub/nsec) + +## Workflow + +- Always check GitHub Actions after pushing to verify CI passes +- Run `make check` locally before pushing to catch issues early diff --git a/static/components/shipping-zones.js b/static/components/shipping-zones.js index 742021a..13f0357 100644 --- a/static/components/shipping-zones.js +++ b/static/components/shipping-zones.js @@ -19,7 +19,6 @@ window.app.component('shipping-zones', { currencies: [], shippingZoneOptions: [ 'Free (digital)', - 'Flat rate', 'Worldwide', 'Europe', 'Australia', @@ -27,6 +26,7 @@ window.app.component('shipping-zones', { 'Belgium', 'Brazil', 'Canada', + 'China', 'Denmark', 'Finland', 'France', @@ -34,8 +34,8 @@ window.app.component('shipping-zones', { 'Greece', 'Hong Kong', 'Hungary', - 'Ireland', 'Indonesia', + 'Ireland', 'Israel', 'Italy', 'Japan', @@ -59,10 +59,9 @@ window.app.component('shipping-zones', { 'Thailand', 'Turkey', 'Ukraine', - 'United Kingdom**', - 'United States***', - 'Vietnam', - 'China' + 'United Kingdom', + 'United States', + 'Vietnam' ] } }, diff --git a/templates/nostrmarket/components/shipping-zones.html b/templates/nostrmarket/components/shipping-zones.html index 3f0fd08..fcbeac3 100644 --- a/templates/nostrmarket/components/shipping-zones.html +++ b/templates/nostrmarket/components/shipping-zones.html @@ -55,18 +55,22 @@ dense v-model="zoneDialog.data.currency" type="text" - label="Unit" + label="Currency" :options="currencies" >
@@ -83,7 +87,7 @@ Create Shipping Zone