Skip to content

Commit f662bdf

Browse files
authored
Merge pull request #515 from tcheeric/refactoring/design-simplification
refactor: simplify nostr-java from 9 modules to 4 (v2.0.0)
2 parents 6e344b3 + 7d85439 commit f662bdf

466 files changed

Lines changed: 5210 additions & 31643 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,80 @@ The format is inspired by Keep a Changelog, and this project adheres to semantic
66

77
## [Unreleased]
88

9-
No unreleased changes yet.
9+
### Removed
10+
- Dead code cleanup — deleted unused classes: `IContent`, `JsonContent`, `Reaction` enum, `Response`, `Nip05Content`, `Nip05ContentDecoder`, `BaseAuthMessage`, `GenericMessage`, `IKey`, `GenericEventConverter`, `GenericEventTypeClassifier`, `GenericEventDecoder`, `FiltersDecoder`, `BaseTagDecoder`, `GenericEventValidator`, `GenericEventSerializer`, `GenericEventUpdater`, `GenericTagQuery`, `HttpClientProvider`, `DefaultHttpClientProvider`.
11+
- `testAuthMessage` test and `GenericEventSupportTest` removed (tested deleted classes).
12+
- `createGenericTagQuery()` removed from `EntityFactory` (only consumer of deleted `GenericTagQuery`).
13+
14+
### Changed
15+
- `RelayAuthenticationMessage` and `CanonicalAuthenticationMessage` now extend `BaseMessage` directly (previously extended the now-deleted `BaseAuthMessage`).
16+
- `BaseKey` now directly implements `Serializable` (previously implemented the now-deleted `IKey` interface).
17+
- `Nip05Validator` now creates `HttpClient` instances directly via a `Function<Duration, HttpClient>` factory (previously used deleted `HttpClientProvider`/`DefaultHttpClientProvider` interface).
18+
19+
## [2.0.0] - 2026-02-24
20+
21+
This is a major release that implements the full design simplification described in `docs/developer/SIMPLIFICATION_PROPOSAL.md`, reducing the library from 9 modules with ~180 classes to 4 modules with ~40 classes.
22+
23+
### Added
24+
- `Kinds` utility class with static `int` constants for common Nostr event kinds (`TEXT_NOTE`, `SET_METADATA`, `CONTACT_LIST`, etc.) and range-check methods (`isReplaceable()`, `isEphemeral()`, `isAddressable()`, `isValid()`).
25+
- `GenericTag.of(String code, String... params)` factory method for concise tag creation.
26+
- `GenericTag.toArray()` returning the NIP-01 wire format `["code", "param0", "param1", ...]`.
27+
- `GenericTag` now stores tag values as `List<String>` (replacing `List<ElementAttribute>`), providing direct access via `getParams()`.
28+
- `EventFilter` builder API for composable relay filters: `.kinds()`, `.authors()`, `.since()`, `.until()`, `.addTagFilter()`, `.limit()`, `.ids()`.
29+
- `RelayTimeoutException` — typed exception replacing silent empty-list returns on relay timeout.
30+
- `ConnectionState` enum (`CONNECTING`, `CONNECTED`, `RECONNECTING`, `CLOSED`) for WebSocket connection state tracking.
31+
- `NostrRelayClient` async Virtual Thread APIs: `connectAsync(...)`, `sendAsync(...)`, and `subscribeAsync(...)`.
32+
- `Nip05Validator.validateAsync()` and `Nip05Validator.validateBatch(...)` for parallel NIP-05 validation workloads.
33+
- Spring Retry support (`@NostrRetryable`, `@Recover`) consolidated directly into `NostrRelayClient`.
34+
35+
### Changed
36+
- **Module consolidation** — merged 9 modules into 4:
37+
- `nostr-java-util` + `nostr-java-crypto``nostr-java-core`
38+
- `nostr-java-base` + `nostr-java-event``nostr-java-event`
39+
- `nostr-java-id` + `nostr-java-encryption``nostr-java-identity`
40+
- `nostr-java-client` (unchanged)
41+
- **`GenericEvent`** is now the sole event class. All 39 concrete event subclasses removed. Events are differentiated by `int kind` instead of Java type.
42+
- **`GenericTag`** is now the sole tag class. All 17 concrete tag subclasses removed. Tags are a simple `code` + `List<String> params`.
43+
- `GenericEvent.kind` changed from `Kind` enum to plain `int`. Builder simplified to `.kind(int)` only.
44+
- `GenericEvent.tags` changed from `List<BaseTag>` to `List<GenericTag>`.
45+
- `GenericEvent` implements `ISignable` directly (no longer extends `BaseEvent`).
46+
- `EventMessage` now references `GenericEvent` directly instead of `IEvent`.
47+
- `IDecoder<T>` type bound changed from `IDecoder<T extends IElement>` to unbounded `IDecoder<T>`.
48+
- `TagDeserializer` now always produces `GenericTag` with `List<String>` params — no registry dispatch.
49+
- `GenericTagSerializer` simplified to output `[code, param0, param1, ...]` directly from `List<String>`.
50+
- `GenericEventDeserializer` simplified — no subclass dispatch to concrete event types.
51+
- `NostrUtil.bytesToHex()` now uses `java.util.HexFormat` instead of hand-rolled hex encoding.
52+
- `NostrUtil.hexToBytes()` family of methods now uses `java.util.HexFormat.parseHex()` — fails fast on invalid hex instead of silently producing corrupt bytes.
53+
- WebSocket client termination detection now uses proper JSON parsing instead of brittle string-prefix matching.
54+
- `StandardWebSocketClient` renamed to `NostrRelayClient`.
55+
- `SpringWebSocketClient` absorbed into `NostrRelayClient` (single client class with retry support).
56+
- Relay subscription callbacks are now dispatched on Virtual Threads to avoid blocking inbound WebSocket processing.
57+
- `DefaultHttpClientProvider` now uses a shared Virtual Thread executor instead of creating a new executor per `HttpClient`.
58+
- All `synchronized` blocks in `NostrRelayClient` replaced with `ReentrantLock` to avoid Virtual Thread pinning.
59+
- Configurable max events per request limit (default 10,000) to prevent unbounded memory accumulation.
60+
61+
### Fixed
62+
- **`GenericTag.getCode()` NPE** — structurally eliminated by removing the dual-path tag architecture. `getCode()` is now a trivial field accessor with zero NPE risk.
63+
- Removed the remaining `synchronized` cleanup block from `NostrRelayClient.send(...)`, using `ReentrantLock` consistently to avoid VT pinning risk.
64+
- Relay timeout now throws `RelayTimeoutException` instead of silently returning an empty list, allowing callers to distinguish "no results" from "timed out".
65+
66+
### Removed
67+
- **`nostr-java-api` module** — all 26 NIP classes (NIP01–NIP99), `EventNostr`, factory classes, client managers, service layer, and configuration classes.
68+
- **`nostr-java-examples` module** — all 6 example classes.
69+
- **39 concrete event subclasses**`TextNoteEvent`, `DirectMessageEvent`, `ContactListEvent`, `ReactionEvent`, `DeletionEvent`, `EphemeralEvent`, `ReplaceableEvent`, `AddressableEvent`, all Calendar/Marketplace/Channel/NostrConnect events, and more. Use `GenericEvent` with the appropriate `int kind`.
70+
- **17 concrete tag subclasses**`EventTag`, `PubKeyTag`, `AddressTag`, `IdentifierTag`, `ReferenceTag`, `HashtagTag`, `ExpirationTag`, `UrlTag`, `SubjectTag`, `DelegationTag`, `RelaysTag`, `NonceTag`, `PriceTag`, `EmojiTag`, `GeohashTag`, `LabelTag`, `LabelNamespaceTag`, `VoteTag`. Use `GenericTag.of(code, params...)`.
71+
- **27 entity classes**`UserProfile`, `Profile`, `ChannelProfile`, `ZapRequest`, `ZapReceipt`, `Reaction`, all Cashu entities, all marketplace entities, and more.
72+
- **`Kind` enum** — replaced by `Kinds` utility class with static `int` constants.
73+
- **`ElementAttribute`** — replaced by `List<String>` in `GenericTag`.
74+
- **`TagRegistry`** — no longer needed with a single tag class.
75+
- **Interfaces and abstract classes**: `IElement`, `ITag`, `IEvent`, `IGenericElement`, `IBech32Encodable`, `Deleteable`, `BaseEvent`, `BaseTag`.
76+
- **Annotations**: `@Tag`, `@Event`, `@Key`.
77+
- **14 filter classes**`AbstractFilterable`, `KindFilter`, `AuthorFilter`, `SinceFilter`, `UntilFilter`, `HashtagTagFilter`, `AddressTagFilter`, `GeohashTagFilter`, `IdentifierTagFilter`, `ReferencedEventFilter`, `ReferencedPublicKeyFilter`, `UrlTagFilter`, `VoteTagFilter`, `GenericTagQueryFilter`. Use `EventFilter.builder()`.
78+
- **Concrete serializers/deserializers**`AddressTagSerializer`, `ReferenceTagSerializer`, `ExpirationTagSerializer`, `IdentifierTagSerializer`, `RelaysTagSerializer`, `BaseTagSerializer`, `AbstractTagSerializer`, `CalendarEventDeserializer`, `ClassifiedListingEventDeserializer`, `CashuTokenSerializer`.
79+
- **Client classes**`WebSocketClientIF`, `WebSocketClientFactory`, `SpringWebSocketClientFactory`, `SpringWebSocketClient`. Use `NostrRelayClient` directly.
80+
- **Dead code**`Marker` enum, `RelayUri` value object.
81+
- **5 old modules**`nostr-java-util`, `nostr-java-crypto`, `nostr-java-base`, `nostr-java-id`, `nostr-java-encryption` (merged into the 4 remaining modules).
82+
- Dead `pollIntervalMs` parameter from WebSocket client constructors.
1083

1184
## [1.3.0] - 2026-01-25
1285

0 commit comments

Comments
 (0)