diff --git a/.gitignore b/.gitignore
index b32ca7f82..caf79dd32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -213,10 +213,9 @@ target/
# Gradle files
.gradle/
-build/
-gradle/
-gradlew
-gradlew.bat
+#gradle/
+#gradlew
+#gradlew.bat
buildSrc/build
### VisualStudioCode ###
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 24807fb22..6d34a5d5a 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -11,7 +11,7 @@ plugins {
}
group = 'xyz.tcheeric'
-version = '0.6.6-SNAPSHOT'
+version = '0.7-SNAPSHOT'
repositories {
mavenCentral()
diff --git a/gradle.properties b/gradle.properties
index 2bd5042ba..8b14d425f 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -6,7 +6,7 @@ org.gradle.parallel=true
org.gradle.warning.mode=none
nostr-java.group=xyz.tcheeric
-nostr-java.version=0.6.6-SNAPSHOT
+nostr-java.version=0.7-SNAPSHOT
nostr-java.description=nostr-java
nostr-java.java-version=21
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 000000000..14066f43f
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,34 @@
+# This file was generated by the Gradle 'init' task.
+# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
+
+[versions]
+com-fasterxml-jackson-module-jackson-module-afterburner = "2.18.3"
+com-google-guava-guava = "33.4.0-jre"
+io-projectreactor-netty-reactor-netty-http = "1.1.20"
+jakarta-websocket-jakarta-websocket-api = "2.2.0"
+jakarta-websocket-jakarta-websocket-client-api = "2.2.0"
+org-apache-commons-commons-lang3 = "3.17.0"
+org-awaitility-awaitility = "4.2.2"
+org-bouncycastle-bcprov-jdk18on = "1.78"
+org-junit-jupiter-junit-jupiter-api = "5.10.2"
+org-projectlombok-lombok = "1.18.34"
+org-springframework-boot-spring-boot-starter-test = "3.4.3"
+org-springframework-boot-spring-boot-starter-websocket = "3.4.3"
+org-springframework-spring-webflux = "6.1.10"
+org-springframework-spring-websocket = "6.1.10"
+
+[libraries]
+com-fasterxml-jackson-module-jackson-module-afterburner = { module = "com.fasterxml.jackson.module:jackson-module-afterburner", version.ref = "com-fasterxml-jackson-module-jackson-module-afterburner" }
+com-google-guava-guava = { module = "com.google.guava:guava", version.ref = "com-google-guava-guava" }
+io-projectreactor-netty-reactor-netty-http = { module = "io.projectreactor.netty:reactor-netty-http", version.ref = "io-projectreactor-netty-reactor-netty-http" }
+jakarta-websocket-jakarta-websocket-api = { module = "jakarta.websocket:jakarta.websocket-api", version.ref = "jakarta-websocket-jakarta-websocket-api" }
+jakarta-websocket-jakarta-websocket-client-api = { module = "jakarta.websocket:jakarta.websocket-client-api", version.ref = "jakarta-websocket-jakarta-websocket-client-api" }
+org-apache-commons-commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "org-apache-commons-commons-lang3" }
+org-awaitility-awaitility = { module = "org.awaitility:awaitility", version.ref = "org-awaitility-awaitility" }
+org-bouncycastle-bcprov-jdk18on = { module = "org.bouncycastle:bcprov-jdk18on", version.ref = "org-bouncycastle-bcprov-jdk18on" }
+org-junit-jupiter-junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "org-junit-jupiter-junit-jupiter-api" }
+org-projectlombok-lombok = { module = "org.projectlombok:lombok", version.ref = "org-projectlombok-lombok" }
+org-springframework-boot-spring-boot-starter-test = { module = "org.springframework.boot:spring-boot-starter-test", version.ref = "org-springframework-boot-spring-boot-starter-test" }
+org-springframework-boot-spring-boot-starter-websocket = { module = "org.springframework.boot:spring-boot-starter-websocket", version.ref = "org-springframework-boot-spring-boot-starter-websocket" }
+org-springframework-spring-webflux = { module = "org.springframework:spring-webflux", version.ref = "org-springframework-spring-webflux" }
+org-springframework-spring-websocket = { module = "org.springframework:spring-websocket", version.ref = "org-springframework-spring-websocket" }
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..37f853b1c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 000000000..faf93008b
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,251 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 000000000..9b42019c7
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,94 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+@rem SPDX-License-Identifier: Apache-2.0
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/nostr-java-api/pom.xml b/nostr-java-api/pom.xml
index c96a05475..fb202e5f0 100644
--- a/nostr-java-api/pom.xml
+++ b/nostr-java-api/pom.xml
@@ -4,7 +4,7 @@
xyz.tcheeric
nostr-java
- 0.6.6-SNAPSHOT
+ 0.7-SNAPSHOT
../pom.xml
diff --git a/nostr-java-api/src/main/java/nostr/api/EventNostr.java b/nostr-java-api/src/main/java/nostr/api/EventNostr.java
index 564839acb..8955e90f5 100644
--- a/nostr-java-api/src/main/java/nostr/api/EventNostr.java
+++ b/nostr-java-api/src/main/java/nostr/api/EventNostr.java
@@ -8,12 +8,12 @@
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.Setter;
-import nostr.api.factory.impl.GenericEventFactory;
import nostr.base.PublicKey;
import nostr.event.BaseMessage;
import nostr.event.BaseTag;
import nostr.event.impl.GenericEvent;
import nostr.event.json.codec.BaseMessageDecoder;
+import nostr.event.message.GenericMessage;
import nostr.id.Identity;
import org.apache.commons.lang3.stream.Streams.FailableStream;
@@ -26,10 +26,10 @@
*/
@Getter
@NoArgsConstructor
-public abstract class EventNostr extends NostrSpringWebSocketClient {
+public abstract class EventNostr extends NostrSpringWebSocketClient {
@Setter
- private T event;
+ private GenericEvent event;
private PublicKey recipient;
@@ -81,29 +81,13 @@ public EventNostr setRecipient(@NonNull PublicKey recipient) {
return this;
}
+ public void updateEvent(@NonNull GenericEvent event) {
+ this.setEvent(event);
+ this.event.update();
+ }
+
public EventNostr addTag(@NonNull BaseTag tag) {
getEvent().addTag(tag);
return this;
}
-
- @NoArgsConstructor
- public static class GenericEventNostr extends EventNostr {
-
- public GenericEventNostr(@NonNull Identity sender) {
- super.setSender(sender);
- }
-
- /**
- * @param content
- * @return
- */
- public GenericEventNostr createGenericEvent(@NonNull Integer kind, @NonNull String content) {
- var factory = new GenericEventFactory(getSender(), kind, content);
- var event = factory.create();
- setEvent((T) event);
-
- return this;
- }
-
- }
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP01.java b/nostr-java-api/src/main/java/nostr/api/NIP01.java
index 16591fe8f..9c3b3ef15 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP01.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP01.java
@@ -5,28 +5,16 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP01Impl.AddressTagFactory;
-import nostr.api.factory.impl.NIP01Impl.CloseMessageFactory;
-import nostr.api.factory.impl.NIP01Impl.EoseMessageFactory;
-import nostr.api.factory.impl.NIP01Impl.EphemeralEventFactory;
-import nostr.api.factory.impl.NIP01Impl.EventMessageFactory;
-import nostr.api.factory.impl.NIP01Impl.EventTagFactory;
-import nostr.api.factory.impl.NIP01Impl.IdentifierTagFactory;
-import nostr.api.factory.impl.NIP01Impl.MetadataEventFactory;
-import nostr.api.factory.impl.NIP01Impl.NoticeMessageFactory;
-import nostr.api.factory.impl.NIP01Impl.ParameterizedReplaceableEventFactory;
-import nostr.api.factory.impl.NIP01Impl.PubKeyTagFactory;
-import nostr.api.factory.impl.NIP01Impl.ReplaceableEventFactory;
-import nostr.api.factory.impl.NIP01Impl.ReqMessageFactory;
-import nostr.api.factory.impl.NIP01Impl.TextNoteEventFactory;
-import nostr.base.IEvent;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.base.Marker;
import nostr.base.PublicKey;
import nostr.base.Relay;
-import nostr.base.UserProfile;
+import nostr.config.Constants;
import nostr.event.BaseTag;
-import nostr.event.Marker;
-import nostr.event.NIP01Event;
+import nostr.event.entities.UserProfile;
import nostr.event.filter.Filters;
+import nostr.event.impl.GenericEvent;
import nostr.event.message.CloseMessage;
import nostr.event.message.EoseMessage;
import nostr.event.message.EventMessage;
@@ -34,19 +22,21 @@
import nostr.event.message.ReqMessage;
import nostr.event.tag.AddressTag;
import nostr.event.tag.EventTag;
+import nostr.event.tag.GenericTag;
import nostr.event.tag.IdentifierTag;
import nostr.event.tag.PubKeyTag;
import nostr.id.Identity;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
- *
* @author eric
*/
-public class NIP01 extends EventNostr {
+public class NIP01 extends EventNostr {
- public NIP01(@NonNull Identity sender) {
+ public NIP01(Identity sender) {
setSender(sender);
}
@@ -56,39 +46,43 @@ public NIP01(@NonNull Identity sender) {
* @param content the content of the note
* @return the text note without tags
*/
- public NIP01 createTextNoteEvent(@NonNull String content) {
- var event = new TextNoteEventFactory(getSender(), content).create();
- this.setEvent((T) event);
-
+ public NIP01 createTextNoteEvent(String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.SHORT_TEXT_NOTE, content).create();
+ this.updateEvent(genericEvent);
return this;
}
@Deprecated
- public NIP01 createTextNoteEvent(@NonNull Identity sender, @NonNull String content) {
- var event = new TextNoteEventFactory(sender, content).create();
- this.setEvent((T) event);
+ public NIP01 createTextNoteEvent(Identity sender, String content) {
+ GenericEvent genericEvent = new GenericEventFactory(sender, Constants.Kind.SHORT_TEXT_NOTE, content).create();
+ this.updateEvent(genericEvent);
+ return this;
+ }
+ public NIP01 createTextNoteEvent(Identity sender, String content, List recipients) {
+ GenericEvent genericEvent = new GenericEventFactory(sender, Constants.Kind.SHORT_TEXT_NOTE, (List) (List>) recipients, content).create();
+ this.updateEvent(genericEvent);
return this;
}
/**
- * Create a NIP01 text note event with tags
+ * Create a NIP01 text note event with recipients
*
- * @param tags the note tags
+ * @param tags the tags
* @param content the content of the note
* @return a text note event
*/
- public NIP01 createTextNoteEvent(@NonNull List tags, @NonNull String content) {
- setEvent((T) new TextNoteEventFactory(getSender(), tags, content).create());
+ public NIP01 createTextNoteEvent(@NonNull List tags, @NonNull String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.SHORT_TEXT_NOTE, tags, content).create();
+ this.updateEvent(genericEvent);
return this;
}
- public NIP01 createMetadataEvent(@NonNull UserProfile profile) {
+ public NIP01 createMetadataEvent(@NonNull UserProfile profile) {
var sender = getSender();
- var event = (sender != null) ? new MetadataEventFactory(sender, profile).create()
- : new MetadataEventFactory(profile).create();
-
- this.setEvent((T) event);
+ GenericEvent genericEvent = (sender != null) ? new GenericEventFactory(sender, Constants.Kind.USER_METADATA, profile.toString()).create()
+ : new GenericEventFactory(Constants.Kind.USER_METADATA, profile.toString()).create();
+ this.updateEvent(genericEvent);
return this;
}
@@ -98,10 +92,10 @@ public NIP01 createMetadataEvent(@NonNull UserProfile profile) {
* @param kind the kind (10000 <= kind < 20000 || kind == 0 || kind == 3)
* @param content the content
*/
- public NIP01 createReplaceableEvent(@NonNull Integer kind, String content) {
- var event = new ReplaceableEventFactory(getSender(), kind, content).create();
-
- this.setEvent((T) event);
+ public NIP01 createReplaceableEvent(Integer kind, String content) {
+ var sender = getSender();
+ GenericEvent genericEvent = new GenericEventFactory(sender, kind, content).create();
+ this.updateEvent(genericEvent);
return this;
}
@@ -112,10 +106,23 @@ public NIP01 createReplaceableEvent(@NonNull Integer kind, String content) {
* @param kind the kind (10000 <= kind < 20000 || kind == 0 || kind == 3)
* @param content the note's content
*/
- public NIP01 createReplaceableEvent(@NonNull List tags, @NonNull Integer kind, String content) {
- var event = new ReplaceableEventFactory(getSender(), tags, kind, content).create();
-
- this.setEvent((T) event);
+ public NIP01 createReplaceableEvent(List tags, Integer kind, String content) {
+ var sender = getSender();
+ GenericEvent genericEvent = new GenericEventFactory(sender, kind, tags, content).create();
+ this.updateEvent(genericEvent);
+ return this;
+ }
+ /**
+ * Create an ephemeral event
+ *
+ * @param kind the kind (20000 <= n < 30000)
+ * @param tags the note's tags
+ * @param content the note's content
+ */
+ public NIP01 createEphemeralEvent(List tags, Integer kind, String content) {
+ var sender = getSender();
+ GenericEvent genericEvent = new GenericEventFactory(sender, kind, tags, content).create();
+ this.updateEvent(genericEvent);
return this;
}
@@ -125,37 +132,102 @@ public NIP01 createReplaceableEvent(@NonNull List tags, @NonNull Int
* @param kind the kind (20000 <= n < 30000)
* @param content the note's content
*/
- public NIP01 createEphemeralEvent(@NonNull Integer kind, String content) {
- var event = new EphemeralEventFactory(getSender(), kind, content).create();
+ public NIP01 createEphemeralEvent(Integer kind, String content) {
+ var sender = getSender();
+ GenericEvent genericEvent = new GenericEventFactory(sender, kind, content).create();
+ this.updateEvent(genericEvent);
+ return this;
+ }
+
+
+ /**
+ * @param content the event's comment
+ */
+ public NIP01 createAddressableEvent(Integer kind, String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), kind, content).create();
+ this.updateEvent(genericEvent);
+ return this;
+ }
- this.setEvent((T) event);
+ /**
+ * @param tags
+ * @param kind
+ * @param content
+ * @return
+ */
+ public NIP01 createAddressableEvent(@NonNull List tags, @NonNull Integer kind, String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), kind, (List) (List>) tags, content).create();
+ this.updateEvent(genericEvent);
return this;
}
/**
* Create a NIP01 event tag
*
- * @param relateEventId the related event id
+ * @param relatedEventId the related event id
* @return an event tag with the id of the related event
*/
- public static EventTag createEventTag(@NonNull String relateEventId) {
- return new EventTagFactory(relateEventId).create();
+ public static BaseTag createEventTag(@NonNull String relatedEventId) {
+ List params = List.of(relatedEventId);
+ return new BaseTagFactory(Constants.Tag.EVENT_CODE, params).create();
}
/**
* Create a NIP01 event tag with additional recommended relay and marker
*
- * @param relateEventId the related event id
- * @param recommendedRelayUrl the recommended relay
+ * @param idEvent the related event id
+ * @param recommendedRelayUrl the recommended relay url
* @param marker the marker
* @return an event tag with the id of the related event and optional
- * recommended relay and marker
+ * recommended relay and marker
*/
- public static EventTag createEventTag(@NonNull String relateEventId, String recommendedRelayUrl, Marker marker) {
- var result = new EventTagFactory(relateEventId).create();
- result.setMarker(marker);
- result.setRecommendedRelayUrl(recommendedRelayUrl);
- return result;
+ public static BaseTag createEventTag(@NonNull String idEvent, String recommendedRelayUrl, Marker marker) {
+
+ List params = new ArrayList<>();
+ params.add(idEvent);
+ if (recommendedRelayUrl != null) {
+ params.add(recommendedRelayUrl);
+ }
+ if (marker != null) {
+ params.add(marker.getValue());
+ }
+
+ return new BaseTagFactory(Constants.Tag.EVENT_CODE, params).create();
+ }
+
+ /**
+ * Create a NIP01 event tag with additional recommended relay and marker
+ *
+ * @param idEvent the related event id
+ * @param marker the marker
+ * @return an event tag with the id of the related event and optional
+ * recommended relay and marker
+ */
+ public static BaseTag createEventTag(@NonNull String idEvent, Marker marker) {
+ return createEventTag(idEvent, (String) null, marker);
+ }
+
+ /**
+ * Create a NIP01 event tag with additional recommended relay and marker
+ *
+ * @param idEvent the related event id
+ * @param recommendedRelay the recommended relay
+ * @param marker the marker
+ * @return an event tag with the id of the related event and optional
+ * recommended relay and marker
+ */
+ public static BaseTag createEventTag(@NonNull String idEvent, Relay recommendedRelay, Marker marker) {
+
+ List params = new ArrayList<>();
+ params.add(idEvent);
+ if (recommendedRelay != null) {
+ params.add(recommendedRelay.getUri());
+ }
+ if (marker != null) {
+ params.add(marker.getValue());
+ }
+
+ return new BaseTagFactory(Constants.Tag.EVENT_CODE, params).create();
}
/**
@@ -163,10 +235,13 @@ public static EventTag createEventTag(@NonNull String relateEventId, String reco
*
* @param publicKey the associated public key
* @return a pubkey tag with the hex representation of the associated public
- * key
+ * key
*/
- public static PubKeyTag createPubKeyTag(@NonNull PublicKey publicKey) {
- return new PubKeyTagFactory(publicKey).create();
+ public static BaseTag createPubKeyTag(@NonNull PublicKey publicKey) {
+ List params = new ArrayList<>();
+ params.add(publicKey.toString());
+
+ return new BaseTagFactory(Constants.Tag.PUBKEY_CODE, params).create();
}
/**
@@ -177,13 +252,84 @@ public static PubKeyTag createPubKeyTag(@NonNull PublicKey publicKey) {
* @param mainRelayUrl the recommended relay
* @param petName the petname
* @return a pubkey tag with the hex representation of the associated public
- * key and the optional recommended relay and petname
+ * key and the optional recommended relay and petname
*/
- public static PubKeyTag createPubKeyTag(@NonNull PublicKey publicKey, String mainRelayUrl, String petName) {
- var result = new PubKeyTagFactory(publicKey).create();
- result.setMainRelayUrl(mainRelayUrl);
- result.setPetName(petName);
- return result;
+ // TODO - Method overloading with Relay as second parameter
+ public static BaseTag createPubKeyTag(@NonNull PublicKey publicKey, String mainRelayUrl, String petName) {
+ List params = new ArrayList<>();
+ params.add(publicKey.toString());
+ params.add(mainRelayUrl);
+ params.add(petName);
+
+ return new BaseTagFactory(Constants.Tag.PUBKEY_CODE, params).create();
+ }
+
+ /**
+ * Create a NIP01 pubkey tag with additional recommended relay and petname
+ * (as defined in NIP02)
+ *
+ * @param publicKey the associated public key
+ * @param mainRelayUrl the recommended relay
+ * @return a pubkey tag with the hex representation of the associated public
+ * key and the optional recommended relay and petname
+ */
+ // TODO - Method overloading with Relay as second parameter
+ public static BaseTag createPubKeyTag(@NonNull PublicKey publicKey, String mainRelayUrl) {
+ List params = new ArrayList<>();
+ params.add(publicKey.toString());
+ params.add(mainRelayUrl);
+
+ return new BaseTagFactory(Constants.Tag.PUBKEY_CODE, params).create();
+ }
+
+ /**
+ * @param id
+ * @return
+ */
+ public static BaseTag createIdentifierTag(@NonNull String id) {
+ List params = new ArrayList<>();
+ params.add(id);
+
+ return new BaseTagFactory(Constants.Tag.IDENTITY_CODE, params).create();
+ }
+
+ /**
+ * @param kind
+ * @param publicKey
+ * @param idTag
+ * @param relay
+ * @return
+ */
+ public static BaseTag createAddressTag(@NonNull Integer kind, @NonNull PublicKey publicKey, BaseTag idTag, Relay relay) {
+ if (idTag != null && !idTag.getCode().equals(Constants.Tag.IDENTITY_CODE)) {
+ throw new IllegalArgumentException("idTag must be an identifier tag");
+ }
+
+ List params = new ArrayList<>();
+ String param = kind + ":" + publicKey + ":";
+ if (idTag != null) {
+ if (idTag instanceof IdentifierTag) {
+ param += ((IdentifierTag) idTag).getUuid();
+ } else {
+ // Should hopefully never happen
+ throw new IllegalArgumentException("idTag must be an identifier tag");
+ }
+ }
+ params.add(param);
+
+ if (relay != null) {
+ params.add(relay.getUri());
+ }
+
+ return new BaseTagFactory(Constants.Tag.ADDRESS_CODE, params).create();
+ }
+
+ public static BaseTag createAddressTag(@NonNull Integer kind, @NonNull PublicKey publicKey, String id, Relay relay) {
+ return createAddressTag(kind, publicKey, createIdentifierTag(id), relay);
+ }
+
+ public static BaseTag createAddressTag(@NonNull Integer kind, @NonNull PublicKey publicKey, String id) {
+ return createAddressTag(kind, publicKey, createIdentifierTag(id), null);
}
/**
@@ -193,8 +339,10 @@ public static PubKeyTag createPubKeyTag(@NonNull PublicKey publicKey, String mai
* @param subscriptionId the related subscription id
* @return an event message
*/
- public static EventMessage createEventMessage(@NonNull IEvent event, @NonNull String subscriptionId) {
- return new EventMessageFactory(event, subscriptionId).create();
+ public static EventMessage createEventMessage(@NonNull GenericEvent event, String subscriptionId) {
+ return Optional.ofNullable(subscriptionId)
+ .map(subId -> new EventMessage(event, subId))
+ .orElse(new EventMessage(event));
}
/**
@@ -205,7 +353,7 @@ public static EventMessage createEventMessage(@NonNull IEvent event, @NonNull St
* @return a REQ message
*/
public static ReqMessage createReqMessage(@NonNull String subscriptionId, @NonNull List filtersList) {
- return new ReqMessageFactory(subscriptionId, filtersList).create();
+ return new ReqMessage(subscriptionId, filtersList);
}
/**
@@ -215,7 +363,7 @@ public static ReqMessage createReqMessage(@NonNull String subscriptionId, @NonNu
* @return a CLOSE message
*/
public static CloseMessage createCloseMessage(@NonNull String subscriptionId) {
- return new CloseMessageFactory(subscriptionId).create();
+ return new CloseMessage(subscriptionId);
}
/**
@@ -226,7 +374,7 @@ public static CloseMessage createCloseMessage(@NonNull String subscriptionId) {
* @return an EOSE message
*/
public static EoseMessage createEoseMessage(@NonNull String subscriptionId) {
- return new EoseMessageFactory(subscriptionId).create();
+ return new EoseMessage(subscriptionId);
}
/**
@@ -237,60 +385,6 @@ public static EoseMessage createEoseMessage(@NonNull String subscriptionId) {
* @return a NOTICE message
*/
public static NoticeMessage createNoticeMessage(@NonNull String message) {
- return new NoticeMessageFactory(message).create();
- }
-
- /**
- *
- * @param comment the event's comment
- */
- public NIP01 createParameterizedReplaceableEvent(@NonNull Integer kind, String comment) {
- var event = new ParameterizedReplaceableEventFactory(getSender(), kind, comment).create();
-
- this.setEvent((T) event);
- return this;
- }
-
- /**
- *
- * @param tags
- * @param kind
- * @param comment
- * @return
- */
- public NIP01 createParameterizedReplaceableEvent(@NonNull List tags, @NonNull Integer kind,
- String comment) {
- var event = new ParameterizedReplaceableEventFactory(getSender(), tags, kind, comment).create();
-
- this.setEvent((T) event);
- return this;
- }
-
- /**
- *
- * @param id
- * @return
- */
- public static IdentifierTag createIdentifierTag(@NonNull String id) {
- return new IdentifierTagFactory(id).create();
- }
-
- /**
- *
- * @param kind
- * @param publicKey
- * @param idTag
- * @param relay
- * @return
- */
- public static AddressTag createAddressTag(@NonNull Integer kind, @NonNull PublicKey publicKey,
- IdentifierTag idTag, Relay relay) {
- var result = new AddressTagFactory(publicKey).create();
- if(idTag != null) {
- result.setIdentifierTag(idTag);
- }
- result.setKind(kind);
- result.setRelay(relay);
- return result;
+ return new NoticeMessage(message);
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP02.java b/nostr-java-api/src/main/java/nostr/api/NIP02.java
index 3d1ec6356..afaba9901 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP02.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP02.java
@@ -5,26 +5,40 @@
package nostr.api;
import lombok.NonNull;
+import nostr.api.factory.impl.GenericEventFactory;
import nostr.base.PublicKey;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.PubKeyTag;
+import nostr.event.tag.GenericTag;
import nostr.id.Identity;
+import java.util.List;
+
/**
* @author eric
*/
-public class NIP02 extends EventNostr {
+public class NIP02 extends EventNostr {
public NIP02(@NonNull Identity sender) {
setSender(sender);
}
+ public NIP02 createContactListEvent(List pubKeyTags) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CONTACT_LIST, pubKeyTags, "").create();
+ updateEvent(genericEvent);
+ return this;
+ }
+
/**
* Add a pubkey tag to the contact list event
*
* @param tag the pubkey tag
*/
- public NIP02 addContactTag(@NonNull PubKeyTag tag) {
+ public NIP02 addContactTag(@NonNull BaseTag tag) {
+ if (!tag.getCode().equals(Constants.Tag.PUBKEY_CODE)) {
+ throw new IllegalArgumentException("Tag must be a pubkey tag");
+ }
getEvent().addTag(tag);
return this;
}
@@ -34,7 +48,7 @@ public NIP02 addContactTag(@NonNull PubKeyTag tag) {
*
* @param publicKey the public key to add to the contact list
*/
- public NIP02 addContactTag(@NonNull PublicKey publicKey) {
+ public NIP02 addContactTag(@NonNull PublicKey publicKey) {
return addContactTag(NIP01.createPubKeyTag(publicKey));
}
}
\ No newline at end of file
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP03.java b/nostr-java-api/src/main/java/nostr/api/NIP03.java
index efe8ce716..eb3bce54a 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP03.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP03.java
@@ -5,8 +5,8 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP03Impl;
-import nostr.base.IEvent;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.config.Constants;
import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
@@ -14,7 +14,7 @@
*
* @author eric
*/
-public class NIP03 extends EventNostr {
+public class NIP03 extends EventNostr {
public NIP03(@NonNull Identity sender) {
setSender(sender);
@@ -27,10 +27,11 @@ public NIP03(@NonNull Identity sender) {
* @param alt the note's content
* @return an OTS event
*/
- public NIP03 createOtsEvent(@NonNull IEvent referencedEvent, @NonNull String ots, @NonNull String alt) {
- var factory = new NIP03Impl.OtsEventFactory(getSender(), referencedEvent, ots, alt);
- var event = factory.create();
- setEvent((T) event);
+ public NIP03 createOtsEvent(@NonNull GenericEvent referencedEvent, @NonNull String ots, @NonNull String alt) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.OTS_ATTESTATION, ots).create();
+ genericEvent.addTag(NIP31.createAltTag(alt));
+ genericEvent.addTag(NIP01.createEventTag(referencedEvent.getId()));
+ this.updateEvent(genericEvent);
return this;
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP04.java b/nostr-java-api/src/main/java/nostr/api/NIP04.java
index b2f4dcd8b..fb8218622 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP04.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP04.java
@@ -6,27 +6,26 @@
import lombok.NonNull;
import lombok.extern.java.Log;
-import nostr.api.factory.impl.NIP04Impl.DirectMessageEventFactory;
-import nostr.base.ITag;
+import nostr.api.factory.impl.GenericEventFactory;
import nostr.base.PublicKey;
+import nostr.config.Constants;
import nostr.encryption.MessageCipher;
import nostr.encryption.MessageCipher04;
-import nostr.event.NIP04Event;
-import nostr.event.impl.DirectMessageEvent;
+import nostr.event.BaseTag;
import nostr.event.impl.GenericEvent;
+import nostr.event.tag.GenericTag;
import nostr.event.tag.PubKeyTag;
import nostr.id.Identity;
+import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
-import java.util.logging.Level;
/**
* @author eric
*/
@Log
-@Deprecated(since = "NIP-44")
-public class NIP04 extends EventNostr {
+public class NIP04 extends EventNostr {
public NIP04(@NonNull Identity sender, @NonNull PublicKey recipient) {
setSender(sender);
@@ -35,29 +34,32 @@ public NIP04(@NonNull Identity sender, @NonNull PublicKey recipient) {
/**
* Create a NIP04 Encrypted Direct Message
+ *
* @param content the DM content in clear-text
*/
- public NIP04 createDirectMessageEvent(@NonNull String content) {
+ public NIP04 createDirectMessageEvent(@NonNull String content) {
var encryptedContent = encrypt(getSender(), content, getRecipient());
- var event = new DirectMessageEventFactory(getSender(), getRecipient(), encryptedContent).create();
- this.setEvent((T) event);
+ List tags = List.of(new PubKeyTag(getRecipient()));
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.ENCRYPTED_DIRECT_MESSAGE, tags, encryptedContent).create();
+ this.updateEvent(genericEvent);
return this;
}
/**
* Encrypt the direct message
+ *
* @return the current instance with an encrypted message
*/
- private NIP04 encrypt() {
- encryptDirectMessage(getSender(), (DirectMessageEvent) getEvent());
+ public NIP04 encrypt() {
+ encryptDirectMessage(getSender(), getEvent());
return this;
}
/**
- *
- * @param senderId the sender identity
- * @param message the message to be encrypted
+ * @param senderId the sender identity
+ * @param message the message to be encrypted
* @param recipient the recipient public key
* @return the encrypted message
*/
@@ -69,19 +71,9 @@ public static String encrypt(@NonNull Identity senderId, @NonNull String message
/**
* Decrypt an encrypted direct message
*
- * @param rcptId
- * @param dm the encrypted direct message
- * @return the DM content in clear-text
- */
- public static String decrypt(@NonNull Identity rcptId, @NonNull DirectMessageEvent dm) {
- return NIP04.decrypt(rcptId, (GenericEvent) dm);
- }
-
- /**
- * Decrypt an encrypted direct message
- * @param identity the sender identity
+ * @param identity the sender identity
* @param encryptedMessage the encrypted message
- * @param recipient the recipient public key
+ * @param recipient the recipient public key
* @return the DM content in clear-text
*/
public static String decrypt(@NonNull Identity identity, @NonNull String encryptedMessage, @NonNull PublicKey recipient) {
@@ -89,18 +81,39 @@ public static String decrypt(@NonNull Identity identity, @NonNull String encrypt
return cipher.decrypt(encryptedMessage);
}
- private static void encryptDirectMessage(@NonNull Identity senderId, @NonNull DirectMessageEvent directMessageEvent) {
+ private static void encryptDirectMessage(@NonNull Identity senderId, @NonNull GenericEvent directMessageEvent) {
- ITag pkTag = directMessageEvent.getTags().get(0);
- if (pkTag instanceof PubKeyTag pubKeyTag) {
- var rcptPublicKey = pubKeyTag.getPublicKey();
- MessageCipher cipher = new MessageCipher04(senderId.getPrivateKey().getRawData(), rcptPublicKey.getRawData());
- var encryptedContent = cipher.encrypt(directMessageEvent.getContent());
- directMessageEvent.setContent(encryptedContent);
+ if (directMessageEvent.getKind() != Constants.Kind.ENCRYPTED_DIRECT_MESSAGE) {
+ throw new IllegalArgumentException("Event is not an encrypted direct message");
}
+
+ GenericTag recipient = directMessageEvent.getTags()
+ .stream()
+ .filter(t -> t.getCode().equalsIgnoreCase("p"))
+ .map(tag -> (GenericTag) tag)
+ .findFirst()
+ .orElseThrow(() -> new NoSuchElementException("No matching p-tag found."));
+
+ PubKeyTag pubKeyTag = GenericTag.convert(recipient, PubKeyTag.class);
+ PublicKey rcptPublicKey = pubKeyTag.getPublicKey();
+ MessageCipher cipher = new MessageCipher04(senderId.getPrivateKey().getRawData(), rcptPublicKey.getRawData());
+ var encryptedContent = cipher.encrypt(directMessageEvent.getContent());
+ directMessageEvent.setContent(encryptedContent);
}
+ /**
+ * Decrypt an encrypted direct message
+ *
+ * @param rcptId
+ * @param event the encrypted direct message
+ * @return the DM content in clear-text
+ */
public static String decrypt(@NonNull Identity rcptId, @NonNull GenericEvent event) {
+
+ if (event.getKind() != Constants.Kind.ENCRYPTED_DIRECT_MESSAGE) {
+ throw new IllegalArgumentException("Event is not an encrypted direct message");
+ }
+
var recipient = event.getTags()
.stream()
.filter(t -> t.getCode().equalsIgnoreCase("p"))
@@ -117,7 +130,6 @@ public static String decrypt(@NonNull Identity rcptId, @NonNull GenericEvent eve
// I am the message recipient
var sender = event.getPubKey();
- log.log(Level.FINE, "The message is being decrypted for {0}", sender);
MessageCipher cipher = new MessageCipher04(rcptId.getPrivateKey().getRawData(), sender.getRawData());
return cipher.decrypt(event.getContent());
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP05.java b/nostr-java-api/src/main/java/nostr/api/NIP05.java
index 61fb7d47b..6e7f97035 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP05.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP05.java
@@ -4,17 +4,26 @@
*/
package nostr.api;
+import com.fasterxml.jackson.core.JsonProcessingException;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP05Impl.InternetIdentifierMetadataEventFactory;
-import nostr.base.UserProfile;
-import nostr.event.NIP05Event;
+import lombok.SneakyThrows;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.config.Constants;
+import nostr.event.entities.UserProfile;
+import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
+import nostr.util.validator.Nip05Validator;
+
+import java.util.ArrayList;
+
+import static nostr.base.IEvent.MAPPER_AFTERBURNER;
+import static nostr.util.NostrUtil.escapeJsonString;
/**
*
* @author eric
*/
-public class NIP05 extends EventNostr {
+public class NIP05 extends EventNostr {
public NIP05(@NonNull Identity sender) {
setSender(sender);
@@ -25,10 +34,22 @@ public NIP05(@NonNull Identity sender) {
* @param profile the associate user profile
* @return the IIM event
*/
- public NIP05 createInternetIdentifierMetadataEvent(@NonNull UserProfile profile) {
- var event = new InternetIdentifierMetadataEventFactory(getSender(), profile).create();
- this.setEvent((T) event);
-
+ @SneakyThrows
+ public NIP05 createInternetIdentifierMetadataEvent(@NonNull UserProfile profile) {
+ String content = getContent(profile);
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.USER_METADATA, new ArrayList<>(), content).create();
+ this.updateEvent(genericEvent);
return this;
}
+
+ private String getContent(UserProfile profile) {
+ try {
+ String jsonString = MAPPER_AFTERBURNER.writeValueAsString(new Nip05Validator(profile.getNip05(), profile.getPublicKey().toString()));
+ return escapeJsonString(jsonString);
+ } catch (JsonProcessingException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP08.java b/nostr-java-api/src/main/java/nostr/api/NIP08.java
index 939e7fe0a..f04161aef 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP08.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP08.java
@@ -5,9 +5,9 @@
package nostr.api;
import lombok.NonNull;
+import nostr.api.factory.impl.GenericEventFactory;
import nostr.event.BaseTag;
-import nostr.event.NIP08Event;
-import nostr.event.impl.MentionsEvent;
+import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
import java.util.List;
@@ -17,7 +17,7 @@
* @author eric
*/
@Deprecated(since = "NIP-27")
-public class NIP08 extends EventNostr {
+public class NIP08 extends EventNostr {
public NIP08(@NonNull Identity sender) {
setSender(sender);
@@ -29,9 +29,9 @@ public NIP08(@NonNull Identity sender) {
* @param content the note's content containing the references to the public keys
* @return the mentions event
*/
- public NIP08 createMentionsEvent(@NonNull List tags, @NonNull String content) {
- var event = new MentionsEvent(getSender().getPublicKey(), tags, content);
- this.setEvent((T) event);
+ public NIP08 createMentionsEvent(@NonNull Integer kind, @NonNull List tags, @NonNull String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), kind, tags, content).create();
+ this.updateEvent(genericEvent);
return this;
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP09.java b/nostr-java-api/src/main/java/nostr/api/NIP09.java
index b839f6bf9..9593e98e0 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP09.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP09.java
@@ -1,17 +1,13 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP09Impl.DeletionEventFactory;
-import nostr.base.PublicKey;
-import nostr.base.Relay;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.config.Constants;
import nostr.event.BaseTag;
import nostr.event.Deleteable;
-import nostr.event.NIP09Event;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.GenericTag;
import nostr.event.tag.AddressTag;
import nostr.event.tag.EventTag;
-import nostr.event.tag.IdentifierTag;
import nostr.id.Identity;
import java.util.ArrayList;
@@ -20,23 +16,37 @@
/**
* @author eric
*/
-public class NIP09 extends EventNostr {
+public class NIP09 extends EventNostr {
public NIP09(@NonNull Identity sender) {
setSender(sender);
}
- public NIP09 createDeletionEvent(@NonNull Deleteable deleteable) {
- return this.createDeletionEvent(List.of(deleteable));
+ /**
+ * Create a NIP09 Deletion Event
+ *
+ * @param deleteables an array of event or address tags to be deleted
+ * @return
+ */
+ public NIP09 createDeletionEvent(@NonNull Deleteable... deleteables) {
+ return this.createDeletionEvent(List.of(deleteables));
}
/**
* Create a NIP09 Deletion Event
*
* @param deleteables list of event or address tags to be deleted
- * @return the deletion event
+ * @return
*/
- public NIP09 createDeletionEvent(@NonNull List deleteables) {
+ public NIP09 createDeletionEvent(@NonNull List deleteables) {
+ List tags = getTags(deleteables);
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.EVENT_DELETION, tags, "").create();
+ this.updateEvent(genericEvent);
+
+ return this;
+ }
+
+ private List getTags(List deleteables) {
List tags = new ArrayList<>();
// Handle GenericEvents
@@ -51,45 +61,17 @@ public NIP09 createDeletionEvent(@NonNull List deleteables) {
.map(d -> (GenericEvent) d)
.map(GenericEvent::getTags)
.forEach(t -> t.stream()
- .filter(tag -> "a".equals(tag.getCode()))
+ //.filter(tag -> "a".equals(tag.getCode()))
+ //.filter(tag -> tag instanceof AddressTag)
+ .map(tag -> (AddressTag) tag)
.forEach(tag -> {
- if (tag instanceof GenericTag) {
- AddressTag addressTag = toAddressTag((GenericTag) tag);
- tags.add(addressTag);
- tags.add(NIP25.createKindTag(addressTag.getKind()));
- } else if (tag instanceof AddressTag) {
- tags.add(tag);
- tags.add(NIP25.createKindTag(((AddressTag) tag).getKind()));
- } else {
- throw new IllegalArgumentException("Unsupported tag type: " + tag.getClass());
- }
+ tags.add(tag);
+ tags.add(NIP25.createKindTag(tag.getKind()));
}));
// Add kind tags for all deleteables
deleteables.forEach(d -> tags.add(NIP25.createKindTag(d.getKind())));
- var event = new DeletionEventFactory(getSender(), tags).create();
- this.setEvent((T) event);
- return this;
- }
-
- private AddressTag toAddressTag(@NonNull GenericTag genericTag) {
- IdentifierTag identifierTag = new IdentifierTag();
- identifierTag.setUuid(genericTag.getAttributes().get(1).getValue().toString());
-
- AddressTag addressTag = new AddressTag();
- addressTag.setIdentifierTag(identifierTag);
-
- String value = genericTag.getAttributes().get(0).getValue().toString();
- String[] parts = value.split(":");
- addressTag.setKind(Integer.decode(parts[0]));
- addressTag.setPublicKey(new PublicKey(parts[1]));
- if (parts.length == 3) {
- addressTag.setRelay(new Relay(parts[2]));
- }
-
- addressTag.setParent(genericTag.getParent());
-
- return addressTag;
+ return tags;
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP12.java b/nostr-java-api/src/main/java/nostr/api/NIP12.java
index 682643c34..006f9eb0e 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP12.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP12.java
@@ -5,14 +5,12 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP12Impl.GeohashTagFactory;
-import nostr.api.factory.impl.NIP12Impl.HashtagTagFactory;
-import nostr.api.factory.impl.NIP12Impl.ReferenceTagFactory;
-import nostr.event.tag.GeohashTag;
-import nostr.event.tag.HashtagTag;
-import nostr.event.tag.ReferenceTag;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
-import java.net.URI;
+import java.net.URL;
+import java.util.List;
/**
*
@@ -24,23 +22,23 @@ public class NIP12 {
* Create a hashtag tag
* @param hashtag the hashtag
*/
- public static HashtagTag createHashtagTag(@NonNull String hashtag) {
- return new HashtagTagFactory(hashtag).create();
+ public static BaseTag createHashtagTag(@NonNull String hashtag) {
+ return new BaseTagFactory(Constants.Tag.HASHTAG_CODE, List.of(hashtag)).create();
}
/**
* Create an URL tag
* @param url the reference
*/
- public static ReferenceTag createReferenceTag(@NonNull URI url) {
- return new ReferenceTagFactory(url).create();
+ public static BaseTag createReferenceTag(@NonNull URL url) {
+ return new BaseTagFactory(Constants.Tag.REFERENCE_CODE, List.of(url.toString())).create();
}
/**
* Create a Geo tag
* @param location the geohash
*/
- public static GeohashTag createGeohashTag(@NonNull String location) {
- return new GeohashTagFactory(location).create();
+ public static BaseTag createGeohashTag(@NonNull String location) {
+ return new BaseTagFactory(Constants.Tag.GEOHASH_CODE, List.of(location)).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP14.java b/nostr-java-api/src/main/java/nostr/api/NIP14.java
index 71f503a8d..11c9a98d8 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP14.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP14.java
@@ -5,8 +5,11 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP14Impl.SubjectTagFactory;
-import nostr.event.tag.SubjectTag;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
+
+import java.util.List;
/**
*
@@ -18,7 +21,7 @@ public class NIP14 {
* Create a subject tag
* @param subject the subject
*/
- public static SubjectTag createSubjectTag(@NonNull String subject) {
- return new SubjectTagFactory(subject).create();
+ public static BaseTag createSubjectTag(@NonNull String subject) {
+ return new BaseTagFactory(Constants.Tag.SUBJECT_CODE, List.of(subject)).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP15.java b/nostr-java-api/src/main/java/nostr/api/NIP15.java
index 568b05962..8dcd82a5b 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP15.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP15.java
@@ -5,12 +5,13 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP15Impl;
-import nostr.event.impl.CreateOrUpdateStallEvent.Stall;
-import nostr.event.impl.CustomerOrderEvent.Customer;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.config.Constants;
+import nostr.event.entities.CustomerOrder;
+import nostr.event.entities.PaymentRequest;
+import nostr.event.entities.Product;
+import nostr.event.entities.Stall;
import nostr.event.impl.GenericEvent;
-import nostr.event.impl.MerchantRequestPaymentEvent.Payment;
-import nostr.event.impl.NostrMarketplaceEvent.Product;
import nostr.id.Identity;
import java.util.List;
@@ -18,60 +19,63 @@
/**
* @author eric
*/
-public class NIP15 extends EventNostr {
+public class NIP15 extends EventNostr {
public NIP15(@NonNull Identity sender) {
setSender(sender);
}
/**
- * @param payment
- * @param customer
+ * @param paymentRequest
+ * @param customerOrder
*/
- public NIP15 createMerchantRequestPaymentEvent(@NonNull Payment payment, @NonNull Customer customer) {
- var factory = new NIP15Impl.MerchantRequestPaymentEventFactory(getSender(), customer, payment);
- var event = factory.create();
- setEvent((T) event);
-
+ public NIP15 createMerchantRequestPaymentEvent(@NonNull PaymentRequest paymentRequest, @NonNull CustomerOrder customerOrder) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.ENCRYPTED_DIRECT_MESSAGE, paymentRequest.value()).create();
+ genericEvent.addTag(NIP01.createPubKeyTag(customerOrder.getContact().getPublicKey()));
+ this.updateEvent(genericEvent);
return this;
}
/**
- *
- * @param customer
+ * @param customerOrder
* @return
*/
- public NIP15 createCustomerOrderEvent(@NonNull Customer customer) {
- var factory = new NIP15Impl.CustomerOrderEventFactory(getSender(), customer);
- var event = factory.create();
- setEvent((T) event);
+ public NIP15 createCustomerOrderEvent(@NonNull CustomerOrder customerOrder) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.ENCRYPTED_DIRECT_MESSAGE, customerOrder.value()).create();
+ genericEvent.addTag(NIP01.createPubKeyTag(customerOrder.getContact().getPublicKey()));
+ this.updateEvent(genericEvent);
return this;
}
/**
- *
* @param stall
* @return
*/
- public NIP15 createCreateOrUpdateStallEvent(@NonNull Stall stall) {
- var factory = new NIP15Impl.CreateOrUpdateStallEventFactory(getSender(), stall);
- var event = factory.create();
- setEvent((T) event);
+ public NIP15 createCreateOrUpdateStallEvent(@NonNull Stall stall) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.SET_STALL, stall.value()).create();
+ genericEvent.addTag(NIP01.createIdentifierTag(stall.getId()));
+ this.updateEvent(genericEvent);
return this;
}
/**
- *
* @param product
* @param categories
* @return
*/
- public NIP15 createCreateOrUpdateProductEvent(@NonNull Product product, List categories) {
- var factory = new NIP15Impl.CreateOrUpdateProductEventFactory(getSender(), product, categories);
- var event = factory.create();
- setEvent((T) event);
+ public NIP15 createCreateOrUpdateProductEvent(@NonNull Product product, List categories) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.SET_PRODUCT, product.value()).create();
+ genericEvent.addTag(NIP01.createIdentifierTag(product.getId()));
+
+ if (categories != null && !categories.isEmpty()) {
+ categories.forEach(category -> {
+ genericEvent.addTag(NIP12.createHashtagTag(category));
+ });
+ }
+
+ this.updateEvent(genericEvent);
return this;
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP20.java b/nostr-java-api/src/main/java/nostr/api/NIP20.java
index e35a99046..14ef6a3c5 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP20.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP20.java
@@ -5,8 +5,7 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP20Impl.OkMessageFactory;
-import nostr.base.IEvent;
+import nostr.event.impl.GenericEvent;
import nostr.event.message.OkMessage;
/**
@@ -22,7 +21,7 @@ public class NIP20 {
* @param message additional information as to why the command succeeded or failed
* @return the OK message
*/
- public static OkMessage createOkMessage(@NonNull IEvent event, boolean flag, String message) {
- return new OkMessageFactory(event, flag, message).create();
+ public static OkMessage createOkMessage(@NonNull GenericEvent event, boolean flag, String message) {
+ return new OkMessage(event.getId(), flag, message);
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP23.java b/nostr-java-api/src/main/java/nostr/api/NIP23.java
index f791e673b..9cda77247 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP23.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP23.java
@@ -5,15 +5,11 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP23Impl;
-import nostr.api.factory.impl.NIP23Impl.ImageTagFactory;
-import nostr.api.factory.impl.NIP23Impl.PublishedAtTagFactory;
-import nostr.api.factory.impl.NIP23Impl.SummaryTagFactory;
-import nostr.api.factory.impl.NIP23Impl.TitleTagFactory;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.GenericTag;
-import nostr.event.tag.AddressTag;
-import nostr.event.tag.EventTag;
import nostr.id.Identity;
import java.net.URL;
@@ -21,7 +17,7 @@
/**
* @author eric
*/
-public class NIP23 extends EventNostr {
+public class NIP23 extends EventNostr {
public NIP23(@NonNull Identity sender) {
setSender(sender);
@@ -32,60 +28,65 @@ public NIP23(@NonNull Identity sender) {
*
* @param content a text in Markdown syntax
*/
- public NIP23 creatLongFormContentEvent(@NonNull String content) {
- var factory = new NIP23Impl.LongFormContentEventFactory(getSender(), content);
- var event = factory.create();
- setEvent((T) event);
+ public NIP23 creatLongFormTextNoteEvent(@NonNull String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.LONG_FORM_TEXT_NOTE, content).create();
+ this.updateEvent(genericEvent);
+ return this;
+ }
+ NIP23 createLongFormDraftEvent(@NonNull String content) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.LONG_FORM_DRAFT, content).create();
+ this.updateEvent(genericEvent);
return this;
}
- public NIP23 addTitleTag(@NonNull String title) {
+ public NIP23 addTitleTag(@NonNull String title) {
getEvent().addTag(createTitleTag(title));
return this;
}
- public NIP23 addImageTag(@NonNull URL url) {
+ public NIP23 addImageTag(@NonNull URL url) {
getEvent().addTag(createImageTag(url));
return this;
}
- public NIP23 addSummaryTag(@NonNull String summary) {
+ public NIP23 addSummaryTag(@NonNull String summary) {
getEvent().addTag(createSummaryTag(summary));
return this;
}
- public NIP23 addPublishedAtTag(@NonNull Integer date) {
+ public NIP23 addPublishedAtTag(@NonNull Long date) {
getEvent().addTag(createPublishedAtTag(date));
return this;
}
- public NIP23 addEventTag(@NonNull EventTag tag) {
- getEvent().addTag(tag);
- return this;
- }
-
- public NIP23 addAddressTag(@NonNull AddressTag tag) {
- getEvent().addTag(tag);
- return this;
- }
/**
* Create a title tag
*
* @param title the article title
*/
- public static GenericTag createTitleTag(@NonNull String title) {
- return new TitleTagFactory(title).create();
+ public static BaseTag createTitleTag(@NonNull String title) {
+ return new BaseTagFactory("title", title).create();
+ }
+
+ /**
+ * Create an image tag
+ *
+ * @param url a URL pointing to an image to be shown along with the title
+ */
+ public static BaseTag createImageTag(@NonNull URL url) {
+ return new BaseTagFactory(Constants.Tag.IMAGE_CODE, url.toString()).create();
}
/**
* Create an image tag
*
* @param url a URL pointing to an image to be shown along with the title
+ * @param size the size of the image
*/
- public static GenericTag createImageTag(@NonNull URL url) {
- return new ImageTagFactory(url).create();
+ public static BaseTag createImageTag(@NonNull URL url, String size) {
+ return new BaseTagFactory(Constants.Tag.IMAGE_CODE, url.toString(), size).create();
}
/**
@@ -93,8 +94,8 @@ public static GenericTag createImageTag(@NonNull URL url) {
*
* @param summary the article summary
*/
- public static GenericTag createSummaryTag(@NonNull String summary) {
- return new SummaryTagFactory(summary).create();
+ public static BaseTag createSummaryTag(@NonNull String summary) {
+ return new BaseTagFactory(Constants.Tag.SUMMARY_CODE, summary).create();
}
/**
@@ -102,7 +103,7 @@ public static GenericTag createSummaryTag(@NonNull String summary) {
*
* @param date the timestamp in unix seconds (stringified) of the first time the article was published
*/
- public static GenericTag createPublishedAtTag(@NonNull Integer date) {
- return new PublishedAtTagFactory(date).create();
+ public static BaseTag createPublishedAtTag(@NonNull Long date) {
+ return new BaseTagFactory(Constants.Tag.PUBLISHED_AT_CODE, date.toString()).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP25.java b/nostr-java-api/src/main/java/nostr/api/NIP25.java
index 9d6e32789..a69e8bb1e 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP25.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP25.java
@@ -5,20 +5,22 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.TagFactory;
-import nostr.api.factory.impl.NIP25Impl.ReactionEventFactory;
+import lombok.SneakyThrows;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.base.Relay;
+import nostr.config.Constants;
import nostr.event.BaseTag;
-import nostr.event.NIP25Event;
-import nostr.event.Reaction;
+import nostr.event.entities.Reaction;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.GenericTag;
import nostr.event.tag.EmojiTag;
+import nostr.event.tag.EventTag;
import nostr.id.Identity;
-import java.util.ArrayList;
-import java.util.List;
+import java.net.URI;
+import java.net.URL;
-public class NIP25 extends EventNostr {
+public class NIP25 extends EventNostr {
public NIP25(@NonNull Identity sender) {
setSender(sender);
@@ -26,91 +28,118 @@ public NIP25(@NonNull Identity sender) {
/**
* Create a Reaction event
- *
+ *
* @param event the related event to react to
* @param reaction
*/
- public NIP25 createReactionEvent(@NonNull GenericEvent event, @NonNull Reaction reaction) {
- var e = new ReactionEventFactory(getSender(), event, reaction).create();
- this.setEvent((T) e);
-
- return this;
+ public NIP25 createReactionEvent(@NonNull GenericEvent event, @NonNull Reaction reaction, Relay relay) {
+ return this.createReactionEvent(event, reaction.getEmoji(), relay);
}
/**
* Create a NIP25 Reaction event to react to a specific event
- *
+ *
* @param event the related event to react to
* @param content MAY be an emoji
*/
- public NIP25 createReactionEvent(@NonNull GenericEvent event, @NonNull String content) {
- var e = new ReactionEventFactory(getSender(), event, content).create();
- this.setEvent((T) e);
+ public NIP25 createReactionEvent(@NonNull GenericEvent event, @NonNull String content, Relay relay) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.REACTION, content).create();
+
+ // Addressable event?
+ if (event.isAddressable()) {
+ genericEvent.addTag(NIP01.createAddressTag(event.getKind(), event.getPubKey(), event.getId()));
+ genericEvent.addTag(NIP25.createKindTag(event.getKind()));
+ } else {
+ genericEvent.addTag(NIP01.createEventTag(event.getId(), relay != null ? relay.toString() : null, null));
+ genericEvent.addTag(NIP01.createPubKeyTag(event.getPubKey()));
+ }
+ this.updateEvent(genericEvent);
+ return this;
+ }
+ public NIP25 createReactionToWebsiteEvent(@NonNull URL url, @NonNull Reaction reaction) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.REACTION_TO_WEBSITE, reaction.getEmoji()).create();
+ genericEvent.addTag(NIP12.createReferenceTag(url));
+ this.updateEvent(genericEvent);
return this;
}
/**
* Create a NIP25 Reaction event to react to a specific event
- *
- * @param event the related event to react to
- * @param emojiTag MUST be an costum emoji (NIP30)
+ *
+ * @param eventTag the e-tag referencing the related event to react to
+ * @param emojiTag MUST be an costum emoji (NIP30)
*/
- public EventNostr createReactionEvent(@NonNull GenericEvent event, @NonNull EmojiTag emojiTag) {
- var content = String.format(":%s:", emojiTag.getShortcode());
- var e = new ReactionEventFactory(getSender(), new ArrayList<>(List.of(emojiTag)), event, content).create();
- this.setEvent((T) e);
+ public NIP25 createReactionEvent(@NonNull BaseTag eventTag, @NonNull BaseTag emojiTag) {
- return this;
- }
+ // 1. Validation
+ if (!(emojiTag instanceof EmojiTag)) {
+ throw new IllegalArgumentException("The tag is not a custom emoji tag");
+ }
- /**
- * Create a NIP25 Reaction event to react to several event and/or pubkeys
- *
- * @param tags the list of events or pubkeys to react to
- * @param content MAY be an emoji
- */
- public NIP25 createReactionEvent(@NonNull List tags, @NonNull String content) {
- var e = new ReactionEventFactory(getSender(), tags, content).create();
- this.setEvent((T) e);
+ if (!(eventTag instanceof EventTag)) {
+ throw new IllegalArgumentException("The tag is not an event tag");
+ }
+
+ String shortCode = ((EmojiTag) emojiTag).getShortcode();
+ var content = String.format(":%s:", shortCode);
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.REACTION, content).create();
+ genericEvent.addTag(emojiTag);
+ genericEvent.addTag(eventTag);
+
+ this.updateEvent(genericEvent);
return this;
}
+
/**
* Create the kind tag
- *
+ *
* @param kind the kind
*/
- public static GenericTag createKindTag(@NonNull Integer kind) {
- return new TagFactory("k", 25, kind.toString()).create();
+ public static BaseTag createKindTag(@NonNull Integer kind) {
+ return new BaseTagFactory(Constants.Tag.KIND_CODE, kind.toString()).create();
+ }
+
+ public static BaseTag createCustomEmojiTag(@NonNull String shortcode, @NonNull URL url) {
+ return new BaseTagFactory(Constants.Tag.EMOJI_CODE, shortcode, url.toString()).create();
+ }
+
+ @SneakyThrows
+ public static BaseTag createCustomEmojiTag(@NonNull String shortcode, @NonNull String url) {
+ return createCustomEmojiTag(shortcode, URI.create(url).toURL());
}
/**
- *
* @param event
*/
+ public void like(@NonNull GenericEvent event, Relay relay) {
+ react(event, Reaction.LIKE.getEmoji(), relay);
+ }
+
public void like(@NonNull GenericEvent event) {
- react(event, Reaction.LIKE.getEmoji());
+ react(event, Reaction.LIKE.getEmoji(), null);
}
/**
- *
* @param event
*/
+ public void dislike(@NonNull GenericEvent event, Relay relay) {
+ react(event, Reaction.DISLIKE.getEmoji(), relay);
+ }
+
public void dislike(@NonNull GenericEvent event) {
- react(event, Reaction.DISLIKE.getEmoji());
+ react(event, Reaction.DISLIKE.getEmoji(), null);
}
/**
- *
* @param event
* @param reaction
*/
- public void react(@NonNull GenericEvent event, @NonNull String reaction) {
- var e = new ReactionEventFactory(getSender(), event, reaction).create();
-
- this.setEvent((T) e);
+ public void react(@NonNull GenericEvent event, @NonNull String reaction, Relay relay) {
+ GenericEvent e = createReactionEvent(event, reaction, relay).getEvent();
+ this.updateEvent(e);
this.sign().send();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP28.java b/nostr-java-api/src/main/java/nostr/api/NIP28.java
index 8b0bc0810..1d56f7963 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP28.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP28.java
@@ -4,20 +4,31 @@
*/
package nostr.api;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP28Impl;
-import nostr.base.ChannelProfile;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.base.IEvent;
+import nostr.base.Marker;
import nostr.base.PublicKey;
import nostr.base.Relay;
-import nostr.event.impl.ChannelCreateEvent;
-import nostr.event.impl.ChannelMessageEvent;
+import nostr.config.Constants;
+import nostr.event.entities.ChannelProfile;
import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import java.util.List;
+
+import static nostr.api.NIP12.createHashtagTag;
/**
* @author eric
*/
-public class NIP28 extends EventNostr {
+public class NIP28 extends EventNostr {
public NIP28(@NonNull Identity sender) {
setSender(sender);
@@ -28,70 +39,111 @@ public NIP28(@NonNull Identity sender) {
*
* @param profile the channel metadata
*/
- public NIP28 createChannelCreateEvent(@NonNull ChannelProfile profile) {
- var factory = new NIP28Impl.ChannelCreateEventFactory(getSender(), profile);
- var event = factory.create();
- setEvent((T) event);
-
+ public NIP28 createChannelCreateEvent(@NonNull ChannelProfile profile) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CHANNEL_CREATION, StringEscapeUtils.escapeJson(profile.toString())).create();
+ this.updateEvent(genericEvent);
return this;
}
/**
* Create a KIND-42 channel message
*
- * @param channelCreateEvent KIND-40 channel create event
- * @param content the message
+ * @param channelCreateEvent KIND-40 channel create event
+ * @param messageReplyTo the reply tag. If present, it must be a reply to a message, else it is a root message
+ * @param recommendedRelayRoot in the scenario of a root message, the recommended relay for the root message
+ * @param recommendedRelayReply in the scenario of a reply message, the recommended relay for the reply message
+ * @param content the message
*/
- public NIP28 createChannelMessageEvent(@NonNull ChannelCreateEvent channelCreateEvent, String content) {
- var factory = new NIP28Impl.ChannelMessageEventFactory(getSender(), channelCreateEvent, content);
- var event = factory.create();
- setEvent((T) event);
+ public NIP28 createChannelMessageEvent(
+ @NonNull GenericEvent channelCreateEvent,
+ GenericEvent messageReplyTo,
+ Relay recommendedRelayRoot,
+ Relay recommendedRelayReply,
+ @NonNull String content) {
+
+ // 1. Validation
+ if (channelCreateEvent.getKind() != Constants.Kind.CHANNEL_CREATION) {
+ throw new IllegalArgumentException("The event is not a channel creation event");
+ }
+
+ // 2. Create the event
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CHANNEL_MESSAGE, content).create();
+
+ // 3. Add the tags
+ genericEvent.addTag(NIP01.createEventTag(channelCreateEvent.getId(), recommendedRelayRoot, Marker.ROOT));
+ if (messageReplyTo != null) {
+ genericEvent.addTag(NIP01.createEventTag(messageReplyTo.getId(), recommendedRelayReply, Marker.REPLY));
+ genericEvent.addTag(NIP01.createPubKeyTag(messageReplyTo.getPubKey()));
+ }
+
+ // 4. Update the event
+ this.updateEvent(genericEvent);
return this;
}
/**
- * Create a KIND-42 channel message reply
+ * Create a KIND-42 channel root message
*
- * @param channelCreateEvent KIND-40 channel create event
- * @param channelMessageEvent the KIND-42 channel message event
- * @param content the message
+ * @param channelCreateEvent KIND-40 channel create event
+ * @param content the message
*/
- public NIP28 createChannelMessageEvent(@NonNull ChannelCreateEvent channelCreateEvent, ChannelMessageEvent channelMessageEvent, String content) {
- return createChannelMessageEvent(channelCreateEvent, channelMessageEvent, content, null, null);
+ public NIP28 createChannelMessageEvent(
+ @NonNull GenericEvent channelCreateEvent,
+ @NonNull Relay recommendedRelayRoot,
+ @NonNull String content) {
+
+ return createChannelMessageEvent(channelCreateEvent, null, recommendedRelayRoot, null, content);
}
/**
- * Create a KIND-41 channel message reply while specifying the recommended relays
+ * Create a KIND-42 channel message reply
*
- * @param channelCreateEvent KIND-40 channel create event
- * @param channelMessageEvent the KIND-42 channel message event
- * @param content the message
- * @param recommendedRelayRoot the recommended relay for the KIND-40 event
- * @param recommendedRelayReply the recommended relay for the KIND-42 event
+ * @param channelCreateEvent KIND-40 channel create event
+ * @param eventTagReplyTo the reply tag with the root marker
+ * @param content the message
*/
- public NIP28 createChannelMessageEvent(@NonNull ChannelCreateEvent channelCreateEvent, @NonNull ChannelMessageEvent channelMessageEvent, String content, Relay recommendedRelayRoot, Relay recommendedRelayReply) {
- var factory = new NIP28Impl.ChannelMessageEventFactory(getSender(), channelCreateEvent, content);
- factory.setRecommendedRelayReply(recommendedRelayReply);
- factory.setRecommendedRelayRoot(recommendedRelayRoot);
- factory.setChannelMessageEvent(channelMessageEvent);
- var event = factory.create();
- setEvent((T) event);
+ public NIP28 createChannelMessageEvent(
+ @NonNull GenericEvent channelCreateEvent,
+ @NonNull GenericEvent eventTagReplyTo,
+ @NonNull String content) {
- return this;
+ return createChannelMessageEvent(channelCreateEvent, eventTagReplyTo, null, null, content);
}
/**
* Create a KIND-41 channel metadata event
*
- * @param channelCreateEvent the channel create event
- * @param profile the channel metadata
+ * @param profile the channel metadata
*/
- public NIP28 createChannelMetadataEvent(@NonNull ChannelCreateEvent channelCreateEvent, @NonNull ChannelProfile profile) {
- var factory = new NIP28Impl.ChannelMetadataEventFactory(getSender(), channelCreateEvent, profile);
- var event = factory.create();
- setEvent((T) event);
+ public NIP28 updateChannelMetadataEvent(@NonNull GenericEvent channelCreateEvent, @NonNull ChannelProfile profile, Relay relay) {
+ return this.updateChannelMetadataEvent(channelCreateEvent, profile, null, relay);
+ }
+ /**
+ * Create a KIND-41 channel metadata event
+ * @param channelCreateEvent KIND-40 channel create event
+ * @param categories the list of categories
+ * @param profile the channel metadata
+ * @param relay the recommended root relay
+ */
+ public NIP28 updateChannelMetadataEvent(@NonNull GenericEvent channelCreateEvent, @NonNull ChannelProfile profile, List categories, Relay relay) {
+
+ // 1. Validation
+ if (channelCreateEvent.getKind() != Constants.Kind.CHANNEL_CREATION) {
+ throw new IllegalArgumentException("The event is not a channel creation event");
+ }
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CHANNEL_METADATA, StringEscapeUtils.escapeJson(profile.toString())).create();
+ genericEvent.addTag(NIP01.createEventTag(channelCreateEvent.getId(), relay, Marker.ROOT));
+ if (categories != null) {
+ categories.stream()
+ .filter(category -> category != null && !category.isEmpty())
+ .forEach(category -> {
+ genericEvent.addTag(createHashtagTag(category));
+ });
+ }
+ updateEvent(genericEvent);
return this;
}
@@ -101,11 +153,15 @@ public NIP28 createChannelMetadataEvent(@NonNull ChannelCreateEvent channelCr
* @param channelMessageEvent NIP-42 event to hide
* @param reason optional reason for the action
*/
- public NIP28 createHideMessageEvent(@NonNull ChannelMessageEvent channelMessageEvent, String reason) {
- var factory = new NIP28Impl.HideMessageEventFactory(getSender(), channelMessageEvent, reason);
- var event = factory.create();
- setEvent((T) event);
+ public NIP28 createHideMessageEvent(@NonNull GenericEvent channelMessageEvent, String reason) {
+
+ if (channelMessageEvent.getKind() != Constants.Kind.CHANNEL_MESSAGE) {
+ throw new IllegalArgumentException("The event is not a channel message event");
+ }
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CHANNEL_HIDE_MESSAGE, Reason.fromString(reason).toString()).create();
+ genericEvent.addTag(NIP01.createEventTag(channelMessageEvent.getId()));
+ updateEvent(genericEvent);
return this;
}
@@ -115,11 +171,32 @@ public NIP28 createHideMessageEvent(@NonNull ChannelMessageEvent channelMessa
* @param mutedUser the user to mute. Their messages will no longer be visible
* @param reason optional reason for the action
*/
- public NIP28 createMuteUserEvent(@NonNull PublicKey mutedUser, String reason) {
- var factory = new NIP28Impl.MuteUserEventFactory(getSender(), mutedUser, reason);
- var event = factory.create();
- setEvent((T) event);
-
+ public NIP28 createMuteUserEvent(@NonNull PublicKey mutedUser, String reason) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CHANNEL_MUTE_USER, Reason.fromString(reason).toString()).create();
+ genericEvent.addTag(NIP01.createPubKeyTag(mutedUser));
+ updateEvent(genericEvent);
return this;
}
+
+
+ @NoArgsConstructor
+ @AllArgsConstructor
+ @EqualsAndHashCode
+ private static class Reason {
+
+ @JsonProperty("reason")
+ private String value;
+
+ public String toString() {
+ try {
+ return IEvent.MAPPER_AFTERBURNER.writeValueAsString(this);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static Reason fromString(String reason) {
+ return new Reason(reason);
+ }
+ }
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP30.java b/nostr-java-api/src/main/java/nostr/api/NIP30.java
index 42955e74c..42be2a77d 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP30.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP30.java
@@ -5,7 +5,9 @@
package nostr.api;
import lombok.NonNull;
-import nostr.event.tag.EmojiTag;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
public class NIP30 {
@@ -14,7 +16,7 @@ public class NIP30 {
* @param shortcode
* @param imageUrl
*/
- public static EmojiTag createCustomEmojiTag(@NonNull String shortcode, @NonNull String imageUrl) {
- return new EmojiTag(shortcode, imageUrl);
- }
+ public static BaseTag createEmojiTag(@NonNull String shortcode, @NonNull String imageUrl) {
+ return new BaseTagFactory(Constants.Tag.EMOJI_CODE, shortcode, imageUrl).create();
+ }
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP31.java b/nostr-java-api/src/main/java/nostr/api/NIP31.java
index d969b0714..04b4c22aa 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP31.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP31.java
@@ -1,12 +1,13 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.TagFactory;
-import nostr.event.tag.GenericTag;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
public class NIP31 {
- public static GenericTag createAltTag(@NonNull String alt) {
- return new TagFactory("alt", 31, alt).create();
+ public static BaseTag createAltTag(@NonNull String alt) {
+ return new BaseTagFactory(Constants.Tag.ALT_CODE, alt).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP32.java b/nostr-java-api/src/main/java/nostr/api/NIP32.java
index aad2c03de..7709b5a82 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP32.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP32.java
@@ -5,13 +5,9 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP32Impl.Label;
-import nostr.api.factory.impl.NIP32Impl.LabelTagFactory;
-import nostr.api.factory.impl.NIP32Impl.NameSpace;
-import nostr.api.factory.impl.NIP32Impl.NamespaceTagFactory;
-import nostr.event.tag.GenericTag;
-
-import java.util.Map;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
/**
*
@@ -23,26 +19,17 @@ public class NIP32 {
*
* @param namespace the namespace
*/
- public static GenericTag createNameSpaceTag(@NonNull String namespace) {
- return new NamespaceTagFactory(new NameSpace(namespace)).create();
- }
-
- /**
- *
- * @param namespace the label's namespace
- * @param label the label value
- * @param metadata optional metadata
- */
- public static GenericTag createLabelTag(@NonNull String namespace, @NonNull String label, Map metadata) {
- return new LabelTagFactory(new Label(new NameSpace(namespace), label, metadata)).create();
+ public static BaseTag createNameSpaceTag(@NonNull String namespace) {
+ return new BaseTagFactory(Constants.Tag.NAMESPACE_CODE, namespace).create();
}
/**
- *
- * @param namespace the label's namespace
+ *
* @param label the label value
+ * @param namespace the label's namespace
+ *
*/
- public static GenericTag createLabelTag(@NonNull String namespace, @NonNull String label) {
- return createLabelTag(namespace, label, null);
+ public static BaseTag createLabelTag(@NonNull String label, @NonNull String namespace) {
+ return new BaseTagFactory(Constants.Tag.LABEL_CODE, label, namespace).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP40.java b/nostr-java-api/src/main/java/nostr/api/NIP40.java
index ec5d8ac66..b741ecb4a 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP40.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP40.java
@@ -5,8 +5,9 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP40Impl.ExpirationTagFactory;
-import nostr.event.tag.ExpirationTag;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
/**
*
@@ -18,7 +19,7 @@ public class NIP40 {
*
* @param expiration
*/
- public static ExpirationTag createExpirationTag(@NonNull Integer expiration) {
- return new ExpirationTagFactory(expiration).create();
+ public static BaseTag createExpirationTag(@NonNull Integer expiration) {
+ return new BaseTagFactory(Constants.Tag.EXPIRATION_CODE, expiration.toString()).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP42.java b/nostr-java-api/src/main/java/nostr/api/NIP42.java
index 8aa62c23d..29df29324 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP42.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP42.java
@@ -5,23 +5,25 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP42Impl;
-import nostr.api.factory.impl.NIP42Impl.ChallengeTagFactory;
-import nostr.api.factory.impl.NIP42Impl.ClientAuthenticationMessageFactory;
-import nostr.api.factory.impl.NIP42Impl.RelayAuthenticationMessageFactory;
-import nostr.api.factory.impl.NIP42Impl.RelaysTagFactory;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.base.Command;
+import nostr.base.ElementAttribute;
import nostr.base.Relay;
+import nostr.config.Constants;
+import nostr.event.BaseTag;
import nostr.event.impl.CanonicalAuthenticationEvent;
import nostr.event.impl.GenericEvent;
-import nostr.event.impl.GenericMessage;
-import nostr.event.tag.GenericTag;
import nostr.event.message.CanonicalAuthenticationMessage;
+import nostr.event.message.GenericMessage;
+import java.util.ArrayList;
+import java.util.List;
/**
*
* @author eric
*/
-public class NIP42 extends EventNostr {
+public class NIP42 extends EventNostr {
/**
*
@@ -29,26 +31,25 @@ public class NIP42 extends EventNostr {
* @param relay
* @return
*/
- public NIP42 createCanonicalAuthenticationEvent(@NonNull String challenge, @NonNull Relay relay) {
- var factory = new NIP42Impl.CanonicalAuthenticationEventFactory(getSender(), challenge, relay);
- var event = factory.create();
- setEvent((T) event);
+ public NIP42 createCanonicalAuthenticationEvent(@NonNull String challenge, @NonNull Relay relay) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.EVENT_DELETION,"").create();
+ this.addChallengeTag(challenge);
+ this.addRelayTag(relay);
+ this.updateEvent(genericEvent);
return this;
}
- public NIP42 addRelayTag(@NonNull Relay relay) {
+ public NIP42 addRelayTag(@NonNull Relay relay) {
var tag = createRelayTag(relay);
- var event = (CanonicalAuthenticationEvent) getEvent();
- event.addTag(tag);
+ getEvent().addTag(tag);
return this;
}
- public NIP42 addChallengeTag(@NonNull String challenge) {
+ public NIP42 addChallengeTag(@NonNull String challenge) {
var tag = createChallengeTag(challenge);
- var event = (CanonicalAuthenticationEvent) getEvent();
- event.addTag(tag);
+ getEvent().addTag(tag);
return this;
}
@@ -56,16 +57,16 @@ public NIP42 addChallengeTag(@NonNull String challenge) {
*
* @param relay
*/
- public static GenericTag createRelayTag(@NonNull Relay relay) {
- return new RelaysTagFactory(relay).create();
+ public static BaseTag createRelayTag(@NonNull Relay relay) {
+ return new BaseTagFactory(Constants.Tag.RELAY_CODE, relay.getUri()).create();
}
/**
*
* @param challenge
*/
- public static GenericTag createChallengeTag(@NonNull String challenge) {
- return new ChallengeTagFactory(challenge).create();
+ public static BaseTag createChallengeTag(@NonNull String challenge) {
+ return new BaseTagFactory(Constants.Tag.CHALLENGE_CODE, challenge).create();
}
/**
@@ -73,7 +74,7 @@ public static GenericTag createChallengeTag(@NonNull String challenge) {
* @param event
*/
public static CanonicalAuthenticationMessage createClientAuthenticationMessage(@NonNull CanonicalAuthenticationEvent event) {
- return new ClientAuthenticationMessageFactory(event).create();
+ return new CanonicalAuthenticationMessage(event);
}
/**
@@ -81,6 +82,9 @@ public static CanonicalAuthenticationMessage createClientAuthenticationMessage(@
* @param challenge
*/
public static GenericMessage createRelayAuthenticationMessage(@NonNull String challenge) {
- return new RelayAuthenticationMessageFactory(challenge).create();
+ final List attributes = new ArrayList<>();
+ final var attr = new ElementAttribute("challenge", challenge);
+ attributes.add(attr);
+ return new GenericMessage(Command.AUTH.name(), attributes);
}
-}
+}
\ No newline at end of file
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP44.java b/nostr-java-api/src/main/java/nostr/api/NIP44.java
index ec5c50f66..65a9d67fc 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP44.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP44.java
@@ -2,61 +2,28 @@
import lombok.NonNull;
import lombok.extern.java.Log;
-import nostr.api.factory.impl.NIP44Impl;
-import nostr.base.ITag;
import nostr.base.PublicKey;
import nostr.encryption.MessageCipher;
import nostr.encryption.MessageCipher44;
-import nostr.event.BaseTag;
import nostr.event.filter.Filterable;
import nostr.event.impl.EncryptedPayloadEvent;
import nostr.event.impl.GenericEvent;
import nostr.event.tag.PubKeyTag;
import nostr.id.Identity;
-import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.logging.Level;
@Log
-public class NIP44 extends EventNostr {
-
- public NIP44(@NonNull Identity sender, @NonNull PublicKey recipient) {
- setSender(sender);
- setRecipient(recipient);
- }
-
- public NIP44 createDirectMessageEvent(@NonNull String content) {
- var encryptedContent = encrypt(getSender(), content, getRecipient());
- var factory = new NIP44Impl.EncryptedPayloadEventFactory(getSender(), getRecipient(), encryptedContent);
- var event = factory.create();
- setEvent((T) event);
- return this;
- }
-
- public NIP44 createDirectMessageEvent(@NonNull List tags, @NonNull PublicKey recipient, @NonNull String content) {
- var encryptedContent = encrypt(getSender(), content, recipient);
- var factory = new NIP44Impl.EncryptedPayloadEventFactory(getSender(), tags, recipient, encryptedContent);
- var event = factory.create();
- setEvent((T) event);
- return this;
- }
-
- public static void encrypt(@NonNull Identity sender, @NonNull EncryptedPayloadEvent ep) {
- encryptDirectMessage(sender, ep);
- }
-
- public NIP44 encrypt() {
- encryptDirectMessage(getSender(), (EncryptedPayloadEvent) getEvent());
- return this;
- }
+public class NIP44 extends EventNostr {
public static String encrypt(@NonNull Identity sender, @NonNull String message, @NonNull PublicKey recipient) {
MessageCipher cipher = new MessageCipher44(sender.getPrivateKey().getRawData(), recipient.getRawData());
return cipher.encrypt(message);
}
+ @Deprecated(forRemoval = true, since = "0.6.6-SNAPSHOT")
public static String decrypt(@NonNull Identity recipient, @NonNull EncryptedPayloadEvent ep) {
return NIP44.decrypt(recipient, (GenericEvent) ep);
}
@@ -85,16 +52,6 @@ public static String decrypt(@NonNull Identity recipient, @NonNull GenericEvent
return cipher.decrypt(event.getContent());
}
- private static void encryptDirectMessage(@NonNull Identity sender, @NonNull EncryptedPayloadEvent ep) {
-
- ITag pkTag = ep.getTags().get(0);
- if (pkTag instanceof PubKeyTag pubKeyTag) {
- var rcptPublicKey = pubKeyTag.getPublicKey();
- MessageCipher cipher = new MessageCipher44(sender.getPrivateKey().getRawData(), rcptPublicKey.getRawData());
- var encryptedContent = cipher.encrypt(ep.getContent());
- ep.setContent(encryptedContent);
- }
- }
private static boolean amITheRecipient(@NonNull Identity recipient, @NonNull GenericEvent event) {
var pTag = event.getTags()
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP46.java b/nostr-java-api/src/main/java/nostr/api/NIP46.java
index 4af9e0584..9c2620f1d 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP46.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP46.java
@@ -6,8 +6,9 @@
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.extern.java.Log;
-import nostr.api.factory.impl.NIP46Impl;
+import nostr.api.factory.impl.GenericEventFactory;
import nostr.base.PublicKey;
+import nostr.config.Constants;
import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
@@ -18,7 +19,7 @@
import static nostr.base.IEvent.MAPPER_AFTERBURNER;
-public final class NIP46 extends EventNostr {
+public final class NIP46 extends EventNostr {
public NIP46(@NonNull Identity sender) {
setSender(sender);
@@ -30,11 +31,11 @@ public NIP46(@NonNull Identity sender) {
* @param signer
* @return
*/
- public NIP46 createRequestEvent(@NonNull NIP46.Request request, @NonNull PublicKey signer) {
- var factory = new NIP46Impl.NostrConnectEventFactory(getSender(), request, signer);
- var event = factory.create();
- setEvent((T) event);
-
+ public NIP46 createRequestEvent(@NonNull NIP46.Request request, @NonNull PublicKey signer) {
+ String content = NIP44.encrypt(getSender(), request.toString(), signer);
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.REQUEST_EVENTS, content).create();
+ genericEvent.addTag(NIP01.createPubKeyTag(signer));
+ this.updateEvent(genericEvent);
return this;
}
@@ -43,18 +44,14 @@ public NIP46 createRequestEvent(@NonNull NIP46.Request request, @NonNull Publ
* @param app
* @return
*/
- public NIP46 createResponseEvent(@NonNull NIP46.Response response, @NonNull PublicKey app) {
- var factory = new NIP46Impl.NostrConnectEventFactory(getSender(), response, app);
- var event = factory.create();
- setEvent((T) event);
-
+ public NIP46 createResponseEvent(@NonNull NIP46.Response response, @NonNull PublicKey app) {
+ String content = NIP44.encrypt(getSender(), response.toString(), app);
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.REQUEST_EVENTS, content).create();
+ genericEvent.addTag(NIP01.createPubKeyTag(app));
+ this.updateEvent(genericEvent);
return this;
}
- public interface NIP46ReqRes {
- String getId();
- }
-
@Data
@AllArgsConstructor
@NoArgsConstructor
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP52.java b/nostr-java-api/src/main/java/nostr/api/NIP52.java
index fc2e6e0e5..061c13f31 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP52.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP52.java
@@ -1,28 +1,156 @@
package nostr.api;
+import java.net.URI;
+import java.util.List;
+import java.util.Optional;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP52Impl.CalendarRsvpEventFactory;
-import nostr.api.factory.impl.NIP52Impl.CalendarTimeBasedEventFactory;
+import lombok.SneakyThrows;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.config.Constants;
import nostr.event.BaseTag;
-import nostr.event.NIP52Event;
-import nostr.event.impl.CalendarContent;
-import nostr.event.impl.CalendarRsvpContent;
+import nostr.event.entities.CalendarContent;
+import nostr.event.entities.CalendarRsvpContent;
+import nostr.event.impl.GenericEvent;
+import nostr.event.tag.GenericTag;
+import nostr.event.tag.GeohashTag;
import nostr.id.Identity;
+import org.apache.commons.lang3.stream.Streams;
+import static nostr.api.NIP01.createIdentifierTag;
+import static nostr.api.NIP23.createImageTag;
+import static nostr.api.NIP23.createSummaryTag;
+import static nostr.api.NIP23.createTitleTag;
+import static nostr.api.NIP99.createLocationTag;
+import static nostr.api.NIP99.createStatusTag;
-import java.util.List;
-
-public class NIP52 extends EventNostr {
+public class NIP52 extends EventNostr {
public NIP52(@NonNull Identity sender) {
setSender(sender);
}
- public NIP52 createCalendarTimeBasedEvent(@NonNull List baseTags, @NonNull String content, @NonNull CalendarContent calendarContent) {
- setEvent((T) new CalendarTimeBasedEventFactory(getSender(), baseTags, content, calendarContent).create());
+ public NIP52 createCalendarTimeBasedEvent(
+ @NonNull List baseTags,
+ @NonNull String content,
+ @NonNull CalendarContent calendarContent) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.TIME_BASED_CALENDAR_CONTENT, baseTags, content).create();
+
+ genericEvent.addTag(calendarContent.getIdentifierTag());
+ genericEvent.addTag(createTitleTag(calendarContent.getTitle()));
+ genericEvent.addTag(createStartTag(calendarContent.getStart()));
+
+ Optional geohashTag = calendarContent.getGeohashTag();
+ geohashTag.ifPresent(genericEvent::addTag);
+ calendarContent.getEnd().ifPresent(aLong -> genericEvent.addTag(createEndTag(aLong)));
+ calendarContent.getStartTzid().ifPresent(s -> genericEvent.addTag(createStartTzidTag(s)));
+ calendarContent.getEndTzid().ifPresent(s -> genericEvent.addTag(createEndTzidTag(s)));
+ calendarContent.getSummary().ifPresent(s -> genericEvent.addTag(createSummaryTag(s)));
+
+ calendarContent.getImage().ifPresent(s ->
+ genericEvent.addTag(createImageTag(
+ Streams.failableStream(URI.create(s))
+ .map(URI::toURL)
+ .stream().findFirst().orElseThrow())));
+
+ calendarContent.getParticipantPubKeyTags().forEach(genericEvent::addTag);
+ calendarContent.getLocation().ifPresent(s -> genericEvent.addTag(createLocationTag(s)));
+ calendarContent.getHashtagTags().forEach(genericEvent::addTag);
+ calendarContent.getReferenceTags().forEach(genericEvent::addTag);
+ calendarContent.getLabelTags().forEach(genericEvent::addTag);
+
+ this.updateEvent(genericEvent);
+
+ return this;
+ }
+
+ public NIP52 createCalendarRsvpEvent(
+ @NonNull String content,
+ @NonNull CalendarRsvpContent calendarRsvpContent) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CALENDAR_EVENT_RSVP, content).create();
+
+// mandatory tags
+ genericEvent.addTag(calendarRsvpContent.getIdentifierTag());
+ genericEvent.addTag(calendarRsvpContent.getAddressTag());
+ genericEvent.addTag(createStatusTag(calendarRsvpContent.getStatus()));
+
+// optional tags
+ calendarRsvpContent.getAuthorPubKeyTag().ifPresent(genericEvent::addTag);
+ calendarRsvpContent.getEventTag().ifPresent(genericEvent::addTag);
+ calendarRsvpContent.getFbTag().ifPresent(genericEvent::addTag);
+
+ this.updateEvent(genericEvent);
+
+ return this;
+ }
+
+ public NIP52 createDateBasedCalendarEvent(@NonNull String content, @NonNull CalendarContent calendarContent) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.TIME_BASED_CALENDAR_CONTENT, content).create();
+
+// mandatory tags
+ genericEvent.addTag(calendarContent.getIdentifierTag());
+ genericEvent.addTag(createTitleTag(calendarContent.getTitle()));
+ genericEvent.addTag(createStartTag(calendarContent.getStart()));
+
+// optional tags
+ calendarContent.getGeohashTag().ifPresent(genericEvent::addTag);
+ calendarContent.getEnd().ifPresent(s -> genericEvent.addTag(createEndTag(s)));
+ calendarContent.getStartTzid().ifPresent(s -> genericEvent.addTag(createStartTzidTag(s)));
+ calendarContent.getEndTzid().ifPresent(s -> genericEvent.addTag(createEndTzidTag(s)));
+ calendarContent.getSummary().ifPresent(s -> genericEvent.addTag(createSummaryTag(s)));
+
+ this.updateEvent(genericEvent);
return this;
}
- public NIP52 createCalendarRsvpEvent(@NonNull List baseTags, @NonNull String content, @NonNull CalendarRsvpContent calendarRsvpContent) {
- setEvent((T) new CalendarRsvpEventFactory(getSender(), baseTags, content, calendarRsvpContent).create());
+ public NIP52 addIdentifierTag(@NonNull String identifier) {
+ addTag(createIdentifierTag(identifier));
return this;
}
+
+ public NIP52 addTitleTag(@NonNull String title) {
+ addTag(createTitleTag(title));
+ return this;
+ }
+
+ public NIP52 addStartTag(@NonNull Long start) {
+ addTag(createStartTag(start));
+ return this;
+ }
+
+ public NIP52 addEndTag(@NonNull Long end) {
+ addTag(createEndTag(end));
+ return this;
+ }
+
+ public NIP52 addEventTag(@NonNull GenericTag eventTag) {
+ if (!Constants.Tag.EVENT_CODE.equals(eventTag.getCode())) { // Sanity check
+ throw new IllegalArgumentException("tag must be of type EventTag");
+ }
+
+ addTag(eventTag);
+ return this;
+ }
+
+ public static BaseTag createStartTag(@NonNull Long start) {
+ return new BaseTagFactory(Constants.Tag.START_CODE, start.toString()).create();
+ }
+
+ public static BaseTag createEndTag(@NonNull Long end) {
+ return new BaseTagFactory(Constants.Tag.END_CODE, end.toString()).create();
+ }
+
+ public static BaseTag createStartTzidTag(@NonNull String startTzid) {
+ return new BaseTagFactory(Constants.Tag.START_TZID_CODE, startTzid).create();
+ }
+
+ public static BaseTag createEndTzidTag(@NonNull String endTzid) {
+ return new BaseTagFactory(Constants.Tag.END_TZID_CODE, endTzid).create();
+ }
+
+ public static BaseTag createFreeBusyTag(@NonNull String fb) {
+ return new BaseTagFactory(Constants.Tag.FREE_BUSY_CODE, fb).create();
+ }
+
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP57.java b/nostr-java-api/src/main/java/nostr/api/NIP57.java
index a7ae15cff..c4927dd71 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP57.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP57.java
@@ -1,22 +1,21 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.TagFactory;
-import nostr.api.factory.impl.NIP57Impl.ZapReceiptEventFactory;
-import nostr.api.factory.impl.NIP57Impl.ZapRequestEventFactory;
-import nostr.base.ElementAttribute;
+import lombok.SneakyThrows;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.base.IEvent;
import nostr.base.PublicKey;
import nostr.base.Relay;
+import nostr.config.Constants;
import nostr.event.BaseTag;
+import nostr.event.entities.ZapRequest;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.GenericTag;
-import nostr.event.impl.ZapRequest;
-import nostr.event.tag.AddressTag;
import nostr.event.tag.EventTag;
-import nostr.event.tag.IdentifierTag;
-import nostr.event.tag.PubKeyTag;
+import nostr.event.tag.GenericTag;
import nostr.event.tag.RelaysTag;
import nostr.id.Identity;
+import org.apache.commons.lang3.StringEscapeUtils;
import java.util.ArrayList;
import java.util.List;
@@ -24,108 +23,201 @@
/**
* @author eric
*/
-public class NIP57 extends EventNostr {
- private static final String LNURL_TAG_NAME = "lnurl";
- private static final String BOLT11_TAG_NAME = "bolt11";
- private static final String PREIMAGE_TAG_NAME = "preimage";
- private static final String DESCRIPTION_TAG_NAME = "description";
- private static final String AMOUNT_TAG_NAME = "amount";
- private static final String ZAP_TAG_NAME = "zap";
+public class NIP57 extends EventNostr {
public NIP57(@NonNull Identity sender) {
setSender(sender);
}
- public NIP57 createZapRequestEvent(@NonNull PublicKey recipientPubKey, @NonNull List baseTags, String content, @NonNull ZapRequest zapRequest) {
- setEvent((T) new ZapRequestEventFactory(getSender(), recipientPubKey, baseTags, content, zapRequest).create());
+ public NIP57 createZapRequestEvent(
+ @NonNull ZapRequest zapRequest,
+ @NonNull String content,
+ PublicKey recipientPubKey,
+ GenericEvent zappedEvent,
+ BaseTag addressTag) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.ZAP_REQUEST, content).create();
+
+ genericEvent.addTag(zapRequest.getRelaysTag());
+ genericEvent.addTag(createAmountTag(zapRequest.getAmount()));
+ genericEvent.addTag(createLnurlTag(zapRequest.getLnUrl()));
+
+ if (recipientPubKey != null) {
+ genericEvent.addTag(NIP01.createPubKeyTag(recipientPubKey));
+ }
+
+ if (zappedEvent != null) {
+ genericEvent.addTag(NIP01.createEventTag(zappedEvent.getId()));
+ }
+
+ if (addressTag != null) {
+ if (!Constants.Tag.ADDRESS_CODE.equals(addressTag.getCode())) { // Sanity check
+ throw new IllegalArgumentException("tag must be of type AddressTag");
+ }
+ genericEvent.addTag(addressTag);
+ }
+
+ this.updateEvent(genericEvent);
return this;
}
- public NIP57 createZapRequestEvent(@NonNull PublicKey recipientPubKey, @NonNull List baseTags, String content, @NonNull Long amount, @NonNull String lnUrl, @NonNull RelaysTag relaysTags) {
- return createZapRequestEvent(recipientPubKey, baseTags, content, new ZapRequest(relaysTags, amount, lnUrl));
- }
+ public NIP57 createZapRequestEvent(
+ @NonNull Long amount,
+ @NonNull String lnUrl,
+ @NonNull BaseTag relaysTags,
+ @NonNull String content,
+ PublicKey recipientPubKey,
+ GenericEvent zappedEvent,
+ BaseTag addressTag) {
+
+ if (!relaysTags.getCode().equals(Constants.Tag.RELAYS_CODE)) {
+ throw new IllegalArgumentException("tag must be of type RelaysTag");
+ }
- public NIP57 createZapRequestEventFromList(@NonNull PublicKey recipientPubKey, @NonNull List baseTags, String content, @NonNull Long amount, @NonNull String lnUrl, @NonNull List relays) {
- return createZapRequestEvent(recipientPubKey, baseTags, content, amount, lnUrl, new RelaysTag(relays));
- }
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.ZAP_REQUEST, content).create();
- public NIP57 createZapRequestEvent(@NonNull PublicKey recipientPubKey, @NonNull List baseTags, String content, @NonNull Long amount, @NonNull String lnUrl, @NonNull List relays) {
- return createZapRequestEventFromList(recipientPubKey, baseTags, content, amount, lnUrl, relays.stream().map(Relay::new).toList());
+ genericEvent.addTag(relaysTags);
+ genericEvent.addTag(createAmountTag(amount));
+ genericEvent.addTag(createLnurlTag(lnUrl));
+
+ if (recipientPubKey != null) {
+ genericEvent.addTag(NIP01.createPubKeyTag(recipientPubKey));
+ }
+
+ if (zappedEvent != null) {
+ genericEvent.addTag(NIP01.createEventTag(zappedEvent.getId()));
+ }
+
+ if (addressTag != null) {
+ if (!addressTag.getCode().equals(Constants.Tag.ADDRESS_CODE)) { // Sanity check
+ throw new IllegalArgumentException("Address tag must be of type AddressTag");
+ }
+ genericEvent.addTag(addressTag);
+ }
+
+ this.updateEvent(genericEvent);
+ return this;
}
- public NIP57 createZapRequestEvent(@NonNull PublicKey recipientPubKey, @NonNull List baseTags, String content, @NonNull Long amount, @NonNull String lnUrl, @NonNull String... relaysTags) {
- return createZapRequestEvent(recipientPubKey, baseTags, content, amount, lnUrl, List.of(relaysTags));
+ public NIP57 createZapRequestEvent(
+ @NonNull Long amount,
+ @NonNull String lnUrl,
+ @NonNull List relays,
+ @NonNull String content,
+ PublicKey recipientPubKey,
+ GenericEvent zappedEvent,
+ BaseTag addressTag) {
+
+ return createZapRequestEvent(amount, lnUrl, new RelaysTag(relays), content, recipientPubKey, zappedEvent, addressTag);
}
- public NIP57 createZapReceiptEvent(@NonNull PubKeyTag zapRequestPubKeyTag, List baseTags, EventTag zapRequestEventTag, AddressTag zapRequestAddressTag, @NonNull String bolt11,
- @NonNull String descriptionSha256, @NonNull String preimage) {
- setEvent((T) new ZapReceiptEventFactory(getSender(), baseTags, zapRequestPubKeyTag, zapRequestEventTag, zapRequestAddressTag, bolt11, descriptionSha256, preimage).create());
- return this;
+ public NIP57 createZapRequestEvent(
+ @NonNull Long amount,
+ @NonNull String lnUrl,
+ @NonNull List relays,
+ @NonNull String content,
+ PublicKey recipientPubKey) {
+
+ return createZapRequestEvent(amount, lnUrl, relays.stream().map(Relay::new).toList(), content, recipientPubKey, null, null);
}
- public NIP57 createZapReceiptEvent(@NonNull String zapRequestPubKeyTag, List baseTags, String zapRequestEventTag, String zapReceiptAddressTag, String zapReceiptIdentifier, String zapReceiptRelayUri, String bolt11, String descriptionSha256, String preimage) {
- return createZapReceiptEvent(new PubKeyTag(new PublicKey(zapRequestPubKeyTag)), baseTags, new EventTag(zapRequestEventTag), new AddressTag(null, new PublicKey(zapReceiptAddressTag), new IdentifierTag(zapReceiptIdentifier), new Relay(zapReceiptRelayUri)), bolt11, descriptionSha256, preimage);
+ @SneakyThrows
+ public NIP57 createZapReceiptEvent(
+ @NonNull GenericEvent zapRequestEvent,
+ @NonNull String bolt11,
+ @NonNull String preimage,
+ @NonNull PublicKey zapRecipient) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.ZAP_RECEIPT, "").create();
+
+ // Add the tags
+ genericEvent.addTag(NIP01.createPubKeyTag(zapRecipient));
+
+ // Zap receipt tags
+ String descriptionSha256 = IEvent.MAPPER_AFTERBURNER.writeValueAsString(zapRequestEvent);
+ genericEvent.addTag(createDescriptionTag(StringEscapeUtils.escapeJson(descriptionSha256)));
+ genericEvent.addTag(createBolt11Tag(bolt11));
+ genericEvent.addTag(createPreImageTag(preimage));
+ genericEvent.addTag(createZapSenderPubKeyTag(zapRequestEvent.getPubKey()));
+ genericEvent.addTag(NIP01.createEventTag(zapRequestEvent.getId()));
+
+ GenericTag addressTag = (GenericTag) zapRequestEvent.getTags().stream()
+ .filter(tag -> tag.getCode().equals(Constants.Tag.ADDRESS_CODE))
+ .findFirst()
+ .orElse(null);
+
+ if (addressTag != null) {
+ genericEvent.addTag(addressTag);
+ }
+
+ genericEvent.setCreatedAt(zapRequestEvent.getCreatedAt());
+
+ // Set the event
+ this.updateEvent(genericEvent);
+
+ // Return this
+ return this;
}
- public NIP57 addLnurlTag(@NonNull String lnurl) {
+ public NIP57 addLnurlTag(@NonNull String lnurl) {
getEvent().addTag(createLnurlTag(lnurl));
return this;
}
- public NIP57 addEventTag(@NonNull EventTag tag) {
+ public NIP57 addEventTag(@NonNull EventTag tag) {
getEvent().addTag(tag);
return this;
}
- public NIP57 addBolt11Tag(@NonNull String bolt11) {
+ public NIP57 addBolt11Tag(@NonNull String bolt11) {
getEvent().addTag(createBolt11Tag(bolt11));
return this;
}
- public NIP57 addPreImageTag(@NonNull String preimage) {
+ public NIP57 addPreImageTag(@NonNull String preimage) {
getEvent().addTag(createPreImageTag(preimage));
return this;
}
- public NIP57 addDescriptionTag(@NonNull String description) {
+ public NIP57 addDescriptionTag(@NonNull String description) {
getEvent().addTag(createDescriptionTag(description));
return this;
}
- public NIP57 addAmountTag(@NonNull Integer amount) {
+ public NIP57 addAmountTag(@NonNull Integer amount) {
getEvent().addTag(createAmountTag(amount));
return this;
}
- public NIP57 addRecipientTag(@NonNull PublicKey recipient) {
+ public NIP57 addRecipientTag(@NonNull PublicKey recipient) {
getEvent().addTag(NIP01.createPubKeyTag(recipient));
return this;
}
- public NIP57 addZapTag(@NonNull PublicKey receiver, @NonNull List relays, Integer weight) {
+ public NIP57 addZapTag(@NonNull PublicKey receiver, @NonNull List relays, Integer weight) {
getEvent().addTag(createZapTag(receiver, relays, weight));
return this;
}
- public NIP57 addZapTag(@NonNull PublicKey receiver, @NonNull List relays) {
+ public NIP57 addZapTag(@NonNull PublicKey receiver, @NonNull List relays) {
getEvent().addTag(createZapTag(receiver, relays));
return this;
}
- public NIP57 addRelaysTag(@NonNull RelaysTag relaysTag) {
+ public NIP57 addRelaysTag(@NonNull RelaysTag relaysTag) {
getEvent().addTag(relaysTag);
return this;
}
- public NIP57 addRelaysList(@NonNull List relays) {
+ public NIP57 addRelaysList(@NonNull List relays) {
return addRelaysTag(new RelaysTag(relays));
}
- public NIP57 addRelays(@NonNull List relays) {
+ public NIP57 addRelays(@NonNull List relays) {
return addRelaysList(relays.stream().map(Relay::new).toList());
}
- public NIP57 addRelays(@NonNull String... relays) {
+ public NIP57 addRelays(@NonNull String... relays) {
return addRelays(List.of(relays));
}
@@ -133,37 +225,44 @@ public NIP57 addRelays(@NonNull String... relays) {
* @param lnurl
* @return
*/
- public static GenericTag createLnurlTag(@NonNull String lnurl) {
- return new TagFactory(LNURL_TAG_NAME, 57, lnurl).create();
+ public static BaseTag createLnurlTag(@NonNull String lnurl) {
+ return new BaseTagFactory(Constants.Tag.LNURL_CODE, lnurl).create();
}
/**
* @param bolt11
* @return
*/
- public static GenericTag createBolt11Tag(@NonNull String bolt11) {
- return new TagFactory(BOLT11_TAG_NAME, 57, bolt11).create();
+ public static BaseTag createBolt11Tag(@NonNull String bolt11) {
+ return new BaseTagFactory(Constants.Tag.BOLT11_CODE, bolt11).create();
}
/**
* @param preimage
*/
- public static GenericTag createPreImageTag(@NonNull String preimage) {
- return new TagFactory(PREIMAGE_TAG_NAME, 57, preimage).create();
+ public static BaseTag createPreImageTag(@NonNull String preimage) {
+ return new BaseTagFactory(Constants.Tag.PREIMAGE_CODE, preimage).create();
}
/**
* @param description
*/
- public static GenericTag createDescriptionTag(@NonNull String description) {
- return new TagFactory(DESCRIPTION_TAG_NAME, 57, description).create();
+ public static BaseTag createDescriptionTag(@NonNull String description) {
+ return new BaseTagFactory(Constants.Tag.DESCRIPTION_CODE, description).create();
}
/**
* @param amount
*/
- public static GenericTag createAmountTag(@NonNull Integer amount) {
- return new TagFactory(AMOUNT_TAG_NAME, 57, amount.toString()).create();
+ public static BaseTag createAmountTag(@NonNull Number amount) {
+ return new BaseTagFactory(Constants.Tag.AMOUNT_CODE, amount.toString()).create();
+ }
+
+ /**
+ * @param publicKey
+ */
+ public static BaseTag createZapSenderPubKeyTag(@NonNull PublicKey publicKey) {
+ return new BaseTagFactory(Constants.Tag.RECIPIENT_PUBKEY_CODE, publicKey.toString()).create();
}
/**
@@ -171,25 +270,23 @@ public static GenericTag createAmountTag(@NonNull Integer amount) {
* @param relays
* @param weight
*/
- public static GenericTag createZapTag(@NonNull PublicKey receiver, @NonNull List relays, Integer weight) {
- List attributes = new ArrayList<>();
- var receiverAttr = new ElementAttribute("receiver", receiver.toString());
- var relayAttrs = relays.stream().map(relay -> new ElementAttribute("relay", relay.getUri())).toList();
+ public static BaseTag createZapTag(@NonNull PublicKey receiver, @NonNull List relays, Integer weight) {
+ List params = new ArrayList<>();
+ params.add(receiver.toString());
+ relays.stream()
+ .map(Relay::getUri)
+ .forEach(params::add);
if (weight != null) {
- var weightAttr = new ElementAttribute("weight", weight);
- attributes.add(weightAttr);
+ params.add(weight.toString());
}
-
- attributes.add(receiverAttr);
- attributes.addAll(relayAttrs);
- return new GenericTag(ZAP_TAG_NAME, attributes);
+ return BaseTag.create(Constants.Tag.ZAP_CODE, params);
}
/**
* @param receiver
* @param relays
*/
- public static GenericTag createZapTag(@NonNull PublicKey receiver, @NonNull List relays) {
+ public static BaseTag createZapTag(@NonNull PublicKey receiver, @NonNull List relays) {
return createZapTag(receiver, relays, null);
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP60.java b/nostr-java-api/src/main/java/nostr/api/NIP60.java
index 123bee06d..8317a95e9 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP60.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP60.java
@@ -1,77 +1,59 @@
package nostr.api;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import com.fasterxml.jackson.annotation.JsonValue;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.SneakyThrows;
-import nostr.api.factory.TagFactory;
-import nostr.api.factory.impl.NIP60Impl;
-import nostr.api.factory.impl.NIP60Impl.SpendingHistoryEventFactory;
-import nostr.api.factory.impl.NIP60Impl.TokenEventFactory;
-import nostr.api.factory.impl.NIP60Impl.WalletEventFactory;
-import nostr.base.Mint;
-import nostr.base.Quote;
-import nostr.base.Token;
-import nostr.base.Wallet;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
import nostr.event.BaseTag;
+import nostr.event.entities.Amount;
+import nostr.event.entities.CashuMint;
+import nostr.event.entities.CashuQuote;
+import nostr.event.entities.CashuToken;
+import nostr.event.entities.CashuWallet;
+import nostr.event.entities.SpendingHistory;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.GenericTag;
import nostr.event.json.codec.BaseTagEncoder;
-import nostr.event.tag.EventTag;
import nostr.id.Identity;
-import static nostr.base.IEvent.MAPPER_AFTERBURNER;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
-public class NIP60 extends EventNostr {
+import static nostr.base.IEvent.MAPPER_AFTERBURNER;
- private static final String MINT_TAG_NAME = "mint";
- private static final String UNIT_TAG_NAME = "unit";
- private static final String PRIVKEY_TAG_NAME = "privkey";
- private static final String BALANCE_TAG_NAME = "balance";
- private static final String DIRECTION_TAG_NAME = "direction";
- private static final String AMOUNT_TAG_NAME = "amount";
- private static final String EXPIRATION_TAG_NAME = "expiration";
+public class NIP60 extends EventNostr {
public NIP60(@NonNull Identity sender) {
setSender(sender);
}
@SuppressWarnings("unchecked")
- public NIP60 createWalletEvent(@NonNull Wallet wallet) {
- setEvent((T) new WalletEventFactory(getSender(), getWalletEventTags(wallet), getWalletEventContent(wallet))
- .create());
+ public NIP60 createWalletEvent(@NonNull CashuWallet wallet) {
+ GenericEvent walletEvent = new GenericEventFactory(getSender(), Constants.Kind.CASHU_WALLET_EVENT, getWalletEventTags(wallet), getWalletEventContent(wallet)).create();
+ updateEvent(walletEvent);
return this;
}
@SuppressWarnings("unchecked")
- public NIP60 createTokenEvent(@NonNull Token token, @NonNull Wallet wallet) {
- setEvent((T) new TokenEventFactory(getSender(), getTokenEventTags(wallet), getTokenEventContent(token))
- .create());
+ public NIP60 createTokenEvent(@NonNull CashuToken token, @NonNull CashuWallet wallet) {
+ GenericEvent tokenEvent = new GenericEventFactory(getSender(), Constants.Kind.CASHU_WALLET_TOKENS, getTokenEventTags(wallet), getTokenEventContent(token)).create();
+ updateEvent(tokenEvent);
return this;
}
@SuppressWarnings("unchecked")
- public NIP60 createSpendingHistoryEvent(@NonNull SpendingHistory spendingHistory, @NonNull Wallet wallet) {
- setEvent((T) new SpendingHistoryEventFactory(getSender(), getSpendingHistoryEventTags(wallet),
- getSpendingHistoryEventContent(spendingHistory))
- .create());
+ public NIP60 createSpendingHistoryEvent(@NonNull SpendingHistory spendingHistory, @NonNull CashuWallet wallet) {
+ GenericEvent spendingHistoryEvent = new GenericEventFactory(getSender(), Constants.Kind.CASHU_WALLET_HISTORY, getSpendingHistoryEventTags(wallet), getSpendingHistoryEventContent(spendingHistory)).create();
+ updateEvent(spendingHistoryEvent);
return this;
}
@SuppressWarnings("unchecked")
- public NIP60 createRedemptionQuoteEvent(@NonNull Quote quote) {
- setEvent((T) new NIP60Impl.RedemptionQuoteEventFactory(getSender(), getRedemptionQuoteEventTags(quote),
- getRedemptionQuoteEventContent(quote))
- .create());
+ public NIP60 createRedemptionQuoteEvent(@NonNull CashuQuote quote) {
+ GenericEvent redemptionQuoteEvent = new GenericEventFactory(getSender(), Constants.Kind.CASHU_RESERVED_WALLET_TOKENS, getRedemptionQuoteEventTags(quote), getRedemptionQuoteEventContent(quote)).create();
+ updateEvent(redemptionQuoteEvent);
return this;
}
@@ -79,7 +61,7 @@ public NIP60 createRedemptionQuoteEvent(@NonNull Quote quote) {
* @param mint
* @return
*/
- public static GenericTag createMintTag(@NonNull Mint mint) {
+ public static BaseTag createMintTag(@NonNull CashuMint mint) {
List units = mint.getUnits();
return createMintTag(mint.getUrl(), units != null ? units.toArray(new String[0]) : null);
}
@@ -88,7 +70,7 @@ public static GenericTag createMintTag(@NonNull Mint mint) {
* @param mintUrl
* @return
*/
- public static GenericTag createMintTag(@NonNull String mintUrl) {
+ public static BaseTag createMintTag(@NonNull String mintUrl) {
return createMintTag(mintUrl, (String[]) null);
}
@@ -97,29 +79,29 @@ public static GenericTag createMintTag(@NonNull String mintUrl) {
* @param units
* @return
*/
- public static GenericTag createMintTag(@NonNull String mintUrl, String... units) {
+ public static BaseTag createMintTag(@NonNull String mintUrl, String... units) {
List params = new ArrayList<>();
params.add(mintUrl);
if (units != null && units.length > 0) {
params.addAll(Arrays.asList(units));
}
- return new TagFactory(MINT_TAG_NAME, 60, params.toArray(new String[0])).create();
+ return new BaseTagFactory(Constants.Tag.MINT_CODE, params.toArray(new String[0])).create();
}
/**
* @param unit
* @return
*/
- public static GenericTag createUnitTag(@NonNull String unit) {
- return new TagFactory(UNIT_TAG_NAME, 60, unit).create();
+ public static BaseTag createUnitTag(@NonNull String unit) {
+ return new BaseTagFactory(Constants.Tag.UNIT_CODE, unit).create();
}
/**
* @param privKey
* @return
*/
- public static GenericTag createPrivKeyTag(@NonNull String privKey) {
- return new TagFactory(PRIVKEY_TAG_NAME, 60, privKey).create();
+ public static BaseTag createPrivKeyTag(@NonNull String privKey) {
+ return new BaseTagFactory(Constants.Tag.PRIVKEY_CODE, privKey).create();
}
/**
@@ -127,65 +109,24 @@ public static GenericTag createPrivKeyTag(@NonNull String privKey) {
* @param unit
* @return
*/
- public static GenericTag createBalanceTag(@NonNull Integer balance, String unit) {
- return new TagFactory(BALANCE_TAG_NAME, 60, balance.toString(), unit).create();
+ public static BaseTag createBalanceTag(@NonNull Integer balance, String unit) {
+ return new BaseTagFactory(Constants.Tag.BALANCE_CODE, balance.toString(), unit).create();
}
- public static GenericTag createDirectionTag(@NonNull NIP60.SpendingHistory.Direction direction) {
- return new TagFactory(DIRECTION_TAG_NAME, 60, direction.getValue()).create();
+ public static BaseTag createDirectionTag(@NonNull SpendingHistory.Direction direction) {
+ return new BaseTagFactory(Constants.Tag.DIRECTION_CODE, direction.getValue()).create();
}
- public static GenericTag createAmountTag(@NonNull SpendingHistory.Amount amount) {
- return new TagFactory(AMOUNT_TAG_NAME, 60, amount.getAmount().toString(), amount.getUnit()).create();
+ public static BaseTag createAmountTag(@NonNull Amount amount) {
+ return new BaseTagFactory(Constants.Tag.AMOUNT_CODE, amount.getAmount().toString(), amount.getUnit()).create();
}
- public static GenericTag createExpirationTag(@NonNull Long expiration) {
- return new TagFactory(EXPIRATION_TAG_NAME, 60, expiration.toString()).create();
- }
-
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Builder
- public static class SpendingHistory {
- private Direction direction;
- private Amount amount;
-
- @Builder.Default
- private List eventTags = new ArrayList<>();
-
- public enum Direction {
- RECEIVED("in"),
- SENT("out");
-
- private final String value;
-
- Direction(String value) {
- this.value = value;
- }
-
- @JsonValue
- public String getValue() {
- return value;
- }
- }
-
- public void addEventTag(@NonNull EventTag eventTag) {
- this.eventTags.add(eventTag);
- }
-
- @Data
- @NoArgsConstructor
- @AllArgsConstructor
- @Builder
- public static class Amount {
- private Integer amount;
- private String unit;
- }
+ public static BaseTag createExpirationTag(@NonNull Long expiration) {
+ return new BaseTagFactory(Constants.Tag.EXPIRATION_CODE, expiration.toString()).create();
}
@SneakyThrows
- private String getWalletEventContent(@NonNull Wallet wallet) {
+ private String getWalletEventContent(@NonNull CashuWallet wallet) {
List tags = new ArrayList<>();
tags.add(NIP60.createBalanceTag(wallet.getBalance(), wallet.getUnit()));
tags.add(NIP60.createPrivKeyTag(wallet.getPrivateKey()));
@@ -194,12 +135,12 @@ private String getWalletEventContent(@NonNull Wallet wallet) {
}
@SneakyThrows
- private String getTokenEventContent(@NonNull Token token) {
+ private String getTokenEventContent(@NonNull CashuToken token) {
return NIP44.encrypt(getSender(), MAPPER_AFTERBURNER.writeValueAsString(token), getSender().getPublicKey());
}
@SneakyThrows
- private String getRedemptionQuoteEventContent(@NonNull Quote quote) {
+ private String getRedemptionQuoteEventContent(@NonNull CashuQuote quote) {
return NIP44.encrypt(getSender(), quote.getId(), getSender().getPublicKey());
}
@@ -222,7 +163,7 @@ private String getContent(@NonNull List tags) {
.collect(Collectors.joining(",")) + "]";
}
- private List getWalletEventTags(@NonNull Wallet wallet) {
+ private List getWalletEventTags(@NonNull CashuWallet wallet) {
List tags = new ArrayList<>();
tags.add(NIP60.createUnitTag(wallet.getUnit()));
@@ -242,24 +183,23 @@ private List getWalletEventTags(@NonNull Wallet wallet) {
return tags;
}
- private List getTokenEventTags(@NonNull Wallet wallet) {
+ private List getTokenEventTags(@NonNull CashuWallet wallet) {
List tags = new ArrayList<>();
- tags.add(NIP01.createAddressTag(37375, getSender().getPublicKey(), NIP01.createIdentifierTag(wallet.getId()),
- null));
+ tags.add(NIP01.createAddressTag(Constants.Kind.CASHU_WALLET_EVENT, getSender().getPublicKey(), NIP01.createIdentifierTag(wallet.getId()), null));
return tags;
}
- private List getSpendingHistoryEventTags(@NonNull Wallet wallet) {
+ private List getSpendingHistoryEventTags(@NonNull CashuWallet wallet) {
return getTokenEventTags(wallet);
}
- private List getRedemptionQuoteEventTags(@NonNull Quote quote) {
+ private List getRedemptionQuoteEventTags(@NonNull CashuQuote quote) {
List tags = new ArrayList<>();
tags.add(NIP60.createExpirationTag(quote.getExpiration()));
tags.add(NIP60.createMintTag(quote.getMint()));
- tags.add(NIP01.createAddressTag(37375, getSender().getPublicKey(),
+ tags.add(NIP01.createAddressTag(Constants.Kind.CASHU_WALLET_EVENT, getSender().getPublicKey(),
NIP01.createIdentifierTag(quote.getWallet().getId()),
null));
return tags;
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP61.java b/nostr-java-api/src/main/java/nostr/api/NIP61.java
index 9d27cf3b3..24fdbe943 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP61.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP61.java
@@ -1,68 +1,79 @@
package nostr.api;
-import java.util.ArrayList;
-import java.util.List;
-
import lombok.NonNull;
-import nostr.api.factory.TagFactory;
-import nostr.api.factory.impl.NIP61Impl.NutzapEventFactory;
-import nostr.api.factory.impl.NIP61Impl.NutzapInformationalEventFactory;
-import nostr.base.Mint;
-import nostr.base.Proof;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
import nostr.base.PublicKey;
import nostr.base.Relay;
+import nostr.config.Constants;
import nostr.event.BaseTag;
+import nostr.event.entities.Amount;
+import nostr.event.entities.CashuMint;
+import nostr.event.entities.CashuProof;
import nostr.event.impl.GenericEvent;
-import nostr.event.tag.GenericTag;
import nostr.event.tag.EventTag;
import nostr.id.Identity;
-public class NIP61 extends EventNostr {
+import java.net.URL;
+import java.util.List;
- private static final String P2PK_TAG_NAME = "pubkey";
- private static final String URL_TAG_NAME = "u";
- private static final String PROOF_TAG_NAME = "proof";
+public class NIP61 extends EventNostr {
public NIP61(@NonNull Identity sender) {
setSender(sender);
}
- @SuppressWarnings("unchecked")
- public NIP61 createNutzapInformationalEvent(@NonNull List p2pkPubkey, @NonNull List relays,
- @NonNull List mints) {
+ public NIP61 createNutzapInformationalEvent
+ (@NonNull List p2pkPubkey,
+ @NonNull List relays,
+ @NonNull List mints) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CASHU_NUTZAP_INFO_EVENT).create();
- List tags = new ArrayList<>();
- relays.forEach(relay -> tags.add(NIP42.createRelayTag(relay)));
- mints.forEach(mint -> tags.add(NIP60.createMintTag(mint)));
- p2pkPubkey.forEach(pubkey -> tags.add(NIP61.createP2pkTag(pubkey)));
+ relays.forEach(relay -> genericEvent.addTag(NIP42.createRelayTag(relay)));
+ mints.forEach(mint -> genericEvent.addTag(NIP60.createMintTag(mint)));
+ p2pkPubkey.forEach(pubkey -> genericEvent.addTag(NIP61.createP2pkTag(pubkey)));
+
+ updateEvent(genericEvent);
- setEvent((T) new NutzapInformationalEventFactory(getSender(), tags, "").create());
return this;
}
- @SuppressWarnings("unchecked")
- public NIP61 createNutzapEvent(@NonNull NIP60.SpendingHistory.Amount amount, List proofs,
- @NonNull Mint mint, List events, @NonNull PublicKey recipient, @NonNull String content) {
+ public NIP61 createNutzapEvent(
+ @NonNull Amount amount,
+ List proofs,
+ @NonNull URL url,
+ List events,
+ @NonNull PublicKey recipient,
+ @NonNull String content) {
+
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CASHU_NUTZAP_EVENT, content).create();
+
+ if (proofs != null) {
+ proofs.forEach(proof -> genericEvent.addTag(NIP61.createProofTag(proof)));
+ }
+ if (events != null) {
+ events.forEach(event -> genericEvent.addTag(event));
+ }
+ genericEvent.addTag(NIP61.createUrlTag(url.toString()));
+ genericEvent.addTag(NIP60.createAmountTag(amount));
+ genericEvent.addTag(NIP60.createUnitTag(amount.getUnit()));
+ genericEvent.addTag(NIP01.createPubKeyTag(recipient));
- List tags = new ArrayList<>();
- tags.add(NIP61.createUrlTag(mint.getUrl()));
- tags.add(NIP60.createAmountTag(amount));
- tags.add(NIP60.createUnitTag(amount.getUnit()));
- tags.add(NIP01.createPubKeyTag(recipient));
+ updateEvent(genericEvent);
- setEvent((T) new NutzapEventFactory(getSender(), tags, content).create());
return this;
}
- public static GenericTag createP2pkTag(@NonNull String pubkey) {
- return new TagFactory(P2PK_TAG_NAME, 61, pubkey).create();
+ public static BaseTag createP2pkTag(@NonNull String pubkey) {
+ return new BaseTagFactory(Constants.Tag.P2PKH_CODE, pubkey).create();
}
- public static GenericTag createUrlTag(@NonNull String url) {
- return new TagFactory(URL_TAG_NAME, 61, url).create();
+ public static BaseTag createUrlTag(@NonNull String url) {
+ return new BaseTagFactory(Constants.Tag.URL_CODE, url).create();
}
- public static GenericTag createProofTag(@NonNull Proof proof) {
- return new TagFactory(PROOF_TAG_NAME, 61, proof.toString().replace("\"", "\\\"")).create();
+ public static BaseTag createProofTag(@NonNull CashuProof proof) {
+ return new BaseTagFactory(Constants.Tag.PROOF_CODE, proof.toString().replace("\"", "\\\"")).create();
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NIP99.java b/nostr-java-api/src/main/java/nostr/api/NIP99.java
index b266cdc30..2b6cf651e 100644
--- a/nostr-java-api/src/main/java/nostr/api/NIP99.java
+++ b/nostr-java-api/src/main/java/nostr/api/NIP99.java
@@ -1,21 +1,118 @@
package nostr.api;
import lombok.NonNull;
-import nostr.api.factory.impl.NIP99Impl.ClassifiedListingEventFactory;
+import nostr.api.factory.impl.GenericEventFactory;
+import nostr.api.factory.impl.BaseTagFactory;
+import nostr.config.Constants;
import nostr.event.BaseTag;
-import nostr.event.NIP99Event;
-import nostr.event.impl.ClassifiedListing;
+import nostr.event.entities.ClassifiedListing;
+import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
+import java.net.URL;
import java.util.List;
-public class NIP99 extends EventNostr {
- public NIP99(@NonNull Identity sender) {
- setSender(sender);
- }
+import static nostr.api.NIP12.createGeohashTag;
+import static nostr.api.NIP12.createHashtagTag;
+import static nostr.api.NIP23.createImageTag;
+import static nostr.api.NIP23.createPublishedAtTag;
+import static nostr.api.NIP23.createSummaryTag;
+import static nostr.api.NIP23.createTitleTag;
- public NIP99 createClassifiedListingEvent(@NonNull List baseTags, String content, @NonNull ClassifiedListing classifiedListing) {
- setEvent((T) new ClassifiedListingEventFactory(getSender(), baseTags, content, classifiedListing).create());
- return this;
- }
+public class NIP99 extends EventNostr {
+
+ public NIP99(@NonNull Identity sender) {
+ setSender(sender);
+ }
+
+ public NIP99 createClassifiedListingEvent(@NonNull List baseTags, String content, @NonNull ClassifiedListing classifiedListing) {
+ GenericEvent genericEvent = new GenericEventFactory(getSender(), Constants.Kind.CLASSIFIED_LISTING, baseTags, content).create();
+
+ genericEvent.addTag(createTitleTag(classifiedListing.getTitle()));
+ genericEvent.addTag(createSummaryTag(classifiedListing.getSummary()));
+
+ if (classifiedListing.getPublishedAt() != null) {
+ genericEvent.addTag(createPublishedAtTag(classifiedListing.getPublishedAt()));
+ }
+
+ if (classifiedListing.getLocation() != null) {
+ genericEvent.addTag(createLocationTag(classifiedListing.getLocation()));
+ }
+
+ genericEvent.addTag(classifiedListing.getPriceTag());
+
+ updateEvent(genericEvent);
+
+ return this;
+ }
+
+ public static BaseTag createLocationTag(@NonNull String location) {
+ return new BaseTagFactory(Constants.Tag.LOCATION_CODE, location).create();
+ }
+
+ public static BaseTag createPriceTag(@NonNull String price, @NonNull String currency) {
+ return new BaseTagFactory(Constants.Tag.PRICE_CODE, price, currency, null).create();
+ }
+
+ public static BaseTag createPriceTag(@NonNull String price, @NonNull String currency, String frequency) {
+ return new BaseTagFactory(Constants.Tag.PRICE_CODE, price, currency, frequency).create();
+ }
+
+ public static BaseTag createStatusTag(@NonNull String status) {
+ return new BaseTagFactory(Constants.Tag.STATUS_CODE, status).create();
+ }
+
+ public NIP99 addHashtagTag(@NonNull String hashtag) {
+ getEvent().addTag(createHashtagTag(hashtag));
+ return this;
+ }
+
+ public NIP99 addLocationTag(@NonNull String location) {
+ getEvent().addTag(createLocationTag(location));
+ return this;
+ }
+
+ public NIP99 addGeohashTag(@NonNull String geohash) {
+ getEvent().addTag(createGeohashTag(geohash));
+ return this;
+ }
+
+ public NIP99 addPriceTag(@NonNull String price, @NonNull String currency, String frequency) {
+ getEvent().addTag(createPriceTag(price, currency, frequency));
+ return this;
+ }
+
+ public NIP99 addPriceTag(@NonNull String price, @NonNull String currency) {
+ return addPriceTag(price, currency, null);
+ }
+
+ public NIP99 addTitleTag(@NonNull String title) {
+ getEvent().addTag(createTitleTag(title));
+ return this;
+ }
+
+ public NIP99 addSummaryTag(@NonNull String summary) {
+ getEvent().addTag(createSummaryTag(summary));
+ return this;
+ }
+
+ public NIP99 addPublishedAtTag(@NonNull Long date) {
+ getEvent().addTag(createPublishedAtTag(date));
+ return this;
+ }
+
+ public NIP99 addImageTag(@NonNull URL url, String size) {
+ getEvent().addTag(createImageTag(url, size));
+ return this;
+ }
+
+ public NIP99 addStatusTag(@NonNull String status) {
+ getEvent().addTag(createStatusTag(status));
+ return this;
+ }
+
+ public NIP99 addTag(@NonNull BaseTag tag) {
+ getEvent().addTag(tag);
+ return this;
+ }
}
diff --git a/nostr-java-api/src/main/java/nostr/api/NostrSpringWebSocketClient.java b/nostr-java-api/src/main/java/nostr/api/NostrSpringWebSocketClient.java
index 31ba1a3eb..a5b7c94b5 100644
--- a/nostr-java-api/src/main/java/nostr/api/NostrSpringWebSocketClient.java
+++ b/nostr-java-api/src/main/java/nostr/api/NostrSpringWebSocketClient.java
@@ -48,14 +48,6 @@ public NostrIF setSender(@NonNull Identity sender) {
return this;
}
- public List sendEvent(T event, Map relays) {
- setRelays(relays);
- return relays.keySet().stream().map(s ->
- clientMap.get(s).sendEvent(event))
- .flatMap(List::stream)
- .distinct().toList();
- }
-
@Override
public NostrIF setRelays(@NonNull Map relays) {
relays.entrySet().stream().forEach(relayEntry ->
diff --git a/nostr-java-api/src/main/java/nostr/api/WebSocketClientHandler.java b/nostr-java-api/src/main/java/nostr/api/WebSocketClientHandler.java
index be0954b6f..512f2a179 100644
--- a/nostr-java-api/src/main/java/nostr/api/WebSocketClientHandler.java
+++ b/nostr-java-api/src/main/java/nostr/api/WebSocketClientHandler.java
@@ -5,6 +5,7 @@
import nostr.base.IEvent;
import nostr.client.springwebsocket.SpringWebSocketClient;
import nostr.event.filter.Filters;
+import nostr.event.impl.GenericEvent;
import nostr.event.message.EventMessage;
import nostr.event.message.ReqMessage;
@@ -16,42 +17,43 @@
import java.util.concurrent.ConcurrentHashMap;
public class WebSocketClientHandler {
- private final SpringWebSocketClient eventClient;
- private final Map requestClientMap = new ConcurrentHashMap<>();
-
- @Getter
- private String relayName;
- @Getter
- private String relayUri;
-
- protected WebSocketClientHandler(@NonNull String relayName, @NonNull String relayUri) {
- this.relayName = relayName;
- this.relayUri = relayUri;
- this.eventClient = new SpringWebSocketClient(relayUri);
- }
-
- protected List sendEvent(@NonNull IEvent event) {
- return eventClient.send(new EventMessage(event)).stream().toList();
- }
-
- protected List sendRequest(@NonNull Filters filters, @NonNull String subscriptionId) {
- return Optional
- .ofNullable(
- requestClientMap.get(subscriptionId))
- .map(client ->
- client.send(new ReqMessage(subscriptionId, filters))).or(() -> {
- requestClientMap.put(subscriptionId, new SpringWebSocketClient(relayUri));
- return Optional.ofNullable(
- requestClientMap.get(subscriptionId).send(
- new ReqMessage(subscriptionId, filters)));
- })
- .orElse(new ArrayList<>());
- }
-
- public void close() throws IOException {
- eventClient.closeSocket();
- for (SpringWebSocketClient client : requestClientMap.values()) {
- client.closeSocket();
+ private final SpringWebSocketClient eventClient;
+ private final Map requestClientMap = new ConcurrentHashMap<>();
+
+ @Getter
+ private String relayName;
+ @Getter
+ private String relayUri;
+
+ protected WebSocketClientHandler(@NonNull String relayName, @NonNull String relayUri) {
+ this.relayName = relayName;
+ this.relayUri = relayUri;
+ this.eventClient = new SpringWebSocketClient(relayUri);
+ }
+
+ protected List sendEvent(@NonNull IEvent event) {
+ ((GenericEvent) event).validate();
+ return eventClient.send(new EventMessage(event)).stream().toList();
+ }
+
+ protected List sendRequest(@NonNull Filters filters, @NonNull String subscriptionId) {
+ return Optional
+ .ofNullable(
+ requestClientMap.get(subscriptionId))
+ .map(client ->
+ client.send(new ReqMessage(subscriptionId, filters))).or(() -> {
+ requestClientMap.put(subscriptionId, new SpringWebSocketClient(relayUri));
+ return Optional.ofNullable(
+ requestClientMap.get(subscriptionId).send(
+ new ReqMessage(subscriptionId, filters)));
+ })
+ .orElse(new ArrayList<>());
+ }
+
+ public void close() throws IOException {
+ eventClient.closeSocket();
+ for (SpringWebSocketClient client : requestClientMap.values()) {
+ client.closeSocket();
+ }
}
- }
}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/AbstractTagFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/BaseMessageFactory.java
similarity index 61%
rename from nostr-java-api/src/main/java/nostr/api/factory/AbstractTagFactory.java
rename to nostr-java-api/src/main/java/nostr/api/factory/BaseMessageFactory.java
index 6a38fa64b..c613107c8 100644
--- a/nostr-java-api/src/main/java/nostr/api/factory/AbstractTagFactory.java
+++ b/nostr-java-api/src/main/java/nostr/api/factory/BaseMessageFactory.java
@@ -4,15 +4,17 @@
*/
package nostr.api.factory;
-import nostr.base.ITag;
+import lombok.NoArgsConstructor;
+import nostr.event.BaseMessage;
+import nostr.event.message.GenericMessage;
/**
*
* @author eric
* @param
*/
-public abstract class AbstractTagFactory {
+@NoArgsConstructor
+public abstract class BaseMessageFactory {
public abstract T create();
-
}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java
index acc5ce23b..f8e4670f6 100644
--- a/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java
+++ b/nostr-java-api/src/main/java/nostr/api/factory/EventFactory.java
@@ -5,9 +5,9 @@
package nostr.api.factory;
import lombok.Data;
-import nostr.base.IEvent;
import nostr.base.PublicKey;
import nostr.event.BaseTag;
+import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
import java.util.ArrayList;
@@ -16,22 +16,21 @@
/**
*
* @author eric
- * @param
*/
@Data
-public abstract class EventFactory {
+public abstract class EventFactory {
private final Identity identity;
private final String content;
private final List tags;
public EventFactory(Identity identity) {
- this(identity, new ArrayList<>(), null);
+ this(identity, new ArrayList<>(), "");
}
protected EventFactory() {
this.identity = null;
- this.content = null;
+ this.content = "";
this.tags = new ArrayList<>();
}
@@ -45,13 +44,16 @@ public EventFactory(Identity sender, List tags, String content) {
this.identity = sender;
}
- public abstract T create();
+ public abstract GenericEvent create();
protected void addTag(BaseTag tag) {
this.tags.add(tag);
}
protected PublicKey getSender() {
- return this.identity.getPublicKey();
+ if (this.identity != null) {
+ return this.identity.getPublicKey();
+ }
+ return null;
}
}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/TagFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/TagFactory.java
deleted file mode 100644
index 7c5197f40..000000000
--- a/nostr-java-api/src/main/java/nostr/api/factory/TagFactory.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
- * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
- */
-package nostr.api.factory;
-
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NonNull;
-import nostr.event.tag.GenericTag;
-
-/**
- *
- * @author eric
- */
-@Data
-@EqualsAndHashCode(callSuper = false)
-public class TagFactory extends AbstractTagFactory {
-
- @NonNull
- private final String code;
-
- @NonNull
- private final Integer nip;
-
- @NonNull
- private final String[] params;
-
- protected TagFactory() {
- this.code = "";
- this.nip = 0;
- this.params = new String[0];
- }
-
- public TagFactory(String code, Integer nip, String... params) {
- this.code = code;
- this.nip = nip;
- this.params = new String[params.length];
- System.arraycopy(params, 0, this.params, 0, params.length);
- }
-
- @Override
- public GenericTag create() {
- return GenericTag.create(code, nip, params);
- }
-}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/BaseTagFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/BaseTagFactory.java
new file mode 100644
index 000000000..740c990ea
--- /dev/null
+++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/BaseTagFactory.java
@@ -0,0 +1,58 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package nostr.api.factory.impl;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import lombok.SneakyThrows;
+import nostr.event.BaseTag;
+import nostr.event.tag.GenericTag;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+/**
+ * @author eric
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class BaseTagFactory {
+
+ private final String code;
+ private final List params;
+
+ private String jsonString;
+
+ protected BaseTagFactory() {
+ this.code = "";
+ this.params = new ArrayList<>();
+ }
+
+ public BaseTagFactory(@NonNull String code, @NonNull List params) {
+ this.code = code;
+ this.params = params;
+ }
+
+ public BaseTagFactory(String code, String... params) {
+ this(code, Stream.of(params).filter(param -> param != null).toList());
+ }
+
+ public BaseTagFactory(@NonNull String jsonString) {
+ this.jsonString = jsonString;
+ this.code = "";
+ this.params = new ArrayList<>();
+ }
+
+ @SneakyThrows
+ public BaseTag create() {
+ if (jsonString != null) {
+ return new ObjectMapper().readValue(jsonString, GenericTag.class);
+ }
+ return BaseTag.create(code, params);
+ }
+}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/EventMessageFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/EventMessageFactory.java
new file mode 100644
index 000000000..3e1c76977
--- /dev/null
+++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/EventMessageFactory.java
@@ -0,0 +1,35 @@
+package nostr.api.factory.impl;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NonNull;
+import nostr.api.factory.BaseMessageFactory;
+import nostr.event.impl.GenericEvent;
+import nostr.event.message.EventMessage;
+
+import java.util.Optional;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class EventMessageFactory extends BaseMessageFactory {
+
+ private final GenericEvent event;
+ private String subscriptionId;
+
+ public EventMessageFactory(@NonNull GenericEvent event) {
+ this.event = event;
+ }
+
+ public EventMessageFactory(@NonNull GenericEvent event, @NonNull String subscriptionId) {
+ this(event);
+ this.subscriptionId = subscriptionId;
+ }
+
+ @Override
+ public EventMessage create() {
+ return Optional.ofNullable(subscriptionId)
+ .map(subscriptionId -> new EventMessage(event, subscriptionId))
+ .orElse(new EventMessage(event));
+ }
+
+}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/GenericEventFactory.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/GenericEventFactory.java
index e199a6eb2..bbf12d1cf 100644
--- a/nostr-java-api/src/main/java/nostr/api/factory/impl/GenericEventFactory.java
+++ b/nostr-java-api/src/main/java/nostr/api/factory/impl/GenericEventFactory.java
@@ -4,20 +4,43 @@
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import nostr.api.factory.EventFactory;
+import nostr.event.BaseTag;
import nostr.event.impl.GenericEvent;
import nostr.id.Identity;
+import java.util.List;
+
@EqualsAndHashCode(callSuper = true)
@Data
-public class GenericEventFactory extends EventFactory {
+public class GenericEventFactory extends EventFactory {
private Integer kind;
+ public GenericEventFactory(@NonNull Integer kind) {
+ super();
+ this.kind = kind;
+ }
+
+ public GenericEventFactory(Identity sender, @NonNull Integer kind) {
+ super(sender);
+ this.kind = kind;
+ }
+
+ public GenericEventFactory(@NonNull Integer kind, @NonNull String content) {
+ super(null, content);
+ this.kind = kind;
+ }
+
public GenericEventFactory(Identity sender, @NonNull Integer kind, @NonNull String content) {
super(sender, content);
this.kind = kind;
}
+ public GenericEventFactory(Identity sender, @NonNull Integer kind, List tags, @NonNull String content) {
+ super(sender, tags, content);
+ this.kind = kind;
+ }
+
public GenericEvent create() {
return new GenericEvent(getIdentity().getPublicKey(), getKind(), getTags(), getContent());
}
diff --git a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01Impl.java b/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01Impl.java
deleted file mode 100644
index 971265ef4..000000000
--- a/nostr-java-api/src/main/java/nostr/api/factory/impl/NIP01Impl.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
- * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
- */
-package nostr.api.factory.impl;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.NonNull;
-import nostr.api.factory.AbstractTagFactory;
-import nostr.api.factory.EventFactory;
-import nostr.api.factory.MessageFactory;
-import nostr.base.IEvent;
-import nostr.base.PublicKey;
-import nostr.base.Relay;
-import nostr.base.UserProfile;
-import nostr.event.BaseTag;
-import nostr.event.Marker;
-import nostr.event.filter.Filters;
-import nostr.event.impl.EphemeralEvent;
-import nostr.event.impl.MetadataEvent;
-import nostr.event.impl.ParameterizedReplaceableEvent;
-import nostr.event.impl.ReplaceableEvent;
-import nostr.event.impl.TextNoteEvent;
-import nostr.event.message.CloseMessage;
-import nostr.event.message.EoseMessage;
-import nostr.event.message.EventMessage;
-import nostr.event.message.NoticeMessage;
-import nostr.event.message.ReqMessage;
-import nostr.event.tag.AddressTag;
-import nostr.event.tag.EventTag;
-import nostr.event.tag.IdentifierTag;
-import nostr.event.tag.PubKeyTag;
-import nostr.id.Identity;
-
-import java.util.List;
-import java.util.Optional;
-
-/**
- *
- * @author eric
- */
-public class NIP01Impl {
-
- @Data
- @EqualsAndHashCode(callSuper = false)
- public static class TextNoteEventFactory extends EventFactory {
-
- public TextNoteEventFactory(@NonNull Identity sender, @NonNull String content) {
- super(sender, content);
- }
-
- public TextNoteEventFactory(@NonNull Identity sender, @NonNull List