This guide helps you migrate between major versions of nostr-java, detailing breaking changes and API replacements.
- Migrating to 2.0.0
- Migrating to 1.0.0 (historical)
Status: Released 2026-02-24
Version 2.0.0 is a major simplification that reduces the library from 9 modules (~180 classes) to 4 modules (~40 classes). See CHANGELOG.md for the full list of changes and docs/developer/SIMPLIFICATION_PROPOSAL.md for the design rationale.
| Old Module | New Module | Notes |
|---|---|---|
nostr-java-util + nostr-java-crypto |
nostr-java-core |
Merged |
nostr-java-base + nostr-java-event |
nostr-java-event |
Merged |
nostr-java-id + nostr-java-encryption |
nostr-java-identity |
Merged |
nostr-java-client |
nostr-java-client |
Unchanged |
nostr-java-api |
(removed) | Use GenericEvent directly |
nostr-java-examples |
(removed) | See docs/howto guides |
Dependency: Replace nostr-java-api with nostr-java-client (transitively includes all modules):
<!-- Before -->
<artifactId>nostr-java-api</artifactId>
<!-- After -->
<artifactId>nostr-java-client</artifactId>// Before (1.x)
NIP01 nip01 = new NIP01(identity);
nip01.createTextNoteEvent("Hello Nostr!")
.sign()
.send(relays);
// After (2.0)
GenericEvent event = GenericEvent.builder()
.pubKey(identity.getPublicKey())
.kind(Kinds.TEXT_NOTE)
.content("Hello Nostr!")
.build();
identity.sign(event);
try (NostrRelayClient client = new NostrRelayClient("wss://relay.398ja.xyz")) {
client.send(new EventMessage(event));
}// Before (1.x)
EventTag eTag = new EventTag("abc123", "wss://relay.example.com", Marker.REPLY);
PubKeyTag pTag = new PubKeyTag(recipientPublicKey);
HashtagTag hTag = new HashtagTag("nostr");
// After (2.0)
GenericTag.of("e", "abc123", "wss://relay.example.com", "reply")
GenericTag.of("p", recipientPublicKey.toString())
GenericTag.of("t", "nostr")// Before (1.x)
Kind.TEXT_NOTE // Kind enum
Kind.TEXT_NOTE.getValue() // to get int
// After (2.0)
Kinds.TEXT_NOTE // static int constant (value: 1)// Before (1.x)
new Filters(
new KindFilter<>(Kind.TEXT_NOTE),
new AuthorFilter<>(pubKey),
new SinceFilter(timestamp)
);
// After (2.0)
EventFilter.builder()
.kinds(List.of(Kinds.TEXT_NOTE))
.authors(List.of(pubKeyHex))
.since(timestamp)
.build();// Before (1.x) — StandardWebSocketClient or SpringWebSocketClient
StandardWebSocketClient client = new StandardWebSocketClient("wss://relay.example.com");
// or: SpringWebSocketClient client = new SpringWebSocketClient(wsClient);
// After (2.0) — NostrRelayClient (with retry, VT dispatch, async APIs)
NostrRelayClient client = new NostrRelayClient("wss://relay.example.com");
// Async:
NostrRelayClient.connectAsync("wss://relay.example.com");// Before (1.x) — silent empty list on timeout
List<String> events = client.send(message); // returns empty list on timeout
// After (2.0) — throws RelayTimeoutException
try {
List<String> events = client.send(message);
} catch (RelayTimeoutException e) {
// explicit timeout handling
}- All 26 NIP classes (
NIP01–NIP99) andEventNostr - All 39 concrete event subclasses (
TextNoteEvent,ReactionEvent, etc.) - All 17 concrete tag subclasses (
EventTag,PubKeyTag, etc.) - All 27 entity classes (
UserProfile,ZapRequest, etc.) Kindenum,ElementAttribute,TagRegistry,BaseTag,BaseEventIElement,ITag,IEvent,IGenericElement,IBech32Encodable,Deleteable@Tag,@Event,@Keyannotations- 14 filter classes (
KindFilter,AuthorFilter, etc.) WebSocketClientIF,WebSocketClientFactory,SpringWebSocketClientFactory,SpringWebSocketClient
Status: Released 2025-10-13 Deprecation Warnings Since: 0.6.2
Version 1.0.0 will remove all APIs deprecated in the 0.6.x series. This guide helps you prepare your codebase for a smooth upgrade.
The following deprecated APIs will be removed in 1.0.0. Migrate to the recommended alternatives before upgrading.
-
Removed:
nostr.config.Constants.Kindnested class- Use:
nostr.base.Kindenum andKind#getValue()when an integer is required - See: Event Kind Constants
- Use:
-
Removed:
nostr.base.Encoder.ENCODER_MAPPER_BLACKBIRD- Use:
nostr.event.json.EventJsonMapper.getMapper()for event JSON - Also available:
nostr.base.json.EventJsonMapper.mapper()in tests/utility contexts - See: ObjectMapper Usage
- Use:
-
Removed:
nostr.api.NIP01#createTextNoteEvent(Identity, String)- Use:
new NIP01(identity).createTextNoteEvent(String)with sender configured on the instance - See: NIP01 API Changes
- Use:
-
Removed:
nostr.api.NIP61#createNutzapEvent(Amount, List<CashuProof>, URL, List<EventTag>, PublicKey, String)- Use:
createNutzapEvent(List<CashuProof>, URL, EventTag, PublicKey, String) - And add amount/unit tags explicitly via
NIP60.createAmountTag(Amount)andNIP60.createUnitTag(String)if needed
- Use:
-
Removed:
nostr.event.tag.GenericTag(String, Integer)constructor- Use:
new GenericTag(String)ornew GenericTag(String, ElementAttribute...)
- Use:
-
Removed:
nostr.id.EntityFactory.Events#createGenericTag(PublicKey, IEvent, Integer)- Use:
createGenericTag(PublicKey, IEvent)
- Use:
These removals were announced with @Deprecated(forRemoval = true) in 0.6.2 and are now finalized in 1.0.0.
Deprecated Since: 0.6.2 Removed In: 1.0.0 Migration Difficulty: 🟢 Easy (find & replace)
The Constants.Kind class is deprecated in favor of the Kind enum, which provides better type safety and IDE support.
import nostr.config.Constants;
// Using deprecated integer constants
int kind = Constants.Kind.TEXT_NOTE;
int dmKind = Constants.Kind.ENCRYPTED_DIRECT_MESSAGE;
int zapKind = Constants.Kind.ZAP_REQUEST;import nostr.base.Kind;
// Using Kind enum
Kind kind = Kind.TEXT_NOTE;
Kind dmKind = Kind.ENCRYPTED_DIRECT_MESSAGE;
Kind zapKind = Kind.ZAP_REQUEST;
// Get integer value when needed
int kindValue = Kind.TEXT_NOTE.getValue();| Deprecated Constant | New Enum | Notes |
|---|---|---|
Constants.Kind.USER_METADATA |
Kind.SET_METADATA |
Renamed for consistency |
Constants.Kind.SHORT_TEXT_NOTE |
Kind.TEXT_NOTE |
Simplified name |
Constants.Kind.RECOMMENDED_RELAY |
Kind.RECOMMEND_SERVER |
Renamed for accuracy |
Constants.Kind.CONTACT_LIST |
Kind.CONTACT_LIST |
Same name |
Constants.Kind.ENCRYPTED_DIRECT_MESSAGE |
Kind.ENCRYPTED_DIRECT_MESSAGE |
Same name |
Constants.Kind.EVENT_DELETION |
Kind.DELETION |
Simplified name |
Constants.Kind.REPOST |
Kind.REPOST |
Same name |
Constants.Kind.REACTION |
Kind.REACTION |
Same name |
Constants.Kind.REACTION_TO_WEBSITE |
Kind.REACTION_TO_WEBSITE |
Same name |
Constants.Kind.CHANNEL_CREATION |
Kind.CHANNEL_CREATE |
Renamed for consistency |
Constants.Kind.CHANNEL_METADATA |
Kind.CHANNEL_METADATA |
Same name |
Constants.Kind.CHANNEL_MESSAGE |
Kind.CHANNEL_MESSAGE |
Same name |
Constants.Kind.CHANNEL_HIDE_MESSAGE |
Kind.HIDE_MESSAGE |
Simplified name |
Constants.Kind.CHANNEL_MUTE_USER |
Kind.MUTE_USER |
Simplified name |
Constants.Kind.OTS_ATTESTATION |
Kind.OTS_EVENT |
Renamed for consistency |
Constants.Kind.REPORT |
Kind.REPORT |
Same name |
Constants.Kind.ZAP_REQUEST |
Kind.ZAP_REQUEST |
Same name |
Constants.Kind.ZAP_RECEIPT |
Kind.ZAP_RECEIPT |
Same name |
Constants.Kind.RELAY_LIST_METADATA |
Kind.RELAY_LIST_METADATA |
Same name |
Constants.Kind.RELAY_LIST_METADATA_EVENT |
Kind.RELAY_LIST_METADATA |
Duplicate removed |
Constants.Kind.CLIENT_AUTHENTICATION |
Kind.CLIENT_AUTH |
Simplified name |
Constants.Kind.REQUEST_EVENTS |
Kind.REQUEST_EVENTS |
Same name |
Constants.Kind.BADGE_DEFINITION |
Kind.BADGE_DEFINITION |
Same name |
Constants.Kind.BADGE_AWARD |
Kind.BADGE_AWARD |
Same name |
Constants.Kind.SET_STALL |
Kind.STALL_CREATE_OR_UPDATE |
Renamed for clarity |
# Example sed commands for bulk migration (test first!)
find . -name "*.java" -exec sed -i 's/Constants\.Kind\.TEXT_NOTE/Kind.TEXT_NOTE/g' {} \;
find . -name "*.java" -exec sed -i 's/Constants\.Kind\.ENCRYPTED_DIRECT_MESSAGE/Kind.ENCRYPTED_DIRECT_MESSAGE/g' {} \;
# ... repeat for other constants- Type Safety: Enum provides compile-time type checking
- IDE Support: Better autocomplete and refactoring
- Extensibility: Easier to add new kinds and metadata
- Clean Architecture: Removes dependency on Constants utility class
Deprecated Since: 0.6.2 Removed In: 1.0.0 Migration Difficulty: 🟢 Easy (find & replace)
The Encoder.ENCODER_MAPPER_BLACKBIRD static field was an anti-pattern (static field in interface). It's now replaced by a dedicated utility class.
import nostr.base.Encoder;
// Using deprecated static field from interface
ObjectMapper mapper = Encoder.ENCODER_MAPPER_BLACKBIRD;
String json = mapper.writeValueAsString(event);import nostr.event.json.EventJsonMapper;
// Using dedicated utility class
ObjectMapper mapper = EventJsonMapper.getMapper();
String json = mapper.writeValueAsString(event);- Better Design: Removes anti-pattern (static field in interface)
- Single Responsibility: JSON configuration in dedicated class
- Discoverability: Clear location for JSON mapper configuration
- Maintainability: Single place to update mapper settings
For most use cases, you don't need the mapper directly. Use event serialization methods instead:
// Recommended: Use built-in serialization
GenericEvent event = ...;
String json = event.toJson();
// Deserialization
GenericEvent event = GenericEvent.fromJson(json);Deprecated Since: 0.6.2 Removed In: 1.0.0 Migration Difficulty: 🟡 Medium (requires code changes)
The createTextNoteEvent(Identity, String) method signature is changing to remove the redundant Identity parameter (the sender is already set in the NIP01 instance).
import nostr.api.NIP01;
import nostr.id.Identity;
Identity sender = new Identity("nsec1...");
NIP01 nip01 = new NIP01(sender);
// Redundant: sender passed both in constructor AND method
nip01.createTextNoteEvent(sender, "Hello Nostr!")
.sign()
.send(relays);import nostr.api.NIP01;
import nostr.id.Identity;
Identity sender = new Identity("nsec1...");
NIP01 nip01 = new NIP01(sender);
// Cleaner: sender only passed in constructor
nip01.createTextNoteEvent("Hello Nostr!")
.sign()
.send(relays);-
Find all usages:
grep -r "createTextNoteEvent(" --include="*.java"
-
Update method calls:
- Remove the first parameter (Identity)
- Keep the content parameter
-
Verify sender is set:
- Ensure NIP01 constructor receives the Identity
- Or use
setSender(identity)before calling methods
- DRY Principle: Don't repeat yourself (sender already in instance)
- Consistency: Matches pattern used by other NIP classes
- Less Verbose: Simpler API with fewer parameters
- Clearer Intent: Sender is instance state, not method parameter
Impact: 🔴 High (widely used)
The entire nostr.config.Constants.Kind class will be removed. Migrate to nostr.base.Kind enum.
Migration: See Event Kind Constants section above.
Impact: 🟡 Medium (internal usage mostly)
The nostr.base.Encoder.ENCODER_MAPPER_BLACKBIRD field will be removed.
Migration: See ObjectMapper Usage section above.
Impact: 🟡 Medium (common usage)
Method signature changes in NIP01:
createTextNoteEvent(Identity, String)→createTextNoteEvent(String)
Migration: See NIP01 API Changes section above.
-
Run compiler with warnings enabled
mvn clean compile -Xlint:deprecation
-
Search for deprecated API usage
grep -r "Constants.Kind\." --include="*.java" src/ grep -r "ENCODER_MAPPER_BLACKBIRD" --include="*.java" src/ grep -r "createTextNoteEvent(.*,.*)" --include="*.java" src/
-
Update imports
- Replace
import nostr.config.Constants;withimport nostr.base.Kind; - Replace
import nostr.base.Encoder;withimport nostr.event.json.EventJsonMapper;
- Replace
-
Update constants
- Replace all
Constants.Kind.XwithKind.X - Update any renamed constants (see migration table)
- Replace all
-
Update method calls
- Remove redundant
Identityparameter fromcreateTextNoteEvent()
- Remove redundant
-
Run tests
mvn clean test -
Verify no deprecation warnings
mvn clean compile -Xlint:deprecation 2>&1 | grep "deprecated"
- Analyze → Run Inspection by Name
- Search for "Deprecated API Usage"
- Apply suggested fixes
- Project → Properties → Java Compiler → Errors/Warnings
- Enable "Deprecated and restricted API"
- Use Quick Fixes (Ctrl+1) on warnings
#!/bin/bash
# Automated migration script (BACKUP YOUR CODE FIRST!)
# Replace Kind constants
find src/ -name "*.java" -exec sed -i 's/Constants\.Kind\.TEXT_NOTE/Kind.TEXT_NOTE/g' {} \;
find src/ -name "*.java" -exec sed -i 's/Constants\.Kind\.ENCRYPTED_DIRECT_MESSAGE/Kind.ENCRYPTED_DIRECT_MESSAGE/g' {} \;
# Replace ObjectMapper
find src/ -name "*.java" -exec sed -i 's/Encoder\.ENCODER_MAPPER_BLACKBIRD/EventJsonMapper.getMapper()/g' {} \;
# Note: NIP01 method calls require manual review due to parameter removalIf you encounter issues during migration:
- Check the documentation: docs/
- Review examples: nostr-java-examples/
- Ask for help: GitHub Issues
- Join discussions: GitHub Discussions
| Version | Release Date | Major Changes |
|---|---|---|
| 0.6.2 | 2025-10-06 | Deprecation warnings added for 1.0.0 |
| 0.6.3 | 2025-10-07 | Extended JavaDoc, exception hierarchy |
| 1.0.0 | TBD | Deprecated APIs removed (breaking) |
Last Updated: 2025-10-07 Applies To: nostr-java 0.6.2 → 1.0.0