mirror of
https://github.com/Permissionless-Software-Foundation/psf-bch-api-base.git
synced 2026-09-22 01:02:00 -07:00
5.2 KiB
5.2 KiB
REST2NOSTR Proxy API Implementation Plan
Overview
Build a REST API server in /app that proxies Nostr WebSocket protocol to REST endpoints, enabling JavaScript developers to interact with Nostr relays via familiar REST APIs instead of WebSockets.
Architecture
Follow Clean Architecture pattern with these layers:
- Entities (
src/entities/): Domain models (Event, Subscription, etc.) - Use Cases (
src/use-cases/): Business logic (PublishEvent, QueryEvents, ManageSubscription) - Adapters (
src/adapters/): External interfaces (NostrRelay WebSocket client, logger) - Controllers (
src/controllers/rest-api/): Express.js route handlers
Directory Structure
/app
├── src/
│ ├── entities/
│ │ └── event.js
│ ├── use-cases/
│ │ ├── index.js
│ │ ├── publish-event.js
│ │ ├── query-events.js
│ │ └── manage-subscription.js
│ ├── adapters/
│ │ ├── index.js
│ │ ├── nostr-relay.js
│ │ └── wlogger.js
│ ├── controllers/
│ │ ├── index.js
│ │ └── rest-api/
│ │ ├── index.js
│ │ ├── event/
│ │ │ ├── controller.js
│ │ │ └── index.js
│ │ └── req/
│ │ ├── controller.js
│ │ └── index.js
│ └── config/
│ ├── index.js
│ └── env/
│ ├── common.js
│ ├── development.js
│ └── production.js
├── examples/
│ └── [refactored sandbox examples]
├── bin/
│ └── server.js
├── .env.example
├── .env
├── index.js
├── package.json
└── apidoc.json
Core Endpoints
POST /event
- Maps to:
["EVENT", <event>] - Publish a signed Nostr event to relay
- Body: JSON event object
- Response:
{"accepted": true/false, "message": ""}(maps to["OK", ...])
GET /req/:subId
- Maps to:
["REQ", <sub_id>, <filters>] - Stateless query - returns events immediately
- Query params: filters (JSON encoded or separate params)
- Response: Array of events
POST /req/:subId
- Maps to:
["REQ", <sub_id>, <filters>] - Establish subscription for Server-Sent Events (SSE)
- Body: filters object
- Response: SSE stream of events
DELETE /req/:subId
- Maps to:
["CLOSE", <sub_id>] - Close an existing subscription
- Response: Confirmation
Implementation Details
1. Package Dependencies
express: REST API frameworkdotenv: Environment variable managementapidoc: API documentation generationwsornostr-tools: WebSocket client for Nostr relayswinston: Logging (following example pattern)
2. Adapter Layer (src/adapters/)
- nostr-relay.js: WebSocket client wrapper
- Connect to configured relay(s)
- Send
EVENT,REQ,CLOSEmessages - Handle relay responses (
EVENT,OK,EOSE,CLOSED,NOTICE) - Manage connection pooling for multiple relays
- wlogger.js: Winston-based logger
3. Use Cases (src/use-cases/)
- publish-event.js: Validate event, send to relay, return OK response
- query-events.js: Stateless query - send REQ, collect events until EOSE, return results
- manage-subscription.js: Create/close subscriptions, handle SSE streaming
4. Controllers (src/controllers/rest-api/)
- event/controller.js: Handle POST /event
- req/controller.js: Handle GET/POST/DELETE /req/:subId
- Express middleware for validation, error handling
- SSE support for subscription endpoint
5. Configuration (src/config/)
- Environment-based config (development, production, test)
- Default relay URL(s) from environment variables
- Port, logging level, etc.
6. Subscription Management
- Store active subscriptions in memory (Map with subId as key)
- Map subscription IDs to WebSocket connections
- Handle cleanup on DELETE /req/:subId
- Support SSE streaming for POST /req/:subId
7. Examples (examples/)
Refactor sandbox examples to use REST API:
01-create-account/- Use REST API to publish kind 0 event02-read-posts/- Use GET /req/:subId for stateless query03-write-post/- Use POST /event04-read-alice-posts/- Use GET /req/:subId with author filter14-get-follow-list/- Use GET /req/:subId with kind 3 filter- Additional examples as needed
8. API Documentation
- Use api-doc annotations in controller files
- Generate docs with
npm run docs - Follow pattern from clean-architecture example
Environment Variables
NOSTR_RELAY_URL: Default relay WebSocket URL (e.g.,wss://nostr-relay.psfoundation.info)PORT: Server port (default: 3000)NODE_ENV: Environment (development, production, test)LOG_LEVEL: Logging level (info, debug, error)
Key Implementation Notes
- WebSocket connections: Maintain persistent connections to relay(s) in adapter
- Error handling: Map Nostr relay errors to appropriate HTTP status codes
- Validation: Validate Nostr events before forwarding (event structure, signature)
- SSE: Use Express response.write() for Server-Sent Events in subscription endpoint
- Stateless queries: For GET /req/:subId, collect events until EOSE, then close subscription automatically