{"id":47839322,"url":"https://github.com/bitkarrot/nostrj","last_synced_at":"2026-04-03T20:36:11.843Z","repository":{"id":347716658,"uuid":"1195037308","full_name":"bitkarrot/nostrj","owner":"bitkarrot","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-29T06:25:26.000Z","size":103,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-29T08:53:58.623Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bitkarrot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-29T06:02:14.000Z","updated_at":"2026-03-29T06:10:05.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bitkarrot/nostrj","commit_stats":null,"previous_names":["bitkarrot/nostrj"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/bitkarrot/nostrj","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitkarrot%2Fnostrj","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitkarrot%2Fnostrj/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitkarrot%2Fnostrj/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitkarrot%2Fnostrj/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bitkarrot","download_url":"https://codeload.github.com/bitkarrot/nostrj/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bitkarrot%2Fnostrj/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31375772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-03T17:53:18.093Z","status":"ssl_error","status_checked_at":"2026-04-03T17:53:17.617Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-03T20:36:11.230Z","updated_at":"2026-04-03T20:36:11.835Z","avatar_url":"https://github.com/bitkarrot.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NostrJ - Nostr Protocol Implementation for Java\n\nA comprehensive Java implementation of the Nostr protocol, providing modular libraries for building Nostr clients, relays, and applications.\n\n## Project Structure\n\nNostrJ is organized as a multi-module Maven project:\n\n### 1. **nostrj-core** (JAR)\nCore Nostr functionality including:\n- **Key Generation**: Generate Nostr public/private key pairs using secp256k1\n- **Bech32 Encoding**: Support for `npub` and `nsec` key formats\n- **Message Signing**: Sign Nostr events with Schnorr signatures\n- **Event Creation**: Builder pattern for creating any Nostr event kind\n- **Signature Verification**: Verify event signatures\n\n### 2. **nostrj-client** (JAR)\nClient library for connecting to Nostr relays:\n- **WebSocket Connections**: Connect to multiple relays simultaneously\n- **Event Publishing**: Publish events to one or more relays\n- **Subscriptions**: Subscribe to events with flexible filters\n- **Message Handling**: Parse and handle all Nostr message types (EVENT, REQ, CLOSE, EOSE, OK, NOTICE)\n\n### 3. **nostrj-server** (JAR)\nFramework-independent relay server components:\n- **Event Storage**: Pluggable event store interface\n- **SQLite Implementation**: Production-ready SQLite event storage\n- **Relay Handler**: Protocol-compliant message handling\n- **Query Engine**: Efficient event querying with filters\n- **Policy System**: Customizable relay policies\n\n### 4. **nostrj-relay-app** (Application)\nComplete Nostr relay server using Micronaut:\n- **WebSocket Support**: Full Nostr protocol over WebSocket\n- **HTTP API**: NIP-11 relay information endpoint\n- **Health Checks**: Monitoring endpoints\n- **Configuration**: YAML-based configuration\n- **Production Ready**: Logging, error handling, and performance optimized\n\n## Requirements\n\n- Java 21 or later (tested with Java 25)\n- Maven 3.9 or later\n- secp256k1 native library (install via `brew install secp256k1` on macOS)\n\n## Dependencies\n\n- **secp256k1-jdk** v0.2.0 - Cryptographic operations\n- **bitcoinj** v0.17.0 - Bech32 encoding reference\n- **Micronaut** v4.2.0 - Web framework for relay app\n- **Jackson** - JSON serialization\n- **SQLite JDBC** - Database storage\n\n## Building\n\nBuild all modules:\n```bash\nmvn clean install\n```\n\nBuild without tests:\n```bash\nmvn clean install -DskipTests\n```\n\nBuild specific module:\n```bash\nmvn clean install -pl nostrj-core\nmvn clean install -pl nostrj-client\nmvn clean install -pl nostrj-server\nmvn clean install -pl nostrj-relay-app\n```\n\n## Usage Examples\n\n### Core Module - Key Generation and Event Signing\n\n```java\nimport org.nostrj.core.*;\n\n// Generate new keys\nNostrKeys keys = NostrKeys.generate();\nSystem.out.println(\"Private key (hex): \" + keys.getPrivateKeyHex());\nSystem.out.println(\"Public key (hex): \" + keys.getPublicKeyHex());\nSystem.out.println(\"Private key (bech32): \" + keys.getPrivateKeyBech32());\nSystem.out.println(\"Public key (bech32): \" + keys.getPublicKeyBech32());\n\n// Create and sign an event\nNostrEvent event = new NostrEventBuilder()\n    .kind(NostrKind.TEXT_NOTE)\n    .content(\"Hello Nostr from Java!\")\n    .tag(\"t\", \"nostrj\")\n    .buildAndSign(keys);\n\n// Verify event\nboolean valid = NostrSigner.verify(event);\nSystem.out.println(\"Event valid: \" + valid);\n```\n\n### Client Module - Connect to Relays\n\n```java\nimport org.nostrj.client.*;\nimport java.net.URI;\n\n// Create client\nNostrClient client = new NostrClient();\n\n// Connect to relays\nclient.connectToRelay(\"wss://relay.damus.io\").join();\nclient.connectToRelay(\"wss://nos.lol\").join();\n\n// Publish event\nNostrEvent event = new NostrEventBuilder()\n    .kind(NostrKind.TEXT_NOTE)\n    .content(\"Hello from NostrJ!\")\n    .buildAndSign(keys);\n\nclient.publishEvent(event, \n    URI.create(\"wss://relay.damus.io\"),\n    URI.create(\"wss://nos.lol\")\n).join();\n\n// Subscribe to events\nNostrFilter filter = NostrFilter.builder()\n    .kinds(NostrKind.TEXT_NOTE)\n    .authors(keys.getPublicKeyHex())\n    .limit(10)\n    .build();\n\nclient.subscribeToAll(filter, (subId, receivedEvent) -\u003e {\n    System.out.println(\"Received: \" + receivedEvent.getContent());\n});\n\n// Close connections\nclient.close();\n```\n\n### Server Module - Custom Relay\n\n```java\nimport org.nostrj.server.*;\n\n// Initialize event store\nEventStore store = new SqliteEventStore(\"relay.db\");\nstore.initialize();\n\n// Create relay handler\nRelayHandler handler = new RelayHandler(store);\n\n// Handle incoming message (integrate with your WebSocket framework)\nString response = handler.handleMessage(sessionId, incomingMessage);\n\n// Query events\nEventQuery query = EventQuery.builder()\n    .kinds(List.of(1))\n    .limit(20)\n    .build();\n\nList\u003cNostrEvent\u003e events = store.queryEvents(query);\n```\n\n### Relay Application - Run a Relay\n\nConfigure `application.yml`:\n```yaml\nrelay:\n  name: My Nostr Relay\n  description: A relay powered by NostrJ\n  contact: admin@example.com\n  db-path: nostr-relay.db\n  enable-nip11: true\n\nmicronaut:\n  server:\n    port: 8080\n```\n\nRun the relay:\n```bash\nmvn exec:java -pl nostrj-relay-app\n```\n\nOr build and run as standalone:\n```bash\nmvn package -pl nostrj-relay-app\njava -jar nostrj-relay-app/target/nostrj-relay-app-0.1.0-SNAPSHOT.jar\n```\n\nConnect to your relay:\n- WebSocket: `ws://localhost:8080/`\n- Relay Info (NIP-11): `http://localhost:8080/`\n- Health Check: `http://localhost:8080/health`\n\n## Testing\n\nRun all tests:\n```bash\nmvn test\n```\n\nRun tests for specific module:\n```bash\nmvn test -pl nostrj-relay-app\n```\n\nRun specific test:\n```bash\nmvn test -pl nostrj-relay-app -Dtest=RelayIntegrationTest\n```\n\n## Supported NIPs\n\n- **NIP-01**: Basic protocol flow\n- **NIP-09**: Event deletion\n- **NIP-11**: Relay information document\n- **NIP-12**: Generic tag queries\n- **NIP-15**: End of stored events notice\n- **NIP-16**: Event treatment\n- **NIP-20**: Command results\n- **NIP-22**: Event created_at limits\n- **NIP-33**: Parameterized replaceable events\n- **NIP-40**: Expiration timestamp\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────┐\n│           nostrj-relay-app (Application)        │\n│  ┌──────────────┐         ┌─────────────────┐  │\n│  │  WebSocket   │         │   HTTP API      │  │\n│  │   Handler    │         │  (NIP-11, etc)  │  │\n│  └──────┬───────┘         └────────┬────────┘  │\n│         │                          │            │\n│         └──────────┬───────────────┘            │\n│                    │                            │\n│         ┌──────────▼──────────┐                 │\n│         │   Micronaut Core    │                 │\n│         └──────────┬──────────┘                 │\n└────────────────────┼────────────────────────────┘\n                     │\n         ┌───────────▼───────────┐\n         │  nostrj-server (JAR)  │\n         │  ┌─────────────────┐  │\n         │  │ RelayHandler    │  │\n         │  ├─────────────────┤  │\n         │  │ EventStore      │  │\n         │  │  - SQLite impl  │  │\n         │  ├─────────────────┤  │\n         │  │ RelayPolicy     │  │\n         │  └─────────────────┘  │\n         └───────────┬───────────┘\n                     │\n         ┌───────────▼───────────┐\n         │  nostrj-client (JAR)  │\n         │  ┌─────────────────┐  │\n         │  │ NostrClient     │  │\n         │  ├─────────────────┤  │\n         │  │ RelayConnection │  │\n         │  ├─────────────────┤  │\n         │  │ NostrFilter     │  │\n         │  └─────────────────┘  │\n         └───────────┬───────────┘\n                     │\n         ┌───────────▼───────────┐\n         │   nostrj-core (JAR)   │\n         │  ┌─────────────────┐  │\n         │  │ NostrKeys       │  │\n         │  ├─────────────────┤  │\n         │  │ NostrEvent      │  │\n         │  ├─────────────────┤  │\n         │  │ NostrSigner     │  │\n         │  ├─────────────────┤  │\n         │  │ Bech32Util      │  │\n         │  └─────────────────┘  │\n         │         │             │\n         │  ┌──────▼──────────┐  │\n         │  │  secp256k1-jdk  │  │\n         │  └─────────────────┘  │\n         └───────────────────────┘\n```\n\n## License\n\nApache License 2.0\n\n## Contributing\n\nContributions are welcome! Please feel free to submit pull requests.\n\n## References\n\n- [Nostr Protocol](https://github.com/nostr-protocol/nostr)\n- [NIPs (Nostr Implementation Possibilities)](https://github.com/nostr-protocol/nips)\n- [secp256k1-jdk](https://github.com/bitcoinj/secp256k1-jdk)\n- [bitcoinj](https://github.com/bitcoinj/bitcoinj)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitkarrot%2Fnostrj","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbitkarrot%2Fnostrj","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbitkarrot%2Fnostrj/lists"}